aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/hwmon/dme173753
-rw-r--r--Documentation/hwmon/it8713
-rw-r--r--Documentation/hwmon/w83627hf4
-rw-r--r--Documentation/hwmon/w83791d6
-rw-r--r--Documentation/video4linux/gspca.txt1
-rw-r--r--Makefile8
-rw-r--r--arch/powerpc/platforms/iseries/Kconfig11
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/viocons.c1167
-rw-r--r--drivers/hwmon/Kconfig16
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/ad7414.c268
-rw-r--r--drivers/hwmon/dme1737.c292
-rw-r--r--drivers/hwmon/f71882fg.c6
-rw-r--r--drivers/hwmon/hwmon-vid.c144
-rw-r--r--drivers/hwmon/it87.c45
-rw-r--r--drivers/hwmon/thmc50.c28
-rw-r--r--drivers/hwmon/w83627hf.c101
-rw-r--r--drivers/hwmon/w83791d.c24
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c7
-rw-r--r--drivers/media/dvb/frontends/Kconfig3
-rw-r--r--drivers/media/video/Kconfig2
-rw-r--r--drivers/media/video/arv.c2
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c1
-rw-r--r--drivers/media/video/gspca/conex.c4
-rw-r--r--drivers/media/video/gspca/etoms.c137
-rw-r--r--drivers/media/video/gspca/gspca.c12
-rw-r--r--drivers/media/video/gspca/gspca.h5
-rw-r--r--drivers/media/video/gspca/ov519.c476
-rw-r--r--drivers/media/video/gspca/pac7311.c54
-rw-r--r--drivers/media/video/gspca/sonixb.c2
-rw-r--r--drivers/media/video/gspca/sonixj.c287
-rw-r--r--drivers/media/video/gspca/spca505.c12
-rw-r--r--drivers/media/video/gspca/spca506.c12
-rw-r--r--drivers/media/video/gspca/spca508.c18
-rw-r--r--drivers/media/video/gspca/spca561.c42
-rw-r--r--drivers/media/video/gspca/vc032x.c4
-rw-r--r--drivers/media/video/gspca/zc3xx.c6
-rw-r--r--drivers/media/video/pxa_camera.c58
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c2
-rw-r--r--drivers/media/video/soc_camera.c26
-rw-r--r--drivers/media/video/soc_camera_platform.c2
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c33
-rw-r--r--drivers/media/video/uvc/uvc_driver.c26
-rw-r--r--drivers/media/video/uvc/uvc_video.c33
-rw-r--r--drivers/media/video/v4l2-dev.c4
-rw-r--r--drivers/media/video/vino.c1
-rw-r--r--drivers/watchdog/Kconfig16
-rw-r--r--drivers/watchdog/Makefile4
-rw-r--r--drivers/watchdog/acquirewdt.c130
-rw-r--r--drivers/watchdog/advantechwdt.c162
-rw-r--r--drivers/watchdog/alim1535_wdt.c189
-rw-r--r--drivers/watchdog/alim7101_wdt.c228
-rw-r--r--drivers/watchdog/ar7_wdt.c8
-rw-r--r--drivers/watchdog/at32ap700x_wdt.c43
-rw-r--r--drivers/watchdog/at91rm9200_wdt.c108
-rw-r--r--drivers/watchdog/bfin_wdt.c147
-rw-r--r--drivers/watchdog/booke_wdt.c44
-rw-r--r--drivers/watchdog/cpu5wdt.c144
-rw-r--r--drivers/watchdog/davinci_wdt.c19
-rw-r--r--drivers/watchdog/ep93xx_wdt.c27
-rw-r--r--drivers/watchdog/eurotechwdt.c95
-rw-r--r--drivers/watchdog/geodewdt.c96
-rw-r--r--drivers/watchdog/hpwdt.c6
-rw-r--r--drivers/watchdog/i6300esb.c366
-rw-r--r--drivers/watchdog/iTCO_vendor.h15
-rw-r--r--drivers/watchdog/iTCO_vendor_support.c62
-rw-r--r--drivers/watchdog/iTCO_wdt.c310
-rw-r--r--drivers/watchdog/ib700wdt.c123
-rw-r--r--drivers/watchdog/ibmasr.c151
-rw-r--r--drivers/watchdog/indydog.c114
-rw-r--r--drivers/watchdog/iop_wdt.c62
-rw-r--r--drivers/watchdog/it8712f_wdt.c6
-rw-r--r--drivers/watchdog/ixp2000_wdt.c60
-rw-r--r--drivers/watchdog/ixp4xx_wdt.c66
-rw-r--r--drivers/watchdog/ks8695_wdt.c119
-rw-r--r--drivers/watchdog/machzwd.c108
-rw-r--r--drivers/watchdog/mixcomwd.c133
-rw-r--r--drivers/watchdog/mpc5200_wdt.c24
-rw-r--r--drivers/watchdog/mpc83xx_wdt.c230
-rw-r--r--drivers/watchdog/mpc8xx_wdt.c37
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c316
-rw-r--r--drivers/watchdog/mpcore_wdt.c73
-rw-r--r--drivers/watchdog/mtx-1_wdt.c111
-rw-r--r--drivers/watchdog/mv64x60_wdt.c21
-rw-r--r--drivers/watchdog/omap_wdt.c42
-rw-r--r--drivers/watchdog/pc87413_wdt.c249
-rw-r--r--drivers/watchdog/pcwd.c191
-rw-r--r--drivers/watchdog/pcwd_pci.c161
-rw-r--r--drivers/watchdog/pcwd_usb.c168
-rw-r--r--drivers/watchdog/pnx4008_wdt.c28
-rw-r--r--drivers/watchdog/rm9k_wdt.c34
-rw-r--r--drivers/watchdog/s3c2410_wdt.c4
-rw-r--r--drivers/watchdog/sa1100_wdt.c42
-rw-r--r--drivers/watchdog/sb_wdog.c92
-rw-r--r--drivers/watchdog/sbc60xxwdt.c223
-rw-r--r--drivers/watchdog/sbc7240_wdt.c70
-rw-r--r--drivers/watchdog/sbc8360.c46
-rw-r--r--drivers/watchdog/sbc_epx_c3.c22
-rw-r--r--drivers/watchdog/sc1200wdt.c39
-rw-r--r--drivers/watchdog/sc520_wdt.c162
-rw-r--r--drivers/watchdog/scx200_wdt.c65
-rw-r--r--drivers/watchdog/shwdt.c139
-rw-r--r--drivers/watchdog/smsc37b787_wdt.c448
-rw-r--r--drivers/watchdog/softdog.c87
-rw-r--r--drivers/watchdog/txx9wdt.c37
-rw-r--r--drivers/watchdog/w83627hf_wdt.c190
-rw-r--r--drivers/watchdog/w83697hf_wdt.c189
-rw-r--r--drivers/watchdog/w83877f_wdt.c199
-rw-r--r--drivers/watchdog/w83977f_wdt.c239
-rw-r--r--drivers/watchdog/wafer5823wdt.c132
-rw-r--r--drivers/watchdog/wd501p.h2
-rw-r--r--drivers/watchdog/wdrtas.c105
-rw-r--r--drivers/watchdog/wdt.c4
-rw-r--r--drivers/watchdog/wdt285.c31
-rw-r--r--drivers/watchdog/wdt977.c162
-rw-r--r--drivers/watchdog/wdt_pci.c8
-rw-r--r--include/media/soc_camera.h5
-rw-r--r--init/Kconfig9
-rwxr-xr-xscripts/patch-kernel3
121 files changed, 5268 insertions, 5794 deletions
diff --git a/Documentation/hwmon/dme1737 b/Documentation/hwmon/dme1737
index b1fe00999439..001d2e70bc11 100644
--- a/Documentation/hwmon/dme1737
+++ b/Documentation/hwmon/dme1737
@@ -10,6 +10,10 @@ Supported chips:
10 Prefix: 'sch311x' 10 Prefix: 'sch311x'
11 Addresses scanned: none, address read from Super-I/O config space 11 Addresses scanned: none, address read from Super-I/O config space
12 Datasheet: http://www.nuhorizons.com/FeaturedProducts/Volume1/SMSC/311x.pdf 12 Datasheet: http://www.nuhorizons.com/FeaturedProducts/Volume1/SMSC/311x.pdf
13 * SMSC SCH5027
14 Prefix: 'sch5027'
15 Addresses scanned: I2C 0x2c, 0x2d, 0x2e
16 Datasheet: Provided by SMSC upon request and under NDA
13 17
14Authors: 18Authors:
15 Juerg Haefliger <juergh@gmail.com> 19 Juerg Haefliger <juergh@gmail.com>
@@ -27,33 +31,31 @@ Module Parameters
27 following boards: 31 following boards:
28 - VIA EPIA SN18000 32 - VIA EPIA SN18000
29 33
30Note that there is no need to use this parameter if the driver loads without
31complaining. The driver will say so if it is necessary.
32
33 34
34Description 35Description
35----------- 36-----------
36 37
37This driver implements support for the hardware monitoring capabilities of the 38This driver implements support for the hardware monitoring capabilities of the
38SMSC DME1737 and Asus A8000 (which are the same) and SMSC SCH311x Super-I/O 39SMSC DME1737 and Asus A8000 (which are the same), SMSC SCH5027, and SMSC
39chips. These chips feature monitoring of 3 temp sensors temp[1-3] (2 remote 40SCH311x Super-I/O chips. These chips feature monitoring of 3 temp sensors
40diodes and 1 internal), 7 voltages in[0-6] (6 external and 1 internal) and up 41temp[1-3] (2 remote diodes and 1 internal), 7 voltages in[0-6] (6 external and
41to 6 fan speeds fan[1-6]. Additionally, the chips implement up to 5 PWM 421 internal) and up to 6 fan speeds fan[1-6]. Additionally, the chips implement
42outputs pwm[1-3,5-6] for controlling fan speeds both manually and 43up to 5 PWM outputs pwm[1-3,5-6] for controlling fan speeds both manually and
43automatically. 44automatically.
44 45
45For the DME1737 and A8000, fan[1-2] and pwm[1-2] are always present. Fan[3-6] 46For the DME1737, A8000 and SCH5027, fan[1-2] and pwm[1-2] are always present.
46and pwm[3,5-6] are optional features and their availability depends on the 47Fan[3-6] and pwm[3,5-6] are optional features and their availability depends on
47configuration of the chip. The driver will detect which features are present 48the configuration of the chip. The driver will detect which features are
48during initialization and create the sysfs attributes accordingly. 49present during initialization and create the sysfs attributes accordingly.
49 50
50For the SCH311x, fan[1-3] and pwm[1-3] are always present and fan[4-6] and 51For the SCH311x, fan[1-3] and pwm[1-3] are always present and fan[4-6] and
51pwm[5-6] don't exist. 52pwm[5-6] don't exist.
52 53
53The hardware monitoring features of the DME1737 and A8000 are only accessible 54The hardware monitoring features of the DME1737, A8000, and SCH5027 are only
54via SMBus, while the SCH311x only provides access via the ISA bus. The driver 55accessible via SMBus, while the SCH311x only provides access via the ISA bus.
55will therefore register itself as an I2C client driver if it detects a DME1737 56The driver will therefore register itself as an I2C client driver if it detects
56or A8000 and as a platform driver if it detects a SCH311x chip. 57a DME1737, A8000, or SCH5027 and as a platform driver if it detects a SCH311x
58chip.
57 59
58 60
59Voltage Monitoring 61Voltage Monitoring
@@ -64,6 +66,7 @@ scaling resistors. The values returned by the driver therefore reflect true
64millivolts and don't need scaling. The voltage inputs are mapped as follows 66millivolts and don't need scaling. The voltage inputs are mapped as follows
65(the last column indicates the input ranges): 67(the last column indicates the input ranges):
66 68
69DME1737, A8000:
67 in0: +5VTR (+5V standby) 0V - 6.64V 70 in0: +5VTR (+5V standby) 0V - 6.64V
68 in1: Vccp (processor core) 0V - 3V 71 in1: Vccp (processor core) 0V - 3V
69 in2: VCC (internal +3.3V) 0V - 4.38V 72 in2: VCC (internal +3.3V) 0V - 4.38V
@@ -72,6 +75,24 @@ millivolts and don't need scaling. The voltage inputs are mapped as follows
72 in5: VTR (+3.3V standby) 0V - 4.38V 75 in5: VTR (+3.3V standby) 0V - 4.38V
73 in6: Vbat (+3.0V) 0V - 4.38V 76 in6: Vbat (+3.0V) 0V - 4.38V
74 77
78SCH311x:
79 in0: +2.5V 0V - 6.64V
80 in1: Vccp (processor core) 0V - 2V
81 in2: VCC (internal +3.3V) 0V - 4.38V
82 in3: +5V 0V - 6.64V
83 in4: +12V 0V - 16V
84 in5: VTR (+3.3V standby) 0V - 4.38V
85 in6: Vbat (+3.0V) 0V - 4.38V
86
87SCH5027:
88 in0: +5VTR (+5V standby) 0V - 6.64V
89 in1: Vccp (processor core) 0V - 3V
90 in2: VCC (internal +3.3V) 0V - 4.38V
91 in3: V2_IN 0V - 1.5V
92 in4: V1_IN 0V - 1.5V
93 in5: VTR (+3.3V standby) 0V - 4.38V
94 in6: Vbat (+3.0V) 0V - 4.38V
95
75Each voltage input has associated min and max limits which trigger an alarm 96Each voltage input has associated min and max limits which trigger an alarm
76when crossed. 97when crossed.
77 98
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index f4ce1fdbeff6..3496b7020e7c 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -6,12 +6,14 @@ Supported chips:
6 Prefix: 'it87' 6 Prefix: 'it87'
7 Addresses scanned: from Super I/O config space (8 I/O ports) 7 Addresses scanned: from Super I/O config space (8 I/O ports)
8 Datasheet: Publicly available at the ITE website 8 Datasheet: Publicly available at the ITE website
9 http://www.ite.com.tw/ 9 http://www.ite.com.tw/product_info/file/pc/IT8705F_V.0.4.1.pdf
10 * IT8712F 10 * IT8712F
11 Prefix: 'it8712' 11 Prefix: 'it8712'
12 Addresses scanned: from Super I/O config space (8 I/O ports) 12 Addresses scanned: from Super I/O config space (8 I/O ports)
13 Datasheet: Publicly available at the ITE website 13 Datasheet: Publicly available at the ITE website
14 http://www.ite.com.tw/ 14 http://www.ite.com.tw/product_info/file/pc/IT8712F_V0.9.1.pdf
15 http://www.ite.com.tw/product_info/file/pc/Errata%20V0.1%20for%20IT8712F%20V0.9.1.pdf
16 http://www.ite.com.tw/product_info/file/pc/IT8712F_V0.9.3.pdf
15 * IT8716F/IT8726F 17 * IT8716F/IT8726F
16 Prefix: 'it8716' 18 Prefix: 'it8716'
17 Addresses scanned: from Super I/O config space (8 I/O ports) 19 Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -90,14 +92,13 @@ upper VID bits share their pins with voltage inputs (in5 and in6) so you
90can't have both on a given board. 92can't have both on a given board.
91 93
92The IT8716F, IT8718F and later IT8712F revisions have support for 94The IT8716F, IT8718F and later IT8712F revisions have support for
932 additional fans. They are supported by the driver for the IT8716F and 952 additional fans. The additional fans are supported by the driver.
94IT8718F but not for the IT8712F
95 96
96The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional 97The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional
9716-bit tachometer counters for fans 1 to 3. This is better (no more fan 9816-bit tachometer counters for fans 1 to 3. This is better (no more fan
98clock divider mess) but not compatible with the older chips and 99clock divider mess) but not compatible with the older chips and
99revisions. For now, the driver only uses the 16-bit mode on the 100revisions. The 16-bit tachometer mode is enabled by the driver when one
100IT8716F and IT8718F. 101of the above chips is detected.
101 102
102The IT8726F is just bit enhanced IT8716F with additional hardware 103The IT8726F is just bit enhanced IT8716F with additional hardware
103for AMD power sequencing. Therefore the chip will appear as IT8716F 104for AMD power sequencing. Therefore the chip will appear as IT8716F
diff --git a/Documentation/hwmon/w83627hf b/Documentation/hwmon/w83627hf
index 880a59f53da9..6ee36dbafd64 100644
--- a/Documentation/hwmon/w83627hf
+++ b/Documentation/hwmon/w83627hf
@@ -40,10 +40,6 @@ Module Parameters
40 (default is 1) 40 (default is 1)
41 Use 'init=0' to bypass initializing the chip. 41 Use 'init=0' to bypass initializing the chip.
42 Try this if your computer crashes when you load the module. 42 Try this if your computer crashes when you load the module.
43* reset: int
44 (default is 0)
45 The driver used to reset the chip on load, but does no more. Use
46 'reset=1' to restore the old behavior. Report if you need to do this.
47 43
48Description 44Description
49----------- 45-----------
diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d
index f153b2f6d62c..a67d3b7a7098 100644
--- a/Documentation/hwmon/w83791d
+++ b/Documentation/hwmon/w83791d
@@ -22,6 +22,7 @@ Credits:
22 22
23Additional contributors: 23Additional contributors:
24 Sven Anders <anders@anduras.de> 24 Sven Anders <anders@anduras.de>
25 Marc Hulsman <m.hulsman@tudelft.nl>
25 26
26Module Parameters 27Module Parameters
27----------------- 28-----------------
@@ -67,9 +68,8 @@ on until the temperature falls below the Hysteresis value.
67 68
68Fan rotation speeds are reported in RPM (rotations per minute). An alarm is 69Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
69triggered if the rotation speed has dropped below a programmable limit. Fan 70triggered if the rotation speed has dropped below a programmable limit. Fan
70readings can be divided by a programmable divider (1, 2, 4, 8 for fan 1/2/3 71readings can be divided by a programmable divider (1, 2, 4, 8, 16,
71and 1, 2, 4, 8, 16, 32, 64 or 128 for fan 4/5) to give the readings more 7232, 64 or 128 for all fans) to give the readings more range or accuracy.
72range or accuracy.
73 73
74Voltage sensors (also known as IN sensors) report their values in millivolts. 74Voltage sensors (also known as IN sensors) report their values in millivolts.
75An alarm is triggered if the voltage has crossed a programmable minimum 75An alarm is triggered if the voltage has crossed a programmable minimum
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index bcaf4ab383be..78a863ab8a5a 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -226,6 +226,7 @@ sonixj 0c45:6130 Sonix Pccam
226sonixj 0c45:6138 Sn9c120 Mo4000 226sonixj 0c45:6138 Sn9c120 Mo4000
227sonixj 0c45:613b Surfer SN-206 227sonixj 0c45:613b Surfer SN-206
228sonixj 0c45:613c Sonix Pccam168 228sonixj 0c45:613c Sonix Pccam168
229sonixj 0c45:6143 Sonix Pccam168
229sunplus 0d64:0303 Sunplus FashionCam DXG 230sunplus 0d64:0303 Sunplus FashionCam DXG
230etoms 102c:6151 Qcam Sangha CIF 231etoms 102c:6151 Qcam Sangha CIF
231etoms 102c:6251 Qcam xxxxxx VGA 232etoms 102c:6251 Qcam xxxxxx VGA
diff --git a/Makefile b/Makefile
index ea413fa03e4e..f3e206509ee1 100644
--- a/Makefile
+++ b/Makefile
@@ -929,10 +929,10 @@ ifneq ($(KBUILD_SRC),)
929 echo " in the '$(srctree)' directory.";\ 929 echo " in the '$(srctree)' directory.";\
930 /bin/false; \ 930 /bin/false; \
931 fi; 931 fi;
932 $(Q)if [ ! -d include2 ]; then mkdir -p include2; fi; 932 $(Q)if [ ! -d include2 ]; then \
933 $(Q)if [ -e $(srctree)/include/asm-$(SRCARCH)/errno.h ]; then \ 933 mkdir -p include2; \
934 ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm; \ 934 ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm; \
935 fi 935 fi
936endif 936endif
937 937
938# prepare2 creates a makefile if using a separate output directory 938# prepare2 creates a makefile if using a separate output directory
@@ -1492,7 +1492,7 @@ quiet_cmd_cscope-file = FILELST cscope.files
1492 cmd_cscope-file = (echo \-k; echo \-q; $(all-sources)) > cscope.files 1492 cmd_cscope-file = (echo \-k; echo \-q; $(all-sources)) > cscope.files
1493 1493
1494quiet_cmd_cscope = MAKE cscope.out 1494quiet_cmd_cscope = MAKE cscope.out
1495 cmd_cscope = cscope -b 1495 cmd_cscope = cscope -b -f cscope.out
1496 1496
1497cscope: FORCE 1497cscope: FORCE
1498 $(call cmd,cscope-file) 1498 $(call cmd,cscope-file)
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig
index ea3e541ac74f..45ffd8e542f4 100644
--- a/arch/powerpc/platforms/iseries/Kconfig
+++ b/arch/powerpc/platforms/iseries/Kconfig
@@ -7,15 +7,6 @@ config PPC_ISERIES
7menu "iSeries device drivers" 7menu "iSeries device drivers"
8 depends on PPC_ISERIES 8 depends on PPC_ISERIES
9 9
10config VIOCONS
11 bool "iSeries Virtual Console Support (Obsolete)"
12 depends on !HVC_ISERIES
13 default n
14 help
15 This is the old virtual console driver for legacy iSeries.
16 You should use the iSeries Hypervisor Virtual Console
17 support instead.
18
19config VIODASD 10config VIODASD
20 tristate "iSeries Virtual I/O disk support" 11 tristate "iSeries Virtual I/O disk support"
21 help 12 help
@@ -38,5 +29,5 @@ endmenu
38 29
39config VIOPATH 30config VIOPATH
40 bool 31 bool
41 depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || ISERIES_VETH 32 depends on VIODASD || VIOCD || VIOTAPE || ISERIES_VETH
42 default y 33 default y
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index d0ac944e1696..caff85149b9d 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -8,7 +8,7 @@ config VT
8 bool "Virtual terminal" if EMBEDDED 8 bool "Virtual terminal" if EMBEDDED
9 depends on !S390 9 depends on !S390
10 select INPUT 10 select INPUT
11 default y if !VIOCONS 11 default y
12 ---help--- 12 ---help---
13 If you say Y here, you will get support for terminal devices with 13 If you say Y here, you will get support for terminal devices with
14 display and keyboard devices. These are called "virtual" because you 14 display and keyboard devices. These are called "virtual" because you
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 8a161c30e1dc..6850f6da7576 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -55,7 +55,6 @@ obj-$(CONFIG_RAW_DRIVER) += raw.o
55obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o 55obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
56obj-$(CONFIG_MSPEC) += mspec.o 56obj-$(CONFIG_MSPEC) += mspec.o
57obj-$(CONFIG_MMTIMER) += mmtimer.o 57obj-$(CONFIG_MMTIMER) += mmtimer.o
58obj-$(CONFIG_VIOCONS) += viocons.o
59obj-$(CONFIG_VIOTAPE) += viotape.o 58obj-$(CONFIG_VIOTAPE) += viotape.o
60obj-$(CONFIG_HVCS) += hvcs.o 59obj-$(CONFIG_HVCS) += hvcs.o
61obj-$(CONFIG_IBM_BSR) += bsr.o 60obj-$(CONFIG_IBM_BSR) += bsr.o
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
deleted file mode 100644
index 7feeb774a101..000000000000
--- a/drivers/char/viocons.c
+++ /dev/null
@@ -1,1167 +0,0 @@
1/* -*- linux-c -*-
2 *
3 * drivers/char/viocons.c
4 *
5 * iSeries Virtual Terminal
6 *
7 * Authors: Dave Boutcher <boutcher@us.ibm.com>
8 * Ryan Arnold <ryanarn@us.ibm.com>
9 * Colin Devilbiss <devilbis@us.ibm.com>
10 * Stephen Rothwell
11 *
12 * (C) Copyright 2000, 2001, 2002, 2003, 2004 IBM Corporation
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) anyu later version.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 */
28#include <linux/kernel.h>
29#include <linux/proc_fs.h>
30#include <linux/errno.h>
31#include <linux/vmalloc.h>
32#include <linux/mm.h>
33#include <linux/console.h>
34#include <linux/module.h>
35#include <asm/uaccess.h>
36#include <linux/init.h>
37#include <linux/wait.h>
38#include <linux/spinlock.h>
39#include <asm/ioctls.h>
40#include <linux/kd.h>
41#include <linux/tty.h>
42#include <linux/tty_flip.h>
43#include <linux/sysrq.h>
44
45#include <asm/firmware.h>
46#include <asm/iseries/vio.h>
47#include <asm/iseries/hv_lp_event.h>
48#include <asm/iseries/hv_call_event.h>
49#include <asm/iseries/hv_lp_config.h>
50#include <asm/iseries/hv_call.h>
51
52#ifdef CONFIG_VT
53#error You must turn off CONFIG_VT to use CONFIG_VIOCONS
54#endif
55
56#define VIOTTY_MAGIC (0x0DCB)
57#define VTTY_PORTS 10
58
59#define VIOCONS_KERN_WARN KERN_WARNING "viocons: "
60#define VIOCONS_KERN_INFO KERN_INFO "viocons: "
61
62static DEFINE_SPINLOCK(consolelock);
63static DEFINE_SPINLOCK(consoleloglock);
64
65static int vio_sysrq_pressed;
66
67#define VIOCHAR_NUM_BUF 16
68
69/*
70 * Our port information. We store a pointer to one entry in the
71 * tty_driver_data
72 */
73static struct port_info {
74 int magic;
75 struct tty_struct *tty;
76 HvLpIndex lp;
77 u8 vcons;
78 u64 seq; /* sequence number of last HV send */
79 u64 ack; /* last ack from HV */
80/*
81 * When we get writes faster than we can send it to the partition,
82 * buffer the data here. Note that used is a bit map of used buffers.
83 * It had better have enough bits to hold VIOCHAR_NUM_BUF the bitops assume
84 * it is a multiple of unsigned long
85 */
86 unsigned long used;
87 u8 *buffer[VIOCHAR_NUM_BUF];
88 int bufferBytes[VIOCHAR_NUM_BUF];
89 int curbuf;
90 int bufferOverflow;
91 int overflowMessage;
92} port_info[VTTY_PORTS];
93
94#define viochar_is_console(pi) ((pi) == &port_info[0])
95#define viochar_port(pi) ((pi) - &port_info[0])
96
97static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp);
98
99static struct tty_driver *viotty_driver;
100
101static void hvlog(char *fmt, ...)
102{
103 int i;
104 unsigned long flags;
105 va_list args;
106 static char buf[256];
107
108 spin_lock_irqsave(&consoleloglock, flags);
109 va_start(args, fmt);
110 i = vscnprintf(buf, sizeof(buf) - 1, fmt, args);
111 va_end(args);
112 buf[i++] = '\r';
113 HvCall_writeLogBuffer(buf, i);
114 spin_unlock_irqrestore(&consoleloglock, flags);
115}
116
117static void hvlogOutput(const char *buf, int count)
118{
119 unsigned long flags;
120 int begin;
121 int index;
122 static const char cr = '\r';
123
124 begin = 0;
125 spin_lock_irqsave(&consoleloglock, flags);
126 for (index = 0; index < count; index++) {
127 if (buf[index] == '\n') {
128 /*
129 * Start right after the last '\n' or at the zeroth
130 * array position and output the number of characters
131 * including the newline.
132 */
133 HvCall_writeLogBuffer(&buf[begin], index - begin + 1);
134 begin = index + 1;
135 HvCall_writeLogBuffer(&cr, 1);
136 }
137 }
138 if ((index - begin) > 0)
139 HvCall_writeLogBuffer(&buf[begin], index - begin);
140 spin_unlock_irqrestore(&consoleloglock, flags);
141}
142
143/*
144 * Make sure we're pointing to a valid port_info structure. Shamelessly
145 * plagerized from serial.c
146 */
147static inline int viotty_paranoia_check(struct port_info *pi,
148 char *name, const char *routine)
149{
150 static const char *bad_pi_addr = VIOCONS_KERN_WARN
151 "warning: bad address for port_info struct (%s) in %s\n";
152 static const char *badmagic = VIOCONS_KERN_WARN
153 "warning: bad magic number for port_info struct (%s) in %s\n";
154
155 if ((pi < &port_info[0]) || (viochar_port(pi) > VTTY_PORTS)) {
156 printk(bad_pi_addr, name, routine);
157 return 1;
158 }
159 if (pi->magic != VIOTTY_MAGIC) {
160 printk(badmagic, name, routine);
161 return 1;
162 }
163 return 0;
164}
165
166/*
167 * Add data to our pending-send buffers.
168 *
169 * NOTE: Don't use printk in here because it gets nastily recursive.
170 * hvlog can be used to log to the hypervisor buffer
171 */
172static int buffer_add(struct port_info *pi, const char *buf, size_t len)
173{
174 size_t bleft;
175 size_t curlen;
176 const char *curbuf;
177 int nextbuf;
178
179 curbuf = buf;
180 bleft = len;
181 while (bleft > 0) {
182 /*
183 * If there is no space left in the current buffer, we have
184 * filled everything up, so return. If we filled the previous
185 * buffer we would already have moved to the next one.
186 */
187 if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) {
188 hvlog ("\n\rviocons: No overflow buffer available for memcpy().\n");
189 pi->bufferOverflow++;
190 pi->overflowMessage = 1;
191 break;
192 }
193
194 /*
195 * Turn on the "used" bit for this buffer. If it's already on,
196 * that's fine.
197 */
198 set_bit(pi->curbuf, &pi->used);
199
200 /*
201 * See if this buffer has been allocated. If not, allocate it.
202 */
203 if (pi->buffer[pi->curbuf] == NULL) {
204 pi->buffer[pi->curbuf] =
205 kmalloc(VIOCHAR_MAX_DATA, GFP_ATOMIC);
206 if (pi->buffer[pi->curbuf] == NULL) {
207 hvlog("\n\rviocons: kmalloc failed allocating spaces for buffer %d.",
208 pi->curbuf);
209 break;
210 }
211 }
212
213 /* Figure out how much we can copy into this buffer. */
214 if (bleft < (VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf]))
215 curlen = bleft;
216 else
217 curlen = VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf];
218
219 /* Copy the data into the buffer. */
220 memcpy(pi->buffer[pi->curbuf] + pi->bufferBytes[pi->curbuf],
221 curbuf, curlen);
222
223 pi->bufferBytes[pi->curbuf] += curlen;
224 curbuf += curlen;
225 bleft -= curlen;
226
227 /*
228 * Now see if we've filled this buffer. If not then
229 * we'll try to use it again later. If we've filled it
230 * up then we'll advance the curbuf to the next in the
231 * circular queue.
232 */
233 if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) {
234 nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF;
235 /*
236 * Move to the next buffer if it hasn't been used yet
237 */
238 if (test_bit(nextbuf, &pi->used) == 0)
239 pi->curbuf = nextbuf;
240 }
241 }
242 return len - bleft;
243}
244
245/*
246 * Send pending data
247 *
248 * NOTE: Don't use printk in here because it gets nastily recursive.
249 * hvlog can be used to log to the hypervisor buffer
250 */
251static void send_buffers(struct port_info *pi)
252{
253 HvLpEvent_Rc hvrc;
254 int nextbuf;
255 struct viocharlpevent *viochar;
256 unsigned long flags;
257
258 spin_lock_irqsave(&consolelock, flags);
259
260 viochar = (struct viocharlpevent *)
261 vio_get_event_buffer(viomajorsubtype_chario);
262
263 /* Make sure we got a buffer */
264 if (viochar == NULL) {
265 hvlog("\n\rviocons: Can't get viochar buffer in sendBuffers().");
266 spin_unlock_irqrestore(&consolelock, flags);
267 return;
268 }
269
270 if (pi->used == 0) {
271 hvlog("\n\rviocons: in sendbuffers(), but no buffers used.\n");
272 vio_free_event_buffer(viomajorsubtype_chario, viochar);
273 spin_unlock_irqrestore(&consolelock, flags);
274 return;
275 }
276
277 /*
278 * curbuf points to the buffer we're filling. We want to
279 * start sending AFTER this one.
280 */
281 nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF;
282
283 /*
284 * Loop until we find a buffer with the used bit on
285 */
286 while (test_bit(nextbuf, &pi->used) == 0)
287 nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF;
288
289 initDataEvent(viochar, pi->lp);
290
291 /*
292 * While we have buffers with data, and our send window
293 * is open, send them
294 */
295 while ((test_bit(nextbuf, &pi->used)) &&
296 ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) {
297 viochar->len = pi->bufferBytes[nextbuf];
298 viochar->event.xCorrelationToken = pi->seq++;
299 viochar->event.xSizeMinus1 =
300 offsetof(struct viocharlpevent, data) + viochar->len;
301
302 memcpy(viochar->data, pi->buffer[nextbuf], viochar->len);
303
304 hvrc = HvCallEvent_signalLpEvent(&viochar->event);
305 if (hvrc) {
306 /*
307 * MUST unlock the spinlock before doing a printk
308 */
309 vio_free_event_buffer(viomajorsubtype_chario, viochar);
310 spin_unlock_irqrestore(&consolelock, flags);
311
312 printk(VIOCONS_KERN_WARN
313 "error sending event! return code %d\n",
314 (int)hvrc);
315 return;
316 }
317
318 /*
319 * clear the used bit, zero the number of bytes in
320 * this buffer, and move to the next buffer
321 */
322 clear_bit(nextbuf, &pi->used);
323 pi->bufferBytes[nextbuf] = 0;
324 nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF;
325 }
326
327 /*
328 * If we have emptied all the buffers, start at 0 again.
329 * this will re-use any allocated buffers
330 */
331 if (pi->used == 0) {
332 pi->curbuf = 0;
333
334 if (pi->overflowMessage)
335 pi->overflowMessage = 0;
336
337 if (pi->tty) {
338 tty_wakeup(pi->tty);
339 }
340 }
341
342 vio_free_event_buffer(viomajorsubtype_chario, viochar);
343 spin_unlock_irqrestore(&consolelock, flags);
344}
345
346/*
347 * Our internal writer. Gets called both from the console device and
348 * the tty device. the tty pointer will be NULL if called from the console.
349 * Return total number of bytes "written".
350 *
351 * NOTE: Don't use printk in here because it gets nastily recursive. hvlog
352 * can be used to log to the hypervisor buffer
353 */
354static int internal_write(struct port_info *pi, const char *buf, size_t len)
355{
356 HvLpEvent_Rc hvrc;
357 size_t bleft;
358 size_t curlen;
359 const char *curbuf;
360 unsigned long flags;
361 struct viocharlpevent *viochar;
362
363 /*
364 * Write to the hvlog of inbound data are now done prior to
365 * calling internal_write() since internal_write() is only called in
366 * the event that an lp event path is active, which isn't the case for
367 * logging attempts prior to console initialization.
368 *
369 * If there is already data queued for this port, send it prior to
370 * attempting to send any new data.
371 */
372 if (pi->used)
373 send_buffers(pi);
374
375 spin_lock_irqsave(&consolelock, flags);
376
377 viochar = vio_get_event_buffer(viomajorsubtype_chario);
378 if (viochar == NULL) {
379 spin_unlock_irqrestore(&consolelock, flags);
380 hvlog("\n\rviocons: Can't get vio buffer in internal_write().");
381 return -EAGAIN;
382 }
383 initDataEvent(viochar, pi->lp);
384
385 curbuf = buf;
386 bleft = len;
387
388 while ((bleft > 0) && (pi->used == 0) &&
389 ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) {
390 if (bleft > VIOCHAR_MAX_DATA)
391 curlen = VIOCHAR_MAX_DATA;
392 else
393 curlen = bleft;
394
395 viochar->event.xCorrelationToken = pi->seq++;
396 memcpy(viochar->data, curbuf, curlen);
397 viochar->len = curlen;
398 viochar->event.xSizeMinus1 =
399 offsetof(struct viocharlpevent, data) + curlen;
400
401 hvrc = HvCallEvent_signalLpEvent(&viochar->event);
402 if (hvrc) {
403 hvlog("viocons: error sending event! %d\n", (int)hvrc);
404 goto out;
405 }
406 curbuf += curlen;
407 bleft -= curlen;
408 }
409
410 /* If we didn't send it all, buffer as much of it as we can. */
411 if (bleft > 0)
412 bleft -= buffer_add(pi, curbuf, bleft);
413out:
414 vio_free_event_buffer(viomajorsubtype_chario, viochar);
415 spin_unlock_irqrestore(&consolelock, flags);
416 return len - bleft;
417}
418
419static struct port_info *get_port_data(struct tty_struct *tty)
420{
421 unsigned long flags;
422 struct port_info *pi;
423
424 spin_lock_irqsave(&consolelock, flags);
425 if (tty) {
426 pi = (struct port_info *)tty->driver_data;
427 if (!pi || viotty_paranoia_check(pi, tty->name,
428 "get_port_data")) {
429 pi = NULL;
430 }
431 } else
432 /*
433 * If this is the console device, use the lp from
434 * the first port entry
435 */
436 pi = &port_info[0];
437 spin_unlock_irqrestore(&consolelock, flags);
438 return pi;
439}
440
441/*
442 * Initialize the common fields in a charLpEvent
443 */
444static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp)
445{
446 struct HvLpEvent *hev = &viochar->event;
447
448 memset(viochar, 0, sizeof(struct viocharlpevent));
449
450 hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK |
451 HV_LP_EVENT_INT;
452 hev->xType = HvLpEvent_Type_VirtualIo;
453 hev->xSubtype = viomajorsubtype_chario | viochardata;
454 hev->xSourceLp = HvLpConfig_getLpIndex();
455 hev->xTargetLp = lp;
456 hev->xSizeMinus1 = sizeof(struct viocharlpevent);
457 hev->xSourceInstanceId = viopath_sourceinst(lp);
458 hev->xTargetInstanceId = viopath_targetinst(lp);
459}
460
461/*
462 * early console device write
463 */
464static void viocons_write_early(struct console *co, const char *s, unsigned count)
465{
466 hvlogOutput(s, count);
467}
468
469/*
470 * console device write
471 */
472static void viocons_write(struct console *co, const char *s, unsigned count)
473{
474 int index;
475 int begin;
476 struct port_info *pi;
477
478 static const char cr = '\r';
479
480 /*
481 * Check port data first because the target LP might be valid but
482 * simply not active, in which case we want to hvlog the output.
483 */
484 pi = get_port_data(NULL);
485 if (pi == NULL) {
486 hvlog("\n\rviocons_write: unable to get port data.");
487 return;
488 }
489
490 hvlogOutput(s, count);
491
492 if (!viopath_isactive(pi->lp))
493 return;
494
495 /*
496 * Any newline character found will cause a
497 * carriage return character to be emitted as well.
498 */
499 begin = 0;
500 for (index = 0; index < count; index++) {
501 if (s[index] == '\n') {
502 /*
503 * Newline found. Print everything up to and
504 * including the newline
505 */
506 internal_write(pi, &s[begin], index - begin + 1);
507 begin = index + 1;
508 /* Emit a carriage return as well */
509 internal_write(pi, &cr, 1);
510 }
511 }
512
513 /* If any characters left to write, write them now */
514 if ((index - begin) > 0)
515 internal_write(pi, &s[begin], index - begin);
516}
517
518/*
519 * Work out the device associate with this console
520 */
521static struct tty_driver *viocons_device(struct console *c, int *index)
522{
523 *index = c->index;
524 return viotty_driver;
525}
526
527/*
528 * console device I/O methods
529 */
530static struct console viocons_early = {
531 .name = "viocons",
532 .write = viocons_write_early,
533 .flags = CON_PRINTBUFFER,
534 .index = -1,
535};
536
537static struct console viocons = {
538 .name = "viocons",
539 .write = viocons_write,
540 .device = viocons_device,
541 .flags = CON_PRINTBUFFER,
542 .index = -1,
543};
544
545/*
546 * TTY Open method
547 */
548static int viotty_open(struct tty_struct *tty, struct file *filp)
549{
550 int port;
551 unsigned long flags;
552 struct port_info *pi;
553
554 port = tty->index;
555
556 if ((port < 0) || (port >= VTTY_PORTS))
557 return -ENODEV;
558
559 spin_lock_irqsave(&consolelock, flags);
560
561 pi = &port_info[port];
562 /* If some other TTY is already connected here, reject the open */
563 if ((pi->tty) && (pi->tty != tty)) {
564 spin_unlock_irqrestore(&consolelock, flags);
565 printk(VIOCONS_KERN_WARN
566 "attempt to open device twice from different ttys\n");
567 return -EBUSY;
568 }
569 tty->driver_data = pi;
570 pi->tty = tty;
571 spin_unlock_irqrestore(&consolelock, flags);
572
573 return 0;
574}
575
576/*
577 * TTY Close method
578 */
579static void viotty_close(struct tty_struct *tty, struct file *filp)
580{
581 unsigned long flags;
582 struct port_info *pi;
583
584 spin_lock_irqsave(&consolelock, flags);
585 pi = (struct port_info *)tty->driver_data;
586
587 if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_close")) {
588 spin_unlock_irqrestore(&consolelock, flags);
589 return;
590 }
591 if (tty->count == 1)
592 pi->tty = NULL;
593 spin_unlock_irqrestore(&consolelock, flags);
594}
595
596/*
597 * TTY Write method
598 */
599static int viotty_write(struct tty_struct *tty, const unsigned char *buf,
600 int count)
601{
602 struct port_info *pi;
603
604 pi = get_port_data(tty);
605 if (pi == NULL) {
606 hvlog("\n\rviotty_write: no port data.");
607 return -ENODEV;
608 }
609
610 if (viochar_is_console(pi))
611 hvlogOutput(buf, count);
612
613 /*
614 * If the path to this LP is closed, don't bother doing anything more.
615 * just dump the data on the floor and return count. For some reason
616 * some user level programs will attempt to probe available tty's and
617 * they'll attempt a viotty_write on an invalid port which maps to an
618 * invalid target lp. If this is the case then ignore the
619 * viotty_write call and, since the viopath isn't active to this
620 * partition, return count.
621 */
622 if (!viopath_isactive(pi->lp))
623 return count;
624
625 return internal_write(pi, buf, count);
626}
627
628/*
629 * TTY put_char method
630 */
631static int viotty_put_char(struct tty_struct *tty, unsigned char ch)
632{
633 struct port_info *pi;
634
635 pi = get_port_data(tty);
636 if (pi == NULL)
637 return 0;
638
639 /* This will append '\r' as well if the char is '\n' */
640 if (viochar_is_console(pi))
641 hvlogOutput(&ch, 1);
642
643 if (viopath_isactive(pi->lp))
644 internal_write(pi, &ch, 1);
645 return 1;
646}
647
648/*
649 * TTY write_room method
650 */
651static int viotty_write_room(struct tty_struct *tty)
652{
653 int i;
654 int room = 0;
655 struct port_info *pi;
656 unsigned long flags;
657
658 spin_lock_irqsave(&consolelock, flags);
659 pi = (struct port_info *)tty->driver_data;
660 if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_write_room")) {
661 spin_unlock_irqrestore(&consolelock, flags);
662 return 0;
663 }
664
665 /* If no buffers are used, return the max size. */
666 if (pi->used == 0) {
667 spin_unlock_irqrestore(&consolelock, flags);
668 return VIOCHAR_MAX_DATA * VIOCHAR_NUM_BUF;
669 }
670
671 /*
672 * We retain the spinlock because we want to get an accurate
673 * count and it can change on us between each operation if we
674 * don't hold the spinlock.
675 */
676 for (i = 0; ((i < VIOCHAR_NUM_BUF) && (room < VIOCHAR_MAX_DATA)); i++)
677 room += (VIOCHAR_MAX_DATA - pi->bufferBytes[i]);
678 spin_unlock_irqrestore(&consolelock, flags);
679
680 if (room > VIOCHAR_MAX_DATA)
681 room = VIOCHAR_MAX_DATA;
682 return room;
683}
684
685/*
686 * TTY chars_in_buffer method
687 */
688static int viotty_chars_in_buffer(struct tty_struct *tty)
689{
690 return 0;
691}
692
693static int viotty_ioctl(struct tty_struct *tty, struct file *file,
694 unsigned int cmd, unsigned long arg)
695{
696 switch (cmd) {
697 /*
698 * the ioctls below read/set the flags usually shown in the leds
699 * don't use them - they will go away without warning
700 */
701 case KDGETLED:
702 case KDGKBLED:
703 return put_user(0, (char *)arg);
704
705 case KDSKBLED:
706 return 0;
707 }
708 return -ENOIOCTLCMD;
709}
710
711/*
712 * Handle an open charLpEvent. Could be either interrupt or ack
713 */
714static void vioHandleOpenEvent(struct HvLpEvent *event)
715{
716 unsigned long flags;
717 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
718 u8 port = cevent->virtual_device;
719 struct port_info *pi;
720 int reject = 0;
721
722 if (hvlpevent_is_ack(event)) {
723 if (port >= VTTY_PORTS)
724 return;
725
726 spin_lock_irqsave(&consolelock, flags);
727 /* Got the lock, don't cause console output */
728
729 pi = &port_info[port];
730 if (event->xRc == HvLpEvent_Rc_Good) {
731 pi->seq = pi->ack = 0;
732 /*
733 * This line allows connections from the primary
734 * partition but once one is connected from the
735 * primary partition nothing short of a reboot
736 * of linux will allow access from the hosting
737 * partition again without a required iSeries fix.
738 */
739 pi->lp = event->xTargetLp;
740 }
741
742 spin_unlock_irqrestore(&consolelock, flags);
743 if (event->xRc != HvLpEvent_Rc_Good)
744 printk(VIOCONS_KERN_WARN
745 "handle_open_event: event->xRc == (%d).\n",
746 event->xRc);
747
748 if (event->xCorrelationToken != 0) {
749 atomic_t *aptr= (atomic_t *)event->xCorrelationToken;
750 atomic_set(aptr, 1);
751 } else
752 printk(VIOCONS_KERN_WARN
753 "weird...got open ack without atomic\n");
754 return;
755 }
756
757 /* This had better require an ack, otherwise complain */
758 if (!hvlpevent_need_ack(event)) {
759 printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n");
760 return;
761 }
762
763 spin_lock_irqsave(&consolelock, flags);
764 /* Got the lock, don't cause console output */
765
766 /* Make sure this is a good virtual tty */
767 if (port >= VTTY_PORTS) {
768 event->xRc = HvLpEvent_Rc_SubtypeError;
769 cevent->subtype_result_code = viorc_openRejected;
770 /*
771 * Flag state here since we can't printk while holding
772 * a spinlock.
773 */
774 reject = 1;
775 } else {
776 pi = &port_info[port];
777 if ((pi->lp != HvLpIndexInvalid) &&
778 (pi->lp != event->xSourceLp)) {
779 /*
780 * If this is tty is already connected to a different
781 * partition, fail.
782 */
783 event->xRc = HvLpEvent_Rc_SubtypeError;
784 cevent->subtype_result_code = viorc_openRejected;
785 reject = 2;
786 } else {
787 pi->lp = event->xSourceLp;
788 event->xRc = HvLpEvent_Rc_Good;
789 cevent->subtype_result_code = viorc_good;
790 pi->seq = pi->ack = 0;
791 reject = 0;
792 }
793 }
794
795 spin_unlock_irqrestore(&consolelock, flags);
796
797 if (reject == 1)
798 printk(VIOCONS_KERN_WARN "open rejected: bad virtual tty.\n");
799 else if (reject == 2)
800 printk(VIOCONS_KERN_WARN
801 "open rejected: console in exclusive use by another partition.\n");
802
803 /* Return the acknowledgement */
804 HvCallEvent_ackLpEvent(event);
805}
806
807/*
808 * Handle a close charLpEvent. This should ONLY be an Interrupt because the
809 * virtual console should never actually issue a close event to the hypervisor
810 * because the virtual console never goes away. A close event coming from the
811 * hypervisor simply means that there are no client consoles connected to the
812 * virtual console.
813 *
814 * Regardless of the number of connections masqueraded on the other side of
815 * the hypervisor ONLY ONE close event should be called to accompany the ONE
816 * open event that is called. The close event should ONLY be called when NO
817 * MORE connections (masqueraded or not) exist on the other side of the
818 * hypervisor.
819 */
820static void vioHandleCloseEvent(struct HvLpEvent *event)
821{
822 unsigned long flags;
823 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
824 u8 port = cevent->virtual_device;
825
826 if (hvlpevent_is_int(event)) {
827 if (port >= VTTY_PORTS) {
828 printk(VIOCONS_KERN_WARN
829 "close message from invalid virtual device.\n");
830 return;
831 }
832
833 /* For closes, just mark the console partition invalid */
834 spin_lock_irqsave(&consolelock, flags);
835 /* Got the lock, don't cause console output */
836
837 if (port_info[port].lp == event->xSourceLp)
838 port_info[port].lp = HvLpIndexInvalid;
839
840 spin_unlock_irqrestore(&consolelock, flags);
841 printk(VIOCONS_KERN_INFO "close from %d\n", event->xSourceLp);
842 } else
843 printk(VIOCONS_KERN_WARN
844 "got unexpected close acknowlegement\n");
845}
846
847/*
848 * Handle a config charLpEvent. Could be either interrupt or ack
849 */
850static void vioHandleConfig(struct HvLpEvent *event)
851{
852 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
853
854 HvCall_writeLogBuffer(cevent->data, cevent->len);
855
856 if (cevent->data[0] == 0x01)
857 printk(VIOCONS_KERN_INFO "window resized to %d: %d: %d: %d\n",
858 cevent->data[1], cevent->data[2],
859 cevent->data[3], cevent->data[4]);
860 else
861 printk(VIOCONS_KERN_WARN "unknown config event\n");
862}
863
864/*
865 * Handle a data charLpEvent.
866 */
867static void vioHandleData(struct HvLpEvent *event)
868{
869 struct tty_struct *tty;
870 unsigned long flags;
871 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
872 struct port_info *pi;
873 int index;
874 int num_pushed;
875 u8 port = cevent->virtual_device;
876
877 if (port >= VTTY_PORTS) {
878 printk(VIOCONS_KERN_WARN "data on invalid virtual device %d\n",
879 port);
880 return;
881 }
882
883 /*
884 * Hold the spinlock so that we don't take an interrupt that
885 * changes tty between the time we fetch the port_info
886 * pointer and the time we paranoia check.
887 */
888 spin_lock_irqsave(&consolelock, flags);
889 pi = &port_info[port];
890
891 /*
892 * Change 05/01/2003 - Ryan Arnold: If a partition other than
893 * the current exclusive partition tries to send us data
894 * events then just drop them on the floor because we don't
895 * want his stinking data. He isn't authorized to receive
896 * data because he wasn't the first one to get the console,
897 * therefore he shouldn't be allowed to send data either.
898 * This will work without an iSeries fix.
899 */
900 if (pi->lp != event->xSourceLp) {
901 spin_unlock_irqrestore(&consolelock, flags);
902 return;
903 }
904
905 tty = pi->tty;
906 if (tty == NULL) {
907 spin_unlock_irqrestore(&consolelock, flags);
908 printk(VIOCONS_KERN_WARN "no tty for virtual device %d\n",
909 port);
910 return;
911 }
912
913 if (tty->magic != TTY_MAGIC) {
914 spin_unlock_irqrestore(&consolelock, flags);
915 printk(VIOCONS_KERN_WARN "tty bad magic\n");
916 return;
917 }
918
919 /*
920 * Just to be paranoid, make sure the tty points back to this port
921 */
922 pi = (struct port_info *)tty->driver_data;
923 if (!pi || viotty_paranoia_check(pi, tty->name, "vioHandleData")) {
924 spin_unlock_irqrestore(&consolelock, flags);
925 return;
926 }
927 spin_unlock_irqrestore(&consolelock, flags);
928
929 /*
930 * Change 07/21/2003 - Ryan Arnold: functionality added to
931 * support sysrq utilizing ^O as the sysrq key. The sysrq
932 * functionality will only work if built into the kernel and
933 * then only if sysrq is enabled through the proc filesystem.
934 */
935 num_pushed = 0;
936 for (index = 0; index < cevent->len; index++) {
937 /*
938 * Will be optimized away if !CONFIG_MAGIC_SYSRQ:
939 */
940 if (sysrq_on()) {
941 /* 0x0f is the ascii character for ^O */
942 if (cevent->data[index] == '\x0f') {
943 vio_sysrq_pressed = 1;
944 /*
945 * continue because we don't want to add
946 * the sysrq key into the data string.
947 */
948 continue;
949 } else if (vio_sysrq_pressed) {
950 handle_sysrq(cevent->data[index], tty);
951 vio_sysrq_pressed = 0;
952 /*
953 * continue because we don't want to add
954 * the sysrq sequence into the data string.
955 */
956 continue;
957 }
958 }
959 /*
960 * The sysrq sequence isn't included in this check if
961 * sysrq is enabled and compiled into the kernel because
962 * the sequence will never get inserted into the buffer.
963 * Don't attempt to copy more data into the buffer than we
964 * have room for because it would fail without indication.
965 */
966 if(tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL) == 0) {
967 printk(VIOCONS_KERN_WARN "input buffer overflow!\n");
968 break;
969 }
970 num_pushed++;
971 }
972
973 if (num_pushed)
974 tty_flip_buffer_push(tty);
975}
976
977/*
978 * Handle an ack charLpEvent.
979 */
980static void vioHandleAck(struct HvLpEvent *event)
981{
982 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
983 unsigned long flags;
984 u8 port = cevent->virtual_device;
985
986 if (port >= VTTY_PORTS) {
987 printk(VIOCONS_KERN_WARN "data on invalid virtual device\n");
988 return;
989 }
990
991 spin_lock_irqsave(&consolelock, flags);
992 port_info[port].ack = event->xCorrelationToken;
993 spin_unlock_irqrestore(&consolelock, flags);
994
995 if (port_info[port].used)
996 send_buffers(&port_info[port]);
997}
998
999/*
1000 * Handle charLpEvents and route to the appropriate routine
1001 */
1002static void vioHandleCharEvent(struct HvLpEvent *event)
1003{
1004 int charminor;
1005
1006 if (event == NULL)
1007 return;
1008
1009 charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
1010 switch (charminor) {
1011 case viocharopen:
1012 vioHandleOpenEvent(event);
1013 break;
1014 case viocharclose:
1015 vioHandleCloseEvent(event);
1016 break;
1017 case viochardata:
1018 vioHandleData(event);
1019 break;
1020 case viocharack:
1021 vioHandleAck(event);
1022 break;
1023 case viocharconfig:
1024 vioHandleConfig(event);
1025 break;
1026 default:
1027 if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {
1028 event->xRc = HvLpEvent_Rc_InvalidSubtype;
1029 HvCallEvent_ackLpEvent(event);
1030 }
1031 }
1032}
1033
1034/*
1035 * Send an open event
1036 */
1037static int send_open(HvLpIndex remoteLp, void *sem)
1038{
1039 return HvCallEvent_signalLpEventFast(remoteLp,
1040 HvLpEvent_Type_VirtualIo,
1041 viomajorsubtype_chario | viocharopen,
1042 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
1043 viopath_sourceinst(remoteLp),
1044 viopath_targetinst(remoteLp),
1045 (u64)(unsigned long)sem, VIOVERSION << 16,
1046 0, 0, 0, 0);
1047}
1048
1049static const struct tty_operations serial_ops = {
1050 .open = viotty_open,
1051 .close = viotty_close,
1052 .write = viotty_write,
1053 .put_char = viotty_put_char,
1054 .write_room = viotty_write_room,
1055 .chars_in_buffer = viotty_chars_in_buffer,
1056 .ioctl = viotty_ioctl,
1057};
1058
1059static int __init viocons_init2(void)
1060{
1061 atomic_t wait_flag;
1062 int rc;
1063
1064 if (!firmware_has_feature(FW_FEATURE_ISERIES))
1065 return -ENODEV;
1066
1067 /* +2 for fudge */
1068 rc = viopath_open(HvLpConfig_getPrimaryLpIndex(),
1069 viomajorsubtype_chario, VIOCHAR_WINDOW + 2);
1070 if (rc)
1071 printk(VIOCONS_KERN_WARN "error opening to primary %d\n", rc);
1072
1073 if (viopath_hostLp == HvLpIndexInvalid)
1074 vio_set_hostlp();
1075
1076 /*
1077 * And if the primary is not the same as the hosting LP, open to the
1078 * hosting lp
1079 */
1080 if ((viopath_hostLp != HvLpIndexInvalid) &&
1081 (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) {
1082 printk(VIOCONS_KERN_INFO "open path to hosting (%d)\n",
1083 viopath_hostLp);
1084 rc = viopath_open(viopath_hostLp, viomajorsubtype_chario,
1085 VIOCHAR_WINDOW + 2); /* +2 for fudge */
1086 if (rc)
1087 printk(VIOCONS_KERN_WARN
1088 "error opening to partition %d: %d\n",
1089 viopath_hostLp, rc);
1090 }
1091
1092 if (vio_setHandler(viomajorsubtype_chario, vioHandleCharEvent) < 0)
1093 printk(VIOCONS_KERN_WARN
1094 "error seting handler for console events!\n");
1095
1096 /*
1097 * First, try to open the console to the hosting lp.
1098 * Wait on a semaphore for the response.
1099 */
1100 atomic_set(&wait_flag, 0);
1101 if ((viopath_isactive(viopath_hostLp)) &&
1102 (send_open(viopath_hostLp, (void *)&wait_flag) == 0)) {
1103 printk(VIOCONS_KERN_INFO "hosting partition %d\n",
1104 viopath_hostLp);
1105 while (atomic_read(&wait_flag) == 0)
1106 mb();
1107 atomic_set(&wait_flag, 0);
1108 }
1109
1110 /*
1111 * If we don't have an active console, try the primary
1112 */
1113 if ((!viopath_isactive(port_info[0].lp)) &&
1114 (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) &&
1115 (send_open(HvLpConfig_getPrimaryLpIndex(), (void *)&wait_flag)
1116 == 0)) {
1117 printk(VIOCONS_KERN_INFO "opening console to primary partition\n");
1118 while (atomic_read(&wait_flag) == 0)
1119 mb();
1120 }
1121
1122 /* Initialize the tty_driver structure */
1123 viotty_driver = alloc_tty_driver(VTTY_PORTS);
1124 viotty_driver->owner = THIS_MODULE;
1125 viotty_driver->driver_name = "vioconsole";
1126 viotty_driver->name = "tty";
1127 viotty_driver->name_base = 1;
1128 viotty_driver->major = TTY_MAJOR;
1129 viotty_driver->minor_start = 1;
1130 viotty_driver->type = TTY_DRIVER_TYPE_CONSOLE;
1131 viotty_driver->subtype = 1;
1132 viotty_driver->init_termios = tty_std_termios;
1133 viotty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
1134 tty_set_operations(viotty_driver, &serial_ops);
1135
1136 if (tty_register_driver(viotty_driver)) {
1137 printk(VIOCONS_KERN_WARN "couldn't register console driver\n");
1138 put_tty_driver(viotty_driver);
1139 viotty_driver = NULL;
1140 }
1141
1142 unregister_console(&viocons_early);
1143 register_console(&viocons);
1144
1145 return 0;
1146}
1147
1148static int __init viocons_init(void)
1149{
1150 int i;
1151
1152 if (!firmware_has_feature(FW_FEATURE_ISERIES))
1153 return -ENODEV;
1154
1155 printk(VIOCONS_KERN_INFO "registering console\n");
1156 for (i = 0; i < VTTY_PORTS; i++) {
1157 port_info[i].lp = HvLpIndexInvalid;
1158 port_info[i].magic = VIOTTY_MAGIC;
1159 }
1160 HvCall_setLogBufferFormatAndCodepage(HvCall_LogBuffer_ASCII, 437);
1161 add_preferred_console("viocons", 0, NULL);
1162 register_console(&viocons_early);
1163 return 0;
1164}
1165
1166console_initcall(viocons_init);
1167module_init(viocons_init2);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c882fd05cf29..bf4ebfb86fa5 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -57,6 +57,16 @@ config SENSORS_ABITUGURU3
57 This driver can also be built as a module. If so, the module 57 This driver can also be built as a module. If so, the module
58 will be called abituguru3. 58 will be called abituguru3.
59 59
60config SENSORS_AD7414
61 tristate "Analog Devices AD7414"
62 depends on I2C && EXPERIMENTAL
63 help
64 If you say yes here you get support for the Analog Devices
65 AD7414 temperature monitoring chip.
66
67 This driver can also be built as a module. If so, the module
68 will be called ad7414.
69
60config SENSORS_AD7418 70config SENSORS_AD7418
61 tristate "Analog Devices AD7416, AD7417 and AD7418" 71 tristate "Analog Devices AD7416, AD7417 and AD7418"
62 depends on I2C && EXPERIMENTAL 72 depends on I2C && EXPERIMENTAL
@@ -124,7 +134,7 @@ config SENSORS_ADM1031
124 134
125config SENSORS_ADM9240 135config SENSORS_ADM9240
126 tristate "Analog Devices ADM9240 and compatibles" 136 tristate "Analog Devices ADM9240 and compatibles"
127 depends on I2C && EXPERIMENTAL 137 depends on I2C
128 select HWMON_VID 138 select HWMON_VID
129 help 139 help
130 If you say yes here you get support for Analog Devices ADM9240, 140 If you say yes here you get support for Analog Devices ADM9240,
@@ -575,8 +585,8 @@ config SENSORS_DME1737
575 select HWMON_VID 585 select HWMON_VID
576 help 586 help
577 If you say yes here you get support for the hardware monitoring 587 If you say yes here you get support for the hardware monitoring
578 and fan control features of the SMSC DME1737 (and compatibles 588 and fan control features of the SMSC DME1737, SCH311x, SCH5027, and
579 like the Asus A8000) and SCH311x Super-I/O chips. 589 Asus A8000 Super-I/O chips.
580 590
581 This driver can also be built as a module. If so, the module 591 This driver can also be built as a module. If so, the module
582 will be called dme1737. 592 will be called dme1737.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index d098677e08de..7943e5cefb06 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_SENSORS_W83791D) += w83791d.o
15 15
16obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o 16obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o
17obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o 17obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o
18obj-$(CONFIG_SENSORS_AD7414) += ad7414.o
18obj-$(CONFIG_SENSORS_AD7418) += ad7418.o 19obj-$(CONFIG_SENSORS_AD7418) += ad7418.o
19obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o 20obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
20obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o 21obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o
diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c
new file mode 100644
index 000000000000..ce8d94fbfd7e
--- /dev/null
+++ b/drivers/hwmon/ad7414.c
@@ -0,0 +1,268 @@
1/*
2 * An hwmon driver for the Analog Devices AD7414
3 *
4 * Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering
5 *
6 * Copyright (c) 2008 PIKA Technologies
7 * Sean MacLennan <smaclennan@pikatech.com>
8 *
9 * Copyright (c) 2008 Spansion Inc.
10 * Frank Edelhaeuser <frank.edelhaeuser at spansion.com>
11 * (converted to "new style" I2C driver model, removed checkpatch.pl warnings)
12 *
13 * Based on ad7418.c
14 * Copyright 2006 Tower Technologies, Alessandro Zummo <a.zummo at towertech.it>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 */
21
22#include <linux/module.h>
23#include <linux/jiffies.h>
24#include <linux/i2c.h>
25#include <linux/hwmon.h>
26#include <linux/hwmon-sysfs.h>
27#include <linux/err.h>
28#include <linux/mutex.h>
29#include <linux/sysfs.h>
30
31
32/* AD7414 registers */
33#define AD7414_REG_TEMP 0x00
34#define AD7414_REG_CONF 0x01
35#define AD7414_REG_T_HIGH 0x02
36#define AD7414_REG_T_LOW 0x03
37
38static u8 AD7414_REG_LIMIT[] = { AD7414_REG_T_HIGH, AD7414_REG_T_LOW };
39
40struct ad7414_data {
41 struct device *hwmon_dev;
42 struct mutex lock; /* atomic read data updates */
43 char valid; /* !=0 if following fields are valid */
44 unsigned long next_update; /* In jiffies */
45 s16 temp_input; /* Register values */
46 s8 temps[ARRAY_SIZE(AD7414_REG_LIMIT)];
47};
48
49/* REG: (0.25C/bit, two's complement) << 6 */
50static inline int ad7414_temp_from_reg(s16 reg)
51{
52 /* use integer division instead of equivalent right shift to
53 * guarantee arithmetic shift and preserve the sign
54 */
55 return ((int)reg / 64) * 250;
56}
57
58static inline int ad7414_read(struct i2c_client *client, u8 reg)
59{
60 if (reg == AD7414_REG_TEMP) {
61 int value = i2c_smbus_read_word_data(client, reg);
62 return (value < 0) ? value : swab16(value);
63 } else
64 return i2c_smbus_read_byte_data(client, reg);
65}
66
67static inline int ad7414_write(struct i2c_client *client, u8 reg, u8 value)
68{
69 return i2c_smbus_write_byte_data(client, reg, value);
70}
71
72struct ad7414_data *ad7414_update_device(struct device *dev)
73{
74 struct i2c_client *client = to_i2c_client(dev);
75 struct ad7414_data *data = i2c_get_clientdata(client);
76
77 mutex_lock(&data->lock);
78
79 if (time_after(jiffies, data->next_update) || !data->valid) {
80 int value, i;
81
82 dev_dbg(&client->dev, "starting ad7414 update\n");
83
84 value = ad7414_read(client, AD7414_REG_TEMP);
85 if (value < 0)
86 dev_dbg(&client->dev, "AD7414_REG_TEMP err %d\n",
87 value);
88 else
89 data->temp_input = value;
90
91 for (i = 0; i < ARRAY_SIZE(AD7414_REG_LIMIT); ++i) {
92 value = ad7414_read(client, AD7414_REG_LIMIT[i]);
93 if (value < 0)
94 dev_dbg(&client->dev, "AD7414 reg %d err %d\n",
95 AD7414_REG_LIMIT[i], value);
96 else
97 data->temps[i] = value;
98 }
99
100 data->next_update = jiffies + HZ + HZ / 2;
101 data->valid = 1;
102 }
103
104 mutex_unlock(&data->lock);
105
106 return data;
107}
108
109static ssize_t show_temp_input(struct device *dev,
110 struct device_attribute *attr, char *buf)
111{
112 struct ad7414_data *data = ad7414_update_device(dev);
113 return sprintf(buf, "%d\n", ad7414_temp_from_reg(data->temp_input));
114}
115static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0);
116
117static ssize_t show_max_min(struct device *dev, struct device_attribute *attr,
118 char *buf)
119{
120 int index = to_sensor_dev_attr(attr)->index;
121 struct ad7414_data *data = ad7414_update_device(dev);
122 return sprintf(buf, "%d\n", data->temps[index] * 1000);
123}
124
125static ssize_t set_max_min(struct device *dev,
126 struct device_attribute *attr,
127 const char *buf, size_t count)
128{
129 struct i2c_client *client = to_i2c_client(dev);
130 struct ad7414_data *data = i2c_get_clientdata(client);
131 int index = to_sensor_dev_attr(attr)->index;
132 u8 reg = AD7414_REG_LIMIT[index];
133 long temp = simple_strtol(buf, NULL, 10);
134
135 temp = SENSORS_LIMIT(temp, -40000, 85000);
136 temp = (temp + (temp < 0 ? -500 : 500)) / 1000;
137
138 mutex_lock(&data->lock);
139 data->temps[index] = temp;
140 ad7414_write(client, reg, temp);
141 mutex_unlock(&data->lock);
142 return count;
143}
144
145static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
146 show_max_min, set_max_min, 0);
147static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
148 show_max_min, set_max_min, 1);
149
150static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
151 char *buf)
152{
153 int bitnr = to_sensor_dev_attr(attr)->index;
154 struct ad7414_data *data = ad7414_update_device(dev);
155 int value = (data->temp_input >> bitnr) & 1;
156 return sprintf(buf, "%d\n", value);
157}
158
159static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 3);
160static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 4);
161
162static struct attribute *ad7414_attributes[] = {
163 &sensor_dev_attr_temp1_input.dev_attr.attr,
164 &sensor_dev_attr_temp1_max.dev_attr.attr,
165 &sensor_dev_attr_temp1_min.dev_attr.attr,
166 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
167 &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
168 NULL
169};
170
171static const struct attribute_group ad7414_group = {
172 .attrs = ad7414_attributes,
173};
174
175static int ad7414_probe(struct i2c_client *client,
176 const struct i2c_device_id *dev_id)
177{
178 struct ad7414_data *data;
179 int conf;
180 int err = 0;
181
182 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
183 I2C_FUNC_SMBUS_READ_WORD_DATA))
184 goto exit;
185
186 data = kzalloc(sizeof(struct ad7414_data), GFP_KERNEL);
187 if (!data) {
188 err = -ENOMEM;
189 goto exit;
190 }
191
192 i2c_set_clientdata(client, data);
193 mutex_init(&data->lock);
194
195 dev_info(&client->dev, "chip found\n");
196
197 /* Make sure the chip is powered up. */
198 conf = i2c_smbus_read_byte_data(client, AD7414_REG_CONF);
199 if (conf < 0)
200 dev_warn(&client->dev,
201 "ad7414_probe unable to read config register.\n");
202 else {
203 conf &= ~(1 << 7);
204 i2c_smbus_write_byte_data(client, AD7414_REG_CONF, conf);
205 }
206
207 /* Register sysfs hooks */
208 err = sysfs_create_group(&client->dev.kobj, &ad7414_group);
209 if (err)
210 goto exit_free;
211
212 data->hwmon_dev = hwmon_device_register(&client->dev);
213 if (IS_ERR(data->hwmon_dev)) {
214 err = PTR_ERR(data->hwmon_dev);
215 goto exit_remove;
216 }
217
218 return 0;
219
220exit_remove:
221 sysfs_remove_group(&client->dev.kobj, &ad7414_group);
222exit_free:
223 kfree(data);
224exit:
225 return err;
226}
227
228static int __devexit ad7414_remove(struct i2c_client *client)
229{
230 struct ad7414_data *data = i2c_get_clientdata(client);
231
232 hwmon_device_unregister(data->hwmon_dev);
233 sysfs_remove_group(&client->dev.kobj, &ad7414_group);
234 kfree(data);
235 return 0;
236}
237
238static const struct i2c_device_id ad7414_id[] = {
239 { "ad7414", 0 },
240 {}
241};
242
243static struct i2c_driver ad7414_driver = {
244 .driver = {
245 .name = "ad7414",
246 },
247 .probe = ad7414_probe,
248 .remove = __devexit_p(ad7414_remove),
249 .id_table = ad7414_id,
250};
251
252static int __init ad7414_init(void)
253{
254 return i2c_add_driver(&ad7414_driver);
255}
256module_init(ad7414_init);
257
258static void __exit ad7414_exit(void)
259{
260 i2c_del_driver(&ad7414_driver);
261}
262module_exit(ad7414_exit);
263
264MODULE_AUTHOR("Stefan Roese <sr at denx.de>, "
265 "Frank Edelhaeuser <frank.edelhaeuser at spansion.com>");
266
267MODULE_DESCRIPTION("AD7414 driver");
268MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index 5e2cf0aef480..cdb8311e4ef7 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -1,11 +1,11 @@
1/* 1/*
2 * dme1737.c - Driver for the SMSC DME1737, Asus A8000, and SMSC SCH311x 2 * dme1737.c - Driver for the SMSC DME1737, Asus A8000, SMSC SCH311x and
3 * Super-I/O chips integrated hardware monitoring features. 3 * SCH5027 Super-I/O chips integrated hardware monitoring features.
4 * Copyright (c) 2007 Juerg Haefliger <juergh@gmail.com> 4 * Copyright (c) 2007, 2008 Juerg Haefliger <juergh@gmail.com>
5 * 5 *
6 * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access 6 * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access
7 * the chip registers if a DME1737 (or A8000) is found and the ISA bus if a 7 * the chip registers if a DME1737, A8000, or SCH5027 is found and the ISA bus
8 * SCH311x chip is found. Both types of chips have very similar hardware 8 * if a SCH311x chip is found. Both types of chips have very similar hardware
9 * monitoring capabilities but differ in the way they can be accessed. 9 * monitoring capabilities but differ in the way they can be accessed.
10 * 10 *
11 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
@@ -57,7 +57,10 @@ MODULE_PARM_DESC(probe_all_addr, "Include probing of non-standard LPC "
57static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END}; 57static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END};
58 58
59/* Insmod parameters */ 59/* Insmod parameters */
60I2C_CLIENT_INSMOD_1(dme1737); 60I2C_CLIENT_INSMOD_2(dme1737, sch5027);
61
62/* ISA chip types */
63enum isa_chips { sch311x = sch5027 + 1 };
61 64
62/* --------------------------------------------------------------------- 65/* ---------------------------------------------------------------------
63 * Registers 66 * Registers
@@ -163,6 +166,7 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23};
163#define DME1737_VERSTEP 0x88 166#define DME1737_VERSTEP 0x88
164#define DME1737_VERSTEP_MASK 0xf8 167#define DME1737_VERSTEP_MASK 0xf8
165#define SCH311X_DEVICE 0x8c 168#define SCH311X_DEVICE 0x8c
169#define SCH5027_VERSTEP 0x69
166 170
167/* Length of ISA address segment */ 171/* Length of ISA address segment */
168#define DME1737_EXTENT 2 172#define DME1737_EXTENT 2
@@ -182,6 +186,7 @@ struct dme1737_data {
182 unsigned long last_update; /* in jiffies */ 186 unsigned long last_update; /* in jiffies */
183 unsigned long last_vbat; /* in jiffies */ 187 unsigned long last_vbat; /* in jiffies */
184 enum chips type; 188 enum chips type;
189 const int *in_nominal; /* pointer to IN_NOMINAL array */
185 190
186 u8 vid; 191 u8 vid;
187 u8 pwm_rr_en; 192 u8 pwm_rr_en;
@@ -220,23 +225,23 @@ static const int IN_NOMINAL_DME1737[] = {5000, 2250, 3300, 5000, 12000, 3300,
220 3300}; 225 3300};
221static const int IN_NOMINAL_SCH311x[] = {2500, 1500, 3300, 5000, 12000, 3300, 226static const int IN_NOMINAL_SCH311x[] = {2500, 1500, 3300, 5000, 12000, 3300,
222 3300}; 227 3300};
223#define IN_NOMINAL(ix, type) (((type) == dme1737) ? \ 228static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300,
224 IN_NOMINAL_DME1737[(ix)] : \ 229 3300};
225 IN_NOMINAL_SCH311x[(ix)]) 230#define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \
231 (type) == sch5027 ? IN_NOMINAL_SCH5027 : \
232 IN_NOMINAL_DME1737)
226 233
227/* Voltage input 234/* Voltage input
228 * Voltage inputs have 16 bits resolution, limit values have 8 bits 235 * Voltage inputs have 16 bits resolution, limit values have 8 bits
229 * resolution. */ 236 * resolution. */
230static inline int IN_FROM_REG(int reg, int ix, int res, int type) 237static inline int IN_FROM_REG(int reg, int nominal, int res)
231{ 238{
232 return (reg * IN_NOMINAL(ix, type) + (3 << (res - 3))) / 239 return (reg * nominal + (3 << (res - 3))) / (3 << (res - 2));
233 (3 << (res - 2));
234} 240}
235 241
236static inline int IN_TO_REG(int val, int ix, int type) 242static inline int IN_TO_REG(int val, int nominal)
237{ 243{
238 return SENSORS_LIMIT((val * 192 + IN_NOMINAL(ix, type) / 2) / 244 return SENSORS_LIMIT((val * 192 + nominal / 2) / nominal, 0, 255);
239 IN_NOMINAL(ix, type), 0, 255);
240} 245}
241 246
242/* Temperature input 247/* Temperature input
@@ -565,7 +570,10 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
565 570
566 /* Sample register contents every 1 sec */ 571 /* Sample register contents every 1 sec */
567 if (time_after(jiffies, data->last_update + HZ) || !data->valid) { 572 if (time_after(jiffies, data->last_update + HZ) || !data->valid) {
568 data->vid = dme1737_read(client, DME1737_REG_VID) & 0x3f; 573 if (data->type != sch5027) {
574 data->vid = dme1737_read(client, DME1737_REG_VID) &
575 0x3f;
576 }
569 577
570 /* In (voltage) registers */ 578 /* In (voltage) registers */
571 for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { 579 for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {
@@ -593,8 +601,10 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
593 DME1737_REG_TEMP_MIN(ix)); 601 DME1737_REG_TEMP_MIN(ix));
594 data->temp_max[ix] = dme1737_read(client, 602 data->temp_max[ix] = dme1737_read(client,
595 DME1737_REG_TEMP_MAX(ix)); 603 DME1737_REG_TEMP_MAX(ix));
596 data->temp_offset[ix] = dme1737_read(client, 604 if (data->type != sch5027) {
597 DME1737_REG_TEMP_OFFSET(ix)); 605 data->temp_offset[ix] = dme1737_read(client,
606 DME1737_REG_TEMP_OFFSET(ix));
607 }
598 } 608 }
599 609
600 /* In and temp LSB registers 610 /* In and temp LSB registers
@@ -669,9 +679,11 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
669 data->zone_abs[ix] = dme1737_read(client, 679 data->zone_abs[ix] = dme1737_read(client,
670 DME1737_REG_ZONE_ABS(ix)); 680 DME1737_REG_ZONE_ABS(ix));
671 } 681 }
672 for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) { 682 if (data->type != sch5027) {
673 data->zone_hyst[ix] = dme1737_read(client, 683 for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) {
684 data->zone_hyst[ix] = dme1737_read(client,
674 DME1737_REG_ZONE_HYST(ix)); 685 DME1737_REG_ZONE_HYST(ix));
686 }
675 } 687 }
676 688
677 /* Alarm registers */ 689 /* Alarm registers */
@@ -735,13 +747,13 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr,
735 747
736 switch (fn) { 748 switch (fn) {
737 case SYS_IN_INPUT: 749 case SYS_IN_INPUT:
738 res = IN_FROM_REG(data->in[ix], ix, 16, data->type); 750 res = IN_FROM_REG(data->in[ix], data->in_nominal[ix], 16);
739 break; 751 break;
740 case SYS_IN_MIN: 752 case SYS_IN_MIN:
741 res = IN_FROM_REG(data->in_min[ix], ix, 8, data->type); 753 res = IN_FROM_REG(data->in_min[ix], data->in_nominal[ix], 8);
742 break; 754 break;
743 case SYS_IN_MAX: 755 case SYS_IN_MAX:
744 res = IN_FROM_REG(data->in_max[ix], ix, 8, data->type); 756 res = IN_FROM_REG(data->in_max[ix], data->in_nominal[ix], 8);
745 break; 757 break;
746 case SYS_IN_ALARM: 758 case SYS_IN_ALARM:
747 res = (data->alarms >> DME1737_BIT_ALARM_IN[ix]) & 0x01; 759 res = (data->alarms >> DME1737_BIT_ALARM_IN[ix]) & 0x01;
@@ -768,12 +780,12 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr,
768 mutex_lock(&data->update_lock); 780 mutex_lock(&data->update_lock);
769 switch (fn) { 781 switch (fn) {
770 case SYS_IN_MIN: 782 case SYS_IN_MIN:
771 data->in_min[ix] = IN_TO_REG(val, ix, data->type); 783 data->in_min[ix] = IN_TO_REG(val, data->in_nominal[ix]);
772 dme1737_write(client, DME1737_REG_IN_MIN(ix), 784 dme1737_write(client, DME1737_REG_IN_MIN(ix),
773 data->in_min[ix]); 785 data->in_min[ix]);
774 break; 786 break;
775 case SYS_IN_MAX: 787 case SYS_IN_MAX:
776 data->in_max[ix] = IN_TO_REG(val, ix, data->type); 788 data->in_max[ix] = IN_TO_REG(val, data->in_nominal[ix]);
777 dme1737_write(client, DME1737_REG_IN_MAX(ix), 789 dme1737_write(client, DME1737_REG_IN_MAX(ix),
778 data->in_max[ix]); 790 data->in_max[ix]);
779 break; 791 break;
@@ -1166,7 +1178,7 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
1166 return sprintf(buf, "%d\n", res); 1178 return sprintf(buf, "%d\n", res);
1167} 1179}
1168 1180
1169static struct attribute *dme1737_attr_pwm[]; 1181static struct attribute *dme1737_pwm_chmod_attr[];
1170static void dme1737_chmod_file(struct device*, struct attribute*, mode_t); 1182static void dme1737_chmod_file(struct device*, struct attribute*, mode_t);
1171 1183
1172static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, 1184static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
@@ -1230,7 +1242,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
1230 switch (val) { 1242 switch (val) {
1231 case 0: 1243 case 0:
1232 /* Change permissions of pwm[ix] to read-only */ 1244 /* Change permissions of pwm[ix] to read-only */
1233 dme1737_chmod_file(dev, dme1737_attr_pwm[ix], 1245 dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix],
1234 S_IRUGO); 1246 S_IRUGO);
1235 /* Turn fan fully on */ 1247 /* Turn fan fully on */
1236 data->pwm_config[ix] = PWM_EN_TO_REG(0, 1248 data->pwm_config[ix] = PWM_EN_TO_REG(0,
@@ -1245,12 +1257,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
1245 dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), 1257 dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
1246 data->pwm_config[ix]); 1258 data->pwm_config[ix]);
1247 /* Change permissions of pwm[ix] to read-writeable */ 1259 /* Change permissions of pwm[ix] to read-writeable */
1248 dme1737_chmod_file(dev, dme1737_attr_pwm[ix], 1260 dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix],
1249 S_IRUGO | S_IWUSR); 1261 S_IRUGO | S_IWUSR);
1250 break; 1262 break;
1251 case 2: 1263 case 2:
1252 /* Change permissions of pwm[ix] to read-only */ 1264 /* Change permissions of pwm[ix] to read-only */
1253 dme1737_chmod_file(dev, dme1737_attr_pwm[ix], 1265 dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix],
1254 S_IRUGO); 1266 S_IRUGO);
1255 /* Turn on auto mode using the saved zone channel 1267 /* Turn on auto mode using the saved zone channel
1256 * assignment */ 1268 * assignment */
@@ -1570,88 +1582,98 @@ static struct attribute *dme1737_attr[] ={
1570 &sensor_dev_attr_temp1_max.dev_attr.attr, 1582 &sensor_dev_attr_temp1_max.dev_attr.attr,
1571 &sensor_dev_attr_temp1_alarm.dev_attr.attr, 1583 &sensor_dev_attr_temp1_alarm.dev_attr.attr,
1572 &sensor_dev_attr_temp1_fault.dev_attr.attr, 1584 &sensor_dev_attr_temp1_fault.dev_attr.attr,
1573 &sensor_dev_attr_temp1_offset.dev_attr.attr,
1574 &sensor_dev_attr_temp2_input.dev_attr.attr, 1585 &sensor_dev_attr_temp2_input.dev_attr.attr,
1575 &sensor_dev_attr_temp2_min.dev_attr.attr, 1586 &sensor_dev_attr_temp2_min.dev_attr.attr,
1576 &sensor_dev_attr_temp2_max.dev_attr.attr, 1587 &sensor_dev_attr_temp2_max.dev_attr.attr,
1577 &sensor_dev_attr_temp2_alarm.dev_attr.attr, 1588 &sensor_dev_attr_temp2_alarm.dev_attr.attr,
1578 &sensor_dev_attr_temp2_fault.dev_attr.attr, 1589 &sensor_dev_attr_temp2_fault.dev_attr.attr,
1579 &sensor_dev_attr_temp2_offset.dev_attr.attr,
1580 &sensor_dev_attr_temp3_input.dev_attr.attr, 1590 &sensor_dev_attr_temp3_input.dev_attr.attr,
1581 &sensor_dev_attr_temp3_min.dev_attr.attr, 1591 &sensor_dev_attr_temp3_min.dev_attr.attr,
1582 &sensor_dev_attr_temp3_max.dev_attr.attr, 1592 &sensor_dev_attr_temp3_max.dev_attr.attr,
1583 &sensor_dev_attr_temp3_alarm.dev_attr.attr, 1593 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
1584 &sensor_dev_attr_temp3_fault.dev_attr.attr, 1594 &sensor_dev_attr_temp3_fault.dev_attr.attr,
1585 &sensor_dev_attr_temp3_offset.dev_attr.attr,
1586 /* Zones */ 1595 /* Zones */
1587 &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr,
1588 &sensor_dev_attr_zone1_auto_point1_temp.dev_attr.attr, 1596 &sensor_dev_attr_zone1_auto_point1_temp.dev_attr.attr,
1589 &sensor_dev_attr_zone1_auto_point2_temp.dev_attr.attr, 1597 &sensor_dev_attr_zone1_auto_point2_temp.dev_attr.attr,
1590 &sensor_dev_attr_zone1_auto_point3_temp.dev_attr.attr, 1598 &sensor_dev_attr_zone1_auto_point3_temp.dev_attr.attr,
1591 &sensor_dev_attr_zone1_auto_channels_temp.dev_attr.attr, 1599 &sensor_dev_attr_zone1_auto_channels_temp.dev_attr.attr,
1592 &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr,
1593 &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr, 1600 &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr,
1594 &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, 1601 &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr,
1595 &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, 1602 &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr,
1596 &sensor_dev_attr_zone2_auto_channels_temp.dev_attr.attr, 1603 &sensor_dev_attr_zone2_auto_channels_temp.dev_attr.attr,
1597 &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr,
1598 &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, 1604 &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr,
1599 &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, 1605 &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr,
1600 &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, 1606 &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr,
1601 &sensor_dev_attr_zone3_auto_channels_temp.dev_attr.attr, 1607 &sensor_dev_attr_zone3_auto_channels_temp.dev_attr.attr,
1608 NULL
1609};
1610
1611static const struct attribute_group dme1737_group = {
1612 .attrs = dme1737_attr,
1613};
1614
1615/* The following struct holds misc attributes, which are not available in all
1616 * chips. Their creation depends on the chip type which is determined during
1617 * module load. */
1618static struct attribute *dme1737_misc_attr[] = {
1619 /* Temperatures */
1620 &sensor_dev_attr_temp1_offset.dev_attr.attr,
1621 &sensor_dev_attr_temp2_offset.dev_attr.attr,
1622 &sensor_dev_attr_temp3_offset.dev_attr.attr,
1623 /* Zones */
1624 &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr,
1625 &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr,
1626 &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr,
1602 /* Misc */ 1627 /* Misc */
1603 &dev_attr_vrm.attr, 1628 &dev_attr_vrm.attr,
1604 &dev_attr_cpu0_vid.attr, 1629 &dev_attr_cpu0_vid.attr,
1605 NULL 1630 NULL
1606}; 1631};
1607 1632
1608static const struct attribute_group dme1737_group = { 1633static const struct attribute_group dme1737_misc_group = {
1609 .attrs = dme1737_attr, 1634 .attrs = dme1737_misc_attr,
1610}; 1635};
1611 1636
1612/* The following structs hold the PWM attributes, some of which are optional. 1637/* The following structs hold the PWM attributes, some of which are optional.
1613 * Their creation depends on the chip configuration which is determined during 1638 * Their creation depends on the chip configuration which is determined during
1614 * module load. */ 1639 * module load. */
1615static struct attribute *dme1737_attr_pwm1[] = { 1640static struct attribute *dme1737_pwm1_attr[] = {
1616 &sensor_dev_attr_pwm1.dev_attr.attr, 1641 &sensor_dev_attr_pwm1.dev_attr.attr,
1617 &sensor_dev_attr_pwm1_freq.dev_attr.attr, 1642 &sensor_dev_attr_pwm1_freq.dev_attr.attr,
1618 &sensor_dev_attr_pwm1_enable.dev_attr.attr, 1643 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
1619 &sensor_dev_attr_pwm1_ramp_rate.dev_attr.attr, 1644 &sensor_dev_attr_pwm1_ramp_rate.dev_attr.attr,
1620 &sensor_dev_attr_pwm1_auto_channels_zone.dev_attr.attr, 1645 &sensor_dev_attr_pwm1_auto_channels_zone.dev_attr.attr,
1621 &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr,
1622 &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, 1646 &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
1623 &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, 1647 &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
1624 NULL 1648 NULL
1625}; 1649};
1626static struct attribute *dme1737_attr_pwm2[] = { 1650static struct attribute *dme1737_pwm2_attr[] = {
1627 &sensor_dev_attr_pwm2.dev_attr.attr, 1651 &sensor_dev_attr_pwm2.dev_attr.attr,
1628 &sensor_dev_attr_pwm2_freq.dev_attr.attr, 1652 &sensor_dev_attr_pwm2_freq.dev_attr.attr,
1629 &sensor_dev_attr_pwm2_enable.dev_attr.attr, 1653 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
1630 &sensor_dev_attr_pwm2_ramp_rate.dev_attr.attr, 1654 &sensor_dev_attr_pwm2_ramp_rate.dev_attr.attr,
1631 &sensor_dev_attr_pwm2_auto_channels_zone.dev_attr.attr, 1655 &sensor_dev_attr_pwm2_auto_channels_zone.dev_attr.attr,
1632 &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr,
1633 &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, 1656 &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
1634 &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, 1657 &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
1635 NULL 1658 NULL
1636}; 1659};
1637static struct attribute *dme1737_attr_pwm3[] = { 1660static struct attribute *dme1737_pwm3_attr[] = {
1638 &sensor_dev_attr_pwm3.dev_attr.attr, 1661 &sensor_dev_attr_pwm3.dev_attr.attr,
1639 &sensor_dev_attr_pwm3_freq.dev_attr.attr, 1662 &sensor_dev_attr_pwm3_freq.dev_attr.attr,
1640 &sensor_dev_attr_pwm3_enable.dev_attr.attr, 1663 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
1641 &sensor_dev_attr_pwm3_ramp_rate.dev_attr.attr, 1664 &sensor_dev_attr_pwm3_ramp_rate.dev_attr.attr,
1642 &sensor_dev_attr_pwm3_auto_channels_zone.dev_attr.attr, 1665 &sensor_dev_attr_pwm3_auto_channels_zone.dev_attr.attr,
1643 &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr,
1644 &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, 1666 &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
1645 &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, 1667 &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
1646 NULL 1668 NULL
1647}; 1669};
1648static struct attribute *dme1737_attr_pwm5[] = { 1670static struct attribute *dme1737_pwm5_attr[] = {
1649 &sensor_dev_attr_pwm5.dev_attr.attr, 1671 &sensor_dev_attr_pwm5.dev_attr.attr,
1650 &sensor_dev_attr_pwm5_freq.dev_attr.attr, 1672 &sensor_dev_attr_pwm5_freq.dev_attr.attr,
1651 &sensor_dev_attr_pwm5_enable.dev_attr.attr, 1673 &sensor_dev_attr_pwm5_enable.dev_attr.attr,
1652 NULL 1674 NULL
1653}; 1675};
1654static struct attribute *dme1737_attr_pwm6[] = { 1676static struct attribute *dme1737_pwm6_attr[] = {
1655 &sensor_dev_attr_pwm6.dev_attr.attr, 1677 &sensor_dev_attr_pwm6.dev_attr.attr,
1656 &sensor_dev_attr_pwm6_freq.dev_attr.attr, 1678 &sensor_dev_attr_pwm6_freq.dev_attr.attr,
1657 &sensor_dev_attr_pwm6_enable.dev_attr.attr, 1679 &sensor_dev_attr_pwm6_enable.dev_attr.attr,
@@ -1659,53 +1681,62 @@ static struct attribute *dme1737_attr_pwm6[] = {
1659}; 1681};
1660 1682
1661static const struct attribute_group dme1737_pwm_group[] = { 1683static const struct attribute_group dme1737_pwm_group[] = {
1662 { .attrs = dme1737_attr_pwm1 }, 1684 { .attrs = dme1737_pwm1_attr },
1663 { .attrs = dme1737_attr_pwm2 }, 1685 { .attrs = dme1737_pwm2_attr },
1664 { .attrs = dme1737_attr_pwm3 }, 1686 { .attrs = dme1737_pwm3_attr },
1665 { .attrs = NULL }, 1687 { .attrs = NULL },
1666 { .attrs = dme1737_attr_pwm5 }, 1688 { .attrs = dme1737_pwm5_attr },
1667 { .attrs = dme1737_attr_pwm6 }, 1689 { .attrs = dme1737_pwm6_attr },
1690};
1691
1692/* The following struct holds misc PWM attributes, which are not available in
1693 * all chips. Their creation depends on the chip type which is determined
1694 * during module load. */
1695static struct attribute *dme1737_pwm_misc_attr[] = {
1696 &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr,
1697 &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr,
1698 &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr,
1668}; 1699};
1669 1700
1670/* The following structs hold the fan attributes, some of which are optional. 1701/* The following structs hold the fan attributes, some of which are optional.
1671 * Their creation depends on the chip configuration which is determined during 1702 * Their creation depends on the chip configuration which is determined during
1672 * module load. */ 1703 * module load. */
1673static struct attribute *dme1737_attr_fan1[] = { 1704static struct attribute *dme1737_fan1_attr[] = {
1674 &sensor_dev_attr_fan1_input.dev_attr.attr, 1705 &sensor_dev_attr_fan1_input.dev_attr.attr,
1675 &sensor_dev_attr_fan1_min.dev_attr.attr, 1706 &sensor_dev_attr_fan1_min.dev_attr.attr,
1676 &sensor_dev_attr_fan1_alarm.dev_attr.attr, 1707 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
1677 &sensor_dev_attr_fan1_type.dev_attr.attr, 1708 &sensor_dev_attr_fan1_type.dev_attr.attr,
1678 NULL 1709 NULL
1679}; 1710};
1680static struct attribute *dme1737_attr_fan2[] = { 1711static struct attribute *dme1737_fan2_attr[] = {
1681 &sensor_dev_attr_fan2_input.dev_attr.attr, 1712 &sensor_dev_attr_fan2_input.dev_attr.attr,
1682 &sensor_dev_attr_fan2_min.dev_attr.attr, 1713 &sensor_dev_attr_fan2_min.dev_attr.attr,
1683 &sensor_dev_attr_fan2_alarm.dev_attr.attr, 1714 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
1684 &sensor_dev_attr_fan2_type.dev_attr.attr, 1715 &sensor_dev_attr_fan2_type.dev_attr.attr,
1685 NULL 1716 NULL
1686}; 1717};
1687static struct attribute *dme1737_attr_fan3[] = { 1718static struct attribute *dme1737_fan3_attr[] = {
1688 &sensor_dev_attr_fan3_input.dev_attr.attr, 1719 &sensor_dev_attr_fan3_input.dev_attr.attr,
1689 &sensor_dev_attr_fan3_min.dev_attr.attr, 1720 &sensor_dev_attr_fan3_min.dev_attr.attr,
1690 &sensor_dev_attr_fan3_alarm.dev_attr.attr, 1721 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
1691 &sensor_dev_attr_fan3_type.dev_attr.attr, 1722 &sensor_dev_attr_fan3_type.dev_attr.attr,
1692 NULL 1723 NULL
1693}; 1724};
1694static struct attribute *dme1737_attr_fan4[] = { 1725static struct attribute *dme1737_fan4_attr[] = {
1695 &sensor_dev_attr_fan4_input.dev_attr.attr, 1726 &sensor_dev_attr_fan4_input.dev_attr.attr,
1696 &sensor_dev_attr_fan4_min.dev_attr.attr, 1727 &sensor_dev_attr_fan4_min.dev_attr.attr,
1697 &sensor_dev_attr_fan4_alarm.dev_attr.attr, 1728 &sensor_dev_attr_fan4_alarm.dev_attr.attr,
1698 &sensor_dev_attr_fan4_type.dev_attr.attr, 1729 &sensor_dev_attr_fan4_type.dev_attr.attr,
1699 NULL 1730 NULL
1700}; 1731};
1701static struct attribute *dme1737_attr_fan5[] = { 1732static struct attribute *dme1737_fan5_attr[] = {
1702 &sensor_dev_attr_fan5_input.dev_attr.attr, 1733 &sensor_dev_attr_fan5_input.dev_attr.attr,
1703 &sensor_dev_attr_fan5_min.dev_attr.attr, 1734 &sensor_dev_attr_fan5_min.dev_attr.attr,
1704 &sensor_dev_attr_fan5_alarm.dev_attr.attr, 1735 &sensor_dev_attr_fan5_alarm.dev_attr.attr,
1705 &sensor_dev_attr_fan5_max.dev_attr.attr, 1736 &sensor_dev_attr_fan5_max.dev_attr.attr,
1706 NULL 1737 NULL
1707}; 1738};
1708static struct attribute *dme1737_attr_fan6[] = { 1739static struct attribute *dme1737_fan6_attr[] = {
1709 &sensor_dev_attr_fan6_input.dev_attr.attr, 1740 &sensor_dev_attr_fan6_input.dev_attr.attr,
1710 &sensor_dev_attr_fan6_min.dev_attr.attr, 1741 &sensor_dev_attr_fan6_min.dev_attr.attr,
1711 &sensor_dev_attr_fan6_alarm.dev_attr.attr, 1742 &sensor_dev_attr_fan6_alarm.dev_attr.attr,
@@ -1714,94 +1745,83 @@ static struct attribute *dme1737_attr_fan6[] = {
1714}; 1745};
1715 1746
1716static const struct attribute_group dme1737_fan_group[] = { 1747static const struct attribute_group dme1737_fan_group[] = {
1717 { .attrs = dme1737_attr_fan1 }, 1748 { .attrs = dme1737_fan1_attr },
1718 { .attrs = dme1737_attr_fan2 }, 1749 { .attrs = dme1737_fan2_attr },
1719 { .attrs = dme1737_attr_fan3 }, 1750 { .attrs = dme1737_fan3_attr },
1720 { .attrs = dme1737_attr_fan4 }, 1751 { .attrs = dme1737_fan4_attr },
1721 { .attrs = dme1737_attr_fan5 }, 1752 { .attrs = dme1737_fan5_attr },
1722 { .attrs = dme1737_attr_fan6 }, 1753 { .attrs = dme1737_fan6_attr },
1723}; 1754};
1724 1755
1725/* The permissions of all of the following attributes are changed to read- 1756/* The permissions of the following zone attributes are changed to read-
1726 * writeable if the chip is *not* locked. Otherwise they stay read-only. */ 1757 * writeable if the chip is *not* locked. Otherwise they stay read-only. */
1727static struct attribute *dme1737_attr_lock[] = { 1758static struct attribute *dme1737_zone_chmod_attr[] = {
1728 /* Temperatures */
1729 &sensor_dev_attr_temp1_offset.dev_attr.attr,
1730 &sensor_dev_attr_temp2_offset.dev_attr.attr,
1731 &sensor_dev_attr_temp3_offset.dev_attr.attr,
1732 /* Zones */
1733 &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr,
1734 &sensor_dev_attr_zone1_auto_point1_temp.dev_attr.attr, 1759 &sensor_dev_attr_zone1_auto_point1_temp.dev_attr.attr,
1735 &sensor_dev_attr_zone1_auto_point2_temp.dev_attr.attr, 1760 &sensor_dev_attr_zone1_auto_point2_temp.dev_attr.attr,
1736 &sensor_dev_attr_zone1_auto_point3_temp.dev_attr.attr, 1761 &sensor_dev_attr_zone1_auto_point3_temp.dev_attr.attr,
1737 &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr,
1738 &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr, 1762 &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr,
1739 &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, 1763 &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr,
1740 &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, 1764 &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr,
1741 &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr,
1742 &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, 1765 &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr,
1743 &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, 1766 &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr,
1744 &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, 1767 &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr,
1745 NULL 1768 NULL
1746}; 1769};
1747 1770
1748static const struct attribute_group dme1737_lock_group = { 1771static const struct attribute_group dme1737_zone_chmod_group = {
1749 .attrs = dme1737_attr_lock, 1772 .attrs = dme1737_zone_chmod_attr,
1750}; 1773};
1751 1774
1752/* The permissions of the following PWM attributes are changed to read- 1775/* The permissions of the following PWM attributes are changed to read-
1753 * writeable if the chip is *not* locked and the respective PWM is available. 1776 * writeable if the chip is *not* locked and the respective PWM is available.
1754 * Otherwise they stay read-only. */ 1777 * Otherwise they stay read-only. */
1755static struct attribute *dme1737_attr_pwm1_lock[] = { 1778static struct attribute *dme1737_pwm1_chmod_attr[] = {
1756 &sensor_dev_attr_pwm1_freq.dev_attr.attr, 1779 &sensor_dev_attr_pwm1_freq.dev_attr.attr,
1757 &sensor_dev_attr_pwm1_enable.dev_attr.attr, 1780 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
1758 &sensor_dev_attr_pwm1_ramp_rate.dev_attr.attr, 1781 &sensor_dev_attr_pwm1_ramp_rate.dev_attr.attr,
1759 &sensor_dev_attr_pwm1_auto_channels_zone.dev_attr.attr, 1782 &sensor_dev_attr_pwm1_auto_channels_zone.dev_attr.attr,
1760 &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr,
1761 &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, 1783 &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
1762 NULL 1784 NULL
1763}; 1785};
1764static struct attribute *dme1737_attr_pwm2_lock[] = { 1786static struct attribute *dme1737_pwm2_chmod_attr[] = {
1765 &sensor_dev_attr_pwm2_freq.dev_attr.attr, 1787 &sensor_dev_attr_pwm2_freq.dev_attr.attr,
1766 &sensor_dev_attr_pwm2_enable.dev_attr.attr, 1788 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
1767 &sensor_dev_attr_pwm2_ramp_rate.dev_attr.attr, 1789 &sensor_dev_attr_pwm2_ramp_rate.dev_attr.attr,
1768 &sensor_dev_attr_pwm2_auto_channels_zone.dev_attr.attr, 1790 &sensor_dev_attr_pwm2_auto_channels_zone.dev_attr.attr,
1769 &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr,
1770 &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, 1791 &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
1771 NULL 1792 NULL
1772}; 1793};
1773static struct attribute *dme1737_attr_pwm3_lock[] = { 1794static struct attribute *dme1737_pwm3_chmod_attr[] = {
1774 &sensor_dev_attr_pwm3_freq.dev_attr.attr, 1795 &sensor_dev_attr_pwm3_freq.dev_attr.attr,
1775 &sensor_dev_attr_pwm3_enable.dev_attr.attr, 1796 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
1776 &sensor_dev_attr_pwm3_ramp_rate.dev_attr.attr, 1797 &sensor_dev_attr_pwm3_ramp_rate.dev_attr.attr,
1777 &sensor_dev_attr_pwm3_auto_channels_zone.dev_attr.attr, 1798 &sensor_dev_attr_pwm3_auto_channels_zone.dev_attr.attr,
1778 &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr,
1779 &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, 1799 &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
1780 NULL 1800 NULL
1781}; 1801};
1782static struct attribute *dme1737_attr_pwm5_lock[] = { 1802static struct attribute *dme1737_pwm5_chmod_attr[] = {
1783 &sensor_dev_attr_pwm5.dev_attr.attr, 1803 &sensor_dev_attr_pwm5.dev_attr.attr,
1784 &sensor_dev_attr_pwm5_freq.dev_attr.attr, 1804 &sensor_dev_attr_pwm5_freq.dev_attr.attr,
1785 NULL 1805 NULL
1786}; 1806};
1787static struct attribute *dme1737_attr_pwm6_lock[] = { 1807static struct attribute *dme1737_pwm6_chmod_attr[] = {
1788 &sensor_dev_attr_pwm6.dev_attr.attr, 1808 &sensor_dev_attr_pwm6.dev_attr.attr,
1789 &sensor_dev_attr_pwm6_freq.dev_attr.attr, 1809 &sensor_dev_attr_pwm6_freq.dev_attr.attr,
1790 NULL 1810 NULL
1791}; 1811};
1792 1812
1793static const struct attribute_group dme1737_pwm_lock_group[] = { 1813static const struct attribute_group dme1737_pwm_chmod_group[] = {
1794 { .attrs = dme1737_attr_pwm1_lock }, 1814 { .attrs = dme1737_pwm1_chmod_attr },
1795 { .attrs = dme1737_attr_pwm2_lock }, 1815 { .attrs = dme1737_pwm2_chmod_attr },
1796 { .attrs = dme1737_attr_pwm3_lock }, 1816 { .attrs = dme1737_pwm3_chmod_attr },
1797 { .attrs = NULL }, 1817 { .attrs = NULL },
1798 { .attrs = dme1737_attr_pwm5_lock }, 1818 { .attrs = dme1737_pwm5_chmod_attr },
1799 { .attrs = dme1737_attr_pwm6_lock }, 1819 { .attrs = dme1737_pwm6_chmod_attr },
1800}; 1820};
1801 1821
1802/* Pwm[1-3] are read-writeable if the associated pwm is in manual mode and the 1822/* Pwm[1-3] are read-writeable if the associated pwm is in manual mode and the
1803 * chip is not locked. Otherwise they are read-only. */ 1823 * chip is not locked. Otherwise they are read-only. */
1804static struct attribute *dme1737_attr_pwm[] = { 1824static struct attribute *dme1737_pwm_chmod_attr[] = {
1805 &sensor_dev_attr_pwm1.dev_attr.attr, 1825 &sensor_dev_attr_pwm1.dev_attr.attr,
1806 &sensor_dev_attr_pwm2.dev_attr.attr, 1826 &sensor_dev_attr_pwm2.dev_attr.attr,
1807 &sensor_dev_attr_pwm3.dev_attr.attr, 1827 &sensor_dev_attr_pwm3.dev_attr.attr,
@@ -1875,9 +1895,17 @@ static void dme1737_remove_files(struct device *dev)
1875 if (data->has_pwm & (1 << ix)) { 1895 if (data->has_pwm & (1 << ix)) {
1876 sysfs_remove_group(&dev->kobj, 1896 sysfs_remove_group(&dev->kobj,
1877 &dme1737_pwm_group[ix]); 1897 &dme1737_pwm_group[ix]);
1898 if (data->type != sch5027 && ix < 3) {
1899 sysfs_remove_file(&dev->kobj,
1900 dme1737_pwm_misc_attr[ix]);
1901 }
1878 } 1902 }
1879 } 1903 }
1880 1904
1905 if (data->type != sch5027) {
1906 sysfs_remove_group(&dev->kobj, &dme1737_misc_group);
1907 }
1908
1881 sysfs_remove_group(&dev->kobj, &dme1737_group); 1909 sysfs_remove_group(&dev->kobj, &dme1737_group);
1882 1910
1883 if (!data->client.driver) { 1911 if (!data->client.driver) {
@@ -1901,6 +1929,13 @@ static int dme1737_create_files(struct device *dev)
1901 goto exit_remove; 1929 goto exit_remove;
1902 } 1930 }
1903 1931
1932 /* Create misc sysfs attributes */
1933 if ((data->type != sch5027) &&
1934 (err = sysfs_create_group(&dev->kobj,
1935 &dme1737_misc_group))) {
1936 goto exit_remove;
1937 }
1938
1904 /* Create fan sysfs attributes */ 1939 /* Create fan sysfs attributes */
1905 for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { 1940 for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {
1906 if (data->has_fan & (1 << ix)) { 1941 if (data->has_fan & (1 << ix)) {
@@ -1918,6 +1953,11 @@ static int dme1737_create_files(struct device *dev)
1918 &dme1737_pwm_group[ix]))) { 1953 &dme1737_pwm_group[ix]))) {
1919 goto exit_remove; 1954 goto exit_remove;
1920 } 1955 }
1956 if (data->type != sch5027 && ix < 3 &&
1957 (err = sysfs_create_file(&dev->kobj,
1958 dme1737_pwm_misc_attr[ix]))) {
1959 goto exit_remove;
1960 }
1921 } 1961 }
1922 } 1962 }
1923 1963
@@ -1927,16 +1967,27 @@ static int dme1737_create_files(struct device *dev)
1927 dev_info(dev, "Device is locked. Some attributes " 1967 dev_info(dev, "Device is locked. Some attributes "
1928 "will be read-only.\n"); 1968 "will be read-only.\n");
1929 } else { 1969 } else {
1930 /* Change permissions of standard attributes */ 1970 /* Change permissions of zone sysfs attributes */
1931 dme1737_chmod_group(dev, &dme1737_lock_group, 1971 dme1737_chmod_group(dev, &dme1737_zone_chmod_group,
1932 S_IRUGO | S_IWUSR); 1972 S_IRUGO | S_IWUSR);
1933 1973
1934 /* Change permissions of PWM attributes */ 1974 /* Change permissions of misc sysfs attributes */
1935 for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_lock_group); ix++) { 1975 if (data->type != sch5027) {
1976 dme1737_chmod_group(dev, &dme1737_misc_group,
1977 S_IRUGO | S_IWUSR);
1978 }
1979
1980 /* Change permissions of PWM sysfs attributes */
1981 for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_chmod_group); ix++) {
1936 if (data->has_pwm & (1 << ix)) { 1982 if (data->has_pwm & (1 << ix)) {
1937 dme1737_chmod_group(dev, 1983 dme1737_chmod_group(dev,
1938 &dme1737_pwm_lock_group[ix], 1984 &dme1737_pwm_chmod_group[ix],
1985 S_IRUGO | S_IWUSR);
1986 if (data->type != sch5027 && ix < 3) {
1987 dme1737_chmod_file(dev,
1988 dme1737_pwm_misc_attr[ix],
1939 S_IRUGO | S_IWUSR); 1989 S_IRUGO | S_IWUSR);
1990 }
1940 } 1991 }
1941 } 1992 }
1942 1993
@@ -1945,7 +1996,7 @@ static int dme1737_create_files(struct device *dev)
1945 if ((data->has_pwm & (1 << ix)) && 1996 if ((data->has_pwm & (1 << ix)) &&
1946 (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) { 1997 (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) {
1947 dme1737_chmod_file(dev, 1998 dme1737_chmod_file(dev,
1948 dme1737_attr_pwm[ix], 1999 dme1737_pwm_chmod_attr[ix],
1949 S_IRUGO | S_IWUSR); 2000 S_IRUGO | S_IWUSR);
1950 } 2001 }
1951 } 2002 }
@@ -1966,6 +2017,9 @@ static int dme1737_init_device(struct device *dev)
1966 int ix; 2017 int ix;
1967 u8 reg; 2018 u8 reg;
1968 2019
2020 /* Point to the right nominal voltages array */
2021 data->in_nominal = IN_NOMINAL(data->type);
2022
1969 data->config = dme1737_read(client, DME1737_REG_CONFIG); 2023 data->config = dme1737_read(client, DME1737_REG_CONFIG);
1970 /* Inform if part is not monitoring/started */ 2024 /* Inform if part is not monitoring/started */
1971 if (!(data->config & 0x01)) { 2025 if (!(data->config & 0x01)) {
@@ -2076,7 +2130,9 @@ static int dme1737_init_device(struct device *dev)
2076 data->pwm_acz[2] = 4; /* pwm3 -> zone3 */ 2130 data->pwm_acz[2] = 4; /* pwm3 -> zone3 */
2077 2131
2078 /* Set VRM */ 2132 /* Set VRM */
2079 data->vrm = vid_which_vrm(); 2133 if (data->type != sch5027) {
2134 data->vrm = vid_which_vrm();
2135 }
2080 2136
2081 return 0; 2137 return 0;
2082} 2138}
@@ -2095,9 +2151,10 @@ static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data)
2095 dme1737_sio_enter(sio_cip); 2151 dme1737_sio_enter(sio_cip);
2096 2152
2097 /* Check device ID 2153 /* Check device ID
2098 * The DME1737 can return either 0x78 or 0x77 as its device ID. */ 2154 * The DME1737 can return either 0x78 or 0x77 as its device ID.
2155 * The SCH5027 returns 0x89 as its device ID. */
2099 reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); 2156 reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20);
2100 if (!(reg == 0x77 || reg == 0x78)) { 2157 if (!(reg == 0x77 || reg == 0x78 || reg == 0x89)) {
2101 err = -ENODEV; 2158 err = -ENODEV;
2102 goto exit; 2159 goto exit;
2103 } 2160 }
@@ -2166,15 +2223,24 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,
2166 company = dme1737_read(client, DME1737_REG_COMPANY); 2223 company = dme1737_read(client, DME1737_REG_COMPANY);
2167 verstep = dme1737_read(client, DME1737_REG_VERSTEP); 2224 verstep = dme1737_read(client, DME1737_REG_VERSTEP);
2168 2225
2169 if (!((company == DME1737_COMPANY_SMSC) && 2226 if (company == DME1737_COMPANY_SMSC &&
2170 ((verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP))) { 2227 (verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) {
2228 kind = dme1737;
2229 } else if (company == DME1737_COMPANY_SMSC &&
2230 verstep == SCH5027_VERSTEP) {
2231 kind = sch5027;
2232 } else {
2171 err = -ENODEV; 2233 err = -ENODEV;
2172 goto exit_kfree; 2234 goto exit_kfree;
2173 } 2235 }
2174 } 2236 }
2175 2237
2176 kind = dme1737; 2238 if (kind == sch5027) {
2177 name = "dme1737"; 2239 name = "sch5027";
2240 } else {
2241 kind = dme1737;
2242 name = "dme1737";
2243 }
2178 data->type = kind; 2244 data->type = kind;
2179 2245
2180 /* Fill in the remaining client fields and put it into the global 2246 /* Fill in the remaining client fields and put it into the global
@@ -2187,8 +2253,9 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,
2187 goto exit_kfree; 2253 goto exit_kfree;
2188 } 2254 }
2189 2255
2190 dev_info(dev, "Found a DME1737 chip at 0x%02x (rev 0x%02x).\n", 2256 dev_info(dev, "Found a %s chip at 0x%02x (rev 0x%02x).\n",
2191 client->addr, verstep); 2257 kind == sch5027 ? "SCH5027" : "DME1737", client->addr,
2258 verstep);
2192 2259
2193 /* Initialize the DME1737 chip */ 2260 /* Initialize the DME1737 chip */
2194 if ((err = dme1737_init_device(dev))) { 2261 if ((err = dme1737_init_device(dev))) {
@@ -2360,15 +2427,18 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
2360 client->addr = res->start; 2427 client->addr = res->start;
2361 platform_set_drvdata(pdev, data); 2428 platform_set_drvdata(pdev, data);
2362 2429
2363 company = dme1737_read(client, DME1737_REG_COMPANY); 2430 /* Skip chip detection if module is loaded with force_id parameter */
2364 device = dme1737_read(client, DME1737_REG_DEVICE); 2431 if (!force_id) {
2432 company = dme1737_read(client, DME1737_REG_COMPANY);
2433 device = dme1737_read(client, DME1737_REG_DEVICE);
2365 2434
2366 if (!((company == DME1737_COMPANY_SMSC) && 2435 if (!((company == DME1737_COMPANY_SMSC) &&
2367 (device == SCH311X_DEVICE))) { 2436 (device == SCH311X_DEVICE))) {
2368 err = -ENODEV; 2437 err = -ENODEV;
2369 goto exit_kfree; 2438 goto exit_kfree;
2439 }
2370 } 2440 }
2371 data->type = -1; 2441 data->type = sch311x;
2372 2442
2373 /* Fill in the remaining client fields and initialize the mutex */ 2443 /* Fill in the remaining client fields and initialize the mutex */
2374 strlcpy(client->name, "sch311x", I2C_NAME_SIZE); 2444 strlcpy(client->name, "sch311x", I2C_NAME_SIZE);
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index cbeb4984b5c7..67067e9a323e 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -87,8 +87,6 @@ static inline void superio_enter(int base);
87static inline void superio_select(int base, int ld); 87static inline void superio_select(int base, int ld);
88static inline void superio_exit(int base); 88static inline void superio_exit(int base);
89 89
90static inline u16 fan_from_reg ( u16 reg );
91
92struct f71882fg_data { 90struct f71882fg_data {
93 unsigned short addr; 91 unsigned short addr;
94 struct device *hwmon_dev; 92 struct device *hwmon_dev;
@@ -116,10 +114,6 @@ struct f71882fg_data {
116 u8 temp_diode_open; 114 u8 temp_diode_open;
117}; 115};
118 116
119static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg);
120static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg);
121static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val);
122
123/* Sysfs in*/ 117/* Sysfs in*/
124static ssize_t show_in(struct device *dev, struct device_attribute *devattr, 118static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
125 char *buf); 119 char *buf);
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 3330667280b9..7b0a32c4dcfb 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -1,76 +1,74 @@
1/* 1/*
2 hwmon-vid.c - VID/VRM/VRD voltage conversions 2 * hwmon-vid.c - VID/VRM/VRD voltage conversions
3 3 *
4 Copyright (c) 2004 Rudolf Marek <r.marek@assembler.cz> 4 * Copyright (c) 2004 Rudolf Marek <r.marek@assembler.cz>
5 5 *
6 Partly imported from i2c-vid.h of the lm_sensors project 6 * Partly imported from i2c-vid.h of the lm_sensors project
7 Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> 7 * Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
8 With assistance from Trent Piepho <xyzzy@speakeasy.org> 8 * With assistance from Trent Piepho <xyzzy@speakeasy.org>
9 9 *
10 This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or 12 * the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version. 13 * (at your option) any later version.
14 14 *
15 This program is distributed in the hope that it will be useful, 15 * This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details. 18 * GNU General Public License for more details.
19 19 *
20 You should have received a copy of the GNU General Public License 20 * You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software 21 * along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*/ 23 */
24 24
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/hwmon-vid.h> 27#include <linux/hwmon-vid.h>
28 28
29/* 29/*
30 Common code for decoding VID pins. 30 * Common code for decoding VID pins.
31 31 *
32 References: 32 * References:
33 33 *
34 For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines", 34 * For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines",
35 available at http://developer.intel.com/. 35 * available at http://developer.intel.com/.
36 36 *
37 For VRD 10.0 and up, "VRD x.y Design Guide", 37 * For VRD 10.0 and up, "VRD x.y Design Guide",
38 available at http://developer.intel.com/. 38 * available at http://developer.intel.com/.
39 39 *
40 AMD Opteron processors don't follow the Intel specifications. 40 * AMD NPT 0Fh (Athlon64 & Opteron), AMD Publication 32559,
41 I'm going to "make up" 2.4 as the spec number for the Opterons. 41 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
42 No good reason just a mnemonic for the 24x Opteron processor 42 * Table 71. VID Code Voltages
43 series. 43 * AMD Opteron processors don't follow the Intel specifications.
44 44 * I'm going to "make up" 2.4 as the spec number for the Opterons.
45 Opteron VID encoding is: 45 * No good reason just a mnemonic for the 24x Opteron processor
46 00000 = 1.550 V 46 * series.
47 00001 = 1.525 V 47 *
48 . . . . 48 * The 17 specification is in fact Intel Mobile Voltage Positioning -
49 11110 = 0.800 V 49 * (IMVP-II). You can find more information in the datasheet of Max1718
50 11111 = 0.000 V (off) 50 * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452
51 51 *
52 The 17 specification is in fact Intel Mobile Voltage Positioning - 52 * The 13 specification corresponds to the Intel Pentium M series. There
53 (IMVP-II). You can find more information in the datasheet of Max1718 53 * doesn't seem to be any named specification for these. The conversion
54 http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452 54 * tables are detailed directly in the various Pentium M datasheets:
55 55 * http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm
56 The 13 specification corresponds to the Intel Pentium M series. There 56 *
57 doesn't seem to be any named specification for these. The conversion 57 * The 14 specification corresponds to Intel Core series. There
58 tables are detailed directly in the various Pentium M datasheets: 58 * doesn't seem to be any named specification for these. The conversion
59 http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm 59 * tables are detailed directly in the various Pentium Core datasheets:
60 60 * http://www.intel.com/design/mobile/datashts/309221.htm
61 The 14 specification corresponds to Intel Core series. There 61 *
62 doesn't seem to be any named specification for these. The conversion 62 * The 110 (VRM 11) specification corresponds to Intel Conroe based series.
63 tables are detailed directly in the various Pentium Core datasheets: 63 * http://www.intel.com/design/processor/applnots/313214.htm
64 http://www.intel.com/design/mobile/datashts/309221.htm 64 */
65 65
66 The 110 (VRM 11) specification corresponds to Intel Conroe based series. 66/*
67 http://www.intel.com/design/processor/applnots/313214.htm 67 * vrm is the VRM/VRD document version multiplied by 10.
68*/ 68 * val is the 4-bit or more VID code.
69 69 * Returned value is in mV to avoid floating point in the kernel.
70/* vrm is the VRM/VRD document version multiplied by 10. 70 * Some VID have some bits in uV scale, this is rounded to mV.
71 val is the 4-bit or more VID code. 71 */
72 Returned value is in mV to avoid floating point in the kernel.
73 Some VID have some bits in uV scale, this is rounded to mV */
74int vid_from_reg(int val, u8 vrm) 72int vid_from_reg(int val, u8 vrm)
75{ 73{
76 int vid; 74 int vid;
@@ -96,9 +94,11 @@ int vid_from_reg(int val, u8 vrm)
96 if (val < 0x02 || val > 0xb2) 94 if (val < 0x02 || val > 0xb2)
97 return 0; 95 return 0;
98 return((1600000 - (val - 2) * 6250 + 500) / 1000); 96 return((1600000 - (val - 2) * 6250 + 500) / 1000);
99 case 24: /* Opteron processor */ 97
100 val &= 0x1f; 98 case 24: /* AMD NPT 0Fh (Athlon64 & Opteron) */
101 return(val == 0x1f ? 0 : 1550 - val * 25); 99 val &= 0x3f;
100 return (val < 32) ? 1550 - 25 * val
101 : 775 - (25 * (val - 31)) / 2;
102 102
103 case 91: /* VRM 9.1 */ 103 case 91: /* VRM 9.1 */
104 case 90: /* VRM 9.0 */ 104 case 90: /* VRM 9.0 */
@@ -141,9 +141,9 @@ int vid_from_reg(int val, u8 vrm)
141 141
142 142
143/* 143/*
144 After this point is the code to automatically determine which 144 * After this point is the code to automatically determine which
145 VRM/VRD specification should be used depending on the CPU. 145 * VRM/VRD specification should be used depending on the CPU.
146*/ 146 */
147 147
148struct vrm_model { 148struct vrm_model {
149 u8 vendor; 149 u8 vendor;
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index e12c132ff83a..30cdb0956779 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -151,9 +151,9 @@ static int fix_pwm_polarity;
151/* The IT8718F has the VID value in a different register, in Super-I/O 151/* The IT8718F has the VID value in a different register, in Super-I/O
152 configuration space. */ 152 configuration space. */
153#define IT87_REG_VID 0x0a 153#define IT87_REG_VID 0x0a
154/* Warning: register 0x0b is used for something completely different in 154/* The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b
155 new chips/revisions. I suspect only 16-bit tachometer mode will work 155 for fan divisors. Later IT8712F revisions must use 16-bit tachometer
156 for these. */ 156 mode. */
157#define IT87_REG_FAN_DIV 0x0b 157#define IT87_REG_FAN_DIV 0x0b
158#define IT87_REG_FAN_16BIT 0x0c 158#define IT87_REG_FAN_16BIT 0x0c
159 159
@@ -234,6 +234,7 @@ static const unsigned int pwm_freq[8] = {
234struct it87_sio_data { 234struct it87_sio_data {
235 enum chips type; 235 enum chips type;
236 /* Values read from Super-I/O config space */ 236 /* Values read from Super-I/O config space */
237 u8 revision;
237 u8 vid_value; 238 u8 vid_value;
238}; 239};
239 240
@@ -242,6 +243,7 @@ struct it87_sio_data {
242struct it87_data { 243struct it87_data {
243 struct device *hwmon_dev; 244 struct device *hwmon_dev;
244 enum chips type; 245 enum chips type;
246 u8 revision;
245 247
246 unsigned short addr; 248 unsigned short addr;
247 const char *name; 249 const char *name;
@@ -268,6 +270,16 @@ struct it87_data {
268 u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ 270 u8 manual_pwm_ctl[3]; /* manual PWM value set by user */
269}; 271};
270 272
273static inline int has_16bit_fans(const struct it87_data *data)
274{
275 /* IT8705F Datasheet 0.4.1, 3h == Version G.
276 IT8712F Datasheet 0.9.1, section 8.3.5 indicates 7h == Version I.
277 These are the first revisions with 16bit tachometer support. */
278 return (data->type == it87 && data->revision >= 0x03)
279 || (data->type == it8712 && data->revision >= 0x07)
280 || data->type == it8716
281 || data->type == it8718;
282}
271 283
272static int it87_probe(struct platform_device *pdev); 284static int it87_probe(struct platform_device *pdev);
273static int __devexit it87_remove(struct platform_device *pdev); 285static int __devexit it87_remove(struct platform_device *pdev);
@@ -991,8 +1003,9 @@ static int __init it87_find(unsigned short *address,
991 } 1003 }
992 1004
993 err = 0; 1005 err = 0;
1006 sio_data->revision = superio_inb(DEVREV) & 0x0f;
994 pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", 1007 pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n",
995 chip_type, *address, superio_inb(DEVREV) & 0x0f); 1008 chip_type, *address, sio_data->revision);
996 1009
997 /* Read GPIO config and VID value from LDN 7 (GPIO) */ 1010 /* Read GPIO config and VID value from LDN 7 (GPIO) */
998 if (chip_type != IT8705F_DEVID) { 1011 if (chip_type != IT8705F_DEVID) {
@@ -1045,6 +1058,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
1045 1058
1046 data->addr = res->start; 1059 data->addr = res->start;
1047 data->type = sio_data->type; 1060 data->type = sio_data->type;
1061 data->revision = sio_data->revision;
1048 data->name = names[sio_data->type]; 1062 data->name = names[sio_data->type];
1049 1063
1050 /* Now, we do the remaining detection. */ 1064 /* Now, we do the remaining detection. */
@@ -1069,7 +1083,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
1069 goto ERROR2; 1083 goto ERROR2;
1070 1084
1071 /* Do not create fan files for disabled fans */ 1085 /* Do not create fan files for disabled fans */
1072 if (data->type == it8716 || data->type == it8718) { 1086 if (has_16bit_fans(data)) {
1073 /* 16-bit tachometers */ 1087 /* 16-bit tachometers */
1074 if (data->has_fan & (1 << 0)) { 1088 if (data->has_fan & (1 << 0)) {
1075 if ((err = device_create_file(dev, 1089 if ((err = device_create_file(dev,
@@ -1350,7 +1364,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
1350 data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; 1364 data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
1351 1365
1352 /* Set tachometers to 16-bit mode if needed */ 1366 /* Set tachometers to 16-bit mode if needed */
1353 if (data->type == it8716 || data->type == it8718) { 1367 if (has_16bit_fans(data)) {
1354 tmp = it87_read_value(data, IT87_REG_FAN_16BIT); 1368 tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
1355 if (~tmp & 0x07 & data->has_fan) { 1369 if (~tmp & 0x07 & data->has_fan) {
1356 dev_dbg(&pdev->dev, 1370 dev_dbg(&pdev->dev,
@@ -1358,10 +1372,13 @@ static void __devinit it87_init_device(struct platform_device *pdev)
1358 it87_write_value(data, IT87_REG_FAN_16BIT, 1372 it87_write_value(data, IT87_REG_FAN_16BIT,
1359 tmp | 0x07); 1373 tmp | 0x07);
1360 } 1374 }
1361 if (tmp & (1 << 4)) 1375 /* IT8705F only supports three fans. */
1362 data->has_fan |= (1 << 3); /* fan4 enabled */ 1376 if (data->type != it87) {
1363 if (tmp & (1 << 5)) 1377 if (tmp & (1 << 4))
1364 data->has_fan |= (1 << 4); /* fan5 enabled */ 1378 data->has_fan |= (1 << 3); /* fan4 enabled */
1379 if (tmp & (1 << 5))
1380 data->has_fan |= (1 << 4); /* fan5 enabled */
1381 }
1365 } 1382 }
1366 1383
1367 /* Set current fan mode registers and the default settings for the 1384 /* Set current fan mode registers and the default settings for the
@@ -1426,7 +1443,7 @@ static struct it87_data *it87_update_device(struct device *dev)
1426 data->fan[i] = it87_read_value(data, 1443 data->fan[i] = it87_read_value(data,
1427 IT87_REG_FAN[i]); 1444 IT87_REG_FAN[i]);
1428 /* Add high byte if in 16-bit mode */ 1445 /* Add high byte if in 16-bit mode */
1429 if (data->type == it8716 || data->type == it8718) { 1446 if (has_16bit_fans(data)) {
1430 data->fan[i] |= it87_read_value(data, 1447 data->fan[i] |= it87_read_value(data,
1431 IT87_REG_FANX[i]) << 8; 1448 IT87_REG_FANX[i]) << 8;
1432 data->fan_min[i] |= it87_read_value(data, 1449 data->fan_min[i] |= it87_read_value(data,
@@ -1443,8 +1460,7 @@ static struct it87_data *it87_update_device(struct device *dev)
1443 } 1460 }
1444 1461
1445 /* Newer chips don't have clock dividers */ 1462 /* Newer chips don't have clock dividers */
1446 if ((data->has_fan & 0x07) && data->type != it8716 1463 if ((data->has_fan & 0x07) && !has_16bit_fans(data)) {
1447 && data->type != it8718) {
1448 i = it87_read_value(data, IT87_REG_FAN_DIV); 1464 i = it87_read_value(data, IT87_REG_FAN_DIV);
1449 data->fan_div[0] = i & 0x07; 1465 data->fan_div[0] = i & 0x07;
1450 data->fan_div[1] = (i >> 3) & 0x07; 1466 data->fan_div[1] = (i >> 3) & 0x07;
@@ -1460,7 +1476,8 @@ static struct it87_data *it87_update_device(struct device *dev)
1460 data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); 1476 data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
1461 1477
1462 data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); 1478 data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
1463 /* The 8705 does not have VID capability */ 1479 /* The 8705 does not have VID capability.
1480 The 8718 does not use IT87_REG_VID for the same purpose. */
1464 if (data->type == it8712 || data->type == it8716) { 1481 if (data->type == it8712 || data->type == it8716) {
1465 data->vid = it87_read_value(data, IT87_REG_VID); 1482 data->vid = it87_read_value(data, IT87_REG_VID);
1466 /* The older IT8712F revisions had only 5 VID pins, 1483 /* The older IT8712F revisions had only 5 VID pins,
diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c
index 3b01001108c1..7d97431e132f 100644
--- a/drivers/hwmon/thmc50.c
+++ b/drivers/hwmon/thmc50.c
@@ -55,8 +55,11 @@ I2C_CLIENT_MODULE_PARM(adm1022_temp3, "List of adapter,address pairs "
55static const u8 THMC50_REG_TEMP[] = { 0x27, 0x26, 0x20 }; 55static const u8 THMC50_REG_TEMP[] = { 0x27, 0x26, 0x20 };
56static const u8 THMC50_REG_TEMP_MIN[] = { 0x3A, 0x38, 0x2C }; 56static const u8 THMC50_REG_TEMP_MIN[] = { 0x3A, 0x38, 0x2C };
57static const u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B }; 57static const u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B };
58static const u8 THMC50_REG_TEMP_CRITICAL[] = { 0x13, 0x14, 0x14 };
59static const u8 THMC50_REG_TEMP_DEFAULT[] = { 0x17, 0x18, 0x18 };
58 60
59#define THMC50_REG_CONF_nFANOFF 0x20 61#define THMC50_REG_CONF_nFANOFF 0x20
62#define THMC50_REG_CONF_PROGRAMMED 0x08
60 63
61/* Each client has this additional data */ 64/* Each client has this additional data */
62struct thmc50_data { 65struct thmc50_data {
@@ -72,6 +75,7 @@ struct thmc50_data {
72 s8 temp_input[3]; 75 s8 temp_input[3];
73 s8 temp_max[3]; 76 s8 temp_max[3];
74 s8 temp_min[3]; 77 s8 temp_min[3];
78 s8 temp_critical[3];
75 u8 analog_out; 79 u8 analog_out;
76 u8 alarms; 80 u8 alarms;
77}; 81};
@@ -199,6 +203,15 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
199 return count; 203 return count;
200} 204}
201 205
206static ssize_t show_temp_critical(struct device *dev,
207 struct device_attribute *attr,
208 char *buf)
209{
210 int nr = to_sensor_dev_attr(attr)->index;
211 struct thmc50_data *data = thmc50_update_device(dev);
212 return sprintf(buf, "%d\n", data->temp_critical[nr] * 1000);
213}
214
202static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, 215static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
203 char *buf) 216 char *buf)
204{ 217{
@@ -214,7 +227,9 @@ static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, \
214static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ 227static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
215 show_temp_min, set_temp_min, offset - 1); \ 228 show_temp_min, set_temp_min, offset - 1); \
216static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ 229static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
217 show_temp_max, set_temp_max, offset - 1); 230 show_temp_max, set_temp_max, offset - 1); \
231static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO, \
232 show_temp_critical, NULL, offset - 1);
218 233
219temp_reg(1); 234temp_reg(1);
220temp_reg(2); 235temp_reg(2);
@@ -234,10 +249,12 @@ static struct attribute *thmc50_attributes[] = {
234 &sensor_dev_attr_temp1_max.dev_attr.attr, 249 &sensor_dev_attr_temp1_max.dev_attr.attr,
235 &sensor_dev_attr_temp1_min.dev_attr.attr, 250 &sensor_dev_attr_temp1_min.dev_attr.attr,
236 &sensor_dev_attr_temp1_input.dev_attr.attr, 251 &sensor_dev_attr_temp1_input.dev_attr.attr,
252 &sensor_dev_attr_temp1_crit.dev_attr.attr,
237 &sensor_dev_attr_temp1_alarm.dev_attr.attr, 253 &sensor_dev_attr_temp1_alarm.dev_attr.attr,
238 &sensor_dev_attr_temp2_max.dev_attr.attr, 254 &sensor_dev_attr_temp2_max.dev_attr.attr,
239 &sensor_dev_attr_temp2_min.dev_attr.attr, 255 &sensor_dev_attr_temp2_min.dev_attr.attr,
240 &sensor_dev_attr_temp2_input.dev_attr.attr, 256 &sensor_dev_attr_temp2_input.dev_attr.attr,
257 &sensor_dev_attr_temp2_crit.dev_attr.attr,
241 &sensor_dev_attr_temp2_alarm.dev_attr.attr, 258 &sensor_dev_attr_temp2_alarm.dev_attr.attr,
242 &sensor_dev_attr_temp2_fault.dev_attr.attr, 259 &sensor_dev_attr_temp2_fault.dev_attr.attr,
243 &sensor_dev_attr_pwm1.dev_attr.attr, 260 &sensor_dev_attr_pwm1.dev_attr.attr,
@@ -254,6 +271,7 @@ static struct attribute *temp3_attributes[] = {
254 &sensor_dev_attr_temp3_max.dev_attr.attr, 271 &sensor_dev_attr_temp3_max.dev_attr.attr,
255 &sensor_dev_attr_temp3_min.dev_attr.attr, 272 &sensor_dev_attr_temp3_min.dev_attr.attr,
256 &sensor_dev_attr_temp3_input.dev_attr.attr, 273 &sensor_dev_attr_temp3_input.dev_attr.attr,
274 &sensor_dev_attr_temp3_crit.dev_attr.attr,
257 &sensor_dev_attr_temp3_alarm.dev_attr.attr, 275 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
258 &sensor_dev_attr_temp3_fault.dev_attr.attr, 276 &sensor_dev_attr_temp3_fault.dev_attr.attr,
259 NULL 277 NULL
@@ -429,6 +447,10 @@ static struct thmc50_data *thmc50_update_device(struct device *dev)
429 447
430 int temps = data->has_temp3 ? 3 : 2; 448 int temps = data->has_temp3 ? 3 : 2;
431 int i; 449 int i;
450 int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
451
452 prog &= THMC50_REG_CONF_PROGRAMMED;
453
432 for (i = 0; i < temps; i++) { 454 for (i = 0; i < temps; i++) {
433 data->temp_input[i] = i2c_smbus_read_byte_data(client, 455 data->temp_input[i] = i2c_smbus_read_byte_data(client,
434 THMC50_REG_TEMP[i]); 456 THMC50_REG_TEMP[i]);
@@ -436,6 +458,10 @@ static struct thmc50_data *thmc50_update_device(struct device *dev)
436 THMC50_REG_TEMP_MAX[i]); 458 THMC50_REG_TEMP_MAX[i]);
437 data->temp_min[i] = i2c_smbus_read_byte_data(client, 459 data->temp_min[i] = i2c_smbus_read_byte_data(client,
438 THMC50_REG_TEMP_MIN[i]); 460 THMC50_REG_TEMP_MIN[i]);
461 data->temp_critical[i] =
462 i2c_smbus_read_byte_data(client,
463 prog ? THMC50_REG_TEMP_CRITICAL[i]
464 : THMC50_REG_TEMP_DEFAULT[i]);
439 } 465 }
440 data->analog_out = 466 data->analog_out =
441 i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT); 467 i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT);
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 9564fb069957..b30e5796cb26 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -67,10 +67,6 @@ module_param(force_i2c, byte, 0);
67MODULE_PARM_DESC(force_i2c, 67MODULE_PARM_DESC(force_i2c,
68 "Initialize the i2c address of the sensors"); 68 "Initialize the i2c address of the sensors");
69 69
70static int reset;
71module_param(reset, bool, 0);
72MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
73
74static int init = 1; 70static int init = 1;
75module_param(init, bool, 0); 71module_param(init, bool, 0);
76MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); 72MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
@@ -209,6 +205,13 @@ static const u16 w83627hf_reg_temp_over[] = { 0x39, 0x155, 0x255 };
209#define W83627HF_REG_PWM1 0x5A 205#define W83627HF_REG_PWM1 0x5A
210#define W83627HF_REG_PWM2 0x5B 206#define W83627HF_REG_PWM2 0x5B
211 207
208static const u8 W83627THF_REG_PWM_ENABLE[] = {
209 0x04, /* FAN 1 mode */
210 0x04, /* FAN 2 mode */
211 0x12, /* FAN AUX mode */
212};
213static const u8 W83627THF_PWM_ENABLE_SHIFT[] = { 2, 4, 1 };
214
212#define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */ 215#define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */
213#define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */ 216#define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */
214#define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */ 217#define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */
@@ -366,6 +369,9 @@ struct w83627hf_data {
366 u32 alarms; /* Register encoding, combined */ 369 u32 alarms; /* Register encoding, combined */
367 u32 beep_mask; /* Register encoding, combined */ 370 u32 beep_mask; /* Register encoding, combined */
368 u8 pwm[3]; /* Register value */ 371 u8 pwm[3]; /* Register value */
372 u8 pwm_enable[3]; /* 1 = manual
373 2 = thermal cruise (also called SmartFan I)
374 3 = fan speed cruise */
369 u8 pwm_freq[3]; /* Register value */ 375 u8 pwm_freq[3]; /* Register value */
370 u16 sens[3]; /* 1 = pentium diode; 2 = 3904 diode; 376 u16 sens[3]; /* 1 = pentium diode; 2 = 3904 diode;
371 4 = thermistor */ 377 4 = thermistor */
@@ -957,6 +963,42 @@ static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1);
957static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2); 963static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2);
958 964
959static ssize_t 965static ssize_t
966show_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf)
967{
968 int nr = to_sensor_dev_attr(devattr)->index;
969 struct w83627hf_data *data = w83627hf_update_device(dev);
970 return sprintf(buf, "%d\n", data->pwm_enable[nr]);
971}
972
973static ssize_t
974store_pwm_enable(struct device *dev, struct device_attribute *devattr,
975 const char *buf, size_t count)
976{
977 int nr = to_sensor_dev_attr(devattr)->index;
978 struct w83627hf_data *data = dev_get_drvdata(dev);
979 unsigned long val = simple_strtoul(buf, NULL, 10);
980 u8 reg;
981
982 if (!val || (val > 3)) /* modes 1, 2 and 3 are supported */
983 return -EINVAL;
984 mutex_lock(&data->update_lock);
985 data->pwm_enable[nr] = val;
986 reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]);
987 reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]);
988 reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr];
989 w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg);
990 mutex_unlock(&data->update_lock);
991 return count;
992}
993
994static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
995 store_pwm_enable, 0);
996static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
997 store_pwm_enable, 1);
998static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
999 store_pwm_enable, 2);
1000
1001static ssize_t
960show_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf) 1002show_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf)
961{ 1003{
962 int nr = to_sensor_dev_attr(devattr)->index; 1004 int nr = to_sensor_dev_attr(devattr)->index;
@@ -1223,6 +1265,11 @@ static struct attribute *w83627hf_attributes_opt[] = {
1223 &sensor_dev_attr_pwm1_freq.dev_attr.attr, 1265 &sensor_dev_attr_pwm1_freq.dev_attr.attr,
1224 &sensor_dev_attr_pwm2_freq.dev_attr.attr, 1266 &sensor_dev_attr_pwm2_freq.dev_attr.attr,
1225 &sensor_dev_attr_pwm3_freq.dev_attr.attr, 1267 &sensor_dev_attr_pwm3_freq.dev_attr.attr,
1268
1269 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
1270 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
1271 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
1272
1226 NULL 1273 NULL
1227}; 1274};
1228 1275
@@ -1366,6 +1413,19 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
1366 &sensor_dev_attr_pwm3_freq.dev_attr))) 1413 &sensor_dev_attr_pwm3_freq.dev_attr)))
1367 goto ERROR4; 1414 goto ERROR4;
1368 1415
1416 if (data->type != w83627hf)
1417 if ((err = device_create_file(dev,
1418 &sensor_dev_attr_pwm1_enable.dev_attr))
1419 || (err = device_create_file(dev,
1420 &sensor_dev_attr_pwm2_enable.dev_attr)))
1421 goto ERROR4;
1422
1423 if (data->type == w83627thf || data->type == w83637hf
1424 || data->type == w83687thf)
1425 if ((err = device_create_file(dev,
1426 &sensor_dev_attr_pwm3_enable.dev_attr)))
1427 goto ERROR4;
1428
1369 data->hwmon_dev = hwmon_device_register(dev); 1429 data->hwmon_dev = hwmon_device_register(dev);
1370 if (IS_ERR(data->hwmon_dev)) { 1430 if (IS_ERR(data->hwmon_dev)) {
1371 err = PTR_ERR(data->hwmon_dev); 1431 err = PTR_ERR(data->hwmon_dev);
@@ -1536,29 +1596,6 @@ static void __devinit w83627hf_init_device(struct platform_device *pdev)
1536 enum chips type = data->type; 1596 enum chips type = data->type;
1537 u8 tmp; 1597 u8 tmp;
1538 1598
1539 if (reset) {
1540 /* Resetting the chip has been the default for a long time,
1541 but repeatedly caused problems (fans going to full
1542 speed...) so it is now optional. It might even go away if
1543 nobody reports it as being useful, as I see very little
1544 reason why this would be needed at all. */
1545 dev_info(&pdev->dev, "If reset=1 solved a problem you were "
1546 "having, please report!\n");
1547
1548 /* save this register */
1549 i = w83627hf_read_value(data, W83781D_REG_BEEP_CONFIG);
1550 /* Reset all except Watchdog values and last conversion values
1551 This sets fan-divs to 2, among others */
1552 w83627hf_write_value(data, W83781D_REG_CONFIG, 0x80);
1553 /* Restore the register and disable power-on abnormal beep.
1554 This saves FAN 1/2/3 input/output values set by BIOS. */
1555 w83627hf_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
1556 /* Disable master beep-enable (reset turns it on).
1557 Individual beeps should be reset to off but for some reason
1558 disabling this bit helps some people not get beeped */
1559 w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, 0);
1560 }
1561
1562 /* Minimize conflicts with other winbond i2c-only clients... */ 1599 /* Minimize conflicts with other winbond i2c-only clients... */
1563 /* disable i2c subclients... how to disable main i2c client?? */ 1600 /* disable i2c subclients... how to disable main i2c client?? */
1564 /* force i2c address to relatively uncommon address */ 1601 /* force i2c address to relatively uncommon address */
@@ -1655,6 +1692,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
1655{ 1692{
1656 struct w83627hf_data *data = dev_get_drvdata(dev); 1693 struct w83627hf_data *data = dev_get_drvdata(dev);
1657 int i, num_temps = (data->type == w83697hf) ? 2 : 3; 1694 int i, num_temps = (data->type == w83697hf) ? 2 : 3;
1695 int num_pwms = (data->type == w83697hf) ? 2 : 3;
1658 1696
1659 mutex_lock(&data->update_lock); 1697 mutex_lock(&data->update_lock);
1660 1698
@@ -1707,6 +1745,15 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
1707 break; 1745 break;
1708 } 1746 }
1709 } 1747 }
1748 if (data->type != w83627hf) {
1749 for (i = 0; i < num_pwms; i++) {
1750 u8 tmp = w83627hf_read_value(data,
1751 W83627THF_REG_PWM_ENABLE[i]);
1752 data->pwm_enable[i] =
1753 ((tmp >> W83627THF_PWM_ENABLE_SHIFT[i])
1754 & 0x03) + 1;
1755 }
1756 }
1710 for (i = 0; i < num_temps; i++) { 1757 for (i = 0; i < num_temps; i++) {
1711 data->temp[i] = w83627hf_read_value( 1758 data->temp[i] = w83627hf_read_value(
1712 data, w83627hf_reg_temp[i]); 1759 data, w83627hf_reg_temp[i]);
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index e4e91c9d480a..daa7d121483b 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -233,11 +233,9 @@ static u8 fan_to_reg(long rpm, int div)
233static u8 div_to_reg(int nr, long val) 233static u8 div_to_reg(int nr, long val)
234{ 234{
235 int i; 235 int i;
236 int max;
237 236
238 /* first three fan's divisor max out at 8, rest max out at 128 */ 237 /* fan divisors max out at 128 */
239 max = (nr < 3) ? 8 : 128; 238 val = SENSORS_LIMIT(val, 1, 128) >> 1;
240 val = SENSORS_LIMIT(val, 1, max) >> 1;
241 for (i = 0; i < 7; i++) { 239 for (i = 0; i < 7; i++) {
242 if (val == 0) 240 if (val == 0)
243 break; 241 break;
@@ -530,6 +528,7 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
530 unsigned long min; 528 unsigned long min;
531 u8 tmp_fan_div; 529 u8 tmp_fan_div;
532 u8 fan_div_reg; 530 u8 fan_div_reg;
531 u8 vbat_reg;
533 int indx = 0; 532 int indx = 0;
534 u8 keep_mask = 0; 533 u8 keep_mask = 0;
535 u8 new_shift = 0; 534 u8 new_shift = 0;
@@ -581,6 +580,16 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
581 w83791d_write(client, W83791D_REG_FAN_DIV[indx], 580 w83791d_write(client, W83791D_REG_FAN_DIV[indx],
582 fan_div_reg | tmp_fan_div); 581 fan_div_reg | tmp_fan_div);
583 582
583 /* Bit 2 of fans 0-2 is stored in the vbat register (bits 5-7) */
584 if (nr < 3) {
585 keep_mask = ~(1 << (nr + 5));
586 vbat_reg = w83791d_read(client, W83791D_REG_VBAT)
587 & keep_mask;
588 tmp_fan_div = (data->fan_div[nr] << (3 + nr)) & ~keep_mask;
589 w83791d_write(client, W83791D_REG_VBAT,
590 vbat_reg | tmp_fan_div);
591 }
592
584 /* Restore fan_min */ 593 /* Restore fan_min */
585 data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr])); 594 data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr]));
586 w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]); 595 w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);
@@ -1182,6 +1191,7 @@ static struct w83791d_data *w83791d_update_device(struct device *dev)
1182 struct w83791d_data *data = i2c_get_clientdata(client); 1191 struct w83791d_data *data = i2c_get_clientdata(client);
1183 int i, j; 1192 int i, j;
1184 u8 reg_array_tmp[3]; 1193 u8 reg_array_tmp[3];
1194 u8 vbat_reg;
1185 1195
1186 mutex_lock(&data->update_lock); 1196 mutex_lock(&data->update_lock);
1187 1197
@@ -1219,6 +1229,12 @@ static struct w83791d_data *w83791d_update_device(struct device *dev)
1219 data->fan_div[3] = reg_array_tmp[2] & 0x07; 1229 data->fan_div[3] = reg_array_tmp[2] & 0x07;
1220 data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07; 1230 data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07;
1221 1231
1232 /* The fan divisor for fans 0-2 get bit 2 from
1233 bits 5-7 respectively of vbat register */
1234 vbat_reg = w83791d_read(client, W83791D_REG_VBAT);
1235 for (i = 0; i < 3; i++)
1236 data->fan_div[i] |= (vbat_reg >> (3 + i)) & 0x04;
1237
1222 /* Update the first temperature sensor */ 1238 /* Update the first temperature sensor */
1223 for (i = 0; i < 3; i++) { 1239 for (i = 0; i < 3; i++) {
1224 data->temp1[i] = w83791d_read(client, 1240 data->temp1[i] = w83791d_read(client,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 578afce6884c..aaa0b6f0b521 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -565,7 +565,8 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
565 565
566static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg) 566static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
567{ 567{
568 struct dvb_usb_device *d = ptr; 568 struct dvb_usb_adapter *adap = ptr;
569 struct dvb_usb_device *d = adap->dev;
569 570
570 switch (command) { 571 switch (command) {
571 case XC2028_TUNER_RESET: 572 case XC2028_TUNER_RESET:
@@ -593,9 +594,9 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
593 .callback = dvico_bluebird_xc2028_callback, 594 .callback = dvico_bluebird_xc2028_callback,
594 }; 595 };
595 static struct xc2028_ctrl ctl = { 596 static struct xc2028_ctrl ctl = {
596 .fname = "xc3028-dvico-au-01.fw", 597 .fname = "xc3028-v27.fw",
597 .max_len = 64, 598 .max_len = 64,
598 .scode_table = XC3028_FE_ZARLINK456, 599 .demod = XC3028_FE_ZARLINK456,
599 }; 600 };
600 601
601 fe = dvb_attach(xc2028_attach, adap->fe, &cfg); 602 fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 574dffe91b68..7dbb4a223c99 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -135,9 +135,8 @@ config DVB_CX22702
135 135
136config DVB_DRX397XD 136config DVB_DRX397XD
137 tristate "Micronas DRX3975D/DRX3977D based" 137 tristate "Micronas DRX3975D/DRX3977D based"
138 depends on DVB_CORE && I2C && HOTPLUG 138 depends on DVB_CORE && I2C
139 default m if DVB_FE_CUSTOMISE 139 default m if DVB_FE_CUSTOMISE
140 select FW_LOADER
141 help 140 help
142 A DVB-T tuner module. Say Y when you want to support this frontend. 141 A DVB-T tuner module. Say Y when you want to support this frontend.
143 142
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index d4a6e56a7135..ecbfa1b39b70 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -630,7 +630,7 @@ config VIDEO_ZORAN_ZR36060
630 depends on VIDEO_ZORAN 630 depends on VIDEO_ZORAN
631 help 631 help
632 Say Y to support Zoran boards based on 36060 chips. 632 Say Y to support Zoran boards based on 36060 chips.
633 This includes Iomega Bus, Pinnacle DC10, Linux media Labs 33 633 This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33
634 and 33 R10 and AverMedia 6 boards. 634 and 33 R10 and AverMedia 6 boards.
635 635
636config VIDEO_ZORAN_BUZ 636config VIDEO_ZORAN_BUZ
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 56ebfd5ef6fa..9e436ad3d34b 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -29,6 +29,7 @@
29#include <linux/sched.h> 29#include <linux/sched.h>
30#include <linux/videodev.h> 30#include <linux/videodev.h>
31#include <media/v4l2-common.h> 31#include <media/v4l2-common.h>
32#include <media/v4l2-ioctl.h>
32#include <linux/mutex.h> 33#include <linux/mutex.h>
33 34
34#include <asm/uaccess.h> 35#include <asm/uaccess.h>
@@ -755,7 +756,6 @@ static const struct file_operations ar_fops = {
755 756
756static struct video_device ar_template = { 757static struct video_device ar_template = {
757 .name = "Colour AR VGA", 758 .name = "Colour AR VGA",
758 .type = VID_TYPE_CAPTURE,
759 .fops = &ar_fops, 759 .fops = &ar_fops,
760 .release = ar_release, 760 .release = ar_release,
761 .minor = -1, 761 .minor = -1,
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 476ae44a62d2..452da70e719f 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -1015,6 +1015,7 @@ struct em28xx_board em28xx_boards[] = {
1015 .valid = EM28XX_BOARD_NOT_VALIDATED, 1015 .valid = EM28XX_BOARD_NOT_VALIDATED,
1016 .vchannels = 3, 1016 .vchannels = 3,
1017 .tuner_type = TUNER_XC2028, 1017 .tuner_type = TUNER_XC2028,
1018 .mts_firmware = 1,
1018 .decoder = EM28XX_TVP5150, 1019 .decoder = EM28XX_TVP5150,
1019 .input = { { 1020 .input = { {
1020 .type = EM28XX_VMUX_TELEVISION, 1021 .type = EM28XX_VMUX_TELEVISION,
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
index 44b0bffeb20e..cd3a3f5829b2 100644
--- a/drivers/media/video/gspca/conex.c
+++ b/drivers/media/video/gspca/conex.c
@@ -123,7 +123,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
123{ 123{
124 struct usb_device *dev = gspca_dev->dev; 124 struct usb_device *dev = gspca_dev->dev;
125 125
126#ifdef CONFIG_VIDEO_ADV_DEBUG 126#ifdef GSPCA_DEBUG
127 if (len > sizeof gspca_dev->usb_buf) { 127 if (len > sizeof gspca_dev->usb_buf) {
128 err("reg_r: buffer overflow"); 128 err("reg_r: buffer overflow");
129 return; 129 return;
@@ -163,7 +163,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
163{ 163{
164 struct usb_device *dev = gspca_dev->dev; 164 struct usb_device *dev = gspca_dev->dev;
165 165
166#ifdef CONFIG_VIDEO_ADV_DEBUG 166#ifdef GSPCA_DEBUG
167 if (len > sizeof gspca_dev->usb_buf) { 167 if (len > sizeof gspca_dev->usb_buf) {
168 err("reg_w: buffer overflow"); 168 err("reg_w: buffer overflow");
169 return; 169 return;
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
index c8c2f02fcf00..1dbe92d01e6a 100644
--- a/drivers/media/video/gspca/etoms.c
+++ b/drivers/media/video/gspca/etoms.c
@@ -233,7 +233,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
233{ 233{
234 struct usb_device *dev = gspca_dev->dev; 234 struct usb_device *dev = gspca_dev->dev;
235 235
236#ifdef CONFIG_VIDEO_ADV_DEBUG 236#ifdef GSPCA_DEBUG
237 if (len > sizeof gspca_dev->usb_buf) { 237 if (len > sizeof gspca_dev->usb_buf) {
238 err("reg_r: buffer overflow"); 238 err("reg_r: buffer overflow");
239 return; 239 return;
@@ -271,7 +271,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
271{ 271{
272 struct usb_device *dev = gspca_dev->dev; 272 struct usb_device *dev = gspca_dev->dev;
273 273
274#ifdef CONFIG_VIDEO_ADV_DEBUG 274#ifdef GSPCA_DEBUG
275 if (len > sizeof gspca_dev->usb_buf) { 275 if (len > sizeof gspca_dev->usb_buf) {
276 err("reg_w: buffer overflow"); 276 err("reg_w: buffer overflow");
277 return; 277 return;
@@ -461,6 +461,52 @@ static void Et_init2(struct gspca_dev *gspca_dev)
461 reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */ 461 reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */
462} 462}
463 463
464static void setbrightness(struct gspca_dev *gspca_dev)
465{
466 struct sd *sd = (struct sd *) gspca_dev;
467 int i;
468 __u8 brightness = sd->brightness;
469
470 for (i = 0; i < 4; i++)
471 reg_w_val(gspca_dev, ET_O_RED + i, brightness);
472}
473
474static void getbrightness(struct gspca_dev *gspca_dev)
475{
476 struct sd *sd = (struct sd *) gspca_dev;
477 int i;
478 int brightness = 0;
479
480 for (i = 0; i < 4; i++) {
481 reg_r(gspca_dev, ET_O_RED + i, 1);
482 brightness += gspca_dev->usb_buf[0];
483 }
484 sd->brightness = brightness >> 3;
485}
486
487static void setcontrast(struct gspca_dev *gspca_dev)
488{
489 struct sd *sd = (struct sd *) gspca_dev;
490 __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
491 __u8 contrast = sd->contrast;
492
493 memset(RGBG, contrast, sizeof(RGBG) - 2);
494 reg_w(gspca_dev, ET_G_RED, RGBG, 6);
495}
496
497static void getcontrast(struct gspca_dev *gspca_dev)
498{
499 struct sd *sd = (struct sd *) gspca_dev;
500 int i;
501 int contrast = 0;
502
503 for (i = 0; i < 4; i++) {
504 reg_r(gspca_dev, ET_G_RED + i, 1);
505 contrast += gspca_dev->usb_buf[0];
506 }
507 sd->contrast = contrast >> 2;
508}
509
464static void setcolors(struct gspca_dev *gspca_dev) 510static void setcolors(struct gspca_dev *gspca_dev)
465{ 511{
466 struct sd *sd = (struct sd *) gspca_dev; 512 struct sd *sd = (struct sd *) gspca_dev;
@@ -492,6 +538,16 @@ static void getcolors(struct gspca_dev *gspca_dev)
492 } 538 }
493} 539}
494 540
541static void setautogain(struct gspca_dev *gspca_dev)
542{
543 struct sd *sd = (struct sd *) gspca_dev;
544
545 if (sd->autogain)
546 sd->ag_cnt = AG_CNT_START;
547 else
548 sd->ag_cnt = -1;
549}
550
495static void Et_init1(struct gspca_dev *gspca_dev) 551static void Et_init1(struct gspca_dev *gspca_dev)
496{ 552{
497 __u8 value; 553 __u8 value;
@@ -614,6 +670,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
614 sd->contrast = CONTRAST_DEF; 670 sd->contrast = CONTRAST_DEF;
615 sd->colors = COLOR_DEF; 671 sd->colors = COLOR_DEF;
616 sd->autogain = AUTOGAIN_DEF; 672 sd->autogain = AUTOGAIN_DEF;
673 sd->ag_cnt = -1;
617 return 0; 674 return 0;
618} 675}
619 676
@@ -641,6 +698,8 @@ static void sd_start(struct gspca_dev *gspca_dev)
641 else 698 else
642 Et_init2(gspca_dev); 699 Et_init2(gspca_dev);
643 700
701 setautogain(gspca_dev);
702
644 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); 703 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
645 et_video(gspca_dev, 1); /* video on */ 704 et_video(gspca_dev, 1); /* video on */
646} 705}
@@ -658,52 +717,6 @@ static void sd_close(struct gspca_dev *gspca_dev)
658{ 717{
659} 718}
660 719
661static void setbrightness(struct gspca_dev *gspca_dev)
662{
663 struct sd *sd = (struct sd *) gspca_dev;
664 int i;
665 __u8 brightness = sd->brightness;
666
667 for (i = 0; i < 4; i++)
668 reg_w_val(gspca_dev, ET_O_RED + i, brightness);
669}
670
671static void getbrightness(struct gspca_dev *gspca_dev)
672{
673 struct sd *sd = (struct sd *) gspca_dev;
674 int i;
675 int brightness = 0;
676
677 for (i = 0; i < 4; i++) {
678 reg_r(gspca_dev, ET_O_RED + i, 1);
679 brightness += gspca_dev->usb_buf[0];
680 }
681 sd->brightness = brightness >> 3;
682}
683
684static void setcontrast(struct gspca_dev *gspca_dev)
685{
686 struct sd *sd = (struct sd *) gspca_dev;
687 __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
688 __u8 contrast = sd->contrast;
689
690 memset(RGBG, contrast, sizeof(RGBG) - 2);
691 reg_w(gspca_dev, ET_G_RED, RGBG, 6);
692}
693
694static void getcontrast(struct gspca_dev *gspca_dev)
695{
696 struct sd *sd = (struct sd *) gspca_dev;
697 int i;
698 int contrast = 0;
699
700 for (i = 0; i < 4; i++) {
701 reg_r(gspca_dev, ET_G_RED + i, 1);
702 contrast += gspca_dev->usb_buf[0];
703 }
704 sd->contrast = contrast >> 2;
705}
706
707static __u8 Et_getgainG(struct gspca_dev *gspca_dev) 720static __u8 Et_getgainG(struct gspca_dev *gspca_dev)
708{ 721{
709 struct sd *sd = (struct sd *) gspca_dev; 722 struct sd *sd = (struct sd *) gspca_dev;
@@ -733,15 +746,22 @@ static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain)
733#define LIMIT(color) \ 746#define LIMIT(color) \
734 (unsigned char)((color > 0xff)?0xff:((color < 0)?0:color)) 747 (unsigned char)((color > 0xff)?0xff:((color < 0)?0:color))
735 748
736static void setautogain(struct gspca_dev *gspca_dev) 749static void do_autogain(struct gspca_dev *gspca_dev)
737{ 750{
738 __u8 luma = 0; 751 struct sd *sd = (struct sd *) gspca_dev;
752 __u8 luma;
739 __u8 luma_mean = 128; 753 __u8 luma_mean = 128;
740 __u8 luma_delta = 20; 754 __u8 luma_delta = 20;
741 __u8 spring = 4; 755 __u8 spring = 4;
742 int Gbright = 0; 756 int Gbright;
743 __u8 r, g, b; 757 __u8 r, g, b;
744 758
759 if (sd->ag_cnt < 0)
760 return;
761 if (--sd->ag_cnt >= 0)
762 return;
763 sd->ag_cnt = AG_CNT_START;
764
745 Gbright = Et_getgainG(gspca_dev); 765 Gbright = Et_getgainG(gspca_dev);
746 reg_r(gspca_dev, ET_LUMA_CENTER, 4); 766 reg_r(gspca_dev, ET_LUMA_CENTER, 4);
747 g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1; 767 g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1;
@@ -768,7 +788,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
768 __u8 *data, /* isoc packet */ 788 __u8 *data, /* isoc packet */
769 int len) /* iso packet length */ 789 int len) /* iso packet length */
770{ 790{
771 struct sd *sd;
772 int seqframe; 791 int seqframe;
773 792
774 seqframe = data[0] & 0x3f; 793 seqframe = data[0] & 0x3f;
@@ -783,13 +802,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
783 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, 802 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
784 data, 0); 803 data, 0);
785 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); 804 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
786 sd = (struct sd *) gspca_dev;
787 if (sd->ag_cnt >= 0) {
788 if (--sd->ag_cnt < 0) {
789 sd->ag_cnt = AG_CNT_START;
790 setautogain(gspca_dev);
791 }
792 }
793 return; 805 return;
794 } 806 }
795 if (len) { 807 if (len) {
@@ -862,10 +874,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
862 struct sd *sd = (struct sd *) gspca_dev; 874 struct sd *sd = (struct sd *) gspca_dev;
863 875
864 sd->autogain = val; 876 sd->autogain = val;
865 if (val) 877 if (gspca_dev->streaming)
866 sd->ag_cnt = AG_CNT_START; 878 setautogain(gspca_dev);
867 else
868 sd->ag_cnt = -1;
869 return 0; 879 return 0;
870} 880}
871 881
@@ -889,6 +899,7 @@ static struct sd_desc sd_desc = {
889 .stop0 = sd_stop0, 899 .stop0 = sd_stop0,
890 .close = sd_close, 900 .close = sd_close,
891 .pkt_scan = sd_pkt_scan, 901 .pkt_scan = sd_pkt_scan,
902 .dq_callback = do_autogain,
892}; 903};
893 904
894/* -- module initialisation -- */ 905/* -- module initialisation -- */
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 3a051c925ff6..15d302b28b79 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -47,7 +47,7 @@ MODULE_LICENSE("GPL");
47 47
48static int video_nr = -1; 48static int video_nr = -1;
49 49
50#ifdef CONFIG_VIDEO_ADV_DEBUG 50#ifdef GSPCA_DEBUG
51int gspca_debug = D_ERR | D_PROBE; 51int gspca_debug = D_ERR | D_PROBE;
52EXPORT_SYMBOL(gspca_debug); 52EXPORT_SYMBOL(gspca_debug);
53 53
@@ -677,7 +677,7 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
677 w = fmt->fmt.pix.width; 677 w = fmt->fmt.pix.width;
678 h = fmt->fmt.pix.height; 678 h = fmt->fmt.pix.height;
679 679
680#ifdef CONFIG_VIDEO_ADV_DEBUG 680#ifdef GSPCA_DEBUG
681 if (gspca_debug & D_CONF) 681 if (gspca_debug & D_CONF)
682 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h); 682 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
683#endif 683#endif
@@ -785,7 +785,7 @@ static int dev_open(struct inode *inode, struct file *file)
785 } 785 }
786 gspca_dev->users++; 786 gspca_dev->users++;
787 file->private_data = gspca_dev; 787 file->private_data = gspca_dev;
788#ifdef CONFIG_VIDEO_ADV_DEBUG 788#ifdef GSPCA_DEBUG
789 /* activate the v4l2 debug */ 789 /* activate the v4l2 debug */
790 if (gspca_debug & D_V4L2) 790 if (gspca_debug & D_V4L2)
791 gspca_dev->vdev.debug |= 3; 791 gspca_dev->vdev.debug |= 3;
@@ -904,7 +904,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
904 if (ctrl->id != ctrls->qctrl.id) 904 if (ctrl->id != ctrls->qctrl.id)
905 continue; 905 continue;
906 if (ctrl->value < ctrls->qctrl.minimum 906 if (ctrl->value < ctrls->qctrl.minimum
907 && ctrl->value > ctrls->qctrl.maximum) 907 || ctrl->value > ctrls->qctrl.maximum)
908 return -ERANGE; 908 return -ERANGE;
909 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); 909 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
910 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) 910 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
@@ -1080,7 +1080,7 @@ static int vidioc_streamon(struct file *file, void *priv,
1080 if (ret < 0) 1080 if (ret < 0)
1081 goto out; 1081 goto out;
1082 } 1082 }
1083#ifdef CONFIG_VIDEO_ADV_DEBUG 1083#ifdef GSPCA_DEBUG
1084 if (gspca_debug & D_STREAM) { 1084 if (gspca_debug & D_STREAM) {
1085 PDEBUG_MODE("stream on OK", 1085 PDEBUG_MODE("stream on OK",
1086 gspca_dev->pixfmt, 1086 gspca_dev->pixfmt,
@@ -1913,7 +1913,7 @@ static void __exit gspca_exit(void)
1913module_init(gspca_init); 1913module_init(gspca_init);
1914module_exit(gspca_exit); 1914module_exit(gspca_exit);
1915 1915
1916#ifdef CONFIG_VIDEO_ADV_DEBUG 1916#ifdef GSPCA_DEBUG
1917module_param_named(debug, gspca_debug, int, 0644); 1917module_param_named(debug, gspca_debug, int, 0644);
1918MODULE_PARM_DESC(debug, 1918MODULE_PARM_DESC(debug,
1919 "Debug (bit) 0x01:error 0x02:probe 0x04:config" 1919 "Debug (bit) 0x01:error 0x02:probe 0x04:config"
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 3fd2c4eee204..67e448940eaa 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -9,7 +9,10 @@
9#include <media/v4l2-common.h> 9#include <media/v4l2-common.h>
10#include <linux/mutex.h> 10#include <linux/mutex.h>
11 11
12#ifdef CONFIG_VIDEO_ADV_DEBUG 12/* compilation option */
13#define GSPCA_DEBUG 1
14
15#ifdef GSPCA_DEBUG
13/* GSPCA our debug messages */ 16/* GSPCA our debug messages */
14extern int gspca_debug; 17extern int gspca_debug;
15#define PDEBUG(level, fmt, args...) \ 18#define PDEBUG(level, fmt, args...) \
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 83139efc4629..b4f00ec0885c 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -40,14 +40,15 @@ struct sd {
40 struct gspca_dev gspca_dev; /* !! must be the first item */ 40 struct gspca_dev gspca_dev; /* !! must be the first item */
41 41
42 /* Determined by sensor type */ 42 /* Determined by sensor type */
43 short maxwidth; 43 char sif;
44 short maxheight;
45 44
46 unsigned char primary_i2c_slave; /* I2C write id of sensor */ 45 unsigned char primary_i2c_slave; /* I2C write id of sensor */
47 46
48 unsigned char brightness; 47 unsigned char brightness;
49 unsigned char contrast; 48 unsigned char contrast;
50 unsigned char colors; 49 unsigned char colors;
50 __u8 hflip;
51 __u8 vflip;
51 52
52 char compress; /* Should the next frame be compressed? */ 53 char compress; /* Should the next frame be compressed? */
53 char compress_inited; /* Are compression params uploaded? */ 54 char compress_inited; /* Are compression params uploaded? */
@@ -77,9 +78,12 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
77static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); 78static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
78static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); 79static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
79static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); 80static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
81static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
83static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
84static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
80 85
81static struct ctrl sd_ctrls[] = { 86static struct ctrl sd_ctrls[] = {
82#define SD_BRIGHTNESS 0
83 { 87 {
84 { 88 {
85 .id = V4L2_CID_BRIGHTNESS, 89 .id = V4L2_CID_BRIGHTNESS,
@@ -88,12 +92,12 @@ static struct ctrl sd_ctrls[] = {
88 .minimum = 0, 92 .minimum = 0,
89 .maximum = 255, 93 .maximum = 255,
90 .step = 1, 94 .step = 1,
91 .default_value = 127, 95#define BRIGHTNESS_DEF 127
96 .default_value = BRIGHTNESS_DEF,
92 }, 97 },
93 .set = sd_setbrightness, 98 .set = sd_setbrightness,
94 .get = sd_getbrightness, 99 .get = sd_getbrightness,
95 }, 100 },
96#define SD_CONTRAST 1
97 { 101 {
98 { 102 {
99 .id = V4L2_CID_CONTRAST, 103 .id = V4L2_CID_CONTRAST,
@@ -102,31 +106,61 @@ static struct ctrl sd_ctrls[] = {
102 .minimum = 0, 106 .minimum = 0,
103 .maximum = 255, 107 .maximum = 255,
104 .step = 1, 108 .step = 1,
105 .default_value = 127, 109#define CONTRAST_DEF 127
110 .default_value = CONTRAST_DEF,
106 }, 111 },
107 .set = sd_setcontrast, 112 .set = sd_setcontrast,
108 .get = sd_getcontrast, 113 .get = sd_getcontrast,
109 }, 114 },
110#define SD_COLOR 2
111 { 115 {
112 { 116 {
113 .id = V4L2_CID_SATURATION, 117 .id = V4L2_CID_SATURATION,
114 .type = V4L2_CTRL_TYPE_INTEGER, 118 .type = V4L2_CTRL_TYPE_INTEGER,
115 .name = "Saturation", 119 .name = "Color",
116 .minimum = 0, 120 .minimum = 0,
117 .maximum = 255, 121 .maximum = 255,
118 .step = 1, 122 .step = 1,
119 .default_value = 127, 123#define COLOR_DEF 127
124 .default_value = COLOR_DEF,
120 }, 125 },
121 .set = sd_setcolors, 126 .set = sd_setcolors,
122 .get = sd_getcolors, 127 .get = sd_getcolors,
123 }, 128 },
129/* next controls work with ov7670 only */
130 {
131 {
132 .id = V4L2_CID_HFLIP,
133 .type = V4L2_CTRL_TYPE_BOOLEAN,
134 .name = "Mirror",
135 .minimum = 0,
136 .maximum = 1,
137 .step = 1,
138#define HFLIP_DEF 0
139 .default_value = HFLIP_DEF,
140 },
141 .set = sd_sethflip,
142 .get = sd_gethflip,
143 },
144 {
145 {
146 .id = V4L2_CID_VFLIP,
147 .type = V4L2_CTRL_TYPE_BOOLEAN,
148 .name = "Vflip",
149 .minimum = 0,
150 .maximum = 1,
151 .step = 1,
152#define VFLIP_DEF 0
153 .default_value = VFLIP_DEF,
154 },
155 .set = sd_setvflip,
156 .get = sd_getvflip,
157 },
124}; 158};
125 159
126static struct v4l2_pix_format vga_mode[] = { 160static struct v4l2_pix_format vga_mode[] = {
127 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 161 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
128 .bytesperline = 320, 162 .bytesperline = 320,
129 .sizeimage = 320 * 240 * 3 / 8 + 589, 163 .sizeimage = 320 * 240 * 3 / 8 + 590,
130 .colorspace = V4L2_COLORSPACE_JPEG, 164 .colorspace = V4L2_COLORSPACE_JPEG,
131 .priv = 1}, 165 .priv = 1},
132 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 166 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@ -138,12 +172,12 @@ static struct v4l2_pix_format vga_mode[] = {
138static struct v4l2_pix_format sif_mode[] = { 172static struct v4l2_pix_format sif_mode[] = {
139 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 173 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
140 .bytesperline = 176, 174 .bytesperline = 176,
141 .sizeimage = 176 * 144 * 3 / 8 + 589, 175 .sizeimage = 176 * 144 * 3 / 8 + 590,
142 .colorspace = V4L2_COLORSPACE_JPEG, 176 .colorspace = V4L2_COLORSPACE_JPEG,
143 .priv = 1}, 177 .priv = 1},
144 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 178 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
145 .bytesperline = 352, 179 .bytesperline = 352,
146 .sizeimage = 352 * 288 * 3 / 8 + 589, 180 .sizeimage = 352 * 288 * 3 / 8 + 590,
147 .colorspace = V4L2_COLORSPACE_JPEG, 181 .colorspace = V4L2_COLORSPACE_JPEG,
148 .priv = 0}, 182 .priv = 0},
149}; 183};
@@ -225,6 +259,7 @@ static struct v4l2_pix_format sif_mode[] = {
225#define OV7670_REG_VSTART 0x19 /* Vert start high bits */ 259#define OV7670_REG_VSTART 0x19 /* Vert start high bits */
226#define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */ 260#define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */
227#define OV7670_REG_MVFP 0x1e /* Mirror / vflip */ 261#define OV7670_REG_MVFP 0x1e /* Mirror / vflip */
262#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */
228#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ 263#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */
229#define OV7670_REG_AEW 0x24 /* AGC upper limit */ 264#define OV7670_REG_AEW 0x24 /* AGC upper limit */
230#define OV7670_REG_AEB 0x25 /* AGC lower limit */ 265#define OV7670_REG_AEB 0x25 /* AGC lower limit */
@@ -258,16 +293,6 @@ static struct v4l2_pix_format sif_mode[] = {
258#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ 293#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */
259#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ 294#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */
260 295
261struct ovsensor_window {
262 short x;
263 short y;
264 short width;
265 short height;
266/* int format; */
267 short quarter; /* Scale width and height down 2x */
268 short clockdiv; /* Clock divisor setting */
269};
270
271static unsigned char ov7670_abs_to_sm(unsigned char v) 296static unsigned char ov7670_abs_to_sm(unsigned char v)
272{ 297{
273 if (v > 127) 298 if (v > 127)
@@ -499,19 +524,6 @@ static int init_ov_sensor(struct sd *sd)
499 return 0; 524 return 0;
500} 525}
501 526
502/* Switch on standard JPEG compression. Returns 0 for success. */
503static int ov519_init_compression(struct sd *sd)
504{
505 if (!sd->compress_inited) {
506 if (reg_w_mask(sd, OV519_SYS_EN_CLK1, 1 << 2, 1 << 2) < 0) {
507 PDEBUG(D_ERR, "Error switching to compressed mode");
508 return -EIO;
509 }
510 sd->compress_inited = 1;
511 }
512 return 0;
513}
514
515/* Set the read and write slave IDs. The "slave" argument is the write slave, 527/* Set the read and write slave IDs. The "slave" argument is the write slave,
516 * and the read slave will be set to (slave + 1). 528 * and the read slave will be set to (slave + 1).
517 * This should not be called from outside the i2c I/O functions. 529 * This should not be called from outside the i2c I/O functions.
@@ -681,21 +693,17 @@ static int ov8xx0_configure(struct sd *sd)
681 return -1; 693 return -1;
682 } 694 }
683 if ((rc & 3) == 1) { 695 if ((rc & 3) == 1) {
684 PDEBUG(D_PROBE, "Sensor is an OV8610");
685 sd->sensor = SEN_OV8610; 696 sd->sensor = SEN_OV8610;
686 } else { 697 } else {
687 PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3); 698 PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
688 return -1; 699 return -1;
689 } 700 }
690 PDEBUG(D_PROBE, "Writing 8610 registers"); 701 PDEBUG(D_PROBE, "Writing 8610 registers");
691 if (write_i2c_regvals(sd, 702 if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
692 norm_8610,
693 sizeof norm_8610 / sizeof norm_8610[0]))
694 return -1; 703 return -1;
695 704
696 /* Set sensor-specific vars */ 705 /* Set sensor-specific vars */
697 sd->maxwidth = 640; 706/* sd->sif = 0; already done */
698 sd->maxheight = 480;
699 return 0; 707 return 0;
700} 708}
701 709
@@ -825,7 +833,7 @@ static int ov7xx0_configure(struct sd *sd)
825 { OV7670_REG_COM7, OV7670_COM7_RESET }, 833 { OV7670_REG_COM7, OV7670_COM7_RESET },
826 { OV7670_REG_TSLB, 0x04 }, /* OV */ 834 { OV7670_REG_TSLB, 0x04 }, /* OV */
827 { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ 835 { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
828 { OV7670_REG_CLKRC, 0x1 }, 836 { OV7670_REG_CLKRC, 0x01 },
829 /* 837 /*
830 * Set the hardware window. These values from OV don't entirely 838 * Set the hardware window. These values from OV don't entirely
831 * make sense - hstop is less than hstart. But they work... 839 * make sense - hstop is less than hstart. But they work...
@@ -839,16 +847,12 @@ static int ov7xx0_configure(struct sd *sd)
839 { 0x70, 0x3a }, { 0x71, 0x35 }, 847 { 0x70, 0x3a }, { 0x71, 0x35 },
840 { 0x72, 0x11 }, { 0x73, 0xf0 }, 848 { 0x72, 0x11 }, { 0x73, 0xf0 },
841 { 0xa2, 0x02 }, 849 { 0xa2, 0x02 },
842/* jfm */ 850/* { OV7670_REG_COM10, 0x0 }, */
843/* { OV7670_REG_COM10, 0x0 }, */
844 851
845 /* Gamma curve values */ 852 /* Gamma curve values */
846 { 0x7a, 0x20 }, 853 { 0x7a, 0x20 },
847/* jfm:win 7b=1c */
848 { 0x7b, 0x10 }, 854 { 0x7b, 0x10 },
849/* jfm:win 7c=28 */
850 { 0x7c, 0x1e }, 855 { 0x7c, 0x1e },
851/* jfm:win 7d=3c */
852 { 0x7d, 0x35 }, 856 { 0x7d, 0x35 },
853 { 0x7e, 0x5a }, { 0x7f, 0x69 }, 857 { 0x7e, 0x5a }, { 0x7f, 0x69 },
854 { 0x80, 0x76 }, { 0x81, 0x80 }, 858 { 0x80, 0x76 }, { 0x81, 0x80 },
@@ -864,13 +868,11 @@ static int ov7xx0_configure(struct sd *sd)
864 | OV7670_COM8_BFILT }, 868 | OV7670_COM8_BFILT },
865 { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 }, 869 { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 },
866 { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */ 870 { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
867/* jfm:win 14=38 */
868 { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ 871 { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
869 { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 }, 872 { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 },
870 { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 }, 873 { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 },
871 { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 }, 874 { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 },
872 { OV7670_REG_HAECC2, 0x68 }, 875 { OV7670_REG_HAECC2, 0x68 },
873/* jfm:win a1=0b */
874 { 0xa1, 0x03 }, /* magic */ 876 { 0xa1, 0x03 }, /* magic */
875 { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 }, 877 { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 },
876 { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 }, 878 { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 },
@@ -884,8 +886,6 @@ static int ov7xx0_configure(struct sd *sd)
884 /* Almost all of these are magic "reserved" values. */ 886 /* Almost all of these are magic "reserved" values. */
885 { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b }, 887 { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b },
886 { 0x16, 0x02 }, 888 { 0x16, 0x02 },
887/* jfm */
888/* { OV7670_REG_MVFP, 0x07|OV7670_MVFP_MIRROR }, */
889 { OV7670_REG_MVFP, 0x07 }, 889 { OV7670_REG_MVFP, 0x07 },
890 { 0x21, 0x02 }, { 0x22, 0x91 }, 890 { 0x21, 0x02 }, { 0x22, 0x91 },
891 { 0x29, 0x07 }, { 0x33, 0x0b }, 891 { 0x29, 0x07 }, { 0x33, 0x0b },
@@ -930,7 +930,10 @@ static int ov7xx0_configure(struct sd *sd)
930 { OV7670_REG_EDGE, 0 }, 930 { OV7670_REG_EDGE, 0 },
931 { 0x75, 0x05 }, { 0x76, 0xe1 }, 931 { 0x75, 0x05 }, { 0x76, 0xe1 },
932 { 0x4c, 0 }, { 0x77, 0x01 }, 932 { 0x4c, 0 }, { 0x77, 0x01 },
933 { OV7670_REG_COM13, 0xc3 }, { 0x4b, 0x09 }, 933 { OV7670_REG_COM13, OV7670_COM13_GAMMA
934 | OV7670_COM13_UVSAT
935 | 2}, /* was 3 */
936 { 0x4b, 0x09 },
934 { 0xc9, 0x60 }, { OV7670_REG_COM16, 0x38 }, 937 { 0xc9, 0x60 }, { OV7670_REG_COM16, 0x38 },
935 { 0x56, 0x40 }, 938 { 0x56, 0x40 },
936 939
@@ -956,30 +959,10 @@ static int ov7xx0_configure(struct sd *sd)
956 { 0x79, 0x03 }, { 0xc8, 0x40 }, 959 { 0x79, 0x03 }, { 0xc8, 0x40 },
957 { 0x79, 0x05 }, { 0xc8, 0x30 }, 960 { 0x79, 0x05 }, { 0xc8, 0x30 },
958 { 0x79, 0x26 }, 961 { 0x79, 0x26 },
959 962 };
960 /* Format YUV422 */
961 { OV7670_REG_COM7, OV7670_COM7_YUV }, /* Selects YUV mode */
962 { OV7670_REG_RGB444, 0 }, /* No RGB444 please */
963 { OV7670_REG_COM1, 0 },
964 { OV7670_REG_COM15, OV7670_COM15_R00FF },
965 { OV7670_REG_COM9, 0x18 },
966 /* 4x gain ceiling; 0x8 is reserved bit */
967 { 0x4f, 0x80 }, /* "matrix coefficient 1" */
968 { 0x50, 0x80 }, /* "matrix coefficient 2" */
969 { 0x52, 0x22 }, /* "matrix coefficient 4" */
970 { 0x53, 0x5e }, /* "matrix coefficient 5" */
971 { 0x54, 0x80 }, /* "matrix coefficient 6" */
972 { OV7670_REG_COM13, OV7670_COM13_GAMMA|OV7670_COM13_UVSAT },
973};
974 963
975 PDEBUG(D_PROBE, "starting OV7xx0 configuration"); 964 PDEBUG(D_PROBE, "starting OV7xx0 configuration");
976 965
977/* jfm:already done? */
978 if (init_ov_sensor(sd) < 0)
979 PDEBUG(D_ERR, "Failed to read sensor ID");
980 else
981 PDEBUG(D_PROBE, "OV7xx0 initialized");
982
983 /* Detect sensor (sub)type */ 966 /* Detect sensor (sub)type */
984 rc = i2c_r(sd, OV7610_REG_COM_I); 967 rc = i2c_r(sd, OV7610_REG_COM_I);
985 968
@@ -1025,20 +1008,25 @@ static int ov7xx0_configure(struct sd *sd)
1025 return low; 1008 return low;
1026 } 1009 }
1027 if (high == 0x76) { 1010 if (high == 0x76) {
1028 if (low == 0x30) { 1011 switch (low) {
1012 case 0x30:
1029 PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635"); 1013 PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635");
1030 sd->sensor = SEN_OV7630; 1014 sd->sensor = SEN_OV7630;
1031 } else if (low == 0x40) { 1015 break;
1016 case 0x40:
1032 PDEBUG(D_PROBE, "Sensor is an OV7645"); 1017 PDEBUG(D_PROBE, "Sensor is an OV7645");
1033 sd->sensor = SEN_OV7640; /* FIXME */ 1018 sd->sensor = SEN_OV7640; /* FIXME */
1034 } else if (low == 0x45) { 1019 break;
1020 case 0x45:
1035 PDEBUG(D_PROBE, "Sensor is an OV7645B"); 1021 PDEBUG(D_PROBE, "Sensor is an OV7645B");
1036 sd->sensor = SEN_OV7640; /* FIXME */ 1022 sd->sensor = SEN_OV7640; /* FIXME */
1037 } else if (low == 0x48) { 1023 break;
1024 case 0x48:
1038 PDEBUG(D_PROBE, "Sensor is an OV7648"); 1025 PDEBUG(D_PROBE, "Sensor is an OV7648");
1039 sd->sensor = SEN_OV7640; /* FIXME */ 1026 sd->sensor = SEN_OV7640; /* FIXME */
1040 } else { 1027 break;
1041 PDEBUG(D_PROBE, "Unknown sensor: 0x76%X", low); 1028 default:
1029 PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
1042 return -1; 1030 return -1;
1043 } 1031 }
1044 } else { 1032 } else {
@@ -1050,34 +1038,34 @@ static int ov7xx0_configure(struct sd *sd)
1050 return -1; 1038 return -1;
1051 } 1039 }
1052 1040
1053 if (sd->sensor == SEN_OV7620) { 1041 switch (sd->sensor) {
1042 case SEN_OV7620:
1054 PDEBUG(D_PROBE, "Writing 7620 registers"); 1043 PDEBUG(D_PROBE, "Writing 7620 registers");
1055 if (write_i2c_regvals(sd, norm_7620, 1044 if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
1056 sizeof norm_7620 / sizeof norm_7620[0]))
1057 return -1; 1045 return -1;
1058 } else if (sd->sensor == SEN_OV7630) { 1046 break;
1047 case SEN_OV7630:
1059 PDEBUG(D_ERR, "7630 is not supported by this driver version"); 1048 PDEBUG(D_ERR, "7630 is not supported by this driver version");
1060 return -1; 1049 return -1;
1061 } else if (sd->sensor == SEN_OV7640) { 1050 case SEN_OV7640:
1062 PDEBUG(D_PROBE, "Writing 7640 registers"); 1051 PDEBUG(D_PROBE, "Writing 7640 registers");
1063 if (write_i2c_regvals(sd, norm_7640, 1052 if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
1064 sizeof norm_7640 / sizeof norm_7640[0]))
1065 return -1; 1053 return -1;
1066 } else if (sd->sensor == SEN_OV7670) { 1054 break;
1055 case SEN_OV7670:
1067 PDEBUG(D_PROBE, "Writing 7670 registers"); 1056 PDEBUG(D_PROBE, "Writing 7670 registers");
1068 if (write_i2c_regvals(sd, norm_7670, 1057 if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
1069 sizeof norm_7670 / sizeof norm_7670[0]))
1070 return -1; 1058 return -1;
1071 } else { 1059 break;
1060 default:
1072 PDEBUG(D_PROBE, "Writing 7610 registers"); 1061 PDEBUG(D_PROBE, "Writing 7610 registers");
1073 if (write_i2c_regvals(sd, norm_7610, 1062 if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
1074 sizeof norm_7610 / sizeof norm_7610[0]))
1075 return -1; 1063 return -1;
1064 break;
1076 } 1065 }
1077 1066
1078 /* Set sensor-specific vars */ 1067 /* Set sensor-specific vars */
1079 sd->maxwidth = 640; 1068/* sd->sif = 0; already done */
1080 sd->maxheight = 480;
1081 return 0; 1069 return 0;
1082} 1070}
1083 1071
@@ -1231,43 +1219,45 @@ static int ov6xx0_configure(struct sd *sd)
1231 /* Ugh. The first two bits are the version bits, but 1219 /* Ugh. The first two bits are the version bits, but
1232 * the entire register value must be used. I guess OVT 1220 * the entire register value must be used. I guess OVT
1233 * underestimated how many variants they would make. */ 1221 * underestimated how many variants they would make. */
1234 if (rc == 0x00) { 1222 switch (rc) {
1223 case 0x00:
1235 sd->sensor = SEN_OV6630; 1224 sd->sensor = SEN_OV6630;
1236 PDEBUG(D_ERR, 1225 PDEBUG(D_ERR,
1237 "WARNING: Sensor is an OV66308. Your camera may have"); 1226 "WARNING: Sensor is an OV66308. Your camera may have");
1238 PDEBUG(D_ERR, "been misdetected in previous driver versions."); 1227 PDEBUG(D_ERR, "been misdetected in previous driver versions.");
1239 } else if (rc == 0x01) { 1228 break;
1229 case 0x01:
1240 sd->sensor = SEN_OV6620; 1230 sd->sensor = SEN_OV6620;
1241 PDEBUG(D_PROBE, "Sensor is an OV6620"); 1231 break;
1242 } else if (rc == 0x02) { 1232 case 0x02:
1243 sd->sensor = SEN_OV6630; 1233 sd->sensor = SEN_OV6630;
1244 PDEBUG(D_PROBE, "Sensor is an OV66308AE"); 1234 PDEBUG(D_PROBE, "Sensor is an OV66308AE");
1245 } else if (rc == 0x03) { 1235 break;
1236 case 0x03:
1246 sd->sensor = SEN_OV6630; 1237 sd->sensor = SEN_OV6630;
1247 PDEBUG(D_PROBE, "Sensor is an OV66308AF"); 1238 PDEBUG(D_PROBE, "Sensor is an OV66308AF");
1248 } else if (rc == 0x90) { 1239 break;
1240 case 0x90:
1249 sd->sensor = SEN_OV6630; 1241 sd->sensor = SEN_OV6630;
1250 PDEBUG(D_ERR, 1242 PDEBUG(D_ERR,
1251 "WARNING: Sensor is an OV66307. Your camera may have"); 1243 "WARNING: Sensor is an OV66307. Your camera may have");
1252 PDEBUG(D_ERR, "been misdetected in previous driver versions."); 1244 PDEBUG(D_ERR, "been misdetected in previous driver versions.");
1253 } else { 1245 break;
1246 default:
1254 PDEBUG(D_ERR, "FATAL: Unknown sensor version: 0x%02x", rc); 1247 PDEBUG(D_ERR, "FATAL: Unknown sensor version: 0x%02x", rc);
1255 return -1; 1248 return -1;
1256 } 1249 }
1257 1250
1258 /* Set sensor-specific vars */ 1251 /* Set sensor-specific vars */
1259 sd->maxwidth = 352; 1252 sd->sif = 1;
1260 sd->maxheight = 288;
1261 1253
1262 if (sd->sensor == SEN_OV6620) { 1254 if (sd->sensor == SEN_OV6620) {
1263 PDEBUG(D_PROBE, "Writing 6x20 registers"); 1255 PDEBUG(D_PROBE, "Writing 6x20 registers");
1264 if (write_i2c_regvals(sd, norm_6x20, 1256 if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
1265 sizeof norm_6x20 / sizeof norm_6x20[0]))
1266 return -1; 1257 return -1;
1267 } else { 1258 } else {
1268 PDEBUG(D_PROBE, "Writing 6x30 registers"); 1259 PDEBUG(D_PROBE, "Writing 6x30 registers");
1269 if (write_i2c_regvals(sd, norm_6x30, 1260 if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
1270 sizeof norm_6x30 / sizeof norm_6x30[0]))
1271 return -1; 1261 return -1;
1272 } 1262 }
1273 return 0; 1263 return 0;
@@ -1276,14 +1266,8 @@ static int ov6xx0_configure(struct sd *sd)
1276/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ 1266/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
1277static void ov51x_led_control(struct sd *sd, int on) 1267static void ov51x_led_control(struct sd *sd, int on)
1278{ 1268{
1279 PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); 1269/* PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); */
1280 1270 reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
1281/* if (sd->bridge == BRG_OV511PLUS) */
1282/* reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); */
1283/* else if (sd->bridge == BRG_OV519) */
1284 reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
1285/* else if (sd->bclass == BCL_OV518) */
1286/* reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); */
1287} 1271}
1288 1272
1289/* this function is called at probe time */ 1273/* this function is called at probe time */
@@ -1293,11 +1277,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
1293 struct sd *sd = (struct sd *) gspca_dev; 1277 struct sd *sd = (struct sd *) gspca_dev;
1294 struct cam *cam; 1278 struct cam *cam;
1295 1279
1296/* (from ov519_configure) */
1297 static const struct ov_regvals init_519[] = { 1280 static const struct ov_regvals init_519[] = {
1298 { 0x5a, 0x6d }, /* EnableSystem */ 1281 { 0x5a, 0x6d }, /* EnableSystem */
1299/* jfm trace usbsnoop3-1.txt */
1300/* jfm 53 = fb */
1301 { 0x53, 0x9b }, 1282 { 0x53, 0x9b },
1302 { 0x54, 0xff }, /* set bit2 to enable jpeg */ 1283 { 0x54, 0xff }, /* set bit2 to enable jpeg */
1303 { 0x5d, 0x03 }, 1284 { 0x5d, 0x03 },
@@ -1314,9 +1295,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
1314 1295
1315 if (write_regvals(sd, init_519, ARRAY_SIZE(init_519))) 1296 if (write_regvals(sd, init_519, ARRAY_SIZE(init_519)))
1316 goto error; 1297 goto error;
1317/* jfm: not seen in windows trace */
1318 if (ov519_init_compression(sd))
1319 goto error;
1320 ov51x_led_control(sd, 0); /* turn LED off */ 1298 ov51x_led_control(sd, 0); /* turn LED off */
1321 1299
1322 /* Test for 76xx */ 1300 /* Test for 76xx */
@@ -1365,16 +1343,18 @@ static int sd_config(struct gspca_dev *gspca_dev,
1365 1343
1366 cam = &gspca_dev->cam; 1344 cam = &gspca_dev->cam;
1367 cam->epaddr = OV511_ENDPOINT_ADDRESS; 1345 cam->epaddr = OV511_ENDPOINT_ADDRESS;
1368 if (sd->maxwidth == 640) { 1346 if (!sd->sif) {
1369 cam->cam_mode = vga_mode; 1347 cam->cam_mode = vga_mode;
1370 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; 1348 cam->nmodes = ARRAY_SIZE(vga_mode);
1371 } else { 1349 } else {
1372 cam->cam_mode = sif_mode; 1350 cam->cam_mode = sif_mode;
1373 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; 1351 cam->nmodes = ARRAY_SIZE(sif_mode);
1374 } 1352 }
1375 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; 1353 sd->brightness = BRIGHTNESS_DEF;
1376 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; 1354 sd->contrast = CONTRAST_DEF;
1377 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; 1355 sd->colors = COLOR_DEF;
1356 sd->hflip = HFLIP_DEF;
1357 sd->vflip = VFLIP_DEF;
1378 return 0; 1358 return 0;
1379error: 1359error:
1380 PDEBUG(D_ERR, "OV519 Config failed"); 1360 PDEBUG(D_ERR, "OV519 Config failed");
@@ -1394,8 +1374,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
1394 * 1374 *
1395 * Do not put any sensor-specific code in here (including I2C I/O functions) 1375 * Do not put any sensor-specific code in here (including I2C I/O functions)
1396 */ 1376 */
1397static int ov519_mode_init_regs(struct sd *sd, 1377static int ov519_mode_init_regs(struct sd *sd)
1398 int width, int height)
1399{ 1378{
1400 static const struct ov_regvals mode_init_519_ov7670[] = { 1379 static const struct ov_regvals mode_init_519_ov7670[] = {
1401 { 0x5d, 0x03 }, /* Turn off suspend mode */ 1380 { 0x5d, 0x03 }, /* Turn off suspend mode */
@@ -1441,36 +1420,23 @@ static int ov519_mode_init_regs(struct sd *sd,
1441 /* windows reads 0x55 at this point, why? */ 1420 /* windows reads 0x55 at this point, why? */
1442 }; 1421 };
1443 1422
1444/* int hi_res; */
1445
1446 PDEBUG(D_CONF, "mode init %dx%d", width, height);
1447
1448/* if (width >= 800 && height >= 600)
1449 hi_res = 1;
1450 else
1451 hi_res = 0; */
1452
1453/* if (ov51x_stop(sd) < 0)
1454 return -EIO; */
1455
1456 /******** Set the mode ********/ 1423 /******** Set the mode ********/
1457 if (sd->sensor != SEN_OV7670) { 1424 if (sd->sensor != SEN_OV7670) {
1458 if (write_regvals(sd, mode_init_519, 1425 if (write_regvals(sd, mode_init_519,
1459 ARRAY_SIZE(mode_init_519))) 1426 ARRAY_SIZE(mode_init_519)))
1460 return -EIO; 1427 return -EIO;
1428 if (sd->sensor == SEN_OV7640) {
1429 /* Select 8-bit input mode */
1430 reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10);
1431 }
1461 } else { 1432 } else {
1462 if (write_regvals(sd, mode_init_519_ov7670, 1433 if (write_regvals(sd, mode_init_519_ov7670,
1463 ARRAY_SIZE(mode_init_519_ov7670))) 1434 ARRAY_SIZE(mode_init_519_ov7670)))
1464 return -EIO; 1435 return -EIO;
1465 } 1436 }
1466 1437
1467 if (sd->sensor == SEN_OV7640) { 1438 reg_w(sd, OV519_CAM_H_SIZE, sd->gspca_dev.width >> 4);
1468 /* Select 8-bit input mode */ 1439 reg_w(sd, OV519_CAM_V_SIZE, sd->gspca_dev.height >> 3);
1469 reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10);
1470 }
1471
1472 reg_w(sd, OV519_CAM_H_SIZE, width >> 4);
1473 reg_w(sd, OV519_CAM_V_SIZE, height >> 3);
1474 reg_w(sd, OV519_CAM_X_OFFSETL, 0x00); 1440 reg_w(sd, OV519_CAM_X_OFFSETL, 0x00);
1475 reg_w(sd, OV519_CAM_X_OFFSETH, 0x00); 1441 reg_w(sd, OV519_CAM_X_OFFSETH, 0x00);
1476 reg_w(sd, OV519_CAM_Y_OFFSETL, 0x00); 1442 reg_w(sd, OV519_CAM_Y_OFFSETL, 0x00);
@@ -1485,9 +1451,10 @@ static int ov519_mode_init_regs(struct sd *sd,
1485 1451
1486/* FIXME: These are only valid at the max resolution. */ 1452/* FIXME: These are only valid at the max resolution. */
1487 sd->clockdiv = 0; 1453 sd->clockdiv = 0;
1488 if (sd->sensor == SEN_OV7640) { 1454 switch (sd->sensor) {
1455 case SEN_OV7640:
1489 switch (sd->frame_rate) { 1456 switch (sd->frame_rate) {
1490/*jfm: default was 30 fps */ 1457/*fixme: default was 30 fps */
1491 case 30: 1458 case 30:
1492 reg_w(sd, 0xa4, 0x0c); 1459 reg_w(sd, 0xa4, 0x0c);
1493 reg_w(sd, 0x23, 0xff); 1460 reg_w(sd, 0x23, 0xff);
@@ -1517,7 +1484,8 @@ static int ov519_mode_init_regs(struct sd *sd,
1517 sd->clockdiv = 1; 1484 sd->clockdiv = 1;
1518 break; 1485 break;
1519 } 1486 }
1520 } else if (sd->sensor == SEN_OV8610) { 1487 break;
1488 case SEN_OV8610:
1521 switch (sd->frame_rate) { 1489 switch (sd->frame_rate) {
1522 default: /* 15 fps */ 1490 default: /* 15 fps */
1523/* case 15: */ 1491/* case 15: */
@@ -1533,41 +1501,37 @@ static int ov519_mode_init_regs(struct sd *sd,
1533 reg_w(sd, 0x23, 0x1b); 1501 reg_w(sd, 0x23, 0x1b);
1534 break; 1502 break;
1535 } 1503 }
1536 sd->clockdiv = 0; 1504 break;
1537 } else if (sd->sensor == SEN_OV7670) { /* guesses, based on 7640 */ 1505 case SEN_OV7670: /* guesses, based on 7640 */
1538 PDEBUG(D_STREAM, "Setting framerate to %d fps", 1506 PDEBUG(D_STREAM, "Setting framerate to %d fps",
1539 (sd->frame_rate == 0) ? 15 : sd->frame_rate); 1507 (sd->frame_rate == 0) ? 15 : sd->frame_rate);
1508 reg_w(sd, 0xa4, 0x10);
1540 switch (sd->frame_rate) { 1509 switch (sd->frame_rate) {
1541 case 30: 1510 case 30:
1542 reg_w(sd, 0xa4, 0x10);
1543 reg_w(sd, 0x23, 0xff); 1511 reg_w(sd, 0x23, 0xff);
1544 break; 1512 break;
1545 case 20: 1513 case 20:
1546 reg_w(sd, 0xa4, 0x10);
1547 reg_w(sd, 0x23, 0x1b); 1514 reg_w(sd, 0x23, 0x1b);
1548 break; 1515 break;
1549 default: /* 15 fps */ 1516 default:
1550/* case 15: */ 1517/* case 15: */
1551 reg_w(sd, 0xa4, 0x10);
1552 reg_w(sd, 0x23, 0xff); 1518 reg_w(sd, 0x23, 0xff);
1553 sd->clockdiv = 1; 1519 sd->clockdiv = 1;
1554 break; 1520 break;
1555 } 1521 }
1522 break;
1556 } 1523 }
1557 1524
1558/* if (ov51x_restart(sd) < 0)
1559 return -EIO; */
1560
1561 /* Reset it just for good measure */
1562/* if (ov51x_reset(sd, OV511_RESET_NOREGS) < 0)
1563 return -EIO; */
1564 return 0; 1525 return 0;
1565} 1526}
1566 1527
1567static int mode_init_ov_sensor_regs(struct sd *sd, 1528static int mode_init_ov_sensor_regs(struct sd *sd)
1568 struct ovsensor_window *win)
1569{ 1529{
1570 int qvga = win->quarter; 1530 struct gspca_dev *gspca_dev;
1531 int qvga;
1532
1533 gspca_dev = &sd->gspca_dev;
1534 qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1571 1535
1572 /******** Mode (VGA/QVGA) and sensor specific regs ********/ 1536 /******** Mode (VGA/QVGA) and sensor specific regs ********/
1573 switch (sd->sensor) { 1537 switch (sd->sensor) {
@@ -1611,8 +1575,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
1611 OV7670_COM7_FMT_MASK); 1575 OV7670_COM7_FMT_MASK);
1612 break; 1576 break;
1613 case SEN_OV6620: 1577 case SEN_OV6620:
1614 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1615 break;
1616 case SEN_OV6630: 1578 case SEN_OV6630:
1617 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 1579 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1618 break; 1580 break;
@@ -1621,24 +1583,21 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
1621 } 1583 }
1622 1584
1623 /******** Palette-specific regs ********/ 1585 /******** Palette-specific regs ********/
1624/* Need to do work here for the OV7670 */ 1586 if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
1625 1587 /* not valid on the OV6620/OV7620/6630? */
1626 if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { 1588 i2c_w_mask(sd, 0x0e, 0x00, 0x40);
1627 /* not valid on the OV6620/OV7620/6630? */ 1589 }
1628 i2c_w_mask(sd, 0x0e, 0x00, 0x40);
1629 }
1630 1590
1631 /* The OV518 needs special treatment. Although both the OV518 1591 /* The OV518 needs special treatment. Although both the OV518
1632 * and the OV6630 support a 16-bit video bus, only the 8 bit Y 1592 * and the OV6630 support a 16-bit video bus, only the 8 bit Y
1633 * bus is actually used. The UV bus is tied to ground. 1593 * bus is actually used. The UV bus is tied to ground.
1634 * Therefore, the OV6630 needs to be in 8-bit multiplexed 1594 * Therefore, the OV6630 needs to be in 8-bit multiplexed
1635 * output mode */ 1595 * output mode */
1636 1596
1637 /* OV7640 is 8-bit only */ 1597 /* OV7640 is 8-bit only */
1638 1598
1639 if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640) 1599 if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640)
1640 i2c_w_mask(sd, 0x13, 0x00, 0x20); 1600 i2c_w_mask(sd, 0x13, 0x00, 0x20);
1641/* } */
1642 1601
1643 /******** Clock programming ********/ 1602 /******** Clock programming ********/
1644 /* The OV6620 needs special handling. This prevents the 1603 /* The OV6620 needs special handling. This prevents the
@@ -1647,14 +1606,14 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
1647 1606
1648 /* Clock down */ 1607 /* Clock down */
1649 i2c_w(sd, 0x2a, 0x04); 1608 i2c_w(sd, 0x2a, 0x04);
1650 i2c_w(sd, 0x11, win->clockdiv); 1609 i2c_w(sd, 0x11, sd->clockdiv);
1651 i2c_w(sd, 0x2a, 0x84); 1610 i2c_w(sd, 0x2a, 0x84);
1652 /* This next setting is critical. It seems to improve 1611 /* This next setting is critical. It seems to improve
1653 * the gain or the contrast. The "reserved" bits seem 1612 * the gain or the contrast. The "reserved" bits seem
1654 * to have some effect in this case. */ 1613 * to have some effect in this case. */
1655 i2c_w(sd, 0x2d, 0x85); 1614 i2c_w(sd, 0x2d, 0x85);
1656 } else if (win->clockdiv >= 0) { 1615 } else if (sd->clockdiv >= 0) {
1657 i2c_w(sd, 0x11, win->clockdiv); 1616 i2c_w(sd, 0x11, sd->clockdiv);
1658 } 1617 }
1659 1618
1660 /******** Special Features ********/ 1619 /******** Special Features ********/
@@ -1674,7 +1633,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
1674 /* is fully tested. */ 1633 /* is fully tested. */
1675 /* 7620/6620/6630? don't have register 0x35, so play it safe */ 1634 /* 7620/6620/6630? don't have register 0x35, so play it safe */
1676 if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { 1635 if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
1677 if (win->width == 640 /*&& win->height == 480*/) 1636 if (!qvga)
1678 i2c_w(sd, 0x35, 0x9e); 1637 i2c_w(sd, 0x35, 0x9e);
1679 else 1638 else
1680 i2c_w(sd, 0x35, 0x1e); 1639 i2c_w(sd, 0x35, 0x1e);
@@ -1682,13 +1641,31 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
1682 return 0; 1641 return 0;
1683} 1642}
1684 1643
1685static int set_ov_sensor_window(struct sd *sd, 1644static void sethvflip(struct sd *sd)
1686 struct ovsensor_window *win)
1687{ 1645{
1646 if (sd->sensor != SEN_OV7670)
1647 return;
1648 if (sd->gspca_dev.streaming)
1649 ov51x_stop(sd);
1650 i2c_w_mask(sd, OV7670_REG_MVFP,
1651 OV7670_MVFP_MIRROR * sd->hflip
1652 | OV7670_MVFP_VFLIP * sd->vflip,
1653 OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
1654 if (sd->gspca_dev.streaming)
1655 ov51x_restart(sd);
1656}
1657
1658static int set_ov_sensor_window(struct sd *sd)
1659{
1660 struct gspca_dev *gspca_dev;
1661 int qvga;
1688 int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; 1662 int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
1689 int ret, hstart, hstop, vstop, vstart; 1663 int ret, hstart, hstop, vstop, vstart;
1690 __u8 v; 1664 __u8 v;
1691 1665
1666 gspca_dev = &sd->gspca_dev;
1667 qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1668
1692 /* The different sensor ICs handle setting up of window differently. 1669 /* The different sensor ICs handle setting up of window differently.
1693 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ 1670 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
1694 switch (sd->sensor) { 1671 switch (sd->sensor) {
@@ -1733,7 +1710,7 @@ static int set_ov_sensor_window(struct sd *sd,
1733 switch (sd->sensor) { 1710 switch (sd->sensor) {
1734 case SEN_OV6620: 1711 case SEN_OV6620:
1735 case SEN_OV6630: 1712 case SEN_OV6630:
1736 if (win->quarter) { /* QCIF */ 1713 if (qvga) { /* QCIF */
1737 hwscale = 0; 1714 hwscale = 0;
1738 vwscale = 0; 1715 vwscale = 0;
1739 } else { /* CIF */ 1716 } else { /* CIF */
@@ -1743,7 +1720,7 @@ static int set_ov_sensor_window(struct sd *sd,
1743 } 1720 }
1744 break; 1721 break;
1745 case SEN_OV8610: 1722 case SEN_OV8610:
1746 if (win->quarter) { /* QSVGA */ 1723 if (qvga) { /* QSVGA */
1747 hwscale = 1; 1724 hwscale = 1;
1748 vwscale = 1; 1725 vwscale = 1;
1749 } else { /* SVGA */ 1726 } else { /* SVGA */
@@ -1752,7 +1729,7 @@ static int set_ov_sensor_window(struct sd *sd,
1752 } 1729 }
1753 break; 1730 break;
1754 default: /* SEN_OV7xx0 */ 1731 default: /* SEN_OV7xx0 */
1755 if (win->quarter) { /* QVGA */ 1732 if (qvga) { /* QVGA */
1756 hwscale = 1; 1733 hwscale = 1;
1757 vwscale = 0; 1734 vwscale = 0;
1758 } else { /* VGA */ 1735 } else { /* VGA */
@@ -1761,7 +1738,7 @@ static int set_ov_sensor_window(struct sd *sd,
1761 } 1738 }
1762 } 1739 }
1763 1740
1764 ret = mode_init_ov_sensor_regs(sd, win); 1741 ret = mode_init_ov_sensor_regs(sd);
1765 if (ret < 0) 1742 if (ret < 0)
1766 return ret; 1743 return ret;
1767 1744
@@ -1782,7 +1759,7 @@ static int set_ov_sensor_window(struct sd *sd,
1782 /* I can hard code this for OV7670s */ 1759 /* I can hard code this for OV7670s */
1783 /* Yes, these numbers do look odd, but they're tested and work! */ 1760 /* Yes, these numbers do look odd, but they're tested and work! */
1784 if (sd->sensor == SEN_OV7670) { 1761 if (sd->sensor == SEN_OV7670) {
1785 if (win->quarter) { /* QVGA from ov7670.c by 1762 if (qvga) { /* QVGA from ov7670.c by
1786 * Jonathan Corbet */ 1763 * Jonathan Corbet */
1787 hstart = 164; 1764 hstart = 164;
1788 hstop = 20; 1765 hstop = 20;
@@ -1796,75 +1773,45 @@ static int set_ov_sensor_window(struct sd *sd,
1796 } 1773 }
1797 /* OV7670 hardware window registers are split across 1774 /* OV7670 hardware window registers are split across
1798 * multiple locations */ 1775 * multiple locations */
1799 i2c_w(sd, OV7670_REG_HSTART, (hstart >> 3) & 0xff); 1776 i2c_w(sd, OV7670_REG_HSTART, hstart >> 3);
1800 i2c_w(sd, OV7670_REG_HSTOP, (hstop >> 3) & 0xff); 1777 i2c_w(sd, OV7670_REG_HSTOP, hstop >> 3);
1801 v = i2c_r(sd, OV7670_REG_HREF); 1778 v = i2c_r(sd, OV7670_REG_HREF);
1802 v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07); 1779 v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07);
1803 msleep(10); /* need to sleep between read and write to 1780 msleep(10); /* need to sleep between read and write to
1804 * same reg! */ 1781 * same reg! */
1805 i2c_w(sd, OV7670_REG_HREF, v); 1782 i2c_w(sd, OV7670_REG_HREF, v);
1806 1783
1807 i2c_w(sd, OV7670_REG_VSTART, (vstart >> 2) & 0xff); 1784 i2c_w(sd, OV7670_REG_VSTART, vstart >> 2);
1808 i2c_w(sd, OV7670_REG_VSTOP, (vstop >> 2) & 0xff); 1785 i2c_w(sd, OV7670_REG_VSTOP, vstop >> 2);
1809 v = i2c_r(sd, OV7670_REG_VREF); 1786 v = i2c_r(sd, OV7670_REG_VREF);
1810 v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03); 1787 v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03);
1811 msleep(10); /* need to sleep between read and write to 1788 msleep(10); /* need to sleep between read and write to
1812 * same reg! */ 1789 * same reg! */
1813 i2c_w(sd, OV7670_REG_VREF, v); 1790 i2c_w(sd, OV7670_REG_VREF, v);
1814 1791 sethvflip(sd);
1815 } else { 1792 } else {
1816 i2c_w(sd, 0x17, hwsbase + (win->x >> hwscale)); 1793 i2c_w(sd, 0x17, hwsbase);
1817 i2c_w(sd, 0x18, hwebase + ((win->x + win->width) >> hwscale)); 1794 i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale));
1818 i2c_w(sd, 0x19, vwsbase + (win->y >> vwscale)); 1795 i2c_w(sd, 0x19, vwsbase);
1819 i2c_w(sd, 0x1a, vwebase + ((win->y + win->height) >> vwscale)); 1796 i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale));
1820 } 1797 }
1821 return 0; 1798 return 0;
1822} 1799}
1823 1800
1824static int ov_sensor_mode_setup(struct sd *sd,
1825 int width, int height)
1826{
1827 struct ovsensor_window win;
1828
1829/* win.format = mode; */
1830
1831 /* Unless subcapture is enabled,
1832 * center the image window and downsample
1833 * if possible to increase the field of view */
1834 /* NOTE: OV518(+) and OV519 does downsampling on its own */
1835 win.width = width;
1836 win.height = height;
1837 if (width == sd->maxwidth)
1838 win.quarter = 0;
1839 else
1840 win.quarter = 1;
1841
1842 /* Center it */
1843 win.x = (win.width - width) / 2;
1844 win.y = (win.height - height) / 2;
1845
1846 /* Clock is determined by OV519 frame rate code */
1847 win.clockdiv = sd->clockdiv;
1848
1849 PDEBUG(D_CONF, "Setting clock divider to %d", win.clockdiv);
1850 return set_ov_sensor_window(sd, &win);
1851}
1852
1853/* -- start the camera -- */ 1801/* -- start the camera -- */
1854static void sd_start(struct gspca_dev *gspca_dev) 1802static void sd_start(struct gspca_dev *gspca_dev)
1855{ 1803{
1856 struct sd *sd = (struct sd *) gspca_dev; 1804 struct sd *sd = (struct sd *) gspca_dev;
1857 int ret; 1805 int ret;
1858 1806
1859 1807 ret = ov519_mode_init_regs(sd);
1860 ret = ov519_mode_init_regs(sd, gspca_dev->width, gspca_dev->height);
1861 if (ret < 0) 1808 if (ret < 0)
1862 goto out; 1809 goto out;
1863 ret = ov_sensor_mode_setup(sd, gspca_dev->width, gspca_dev->height); 1810 ret = set_ov_sensor_window(sd);
1864 if (ret < 0) 1811 if (ret < 0)
1865 goto out; 1812 goto out;
1866 1813
1867 ret = ov51x_restart((struct sd *) gspca_dev); 1814 ret = ov51x_restart(sd);
1868 if (ret < 0) 1815 if (ret < 0)
1869 goto out; 1816 goto out;
1870 PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); 1817 PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
@@ -1938,12 +1885,10 @@ static void setbrightness(struct gspca_dev *gspca_dev)
1938{ 1885{
1939 struct sd *sd = (struct sd *) gspca_dev; 1886 struct sd *sd = (struct sd *) gspca_dev;
1940 int val; 1887 int val;
1941/* int was_streaming; */
1942 1888
1943 val = sd->brightness; 1889 val = sd->brightness;
1944 PDEBUG(D_CONF, "brightness:%d", val); 1890 PDEBUG(D_CONF, "brightness:%d", val);
1945/* was_streaming = gspca_dev->streaming; 1891/* if (gspca_dev->streaming)
1946 * if (was_streaming)
1947 * ov51x_stop(sd); */ 1892 * ov51x_stop(sd); */
1948 switch (sd->sensor) { 1893 switch (sd->sensor) {
1949 case SEN_OV8610: 1894 case SEN_OV8610:
@@ -1961,12 +1906,12 @@ static void setbrightness(struct gspca_dev *gspca_dev)
1961 i2c_w(sd, OV7610_REG_BRT, val); 1906 i2c_w(sd, OV7610_REG_BRT, val);
1962 break; 1907 break;
1963 case SEN_OV7670: 1908 case SEN_OV7670:
1964/*jfm - from windblows 1909/*win trace
1965 * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */ 1910 * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */
1966 i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val)); 1911 i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val));
1967 break; 1912 break;
1968 } 1913 }
1969/* if (was_streaming) 1914/* if (gspca_dev->streaming)
1970 * ov51x_restart(sd); */ 1915 * ov51x_restart(sd); */
1971} 1916}
1972 1917
@@ -1974,12 +1919,10 @@ static void setcontrast(struct gspca_dev *gspca_dev)
1974{ 1919{
1975 struct sd *sd = (struct sd *) gspca_dev; 1920 struct sd *sd = (struct sd *) gspca_dev;
1976 int val; 1921 int val;
1977/* int was_streaming; */
1978 1922
1979 val = sd->contrast; 1923 val = sd->contrast;
1980 PDEBUG(D_CONF, "contrast:%d", val); 1924 PDEBUG(D_CONF, "contrast:%d", val);
1981/* was_streaming = gspca_dev->streaming; 1925/* if (gspca_dev->streaming)
1982 if (was_streaming)
1983 ov51x_stop(sd); */ 1926 ov51x_stop(sd); */
1984 switch (sd->sensor) { 1927 switch (sd->sensor) {
1985 case SEN_OV7610: 1928 case SEN_OV7610:
@@ -2016,7 +1959,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
2016 i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); 1959 i2c_w(sd, OV7670_REG_CONTRAS, val >> 1);
2017 break; 1960 break;
2018 } 1961 }
2019/* if (was_streaming) 1962/* if (gspca_dev->streaming)
2020 ov51x_restart(sd); */ 1963 ov51x_restart(sd); */
2021} 1964}
2022 1965
@@ -2024,12 +1967,10 @@ static void setcolors(struct gspca_dev *gspca_dev)
2024{ 1967{
2025 struct sd *sd = (struct sd *) gspca_dev; 1968 struct sd *sd = (struct sd *) gspca_dev;
2026 int val; 1969 int val;
2027/* int was_streaming; */
2028 1970
2029 val = sd->colors; 1971 val = sd->colors;
2030 PDEBUG(D_CONF, "saturation:%d", val); 1972 PDEBUG(D_CONF, "saturation:%d", val);
2031/* was_streaming = gspca_dev->streaming; 1973/* if (gspca_dev->streaming)
2032 if (was_streaming)
2033 ov51x_stop(sd); */ 1974 ov51x_stop(sd); */
2034 switch (sd->sensor) { 1975 switch (sd->sensor) {
2035 case SEN_OV8610: 1976 case SEN_OV8610:
@@ -2055,7 +1996,7 @@ static void setcolors(struct gspca_dev *gspca_dev)
2055 /* set REG_COM13 values for UV sat auto mode */ 1996 /* set REG_COM13 values for UV sat auto mode */
2056 break; 1997 break;
2057 } 1998 }
2058/* if (was_streaming) 1999/* if (gspca_dev->streaming)
2059 ov51x_restart(sd); */ 2000 ov51x_restart(sd); */
2060} 2001}
2061 2002
@@ -2110,6 +2051,40 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
2110 return 0; 2051 return 0;
2111} 2052}
2112 2053
2054static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
2055{
2056 struct sd *sd = (struct sd *) gspca_dev;
2057
2058 sd->hflip = val;
2059 sethvflip(sd);
2060 return 0;
2061}
2062
2063static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
2064{
2065 struct sd *sd = (struct sd *) gspca_dev;
2066
2067 *val = sd->hflip;
2068 return 0;
2069}
2070
2071static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
2072{
2073 struct sd *sd = (struct sd *) gspca_dev;
2074
2075 sd->vflip = val;
2076 sethvflip(sd);
2077 return 0;
2078}
2079
2080static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
2081{
2082 struct sd *sd = (struct sd *) gspca_dev;
2083
2084 *val = sd->vflip;
2085 return 0;
2086}
2087
2113/* sub-driver description */ 2088/* sub-driver description */
2114static const struct sd_desc sd_desc = { 2089static const struct sd_desc sd_desc = {
2115 .name = MODULE_NAME, 2090 .name = MODULE_NAME,
@@ -2178,4 +2153,3 @@ module_exit(sd_mod_exit);
2178 2153
2179module_param(frame_rate, int, 0644); 2154module_param(frame_rate, int, 0644);
2180MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)"); 2155MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");
2181
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index ea3d7021f401..815bea6edc44 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -31,7 +31,9 @@ MODULE_LICENSE("GPL");
31struct sd { 31struct sd {
32 struct gspca_dev gspca_dev; /* !! must be the first item */ 32 struct gspca_dev gspca_dev; /* !! must be the first item */
33 33
34 int avg_lum; 34 int lum_sum;
35 atomic_t avg_lum;
36 atomic_t do_gain;
35 37
36 unsigned char brightness; 38 unsigned char brightness;
37 unsigned char contrast; 39 unsigned char contrast;
@@ -271,6 +273,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
271 sd->contrast = CONTRAST_DEF; 273 sd->contrast = CONTRAST_DEF;
272 sd->colors = COLOR_DEF; 274 sd->colors = COLOR_DEF;
273 sd->autogain = AUTOGAIN_DEF; 275 sd->autogain = AUTOGAIN_DEF;
276 sd->ag_cnt = -1;
274 return 0; 277 return 0;
275} 278}
276 279
@@ -311,6 +314,18 @@ static void setcolors(struct gspca_dev *gspca_dev)
311 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); 314 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
312} 315}
313 316
317static void setautogain(struct gspca_dev *gspca_dev)
318{
319 struct sd *sd = (struct sd *) gspca_dev;
320
321 if (sd->autogain) {
322 sd->lum_sum = 0;
323 sd->ag_cnt = AG_CNT_START;
324 } else {
325 sd->ag_cnt = -1;
326 }
327}
328
314/* this function is called at open time */ 329/* this function is called at open time */
315static int sd_open(struct gspca_dev *gspca_dev) 330static int sd_open(struct gspca_dev *gspca_dev)
316{ 331{
@@ -320,8 +335,6 @@ static int sd_open(struct gspca_dev *gspca_dev)
320 335
321static void sd_start(struct gspca_dev *gspca_dev) 336static void sd_start(struct gspca_dev *gspca_dev)
322{ 337{
323 struct sd *sd = (struct sd *) gspca_dev;
324
325 reg_w(gspca_dev, 0xff, 0x01); 338 reg_w(gspca_dev, 0xff, 0x01);
326 reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8); 339 reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
327 reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8); 340 reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
@@ -394,6 +407,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
394 setcontrast(gspca_dev); 407 setcontrast(gspca_dev);
395 setbrightness(gspca_dev); 408 setbrightness(gspca_dev);
396 setcolors(gspca_dev); 409 setcolors(gspca_dev);
410 setautogain(gspca_dev);
397 411
398 /* set correct resolution */ 412 /* set correct resolution */
399 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { 413 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
@@ -431,13 +445,6 @@ static void sd_start(struct gspca_dev *gspca_dev)
431 reg_w(gspca_dev, 0xff, 0x01); 445 reg_w(gspca_dev, 0xff, 0x01);
432 reg_w(gspca_dev, 0x78, 0x04); 446 reg_w(gspca_dev, 0x78, 0x04);
433 reg_w(gspca_dev, 0x78, 0x05); 447 reg_w(gspca_dev, 0x78, 0x05);
434
435 if (sd->autogain) {
436 sd->ag_cnt = AG_CNT_START;
437 sd->avg_lum = 0;
438 } else {
439 sd->ag_cnt = -1;
440 }
441} 448}
442 449
443static void sd_stopN(struct gspca_dev *gspca_dev) 450static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -473,13 +480,20 @@ static void sd_close(struct gspca_dev *gspca_dev)
473 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ 480 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
474} 481}
475 482
476static void setautogain(struct gspca_dev *gspca_dev, int luma) 483static void do_autogain(struct gspca_dev *gspca_dev)
477{ 484{
485 struct sd *sd = (struct sd *) gspca_dev;
486 int luma;
478 int luma_mean = 128; 487 int luma_mean = 128;
479 int luma_delta = 20; 488 int luma_delta = 20;
480 __u8 spring = 5; 489 __u8 spring = 5;
481 int Gbright; 490 int Gbright;
482 491
492 if (!atomic_read(&sd->do_gain))
493 return;
494 atomic_set(&sd->do_gain, 0);
495
496 luma = atomic_read(&sd->avg_lum);
483 Gbright = reg_r(gspca_dev, 0x02); 497 Gbright = reg_r(gspca_dev, 0x02);
484 PDEBUG(D_FRAM, "luma mean %d", luma); 498 PDEBUG(D_FRAM, "luma mean %d", luma);
485 if (luma < luma_mean - luma_delta || 499 if (luma < luma_mean - luma_delta ||
@@ -523,12 +537,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
523 537
524 /* start of frame */ 538 /* start of frame */
525 if (sd->ag_cnt >= 0 && p > 28) { 539 if (sd->ag_cnt >= 0 && p > 28) {
526 sd->avg_lum += data[p - 23]; 540 sd->lum_sum += data[p - 23];
527 if (--sd->ag_cnt < 0) { 541 if (--sd->ag_cnt < 0) {
528 sd->ag_cnt = AG_CNT_START; 542 sd->ag_cnt = AG_CNT_START;
529 setautogain(gspca_dev, 543 atomic_set(&sd->avg_lum,
530 sd->avg_lum / AG_CNT_START); 544 sd->lum_sum / AG_CNT_START);
531 sd->avg_lum = 0; 545 sd->lum_sum = 0;
546 atomic_set(&sd->do_gain, 1);
532 } 547 }
533 } 548 }
534 549
@@ -677,12 +692,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
677 struct sd *sd = (struct sd *) gspca_dev; 692 struct sd *sd = (struct sd *) gspca_dev;
678 693
679 sd->autogain = val; 694 sd->autogain = val;
680 if (val) { 695 if (gspca_dev->streaming)
681 sd->ag_cnt = AG_CNT_START; 696 setautogain(gspca_dev);
682 sd->avg_lum = 0;
683 } else {
684 sd->ag_cnt = -1;
685 }
686 return 0; 697 return 0;
687} 698}
688 699
@@ -706,6 +717,7 @@ static struct sd_desc sd_desc = {
706 .stop0 = sd_stop0, 717 .stop0 = sd_stop0,
707 .close = sd_close, 718 .close = sd_close,
708 .pkt_scan = sd_pkt_scan, 719 .pkt_scan = sd_pkt_scan,
720 .dq_callback = do_autogain,
709}; 721};
710 722
711/* -- module initialisation -- */ 723/* -- module initialisation -- */
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index e18748c5a14d..11210c71f66c 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -408,7 +408,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
408 const __u8 *buffer, 408 const __u8 *buffer,
409 int len) 409 int len)
410{ 410{
411#ifdef CONFIG_VIDEO_ADV_DEBUG 411#ifdef GSPCA_DEBUG
412 if (len > sizeof gspca_dev->usb_buf) { 412 if (len > sizeof gspca_dev->usb_buf) {
413 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow"); 413 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
414 return; 414 return;
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index 33a3df1f6915..245a30ec5fb1 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -32,7 +32,7 @@ MODULE_LICENSE("GPL");
32struct sd { 32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */ 33 struct gspca_dev gspca_dev; /* !! must be the first item */
34 34
35 int avg_lum; 35 atomic_t avg_lum;
36 unsigned int exposure; 36 unsigned int exposure;
37 37
38 unsigned short brightness; 38 unsigned short brightness;
@@ -148,55 +148,58 @@ static struct v4l2_pix_format vga_mode[] = {
148 148
149/*Data from sn9c102p+hv71331r */ 149/*Data from sn9c102p+hv71331r */
150static const __u8 sn_hv7131[] = { 150static const __u8 sn_hv7131[] = {
151/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */ 151/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
152 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11, 152 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
153/* rega regb regc regd rege regf reg10 reg11 */ 153/* reg8 reg9 rega regb regc regd rege regf */
154 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */ 154 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
155/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */ 155/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
156 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00, 156 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
157/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */ 157/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 158 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
159}; 159};
160 160
161static const __u8 sn_mi0360[] = { 161static const __u8 sn_mi0360[] = {
162/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */ 162/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
163 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d, 163 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
164/* rega regb regc regd rege regf reg10 reg11 */ 164/* reg8 reg9 rega regb regc regd rege regf */
165 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 165 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
166/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */ 166/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
167 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00, 167 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
168/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */ 168/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 169 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
170}; 170};
171 171
172static const __u8 sn_mo4000[] = { 172static const __u8 sn_mo4000[] = {
173/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */ 173/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
174 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81, 174 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
175/* reg9 rega regb regc regd rege regf reg10 reg11*/ 175/* reg8 reg9 rega regb regc regd rege regf */
176 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 176 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/ 177/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
178 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00, 178 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
179/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/ 179/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b, 180 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
181 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
182 0xd3, 0xdf, 0xea, 0xf5
183}; 181};
184 182
185static const __u8 sn_ov7648[] = { 183static const __u8 sn_ov7648[] = {
186 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65, 184/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
187 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82, 185 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
188 0x07, 0x00, 0x00, 0x00, 0x00, 0x00 186/* reg8 reg9 rega regb regc regd rege regf */
187 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
188/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
189 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
190/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
191 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
189}; 192};
190 193
191static const __u8 sn_ov7660[] = { 194static const __u8 sn_ov7660[] = {
192/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */ 195/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
193 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81, 196 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
194/* reg9 rega regb regc regd rege regf reg10 reg11*/ 197/* reg8 reg9 rega regb regc regd rege regf */
195 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 198 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
196/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/ 199/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
197 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00, 200 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
198/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/ 201/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 202 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200}; 203};
201 204
202/* sequence specific to the sensors - !! index = SENSOR_xxx */ 205/* sequence specific to the sensors - !! index = SENSOR_xxx */
@@ -212,10 +215,6 @@ static const __u8 regsn20[] = {
212 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, 215 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
213 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff 216 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
214}; 217};
215static const __u8 regsn20_sn9c120[] = {
216 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
217 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
218};
219static const __u8 regsn20_sn9c325[] = { 218static const __u8 regsn20_sn9c325[] = {
220 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4, 219 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
221 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5 220 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
@@ -227,21 +226,6 @@ static const __u8 reg84[] = {
227/* 0x00, 0x00, 0x00, 0x00, 0x00 */ 226/* 0x00, 0x00, 0x00, 0x00, 0x00 */
228 0xf7, 0x0f, 0x0a, 0x00, 0x00 227 0xf7, 0x0f, 0x0a, 0x00, 0x00
229}; 228};
230static const __u8 reg84_sn9c120_1[] = {
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x0c, 0x00, 0x00
234};
235static const __u8 reg84_sn9c120_2[] = {
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x0c, 0x02, 0x3b
239};
240static const __u8 reg84_sn9c120_3[] = {
241 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
242 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
243 0xf5, 0x0f, 0x0c, 0x02, 0x3b
244};
245static const __u8 reg84_sn9c325[] = { 229static const __u8 reg84_sn9c325[] = {
246 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f, 230 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
247 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f, 231 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
@@ -360,17 +344,15 @@ static const __u8 ov7660_sensor_init[][8] = {
360 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */ 344 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
361/* (delay 20ms) */ 345/* (delay 20ms) */
362 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10}, 346 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
363 /* Outformat ?? rawRGB */ 347 /* Outformat = rawRGB */
364 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */ 348 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
365 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10}, 349 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
366/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
367 /* GAIN BLUE RED VREF */ 350 /* GAIN BLUE RED VREF */
368 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10}, 351 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
369 /* COM 1 BAVE GEAVE AECHH */ 352 /* COM 1 BAVE GEAVE AECHH */
370 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */ 353 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
371 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */ 354 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
372 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10}, 355 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
373/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
374 /* AECH CLKRC COM7 COM8 */ 356 /* AECH CLKRC COM7 COM8 */
375 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */ 357 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
376 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10}, 358 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
@@ -379,8 +361,8 @@ static const __u8 ov7660_sensor_init[][8] = {
379 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */ 361 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
380 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10}, 362 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
381 /* BOS GBOS GROS ROS (BGGR offset) */ 363 /* BOS GBOS GROS ROS (BGGR offset) */
382 {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, 364/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
383/* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */ 365 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
384 /* AEW AEB VPT BBIAS */ 366 /* AEW AEB VPT BBIAS */
385 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10}, 367 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
386 /* GbBIAS RSVD EXHCH EXHCL */ 368 /* GbBIAS RSVD EXHCH EXHCL */
@@ -407,9 +389,9 @@ static const __u8 ov7660_sensor_init[][8] = {
407 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10}, 389 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
408 /* LCC1 LCC2 LCC3 LCC4 */ 390 /* LCC1 LCC2 LCC3 LCC4 */
409 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */ 391 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
410 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, 392 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
411 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10}, 393 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
412 /* band gap reference [0..3] DBLV */ 394 /* band gap reference [0:3] DBLV */
413 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */ 395 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
414 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */ 396 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
415 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */ 397 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
@@ -419,37 +401,35 @@ static const __u8 ov7660_sensor_init[][8] = {
419 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */ 401 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
420 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */ 402 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
421 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */ 403 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
422 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, 404 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
423/****** (some exchanges in the win trace) ******/ 405/****** (some exchanges in the win trace) ******/
424 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, 406 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
425 /* bits[3..0]reserved */ 407 /* bits[3..0]reserved */
426 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, 408 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
427 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}, 409 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
428 /* VREF vertical frame ctrl */ 410 /* VREF vertical frame ctrl */
429 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}, 411 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
430 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */ 412 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
431 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, 413 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
432 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, 414 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
433/* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */ 415 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
434 {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10}, 416/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
435 {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
436/****** (some exchanges in the win trace) ******/ 417/****** (some exchanges in the win trace) ******/
437 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */ 418 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
438 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */ 419 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
439 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, 420 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
440 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, 421 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
441 {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, 422/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
442/****** (some exchanges in the win trace) ******/ 423/****** (some exchanges in the win trace) ******/
443/**********startsensor KO if changed !!****/ 424/******!! startsensor KO if changed !!****/
444 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10}, 425 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
445 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10}, 426 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
446 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, 427 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
447 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10}, 428 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
448/* here may start the isoc exchanges */
449 {} 429 {}
450}; 430};
451/* reg0x04 reg0x07 reg 0x10 */ 431/* reg 0x04 reg 0x07 reg 0x10 */
452/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */ 432/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
453 433
454static const __u8 ov7648_sensor_init[][8] = { 434static const __u8 ov7648_sensor_init[][8] = {
455 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00}, 435 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
@@ -680,13 +660,12 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
680 const __u8 *reg9a; 660 const __u8 *reg9a;
681 static const __u8 reg9a_def[] = 661 static const __u8 reg9a_def[] =
682 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04}; 662 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
683 static const __u8 reg9a_sn9c120[] = /* from win trace */
684 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
685 static const __u8 reg9a_sn9c325[] = 663 static const __u8 reg9a_sn9c325[] =
686 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20}; 664 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
665 static const __u8 regd4[] = {0x60, 0x00, 0x00};
687 666
688 reg_w1(gspca_dev, 0xf1, 0x00); 667 reg_w1(gspca_dev, 0xf1, 0x00);
689 reg_w1(gspca_dev, 0x01, sn9c1xx[0]); /*fixme:jfm was [1] en v1*/ 668 reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/
690 669
691 /* configure gpio */ 670 /* configure gpio */
692 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2); 671 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
@@ -696,25 +675,17 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
696 case BRIDGE_SN9C325: 675 case BRIDGE_SN9C325:
697 reg9a = reg9a_sn9c325; 676 reg9a = reg9a_sn9c325;
698 break; 677 break;
699 case BRIDGE_SN9C120:
700 reg9a = reg9a_sn9c120;
701 break;
702 default: 678 default:
703 reg9a = reg9a_def; 679 reg9a = reg9a_def;
704 break; 680 break;
705 } 681 }
706 reg_w(gspca_dev, 0x9a, reg9a, 6); 682 reg_w(gspca_dev, 0x9a, reg9a, 6);
707 683
708 reg_w1(gspca_dev, 0xd4, 0x60); /*fixme:jfm 60 00 00 (3) ? */ 684 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
709 685
710 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); 686 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
711 687
712 switch (sd->bridge) { 688 switch (sd->bridge) {
713 case BRIDGE_SN9C120: /* from win trace */
714 reg_w1(gspca_dev, 0x01, 0x61);
715 reg_w1(gspca_dev, 0x17, 0x20);
716 reg_w1(gspca_dev, 0x01, 0x60);
717 break;
718 case BRIDGE_SN9C325: 689 case BRIDGE_SN9C325:
719 reg_w1(gspca_dev, 0x01, 0x43); 690 reg_w1(gspca_dev, 0x01, 0x43);
720 reg_w1(gspca_dev, 0x17, 0xae); 691 reg_w1(gspca_dev, 0x17, 0xae);
@@ -810,6 +781,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
810 sd->contrast = CONTRAST_DEF; 781 sd->contrast = CONTRAST_DEF;
811 sd->colors = COLOR_DEF; 782 sd->colors = COLOR_DEF;
812 sd->autogain = AUTOGAIN_DEF; 783 sd->autogain = AUTOGAIN_DEF;
784 sd->ag_cnt = -1;
785
813 return 0; 786 return 0;
814} 787}
815 788
@@ -823,10 +796,11 @@ static int sd_open(struct gspca_dev *gspca_dev)
823 796
824 /* setup a selector by bridge */ 797 /* setup a selector by bridge */
825 reg_w1(gspca_dev, 0xf1, 0x01); 798 reg_w1(gspca_dev, 0xf1, 0x01);
826 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
827 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
828 reg_r(gspca_dev, 0x00, 1); 799 reg_r(gspca_dev, 0x00, 1);
800 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
801 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
829 regF1 = gspca_dev->usb_buf[0]; 802 regF1 = gspca_dev->usb_buf[0];
803 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
830 switch (sd->bridge) { 804 switch (sd->bridge) {
831 case BRIDGE_SN9C102P: 805 case BRIDGE_SN9C102P:
832 if (regF1 != 0x11) 806 if (regF1 != 0x11)
@@ -937,15 +911,10 @@ static void setbrightness(struct gspca_dev *gspca_dev)
937 sd->exposure = setexposure(gspca_dev, expo); 911 sd->exposure = setexposure(gspca_dev, expo);
938 break; 912 break;
939 case SENSOR_MI0360: 913 case SENSOR_MI0360:
940 expo = sd->brightness >> 4;
941 sd->exposure = setexposure(gspca_dev, expo);
942 break;
943 case SENSOR_MO4000: 914 case SENSOR_MO4000:
944 expo = sd->brightness >> 4; 915 expo = sd->brightness >> 4;
945 sd->exposure = setexposure(gspca_dev, expo); 916 sd->exposure = setexposure(gspca_dev, expo);
946 break; 917 break;
947 case SENSOR_OV7660:
948 return; /*jfm??*/
949 } 918 }
950 919
951 k2 = sd->brightness >> 10; 920 k2 = sd->brightness >> 10;
@@ -958,8 +927,6 @@ static void setcontrast(struct gspca_dev *gspca_dev)
958 __u8 k2; 927 __u8 k2;
959 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 }; 928 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
960 929
961 if (sd->sensor == SENSOR_OV7660)
962 return; /*jfm??*/
963 k2 = sd->contrast; 930 k2 = sd->contrast;
964 contrast[2] = k2; 931 contrast[2] = k2;
965 contrast[0] = (k2 + 1) >> 1; 932 contrast[0] = (k2 + 1) >> 1;
@@ -981,20 +948,32 @@ static void setcolors(struct gspca_dev *gspca_dev)
981 reg_w1(gspca_dev, 0x05, data); 948 reg_w1(gspca_dev, 0x05, data);
982} 949}
983 950
951static void setautogain(struct gspca_dev *gspca_dev)
952{
953 struct sd *sd = (struct sd *) gspca_dev;
954
955 switch (sd->sensor) {
956 case SENSOR_HV7131R:
957 case SENSOR_MO4000:
958 case SENSOR_MI0360:
959 if (sd->autogain)
960 sd->ag_cnt = AG_CNT_START;
961 else
962 sd->ag_cnt = -1;
963 break;
964 }
965}
966
984/* -- start the camera -- */ 967/* -- start the camera -- */
985static void sd_start(struct gspca_dev *gspca_dev) 968static void sd_start(struct gspca_dev *gspca_dev)
986{ 969{
987 struct sd *sd = (struct sd *) gspca_dev; 970 struct sd *sd = (struct sd *) gspca_dev;
988 int i; 971 int i;
989 __u8 data; 972 __u8 reg1, reg17, reg18;
990 __u8 reg1;
991 __u8 reg17;
992 const __u8 *sn9c1xx; 973 const __u8 *sn9c1xx;
993 int mode; 974 int mode;
994 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; 975 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
995 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; 976 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
996 static const __u8 CA_sn9c120[] =
997 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
998 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ 977 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
999 static const __u8 CE_sn9c325[] = 978 static const __u8 CE_sn9c325[] =
1000 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */ 979 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
@@ -1002,9 +981,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
1002 sn9c1xx = sn_tb[(int) sd->sensor]; 981 sn9c1xx = sn_tb[(int) sd->sensor];
1003 configure_gpio(gspca_dev, sn9c1xx); 982 configure_gpio(gspca_dev, sn9c1xx);
1004 983
1005/*fixme:jfm this sequence should appear at end of sd_start */ 984/* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
1006/* with
1007 reg_w1(gspca_dev, 0x01, 0x44); */
1008 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]); 985 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1009 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]); 986 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1010 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]); 987 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
@@ -1016,20 +993,16 @@ static void sd_start(struct gspca_dev *gspca_dev)
1016 reg_w1(gspca_dev, 0xc7, 0x00); 993 reg_w1(gspca_dev, 0xc7, 0x00);
1017 reg_w1(gspca_dev, 0xc8, 0x50); 994 reg_w1(gspca_dev, 0xc8, 0x50);
1018 reg_w1(gspca_dev, 0xc9, 0x3c); 995 reg_w1(gspca_dev, 0xc9, 0x3c);
1019/*fixme:jfm end of ending sequence */
1020 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); 996 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1021 switch (sd->bridge) { 997 switch (sd->bridge) {
1022 case BRIDGE_SN9C325: 998 case BRIDGE_SN9C325:
1023 data = 0xae; 999 reg17 = 0xae;
1024 break;
1025 case BRIDGE_SN9C120:
1026 data = 0xa0;
1027 break; 1000 break;
1028 default: 1001 default:
1029 data = 0x60; 1002 reg17 = 0x60;
1030 break; 1003 break;
1031 } 1004 }
1032 reg_w1(gspca_dev, 0x17, data); 1005 reg_w1(gspca_dev, 0x17, reg17);
1033 reg_w1(gspca_dev, 0x05, sn9c1xx[5]); 1006 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1034 reg_w1(gspca_dev, 0x07, sn9c1xx[7]); 1007 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1035 reg_w1(gspca_dev, 0x06, sn9c1xx[6]); 1008 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
@@ -1044,20 +1017,6 @@ static void sd_start(struct gspca_dev *gspca_dev)
1044 reg_w1(gspca_dev, 0x9a, 0x0a); 1017 reg_w1(gspca_dev, 0x9a, 0x0a);
1045 reg_w1(gspca_dev, 0x99, 0x60); 1018 reg_w1(gspca_dev, 0x99, 0x60);
1046 break; 1019 break;
1047 case BRIDGE_SN9C120:
1048 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1049 sizeof regsn20_sn9c120);
1050 for (i = 0; i < 2; i++)
1051 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1052 sizeof reg84_sn9c120_1);
1053 for (i = 0; i < 6; i++)
1054 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1055 sizeof reg84_sn9c120_2);
1056 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1057 sizeof reg84_sn9c120_3);
1058 reg_w1(gspca_dev, 0x9a, 0x05);
1059 reg_w1(gspca_dev, 0x99, 0x5b);
1060 break;
1061 default: 1020 default:
1062 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20); 1021 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
1063 for (i = 0; i < 8; i++) 1022 for (i = 0; i < 8; i++)
@@ -1107,22 +1066,14 @@ static void sd_start(struct gspca_dev *gspca_dev)
1107/* reg1 = 0x44; */ 1066/* reg1 = 0x44; */
1108/* reg1 = 0x46; (done) */ 1067/* reg1 = 0x46; (done) */
1109 } else { 1068 } else {
1110 reg17 = 0xa2; /* 640 */ 1069 reg17 = 0x22; /* 640 MCKSIZE */
1111 reg1 = 0x40; 1070 reg1 = 0x06;
1112 } 1071 }
1113 break; 1072 break;
1114 } 1073 }
1115 reg_w(gspca_dev, 0xc0, C0, 6); 1074 reg_w(gspca_dev, 0xc0, C0, 6);
1075 reg_w(gspca_dev, 0xca, CA, 4);
1116 switch (sd->bridge) { 1076 switch (sd->bridge) {
1117 case BRIDGE_SN9C120: /*jfm ?? */
1118 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
1119 break;
1120 default:
1121 reg_w(gspca_dev, 0xca, CA, 4);
1122 break;
1123 }
1124 switch (sd->bridge) {
1125 case BRIDGE_SN9C120: /*jfm ?? */
1126 case BRIDGE_SN9C325: 1077 case BRIDGE_SN9C325:
1127 reg_w(gspca_dev, 0xce, CE_sn9c325, 4); 1078 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
1128 break; 1079 break;
@@ -1133,19 +1084,19 @@ static void sd_start(struct gspca_dev *gspca_dev)
1133 } 1084 }
1134 1085
1135 /* here change size mode 0 -> VGA; 1 -> CIF */ 1086 /* here change size mode 0 -> VGA; 1 -> CIF */
1136 data = 0x40 | sn9c1xx[0x18] | (mode << 4); 1087 reg18 = sn9c1xx[0x18] | (mode << 4);
1137 reg_w1(gspca_dev, 0x18, data); 1088 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
1138 1089
1139 reg_w(gspca_dev, 0x100, qtable4, 0x40); 1090 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1140 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40); 1091 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1141 1092
1142 data = sn9c1xx[0x18] | (mode << 4); 1093 reg_w1(gspca_dev, 0x18, reg18);
1143 reg_w1(gspca_dev, 0x18, data);
1144 1094
1145 reg_w1(gspca_dev, 0x17, reg17); 1095 reg_w1(gspca_dev, 0x17, reg17);
1146 reg_w1(gspca_dev, 0x01, reg1); 1096 reg_w1(gspca_dev, 0x01, reg1);
1147 setbrightness(gspca_dev); 1097 setbrightness(gspca_dev);
1148 setcontrast(gspca_dev); 1098 setcontrast(gspca_dev);
1099 setautogain(gspca_dev);
1149} 1100}
1150 1101
1151static void sd_stopN(struct gspca_dev *gspca_dev) 1102static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1168,12 +1119,11 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
1168 i2c_w8(gspca_dev, stopmi0360); 1119 i2c_w8(gspca_dev, stopmi0360);
1169 data = 0x29; 1120 data = 0x29;
1170 break; 1121 break;
1171 case SENSOR_MO4000:
1172 break;
1173 case SENSOR_OV7648: 1122 case SENSOR_OV7648:
1174 data = 0x29; 1123 data = 0x29;
1175 break; 1124 break;
1176 default: 1125 default:
1126/* case SENSOR_MO4000: */
1177/* case SENSOR_OV7660: */ 1127/* case SENSOR_OV7660: */
1178 break; 1128 break;
1179 } 1129 }
@@ -1193,16 +1143,23 @@ static void sd_close(struct gspca_dev *gspca_dev)
1193{ 1143{
1194} 1144}
1195 1145
1196static void setautogain(struct gspca_dev *gspca_dev) 1146static void do_autogain(struct gspca_dev *gspca_dev)
1197{ 1147{
1198 struct sd *sd = (struct sd *) gspca_dev; 1148 struct sd *sd = (struct sd *) gspca_dev;
1199 /* Thanks S., without your advice, autobright should not work :) */
1200 int delta; 1149 int delta;
1201 int expotimes = 0; 1150 int expotimes;
1202 __u8 luma_mean = 130; 1151 __u8 luma_mean = 130;
1203 __u8 luma_delta = 20; 1152 __u8 luma_delta = 20;
1204 1153
1205 delta = sd->avg_lum; 1154 /* Thanks S., without your advice, autobright should not work :) */
1155 if (sd->ag_cnt < 0)
1156 return;
1157 if (--sd->ag_cnt >= 0)
1158 return;
1159 sd->ag_cnt = AG_CNT_START;
1160
1161 delta = atomic_read(&sd->avg_lum);
1162 PDEBUG(D_FRAM, "mean lum %d", delta);
1206 if (delta < luma_mean - luma_delta || 1163 if (delta < luma_mean - luma_delta ||
1207 delta > luma_mean + luma_delta) { 1164 delta > luma_mean + luma_delta) {
1208 switch (sd->sensor) { 1165 switch (sd->sensor) {
@@ -1214,8 +1171,9 @@ static void setautogain(struct gspca_dev *gspca_dev)
1214 sd->exposure = setexposure(gspca_dev, 1171 sd->exposure = setexposure(gspca_dev,
1215 (unsigned int) (expotimes << 8)); 1172 (unsigned int) (expotimes << 8));
1216 break; 1173 break;
1217 case SENSOR_MO4000: 1174 default:
1218 case SENSOR_MI0360: 1175/* case SENSOR_MO4000: */
1176/* case SENSOR_MI0360: */
1219 expotimes = sd->exposure; 1177 expotimes = sd->exposure;
1220 expotimes += (luma_mean - delta) >> 6; 1178 expotimes += (luma_mean - delta) >> 6;
1221 if (expotimes < 0) 1179 if (expotimes < 0)
@@ -1228,6 +1186,8 @@ static void setautogain(struct gspca_dev *gspca_dev)
1228 } 1186 }
1229} 1187}
1230 1188
1189/* scan the URB packets */
1190/* This function is run at interrupt level. */
1231static void sd_pkt_scan(struct gspca_dev *gspca_dev, 1191static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1232 struct gspca_frame *frame, /* target */ 1192 struct gspca_frame *frame, /* target */
1233 __u8 *data, /* isoc packet */ 1193 __u8 *data, /* isoc packet */
@@ -1244,9 +1204,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1244 frame, data, sof + 2); 1204 frame, data, sof + 2);
1245 if (sd->ag_cnt < 0) 1205 if (sd->ag_cnt < 0)
1246 return; 1206 return;
1247 if (--sd->ag_cnt >= 0)
1248 return;
1249 sd->ag_cnt = AG_CNT_START;
1250/* w1 w2 w3 */ 1207/* w1 w2 w3 */
1251/* w4 w5 w6 */ 1208/* w4 w5 w6 */
1252/* w7 w8 */ 1209/* w7 w8 */
@@ -1261,9 +1218,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1261/* w5 */ 1218/* w5 */
1262 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4; 1219 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1263 avg_lum >>= 4; 1220 avg_lum >>= 4;
1264 sd->avg_lum = avg_lum; 1221 atomic_set(&sd->avg_lum, avg_lum);
1265 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1266 setautogain(gspca_dev);
1267 return; 1222 return;
1268 } 1223 }
1269 if (gspca_dev->last_packet_type == LAST_PACKET) { 1224 if (gspca_dev->last_packet_type == LAST_PACKET) {
@@ -1300,6 +1255,7 @@ static unsigned int getexposure(struct gspca_dev *gspca_dev)
1300 (hexpo << 10) | (mexpo << 2) | lexpo); 1255 (hexpo << 10) | (mexpo << 2) | lexpo);
1301 return (hexpo << 10) | (mexpo << 2) | lexpo; 1256 return (hexpo << 10) | (mexpo << 2) | lexpo;
1302 default: 1257 default:
1258/* case SENSOR_OV7648: * jfm: is it ok for 7648? */
1303/* case SENSOR_OV7660: */ 1259/* case SENSOR_OV7660: */
1304 /* read sensor exposure */ 1260 /* read sensor exposure */
1305 i2c_r5(gspca_dev, 0x04); 1261 i2c_r5(gspca_dev, 0x04);
@@ -1318,14 +1274,12 @@ static void getbrightness(struct gspca_dev *gspca_dev)
1318 /* hardcoded registers seem not readable */ 1274 /* hardcoded registers seem not readable */
1319 switch (sd->sensor) { 1275 switch (sd->sensor) {
1320 case SENSOR_HV7131R: 1276 case SENSOR_HV7131R:
1321/* sd->brightness = 0x7fff; */
1322 sd->brightness = getexposure(gspca_dev) >> 4; 1277 sd->brightness = getexposure(gspca_dev) >> 4;
1323 break; 1278 break;
1324 case SENSOR_MI0360: 1279 case SENSOR_MI0360:
1325 sd->brightness = getexposure(gspca_dev) << 4; 1280 sd->brightness = getexposure(gspca_dev) << 4;
1326 break; 1281 break;
1327 case SENSOR_MO4000: 1282 case SENSOR_MO4000:
1328/* sd->brightness = 0x1fff; */
1329 sd->brightness = getexposure(gspca_dev) << 4; 1283 sd->brightness = getexposure(gspca_dev) << 4;
1330 break; 1284 break;
1331 } 1285 }
@@ -1391,10 +1345,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1391 struct sd *sd = (struct sd *) gspca_dev; 1345 struct sd *sd = (struct sd *) gspca_dev;
1392 1346
1393 sd->autogain = val; 1347 sd->autogain = val;
1394 if (val) 1348 if (gspca_dev->streaming)
1395 sd->ag_cnt = AG_CNT_START; 1349 setautogain(gspca_dev);
1396 else
1397 sd->ag_cnt = -1;
1398 return 0; 1350 return 0;
1399} 1351}
1400 1352
@@ -1418,6 +1370,7 @@ static const struct sd_desc sd_desc = {
1418 .stop0 = sd_stop0, 1370 .stop0 = sd_stop0,
1419 .close = sd_close, 1371 .close = sd_close,
1420 .pkt_scan = sd_pkt_scan, 1372 .pkt_scan = sd_pkt_scan,
1373 .dq_callback = do_autogain,
1421}; 1374};
1422 1375
1423/* -- module initialisation -- */ 1376/* -- module initialisation -- */
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
index 3c2be80cbd65..eda29d609359 100644
--- a/drivers/media/video/gspca/spca505.c
+++ b/drivers/media/video/gspca/spca505.c
@@ -61,27 +61,27 @@ static struct ctrl sd_ctrls[] = {
61 61
62static struct v4l2_pix_format vga_mode[] = { 62static struct v4l2_pix_format vga_mode[] = {
63 {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 63 {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
64 .bytesperline = 160 * 3, 64 .bytesperline = 160,
65 .sizeimage = 160 * 120 * 3 / 2, 65 .sizeimage = 160 * 120 * 3 / 2,
66 .colorspace = V4L2_COLORSPACE_SRGB, 66 .colorspace = V4L2_COLORSPACE_SRGB,
67 .priv = 5}, 67 .priv = 5},
68 {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 68 {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
69 .bytesperline = 176 * 3, 69 .bytesperline = 176,
70 .sizeimage = 176 * 144 * 3 / 2, 70 .sizeimage = 176 * 144 * 3 / 2,
71 .colorspace = V4L2_COLORSPACE_SRGB, 71 .colorspace = V4L2_COLORSPACE_SRGB,
72 .priv = 4}, 72 .priv = 4},
73 {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 73 {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
74 .bytesperline = 320 * 3, 74 .bytesperline = 320,
75 .sizeimage = 320 * 240 * 3 / 2, 75 .sizeimage = 320 * 240 * 3 / 2,
76 .colorspace = V4L2_COLORSPACE_SRGB, 76 .colorspace = V4L2_COLORSPACE_SRGB,
77 .priv = 2}, 77 .priv = 2},
78 {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 78 {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
79 .bytesperline = 352 * 3, 79 .bytesperline = 352,
80 .sizeimage = 352 * 288 * 3 / 2, 80 .sizeimage = 352 * 288 * 3 / 2,
81 .colorspace = V4L2_COLORSPACE_SRGB, 81 .colorspace = V4L2_COLORSPACE_SRGB,
82 .priv = 1}, 82 .priv = 1},
83 {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 83 {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
84 .bytesperline = 640 * 3, 84 .bytesperline = 640,
85 .sizeimage = 640 * 480 * 3 / 2, 85 .sizeimage = 640 * 480 * 3 / 2,
86 .colorspace = V4L2_COLORSPACE_SRGB, 86 .colorspace = V4L2_COLORSPACE_SRGB,
87 .priv = 0}, 87 .priv = 0},
@@ -776,7 +776,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
776 default: 776 default:
777 data += 1; 777 data += 1;
778 len -= 1; 778 len -= 1;
779 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, 779 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
780 data, len); 780 data, len);
781 break; 781 break;
782 } 782 }
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
index 6fe715c80ad2..f622fa75766d 100644
--- a/drivers/media/video/gspca/spca506.c
+++ b/drivers/media/video/gspca/spca506.c
@@ -112,27 +112,27 @@ static struct ctrl sd_ctrls[] = {
112 112
113static struct v4l2_pix_format vga_mode[] = { 113static struct v4l2_pix_format vga_mode[] = {
114 {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 114 {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
115 .bytesperline = 160 * 3, 115 .bytesperline = 160,
116 .sizeimage = 160 * 120 * 3 / 2, 116 .sizeimage = 160 * 120 * 3 / 2,
117 .colorspace = V4L2_COLORSPACE_SRGB, 117 .colorspace = V4L2_COLORSPACE_SRGB,
118 .priv = 5}, 118 .priv = 5},
119 {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 119 {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
120 .bytesperline = 176 * 3, 120 .bytesperline = 176,
121 .sizeimage = 176 * 144 * 3 / 2, 121 .sizeimage = 176 * 144 * 3 / 2,
122 .colorspace = V4L2_COLORSPACE_SRGB, 122 .colorspace = V4L2_COLORSPACE_SRGB,
123 .priv = 4}, 123 .priv = 4},
124 {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 124 {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
125 .bytesperline = 320 * 3, 125 .bytesperline = 320,
126 .sizeimage = 320 * 240 * 3 / 2, 126 .sizeimage = 320 * 240 * 3 / 2,
127 .colorspace = V4L2_COLORSPACE_SRGB, 127 .colorspace = V4L2_COLORSPACE_SRGB,
128 .priv = 2}, 128 .priv = 2},
129 {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 129 {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
130 .bytesperline = 352 * 3, 130 .bytesperline = 352,
131 .sizeimage = 352 * 288 * 3 / 2, 131 .sizeimage = 352 * 288 * 3 / 2,
132 .colorspace = V4L2_COLORSPACE_SRGB, 132 .colorspace = V4L2_COLORSPACE_SRGB,
133 .priv = 1}, 133 .priv = 1},
134 {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 134 {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
135 .bytesperline = 640 * 3, 135 .bytesperline = 640,
136 .sizeimage = 640 * 480 * 3 / 2, 136 .sizeimage = 640 * 480 * 3 / 2,
137 .colorspace = V4L2_COLORSPACE_SRGB, 137 .colorspace = V4L2_COLORSPACE_SRGB,
138 .priv = 0}, 138 .priv = 0},
@@ -588,7 +588,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
588 default: 588 default:
589 data += 1; 589 data += 1;
590 len -= 1; 590 len -= 1;
591 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, 591 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
592 data, len); 592 data, len);
593 break; 593 break;
594 } 594 }
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
index b608a27ad115..699340c17dea 100644
--- a/drivers/media/video/gspca/spca508.c
+++ b/drivers/media/video/gspca/spca508.c
@@ -63,23 +63,23 @@ static struct ctrl sd_ctrls[] = {
63}; 63};
64 64
65static struct v4l2_pix_format sif_mode[] = { 65static struct v4l2_pix_format sif_mode[] = {
66 {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, 66 {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
67 .bytesperline = 160 * 3, 67 .bytesperline = 160,
68 .sizeimage = 160 * 120 * 3 / 2, 68 .sizeimage = 160 * 120 * 3 / 2,
69 .colorspace = V4L2_COLORSPACE_SRGB, 69 .colorspace = V4L2_COLORSPACE_SRGB,
70 .priv = 3}, 70 .priv = 3},
71 {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, 71 {176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
72 .bytesperline = 176 * 3, 72 .bytesperline = 176,
73 .sizeimage = 176 * 144 * 3 / 2, 73 .sizeimage = 176 * 144 * 3 / 2,
74 .colorspace = V4L2_COLORSPACE_SRGB, 74 .colorspace = V4L2_COLORSPACE_SRGB,
75 .priv = 2}, 75 .priv = 2},
76 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, 76 {320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
77 .bytesperline = 320 * 3, 77 .bytesperline = 320,
78 .sizeimage = 320 * 240 * 3 / 2, 78 .sizeimage = 320 * 240 * 3 / 2,
79 .colorspace = V4L2_COLORSPACE_SRGB, 79 .colorspace = V4L2_COLORSPACE_SRGB,
80 .priv = 1}, 80 .priv = 1},
81 {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, 81 {352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
82 .bytesperline = 352 * 3, 82 .bytesperline = 352,
83 .sizeimage = 352 * 288 * 3 / 2, 83 .sizeimage = 352 * 288 * 3 / 2,
84 .colorspace = V4L2_COLORSPACE_SRGB, 84 .colorspace = V4L2_COLORSPACE_SRGB,
85 .priv = 0}, 85 .priv = 0},
@@ -1583,7 +1583,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1583 default: 1583 default:
1584 data += 1; 1584 data += 1;
1585 len -= 1; 1585 len -= 1;
1586 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, 1586 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1587 data, len); 1587 data, len);
1588 break; 1588 break;
1589 } 1589 }
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index a26174508cb9..1073ac3d2ec6 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -644,6 +644,18 @@ static void setcontrast(struct gspca_dev *gspca_dev)
644 } 644 }
645} 645}
646 646
647static void setautogain(struct gspca_dev *gspca_dev)
648{
649 struct sd *sd = (struct sd *) gspca_dev;
650
651 if (sd->chip_revision == Rev072A) {
652 if (sd->autogain)
653 sd->ag_cnt = AG_CNT_START;
654 else
655 sd->ag_cnt = -1;
656 }
657}
658
647static void sd_start(struct gspca_dev *gspca_dev) 659static void sd_start(struct gspca_dev *gspca_dev)
648{ 660{
649 struct sd *sd = (struct sd *) gspca_dev; 661 struct sd *sd = (struct sd *) gspca_dev;
@@ -671,6 +683,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
671 reg_w_val(dev, 0x8500, mode); /* mode */ 683 reg_w_val(dev, 0x8500, mode); /* mode */
672 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ 684 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
673 reg_w_val(dev, 0x8112, 0x10 | 0x20); 685 reg_w_val(dev, 0x8112, 0x10 | 0x20);
686 setautogain(gspca_dev);
674 break; 687 break;
675 default: 688 default:
676/* case Rev012A: */ 689/* case Rev012A: */
@@ -720,18 +733,24 @@ static void sd_close(struct gspca_dev *gspca_dev)
720 reg_w_val(gspca_dev->dev, 0x8114, 0); 733 reg_w_val(gspca_dev->dev, 0x8114, 0);
721} 734}
722 735
723static void setautogain(struct gspca_dev *gspca_dev) 736static void do_autogain(struct gspca_dev *gspca_dev)
724{ 737{
725 struct sd *sd = (struct sd *) gspca_dev; 738 struct sd *sd = (struct sd *) gspca_dev;
726 int expotimes = 0; 739 int expotimes;
727 int pixelclk = 0; 740 int pixelclk;
728 int gainG = 0; 741 int gainG;
729 __u8 R, Gr, Gb, B; 742 __u8 R, Gr, Gb, B;
730 int y; 743 int y;
731 __u8 luma_mean = 110; 744 __u8 luma_mean = 110;
732 __u8 luma_delta = 20; 745 __u8 luma_delta = 20;
733 __u8 spring = 4; 746 __u8 spring = 4;
734 747
748 if (sd->ag_cnt < 0)
749 return;
750 if (--sd->ag_cnt >= 0)
751 return;
752 sd->ag_cnt = AG_CNT_START;
753
735 switch (sd->chip_revision) { 754 switch (sd->chip_revision) {
736 case Rev072A: 755 case Rev072A:
737 reg_r(gspca_dev, 0x8621, 1); 756 reg_r(gspca_dev, 0x8621, 1);
@@ -795,18 +814,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
795 __u8 *data, /* isoc packet */ 814 __u8 *data, /* isoc packet */
796 int len) /* iso packet length */ 815 int len) /* iso packet length */
797{ 816{
798 struct sd *sd = (struct sd *) gspca_dev;
799
800 switch (data[0]) { 817 switch (data[0]) {
801 case 0: /* start of frame */ 818 case 0: /* start of frame */
802 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, 819 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
803 data, 0); 820 data, 0);
804 if (sd->ag_cnt >= 0) {
805 if (--sd->ag_cnt < 0) {
806 sd->ag_cnt = AG_CNT_START;
807 setautogain(gspca_dev);
808 }
809 }
810 data += SPCA561_OFFSET_DATA; 821 data += SPCA561_OFFSET_DATA;
811 len -= SPCA561_OFFSET_DATA; 822 len -= SPCA561_OFFSET_DATA;
812 if (data[1] & 0x10) { 823 if (data[1] & 0x10) {
@@ -944,10 +955,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
944 struct sd *sd = (struct sd *) gspca_dev; 955 struct sd *sd = (struct sd *) gspca_dev;
945 956
946 sd->autogain = val; 957 sd->autogain = val;
947 if (val) 958 if (gspca_dev->streaming)
948 sd->ag_cnt = AG_CNT_START; 959 setautogain(gspca_dev);
949 else
950 sd->ag_cnt = -1;
951 return 0; 960 return 0;
952} 961}
953 962
@@ -971,6 +980,7 @@ static const struct sd_desc sd_desc = {
971 .stop0 = sd_stop0, 980 .stop0 = sd_stop0,
972 .close = sd_close, 981 .close = sd_close,
973 .pkt_scan = sd_pkt_scan, 982 .pkt_scan = sd_pkt_scan,
983 .dq_callback = do_autogain,
974}; 984};
975 985
976/* -- module initialisation -- */ 986/* -- module initialisation -- */
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index a4221753e1bf..f4a52956e0d9 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -88,12 +88,12 @@ static struct ctrl sd_ctrls[] = {
88 88
89static struct v4l2_pix_format vc0321_mode[] = { 89static struct v4l2_pix_format vc0321_mode[] = {
90 {320, 240, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE, 90 {320, 240, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
91 .bytesperline = 320 * 2, 91 .bytesperline = 320,
92 .sizeimage = 320 * 240 * 2, 92 .sizeimage = 320 * 240 * 2,
93 .colorspace = V4L2_COLORSPACE_SRGB, 93 .colorspace = V4L2_COLORSPACE_SRGB,
94 .priv = 1}, 94 .priv = 1},
95 {640, 480, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE, 95 {640, 480, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
96 .bytesperline = 640 * 2, 96 .bytesperline = 640,
97 .sizeimage = 640 * 480 * 2, 97 .sizeimage = 640 * 480 * 2,
98 .colorspace = V4L2_COLORSPACE_SRGB, 98 .colorspace = V4L2_COLORSPACE_SRGB,
99 .priv = 0}, 99 .priv = 0},
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 22a994ccb1d5..bc7d0eedcd81 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -6469,7 +6469,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
6469 NULL, Tgradient_1, Tgradient_2, 6469 NULL, Tgradient_1, Tgradient_2,
6470 Tgradient_3, Tgradient_4, Tgradient_5, Tgradient_6 6470 Tgradient_3, Tgradient_4, Tgradient_5, Tgradient_6
6471 }; 6471 };
6472#ifdef CONFIG_VIDEO_ADV_DEBUG 6472#ifdef GSPCA_DEBUG
6473 __u8 v[16]; 6473 __u8 v[16];
6474#endif 6474#endif
6475 6475
@@ -6487,7 +6487,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
6487 else if (g <= 0) 6487 else if (g <= 0)
6488 g = 1; 6488 g = 1;
6489 reg_w(dev, g, 0x0120 + i); /* gamma */ 6489 reg_w(dev, g, 0x0120 + i); /* gamma */
6490#ifdef CONFIG_VIDEO_ADV_DEBUG 6490#ifdef GSPCA_DEBUG
6491 if (gspca_debug & D_CONF) 6491 if (gspca_debug & D_CONF)
6492 v[i] = g; 6492 v[i] = g;
6493#endif 6493#endif
@@ -6507,7 +6507,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
6507 g = 1; 6507 g = 1;
6508 } 6508 }
6509 reg_w(dev, g, 0x0130 + i); /* gradient */ 6509 reg_w(dev, g, 0x0130 + i); /* gradient */
6510#ifdef CONFIG_VIDEO_ADV_DEBUG 6510#ifdef GSPCA_DEBUG
6511 if (gspca_debug & D_CONF) 6511 if (gspca_debug & D_CONF)
6512 v[i] = g; 6512 v[i] = g;
6513#endif 6513#endif
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index b15f82c49766..ead87ddaf7fb 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -128,6 +128,8 @@ struct pxa_camera_dev {
128 128
129 struct pxa_buffer *active; 129 struct pxa_buffer *active;
130 struct pxa_dma_desc *sg_tail[3]; 130 struct pxa_dma_desc *sg_tail[3];
131
132 u32 save_cicr[5];
131}; 133};
132 134
133static const char *pxa_cam_driver_description = "PXA_Camera"; 135static const char *pxa_cam_driver_description = "PXA_Camera";
@@ -997,10 +999,64 @@ static int pxa_camera_querycap(struct soc_camera_host *ici,
997 return 0; 999 return 0;
998} 1000}
999 1001
1002static int pxa_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
1003{
1004 struct soc_camera_host *ici =
1005 to_soc_camera_host(icd->dev.parent);
1006 struct pxa_camera_dev *pcdev = ici->priv;
1007 int i = 0, ret = 0;
1008
1009 pcdev->save_cicr[i++] = CICR0;
1010 pcdev->save_cicr[i++] = CICR1;
1011 pcdev->save_cicr[i++] = CICR2;
1012 pcdev->save_cicr[i++] = CICR3;
1013 pcdev->save_cicr[i++] = CICR4;
1014
1015 if ((pcdev->icd) && (pcdev->icd->ops->suspend))
1016 ret = pcdev->icd->ops->suspend(pcdev->icd, state);
1017
1018 return ret;
1019}
1020
1021static int pxa_camera_resume(struct soc_camera_device *icd)
1022{
1023 struct soc_camera_host *ici =
1024 to_soc_camera_host(icd->dev.parent);
1025 struct pxa_camera_dev *pcdev = ici->priv;
1026 int i = 0, ret = 0;
1027
1028 DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD;
1029 DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD;
1030 DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD;
1031
1032 CICR0 = pcdev->save_cicr[i++] & ~CICR0_ENB;
1033 CICR1 = pcdev->save_cicr[i++];
1034 CICR2 = pcdev->save_cicr[i++];
1035 CICR3 = pcdev->save_cicr[i++];
1036 CICR4 = pcdev->save_cicr[i++];
1037
1038 if ((pcdev->icd) && (pcdev->icd->ops->resume))
1039 ret = pcdev->icd->ops->resume(pcdev->icd);
1040
1041 /* Restart frame capture if active buffer exists */
1042 if (!ret && pcdev->active) {
1043 /* Reset the FIFOs */
1044 CIFR |= CIFR_RESET_F;
1045 /* Enable End-Of-Frame Interrupt */
1046 CICR0 &= ~CICR0_EOFM;
1047 /* Restart the Capture Interface */
1048 CICR0 |= CICR0_ENB;
1049 }
1050
1051 return ret;
1052}
1053
1000static struct soc_camera_host_ops pxa_soc_camera_host_ops = { 1054static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
1001 .owner = THIS_MODULE, 1055 .owner = THIS_MODULE,
1002 .add = pxa_camera_add_device, 1056 .add = pxa_camera_add_device,
1003 .remove = pxa_camera_remove_device, 1057 .remove = pxa_camera_remove_device,
1058 .suspend = pxa_camera_suspend,
1059 .resume = pxa_camera_resume,
1004 .set_fmt_cap = pxa_camera_set_fmt_cap, 1060 .set_fmt_cap = pxa_camera_set_fmt_cap,
1005 .try_fmt_cap = pxa_camera_try_fmt_cap, 1061 .try_fmt_cap = pxa_camera_try_fmt_cap,
1006 .init_videobuf = pxa_camera_init_videobuf, 1062 .init_videobuf = pxa_camera_init_videobuf,
@@ -1198,7 +1254,7 @@ static int __devinit pxa_camera_init(void)
1198 1254
1199static void __exit pxa_camera_exit(void) 1255static void __exit pxa_camera_exit(void)
1200{ 1256{
1201 return platform_driver_unregister(&pxa_camera_driver); 1257 platform_driver_unregister(&pxa_camera_driver);
1202} 1258}
1203 1259
1204module_init(pxa_camera_init); 1260module_init(pxa_camera_init);
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index f7ca3cb9340a..318754e73132 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -647,7 +647,7 @@ static int __init sh_mobile_ceu_init(void)
647 647
648static void __exit sh_mobile_ceu_exit(void) 648static void __exit sh_mobile_ceu_exit(void)
649{ 649{
650 return platform_driver_unregister(&sh_mobile_ceu_driver); 650 platform_driver_unregister(&sh_mobile_ceu_driver);
651} 651}
652 652
653module_init(sh_mobile_ceu_init); 653module_init(sh_mobile_ceu_init);
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index b6be5ee678b6..66ebe5956a87 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -732,10 +732,36 @@ static int soc_camera_remove(struct device *dev)
732 return 0; 732 return 0;
733} 733}
734 734
735static int soc_camera_suspend(struct device *dev, pm_message_t state)
736{
737 struct soc_camera_device *icd = to_soc_camera_dev(dev);
738 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
739 int ret = 0;
740
741 if (ici->ops->suspend)
742 ret = ici->ops->suspend(icd, state);
743
744 return ret;
745}
746
747static int soc_camera_resume(struct device *dev)
748{
749 struct soc_camera_device *icd = to_soc_camera_dev(dev);
750 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
751 int ret = 0;
752
753 if (ici->ops->resume)
754 ret = ici->ops->resume(icd);
755
756 return ret;
757}
758
735static struct bus_type soc_camera_bus_type = { 759static struct bus_type soc_camera_bus_type = {
736 .name = "soc-camera", 760 .name = "soc-camera",
737 .probe = soc_camera_probe, 761 .probe = soc_camera_probe,
738 .remove = soc_camera_remove, 762 .remove = soc_camera_remove,
763 .suspend = soc_camera_suspend,
764 .resume = soc_camera_resume,
739}; 765};
740 766
741static struct device_driver ic_drv = { 767static struct device_driver ic_drv = {
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index eefb0327ebb6..1adc257ebdb9 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -187,7 +187,7 @@ static int __init soc_camera_platform_module_init(void)
187 187
188static void __exit soc_camera_platform_module_exit(void) 188static void __exit soc_camera_platform_module_exit(void)
189{ 189{
190 return platform_driver_unregister(&soc_camera_platform_driver); 190 platform_driver_unregister(&soc_camera_platform_driver);
191} 191}
192 192
193module_init(soc_camera_platform_module_init); 193module_init(soc_camera_platform_module_init);
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 626f4ad7e876..6ef3e5297de8 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -585,13 +585,17 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
585 struct uvc_control_mapping *mapping; 585 struct uvc_control_mapping *mapping;
586 struct uvc_menu_info *menu; 586 struct uvc_menu_info *menu;
587 unsigned int i; 587 unsigned int i;
588 __u8 data[8]; 588 __u8 *data;
589 int ret; 589 int ret;
590 590
591 ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping); 591 ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping);
592 if (ctrl == NULL) 592 if (ctrl == NULL)
593 return -EINVAL; 593 return -EINVAL;
594 594
595 data = kmalloc(8, GFP_KERNEL);
596 if (data == NULL)
597 return -ENOMEM;
598
595 memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); 599 memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
596 v4l2_ctrl->id = mapping->id; 600 v4l2_ctrl->id = mapping->id;
597 v4l2_ctrl->type = mapping->v4l2_type; 601 v4l2_ctrl->type = mapping->v4l2_type;
@@ -604,8 +608,8 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
604 if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { 608 if (ctrl->info->flags & UVC_CONTROL_GET_DEF) {
605 if ((ret = uvc_query_ctrl(video->dev, GET_DEF, ctrl->entity->id, 609 if ((ret = uvc_query_ctrl(video->dev, GET_DEF, ctrl->entity->id,
606 video->dev->intfnum, ctrl->info->selector, 610 video->dev->intfnum, ctrl->info->selector,
607 &data, ctrl->info->size)) < 0) 611 data, ctrl->info->size)) < 0)
608 return ret; 612 goto out;
609 v4l2_ctrl->default_value = uvc_get_le_value(data, mapping); 613 v4l2_ctrl->default_value = uvc_get_le_value(data, mapping);
610 } 614 }
611 615
@@ -623,13 +627,15 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
623 } 627 }
624 } 628 }
625 629
626 return 0; 630 ret = 0;
631 goto out;
627 632
628 case V4L2_CTRL_TYPE_BOOLEAN: 633 case V4L2_CTRL_TYPE_BOOLEAN:
629 v4l2_ctrl->minimum = 0; 634 v4l2_ctrl->minimum = 0;
630 v4l2_ctrl->maximum = 1; 635 v4l2_ctrl->maximum = 1;
631 v4l2_ctrl->step = 1; 636 v4l2_ctrl->step = 1;
632 return 0; 637 ret = 0;
638 goto out;
633 639
634 default: 640 default:
635 break; 641 break;
@@ -638,26 +644,29 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
638 if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { 644 if (ctrl->info->flags & UVC_CONTROL_GET_MIN) {
639 if ((ret = uvc_query_ctrl(video->dev, GET_MIN, ctrl->entity->id, 645 if ((ret = uvc_query_ctrl(video->dev, GET_MIN, ctrl->entity->id,
640 video->dev->intfnum, ctrl->info->selector, 646 video->dev->intfnum, ctrl->info->selector,
641 &data, ctrl->info->size)) < 0) 647 data, ctrl->info->size)) < 0)
642 return ret; 648 goto out;
643 v4l2_ctrl->minimum = uvc_get_le_value(data, mapping); 649 v4l2_ctrl->minimum = uvc_get_le_value(data, mapping);
644 } 650 }
645 if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { 651 if (ctrl->info->flags & UVC_CONTROL_GET_MAX) {
646 if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id, 652 if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id,
647 video->dev->intfnum, ctrl->info->selector, 653 video->dev->intfnum, ctrl->info->selector,
648 &data, ctrl->info->size)) < 0) 654 data, ctrl->info->size)) < 0)
649 return ret; 655 goto out;
650 v4l2_ctrl->maximum = uvc_get_le_value(data, mapping); 656 v4l2_ctrl->maximum = uvc_get_le_value(data, mapping);
651 } 657 }
652 if (ctrl->info->flags & UVC_CONTROL_GET_RES) { 658 if (ctrl->info->flags & UVC_CONTROL_GET_RES) {
653 if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id, 659 if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id,
654 video->dev->intfnum, ctrl->info->selector, 660 video->dev->intfnum, ctrl->info->selector,
655 &data, ctrl->info->size)) < 0) 661 data, ctrl->info->size)) < 0)
656 return ret; 662 goto out;
657 v4l2_ctrl->step = uvc_get_le_value(data, mapping); 663 v4l2_ctrl->step = uvc_get_le_value(data, mapping);
658 } 664 }
659 665
660 return 0; 666 ret = 0;
667out:
668 kfree(data);
669 return ret;
661} 670}
662 671
663 672
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index b3c4d75e8490..7e102034d38d 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1884,7 +1884,7 @@ static struct usb_device_id uvc_ids[] = {
1884 .bInterfaceSubClass = 1, 1884 .bInterfaceSubClass = 1,
1885 .bInterfaceProtocol = 0, 1885 .bInterfaceProtocol = 0,
1886 .driver_info = UVC_QUIRK_PROBE_MINMAX }, 1886 .driver_info = UVC_QUIRK_PROBE_MINMAX },
1887 /* Packard Bell OEM Webcam */ 1887 /* Packard Bell OEM Webcam - Bison Electronics */
1888 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE 1888 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1889 | USB_DEVICE_ID_MATCH_INT_INFO, 1889 | USB_DEVICE_ID_MATCH_INT_INFO,
1890 .idVendor = 0x5986, 1890 .idVendor = 0x5986,
@@ -1893,7 +1893,7 @@ static struct usb_device_id uvc_ids[] = {
1893 .bInterfaceSubClass = 1, 1893 .bInterfaceSubClass = 1,
1894 .bInterfaceProtocol = 0, 1894 .bInterfaceProtocol = 0,
1895 .driver_info = UVC_QUIRK_PROBE_MINMAX }, 1895 .driver_info = UVC_QUIRK_PROBE_MINMAX },
1896 /* Acer Crystal Eye webcam */ 1896 /* Acer Crystal Eye webcam - Bison Electronics */
1897 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE 1897 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1898 | USB_DEVICE_ID_MATCH_INT_INFO, 1898 | USB_DEVICE_ID_MATCH_INT_INFO,
1899 .idVendor = 0x5986, 1899 .idVendor = 0x5986,
@@ -1902,7 +1902,7 @@ static struct usb_device_id uvc_ids[] = {
1902 .bInterfaceSubClass = 1, 1902 .bInterfaceSubClass = 1,
1903 .bInterfaceProtocol = 0, 1903 .bInterfaceProtocol = 0,
1904 .driver_info = UVC_QUIRK_PROBE_MINMAX }, 1904 .driver_info = UVC_QUIRK_PROBE_MINMAX },
1905 /* Medion Akoya Mini E1210 */ 1905 /* Medion Akoya Mini E1210 - Bison Electronics */
1906 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE 1906 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1907 | USB_DEVICE_ID_MATCH_INT_INFO, 1907 | USB_DEVICE_ID_MATCH_INT_INFO,
1908 .idVendor = 0x5986, 1908 .idVendor = 0x5986,
@@ -1911,7 +1911,7 @@ static struct usb_device_id uvc_ids[] = {
1911 .bInterfaceSubClass = 1, 1911 .bInterfaceSubClass = 1,
1912 .bInterfaceProtocol = 0, 1912 .bInterfaceProtocol = 0,
1913 .driver_info = UVC_QUIRK_PROBE_MINMAX }, 1913 .driver_info = UVC_QUIRK_PROBE_MINMAX },
1914 /* Acer OrbiCam - Unknown vendor */ 1914 /* Acer OrbiCam - Bison Electronics */
1915 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE 1915 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1916 | USB_DEVICE_ID_MATCH_INT_INFO, 1916 | USB_DEVICE_ID_MATCH_INT_INFO,
1917 .idVendor = 0x5986, 1917 .idVendor = 0x5986,
@@ -1920,6 +1920,24 @@ static struct usb_device_id uvc_ids[] = {
1920 .bInterfaceSubClass = 1, 1920 .bInterfaceSubClass = 1,
1921 .bInterfaceProtocol = 0, 1921 .bInterfaceProtocol = 0,
1922 .driver_info = UVC_QUIRK_PROBE_MINMAX }, 1922 .driver_info = UVC_QUIRK_PROBE_MINMAX },
1923 /* Bison Electronics */
1924 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1925 | USB_DEVICE_ID_MATCH_INT_INFO,
1926 .idVendor = 0x5986,
1927 .idProduct = 0x0300,
1928 .bInterfaceClass = USB_CLASS_VIDEO,
1929 .bInterfaceSubClass = 1,
1930 .bInterfaceProtocol = 0,
1931 .driver_info = UVC_QUIRK_PROBE_MINMAX },
1932 /* Clevo M570TU - Bison Electronics */
1933 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1934 | USB_DEVICE_ID_MATCH_INT_INFO,
1935 .idVendor = 0x5986,
1936 .idProduct = 0x0303,
1937 .bInterfaceClass = USB_CLASS_VIDEO,
1938 .bInterfaceSubClass = 1,
1939 .bInterfaceProtocol = 0,
1940 .driver_info = UVC_QUIRK_PROBE_MINMAX },
1923 /* Generic USB Video Class */ 1941 /* Generic USB Video Class */
1924 { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, 1942 { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
1925 {} 1943 {}
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index ad63794fda77..6854ac78a161 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -90,17 +90,20 @@ static void uvc_fixup_buffer_size(struct uvc_video_device *video,
90static int uvc_get_video_ctrl(struct uvc_video_device *video, 90static int uvc_get_video_ctrl(struct uvc_video_device *video,
91 struct uvc_streaming_control *ctrl, int probe, __u8 query) 91 struct uvc_streaming_control *ctrl, int probe, __u8 query)
92{ 92{
93 __u8 data[34]; 93 __u8 *data;
94 __u8 size; 94 __u16 size;
95 int ret; 95 int ret;
96 96
97 size = video->dev->uvc_version >= 0x0110 ? 34 : 26; 97 size = video->dev->uvc_version >= 0x0110 ? 34 : 26;
98 data = kmalloc(size, GFP_KERNEL);
99 if (data == NULL)
100 return -ENOMEM;
101
98 ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, 102 ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum,
99 probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size, 103 probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
100 UVC_CTRL_STREAMING_TIMEOUT); 104 UVC_CTRL_STREAMING_TIMEOUT);
101
102 if (ret < 0) 105 if (ret < 0)
103 return ret; 106 goto out;
104 107
105 ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]); 108 ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]);
106 ctrl->bFormatIndex = data[2]; 109 ctrl->bFormatIndex = data[2];
@@ -136,17 +139,22 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
136 */ 139 */
137 uvc_fixup_buffer_size(video, ctrl); 140 uvc_fixup_buffer_size(video, ctrl);
138 141
139 return 0; 142out:
143 kfree(data);
144 return ret;
140} 145}
141 146
142int uvc_set_video_ctrl(struct uvc_video_device *video, 147int uvc_set_video_ctrl(struct uvc_video_device *video,
143 struct uvc_streaming_control *ctrl, int probe) 148 struct uvc_streaming_control *ctrl, int probe)
144{ 149{
145 __u8 data[34]; 150 __u8 *data;
146 __u8 size; 151 __u16 size;
152 int ret;
147 153
148 size = video->dev->uvc_version >= 0x0110 ? 34 : 26; 154 size = video->dev->uvc_version >= 0x0110 ? 34 : 26;
149 memset(data, 0, sizeof data); 155 data = kzalloc(size, GFP_KERNEL);
156 if (data == NULL)
157 return -ENOMEM;
150 158
151 *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint); 159 *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint);
152 data[2] = ctrl->bFormatIndex; 160 data[2] = ctrl->bFormatIndex;
@@ -174,10 +182,13 @@ int uvc_set_video_ctrl(struct uvc_video_device *video,
174 data[33] = ctrl->bMaxVersion; 182 data[33] = ctrl->bMaxVersion;
175 } 183 }
176 184
177 return __uvc_query_ctrl(video->dev, SET_CUR, 0, 185 ret = __uvc_query_ctrl(video->dev, SET_CUR, 0,
178 video->streaming->intfnum, 186 video->streaming->intfnum,
179 probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size, 187 probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
180 UVC_CTRL_STREAMING_TIMEOUT); 188 UVC_CTRL_STREAMING_TIMEOUT);
189
190 kfree(data);
191 return ret;
181} 192}
182 193
183int uvc_probe_video(struct uvc_video_device *video, 194int uvc_probe_video(struct uvc_video_device *video,
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 556615fe93de..6f36006aecda 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -222,11 +222,13 @@ int video_register_device(struct video_device *vfd, int type, int nr)
222EXPORT_SYMBOL(video_register_device); 222EXPORT_SYMBOL(video_register_device);
223 223
224/** 224/**
225 * video_register_device - register video4linux devices 225 * video_register_device_index - register video4linux devices
226 * @vfd: video device structure we want to register 226 * @vfd: video device structure we want to register
227 * @type: type of device to register 227 * @type: type of device to register
228 * @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ... 228 * @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ...
229 * -1 == first free) 229 * -1 == first free)
230 * @index: stream number based on parent device;
231 * -1 if auto assign, requested number otherwise
230 * 232 *
231 * The registration code assigns minor numbers based on the type 233 * The registration code assigns minor numbers based on the type
232 * requested. -ENFILE is returned in all the device slots for this 234 * requested. -ENFILE is returned in all the device slots for this
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index ef7572cbc4ab..1edda456fc64 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -41,6 +41,7 @@
41#include <linux/videodev2.h> 41#include <linux/videodev2.h>
42#include <media/v4l2-ioctl.h> 42#include <media/v4l2-ioctl.h>
43#include <media/v4l2-common.h> 43#include <media/v4l2-common.h>
44#include <media/v4l2-ioctl.h>
44#include <linux/video_decoder.h> 45#include <linux/video_decoder.h>
45#include <linux/mutex.h> 46#include <linux/mutex.h>
46 47
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 48399e134c0d..32b9fe153641 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -463,7 +463,7 @@ config PC87413_WDT
463 module will be called pc87413_wdt. 463 module will be called pc87413_wdt.
464 464
465 Most people will say N. 465 Most people will say N.
466 466
467config 60XX_WDT 467config 60XX_WDT
468 tristate "SBC-60XX Watchdog Timer" 468 tristate "SBC-60XX Watchdog Timer"
469 depends on X86 469 depends on X86
@@ -695,9 +695,17 @@ config 8xx_WDT
695 tristate "MPC8xx Watchdog Timer" 695 tristate "MPC8xx Watchdog Timer"
696 depends on 8xx 696 depends on 8xx
697 697
698config 83xx_WDT 698config 8xxx_WDT
699 tristate "MPC83xx Watchdog Timer" 699 tristate "MPC8xxx Platform Watchdog Timer"
700 depends on PPC_83xx 700 depends on PPC_8xx || PPC_83xx || PPC_86xx
701 help
702 This driver is for a SoC level watchdog that exists on some
703 Freescale PowerPC processors. So far this driver supports:
704 - MPC8xx watchdogs
705 - MPC83xx watchdogs
706 - MPC86xx watchdogs
707
708 For BookE processors (MPC85xx) use the BOOKE_WDT driver instead.
701 709
702config MV64X60_WDT 710config MV64X60_WDT
703 tristate "MV64X60 (Marvell Discovery) Watchdog Timer" 711 tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index edd305a64e63..049c91895699 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -92,7 +92,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
92 92
93# MIPS Architecture 93# MIPS Architecture
94obj-$(CONFIG_INDYDOG) += indydog.o 94obj-$(CONFIG_INDYDOG) += indydog.o
95obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o 95obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
96obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o 96obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
97obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o 97obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
98obj-$(CONFIG_AR7_WDT) += ar7_wdt.o 98obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
@@ -103,7 +103,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
103# POWERPC Architecture 103# POWERPC Architecture
104obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o 104obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
105obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o 105obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o
106obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o 106obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o
107obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o 107obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
108obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o 108obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
109 109
diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
index 85269c365a10..6e46a551395c 100644
--- a/drivers/watchdog/acquirewdt.c
+++ b/drivers/watchdog/acquirewdt.c
@@ -58,39 +58,45 @@
58#include <linux/types.h> /* For standard types (like size_t) */ 58#include <linux/types.h> /* For standard types (like size_t) */
59#include <linux/errno.h> /* For the -ENODEV/... values */ 59#include <linux/errno.h> /* For the -ENODEV/... values */
60#include <linux/kernel.h> /* For printk/panic/... */ 60#include <linux/kernel.h> /* For printk/panic/... */
61#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ 61#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV
62 (WATCHDOG_MINOR) */
62#include <linux/watchdog.h> /* For the watchdog specific items */ 63#include <linux/watchdog.h> /* For the watchdog specific items */
63#include <linux/fs.h> /* For file operations */ 64#include <linux/fs.h> /* For file operations */
64#include <linux/ioport.h> /* For io-port access */ 65#include <linux/ioport.h> /* For io-port access */
65#include <linux/platform_device.h> /* For platform_driver framework */ 66#include <linux/platform_device.h> /* For platform_driver framework */
66#include <linux/init.h> /* For __init/__exit/... */ 67#include <linux/init.h> /* For __init/__exit/... */
67 68#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
68#include <asm/uaccess.h> /* For copy_to_user/put_user/... */ 69#include <linux/io.h> /* For inb/outb/... */
69#include <asm/io.h> /* For inb/outb/... */
70 70
71/* Module information */ 71/* Module information */
72#define DRV_NAME "acquirewdt" 72#define DRV_NAME "acquirewdt"
73#define PFX DRV_NAME ": " 73#define PFX DRV_NAME ": "
74#define WATCHDOG_NAME "Acquire WDT" 74#define WATCHDOG_NAME "Acquire WDT"
75#define WATCHDOG_HEARTBEAT 0 /* There is no way to see what the correct time-out period is */ 75/* There is no way to see what the correct time-out period is */
76#define WATCHDOG_HEARTBEAT 0
76 77
77/* internal variables */ 78/* internal variables */
78static struct platform_device *acq_platform_device; /* the watchdog platform device */ 79/* the watchdog platform device */
80static struct platform_device *acq_platform_device;
79static unsigned long acq_is_open; 81static unsigned long acq_is_open;
80static char expect_close; 82static char expect_close;
81 83
82/* module parameters */ 84/* module parameters */
83static int wdt_stop = 0x43; /* You must set this - there is no sane way to probe for this board. */ 85/* You must set this - there is no sane way to probe for this board. */
86static int wdt_stop = 0x43;
84module_param(wdt_stop, int, 0); 87module_param(wdt_stop, int, 0);
85MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)"); 88MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)");
86 89
87static int wdt_start = 0x443; /* You must set this - there is no sane way to probe for this board. */ 90/* You must set this - there is no sane way to probe for this board. */
91static int wdt_start = 0x443;
88module_param(wdt_start, int, 0); 92module_param(wdt_start, int, 0);
89MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)"); 93MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)");
90 94
91static int nowayout = WATCHDOG_NOWAYOUT; 95static int nowayout = WATCHDOG_NOWAYOUT;
92module_param(nowayout, int, 0); 96module_param(nowayout, int, 0);
93MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 97MODULE_PARM_DESC(nowayout,
98 "Watchdog cannot be stopped once started (default="
99 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
94 100
95/* 101/*
96 * Watchdog Operations 102 * Watchdog Operations
@@ -112,18 +118,18 @@ static void acq_stop(void)
112 * /dev/watchdog handling 118 * /dev/watchdog handling
113 */ 119 */
114 120
115static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 121static ssize_t acq_write(struct file *file, const char __user *buf,
122 size_t count, loff_t *ppos)
116{ 123{
117 /* See if we got the magic character 'V' and reload the timer */ 124 /* See if we got the magic character 'V' and reload the timer */
118 if(count) { 125 if (count) {
119 if (!nowayout) { 126 if (!nowayout) {
120 size_t i; 127 size_t i;
121
122 /* note: just in case someone wrote the magic character 128 /* note: just in case someone wrote the magic character
123 * five months ago... */ 129 five months ago... */
124 expect_close = 0; 130 expect_close = 0;
125 131 /* scan to see whether or not we got the
126 /* scan to see whether or not we got the magic character */ 132 magic character */
127 for (i = 0; i != count; i++) { 133 for (i = 0; i != count; i++) {
128 char c; 134 char c;
129 if (get_user(c, buf + i)) 135 if (get_user(c, buf + i))
@@ -132,64 +138,55 @@ static ssize_t acq_write(struct file *file, const char __user *buf, size_t count
132 expect_close = 42; 138 expect_close = 42;
133 } 139 }
134 } 140 }
135 141 /* Well, anyhow someone wrote to us, we should
136 /* Well, anyhow someone wrote to us, we should return that favour */ 142 return that favour */
137 acq_keepalive(); 143 acq_keepalive();
138 } 144 }
139 return count; 145 return count;
140} 146}
141 147
142static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 148static long acq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
143 unsigned long arg)
144{ 149{
145 int options, retval = -EINVAL; 150 int options, retval = -EINVAL;
146 void __user *argp = (void __user *)arg; 151 void __user *argp = (void __user *)arg;
147 int __user *p = argp; 152 int __user *p = argp;
148 static struct watchdog_info ident = 153 static struct watchdog_info ident = {
149 {
150 .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 154 .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
151 .firmware_version = 1, 155 .firmware_version = 1,
152 .identity = WATCHDOG_NAME, 156 .identity = WATCHDOG_NAME,
153 }; 157 };
154 158
155 switch(cmd) 159 switch (cmd) {
156 {
157 case WDIOC_GETSUPPORT: 160 case WDIOC_GETSUPPORT:
158 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 161 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
159 162
160 case WDIOC_GETSTATUS: 163 case WDIOC_GETSTATUS:
161 case WDIOC_GETBOOTSTATUS: 164 case WDIOC_GETBOOTSTATUS:
162 return put_user(0, p); 165 return put_user(0, p);
163
164 case WDIOC_KEEPALIVE:
165 acq_keepalive();
166 return 0;
167
168 case WDIOC_GETTIMEOUT:
169 return put_user(WATCHDOG_HEARTBEAT, p);
170 166
171 case WDIOC_SETOPTIONS: 167 case WDIOC_SETOPTIONS:
172 { 168 {
173 if (get_user(options, p)) 169 if (get_user(options, p))
174 return -EFAULT; 170 return -EFAULT;
175 171 if (options & WDIOS_DISABLECARD) {
176 if (options & WDIOS_DISABLECARD) 172 acq_stop();
177 { 173 retval = 0;
178 acq_stop(); 174 }
179 retval = 0; 175 if (options & WDIOS_ENABLECARD) {
180 } 176 acq_keepalive();
181 177 retval = 0;
182 if (options & WDIOS_ENABLECARD) 178 }
183 { 179 return retval;
184 acq_keepalive();
185 retval = 0;
186 }
187
188 return retval;
189 } 180 }
181 case WDIOC_KEEPALIVE:
182 acq_keepalive();
183 return 0;
184
185 case WDIOC_GETTIMEOUT:
186 return put_user(WATCHDOG_HEARTBEAT, p);
190 187
191 default: 188 default:
192 return -ENOTTY; 189 return -ENOTTY;
193 } 190 }
194} 191}
195 192
@@ -211,7 +208,8 @@ static int acq_close(struct inode *inode, struct file *file)
211 if (expect_close == 42) { 208 if (expect_close == 42) {
212 acq_stop(); 209 acq_stop();
213 } else { 210 } else {
214 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 211 printk(KERN_CRIT PFX
212 "Unexpected close, not stopping watchdog!\n");
215 acq_keepalive(); 213 acq_keepalive();
216 } 214 }
217 clear_bit(0, &acq_is_open); 215 clear_bit(0, &acq_is_open);
@@ -227,7 +225,7 @@ static const struct file_operations acq_fops = {
227 .owner = THIS_MODULE, 225 .owner = THIS_MODULE,
228 .llseek = no_llseek, 226 .llseek = no_llseek,
229 .write = acq_write, 227 .write = acq_write,
230 .ioctl = acq_ioctl, 228 .unlocked_ioctl = acq_ioctl,
231 .open = acq_open, 229 .open = acq_open,
232 .release = acq_close, 230 .release = acq_close,
233}; 231};
@@ -248,32 +246,29 @@ static int __devinit acq_probe(struct platform_device *dev)
248 246
249 if (wdt_stop != wdt_start) { 247 if (wdt_stop != wdt_start) {
250 if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) { 248 if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
251 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", 249 printk(KERN_ERR PFX
252 wdt_stop); 250 "I/O address 0x%04x already in use\n", wdt_stop);
253 ret = -EIO; 251 ret = -EIO;
254 goto out; 252 goto out;
255 } 253 }
256 } 254 }
257 255
258 if (!request_region(wdt_start, 1, WATCHDOG_NAME)) { 256 if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
259 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", 257 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
260 wdt_start); 258 wdt_start);
261 ret = -EIO; 259 ret = -EIO;
262 goto unreg_stop; 260 goto unreg_stop;
263 } 261 }
264
265 ret = misc_register(&acq_miscdev); 262 ret = misc_register(&acq_miscdev);
266 if (ret != 0) { 263 if (ret != 0) {
267 printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 264 printk(KERN_ERR PFX
268 WATCHDOG_MINOR, ret); 265 "cannot register miscdev on minor=%d (err=%d)\n",
266 WATCHDOG_MINOR, ret);
269 goto unreg_regions; 267 goto unreg_regions;
270 } 268 }
271 269 printk(KERN_INFO PFX "initialized. (nowayout=%d)\n", nowayout);
272 printk (KERN_INFO PFX "initialized. (nowayout=%d)\n",
273 nowayout);
274 270
275 return 0; 271 return 0;
276
277unreg_regions: 272unreg_regions:
278 release_region(wdt_start, 1); 273 release_region(wdt_start, 1);
279unreg_stop: 274unreg_stop:
@@ -286,9 +281,9 @@ out:
286static int __devexit acq_remove(struct platform_device *dev) 281static int __devexit acq_remove(struct platform_device *dev)
287{ 282{
288 misc_deregister(&acq_miscdev); 283 misc_deregister(&acq_miscdev);
289 release_region(wdt_start,1); 284 release_region(wdt_start, 1);
290 if(wdt_stop != wdt_start) 285 if (wdt_stop != wdt_start)
291 release_region(wdt_stop,1); 286 release_region(wdt_stop, 1);
292 287
293 return 0; 288 return 0;
294} 289}
@@ -313,18 +308,19 @@ static int __init acq_init(void)
313{ 308{
314 int err; 309 int err;
315 310
316 printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n"); 311 printk(KERN_INFO
312 "WDT driver for Acquire single board computer initialising.\n");
317 313
318 err = platform_driver_register(&acquirewdt_driver); 314 err = platform_driver_register(&acquirewdt_driver);
319 if (err) 315 if (err)
320 return err; 316 return err;
321 317
322 acq_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); 318 acq_platform_device = platform_device_register_simple(DRV_NAME,
319 -1, NULL, 0);
323 if (IS_ERR(acq_platform_device)) { 320 if (IS_ERR(acq_platform_device)) {
324 err = PTR_ERR(acq_platform_device); 321 err = PTR_ERR(acq_platform_device);
325 goto unreg_platform_driver; 322 goto unreg_platform_driver;
326 } 323 }
327
328 return 0; 324 return 0;
329 325
330unreg_platform_driver: 326unreg_platform_driver:
diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
index 8121cc247343..a5110f93a755 100644
--- a/drivers/watchdog/advantechwdt.c
+++ b/drivers/watchdog/advantechwdt.c
@@ -37,9 +37,9 @@
37#include <linux/ioport.h> 37#include <linux/ioport.h>
38#include <linux/platform_device.h> 38#include <linux/platform_device.h>
39#include <linux/init.h> 39#include <linux/init.h>
40#include <linux/io.h>
41#include <linux/uaccess.h>
40 42
41#include <asm/io.h>
42#include <asm/uaccess.h>
43#include <asm/system.h> 43#include <asm/system.h>
44 44
45#define DRV_NAME "advantechwdt" 45#define DRV_NAME "advantechwdt"
@@ -47,7 +47,8 @@
47#define WATCHDOG_NAME "Advantech WDT" 47#define WATCHDOG_NAME "Advantech WDT"
48#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ 48#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
49 49
50static struct platform_device *advwdt_platform_device; /* the watchdog platform device */ 50/* the watchdog platform device */
51static struct platform_device *advwdt_platform_device;
51static unsigned long advwdt_is_open; 52static unsigned long advwdt_is_open;
52static char adv_expect_close; 53static char adv_expect_close;
53 54
@@ -72,35 +73,35 @@ MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)");
72 73
73static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ 74static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
74module_param(timeout, int, 0); 75module_param(timeout, int, 0);
75MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); 76MODULE_PARM_DESC(timeout,
77 "Watchdog timeout in seconds. 1<= timeout <=63, default="
78 __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
76 79
77static int nowayout = WATCHDOG_NOWAYOUT; 80static int nowayout = WATCHDOG_NOWAYOUT;
78module_param(nowayout, int, 0); 81module_param(nowayout, int, 0);
79MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 82MODULE_PARM_DESC(nowayout,
83 "Watchdog cannot be stopped once started (default="
84 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
80 85
81/* 86/*
82 * Watchdog Operations 87 * Watchdog Operations
83 */ 88 */
84 89
85static void 90static void advwdt_ping(void)
86advwdt_ping(void)
87{ 91{
88 /* Write a watchdog value */ 92 /* Write a watchdog value */
89 outb_p(timeout, wdt_start); 93 outb_p(timeout, wdt_start);
90} 94}
91 95
92static void 96static void advwdt_disable(void)
93advwdt_disable(void)
94{ 97{
95 inb_p(wdt_stop); 98 inb_p(wdt_stop);
96} 99}
97 100
98static int 101static int advwdt_set_heartbeat(int t)
99advwdt_set_heartbeat(int t)
100{ 102{
101 if ((t < 1) || (t > 63)) 103 if (t < 1 || t > 63)
102 return -EINVAL; 104 return -EINVAL;
103
104 timeout = t; 105 timeout = t;
105 return 0; 106 return 0;
106} 107}
@@ -109,8 +110,8 @@ advwdt_set_heartbeat(int t)
109 * /dev/watchdog handling 110 * /dev/watchdog handling
110 */ 111 */
111 112
112static ssize_t 113static ssize_t advwdt_write(struct file *file, const char __user *buf,
113advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 114 size_t count, loff_t *ppos)
114{ 115{
115 if (count) { 116 if (count) {
116 if (!nowayout) { 117 if (!nowayout) {
@@ -120,7 +121,7 @@ advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *pp
120 121
121 for (i = 0; i != count; i++) { 122 for (i = 0; i != count; i++) {
122 char c; 123 char c;
123 if (get_user(c, buf+i)) 124 if (get_user(c, buf + i))
124 return -EFAULT; 125 return -EFAULT;
125 if (c == 'V') 126 if (c == 'V')
126 adv_expect_close = 42; 127 adv_expect_close = 42;
@@ -131,9 +132,7 @@ advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *pp
131 return count; 132 return count;
132} 133}
133 134
134static int 135static long advwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
135advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
136 unsigned long arg)
137{ 136{
138 int new_timeout; 137 int new_timeout;
139 void __user *argp = (void __user *)arg; 138 void __user *argp = (void __user *)arg;
@@ -146,57 +145,50 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
146 145
147 switch (cmd) { 146 switch (cmd) {
148 case WDIOC_GETSUPPORT: 147 case WDIOC_GETSUPPORT:
149 if (copy_to_user(argp, &ident, sizeof(ident))) 148 if (copy_to_user(argp, &ident, sizeof(ident)))
150 return -EFAULT; 149 return -EFAULT;
151 break; 150 break;
152 151
153 case WDIOC_GETSTATUS: 152 case WDIOC_GETSTATUS:
154 case WDIOC_GETBOOTSTATUS: 153 case WDIOC_GETBOOTSTATUS:
155 return put_user(0, p); 154 return put_user(0, p);
156
157 case WDIOC_KEEPALIVE:
158 advwdt_ping();
159 break;
160
161 case WDIOC_SETTIMEOUT:
162 if (get_user(new_timeout, p))
163 return -EFAULT;
164 if (advwdt_set_heartbeat(new_timeout))
165 return -EINVAL;
166 advwdt_ping();
167 /* Fall */
168
169 case WDIOC_GETTIMEOUT:
170 return put_user(timeout, p);
171 155
172 case WDIOC_SETOPTIONS: 156 case WDIOC_SETOPTIONS:
173 { 157 {
174 int options, retval = -EINVAL; 158 int options, retval = -EINVAL;
175
176 if (get_user(options, p))
177 return -EFAULT;
178
179 if (options & WDIOS_DISABLECARD) {
180 advwdt_disable();
181 retval = 0;
182 }
183 159
184 if (options & WDIOS_ENABLECARD) { 160 if (get_user(options, p))
185 advwdt_ping(); 161 return -EFAULT;
186 retval = 0; 162 if (options & WDIOS_DISABLECARD) {
187 } 163 advwdt_disable();
188 164 retval = 0;
189 return retval; 165 }
166 if (options & WDIOS_ENABLECARD) {
167 advwdt_ping();
168 retval = 0;
169 }
170 return retval;
190 } 171 }
172 case WDIOC_KEEPALIVE:
173 advwdt_ping();
174 break;
191 175
176 case WDIOC_SETTIMEOUT:
177 if (get_user(new_timeout, p))
178 return -EFAULT;
179 if (advwdt_set_heartbeat(new_timeout))
180 return -EINVAL;
181 advwdt_ping();
182 /* Fall */
183 case WDIOC_GETTIMEOUT:
184 return put_user(timeout, p);
192 default: 185 default:
193 return -ENOTTY; 186 return -ENOTTY;
194 } 187 }
195 return 0; 188 return 0;
196} 189}
197 190
198static int 191static int advwdt_open(struct inode *inode, struct file *file)
199advwdt_open(struct inode *inode, struct file *file)
200{ 192{
201 if (test_and_set_bit(0, &advwdt_is_open)) 193 if (test_and_set_bit(0, &advwdt_is_open))
202 return -EBUSY; 194 return -EBUSY;
@@ -208,13 +200,13 @@ advwdt_open(struct inode *inode, struct file *file)
208 return nonseekable_open(inode, file); 200 return nonseekable_open(inode, file);
209} 201}
210 202
211static int 203static int advwdt_close(struct inode *inode, struct file *file)
212advwdt_close(struct inode *inode, struct file *file)
213{ 204{
214 if (adv_expect_close == 42) { 205 if (adv_expect_close == 42) {
215 advwdt_disable(); 206 advwdt_disable();
216 } else { 207 } else {
217 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 208 printk(KERN_CRIT PFX
209 "Unexpected close, not stopping watchdog!\n");
218 advwdt_ping(); 210 advwdt_ping();
219 } 211 }
220 clear_bit(0, &advwdt_is_open); 212 clear_bit(0, &advwdt_is_open);
@@ -230,7 +222,7 @@ static const struct file_operations advwdt_fops = {
230 .owner = THIS_MODULE, 222 .owner = THIS_MODULE,
231 .llseek = no_llseek, 223 .llseek = no_llseek,
232 .write = advwdt_write, 224 .write = advwdt_write,
233 .ioctl = advwdt_ioctl, 225 .unlocked_ioctl = advwdt_ioctl,
234 .open = advwdt_open, 226 .open = advwdt_open,
235 .release = advwdt_close, 227 .release = advwdt_close,
236}; 228};
@@ -245,23 +237,24 @@ static struct miscdevice advwdt_miscdev = {
245 * Init & exit routines 237 * Init & exit routines
246 */ 238 */
247 239
248static int __devinit 240static int __devinit advwdt_probe(struct platform_device *dev)
249advwdt_probe(struct platform_device *dev)
250{ 241{
251 int ret; 242 int ret;
252 243
253 if (wdt_stop != wdt_start) { 244 if (wdt_stop != wdt_start) {
254 if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) { 245 if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
255 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", 246 printk(KERN_ERR PFX
256 wdt_stop); 247 "I/O address 0x%04x already in use\n",
248 wdt_stop);
257 ret = -EIO; 249 ret = -EIO;
258 goto out; 250 goto out;
259 } 251 }
260 } 252 }
261 253
262 if (!request_region(wdt_start, 1, WATCHDOG_NAME)) { 254 if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
263 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", 255 printk(KERN_ERR PFX
264 wdt_start); 256 "I/O address 0x%04x already in use\n",
257 wdt_start);
265 ret = -EIO; 258 ret = -EIO;
266 goto unreg_stop; 259 goto unreg_stop;
267 } 260 }
@@ -269,20 +262,19 @@ advwdt_probe(struct platform_device *dev)
269 /* Check that the heartbeat value is within it's range ; if not reset to the default */ 262 /* Check that the heartbeat value is within it's range ; if not reset to the default */
270 if (advwdt_set_heartbeat(timeout)) { 263 if (advwdt_set_heartbeat(timeout)) {
271 advwdt_set_heartbeat(WATCHDOG_TIMEOUT); 264 advwdt_set_heartbeat(WATCHDOG_TIMEOUT);
272 printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n", 265 printk(KERN_INFO PFX
273 timeout); 266 "timeout value must be 1<=x<=63, using %d\n", timeout);
274 } 267 }
275 268
276 ret = misc_register(&advwdt_miscdev); 269 ret = misc_register(&advwdt_miscdev);
277 if (ret != 0) { 270 if (ret != 0) {
278 printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 271 printk(KERN_ERR PFX
279 WATCHDOG_MINOR, ret); 272 "cannot register miscdev on minor=%d (err=%d)\n",
273 WATCHDOG_MINOR, ret);
280 goto unreg_regions; 274 goto unreg_regions;
281 } 275 }
282 276 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
283 printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
284 timeout, nowayout); 277 timeout, nowayout);
285
286out: 278out:
287 return ret; 279 return ret;
288unreg_regions: 280unreg_regions:
@@ -293,19 +285,17 @@ unreg_stop:
293 goto out; 285 goto out;
294} 286}
295 287
296static int __devexit 288static int __devexit advwdt_remove(struct platform_device *dev)
297advwdt_remove(struct platform_device *dev)
298{ 289{
299 misc_deregister(&advwdt_miscdev); 290 misc_deregister(&advwdt_miscdev);
300 release_region(wdt_start,1); 291 release_region(wdt_start, 1);
301 if(wdt_stop != wdt_start) 292 if (wdt_stop != wdt_start)
302 release_region(wdt_stop,1); 293 release_region(wdt_stop, 1);
303 294
304 return 0; 295 return 0;
305} 296}
306 297
307static void 298static void advwdt_shutdown(struct platform_device *dev)
308advwdt_shutdown(struct platform_device *dev)
309{ 299{
310 /* Turn the WDT off if we have a soft shutdown */ 300 /* Turn the WDT off if we have a soft shutdown */
311 advwdt_disable(); 301 advwdt_disable();
@@ -321,18 +311,19 @@ static struct platform_driver advwdt_driver = {
321 }, 311 },
322}; 312};
323 313
324static int __init 314static int __init advwdt_init(void)
325advwdt_init(void)
326{ 315{
327 int err; 316 int err;
328 317
329 printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n"); 318 printk(KERN_INFO
319 "WDT driver for Advantech single board computer initialising.\n");
330 320
331 err = platform_driver_register(&advwdt_driver); 321 err = platform_driver_register(&advwdt_driver);
332 if (err) 322 if (err)
333 return err; 323 return err;
334 324
335 advwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); 325 advwdt_platform_device = platform_device_register_simple(DRV_NAME,
326 -1, NULL, 0);
336 if (IS_ERR(advwdt_platform_device)) { 327 if (IS_ERR(advwdt_platform_device)) {
337 err = PTR_ERR(advwdt_platform_device); 328 err = PTR_ERR(advwdt_platform_device);
338 goto unreg_platform_driver; 329 goto unreg_platform_driver;
@@ -345,8 +336,7 @@ unreg_platform_driver:
345 return err; 336 return err;
346} 337}
347 338
348static void __exit 339static void __exit advwdt_exit(void)
349advwdt_exit(void)
350{ 340{
351 platform_device_unregister(advwdt_platform_device); 341 platform_device_unregister(advwdt_platform_device);
352 platform_driver_unregister(&advwdt_driver); 342 platform_driver_unregister(&advwdt_driver);
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c
index 2b1fbdb2fcf7..2a7690ecf97d 100644
--- a/drivers/watchdog/alim1535_wdt.c
+++ b/drivers/watchdog/alim1535_wdt.c
@@ -18,9 +18,8 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/fs.h> 19#include <linux/fs.h>
20#include <linux/pci.h> 20#include <linux/pci.h>
21 21#include <linux/uaccess.h>
22#include <asm/uaccess.h> 22#include <linux/io.h>
23#include <asm/io.h>
24 23
25#define WATCHDOG_NAME "ALi_M1535" 24#define WATCHDOG_NAME "ALi_M1535"
26#define PFX WATCHDOG_NAME ": " 25#define PFX WATCHDOG_NAME ": "
@@ -30,17 +29,21 @@
30static unsigned long ali_is_open; 29static unsigned long ali_is_open;
31static char ali_expect_release; 30static char ali_expect_release;
32static struct pci_dev *ali_pci; 31static struct pci_dev *ali_pci;
33static u32 ali_timeout_bits; /* stores the computed timeout */ 32static u32 ali_timeout_bits; /* stores the computed timeout */
34static DEFINE_SPINLOCK(ali_lock); /* Guards the hardware */ 33static DEFINE_SPINLOCK(ali_lock); /* Guards the hardware */
35 34
36/* module parameters */ 35/* module parameters */
37static int timeout = WATCHDOG_TIMEOUT; 36static int timeout = WATCHDOG_TIMEOUT;
38module_param(timeout, int, 0); 37module_param(timeout, int, 0);
39MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 38MODULE_PARM_DESC(timeout,
39 "Watchdog timeout in seconds. (0 < timeout < 18000, default="
40 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
40 41
41static int nowayout = WATCHDOG_NOWAYOUT; 42static int nowayout = WATCHDOG_NOWAYOUT;
42module_param(nowayout, int, 0); 43module_param(nowayout, int, 0);
43MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 44MODULE_PARM_DESC(nowayout,
45 "Watchdog cannot be stopped once started (default="
46 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
44 47
45/* 48/*
46 * ali_start - start watchdog countdown 49 * ali_start - start watchdog countdown
@@ -103,15 +106,16 @@ static void ali_keepalive(void)
103 106
104static int ali_settimer(int t) 107static int ali_settimer(int t)
105{ 108{
106 if(t < 0) 109 if (t < 0)
107 return -EINVAL; 110 return -EINVAL;
108 else if(t < 60) 111 else if (t < 60)
109 ali_timeout_bits = t|(1<<6); 112 ali_timeout_bits = t|(1<<6);
110 else if(t < 3600) 113 else if (t < 3600)
111 ali_timeout_bits = (t/60)|(1<<7); 114 ali_timeout_bits = (t/60)|(1<<7);
112 else if(t < 18000) 115 else if (t < 18000)
113 ali_timeout_bits = (t/300)|(1<<6)|(1<<7); 116 ali_timeout_bits = (t/300)|(1<<6)|(1<<7);
114 else return -EINVAL; 117 else
118 return -EINVAL;
115 119
116 timeout = t; 120 timeout = t;
117 return 0; 121 return 0;
@@ -134,21 +138,22 @@ static int ali_settimer(int t)
134 */ 138 */
135 139
136static ssize_t ali_write(struct file *file, const char __user *data, 140static ssize_t ali_write(struct file *file, const char __user *data,
137 size_t len, loff_t * ppos) 141 size_t len, loff_t *ppos)
138{ 142{
139 /* See if we got the magic character 'V' and reload the timer */ 143 /* See if we got the magic character 'V' and reload the timer */
140 if (len) { 144 if (len) {
141 if (!nowayout) { 145 if (!nowayout) {
142 size_t i; 146 size_t i;
143 147
144 /* note: just in case someone wrote the magic character 148 /* note: just in case someone wrote the
145 * five months ago... */ 149 magic character five months ago... */
146 ali_expect_release = 0; 150 ali_expect_release = 0;
147 151
148 /* scan to see whether or not we got the magic character */ 152 /* scan to see whether or not we got
153 the magic character */
149 for (i = 0; i != len; i++) { 154 for (i = 0; i != len; i++) {
150 char c; 155 char c;
151 if(get_user(c, data+i)) 156 if (get_user(c, data + i))
152 return -EFAULT; 157 return -EFAULT;
153 if (c == 'V') 158 if (c == 'V')
154 ali_expect_release = 42; 159 ali_expect_release = 42;
@@ -163,7 +168,6 @@ static ssize_t ali_write(struct file *file, const char __user *data,
163 168
164/* 169/*
165 * ali_ioctl - handle watchdog ioctls 170 * ali_ioctl - handle watchdog ioctls
166 * @inode: VFS inode
167 * @file: VFS file pointer 171 * @file: VFS file pointer
168 * @cmd: ioctl number 172 * @cmd: ioctl number
169 * @arg: arguments to the ioctl 173 * @arg: arguments to the ioctl
@@ -172,8 +176,7 @@ static ssize_t ali_write(struct file *file, const char __user *data,
172 * we want an extension to enable irq ack monitoring and the like 176 * we want an extension to enable irq ack monitoring and the like
173 */ 177 */
174 178
175static int ali_ioctl(struct inode *inode, struct file *file, 179static long ali_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
176 unsigned int cmd, unsigned long arg)
177{ 180{
178 void __user *argp = (void __user *)arg; 181 void __user *argp = (void __user *)arg;
179 int __user *p = argp; 182 int __user *p = argp;
@@ -186,57 +189,45 @@ static int ali_ioctl(struct inode *inode, struct file *file,
186 }; 189 };
187 190
188 switch (cmd) { 191 switch (cmd) {
189 case WDIOC_GETSUPPORT: 192 case WDIOC_GETSUPPORT:
190 return copy_to_user(argp, &ident, 193 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
191 sizeof (ident)) ? -EFAULT : 0; 194
192 195 case WDIOC_GETSTATUS:
193 case WDIOC_GETSTATUS: 196 case WDIOC_GETBOOTSTATUS:
194 case WDIOC_GETBOOTSTATUS: 197 return put_user(0, p);
195 return put_user(0, p); 198 case WDIOC_SETOPTIONS:
196 199 {
197 case WDIOC_KEEPALIVE: 200 int new_options, retval = -EINVAL;
198 ali_keepalive(); 201
199 return 0; 202 if (get_user(new_options, p))
200 203 return -EFAULT;
201 case WDIOC_SETOPTIONS: 204 if (new_options & WDIOS_DISABLECARD) {
202 { 205 ali_stop();
203 int new_options, retval = -EINVAL; 206 retval = 0;
204
205 if (get_user (new_options, p))
206 return -EFAULT;
207
208 if (new_options & WDIOS_DISABLECARD) {
209 ali_stop();
210 retval = 0;
211 }
212
213 if (new_options & WDIOS_ENABLECARD) {
214 ali_start();
215 retval = 0;
216 }
217
218 return retval;
219 } 207 }
220 208 if (new_options & WDIOS_ENABLECARD) {
221 case WDIOC_SETTIMEOUT: 209 ali_start();
222 { 210 retval = 0;
223 int new_timeout;
224
225 if (get_user(new_timeout, p))
226 return -EFAULT;
227
228 if (ali_settimer(new_timeout))
229 return -EINVAL;
230
231 ali_keepalive();
232 /* Fall */
233 } 211 }
234 212 return retval;
235 case WDIOC_GETTIMEOUT: 213 }
236 return put_user(timeout, p); 214 case WDIOC_KEEPALIVE:
237 215 ali_keepalive();
238 default: 216 return 0;
239 return -ENOTTY; 217 case WDIOC_SETTIMEOUT:
218 {
219 int new_timeout;
220 if (get_user(new_timeout, p))
221 return -EFAULT;
222 if (ali_settimer(new_timeout))
223 return -EINVAL;
224 ali_keepalive();
225 /* Fall */
226 }
227 case WDIOC_GETTIMEOUT:
228 return put_user(timeout, p);
229 default:
230 return -ENOTTY;
240 } 231 }
241} 232}
242 233
@@ -274,10 +265,11 @@ static int ali_release(struct inode *inode, struct file *file)
274 /* 265 /*
275 * Shut off the timer. 266 * Shut off the timer.
276 */ 267 */
277 if (ali_expect_release == 42) { 268 if (ali_expect_release == 42)
278 ali_stop(); 269 ali_stop();
279 } else { 270 else {
280 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 271 printk(KERN_CRIT PFX
272 "Unexpected close, not stopping watchdog!\n");
281 ali_keepalive(); 273 ali_keepalive();
282 } 274 }
283 clear_bit(0, &ali_is_open); 275 clear_bit(0, &ali_is_open);
@@ -292,13 +284,11 @@ static int ali_release(struct inode *inode, struct file *file)
292 */ 284 */
293 285
294 286
295static int ali_notify_sys(struct notifier_block *this, unsigned long code, void *unused) 287static int ali_notify_sys(struct notifier_block *this,
288 unsigned long code, void *unused)
296{ 289{
297 if (code==SYS_DOWN || code==SYS_HALT) { 290 if (code == SYS_DOWN || code == SYS_HALT)
298 /* Turn the WDT off */ 291 ali_stop(); /* Turn the WDT off */
299 ali_stop();
300 }
301
302 return NOTIFY_DONE; 292 return NOTIFY_DONE;
303} 293}
304 294
@@ -340,10 +330,10 @@ static int __init ali_find_watchdog(void)
340 330
341 /* Check for the a 7101 PMU */ 331 /* Check for the a 7101 PMU */
342 pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL); 332 pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL);
343 if(pdev == NULL) 333 if (pdev == NULL)
344 return -ENODEV; 334 return -ENODEV;
345 335
346 if(pci_enable_device(pdev)) { 336 if (pci_enable_device(pdev)) {
347 pci_dev_put(pdev); 337 pci_dev_put(pdev);
348 return -EIO; 338 return -EIO;
349 } 339 }
@@ -355,9 +345,12 @@ static int __init ali_find_watchdog(void)
355 */ 345 */
356 pci_read_config_dword(pdev, 0xCC, &wdog); 346 pci_read_config_dword(pdev, 0xCC, &wdog);
357 347
358 wdog &= ~0x3F; /* Timer bits */ 348 /* Timer bits */
359 wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24)); /* Issued events */ 349 wdog &= ~0x3F;
360 wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)); /* No monitor bits */ 350 /* Issued events */
351 wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24));
352 /* No monitor bits */
353 wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9));
361 354
362 pci_write_config_dword(pdev, 0xCC, wdog); 355 pci_write_config_dword(pdev, 0xCC, wdog);
363 356
@@ -369,12 +362,12 @@ static int __init ali_find_watchdog(void)
369 */ 362 */
370 363
371static const struct file_operations ali_fops = { 364static const struct file_operations ali_fops = {
372 .owner = THIS_MODULE, 365 .owner = THIS_MODULE,
373 .llseek = no_llseek, 366 .llseek = no_llseek,
374 .write = ali_write, 367 .write = ali_write,
375 .ioctl = ali_ioctl, 368 .unlocked_ioctl = ali_ioctl,
376 .open = ali_open, 369 .open = ali_open,
377 .release = ali_release, 370 .release = ali_release,
378}; 371};
379 372
380static struct miscdevice ali_miscdev = { 373static struct miscdevice ali_miscdev = {
@@ -399,15 +392,16 @@ static int __init watchdog_init(void)
399 int ret; 392 int ret;
400 393
401 /* Check whether or not the hardware watchdog is there */ 394 /* Check whether or not the hardware watchdog is there */
402 if (ali_find_watchdog() != 0) { 395 if (ali_find_watchdog() != 0)
403 return -ENODEV; 396 return -ENODEV;
404 }
405 397
406 /* Check that the timeout value is within it's range ; if not reset to the default */ 398 /* Check that the timeout value is within it's range;
399 if not reset to the default */
407 if (timeout < 1 || timeout >= 18000) { 400 if (timeout < 1 || timeout >= 18000) {
408 timeout = WATCHDOG_TIMEOUT; 401 timeout = WATCHDOG_TIMEOUT;
409 printk(KERN_INFO PFX "timeout value must be 0<timeout<18000, using %d\n", 402 printk(KERN_INFO PFX
410 timeout); 403 "timeout value must be 0 < timeout < 18000, using %d\n",
404 timeout);
411 } 405 }
412 406
413 /* Calculate the watchdog's timeout */ 407 /* Calculate the watchdog's timeout */
@@ -415,15 +409,16 @@ static int __init watchdog_init(void)
415 409
416 ret = register_reboot_notifier(&ali_notifier); 410 ret = register_reboot_notifier(&ali_notifier);
417 if (ret != 0) { 411 if (ret != 0) {
418 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 412 printk(KERN_ERR PFX
419 ret); 413 "cannot register reboot notifier (err=%d)\n", ret);
420 goto out; 414 goto out;
421 } 415 }
422 416
423 ret = misc_register(&ali_miscdev); 417 ret = misc_register(&ali_miscdev);
424 if (ret != 0) { 418 if (ret != 0) {
425 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 419 printk(KERN_ERR PFX
426 WATCHDOG_MINOR, ret); 420 "cannot register miscdev on minor=%d (err=%d)\n",
421 WATCHDOG_MINOR, ret);
427 goto unreg_reboot; 422 goto unreg_reboot;
428 } 423 }
429 424
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c
index 238273c98656..a045ef869439 100644
--- a/drivers/watchdog/alim7101_wdt.c
+++ b/drivers/watchdog/alim7101_wdt.c
@@ -31,9 +31,9 @@
31#include <linux/init.h> 31#include <linux/init.h>
32#include <linux/fs.h> 32#include <linux/fs.h>
33#include <linux/pci.h> 33#include <linux/pci.h>
34#include <linux/io.h>
35#include <linux/uaccess.h>
34 36
35#include <asm/io.h>
36#include <asm/uaccess.h>
37#include <asm/system.h> 37#include <asm/system.h>
38 38
39#define OUR_NAME "alim7101_wdt" 39#define OUR_NAME "alim7101_wdt"
@@ -60,13 +60,17 @@
60 */ 60 */
61 61
62#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ 62#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */
63static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ 63/* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
64static int timeout = WATCHDOG_TIMEOUT;
64module_param(timeout, int, 0); 65module_param(timeout, int, 0);
65MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 66MODULE_PARM_DESC(timeout,
67 "Watchdog timeout in seconds. (1<=timeout<=3600, default="
68 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
66 69
67static int use_gpio = 0; /* Use the pic (for a1d revision alim7101) */ 70static int use_gpio; /* Use the pic (for a1d revision alim7101) */
68module_param(use_gpio, int, 0); 71module_param(use_gpio, int, 0);
69MODULE_PARM_DESC(use_gpio, "Use the gpio watchdog. (required by old cobalt boards)"); 72MODULE_PARM_DESC(use_gpio,
73 "Use the gpio watchdog (required by old cobalt boards).");
70 74
71static void wdt_timer_ping(unsigned long); 75static void wdt_timer_ping(unsigned long);
72static DEFINE_TIMER(timer, wdt_timer_ping, 0, 1); 76static DEFINE_TIMER(timer, wdt_timer_ping, 0, 1);
@@ -77,8 +81,9 @@ static struct pci_dev *alim7101_pmu;
77 81
78static int nowayout = WATCHDOG_NOWAYOUT; 82static int nowayout = WATCHDOG_NOWAYOUT;
79module_param(nowayout, int, 0); 83module_param(nowayout, int, 0);
80MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 84MODULE_PARM_DESC(nowayout,
81 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 85 "Watchdog cannot be stopped once started (default="
86 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
82 87
83/* 88/*
84 * Whack the dog 89 * Whack the dog
@@ -89,23 +94,26 @@ static void wdt_timer_ping(unsigned long data)
89 /* If we got a heartbeat pulse within the WDT_US_INTERVAL 94 /* If we got a heartbeat pulse within the WDT_US_INTERVAL
90 * we agree to ping the WDT 95 * we agree to ping the WDT
91 */ 96 */
92 char tmp; 97 char tmp;
93 98
94 if(time_before(jiffies, next_heartbeat)) 99 if (time_before(jiffies, next_heartbeat)) {
95 {
96 /* Ping the WDT (this is actually a disarm/arm sequence) */ 100 /* Ping the WDT (this is actually a disarm/arm sequence) */
97 pci_read_config_byte(alim7101_pmu, 0x92, &tmp); 101 pci_read_config_byte(alim7101_pmu, 0x92, &tmp);
98 pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp & ~ALI_WDT_ARM)); 102 pci_write_config_byte(alim7101_pmu,
99 pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp | ALI_WDT_ARM)); 103 ALI_7101_WDT, (tmp & ~ALI_WDT_ARM));
104 pci_write_config_byte(alim7101_pmu,
105 ALI_7101_WDT, (tmp | ALI_WDT_ARM));
100 if (use_gpio) { 106 if (use_gpio) {
101 pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp); 107 pci_read_config_byte(alim7101_pmu,
102 pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp 108 ALI_7101_GPIO_O, &tmp);
103 | 0x20); 109 pci_write_config_byte(alim7101_pmu,
104 pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp 110 ALI_7101_GPIO_O, tmp | 0x20);
105 & ~0x20); 111 pci_write_config_byte(alim7101_pmu,
112 ALI_7101_GPIO_O, tmp & ~0x20);
106 } 113 }
107 } else { 114 } else {
108 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); 115 printk(KERN_WARNING PFX
116 "Heartbeat lost! Will not ping the watchdog\n");
109 } 117 }
110 /* Re-set the timer interval */ 118 /* Re-set the timer interval */
111 mod_timer(&timer, jiffies + WDT_INTERVAL); 119 mod_timer(&timer, jiffies + WDT_INTERVAL);
@@ -117,21 +125,27 @@ static void wdt_timer_ping(unsigned long data)
117 125
118static void wdt_change(int writeval) 126static void wdt_change(int writeval)
119{ 127{
120 char tmp; 128 char tmp;
121 129
122 pci_read_config_byte(alim7101_pmu, ALI_7101_WDT, &tmp); 130 pci_read_config_byte(alim7101_pmu, ALI_7101_WDT, &tmp);
123 if (writeval == WDT_ENABLE) { 131 if (writeval == WDT_ENABLE) {
124 pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp | ALI_WDT_ARM)); 132 pci_write_config_byte(alim7101_pmu,
133 ALI_7101_WDT, (tmp | ALI_WDT_ARM));
125 if (use_gpio) { 134 if (use_gpio) {
126 pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp); 135 pci_read_config_byte(alim7101_pmu,
127 pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp & ~0x20); 136 ALI_7101_GPIO_O, &tmp);
137 pci_write_config_byte(alim7101_pmu,
138 ALI_7101_GPIO_O, tmp & ~0x20);
128 } 139 }
129 140
130 } else { 141 } else {
131 pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp & ~ALI_WDT_ARM)); 142 pci_write_config_byte(alim7101_pmu,
143 ALI_7101_WDT, (tmp & ~ALI_WDT_ARM));
132 if (use_gpio) { 144 if (use_gpio) {
133 pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp); 145 pci_read_config_byte(alim7101_pmu,
134 pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp | 0x20); 146 ALI_7101_GPIO_O, &tmp);
147 pci_write_config_byte(alim7101_pmu,
148 ALI_7101_GPIO_O, tmp | 0x20);
135 } 149 }
136 } 150 }
137} 151}
@@ -169,10 +183,11 @@ static void wdt_keepalive(void)
169 * /dev/watchdog handling 183 * /dev/watchdog handling
170 */ 184 */
171 185
172static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) 186static ssize_t fop_write(struct file *file, const char __user *buf,
187 size_t count, loff_t *ppos)
173{ 188{
174 /* See if we got the magic character 'V' and reload the timer */ 189 /* See if we got the magic character 'V' and reload the timer */
175 if(count) { 190 if (count) {
176 if (!nowayout) { 191 if (!nowayout) {
177 size_t ofs; 192 size_t ofs;
178 193
@@ -183,7 +198,7 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou
183 /* now scan */ 198 /* now scan */
184 for (ofs = 0; ofs != count; ofs++) { 199 for (ofs = 0; ofs != count; ofs++) {
185 char c; 200 char c;
186 if (get_user(c, buf+ofs)) 201 if (get_user(c, buf + ofs))
187 return -EFAULT; 202 return -EFAULT;
188 if (c == 'V') 203 if (c == 'V')
189 wdt_expect_close = 42; 204 wdt_expect_close = 42;
@@ -195,119 +210,116 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou
195 return count; 210 return count;
196} 211}
197 212
198static int fop_open(struct inode * inode, struct file * file) 213static int fop_open(struct inode *inode, struct file *file)
199{ 214{
200 /* Just in case we're already talking to someone... */ 215 /* Just in case we're already talking to someone... */
201 if(test_and_set_bit(0, &wdt_is_open)) 216 if (test_and_set_bit(0, &wdt_is_open))
202 return -EBUSY; 217 return -EBUSY;
203 /* Good, fire up the show */ 218 /* Good, fire up the show */
204 wdt_startup(); 219 wdt_startup();
205 return nonseekable_open(inode, file); 220 return nonseekable_open(inode, file);
206} 221}
207 222
208static int fop_close(struct inode * inode, struct file * file) 223static int fop_close(struct inode *inode, struct file *file)
209{ 224{
210 if(wdt_expect_close == 42) 225 if (wdt_expect_close == 42)
211 wdt_turnoff(); 226 wdt_turnoff();
212 else { 227 else {
213 /* wim: shouldn't there be a: del_timer(&timer); */ 228 /* wim: shouldn't there be a: del_timer(&timer); */
214 printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n"); 229 printk(KERN_CRIT PFX
230 "device file closed unexpectedly. Will not stop the WDT!\n");
215 } 231 }
216 clear_bit(0, &wdt_is_open); 232 clear_bit(0, &wdt_is_open);
217 wdt_expect_close = 0; 233 wdt_expect_close = 0;
218 return 0; 234 return 0;
219} 235}
220 236
221static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 237static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
222{ 238{
223 void __user *argp = (void __user *)arg; 239 void __user *argp = (void __user *)arg;
224 int __user *p = argp; 240 int __user *p = argp;
225 static struct watchdog_info ident = 241 static struct watchdog_info ident = {
226 { 242 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
227 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 243 | WDIOF_MAGICCLOSE,
228 .firmware_version = 1, 244 .firmware_version = 1,
229 .identity = "ALiM7101", 245 .identity = "ALiM7101",
230 }; 246 };
231 247
232 switch(cmd) 248 switch (cmd) {
249 case WDIOC_GETSUPPORT:
250 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
251 case WDIOC_GETSTATUS:
252 case WDIOC_GETBOOTSTATUS:
253 return put_user(0, p);
254 case WDIOC_SETOPTIONS:
233 { 255 {
234 case WDIOC_GETSUPPORT: 256 int new_options, retval = -EINVAL;
235 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
236 case WDIOC_GETSTATUS:
237 case WDIOC_GETBOOTSTATUS:
238 return put_user(0, p);
239 case WDIOC_KEEPALIVE:
240 wdt_keepalive();
241 return 0;
242 case WDIOC_SETOPTIONS:
243 {
244 int new_options, retval = -EINVAL;
245
246 if(get_user(new_options, p))
247 return -EFAULT;
248
249 if(new_options & WDIOS_DISABLECARD) {
250 wdt_turnoff();
251 retval = 0;
252 }
253 257
254 if(new_options & WDIOS_ENABLECARD) { 258 if (get_user(new_options, p))
255 wdt_startup(); 259 return -EFAULT;
256 retval = 0; 260 if (new_options & WDIOS_DISABLECARD) {
257 } 261 wdt_turnoff();
258 262 retval = 0;
259 return retval;
260 } 263 }
261 case WDIOC_SETTIMEOUT: 264 if (new_options & WDIOS_ENABLECARD) {
262 { 265 wdt_startup();
263 int new_timeout; 266 retval = 0;
264
265 if(get_user(new_timeout, p))
266 return -EFAULT;
267
268 if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
269 return -EINVAL;
270
271 timeout = new_timeout;
272 wdt_keepalive();
273 /* Fall through */
274 } 267 }
275 case WDIOC_GETTIMEOUT: 268 return retval;
276 return put_user(timeout, p); 269 }
277 default: 270 case WDIOC_KEEPALIVE:
278 return -ENOTTY; 271 wdt_keepalive();
272 return 0;
273 case WDIOC_SETTIMEOUT:
274 {
275 int new_timeout;
276
277 if (get_user(new_timeout, p))
278 return -EFAULT;
279 /* arbitrary upper limit */
280 if (new_timeout < 1 || new_timeout > 3600)
281 return -EINVAL;
282 timeout = new_timeout;
283 wdt_keepalive();
284 /* Fall through */
285 }
286 case WDIOC_GETTIMEOUT:
287 return put_user(timeout, p);
288 default:
289 return -ENOTTY;
279 } 290 }
280} 291}
281 292
282static const struct file_operations wdt_fops = { 293static const struct file_operations wdt_fops = {
283 .owner= THIS_MODULE, 294 .owner = THIS_MODULE,
284 .llseek= no_llseek, 295 .llseek = no_llseek,
285 .write= fop_write, 296 .write = fop_write,
286 .open= fop_open, 297 .open = fop_open,
287 .release= fop_close, 298 .release = fop_close,
288 .ioctl= fop_ioctl, 299 .unlocked_ioctl = fop_ioctl,
289}; 300};
290 301
291static struct miscdevice wdt_miscdev = { 302static struct miscdevice wdt_miscdev = {
292 .minor=WATCHDOG_MINOR, 303 .minor = WATCHDOG_MINOR,
293 .name="watchdog", 304 .name = "watchdog",
294 .fops=&wdt_fops, 305 .fops = &wdt_fops,
295}; 306};
296 307
297/* 308/*
298 * Notifier for system down 309 * Notifier for system down
299 */ 310 */
300 311
301static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) 312static int wdt_notify_sys(struct notifier_block *this,
313 unsigned long code, void *unused)
302{ 314{
303 if (code==SYS_DOWN || code==SYS_HALT) 315 if (code == SYS_DOWN || code == SYS_HALT)
304 wdt_turnoff(); 316 wdt_turnoff();
305 317
306 if (code==SYS_RESTART) { 318 if (code == SYS_RESTART) {
307 /* 319 /*
308 * Cobalt devices have no way of rebooting themselves other than 320 * Cobalt devices have no way of rebooting themselves other
309 * getting the watchdog to pull reset, so we restart the watchdog on 321 * than getting the watchdog to pull reset, so we restart the
310 * reboot with no heartbeat 322 * watchdog on reboot with no heartbeat
311 */ 323 */
312 wdt_change(WDT_ENABLE); 324 wdt_change(WDT_ENABLE);
313 printk(KERN_INFO PFX "Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.\n"); 325 printk(KERN_INFO PFX "Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.\n");
@@ -320,8 +332,7 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void
320 * turn the timebomb registers off. 332 * turn the timebomb registers off.
321 */ 333 */
322 334
323static struct notifier_block wdt_notifier= 335static struct notifier_block wdt_notifier = {
324{
325 .notifier_call = wdt_notify_sys, 336 .notifier_call = wdt_notify_sys,
326}; 337};
327 338
@@ -354,7 +365,8 @@ static int __init alim7101_wdt_init(void)
354 ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 365 ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
355 NULL); 366 NULL);
356 if (!ali1543_south) { 367 if (!ali1543_south) {
357 printk(KERN_INFO PFX "ALi 1543 South-Bridge not present - WDT not set\n"); 368 printk(KERN_INFO PFX
369 "ALi 1543 South-Bridge not present - WDT not set\n");
358 goto err_out; 370 goto err_out;
359 } 371 }
360 pci_read_config_byte(ali1543_south, 0x5e, &tmp); 372 pci_read_config_byte(ali1543_south, 0x5e, &tmp);
@@ -363,24 +375,25 @@ static int __init alim7101_wdt_init(void)
363 if (!use_gpio) { 375 if (!use_gpio) {
364 printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'. If this is a cobalt board, set the 'use_gpio' module parameter.\n"); 376 printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'. If this is a cobalt board, set the 'use_gpio' module parameter.\n");
365 goto err_out; 377 goto err_out;
366 } 378 }
367 nowayout = 1; 379 nowayout = 1;
368 } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) { 380 } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) {
369 printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n"); 381 printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n");
370 goto err_out; 382 goto err_out;
371 } 383 }
372 384
373 if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ 385 if (timeout < 1 || timeout > 3600) {
374 { 386 /* arbitrary upper limit */
375 timeout = WATCHDOG_TIMEOUT; 387 timeout = WATCHDOG_TIMEOUT;
376 printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", 388 printk(KERN_INFO PFX
377 timeout); 389 "timeout value must be 1 <= x <= 3600, using %d\n",
390 timeout);
378 } 391 }
379 392
380 rc = register_reboot_notifier(&wdt_notifier); 393 rc = register_reboot_notifier(&wdt_notifier);
381 if (rc) { 394 if (rc) {
382 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 395 printk(KERN_ERR PFX
383 rc); 396 "cannot register reboot notifier (err=%d)\n", rc);
384 goto err_out; 397 goto err_out;
385 } 398 }
386 399
@@ -391,9 +404,8 @@ static int __init alim7101_wdt_init(void)
391 goto err_out_reboot; 404 goto err_out_reboot;
392 } 405 }
393 406
394 if (nowayout) { 407 if (nowayout)
395 __module_get(THIS_MODULE); 408 __module_get(THIS_MODULE);
396 }
397 409
398 printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n", 410 printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n",
399 timeout, nowayout); 411 timeout, nowayout);
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index ef7b0d67095e..55dcbfe2bb72 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -213,7 +213,7 @@ static int ar7_wdt_notify_sys(struct notifier_block *this,
213} 213}
214 214
215static struct notifier_block ar7_wdt_notifier = { 215static struct notifier_block ar7_wdt_notifier = {
216 .notifier_call = ar7_wdt_notify_sys 216 .notifier_call = ar7_wdt_notify_sys,
217}; 217};
218 218
219static ssize_t ar7_wdt_write(struct file *file, const char *data, 219static ssize_t ar7_wdt_write(struct file *file, const char *data,
@@ -230,7 +230,7 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data,
230 expect_close = 0; 230 expect_close = 0;
231 for (i = 0; i < len; ++i) { 231 for (i = 0; i < len; ++i) {
232 char c; 232 char c;
233 if (get_user(c, data+i)) 233 if (get_user(c, data + i))
234 return -EFAULT; 234 return -EFAULT;
235 if (c == 'V') 235 if (c == 'V')
236 expect_close = 1; 236 expect_close = 1;
@@ -251,8 +251,6 @@ static long ar7_wdt_ioctl(struct file *file,
251 int new_margin; 251 int new_margin;
252 252
253 switch (cmd) { 253 switch (cmd) {
254 default:
255 return -ENOTTY;
256 case WDIOC_GETSUPPORT: 254 case WDIOC_GETSUPPORT:
257 if (copy_to_user((struct watchdog_info *)arg, &ident, 255 if (copy_to_user((struct watchdog_info *)arg, &ident,
258 sizeof(ident))) 256 sizeof(ident)))
@@ -281,6 +279,8 @@ static long ar7_wdt_ioctl(struct file *file,
281 if (put_user(margin, (int *)arg)) 279 if (put_user(margin, (int *)arg))
282 return -EFAULT; 280 return -EFAULT;
283 return 0; 281 return 0;
282 default:
283 return -ENOTTY;
284 } 284 }
285} 285}
286 286
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
index ae0fca5e8749..e8ae638e5804 100644
--- a/drivers/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
@@ -212,8 +212,8 @@ static struct watchdog_info at32_wdt_info = {
212/* 212/*
213 * Handle commands from user-space. 213 * Handle commands from user-space.
214 */ 214 */
215static int at32_wdt_ioctl(struct inode *inode, struct file *file, 215static long at32_wdt_ioctl(struct file *file,
216 unsigned int cmd, unsigned long arg) 216 unsigned int cmd, unsigned long arg)
217{ 217{
218 int ret = -ENOTTY; 218 int ret = -ENOTTY;
219 int time; 219 int time;
@@ -221,27 +221,10 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file,
221 int __user *p = argp; 221 int __user *p = argp;
222 222
223 switch (cmd) { 223 switch (cmd) {
224 case WDIOC_KEEPALIVE:
225 at32_wdt_pat();
226 ret = 0;
227 break;
228 case WDIOC_GETSUPPORT: 224 case WDIOC_GETSUPPORT:
229 ret = copy_to_user(argp, &at32_wdt_info, 225 ret = copy_to_user(argp, &at32_wdt_info,
230 sizeof(at32_wdt_info)) ? -EFAULT : 0; 226 sizeof(at32_wdt_info)) ? -EFAULT : 0;
231 break; 227 break;
232 case WDIOC_SETTIMEOUT:
233 ret = get_user(time, p);
234 if (ret)
235 break;
236 ret = at32_wdt_settimeout(time);
237 if (ret)
238 break;
239 /* Enable new time value */
240 at32_wdt_start();
241 /* fall through */
242 case WDIOC_GETTIMEOUT:
243 ret = put_user(wdt->timeout, p);
244 break;
245 case WDIOC_GETSTATUS: 228 case WDIOC_GETSTATUS:
246 ret = put_user(0, p); 229 ret = put_user(0, p);
247 break; 230 break;
@@ -258,6 +241,23 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file,
258 at32_wdt_start(); 241 at32_wdt_start();
259 ret = 0; 242 ret = 0;
260 break; 243 break;
244 case WDIOC_KEEPALIVE:
245 at32_wdt_pat();
246 ret = 0;
247 break;
248 case WDIOC_SETTIMEOUT:
249 ret = get_user(time, p);
250 if (ret)
251 break;
252 ret = at32_wdt_settimeout(time);
253 if (ret)
254 break;
255 /* Enable new time value */
256 at32_wdt_start();
257 /* fall through */
258 case WDIOC_GETTIMEOUT:
259 ret = put_user(wdt->timeout, p);
260 break;
261 } 261 }
262 262
263 return ret; 263 return ret;
@@ -283,7 +283,7 @@ static ssize_t at32_wdt_write(struct file *file, const char __user *data,
283 */ 283 */
284 for (i = 0; i != len; i++) { 284 for (i = 0; i != len; i++) {
285 char c; 285 char c;
286 if (get_user(c, data+i)) 286 if (get_user(c, data + i))
287 return -EFAULT; 287 return -EFAULT;
288 if (c == 'V') 288 if (c == 'V')
289 expect_release = 42; 289 expect_release = 42;
@@ -298,7 +298,7 @@ static ssize_t at32_wdt_write(struct file *file, const char __user *data,
298static const struct file_operations at32_wdt_fops = { 298static const struct file_operations at32_wdt_fops = {
299 .owner = THIS_MODULE, 299 .owner = THIS_MODULE,
300 .llseek = no_llseek, 300 .llseek = no_llseek,
301 .ioctl = at32_wdt_ioctl, 301 .unlocked_ioctl = at32_wdt_ioctl,
302 .open = at32_wdt_open, 302 .open = at32_wdt_open,
303 .release = at32_wdt_close, 303 .release = at32_wdt_close,
304 .write = at32_wdt_write, 304 .write = at32_wdt_write,
@@ -391,7 +391,6 @@ static int __exit at32_wdt_remove(struct platform_device *pdev)
391 wdt = NULL; 391 wdt = NULL;
392 platform_set_drvdata(pdev, NULL); 392 platform_set_drvdata(pdev, NULL);
393 } 393 }
394
395 return 0; 394 return 0;
396} 395}
397 396
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index 9ff9a9565320..2313f44144f8 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -20,7 +20,7 @@
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/types.h> 21#include <linux/types.h>
22#include <linux/watchdog.h> 22#include <linux/watchdog.h>
23#include <asm/uaccess.h> 23#include <linux/uaccess.h>
24#include <asm/arch/at91_st.h> 24#include <asm/arch/at91_st.h>
25 25
26 26
@@ -31,11 +31,14 @@ static int wdt_time = WDT_DEFAULT_TIME;
31static int nowayout = WATCHDOG_NOWAYOUT; 31static int nowayout = WATCHDOG_NOWAYOUT;
32 32
33module_param(wdt_time, int, 0); 33module_param(wdt_time, int, 0);
34MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); 34MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
35 __MODULE_STRING(WDT_DEFAULT_TIME) ")");
35 36
36#ifdef CONFIG_WATCHDOG_NOWAYOUT 37#ifdef CONFIG_WATCHDOG_NOWAYOUT
37module_param(nowayout, int, 0); 38module_param(nowayout, int, 0);
38MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 39MODULE_PARM_DESC(nowayout,
40 "Watchdog cannot be stopped once started (default="
41 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
39#endif 42#endif
40 43
41 44
@@ -46,7 +49,7 @@ static unsigned long at91wdt_busy;
46/* 49/*
47 * Disable the watchdog. 50 * Disable the watchdog.
48 */ 51 */
49static void inline at91_wdt_stop(void) 52static inline void at91_wdt_stop(void)
50{ 53{
51 at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); 54 at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN);
52} 55}
@@ -54,16 +57,17 @@ static void inline at91_wdt_stop(void)
54/* 57/*
55 * Enable and reset the watchdog. 58 * Enable and reset the watchdog.
56 */ 59 */
57static void inline at91_wdt_start(void) 60static inline void at91_wdt_start(void)
58{ 61{
59 at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); 62 at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN |
63 (((65536 * wdt_time) >> 8) & AT91_ST_WDV));
60 at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); 64 at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
61} 65}
62 66
63/* 67/*
64 * Reload the watchdog timer. (ie, pat the watchdog) 68 * Reload the watchdog timer. (ie, pat the watchdog)
65 */ 69 */
66static void inline at91_wdt_reload(void) 70static inline void at91_wdt_reload(void)
67{ 71{
68 at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); 72 at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
69} 73}
@@ -89,8 +93,9 @@ static int at91_wdt_open(struct inode *inode, struct file *file)
89 */ 93 */
90static int at91_wdt_close(struct inode *inode, struct file *file) 94static int at91_wdt_close(struct inode *inode, struct file *file)
91{ 95{
96 /* Disable the watchdog when file is closed */
92 if (!nowayout) 97 if (!nowayout)
93 at91_wdt_stop(); /* Disable the watchdog when file is closed */ 98 at91_wdt_stop();
94 99
95 clear_bit(0, &at91wdt_busy); 100 clear_bit(0, &at91wdt_busy);
96 return 0; 101 return 0;
@@ -110,7 +115,8 @@ static int at91_wdt_settimeout(int new_time)
110 if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) 115 if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
111 return -EINVAL; 116 return -EINVAL;
112 117
113 /* Set new watchdog time. It will be used when at91_wdt_start() is called. */ 118 /* Set new watchdog time. It will be used when
119 at91_wdt_start() is called. */
114 wdt_time = new_time; 120 wdt_time = new_time;
115 return 0; 121 return 0;
116} 122}
@@ -123,60 +129,52 @@ static struct watchdog_info at91_wdt_info = {
123/* 129/*
124 * Handle commands from user-space. 130 * Handle commands from user-space.
125 */ 131 */
126static int at91_wdt_ioctl(struct inode *inode, struct file *file, 132static long at91_wdt_ioct(struct file *file,
127 unsigned int cmd, unsigned long arg) 133 unsigned int cmd, unsigned long arg)
128{ 134{
129 void __user *argp = (void __user *)arg; 135 void __user *argp = (void __user *)arg;
130 int __user *p = argp; 136 int __user *p = argp;
131 int new_value; 137 int new_value;
132 138
133 switch(cmd) { 139 switch (cmd) {
134 case WDIOC_KEEPALIVE: 140 case WDIOC_GETSUPPORT:
135 at91_wdt_reload(); /* pat the watchdog */ 141 return copy_to_user(argp, &at91_wdt_info,
136 return 0; 142 sizeof(at91_wdt_info)) ? -EFAULT : 0;
137 143 case WDIOC_GETSTATUS:
138 case WDIOC_GETSUPPORT: 144 case WDIOC_GETBOOTSTATUS:
139 return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0; 145 return put_user(0, p);
140 146 case WDIOC_SETOPTIONS:
141 case WDIOC_SETTIMEOUT: 147 if (get_user(new_value, p))
142 if (get_user(new_value, p)) 148 return -EFAULT;
143 return -EFAULT; 149 if (new_value & WDIOS_DISABLECARD)
144 150 at91_wdt_stop();
145 if (at91_wdt_settimeout(new_value)) 151 if (new_value & WDIOS_ENABLECARD)
146 return -EINVAL;
147
148 /* Enable new time value */
149 at91_wdt_start(); 152 at91_wdt_start();
150 153 return 0;
151 /* Return current value */ 154 case WDIOC_KEEPALIVE:
152 return put_user(wdt_time, p); 155 at91_wdt_reload(); /* pat the watchdog */
153 156 return 0;
154 case WDIOC_GETTIMEOUT: 157 case WDIOC_SETTIMEOUT:
155 return put_user(wdt_time, p); 158 if (get_user(new_value, p))
156 159 return -EFAULT;
157 case WDIOC_GETSTATUS: 160 if (at91_wdt_settimeout(new_value))
158 case WDIOC_GETBOOTSTATUS: 161 return -EINVAL;
159 return put_user(0, p); 162 /* Enable new time value */
160 163 at91_wdt_start();
161 case WDIOC_SETOPTIONS: 164 /* Return current value */
162 if (get_user(new_value, p)) 165 return put_user(wdt_time, p);
163 return -EFAULT; 166 case WDIOC_GETTIMEOUT:
164 167 return put_user(wdt_time, p);
165 if (new_value & WDIOS_DISABLECARD) 168 default:
166 at91_wdt_stop(); 169 return -ENOTTY;
167 if (new_value & WDIOS_ENABLECARD)
168 at91_wdt_start();
169 return 0;
170
171 default:
172 return -ENOTTY;
173 } 170 }
174} 171}
175 172
176/* 173/*
177 * Pat the watchdog whenever device is written to. 174 * Pat the watchdog whenever device is written to.
178 */ 175 */
179static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) 176static ssize_t at91_wdt_write(struct file *file, const char *data,
177 size_t len, loff_t *ppos)
180{ 178{
181 at91_wdt_reload(); /* pat the watchdog */ 179 at91_wdt_reload(); /* pat the watchdog */
182 return len; 180 return len;
@@ -187,7 +185,7 @@ static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, l
187static const struct file_operations at91wdt_fops = { 185static const struct file_operations at91wdt_fops = {
188 .owner = THIS_MODULE, 186 .owner = THIS_MODULE,
189 .llseek = no_llseek, 187 .llseek = no_llseek,
190 .ioctl = at91_wdt_ioctl, 188 .unlocked_ioctl = at91_wdt_ioctl,
191 .open = at91_wdt_open, 189 .open = at91_wdt_open,
192 .release = at91_wdt_close, 190 .release = at91_wdt_close,
193 .write = at91_wdt_write, 191 .write = at91_wdt_write,
@@ -211,7 +209,8 @@ static int __init at91wdt_probe(struct platform_device *pdev)
211 if (res) 209 if (res)
212 return res; 210 return res;
213 211
214 printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); 212 printk(KERN_INFO "AT91 Watchdog Timer enabled (%d seconds%s)\n",
213 wdt_time, nowayout ? ", nowayout" : "");
215 return 0; 214 return 0;
216} 215}
217 216
@@ -265,7 +264,8 @@ static struct platform_driver at91wdt_driver = {
265 264
266static int __init at91_wdt_init(void) 265static int __init at91_wdt_init(void)
267{ 266{
268 /* Check that the heartbeat value is within range; if not reset to the default */ 267 /* Check that the heartbeat value is within range;
268 if not reset to the default */
269 if (at91_wdt_settimeout(wdt_time)) { 269 if (at91_wdt_settimeout(wdt_time)) {
270 at91_wdt_settimeout(WDT_DEFAULT_TIME); 270 at91_wdt_settimeout(WDT_DEFAULT_TIME);
271 pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); 271 pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time);
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 03b3e3d91e7c..31b42253054e 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -24,8 +24,8 @@
24#include <linux/reboot.h> 24#include <linux/reboot.h>
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/uaccess.h>
27#include <asm/blackfin.h> 28#include <asm/blackfin.h>
28#include <asm/uaccess.h>
29 29
30#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) 30#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
31#define stampit() stamp("here i am") 31#define stampit() stamp("here i am")
@@ -148,7 +148,8 @@ static int bfin_wdt_set_timeout(unsigned long t)
148 int run = bfin_wdt_running(); 148 int run = bfin_wdt_running();
149 bfin_wdt_stop(); 149 bfin_wdt_stop();
150 bfin_write_WDOG_CNT(cnt); 150 bfin_write_WDOG_CNT(cnt);
151 if (run) bfin_wdt_start(); 151 if (run)
152 bfin_wdt_start();
152 } 153 }
153 spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); 154 spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
154 155
@@ -191,16 +192,15 @@ static int bfin_wdt_release(struct inode *inode, struct file *file)
191{ 192{
192 stampit(); 193 stampit();
193 194
194 if (expect_close == 42) { 195 if (expect_close == 42)
195 bfin_wdt_stop(); 196 bfin_wdt_stop();
196 } else { 197 else {
197 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 198 printk(KERN_CRIT PFX
199 "Unexpected close, not stopping watchdog!\n");
198 bfin_wdt_keepalive(); 200 bfin_wdt_keepalive();
199 } 201 }
200
201 expect_close = 0; 202 expect_close = 0;
202 clear_bit(0, &open_check); 203 clear_bit(0, &open_check);
203
204 return 0; 204 return 0;
205} 205}
206 206
@@ -214,7 +214,7 @@ static int bfin_wdt_release(struct inode *inode, struct file *file)
214 * Pings the watchdog on write. 214 * Pings the watchdog on write.
215 */ 215 */
216static ssize_t bfin_wdt_write(struct file *file, const char __user *data, 216static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
217 size_t len, loff_t *ppos) 217 size_t len, loff_t *ppos)
218{ 218{
219 stampit(); 219 stampit();
220 220
@@ -241,7 +241,6 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
241 241
242/** 242/**
243 * bfin_wdt_ioctl - Query Device 243 * bfin_wdt_ioctl - Query Device
244 * @inode: inode of device
245 * @file: file handle of device 244 * @file: file handle of device
246 * @cmd: watchdog command 245 * @cmd: watchdog command
247 * @arg: argument 246 * @arg: argument
@@ -249,8 +248,8 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
249 * Query basic information from the device or ping it, as outlined by the 248 * Query basic information from the device or ping it, as outlined by the
250 * watchdog API. 249 * watchdog API.
251 */ 250 */
252static int bfin_wdt_ioctl(struct inode *inode, struct file *file, 251static long bfin_wdt_ioctl(struct file *file,
253 unsigned int cmd, unsigned long arg) 252 unsigned int cmd, unsigned long arg)
254{ 253{
255 void __user *argp = (void __user *)arg; 254 void __user *argp = (void __user *)arg;
256 int __user *p = argp; 255 int __user *p = argp;
@@ -258,59 +257,49 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file,
258 stampit(); 257 stampit();
259 258
260 switch (cmd) { 259 switch (cmd) {
261 default: 260 case WDIOC_GETSUPPORT:
262 return -ENOTTY; 261 if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info)))
263 262 return -EFAULT;
264 case WDIOC_GETSUPPORT: 263 else
265 if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info)))
266 return -EFAULT;
267 else
268 return 0;
269
270 case WDIOC_GETSTATUS:
271 case WDIOC_GETBOOTSTATUS:
272 return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p);
273
274 case WDIOC_KEEPALIVE:
275 bfin_wdt_keepalive();
276 return 0; 264 return 0;
277 265 case WDIOC_GETSTATUS:
278 case WDIOC_SETTIMEOUT: { 266 case WDIOC_GETBOOTSTATUS:
279 int new_timeout; 267 return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p);
280 268 case WDIOC_SETOPTIONS: {
281 if (get_user(new_timeout, p)) 269 unsigned long flags;
282 return -EFAULT; 270 int options, ret = -EINVAL;
283 271
284 if (bfin_wdt_set_timeout(new_timeout)) 272 if (get_user(options, p))
285 return -EINVAL; 273 return -EFAULT;
274
275 spin_lock_irqsave(&bfin_wdt_spinlock, flags);
276 if (options & WDIOS_DISABLECARD) {
277 bfin_wdt_stop();
278 ret = 0;
286 } 279 }
287 /* Fall */ 280 if (options & WDIOS_ENABLECARD) {
288 case WDIOC_GETTIMEOUT: 281 bfin_wdt_start();
289 return put_user(timeout, p); 282 ret = 0;
290
291 case WDIOC_SETOPTIONS: {
292 unsigned long flags;
293 int options, ret = -EINVAL;
294
295 if (get_user(options, p))
296 return -EFAULT;
297
298 spin_lock_irqsave(&bfin_wdt_spinlock, flags);
299
300 if (options & WDIOS_DISABLECARD) {
301 bfin_wdt_stop();
302 ret = 0;
303 }
304
305 if (options & WDIOS_ENABLECARD) {
306 bfin_wdt_start();
307 ret = 0;
308 }
309
310 spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
311
312 return ret;
313 } 283 }
284 spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
285 return ret;
286 }
287 case WDIOC_KEEPALIVE:
288 bfin_wdt_keepalive();
289 return 0;
290 case WDIOC_SETTIMEOUT: {
291 int new_timeout;
292
293 if (get_user(new_timeout, p))
294 return -EFAULT;
295 if (bfin_wdt_set_timeout(new_timeout))
296 return -EINVAL;
297 }
298 /* Fall */
299 case WDIOC_GETTIMEOUT:
300 return put_user(timeout, p);
301 default:
302 return -ENOTTY;
314 } 303 }
315} 304}
316 305
@@ -323,8 +312,8 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file,
323 * Handles specific events, such as turning off the watchdog during a 312 * Handles specific events, such as turning off the watchdog during a
324 * shutdown event. 313 * shutdown event.
325 */ 314 */
326static int bfin_wdt_notify_sys(struct notifier_block *this, unsigned long code, 315static int bfin_wdt_notify_sys(struct notifier_block *this,
327 void *unused) 316 unsigned long code, void *unused)
328{ 317{
329 stampit(); 318 stampit();
330 319
@@ -379,12 +368,12 @@ static int bfin_wdt_resume(struct platform_device *pdev)
379#endif 368#endif
380 369
381static const struct file_operations bfin_wdt_fops = { 370static const struct file_operations bfin_wdt_fops = {
382 .owner = THIS_MODULE, 371 .owner = THIS_MODULE,
383 .llseek = no_llseek, 372 .llseek = no_llseek,
384 .write = bfin_wdt_write, 373 .write = bfin_wdt_write,
385 .ioctl = bfin_wdt_ioctl, 374 .unlocked_ioctl = bfin_wdt_ioctl,
386 .open = bfin_wdt_open, 375 .open = bfin_wdt_open,
387 .release = bfin_wdt_release, 376 .release = bfin_wdt_release,
388}; 377};
389 378
390static struct miscdevice bfin_wdt_miscdev = { 379static struct miscdevice bfin_wdt_miscdev = {
@@ -396,8 +385,8 @@ static struct miscdevice bfin_wdt_miscdev = {
396static struct watchdog_info bfin_wdt_info = { 385static struct watchdog_info bfin_wdt_info = {
397 .identity = "Blackfin Watchdog", 386 .identity = "Blackfin Watchdog",
398 .options = WDIOF_SETTIMEOUT | 387 .options = WDIOF_SETTIMEOUT |
399 WDIOF_KEEPALIVEPING | 388 WDIOF_KEEPALIVEPING |
400 WDIOF_MAGICCLOSE, 389 WDIOF_MAGICCLOSE,
401}; 390};
402 391
403static struct notifier_block bfin_wdt_notifier = { 392static struct notifier_block bfin_wdt_notifier = {
@@ -416,14 +405,16 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev)
416 405
417 ret = register_reboot_notifier(&bfin_wdt_notifier); 406 ret = register_reboot_notifier(&bfin_wdt_notifier);
418 if (ret) { 407 if (ret) {
419 pr_devinit(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); 408 pr_devinit(KERN_ERR PFX
409 "cannot register reboot notifier (err=%d)\n", ret);
420 return ret; 410 return ret;
421 } 411 }
422 412
423 ret = misc_register(&bfin_wdt_miscdev); 413 ret = misc_register(&bfin_wdt_miscdev);
424 if (ret) { 414 if (ret) {
425 pr_devinit(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 415 pr_devinit(KERN_ERR PFX
426 WATCHDOG_MINOR, ret); 416 "cannot register miscdev on minor=%d (err=%d)\n",
417 WATCHDOG_MINOR, ret);
427 unregister_reboot_notifier(&bfin_wdt_notifier); 418 unregister_reboot_notifier(&bfin_wdt_notifier);
428 return ret; 419 return ret;
429 } 420 }
@@ -516,7 +507,11 @@ MODULE_LICENSE("GPL");
516MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 507MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
517 508
518module_param(timeout, uint, 0); 509module_param(timeout, uint, 0);
519MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 510MODULE_PARM_DESC(timeout,
511 "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
512 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
520 513
521module_param(nowayout, int, 0); 514module_param(nowayout, int, 0);
522MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 515MODULE_PARM_DESC(nowayout,
516 "Watchdog cannot be stopped once started (default="
517 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index 770824458d45..c3b78a76f173 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -18,9 +18,9 @@
18#include <linux/miscdevice.h> 18#include <linux/miscdevice.h>
19#include <linux/notifier.h> 19#include <linux/notifier.h>
20#include <linux/watchdog.h> 20#include <linux/watchdog.h>
21#include <linux/uaccess.h>
21 22
22#include <asm/reg_booke.h> 23#include <asm/reg_booke.h>
23#include <asm/uaccess.h>
24#include <asm/system.h> 24#include <asm/system.h>
25 25
26/* If the kernel parameter wdt=1, the watchdog will be enabled at boot. 26/* If the kernel parameter wdt=1, the watchdog will be enabled at boot.
@@ -32,7 +32,7 @@
32 */ 32 */
33 33
34#ifdef CONFIG_FSL_BOOKE 34#ifdef CONFIG_FSL_BOOKE
35#define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */ 35#define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */
36#else 36#else
37#define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ 37#define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */
38#endif /* for timing information */ 38#endif /* for timing information */
@@ -82,16 +82,15 @@ static struct watchdog_info ident = {
82 .identity = "PowerPC Book-E Watchdog", 82 .identity = "PowerPC Book-E Watchdog",
83}; 83};
84 84
85static int booke_wdt_ioctl(struct inode *inode, struct file *file, 85static long booke_wdt_ioctl(struct file *file,
86 unsigned int cmd, unsigned long arg) 86 unsigned int cmd, unsigned long arg)
87{ 87{
88 u32 tmp = 0; 88 u32 tmp = 0;
89 u32 __user *p = (u32 __user *)arg; 89 u32 __user *p = (u32 __user *)arg;
90 90
91 switch (cmd) { 91 switch (cmd) {
92 case WDIOC_GETSUPPORT: 92 case WDIOC_GETSUPPORT:
93 if (copy_to_user((struct watchdog_info __user *)arg, &ident, 93 if (copy_to_user(arg, &ident, sizeof(struct watchdog_info)))
94 sizeof(struct watchdog_info)))
95 return -EFAULT; 94 return -EFAULT;
96 case WDIOC_GETSTATUS: 95 case WDIOC_GETSTATUS:
97 return put_user(ident.options, p); 96 return put_user(ident.options, p);
@@ -100,16 +99,6 @@ static int booke_wdt_ioctl(struct inode *inode, struct file *file,
100 tmp = mfspr(SPRN_TSR) & TSR_WRS(3); 99 tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
101 /* returns 1 if last reset was caused by the WDT */ 100 /* returns 1 if last reset was caused by the WDT */
102 return (tmp ? 1 : 0); 101 return (tmp ? 1 : 0);
103 case WDIOC_KEEPALIVE:
104 booke_wdt_ping();
105 return 0;
106 case WDIOC_SETTIMEOUT:
107 if (get_user(booke_wdt_period, p))
108 return -EFAULT;
109 mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(booke_wdt_period));
110 return 0;
111 case WDIOC_GETTIMEOUT:
112 return put_user(booke_wdt_period, p);
113 case WDIOC_SETOPTIONS: 102 case WDIOC_SETOPTIONS:
114 if (get_user(tmp, p)) 103 if (get_user(tmp, p))
115 return -EINVAL; 104 return -EINVAL;
@@ -119,6 +108,17 @@ static int booke_wdt_ioctl(struct inode *inode, struct file *file,
119 } else 108 } else
120 return -EINVAL; 109 return -EINVAL;
121 return 0; 110 return 0;
111 case WDIOC_KEEPALIVE:
112 booke_wdt_ping();
113 return 0;
114 case WDIOC_SETTIMEOUT:
115 if (get_user(booke_wdt_period, p))
116 return -EFAULT;
117 mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP(0)) |
118 WDTP(booke_wdt_period));
119 return 0;
120 case WDIOC_GETTIMEOUT:
121 return put_user(booke_wdt_period, p);
122 default: 122 default:
123 return -ENOTTY; 123 return -ENOTTY;
124 } 124 }
@@ -132,8 +132,9 @@ static int booke_wdt_open(struct inode *inode, struct file *file)
132 if (booke_wdt_enabled == 0) { 132 if (booke_wdt_enabled == 0) {
133 booke_wdt_enabled = 1; 133 booke_wdt_enabled = 1;
134 on_each_cpu(__booke_wdt_enable, NULL, 0); 134 on_each_cpu(__booke_wdt_enable, NULL, 0);
135 printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled " 135 printk(KERN_INFO
136 "(wdt_period=%d)\n", booke_wdt_period); 136 "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
137 booke_wdt_period);
137 } 138 }
138 spin_unlock(&booke_wdt_lock); 139 spin_unlock(&booke_wdt_lock);
139 140
@@ -144,7 +145,7 @@ static const struct file_operations booke_wdt_fops = {
144 .owner = THIS_MODULE, 145 .owner = THIS_MODULE,
145 .llseek = no_llseek, 146 .llseek = no_llseek,
146 .write = booke_wdt_write, 147 .write = booke_wdt_write,
147 .ioctl = booke_wdt_ioctl, 148 .unlocked_ioctl = booke_wdt_ioctl,
148 .open = booke_wdt_open, 149 .open = booke_wdt_open,
149}; 150};
150 151
@@ -175,8 +176,9 @@ static int __init booke_wdt_init(void)
175 176
176 spin_lock(&booke_wdt_lock); 177 spin_lock(&booke_wdt_lock);
177 if (booke_wdt_enabled == 1) { 178 if (booke_wdt_enabled == 1) {
178 printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled " 179 printk(KERN_INFO
179 "(wdt_period=%d)\n", booke_wdt_period); 180 "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
181 booke_wdt_period);
180 on_each_cpu(__booke_wdt_enable, NULL, 0); 182 on_each_cpu(__booke_wdt_enable, NULL, 0);
181 } 183 }
182 spin_unlock(&booke_wdt_lock); 184 spin_unlock(&booke_wdt_lock);
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
index df72f90123df..71f6d7eec9a8 100644
--- a/drivers/watchdog/cpu5wdt.c
+++ b/drivers/watchdog/cpu5wdt.c
@@ -30,16 +30,16 @@
30#include <linux/timer.h> 30#include <linux/timer.h>
31#include <linux/completion.h> 31#include <linux/completion.h>
32#include <linux/jiffies.h> 32#include <linux/jiffies.h>
33#include <asm/io.h> 33#include <linux/io.h>
34#include <asm/uaccess.h> 34#include <linux/uaccess.h>
35
36#include <linux/watchdog.h> 35#include <linux/watchdog.h>
37 36
38/* adjustable parameters */ 37/* adjustable parameters */
39 38
40static int verbose = 0; 39static int verbose;
41static int port = 0x91; 40static int port = 0x91;
42static int ticks = 10000; 41static int ticks = 10000;
42static spinlock_t cpu5wdt_lock;
43 43
44#define PFX "cpu5wdt: " 44#define PFX "cpu5wdt: "
45 45
@@ -70,12 +70,13 @@ static struct {
70 70
71static void cpu5wdt_trigger(unsigned long unused) 71static void cpu5wdt_trigger(unsigned long unused)
72{ 72{
73 if ( verbose > 2 ) 73 if (verbose > 2)
74 printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks); 74 printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks);
75 75
76 if( cpu5wdt_device.running ) 76 if (cpu5wdt_device.running)
77 ticks--; 77 ticks--;
78 78
79 spin_lock(&cpu5wdt_lock);
79 /* keep watchdog alive */ 80 /* keep watchdog alive */
80 outb(1, port + CPU5WDT_TRIGGER_REG); 81 outb(1, port + CPU5WDT_TRIGGER_REG);
81 82
@@ -86,6 +87,7 @@ static void cpu5wdt_trigger(unsigned long unused)
86 /* ticks doesn't matter anyway */ 87 /* ticks doesn't matter anyway */
87 complete(&cpu5wdt_device.stop); 88 complete(&cpu5wdt_device.stop);
88 } 89 }
90 spin_unlock(&cpu5wdt_lock);
89 91
90} 92}
91 93
@@ -93,14 +95,17 @@ static void cpu5wdt_reset(void)
93{ 95{
94 ticks = cpu5wdt_device.default_ticks; 96 ticks = cpu5wdt_device.default_ticks;
95 97
96 if ( verbose ) 98 if (verbose)
97 printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks); 99 printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks);
98 100
99} 101}
100 102
101static void cpu5wdt_start(void) 103static void cpu5wdt_start(void)
102{ 104{
103 if ( !cpu5wdt_device.queue ) { 105 unsigned long flags;
106
107 spin_lock_irqsave(&cpu5wdt_lock, flags);
108 if (!cpu5wdt_device.queue) {
104 cpu5wdt_device.queue = 1; 109 cpu5wdt_device.queue = 1;
105 outb(0, port + CPU5WDT_TIME_A_REG); 110 outb(0, port + CPU5WDT_TIME_A_REG);
106 outb(0, port + CPU5WDT_TIME_B_REG); 111 outb(0, port + CPU5WDT_TIME_B_REG);
@@ -111,18 +116,20 @@ static void cpu5wdt_start(void)
111 } 116 }
112 /* if process dies, counter is not decremented */ 117 /* if process dies, counter is not decremented */
113 cpu5wdt_device.running++; 118 cpu5wdt_device.running++;
119 spin_unlock_irqrestore(&cpu5wdt_lock, flags);
114} 120}
115 121
116static int cpu5wdt_stop(void) 122static int cpu5wdt_stop(void)
117{ 123{
118 if ( cpu5wdt_device.running ) 124 unsigned long flags;
119 cpu5wdt_device.running = 0;
120 125
126 spin_lock_irqsave(&cpu5wdt_lock, flags);
127 if (cpu5wdt_device.running)
128 cpu5wdt_device.running = 0;
121 ticks = cpu5wdt_device.default_ticks; 129 ticks = cpu5wdt_device.default_ticks;
122 130 spin_unlock_irqrestore(&cpu5wdt_lock, flags);
123 if ( verbose ) 131 if (verbose)
124 printk(KERN_CRIT PFX "stop not possible\n"); 132 printk(KERN_CRIT PFX "stop not possible\n");
125
126 return -EIO; 133 return -EIO;
127} 134}
128 135
@@ -130,9 +137,8 @@ static int cpu5wdt_stop(void)
130 137
131static int cpu5wdt_open(struct inode *inode, struct file *file) 138static int cpu5wdt_open(struct inode *inode, struct file *file)
132{ 139{
133 if ( test_and_set_bit(0, &cpu5wdt_device.inuse) ) 140 if (test_and_set_bit(0, &cpu5wdt_device.inuse))
134 return -EBUSY; 141 return -EBUSY;
135
136 return nonseekable_open(inode, file); 142 return nonseekable_open(inode, file);
137} 143}
138 144
@@ -142,67 +148,58 @@ static int cpu5wdt_release(struct inode *inode, struct file *file)
142 return 0; 148 return 0;
143} 149}
144 150
145static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 151static long cpu5wdt_ioctl(struct file *file, unsigned int cmd,
152 unsigned long arg)
146{ 153{
147 void __user *argp = (void __user *)arg; 154 void __user *argp = (void __user *)arg;
155 int __user *p = argp;
148 unsigned int value; 156 unsigned int value;
149 static struct watchdog_info ident = 157 static struct watchdog_info ident = {
150 {
151 .options = WDIOF_CARDRESET, 158 .options = WDIOF_CARDRESET,
152 .identity = "CPU5 WDT", 159 .identity = "CPU5 WDT",
153 }; 160 };
154 161
155 switch(cmd) { 162 switch (cmd) {
156 case WDIOC_KEEPALIVE: 163 case WDIOC_GETSUPPORT:
157 cpu5wdt_reset(); 164 if (copy_to_user(argp, &ident, sizeof(ident)))
158 break; 165 return -EFAULT;
159 case WDIOC_GETSTATUS: 166 break;
160 value = inb(port + CPU5WDT_STATUS_REG); 167 case WDIOC_GETSTATUS:
161 value = (value >> 2) & 1; 168 value = inb(port + CPU5WDT_STATUS_REG);
162 if ( copy_to_user(argp, &value, sizeof(int)) ) 169 value = (value >> 2) & 1;
163 return -EFAULT; 170 return put_user(value, p);
164 break; 171 case WDIOC_GETBOOTSTATUS:
165 case WDIOC_GETBOOTSTATUS: 172 return put_user(0, p);
166 if ( copy_to_user(argp, &value, sizeof(int)) ) 173 case WDIOC_SETOPTIONS:
167 return -EFAULT; 174 if (get_user(value, p))
168 break; 175 return -EFAULT;
169 case WDIOC_GETSUPPORT: 176 if (value & WDIOS_ENABLECARD)
170 if ( copy_to_user(argp, &ident, sizeof(ident)) ) 177 cpu5wdt_start();
171 return -EFAULT; 178 if (value & WDIOS_DISABLECARD)
172 break; 179 cpu5wdt_stop();
173 case WDIOC_SETOPTIONS: 180 break;
174 if ( copy_from_user(&value, argp, sizeof(int)) ) 181 case WDIOC_KEEPALIVE:
175 return -EFAULT; 182 cpu5wdt_reset();
176 switch(value) { 183 break;
177 case WDIOS_ENABLECARD: 184 default:
178 cpu5wdt_start(); 185 return -ENOTTY;
179 break;
180 case WDIOS_DISABLECARD:
181 return cpu5wdt_stop();
182 default:
183 return -EINVAL;
184 }
185 break;
186 default:
187 return -ENOTTY;
188 } 186 }
189 return 0; 187 return 0;
190} 188}
191 189
192static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 190static ssize_t cpu5wdt_write(struct file *file, const char __user *buf,
191 size_t count, loff_t *ppos)
193{ 192{
194 if ( !count ) 193 if (!count)
195 return -EIO; 194 return -EIO;
196
197 cpu5wdt_reset(); 195 cpu5wdt_reset();
198
199 return count; 196 return count;
200} 197}
201 198
202static const struct file_operations cpu5wdt_fops = { 199static const struct file_operations cpu5wdt_fops = {
203 .owner = THIS_MODULE, 200 .owner = THIS_MODULE,
204 .llseek = no_llseek, 201 .llseek = no_llseek,
205 .ioctl = cpu5wdt_ioctl, 202 .unlocked_ioctl = cpu5wdt_ioctl,
206 .open = cpu5wdt_open, 203 .open = cpu5wdt_open,
207 .write = cpu5wdt_write, 204 .write = cpu5wdt_write,
208 .release = cpu5wdt_release, 205 .release = cpu5wdt_release,
@@ -221,37 +218,36 @@ static int __devinit cpu5wdt_init(void)
221 unsigned int val; 218 unsigned int val;
222 int err; 219 int err;
223 220
224 if ( verbose ) 221 if (verbose)
225 printk(KERN_DEBUG PFX "port=0x%x, verbose=%i\n", port, verbose); 222 printk(KERN_DEBUG PFX
223 "port=0x%x, verbose=%i\n", port, verbose);
226 224
227 if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) { 225 init_completion(&cpu5wdt_device.stop);
226 spin_lock_init(&cpu5wdt_lock);
227 cpu5wdt_device.queue = 0;
228 setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
229 cpu5wdt_device.default_ticks = ticks;
230
231 if (!request_region(port, CPU5WDT_EXTENT, PFX)) {
228 printk(KERN_ERR PFX "request_region failed\n"); 232 printk(KERN_ERR PFX "request_region failed\n");
229 err = -EBUSY; 233 err = -EBUSY;
230 goto no_port; 234 goto no_port;
231 } 235 }
232 236
233 if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) {
234 printk(KERN_ERR PFX "misc_register failed\n");
235 goto no_misc;
236 }
237
238 /* watchdog reboot? */ 237 /* watchdog reboot? */
239 val = inb(port + CPU5WDT_STATUS_REG); 238 val = inb(port + CPU5WDT_STATUS_REG);
240 val = (val >> 2) & 1; 239 val = (val >> 2) & 1;
241 if ( !val ) 240 if (!val)
242 printk(KERN_INFO PFX "sorry, was my fault\n"); 241 printk(KERN_INFO PFX "sorry, was my fault\n");
243 242
244 init_completion(&cpu5wdt_device.stop); 243 err = misc_register(&cpu5wdt_misc);
245 cpu5wdt_device.queue = 0; 244 if (err < 0) {
246 245 printk(KERN_ERR PFX "misc_register failed\n");
247 clear_bit(0, &cpu5wdt_device.inuse); 246 goto no_misc;
248 247 }
249 setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
250 248
251 cpu5wdt_device.default_ticks = ticks;
252 249
253 printk(KERN_INFO PFX "init success\n"); 250 printk(KERN_INFO PFX "init success\n");
254
255 return 0; 251 return 0;
256 252
257no_misc: 253no_misc:
@@ -267,7 +263,7 @@ static int __devinit cpu5wdt_init_module(void)
267 263
268static void __devexit cpu5wdt_exit(void) 264static void __devexit cpu5wdt_exit(void)
269{ 265{
270 if ( cpu5wdt_device.queue ) { 266 if (cpu5wdt_device.queue) {
271 cpu5wdt_device.queue = 0; 267 cpu5wdt_device.queue = 0;
272 wait_for_completion(&cpu5wdt_device.stop); 268 wait_for_completion(&cpu5wdt_device.stop);
273 } 269 }
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index 1782c79eff06..802aeba347a0 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -22,10 +22,10 @@
22#include <linux/bitops.h> 22#include <linux/bitops.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/spinlock.h> 24#include <linux/spinlock.h>
25#include <linux/uaccess.h>
26#include <linux/io.h>
25 27
26#include <asm/hardware.h> 28#include <asm/hardware.h>
27#include <asm/uaccess.h>
28#include <asm/io.h>
29 29
30#define MODULE_NAME "DAVINCI-WDT: " 30#define MODULE_NAME "DAVINCI-WDT: "
31 31
@@ -143,9 +143,8 @@ static struct watchdog_info ident = {
143 .identity = "DaVinci Watchdog", 143 .identity = "DaVinci Watchdog",
144}; 144};
145 145
146static int 146static long davinci_wdt_ioctl(struct file *file,
147davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 147 unsigned int cmd, unsigned long arg)
148 unsigned long arg)
149{ 148{
150 int ret = -ENOTTY; 149 int ret = -ENOTTY;
151 150
@@ -160,14 +159,14 @@ davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
160 ret = put_user(0, (int *)arg); 159 ret = put_user(0, (int *)arg);
161 break; 160 break;
162 161
163 case WDIOC_GETTIMEOUT:
164 ret = put_user(heartbeat, (int *)arg);
165 break;
166
167 case WDIOC_KEEPALIVE: 162 case WDIOC_KEEPALIVE:
168 wdt_service(); 163 wdt_service();
169 ret = 0; 164 ret = 0;
170 break; 165 break;
166
167 case WDIOC_GETTIMEOUT:
168 ret = put_user(heartbeat, (int *)arg);
169 break;
171 } 170 }
172 return ret; 171 return ret;
173} 172}
@@ -184,7 +183,7 @@ static const struct file_operations davinci_wdt_fops = {
184 .owner = THIS_MODULE, 183 .owner = THIS_MODULE,
185 .llseek = no_llseek, 184 .llseek = no_llseek,
186 .write = davinci_wdt_write, 185 .write = davinci_wdt_write,
187 .ioctl = davinci_wdt_ioctl, 186 .unlocked_ioctl = davinci_wdt_ioctl,
188 .open = davinci_wdt_open, 187 .open = davinci_wdt_open,
189 .release = davinci_wdt_release, 188 .release = davinci_wdt_release,
190}; 189};
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index 0e4787a0bb87..07b74a768922 100644
--- a/drivers/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
@@ -28,9 +28,9 @@
28#include <linux/miscdevice.h> 28#include <linux/miscdevice.h>
29#include <linux/watchdog.h> 29#include <linux/watchdog.h>
30#include <linux/timer.h> 30#include <linux/timer.h>
31#include <linux/uaccess.h>
31 32
32#include <asm/hardware.h> 33#include <asm/hardware.h>
33#include <asm/uaccess.h>
34 34
35#define WDT_VERSION "0.3" 35#define WDT_VERSION "0.3"
36#define PFX "ep93xx_wdt: " 36#define PFX "ep93xx_wdt: "
@@ -136,9 +136,8 @@ static struct watchdog_info ident = {
136 .identity = "EP93xx Watchdog", 136 .identity = "EP93xx Watchdog",
137}; 137};
138 138
139static int 139static long ep93xx_wdt_ioctl(struct file *file,
140ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 140 unsigned int cmd, unsigned long arg)
141 unsigned long arg)
142{ 141{
143 int ret = -ENOTTY; 142 int ret = -ENOTTY;
144 143
@@ -156,15 +155,15 @@ ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
156 ret = put_user(boot_status, (int __user *)arg); 155 ret = put_user(boot_status, (int __user *)arg);
157 break; 156 break;
158 157
159 case WDIOC_GETTIMEOUT:
160 /* actually, it is 0.250 seconds.... */
161 ret = put_user(1, (int __user *)arg);
162 break;
163
164 case WDIOC_KEEPALIVE: 158 case WDIOC_KEEPALIVE:
165 wdt_keepalive(); 159 wdt_keepalive();
166 ret = 0; 160 ret = 0;
167 break; 161 break;
162
163 case WDIOC_GETTIMEOUT:
164 /* actually, it is 0.250 seconds.... */
165 ret = put_user(1, (int __user *)arg);
166 break;
168 } 167 }
169 return ret; 168 return ret;
170} 169}
@@ -174,8 +173,8 @@ static int ep93xx_wdt_release(struct inode *inode, struct file *file)
174 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) 173 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
175 wdt_shutdown(); 174 wdt_shutdown();
176 else 175 else
177 printk(KERN_CRIT PFX "Device closed unexpectedly - " 176 printk(KERN_CRIT PFX
178 "timer will not stop\n"); 177 "Device closed unexpectedly - timer will not stop\n");
179 178
180 clear_bit(WDT_IN_USE, &wdt_status); 179 clear_bit(WDT_IN_USE, &wdt_status);
181 clear_bit(WDT_OK_TO_CLOSE, &wdt_status); 180 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
@@ -186,7 +185,7 @@ static int ep93xx_wdt_release(struct inode *inode, struct file *file)
186static const struct file_operations ep93xx_wdt_fops = { 185static const struct file_operations ep93xx_wdt_fops = {
187 .owner = THIS_MODULE, 186 .owner = THIS_MODULE,
188 .write = ep93xx_wdt_write, 187 .write = ep93xx_wdt_write,
189 .ioctl = ep93xx_wdt_ioctl, 188 .unlocked_ioctl = ep93xx_wdt_ioctl,
190 .open = ep93xx_wdt_open, 189 .open = ep93xx_wdt_open,
191 .release = ep93xx_wdt_release, 190 .release = ep93xx_wdt_release,
192}; 191};
@@ -243,7 +242,9 @@ module_param(nowayout, int, 0);
243MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); 242MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
244 243
245module_param(timeout, int, 0); 244module_param(timeout, int, 0);
246MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 245MODULE_PARM_DESC(timeout,
246 "Watchdog timeout in seconds. (1<=timeout<=3600, default="
247 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
247 248
248MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>," 249MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"
249 "Alessandro Zummo <a.zummo@towertech.it>"); 250 "Alessandro Zummo <a.zummo@towertech.it>");
diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c
index b14e9d1f164d..bbd14e34319f 100644
--- a/drivers/watchdog/eurotechwdt.c
+++ b/drivers/watchdog/eurotechwdt.c
@@ -56,14 +56,15 @@
56#include <linux/notifier.h> 56#include <linux/notifier.h>
57#include <linux/reboot.h> 57#include <linux/reboot.h>
58#include <linux/init.h> 58#include <linux/init.h>
59#include <linux/io.h>
60#include <linux/uaccess.h>
59 61
60#include <asm/io.h>
61#include <asm/uaccess.h>
62#include <asm/system.h> 62#include <asm/system.h>
63 63
64static unsigned long eurwdt_is_open; 64static unsigned long eurwdt_is_open;
65static int eurwdt_timeout; 65static int eurwdt_timeout;
66static char eur_expect_close; 66static char eur_expect_close;
67static spinlock_t eurwdt_lock;
67 68
68/* 69/*
69 * 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.
@@ -78,7 +79,9 @@ static char *ev = "int";
78 79
79static int nowayout = WATCHDOG_NOWAYOUT; 80static int nowayout = WATCHDOG_NOWAYOUT;
80module_param(nowayout, int, 0); 81module_param(nowayout, int, 0);
81MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 82MODULE_PARM_DESC(nowayout,
83 "Watchdog cannot be stopped once started (default="
84 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
82 85
83/* 86/*
84 * Some symbolic names 87 * Some symbolic names
@@ -137,7 +140,8 @@ static void eurwdt_activate_timer(void)
137{ 140{
138 eurwdt_disable_timer(); 141 eurwdt_disable_timer();
139 eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */ 142 eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */
140 eurwdt_write_reg(WDT_OUTPIN_CFG, !strcmp("int", ev) ? WDT_EVENT_INT : WDT_EVENT_REBOOT); 143 eurwdt_write_reg(WDT_OUTPIN_CFG,
144 !strcmp("int", ev) ? WDT_EVENT_INT : WDT_EVENT_REBOOT);
141 145
142 /* Setting interrupt line */ 146 /* Setting interrupt line */
143 if (irq == 2 || irq > 15 || irq < 0) { 147 if (irq == 2 || irq > 15 || irq < 0) {
@@ -206,21 +210,21 @@ size_t count, loff_t *ppos)
206 210
207 for (i = 0; i != count; i++) { 211 for (i = 0; i != count; i++) {
208 char c; 212 char c;
209 if(get_user(c, buf+i)) 213 if (get_user(c, buf + i))
210 return -EFAULT; 214 return -EFAULT;
211 if (c == 'V') 215 if (c == 'V')
212 eur_expect_close = 42; 216 eur_expect_close = 42;
213 } 217 }
214 } 218 }
219 spin_lock(&eurwdt_lock);
215 eurwdt_ping(); /* the default timeout */ 220 eurwdt_ping(); /* the default timeout */
221 spin_unlock(&eurwdt_lock);
216 } 222 }
217
218 return count; 223 return count;
219} 224}
220 225
221/** 226/**
222 * eurwdt_ioctl: 227 * eurwdt_ioctl:
223 * @inode: inode of the device
224 * @file: file handle to the device 228 * @file: file handle to the device
225 * @cmd: watchdog command 229 * @cmd: watchdog command
226 * @arg: argument pointer 230 * @arg: argument pointer
@@ -229,13 +233,14 @@ size_t count, loff_t *ppos)
229 * according to their available features. 233 * according to their available features.
230 */ 234 */
231 235
232static int eurwdt_ioctl(struct inode *inode, struct file *file, 236static long eurwdt_ioctl(struct file *file,
233 unsigned int cmd, unsigned long arg) 237 unsigned int cmd, unsigned long arg)
234{ 238{
235 void __user *argp = (void __user *)arg; 239 void __user *argp = (void __user *)arg;
236 int __user *p = argp; 240 int __user *p = argp;
237 static struct watchdog_info ident = { 241 static struct watchdog_info ident = {
238 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 242 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
243 | WDIOF_MAGICCLOSE,
239 .firmware_version = 1, 244 .firmware_version = 1,
240 .identity = "WDT Eurotech CPU-1220/1410", 245 .identity = "WDT Eurotech CPU-1220/1410",
241 }; 246 };
@@ -243,10 +248,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
243 int time; 248 int time;
244 int options, retval = -EINVAL; 249 int options, retval = -EINVAL;
245 250
246 switch(cmd) { 251 switch (cmd) {
247 default:
248 return -ENOTTY;
249
250 case WDIOC_GETSUPPORT: 252 case WDIOC_GETSUPPORT:
251 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 253 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
252 254
@@ -254,8 +256,26 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
254 case WDIOC_GETBOOTSTATUS: 256 case WDIOC_GETBOOTSTATUS:
255 return put_user(0, p); 257 return put_user(0, p);
256 258
259 case WDIOC_SETOPTIONS:
260 if (get_user(options, p))
261 return -EFAULT;
262 spin_lock(&eurwdt_lock);
263 if (options & WDIOS_DISABLECARD) {
264 eurwdt_disable_timer();
265 retval = 0;
266 }
267 if (options & WDIOS_ENABLECARD) {
268 eurwdt_activate_timer();
269 eurwdt_ping();
270 retval = 0;
271 }
272 spin_unlock(&eurwdt_lock);
273 return retval;
274
257 case WDIOC_KEEPALIVE: 275 case WDIOC_KEEPALIVE:
276 spin_lock(&eurwdt_lock);
258 eurwdt_ping(); 277 eurwdt_ping();
278 spin_unlock(&eurwdt_lock);
259 return 0; 279 return 0;
260 280
261 case WDIOC_SETTIMEOUT: 281 case WDIOC_SETTIMEOUT:
@@ -266,26 +286,17 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
266 if (time < 0 || time > 255) 286 if (time < 0 || time > 255)
267 return -EINVAL; 287 return -EINVAL;
268 288
289 spin_lock(&eurwdt_lock);
269 eurwdt_timeout = time; 290 eurwdt_timeout = time;
270 eurwdt_set_timeout(time); 291 eurwdt_set_timeout(time);
292 spin_unlock(&eurwdt_lock);
271 /* Fall */ 293 /* Fall */
272 294
273 case WDIOC_GETTIMEOUT: 295 case WDIOC_GETTIMEOUT:
274 return put_user(eurwdt_timeout, p); 296 return put_user(eurwdt_timeout, p);
275 297
276 case WDIOC_SETOPTIONS: 298 default:
277 if (get_user(options, p)) 299 return -ENOTTY;
278 return -EFAULT;
279 if (options & WDIOS_DISABLECARD) {
280 eurwdt_disable_timer();
281 retval = 0;
282 }
283 if (options & WDIOS_ENABLECARD) {
284 eurwdt_activate_timer();
285 eurwdt_ping();
286 retval = 0;
287 }
288 return retval;
289 } 300 }
290} 301}
291 302
@@ -322,10 +333,11 @@ static int eurwdt_open(struct inode *inode, struct file *file)
322 333
323static int eurwdt_release(struct inode *inode, struct file *file) 334static int eurwdt_release(struct inode *inode, struct file *file)
324{ 335{
325 if (eur_expect_close == 42) { 336 if (eur_expect_close == 42)
326 eurwdt_disable_timer(); 337 eurwdt_disable_timer();
327 } else { 338 else {
328 printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n"); 339 printk(KERN_CRIT
340 "eurwdt: Unexpected close, not stopping watchdog!\n");
329 eurwdt_ping(); 341 eurwdt_ping();
330 } 342 }
331 clear_bit(0, &eurwdt_is_open); 343 clear_bit(0, &eurwdt_is_open);
@@ -348,10 +360,8 @@ static int eurwdt_release(struct inode *inode, struct file *file)
348static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code, 360static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code,
349 void *unused) 361 void *unused)
350{ 362{
351 if (code == SYS_DOWN || code == SYS_HALT) { 363 if (code == SYS_DOWN || code == SYS_HALT)
352 /* Turn the card off */ 364 eurwdt_disable_timer(); /* Turn the card off */
353 eurwdt_disable_timer();
354 }
355 365
356 return NOTIFY_DONE; 366 return NOTIFY_DONE;
357} 367}
@@ -362,11 +372,11 @@ static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code,
362 372
363 373
364static const struct file_operations eurwdt_fops = { 374static const struct file_operations eurwdt_fops = {
365 .owner = THIS_MODULE, 375 .owner = THIS_MODULE,
366 .llseek = no_llseek, 376 .llseek = no_llseek,
367 .write = eurwdt_write, 377 .write = eurwdt_write,
368 .ioctl = eurwdt_ioctl, 378 .unlocked_ioctl = eurwdt_ioctl,
369 .open = eurwdt_open, 379 .open = eurwdt_open,
370 .release = eurwdt_release, 380 .release = eurwdt_release,
371}; 381};
372 382
@@ -419,7 +429,7 @@ static int __init eurwdt_init(void)
419 int ret; 429 int ret;
420 430
421 ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL); 431 ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL);
422 if(ret) { 432 if (ret) {
423 printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); 433 printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
424 goto out; 434 goto out;
425 } 435 }
@@ -432,10 +442,13 @@ static int __init eurwdt_init(void)
432 442
433 ret = register_reboot_notifier(&eurwdt_notifier); 443 ret = register_reboot_notifier(&eurwdt_notifier);
434 if (ret) { 444 if (ret) {
435 printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret); 445 printk(KERN_ERR
446 "eurwdt: can't register reboot notifier (err=%d)\n", ret);
436 goto outreg; 447 goto outreg;
437 } 448 }
438 449
450 spin_lock_init(&eurwdt_lock);
451
439 ret = misc_register(&eurwdt_miscdev); 452 ret = misc_register(&eurwdt_miscdev);
440 if (ret) { 453 if (ret) {
441 printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", 454 printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
index 30d09cbbad94..614a5c7017b6 100644
--- a/drivers/watchdog/geodewdt.c
+++ b/drivers/watchdog/geodewdt.c
@@ -17,8 +17,8 @@
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/reboot.h> 19#include <linux/reboot.h>
20#include <linux/uaccess.h>
20 21
21#include <asm/uaccess.h>
22#include <asm/geode.h> 22#include <asm/geode.h>
23 23
24#define GEODEWDT_HZ 500 24#define GEODEWDT_HZ 500
@@ -77,27 +77,24 @@ static int geodewdt_set_heartbeat(int val)
77 return 0; 77 return 0;
78} 78}
79 79
80static int 80static int geodewdt_open(struct inode *inode, struct file *file)
81geodewdt_open(struct inode *inode, struct file *file)
82{ 81{
83 if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) 82 if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags))
84 return -EBUSY; 83 return -EBUSY;
85 84
86 if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) 85 if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags))
87 __module_get(THIS_MODULE); 86 __module_get(THIS_MODULE);
88 87
89 geodewdt_ping(); 88 geodewdt_ping();
90 return nonseekable_open(inode, file); 89 return nonseekable_open(inode, file);
91} 90}
92 91
93static int 92static int geodewdt_release(struct inode *inode, struct file *file)
94geodewdt_release(struct inode *inode, struct file *file)
95{ 93{
96 if (safe_close) { 94 if (safe_close) {
97 geodewdt_disable(); 95 geodewdt_disable();
98 module_put(THIS_MODULE); 96 module_put(THIS_MODULE);
99 } 97 } else {
100 else {
101 printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n"); 98 printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n");
102 geodewdt_ping(); 99 geodewdt_ping();
103 100
@@ -109,11 +106,10 @@ geodewdt_release(struct inode *inode, struct file *file)
109 return 0; 106 return 0;
110} 107}
111 108
112static ssize_t 109static ssize_t geodewdt_write(struct file *file, const char __user *data,
113geodewdt_write(struct file *file, const char __user *data, size_t len, 110 size_t len, loff_t *ppos)
114 loff_t *ppos)
115{ 111{
116 if(len) { 112 if (len) {
117 if (!nowayout) { 113 if (!nowayout) {
118 size_t i; 114 size_t i;
119 safe_close = 0; 115 safe_close = 0;
@@ -134,9 +130,8 @@ geodewdt_write(struct file *file, const char __user *data, size_t len,
134 return len; 130 return len;
135} 131}
136 132
137static int 133static int geodewdt_ioctl(struct inode *inode, struct file *file,
138geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 134 unsigned int cmd, unsigned long arg)
139 unsigned long arg)
140{ 135{
141 void __user *argp = (void __user *)arg; 136 void __user *argp = (void __user *)arg;
142 int __user *p = argp; 137 int __user *p = argp;
@@ -147,9 +142,9 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
147 | WDIOF_MAGICCLOSE, 142 | WDIOF_MAGICCLOSE,
148 .firmware_version = 1, 143 .firmware_version = 1,
149 .identity = WATCHDOG_NAME, 144 .identity = WATCHDOG_NAME,
150 }; 145 };
151 146
152 switch(cmd) { 147 switch (cmd) {
153 case WDIOC_GETSUPPORT: 148 case WDIOC_GETSUPPORT:
154 return copy_to_user(argp, &ident, 149 return copy_to_user(argp, &ident,
155 sizeof(ident)) ? -EFAULT : 0; 150 sizeof(ident)) ? -EFAULT : 0;
@@ -159,22 +154,6 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
159 case WDIOC_GETBOOTSTATUS: 154 case WDIOC_GETBOOTSTATUS:
160 return put_user(0, p); 155 return put_user(0, p);
161 156
162 case WDIOC_KEEPALIVE:
163 geodewdt_ping();
164 return 0;
165
166 case WDIOC_SETTIMEOUT:
167 if (get_user(interval, p))
168 return -EFAULT;
169
170 if (geodewdt_set_heartbeat(interval))
171 return -EINVAL;
172
173/* Fall through */
174
175 case WDIOC_GETTIMEOUT:
176 return put_user(timeout, p);
177
178 case WDIOC_SETOPTIONS: 157 case WDIOC_SETOPTIONS:
179 { 158 {
180 int options, ret = -EINVAL; 159 int options, ret = -EINVAL;
@@ -194,6 +173,20 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
194 173
195 return ret; 174 return ret;
196 } 175 }
176 case WDIOC_KEEPALIVE:
177 geodewdt_ping();
178 return 0;
179
180 case WDIOC_SETTIMEOUT:
181 if (get_user(interval, p))
182 return -EFAULT;
183
184 if (geodewdt_set_heartbeat(interval))
185 return -EINVAL;
186 /* Fall through */
187 case WDIOC_GETTIMEOUT:
188 return put_user(timeout, p);
189
197 default: 190 default:
198 return -ENOTTY; 191 return -ENOTTY;
199 } 192 }
@@ -202,22 +195,21 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
202} 195}
203 196
204static const struct file_operations geodewdt_fops = { 197static const struct file_operations geodewdt_fops = {
205 .owner = THIS_MODULE, 198 .owner = THIS_MODULE,
206 .llseek = no_llseek, 199 .llseek = no_llseek,
207 .write = geodewdt_write, 200 .write = geodewdt_write,
208 .ioctl = geodewdt_ioctl, 201 .ioctl = geodewdt_ioctl,
209 .open = geodewdt_open, 202 .open = geodewdt_open,
210 .release = geodewdt_release, 203 .release = geodewdt_release,
211}; 204};
212 205
213static struct miscdevice geodewdt_miscdev = { 206static struct miscdevice geodewdt_miscdev = {
214 .minor = WATCHDOG_MINOR, 207 .minor = WATCHDOG_MINOR,
215 .name = "watchdog", 208 .name = "watchdog",
216 .fops = &geodewdt_fops 209 .fops = &geodewdt_fops,
217}; 210};
218 211
219static int __devinit 212static int __devinit geodewdt_probe(struct platform_device *dev)
220geodewdt_probe(struct platform_device *dev)
221{ 213{
222 int ret, timer; 214 int ret, timer;
223 215
@@ -248,15 +240,13 @@ geodewdt_probe(struct platform_device *dev)
248 return ret; 240 return ret;
249} 241}
250 242
251static int __devexit 243static int __devexit geodewdt_remove(struct platform_device *dev)
252geodewdt_remove(struct platform_device *dev)
253{ 244{
254 misc_deregister(&geodewdt_miscdev); 245 misc_deregister(&geodewdt_miscdev);
255 return 0; 246 return 0;
256} 247}
257 248
258static void 249static void geodewdt_shutdown(struct platform_device *dev)
259geodewdt_shutdown(struct platform_device *dev)
260{ 250{
261 geodewdt_disable(); 251 geodewdt_disable();
262} 252}
@@ -271,8 +261,7 @@ static struct platform_driver geodewdt_driver = {
271 }, 261 },
272}; 262};
273 263
274static int __init 264static int __init geodewdt_init(void)
275geodewdt_init(void)
276{ 265{
277 int ret; 266 int ret;
278 267
@@ -292,8 +281,7 @@ err:
292 return ret; 281 return ret;
293} 282}
294 283
295static void __exit 284static void __exit geodewdt_exit(void)
296geodewdt_exit(void)
297{ 285{
298 platform_device_unregister(geodewdt_platform_device); 286 platform_device_unregister(geodewdt_platform_device);
299 platform_driver_unregister(&geodewdt_driver); 287 platform_driver_unregister(&geodewdt_driver);
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index ccd6c530782d..d039d5f2fd1c 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -39,9 +39,7 @@
39#include <linux/string.h> 39#include <linux/string.h>
40#include <linux/bootmem.h> 40#include <linux/bootmem.h>
41#include <linux/slab.h> 41#include <linux/slab.h>
42#include <asm/dmi.h>
43#include <asm/desc.h> 42#include <asm/desc.h>
44#include <asm/kdebug.h>
45 43
46#define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ 44#define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */
47#define CRU_BIOS_SIGNATURE_VALUE 0x55524324 45#define CRU_BIOS_SIGNATURE_VALUE 0x55524324
@@ -407,7 +405,7 @@ static int __devinit detect_cru_service(void)
407 dmi_walk(dmi_find_cru); 405 dmi_walk(dmi_find_cru);
408 406
409 /* if cru_rom_addr has been set then we found a CRU service */ 407 /* if cru_rom_addr has been set then we found a CRU service */
410 return ((cru_rom_addr != NULL)? 0: -ENODEV); 408 return ((cru_rom_addr != NULL) ? 0: -ENODEV);
411} 409}
412 410
413/* ------------------------------------------------------------------------- */ 411/* ------------------------------------------------------------------------- */
@@ -535,7 +533,7 @@ static ssize_t hpwdt_write(struct file *file, const char __user *data,
535 /* scan to see whether or not we got the magic char. */ 533 /* scan to see whether or not we got the magic char. */
536 for (i = 0; i != len; i++) { 534 for (i = 0; i != len; i++) {
537 char c; 535 char c;
538 if (get_user(c, data+i)) 536 if (get_user(c, data + i))
539 return -EFAULT; 537 return -EFAULT;
540 if (c == 'V') 538 if (c == 'V')
541 expect_release = 42; 539 expect_release = 42;
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index ca44fd9b19bb..c13383f7fcb9 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -9,18 +9,18 @@
9 * as published by the Free Software Foundation; either version 9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version. 10 * 2 of the License, or (at your option) any later version.
11 * 11 *
12 * based on i810-tco.c which is in turn based on softdog.c 12 * based on i810-tco.c which is in turn based on softdog.c
13 * 13 *
14 * The timer is implemented in the following I/O controller hubs: 14 * The timer is implemented in the following I/O controller hubs:
15 * (See the intel documentation on http://developer.intel.com.) 15 * (See the intel documentation on http://developer.intel.com.)
16 * 6300ESB chip : document number 300641-003 16 * 6300ESB chip : document number 300641-003
17 * 17 *
18 * 2004YYZZ Ross Biro 18 * 2004YYZZ Ross Biro
19 * Initial version 0.01 19 * Initial version 0.01
20 * 2004YYZZ Ross Biro 20 * 2004YYZZ Ross Biro
21 * Version 0.02 21 * Version 0.02
22 * 20050210 David Härdeman <david@2gen.com> 22 * 20050210 David Härdeman <david@2gen.com>
23 * Ported driver to kernel 2.6 23 * Ported driver to kernel 2.6
24 */ 24 */
25 25
26/* 26/*
@@ -38,9 +38,8 @@
38#include <linux/init.h> 38#include <linux/init.h>
39#include <linux/pci.h> 39#include <linux/pci.h>
40#include <linux/ioport.h> 40#include <linux/ioport.h>
41 41#include <linux/uaccess.h>
42#include <asm/uaccess.h> 42#include <linux/io.h>
43#include <asm/io.h>
44 43
45/* Module and version information */ 44/* Module and version information */
46#define ESB_VERSION "0.03" 45#define ESB_VERSION "0.03"
@@ -59,17 +58,17 @@
59#define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */ 58#define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */
60 59
61/* Lock register bits */ 60/* Lock register bits */
62#define ESB_WDT_FUNC ( 0x01 << 2 ) /* Watchdog functionality */ 61#define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */
63#define ESB_WDT_ENABLE ( 0x01 << 1 ) /* Enable WDT */ 62#define ESB_WDT_ENABLE (0x01 << 1) /* Enable WDT */
64#define ESB_WDT_LOCK ( 0x01 << 0 ) /* Lock (nowayout) */ 63#define ESB_WDT_LOCK (0x01 << 0) /* Lock (nowayout) */
65 64
66/* Config register bits */ 65/* Config register bits */
67#define ESB_WDT_REBOOT ( 0x01 << 5 ) /* Enable reboot on timeout */ 66#define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */
68#define ESB_WDT_FREQ ( 0x01 << 2 ) /* Decrement frequency */ 67#define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */
69#define ESB_WDT_INTTYPE ( 0x11 << 0 ) /* Interrupt type on timer1 timeout */ 68#define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */
70 69
71/* Reload register bits */ 70/* Reload register bits */
72#define ESB_WDT_RELOAD ( 0x01 << 8 ) /* prevent timeout */ 71#define ESB_WDT_RELOAD (0x01 << 8) /* prevent timeout */
73 72
74/* Magic constants */ 73/* Magic constants */
75#define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */ 74#define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */
@@ -84,14 +83,20 @@ static unsigned short triggered; /* The status of the watchdog upon boot */
84static char esb_expect_close; 83static char esb_expect_close;
85 84
86/* module parameters */ 85/* module parameters */
87#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (1<heartbeat<2*1023) */ 86/* 30 sec default heartbeat (1 < heartbeat < 2*1023) */
87#define WATCHDOG_HEARTBEAT 30
88static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 88static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
89
89module_param(heartbeat, int, 0); 90module_param(heartbeat, int, 0);
90MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 91MODULE_PARM_DESC(heartbeat,
92 "Watchdog heartbeat in seconds. (1<heartbeat<2046, default="
93 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
91 94
92static int nowayout = WATCHDOG_NOWAYOUT; 95static int nowayout = WATCHDOG_NOWAYOUT;
93module_param(nowayout, int, 0); 96module_param(nowayout, int, 0);
94MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 97MODULE_PARM_DESC(nowayout,
98 "Watchdog cannot be stopped once started (default="
99 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
95 100
96/* 101/*
97 * Some i6300ESB specific functions 102 * Some i6300ESB specific functions
@@ -103,9 +108,10 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" _
103 * reload register. After this the appropriate registers can be written 108 * reload register. After this the appropriate registers can be written
104 * to once before they need to be unlocked again. 109 * to once before they need to be unlocked again.
105 */ 110 */
106static inline void esb_unlock_registers(void) { 111static inline void esb_unlock_registers(void)
107 writeb(ESB_UNLOCK1, ESB_RELOAD_REG); 112{
108 writeb(ESB_UNLOCK2, ESB_RELOAD_REG); 113 writeb(ESB_UNLOCK1, ESB_RELOAD_REG);
114 writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
109} 115}
110 116
111static void esb_timer_start(void) 117static void esb_timer_start(void)
@@ -114,8 +120,7 @@ static void esb_timer_start(void)
114 120
115 /* Enable or Enable + Lock? */ 121 /* Enable or Enable + Lock? */
116 val = 0x02 | (nowayout ? 0x01 : 0x00); 122 val = 0x02 | (nowayout ? 0x01 : 0x00);
117 123 pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
118 pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
119} 124}
120 125
121static int esb_timer_stop(void) 126static int esb_timer_stop(void)
@@ -140,7 +145,7 @@ static void esb_timer_keepalive(void)
140 spin_lock(&esb_lock); 145 spin_lock(&esb_lock);
141 esb_unlock_registers(); 146 esb_unlock_registers();
142 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 147 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
143 /* FIXME: Do we need to flush anything here? */ 148 /* FIXME: Do we need to flush anything here? */
144 spin_unlock(&esb_lock); 149 spin_unlock(&esb_lock);
145} 150}
146 151
@@ -165,9 +170,9 @@ static int esb_timer_set_heartbeat(int time)
165 170
166 /* Write timer 2 */ 171 /* Write timer 2 */
167 esb_unlock_registers(); 172 esb_unlock_registers();
168 writel(val, ESB_TIMER2_REG); 173 writel(val, ESB_TIMER2_REG);
169 174
170 /* Reload */ 175 /* Reload */
171 esb_unlock_registers(); 176 esb_unlock_registers();
172 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 177 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
173 178
@@ -179,54 +184,55 @@ static int esb_timer_set_heartbeat(int time)
179 return 0; 184 return 0;
180} 185}
181 186
182static int esb_timer_read (void) 187static int esb_timer_read(void)
183{ 188{
184 u32 count; 189 u32 count;
185 190
186 /* This isn't documented, and doesn't take into 191 /* This isn't documented, and doesn't take into
187 * acount which stage is running, but it looks 192 * acount which stage is running, but it looks
188 * like a 20 bit count down, so we might as well report it. 193 * like a 20 bit count down, so we might as well report it.
189 */ 194 */
190 pci_read_config_dword(esb_pci, 0x64, &count); 195 pci_read_config_dword(esb_pci, 0x64, &count);
191 return (int)count; 196 return (int)count;
192} 197}
193 198
194/* 199/*
195 * /dev/watchdog handling 200 * /dev/watchdog handling
196 */ 201 */
197 202
198static int esb_open (struct inode *inode, struct file *file) 203static int esb_open(struct inode *inode, struct file *file)
199{ 204{
200 /* /dev/watchdog can only be opened once */ 205 /* /dev/watchdog can only be opened once */
201 if (test_and_set_bit(0, &timer_alive)) 206 if (test_and_set_bit(0, &timer_alive))
202 return -EBUSY; 207 return -EBUSY;
203 208
204 /* Reload and activate timer */ 209 /* Reload and activate timer */
205 esb_timer_keepalive (); 210 esb_timer_keepalive();
206 esb_timer_start (); 211 esb_timer_start();
207 212
208 return nonseekable_open(inode, file); 213 return nonseekable_open(inode, file);
209} 214}
210 215
211static int esb_release (struct inode *inode, struct file *file) 216static int esb_release(struct inode *inode, struct file *file)
212{ 217{
213 /* Shut off the timer. */ 218 /* Shut off the timer. */
214 if (esb_expect_close == 42) { 219 if (esb_expect_close == 42)
215 esb_timer_stop (); 220 esb_timer_stop();
216 } else { 221 else {
217 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 222 printk(KERN_CRIT PFX
218 esb_timer_keepalive (); 223 "Unexpected close, not stopping watchdog!\n");
219 } 224 esb_timer_keepalive();
220 clear_bit(0, &timer_alive); 225 }
221 esb_expect_close = 0; 226 clear_bit(0, &timer_alive);
222 return 0; 227 esb_expect_close = 0;
228 return 0;
223} 229}
224 230
225static ssize_t esb_write (struct file *file, const char __user *data, 231static ssize_t esb_write(struct file *file, const char __user *data,
226 size_t len, loff_t * ppos) 232 size_t len, loff_t *ppos)
227{ 233{
228 /* See if we got the magic character 'V' and reload the timer */ 234 /* See if we got the magic character 'V' and reload the timer */
229 if (len) { 235 if (len) {
230 if (!nowayout) { 236 if (!nowayout) {
231 size_t i; 237 size_t i;
232 238
@@ -237,7 +243,7 @@ static ssize_t esb_write (struct file *file, const char __user *data,
237 /* scan to see whether or not we got the magic character */ 243 /* scan to see whether or not we got the magic character */
238 for (i = 0; i != len; i++) { 244 for (i = 0; i != len; i++) {
239 char c; 245 char c;
240 if(get_user(c, data+i)) 246 if (get_user(c, data + i))
241 return -EFAULT; 247 return -EFAULT;
242 if (c == 'V') 248 if (c == 'V')
243 esb_expect_close = 42; 249 esb_expect_close = 42;
@@ -245,92 +251,84 @@ static ssize_t esb_write (struct file *file, const char __user *data,
245 } 251 }
246 252
247 /* someone wrote to us, we should reload the timer */ 253 /* someone wrote to us, we should reload the timer */
248 esb_timer_keepalive (); 254 esb_timer_keepalive();
249 } 255 }
250 return len; 256 return len;
251} 257}
252 258
253static int esb_ioctl (struct inode *inode, struct file *file, 259static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
254 unsigned int cmd, unsigned long arg)
255{ 260{
256 int new_options, retval = -EINVAL; 261 int new_options, retval = -EINVAL;
257 int new_heartbeat; 262 int new_heartbeat;
258 void __user *argp = (void __user *)arg; 263 void __user *argp = (void __user *)arg;
259 int __user *p = argp; 264 int __user *p = argp;
260 static struct watchdog_info ident = { 265 static struct watchdog_info ident = {
261 .options = WDIOF_SETTIMEOUT | 266 .options = WDIOF_SETTIMEOUT |
262 WDIOF_KEEPALIVEPING | 267 WDIOF_KEEPALIVEPING |
263 WDIOF_MAGICCLOSE, 268 WDIOF_MAGICCLOSE,
264 .firmware_version = 0, 269 .firmware_version = 0,
265 .identity = ESB_MODULE_NAME, 270 .identity = ESB_MODULE_NAME,
266 }; 271 };
267 272
268 switch (cmd) { 273 switch (cmd) {
269 case WDIOC_GETSUPPORT: 274 case WDIOC_GETSUPPORT:
270 return copy_to_user(argp, &ident, 275 return copy_to_user(argp, &ident,
271 sizeof (ident)) ? -EFAULT : 0; 276 sizeof(ident)) ? -EFAULT : 0;
272
273 case WDIOC_GETSTATUS:
274 return put_user (esb_timer_read(), p);
275
276 case WDIOC_GETBOOTSTATUS:
277 return put_user (triggered, p);
278 277
279 case WDIOC_KEEPALIVE: 278 case WDIOC_GETSTATUS:
280 esb_timer_keepalive (); 279 return put_user(esb_timer_read(), p);
281 return 0;
282 280
283 case WDIOC_SETOPTIONS: 281 case WDIOC_GETBOOTSTATUS:
284 { 282 return put_user(triggered, p);
285 if (get_user (new_options, p))
286 return -EFAULT;
287 283
288 if (new_options & WDIOS_DISABLECARD) { 284 case WDIOC_SETOPTIONS:
289 esb_timer_stop (); 285 {
290 retval = 0; 286 if (get_user(new_options, p))
291 } 287 return -EFAULT;
292 288
293 if (new_options & WDIOS_ENABLECARD) { 289 if (new_options & WDIOS_DISABLECARD) {
294 esb_timer_keepalive (); 290 esb_timer_stop();
295 esb_timer_start (); 291 retval = 0;
296 retval = 0; 292 }
297 }
298
299 return retval;
300 }
301
302 case WDIOC_SETTIMEOUT:
303 {
304 if (get_user(new_heartbeat, p))
305 return -EFAULT;
306
307 if (esb_timer_set_heartbeat(new_heartbeat))
308 return -EINVAL;
309
310 esb_timer_keepalive ();
311 /* Fall */
312 }
313
314 case WDIOC_GETTIMEOUT:
315 return put_user(heartbeat, p);
316 293
317 default: 294 if (new_options & WDIOS_ENABLECARD) {
318 return -ENOTTY; 295 esb_timer_keepalive();
319 } 296 esb_timer_start();
297 retval = 0;
298 }
299 return retval;
300 }
301 case WDIOC_KEEPALIVE:
302 esb_timer_keepalive();
303 return 0;
304
305 case WDIOC_SETTIMEOUT:
306 {
307 if (get_user(new_heartbeat, p))
308 return -EFAULT;
309 if (esb_timer_set_heartbeat(new_heartbeat))
310 return -EINVAL;
311 esb_timer_keepalive();
312 /* Fall */
313 }
314 case WDIOC_GETTIMEOUT:
315 return put_user(heartbeat, p);
316 default:
317 return -ENOTTY;
318 }
320} 319}
321 320
322/* 321/*
323 * Notify system 322 * Notify system
324 */ 323 */
325 324
326static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused) 325static int esb_notify_sys(struct notifier_block *this,
326 unsigned long code, void *unused)
327{ 327{
328 if (code==SYS_DOWN || code==SYS_HALT) { 328 if (code == SYS_DOWN || code == SYS_HALT)
329 /* Turn the WDT off */ 329 esb_timer_stop(); /* Turn the WDT off */
330 esb_timer_stop ();
331 }
332 330
333 return NOTIFY_DONE; 331 return NOTIFY_DONE;
334} 332}
335 333
336/* 334/*
@@ -338,22 +336,22 @@ static int esb_notify_sys (struct notifier_block *this, unsigned long code, void
338 */ 336 */
339 337
340static const struct file_operations esb_fops = { 338static const struct file_operations esb_fops = {
341 .owner = THIS_MODULE, 339 .owner = THIS_MODULE,
342 .llseek = no_llseek, 340 .llseek = no_llseek,
343 .write = esb_write, 341 .write = esb_write,
344 .ioctl = esb_ioctl, 342 .unlocked_ioctl = esb_ioctl,
345 .open = esb_open, 343 .open = esb_open,
346 .release = esb_release, 344 .release = esb_release,
347}; 345};
348 346
349static struct miscdevice esb_miscdev = { 347static struct miscdevice esb_miscdev = {
350 .minor = WATCHDOG_MINOR, 348 .minor = WATCHDOG_MINOR,
351 .name = "watchdog", 349 .name = "watchdog",
352 .fops = &esb_fops, 350 .fops = &esb_fops,
353}; 351};
354 352
355static struct notifier_block esb_notifier = { 353static struct notifier_block esb_notifier = {
356 .notifier_call = esb_notify_sys, 354 .notifier_call = esb_notify_sys,
357}; 355};
358 356
359/* 357/*
@@ -365,50 +363,44 @@ static struct notifier_block esb_notifier = {
365 * want to register another driver on the same PCI id. 363 * want to register another driver on the same PCI id.
366 */ 364 */
367static struct pci_device_id esb_pci_tbl[] = { 365static struct pci_device_id esb_pci_tbl[] = {
368 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, 366 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
369 { 0, }, /* End of list */ 367 { 0, }, /* End of list */
370}; 368};
371MODULE_DEVICE_TABLE (pci, esb_pci_tbl); 369MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
372 370
373/* 371/*
374 * Init & exit routines 372 * Init & exit routines
375 */ 373 */
376 374
377static unsigned char __init esb_getdevice (void) 375static unsigned char __init esb_getdevice(void)
378{ 376{
379 u8 val1; 377 u8 val1;
380 unsigned short val2; 378 unsigned short val2;
379 /*
380 * Find the PCI device
381 */
381 382
382 struct pci_dev *dev = NULL; 383 esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL,
383 /* 384 PCI_DEVICE_ID_INTEL_ESB_9, NULL);
384 * Find the PCI device
385 */
386
387 for_each_pci_dev(dev) {
388 if (pci_match_id(esb_pci_tbl, dev)) {
389 esb_pci = dev;
390 break;
391 }
392 }
393 385
394 if (esb_pci) { 386 if (esb_pci) {
395 if (pci_enable_device(esb_pci)) { 387 if (pci_enable_device(esb_pci)) {
396 printk (KERN_ERR PFX "failed to enable device\n"); 388 printk(KERN_ERR PFX "failed to enable device\n");
397 goto err_devput; 389 goto err_devput;
398 } 390 }
399 391
400 if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { 392 if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
401 printk (KERN_ERR PFX "failed to request region\n"); 393 printk(KERN_ERR PFX "failed to request region\n");
402 goto err_disable; 394 goto err_disable;
403 } 395 }
404 396
405 BASEADDR = ioremap(pci_resource_start(esb_pci, 0), 397 BASEADDR = ioremap(pci_resource_start(esb_pci, 0),
406 pci_resource_len(esb_pci, 0)); 398 pci_resource_len(esb_pci, 0));
407 if (BASEADDR == NULL) { 399 if (BASEADDR == NULL) {
408 /* Something's wrong here, BASEADDR has to be set */ 400 /* Something's wrong here, BASEADDR has to be set */
409 printk (KERN_ERR PFX "failed to get BASEADDR\n"); 401 printk(KERN_ERR PFX "failed to get BASEADDR\n");
410 goto err_release; 402 goto err_release;
411 } 403 }
412 404
413 /* 405 /*
414 * The watchdog has two timers, it can be setup so that the 406 * The watchdog has two timers, it can be setup so that the
@@ -425,7 +417,7 @@ static unsigned char __init esb_getdevice (void)
425 /* Check that the WDT isn't already locked */ 417 /* Check that the WDT isn't already locked */
426 pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); 418 pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
427 if (val1 & ESB_WDT_LOCK) 419 if (val1 & ESB_WDT_LOCK)
428 printk (KERN_WARNING PFX "nowayout already set\n"); 420 printk(KERN_WARNING PFX "nowayout already set\n");
429 421
430 /* Set the timer to watchdog mode and disable it for now */ 422 /* Set the timer to watchdog mode and disable it for now */
431 pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); 423 pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
@@ -452,44 +444,44 @@ err_devput:
452 return 0; 444 return 0;
453} 445}
454 446
455static int __init watchdog_init (void) 447static int __init watchdog_init(void)
456{ 448{
457 int ret; 449 int ret;
458 450
459 /* Check whether or not the hardware watchdog is there */ 451 /* Check whether or not the hardware watchdog is there */
460 if (!esb_getdevice () || esb_pci == NULL) 452 if (!esb_getdevice() || esb_pci == NULL)
461 return -ENODEV; 453 return -ENODEV;
462 454
463 /* Check that the heartbeat value is within it's range ; if not reset to the default */ 455 /* Check that the heartbeat value is within it's range;
464 if (esb_timer_set_heartbeat (heartbeat)) { 456 if not reset to the default */
465 esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT); 457 if (esb_timer_set_heartbeat(heartbeat)) {
466 printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n", 458 esb_timer_set_heartbeat(WATCHDOG_HEARTBEAT);
467 heartbeat); 459 printk(KERN_INFO PFX
468 } 460 "heartbeat value must be 1<heartbeat<2046, using %d\n",
469 461 heartbeat);
470 ret = register_reboot_notifier(&esb_notifier); 462 }
471 if (ret != 0) { 463 ret = register_reboot_notifier(&esb_notifier);
472 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 464 if (ret != 0) {
473 ret); 465 printk(KERN_ERR PFX
474 goto err_unmap; 466 "cannot register reboot notifier (err=%d)\n", ret);
475 } 467 goto err_unmap;
476 468 }
477 ret = misc_register(&esb_miscdev);
478 if (ret != 0) {
479 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
480 WATCHDOG_MINOR, ret);
481 goto err_notifier;
482 }
483
484 esb_timer_stop ();
485
486 printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
487 BASEADDR, heartbeat, nowayout);
488 469
489 return 0; 470 ret = misc_register(&esb_miscdev);
471 if (ret != 0) {
472 printk(KERN_ERR PFX
473 "cannot register miscdev on minor=%d (err=%d)\n",
474 WATCHDOG_MINOR, ret);
475 goto err_notifier;
476 }
477 esb_timer_stop();
478 printk(KERN_INFO PFX
479 "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
480 BASEADDR, heartbeat, nowayout);
481 return 0;
490 482
491err_notifier: 483err_notifier:
492 unregister_reboot_notifier(&esb_notifier); 484 unregister_reboot_notifier(&esb_notifier);
493err_unmap: 485err_unmap:
494 iounmap(BASEADDR); 486 iounmap(BASEADDR);
495/* err_release: */ 487/* err_release: */
@@ -498,18 +490,18 @@ err_unmap:
498 pci_disable_device(esb_pci); 490 pci_disable_device(esb_pci);
499/* err_devput: */ 491/* err_devput: */
500 pci_dev_put(esb_pci); 492 pci_dev_put(esb_pci);
501 return ret; 493 return ret;
502} 494}
503 495
504static void __exit watchdog_cleanup (void) 496static void __exit watchdog_cleanup(void)
505{ 497{
506 /* Stop the timer before we leave */ 498 /* Stop the timer before we leave */
507 if (!nowayout) 499 if (!nowayout)
508 esb_timer_stop (); 500 esb_timer_stop();
509 501
510 /* Deregister */ 502 /* Deregister */
511 misc_deregister(&esb_miscdev); 503 misc_deregister(&esb_miscdev);
512 unregister_reboot_notifier(&esb_notifier); 504 unregister_reboot_notifier(&esb_notifier);
513 iounmap(BASEADDR); 505 iounmap(BASEADDR);
514 pci_release_region(esb_pci, 0); 506 pci_release_region(esb_pci, 0);
515 pci_disable_device(esb_pci); 507 pci_disable_device(esb_pci);
diff --git a/drivers/watchdog/iTCO_vendor.h b/drivers/watchdog/iTCO_vendor.h
new file mode 100644
index 000000000000..9e27e6422f66
--- /dev/null
+++ b/drivers/watchdog/iTCO_vendor.h
@@ -0,0 +1,15 @@
1/* iTCO Vendor Specific Support hooks */
2#ifdef CONFIG_ITCO_VENDOR_SUPPORT
3extern void iTCO_vendor_pre_start(unsigned long, unsigned int);
4extern void iTCO_vendor_pre_stop(unsigned long);
5extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int);
6extern void iTCO_vendor_pre_set_heartbeat(unsigned int);
7extern int iTCO_vendor_check_noreboot_on(void);
8#else
9#define iTCO_vendor_pre_start(acpibase, heartbeat) {}
10#define iTCO_vendor_pre_stop(acpibase) {}
11#define iTCO_vendor_pre_keepalive(acpibase, heartbeat) {}
12#define iTCO_vendor_pre_set_heartbeat(heartbeat) {}
13#define iTCO_vendor_check_noreboot_on() 1
14 /* 1=check noreboot; 0=don't check */
15#endif
diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c
index cafc465f2ae3..ca344a85eb95 100644
--- a/drivers/watchdog/iTCO_vendor_support.c
+++ b/drivers/watchdog/iTCO_vendor_support.c
@@ -18,9 +18,9 @@
18 */ 18 */
19 19
20/* Module and version information */ 20/* Module and version information */
21#define DRV_NAME "iTCO_vendor_support" 21#define DRV_NAME "iTCO_vendor_support"
22#define DRV_VERSION "1.01" 22#define DRV_VERSION "1.01"
23#define DRV_RELDATE "11-Nov-2006" 23#define DRV_RELDATE "11-Nov-2006"
24#define PFX DRV_NAME ": " 24#define PFX DRV_NAME ": "
25 25
26/* Includes */ 26/* Includes */
@@ -31,19 +31,22 @@
31#include <linux/kernel.h> /* For printk/panic/... */ 31#include <linux/kernel.h> /* For printk/panic/... */
32#include <linux/init.h> /* For __init/__exit/... */ 32#include <linux/init.h> /* For __init/__exit/... */
33#include <linux/ioport.h> /* For io-port access */ 33#include <linux/ioport.h> /* For io-port access */
34#include <linux/io.h> /* For inb/outb/... */
34 35
35#include <asm/io.h> /* For inb/outb/... */ 36#include "iTCO_vendor.h"
36 37
37/* iTCO defines */ 38/* iTCO defines */
38#define SMI_EN acpibase + 0x30 /* SMI Control and Enable Register */ 39#define SMI_EN acpibase + 0x30 /* SMI Control and Enable Register */
39#define TCOBASE acpibase + 0x60 /* TCO base address */ 40#define TCOBASE acpibase + 0x60 /* TCO base address */
40#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ 41#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */
41 42
42/* List of vendor support modes */ 43/* List of vendor support modes */
43#define SUPERMICRO_OLD_BOARD 1 /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */ 44/* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */
44#define SUPERMICRO_NEW_BOARD 2 /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems */ 45#define SUPERMICRO_OLD_BOARD 1
46/* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems */
47#define SUPERMICRO_NEW_BOARD 2
45 48
46static int vendorsupport = 0; 49static int vendorsupport;
47module_param(vendorsupport, int, 0); 50module_param(vendorsupport, int, 0);
48MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+"); 51MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+");
49 52
@@ -143,34 +146,35 @@ static void supermicro_old_pre_keepalive(unsigned long acpibase)
143 */ 146 */
144 147
145/* I/O Port's */ 148/* I/O Port's */
146#define SM_REGINDEX 0x2e /* SuperMicro ICH4+ Register Index */ 149#define SM_REGINDEX 0x2e /* SuperMicro ICH4+ Register Index */
147#define SM_DATAIO 0x2f /* SuperMicro ICH4+ Register Data I/O */ 150#define SM_DATAIO 0x2f /* SuperMicro ICH4+ Register Data I/O */
148 151
149/* Control Register's */ 152/* Control Register's */
150#define SM_CTLPAGESW 0x07 /* SuperMicro ICH4+ Control Page Switch */ 153#define SM_CTLPAGESW 0x07 /* SuperMicro ICH4+ Control Page Switch */
151#define SM_CTLPAGE 0x08 /* SuperMicro ICH4+ Control Page Num */ 154#define SM_CTLPAGE 0x08 /* SuperMicro ICH4+ Control Page Num */
152 155
153#define SM_WATCHENABLE 0x30 /* Watchdog enable: Bit 0: 0=off, 1=on */ 156#define SM_WATCHENABLE 0x30 /* Watchdog enable: Bit 0: 0=off, 1=on */
154 157
155#define SM_WATCHPAGE 0x87 /* Watchdog unlock control page */ 158#define SM_WATCHPAGE 0x87 /* Watchdog unlock control page */
156 159
157#define SM_ENDWATCH 0xAA /* Watchdog lock control page */ 160#define SM_ENDWATCH 0xAA /* Watchdog lock control page */
158 161
159#define SM_COUNTMODE 0xf5 /* Watchdog count mode select */ 162#define SM_COUNTMODE 0xf5 /* Watchdog count mode select */
160 /* (Bit 3: 0 = seconds, 1 = minutes */ 163 /* (Bit 3: 0 = seconds, 1 = minutes */
161 164
162#define SM_WATCHTIMER 0xf6 /* 8-bits, Watchdog timer counter (RW) */ 165#define SM_WATCHTIMER 0xf6 /* 8-bits, Watchdog timer counter (RW) */
163 166
164#define SM_RESETCONTROL 0xf7 /* Watchdog reset control */ 167#define SM_RESETCONTROL 0xf7 /* Watchdog reset control */
165 /* Bit 6: timer is reset by kbd interrupt */ 168 /* Bit 6: timer is reset by kbd interrupt */
166 /* Bit 7: timer is reset by mouse interrupt */ 169 /* Bit 7: timer is reset by mouse interrupt */
167 170
168static void supermicro_new_unlock_watchdog(void) 171static void supermicro_new_unlock_watchdog(void)
169{ 172{
170 outb(SM_WATCHPAGE, SM_REGINDEX); /* Write 0x87 to port 0x2e twice */ 173 /* Write 0x87 to port 0x2e twice */
171 outb(SM_WATCHPAGE, SM_REGINDEX); 174 outb(SM_WATCHPAGE, SM_REGINDEX);
172 175 outb(SM_WATCHPAGE, SM_REGINDEX);
173 outb(SM_CTLPAGESW, SM_REGINDEX); /* Switch to watchdog control page */ 176 /* Switch to watchdog control page */
177 outb(SM_CTLPAGESW, SM_REGINDEX);
174 outb(SM_CTLPAGE, SM_DATAIO); 178 outb(SM_CTLPAGE, SM_DATAIO);
175} 179}
176 180
@@ -192,7 +196,7 @@ static void supermicro_new_pre_start(unsigned int heartbeat)
192 outb(val, SM_DATAIO); 196 outb(val, SM_DATAIO);
193 197
194 /* Write heartbeat interval to WDOG */ 198 /* Write heartbeat interval to WDOG */
195 outb (SM_WATCHTIMER, SM_REGINDEX); 199 outb(SM_WATCHTIMER, SM_REGINDEX);
196 outb((heartbeat & 255), SM_DATAIO); 200 outb((heartbeat & 255), SM_DATAIO);
197 201
198 /* Make sure keyboard/mouse interrupts don't interfere */ 202 /* Make sure keyboard/mouse interrupts don't interfere */
@@ -277,7 +281,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_set_heartbeat);
277 281
278int iTCO_vendor_check_noreboot_on(void) 282int iTCO_vendor_check_noreboot_on(void)
279{ 283{
280 switch(vendorsupport) { 284 switch (vendorsupport) {
281 case SUPERMICRO_OLD_BOARD: 285 case SUPERMICRO_OLD_BOARD:
282 return 0; 286 return 0;
283 default: 287 default:
@@ -288,13 +292,13 @@ EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
288 292
289static int __init iTCO_vendor_init_module(void) 293static int __init iTCO_vendor_init_module(void)
290{ 294{
291 printk (KERN_INFO PFX "vendor-support=%d\n", vendorsupport); 295 printk(KERN_INFO PFX "vendor-support=%d\n", vendorsupport);
292 return 0; 296 return 0;
293} 297}
294 298
295static void __exit iTCO_vendor_exit_module(void) 299static void __exit iTCO_vendor_exit_module(void)
296{ 300{
297 printk (KERN_INFO PFX "Module Unloaded\n"); 301 printk(KERN_INFO PFX "Module Unloaded\n");
298} 302}
299 303
300module_init(iTCO_vendor_init_module); 304module_init(iTCO_vendor_init_module);
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 95ba985bd341..bfb93bc2ca9f 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -55,9 +55,9 @@
55 */ 55 */
56 56
57/* Module and version information */ 57/* Module and version information */
58#define DRV_NAME "iTCO_wdt" 58#define DRV_NAME "iTCO_wdt"
59#define DRV_VERSION "1.03" 59#define DRV_VERSION "1.03"
60#define DRV_RELDATE "30-Apr-2008" 60#define DRV_RELDATE "30-Apr-2008"
61#define PFX DRV_NAME ": " 61#define PFX DRV_NAME ": "
62 62
63/* Includes */ 63/* Includes */
@@ -66,7 +66,8 @@
66#include <linux/types.h> /* For standard types (like size_t) */ 66#include <linux/types.h> /* For standard types (like size_t) */
67#include <linux/errno.h> /* For the -ENODEV/... values */ 67#include <linux/errno.h> /* For the -ENODEV/... values */
68#include <linux/kernel.h> /* For printk/panic/... */ 68#include <linux/kernel.h> /* For printk/panic/... */
69#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ 69#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV
70 (WATCHDOG_MINOR) */
70#include <linux/watchdog.h> /* For the watchdog specific items */ 71#include <linux/watchdog.h> /* For the watchdog specific items */
71#include <linux/init.h> /* For __init/__exit/... */ 72#include <linux/init.h> /* For __init/__exit/... */
72#include <linux/fs.h> /* For file operations */ 73#include <linux/fs.h> /* For file operations */
@@ -74,9 +75,10 @@
74#include <linux/pci.h> /* For pci functions */ 75#include <linux/pci.h> /* For pci functions */
75#include <linux/ioport.h> /* For io-port access */ 76#include <linux/ioport.h> /* For io-port access */
76#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ 77#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
78#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
79#include <linux/io.h> /* For inb/outb/... */
77 80
78#include <asm/uaccess.h> /* For copy_to_user/put_user/... */ 81#include "iTCO_vendor.h"
79#include <asm/io.h> /* For inb/outb/... */
80 82
81/* TCO related info */ 83/* TCO related info */
82enum iTCO_chipsets { 84enum iTCO_chipsets {
@@ -105,7 +107,7 @@ enum iTCO_chipsets {
105 TCO_ICH9, /* ICH9 */ 107 TCO_ICH9, /* ICH9 */
106 TCO_ICH9R, /* ICH9R */ 108 TCO_ICH9R, /* ICH9R */
107 TCO_ICH9DH, /* ICH9DH */ 109 TCO_ICH9DH, /* ICH9DH */
108 TCO_ICH9DO, /* ICH9DO */ 110 TCO_ICH9DO, /* ICH9DO */
109 TCO_631XESB, /* 631xESB/632xESB */ 111 TCO_631XESB, /* 631xESB/632xESB */
110}; 112};
111 113
@@ -140,7 +142,7 @@ static struct {
140 {"ICH9DH", 2}, 142 {"ICH9DH", 2},
141 {"ICH9DO", 2}, 143 {"ICH9DO", 2},
142 {"631xESB/632xESB", 2}, 144 {"631xESB/632xESB", 2},
143 {NULL,0} 145 {NULL, 0}
144}; 146};
145 147
146#define ITCO_PCI_DEVICE(dev, data) \ 148#define ITCO_PCI_DEVICE(dev, data) \
@@ -159,32 +161,32 @@ static struct {
159 * functions that probably will be registered by other drivers. 161 * functions that probably will be registered by other drivers.
160 */ 162 */
161static struct pci_device_id iTCO_wdt_pci_tbl[] = { 163static struct pci_device_id iTCO_wdt_pci_tbl[] = {
162 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH )}, 164 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH)},
163 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0 )}, 165 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0)},
164 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2 )}, 166 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2)},
165 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_10, TCO_ICH2M )}, 167 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_10, TCO_ICH2M)},
166 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_0, TCO_ICH3 )}, 168 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_0, TCO_ICH3)},
167 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_12, TCO_ICH3M )}, 169 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_12, TCO_ICH3M)},
168 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_0, TCO_ICH4 )}, 170 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_0, TCO_ICH4)},
169 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_12, TCO_ICH4M )}, 171 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_12, TCO_ICH4M)},
170 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801E_0, TCO_CICH )}, 172 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801E_0, TCO_CICH)},
171 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801EB_0, TCO_ICH5 )}, 173 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801EB_0, TCO_ICH5)},
172 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB_1, TCO_6300ESB)}, 174 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB_1, TCO_6300ESB)},
173 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0, TCO_ICH6 )}, 175 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0, TCO_ICH6)},
174 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1, TCO_ICH6M )}, 176 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1, TCO_ICH6M)},
175 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2, TCO_ICH6W )}, 177 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2, TCO_ICH6W)},
176 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0, TCO_ICH7 )}, 178 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0, TCO_ICH7)},
177 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M )}, 179 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)},
178 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, 180 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)},
179 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8 )}, 181 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)},
180 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1, TCO_ICH8ME )}, 182 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1, TCO_ICH8ME)},
181 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH )}, 183 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)},
182 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO )}, 184 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)},
183 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4, TCO_ICH8M )}, 185 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4, TCO_ICH8M)},
184 { ITCO_PCI_DEVICE(0x2918, TCO_ICH9 )}, 186 { ITCO_PCI_DEVICE(0x2918, TCO_ICH9)},
185 { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R )}, 187 { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R)},
186 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH )}, 188 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH)},
187 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO )}, 189 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO)},
188 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)}, 190 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)},
189 { ITCO_PCI_DEVICE(0x2671, TCO_631XESB)}, 191 { ITCO_PCI_DEVICE(0x2671, TCO_631XESB)},
190 { ITCO_PCI_DEVICE(0x2672, TCO_631XESB)}, 192 { ITCO_PCI_DEVICE(0x2672, TCO_631XESB)},
@@ -203,13 +205,15 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
203 { ITCO_PCI_DEVICE(0x267f, TCO_631XESB)}, 205 { ITCO_PCI_DEVICE(0x267f, TCO_631XESB)},
204 { 0, }, /* End of list */ 206 { 0, }, /* End of list */
205}; 207};
206MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); 208MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
207 209
208/* Address definitions for the TCO */ 210/* Address definitions for the TCO */
209#define TCOBASE iTCO_wdt_private.ACPIBASE + 0x60 /* TCO base address */ 211/* TCO base address */
210#define SMI_EN iTCO_wdt_private.ACPIBASE + 0x30 /* SMI Control and Enable Register */ 212#define TCOBASE iTCO_wdt_private.ACPIBASE + 0x60
213/* SMI Control and Enable Register */
214#define SMI_EN iTCO_wdt_private.ACPIBASE + 0x30
211 215
212#define TCO_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ 216#define TCO_RLD TCOBASE + 0x00 /* TCO Timer Reload and Curr. Value */
213#define TCOv1_TMR TCOBASE + 0x01 /* TCOv1 Timer Initial Value */ 217#define TCOv1_TMR TCOBASE + 0x01 /* TCOv1 Timer Initial Value */
214#define TCO_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ 218#define TCO_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */
215#define TCO_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ 219#define TCO_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */
@@ -222,15 +226,21 @@ MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl);
222/* internal variables */ 226/* internal variables */
223static unsigned long is_active; 227static unsigned long is_active;
224static char expect_release; 228static char expect_release;
225static struct { /* this is private data for the iTCO_wdt device */ 229static struct { /* this is private data for the iTCO_wdt device */
226 unsigned int iTCO_version; /* TCO version/generation */ 230 /* TCO version/generation */
227 unsigned long ACPIBASE; /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ 231 unsigned int iTCO_version;
228 unsigned long __iomem *gcs; /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2) */ 232 /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
229 spinlock_t io_lock; /* the lock for io operations */ 233 unsigned long ACPIBASE;
230 struct pci_dev *pdev; /* the PCI-device */ 234 /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
235 unsigned long __iomem *gcs;
236 /* the lock for io operations */
237 spinlock_t io_lock;
238 /* the PCI-device */
239 struct pci_dev *pdev;
231} iTCO_wdt_private; 240} iTCO_wdt_private;
232 241
233static struct platform_device *iTCO_wdt_platform_device; /* the watchdog platform device */ 242/* the watchdog platform device */
243static struct platform_device *iTCO_wdt_platform_device;
234 244
235/* module parameters */ 245/* module parameters */
236#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ 246#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
@@ -240,22 +250,9 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39 (TCO
240 250
241static int nowayout = WATCHDOG_NOWAYOUT; 251static int nowayout = WATCHDOG_NOWAYOUT;
242module_param(nowayout, int, 0); 252module_param(nowayout, int, 0);
243MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 253MODULE_PARM_DESC(nowayout,
244 254 "Watchdog cannot be stopped once started (default="
245/* iTCO Vendor Specific Support hooks */ 255 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
246#ifdef CONFIG_ITCO_VENDOR_SUPPORT
247extern void iTCO_vendor_pre_start(unsigned long, unsigned int);
248extern void iTCO_vendor_pre_stop(unsigned long);
249extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int);
250extern void iTCO_vendor_pre_set_heartbeat(unsigned int);
251extern int iTCO_vendor_check_noreboot_on(void);
252#else
253#define iTCO_vendor_pre_start(acpibase, heartbeat) {}
254#define iTCO_vendor_pre_stop(acpibase) {}
255#define iTCO_vendor_pre_keepalive(acpibase,heartbeat) {}
256#define iTCO_vendor_pre_set_heartbeat(heartbeat) {}
257#define iTCO_vendor_check_noreboot_on() 1 /* 1=check noreboot; 0=don't check */
258#endif
259 256
260/* 257/*
261 * Some TCO specific functions 258 * Some TCO specific functions
@@ -369,11 +366,10 @@ static int iTCO_wdt_keepalive(void)
369 iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat); 366 iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
370 367
371 /* Reload the timer by writing to the TCO Timer Counter register */ 368 /* Reload the timer by writing to the TCO Timer Counter register */
372 if (iTCO_wdt_private.iTCO_version == 2) { 369 if (iTCO_wdt_private.iTCO_version == 2)
373 outw(0x01, TCO_RLD); 370 outw(0x01, TCO_RLD);
374 } else if (iTCO_wdt_private.iTCO_version == 1) { 371 else if (iTCO_wdt_private.iTCO_version == 1)
375 outb(0x01, TCO_RLD); 372 outb(0x01, TCO_RLD);
376 }
377 373
378 spin_unlock(&iTCO_wdt_private.io_lock); 374 spin_unlock(&iTCO_wdt_private.io_lock);
379 return 0; 375 return 0;
@@ -425,7 +421,7 @@ static int iTCO_wdt_set_heartbeat(int t)
425 return 0; 421 return 0;
426} 422}
427 423
428static int iTCO_wdt_get_timeleft (int *time_left) 424static int iTCO_wdt_get_timeleft(int *time_left)
429{ 425{
430 unsigned int val16; 426 unsigned int val16;
431 unsigned char val8; 427 unsigned char val8;
@@ -454,7 +450,7 @@ static int iTCO_wdt_get_timeleft (int *time_left)
454 * /dev/watchdog handling 450 * /dev/watchdog handling
455 */ 451 */
456 452
457static int iTCO_wdt_open (struct inode *inode, struct file *file) 453static int iTCO_wdt_open(struct inode *inode, struct file *file)
458{ 454{
459 /* /dev/watchdog can only be opened once */ 455 /* /dev/watchdog can only be opened once */
460 if (test_and_set_bit(0, &is_active)) 456 if (test_and_set_bit(0, &is_active))
@@ -468,7 +464,7 @@ static int iTCO_wdt_open (struct inode *inode, struct file *file)
468 return nonseekable_open(inode, file); 464 return nonseekable_open(inode, file);
469} 465}
470 466
471static int iTCO_wdt_release (struct inode *inode, struct file *file) 467static int iTCO_wdt_release(struct inode *inode, struct file *file)
472{ 468{
473 /* 469 /*
474 * Shut off the timer. 470 * Shut off the timer.
@@ -476,7 +472,8 @@ static int iTCO_wdt_release (struct inode *inode, struct file *file)
476 if (expect_release == 42) { 472 if (expect_release == 42) {
477 iTCO_wdt_stop(); 473 iTCO_wdt_stop();
478 } else { 474 } else {
479 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 475 printk(KERN_CRIT PFX
476 "Unexpected close, not stopping watchdog!\n");
480 iTCO_wdt_keepalive(); 477 iTCO_wdt_keepalive();
481 } 478 }
482 clear_bit(0, &is_active); 479 clear_bit(0, &is_active);
@@ -484,22 +481,23 @@ static int iTCO_wdt_release (struct inode *inode, struct file *file)
484 return 0; 481 return 0;
485} 482}
486 483
487static ssize_t iTCO_wdt_write (struct file *file, const char __user *data, 484static ssize_t iTCO_wdt_write(struct file *file, const char __user *data,
488 size_t len, loff_t * ppos) 485 size_t len, loff_t *ppos)
489{ 486{
490 /* See if we got the magic character 'V' and reload the timer */ 487 /* See if we got the magic character 'V' and reload the timer */
491 if (len) { 488 if (len) {
492 if (!nowayout) { 489 if (!nowayout) {
493 size_t i; 490 size_t i;
494 491
495 /* note: just in case someone wrote the magic character 492 /* note: just in case someone wrote the magic
496 * five months ago... */ 493 character five months ago... */
497 expect_release = 0; 494 expect_release = 0;
498 495
499 /* scan to see whether or not we got the magic character */ 496 /* scan to see whether or not we got the
497 magic character */
500 for (i = 0; i != len; i++) { 498 for (i = 0; i != len; i++) {
501 char c; 499 char c;
502 if (get_user(c, data+i)) 500 if (get_user(c, data + i))
503 return -EFAULT; 501 return -EFAULT;
504 if (c == 'V') 502 if (c == 'V')
505 expect_release = 42; 503 expect_release = 42;
@@ -512,8 +510,8 @@ static ssize_t iTCO_wdt_write (struct file *file, const char __user *data,
512 return len; 510 return len;
513} 511}
514 512
515static int iTCO_wdt_ioctl (struct inode *inode, struct file *file, 513static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd,
516 unsigned int cmd, unsigned long arg) 514 unsigned long arg)
517{ 515{
518 int new_options, retval = -EINVAL; 516 int new_options, retval = -EINVAL;
519 int new_heartbeat; 517 int new_heartbeat;
@@ -528,64 +526,52 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file,
528 }; 526 };
529 527
530 switch (cmd) { 528 switch (cmd) {
531 case WDIOC_GETSUPPORT: 529 case WDIOC_GETSUPPORT:
532 return copy_to_user(argp, &ident, 530 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
533 sizeof (ident)) ? -EFAULT : 0; 531 case WDIOC_GETSTATUS:
534 532 case WDIOC_GETBOOTSTATUS:
535 case WDIOC_GETSTATUS: 533 return put_user(0, p);
536 case WDIOC_GETBOOTSTATUS: 534
537 return put_user(0, p); 535 case WDIOC_SETOPTIONS:
538 536 {
539 case WDIOC_KEEPALIVE: 537 if (get_user(new_options, p))
540 iTCO_wdt_keepalive(); 538 return -EFAULT;
541 return 0; 539
542 540 if (new_options & WDIOS_DISABLECARD) {
543 case WDIOC_SETOPTIONS: 541 iTCO_wdt_stop();
544 { 542 retval = 0;
545 if (get_user(new_options, p))
546 return -EFAULT;
547
548 if (new_options & WDIOS_DISABLECARD) {
549 iTCO_wdt_stop();
550 retval = 0;
551 }
552
553 if (new_options & WDIOS_ENABLECARD) {
554 iTCO_wdt_keepalive();
555 iTCO_wdt_start();
556 retval = 0;
557 }
558
559 return retval;
560 } 543 }
561 544 if (new_options & WDIOS_ENABLECARD) {
562 case WDIOC_SETTIMEOUT:
563 {
564 if (get_user(new_heartbeat, p))
565 return -EFAULT;
566
567 if (iTCO_wdt_set_heartbeat(new_heartbeat))
568 return -EINVAL;
569
570 iTCO_wdt_keepalive(); 545 iTCO_wdt_keepalive();
571 /* Fall */ 546 iTCO_wdt_start();
572 } 547 retval = 0;
573
574 case WDIOC_GETTIMEOUT:
575 return put_user(heartbeat, p);
576
577 case WDIOC_GETTIMELEFT:
578 {
579 int time_left;
580
581 if (iTCO_wdt_get_timeleft(&time_left))
582 return -EINVAL;
583
584 return put_user(time_left, p);
585 } 548 }
549 return retval;
550 }
551 case WDIOC_KEEPALIVE:
552 iTCO_wdt_keepalive();
553 return 0;
586 554
587 default: 555 case WDIOC_SETTIMEOUT:
588 return -ENOTTY; 556 {
557 if (get_user(new_heartbeat, p))
558 return -EFAULT;
559 if (iTCO_wdt_set_heartbeat(new_heartbeat))
560 return -EINVAL;
561 iTCO_wdt_keepalive();
562 /* Fall */
563 }
564 case WDIOC_GETTIMEOUT:
565 return put_user(heartbeat, p);
566 case WDIOC_GETTIMELEFT:
567 {
568 int time_left;
569 if (iTCO_wdt_get_timeleft(&time_left))
570 return -EINVAL;
571 return put_user(time_left, p);
572 }
573 default:
574 return -ENOTTY;
589 } 575 }
590} 576}
591 577
@@ -594,12 +580,12 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file,
594 */ 580 */
595 581
596static const struct file_operations iTCO_wdt_fops = { 582static const struct file_operations iTCO_wdt_fops = {
597 .owner = THIS_MODULE, 583 .owner = THIS_MODULE,
598 .llseek = no_llseek, 584 .llseek = no_llseek,
599 .write = iTCO_wdt_write, 585 .write = iTCO_wdt_write,
600 .ioctl = iTCO_wdt_ioctl, 586 .unlocked_ioctl = iTCO_wdt_ioctl,
601 .open = iTCO_wdt_open, 587 .open = iTCO_wdt_open,
602 .release = iTCO_wdt_release, 588 .release = iTCO_wdt_release,
603}; 589};
604 590
605static struct miscdevice iTCO_wdt_miscdev = { 591static struct miscdevice iTCO_wdt_miscdev = {
@@ -612,7 +598,8 @@ static struct miscdevice iTCO_wdt_miscdev = {
612 * Init & exit routines 598 * Init & exit routines
613 */ 599 */
614 600
615static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev) 601static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
602 const struct pci_device_id *ent, struct platform_device *dev)
616{ 603{
617 int ret; 604 int ret;
618 u32 base_address; 605 u32 base_address;
@@ -632,17 +619,19 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device
632 pci_dev_put(pdev); 619 pci_dev_put(pdev);
633 return -ENODEV; 620 return -ENODEV;
634 } 621 }
635 iTCO_wdt_private.iTCO_version = iTCO_chipset_info[ent->driver_data].iTCO_version; 622 iTCO_wdt_private.iTCO_version =
623 iTCO_chipset_info[ent->driver_data].iTCO_version;
636 iTCO_wdt_private.ACPIBASE = base_address; 624 iTCO_wdt_private.ACPIBASE = base_address;
637 iTCO_wdt_private.pdev = pdev; 625 iTCO_wdt_private.pdev = pdev;
638 626
639 /* Get the Memory-Mapped GCS register, we need it for the NO_REBOOT flag (TCO v2) */ 627 /* Get the Memory-Mapped GCS register, we need it for the
640 /* To get access to it you have to read RCBA from PCI Config space 0xf0 628 NO_REBOOT flag (TCO v2). To get access to it you have to
641 and use it as base. GCS = RCBA + ICH6_GCS(0x3410). */ 629 read RCBA from PCI Config space 0xf0 and use it as base.
630 GCS = RCBA + ICH6_GCS(0x3410). */
642 if (iTCO_wdt_private.iTCO_version == 2) { 631 if (iTCO_wdt_private.iTCO_version == 2) {
643 pci_read_config_dword(pdev, 0xf0, &base_address); 632 pci_read_config_dword(pdev, 0xf0, &base_address);
644 RCBA = base_address & 0xffffc000; 633 RCBA = base_address & 0xffffc000;
645 iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410),4); 634 iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4);
646 } 635 }
647 636
648 /* Check chipset's NO_REBOOT bit */ 637 /* Check chipset's NO_REBOOT bit */
@@ -657,8 +646,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device
657 646
658 /* Set the TCO_EN bit in SMI_EN register */ 647 /* Set the TCO_EN bit in SMI_EN register */
659 if (!request_region(SMI_EN, 4, "iTCO_wdt")) { 648 if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
660 printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n", 649 printk(KERN_ERR PFX
661 SMI_EN ); 650 "I/O address 0x%04lx already in use\n", SMI_EN);
662 ret = -EIO; 651 ret = -EIO;
663 goto out; 652 goto out;
664 } 653 }
@@ -667,18 +656,20 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device
667 outl(val32, SMI_EN); 656 outl(val32, SMI_EN);
668 release_region(SMI_EN, 4); 657 release_region(SMI_EN, 4);
669 658
670 /* The TCO I/O registers reside in a 32-byte range pointed to by the TCOBASE value */ 659 /* The TCO I/O registers reside in a 32-byte range pointed to
671 if (!request_region (TCOBASE, 0x20, "iTCO_wdt")) { 660 by the TCOBASE value */
672 printk (KERN_ERR PFX "I/O address 0x%04lx already in use\n", 661 if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
662 printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n",
673 TCOBASE); 663 TCOBASE);
674 ret = -EIO; 664 ret = -EIO;
675 goto out; 665 goto out;
676 } 666 }
677 667
678 printk(KERN_INFO PFX "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n", 668 printk(KERN_INFO PFX
679 iTCO_chipset_info[ent->driver_data].name, 669 "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
680 iTCO_chipset_info[ent->driver_data].iTCO_version, 670 iTCO_chipset_info[ent->driver_data].name,
681 TCOBASE); 671 iTCO_chipset_info[ent->driver_data].iTCO_version,
672 TCOBASE);
682 673
683 /* Clear out the (probably old) status */ 674 /* Clear out the (probably old) status */
684 outb(0, TCO1_STS); 675 outb(0, TCO1_STS);
@@ -687,27 +678,29 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device
687 /* Make sure the watchdog is not running */ 678 /* Make sure the watchdog is not running */
688 iTCO_wdt_stop(); 679 iTCO_wdt_stop();
689 680
690 /* Check that the heartbeat value is within it's range ; if not reset to the default */ 681 /* Check that the heartbeat value is within it's range;
682 if not reset to the default */
691 if (iTCO_wdt_set_heartbeat(heartbeat)) { 683 if (iTCO_wdt_set_heartbeat(heartbeat)) {
692 iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT); 684 iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
693 printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39 (TCO v1) or 613 (TCO v2), using %d\n", 685 printk(KERN_INFO PFX "heartbeat value must be 2 < heartbeat < 39 (TCO v1) or 613 (TCO v2), using %d\n",
694 heartbeat); 686 heartbeat);
695 } 687 }
696 688
697 ret = misc_register(&iTCO_wdt_miscdev); 689 ret = misc_register(&iTCO_wdt_miscdev);
698 if (ret != 0) { 690 if (ret != 0) {
699 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 691 printk(KERN_ERR PFX
700 WATCHDOG_MINOR, ret); 692 "cannot register miscdev on minor=%d (err=%d)\n",
693 WATCHDOG_MINOR, ret);
701 goto unreg_region; 694 goto unreg_region;
702 } 695 }
703 696
704 printk (KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", 697 printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
705 heartbeat, nowayout); 698 heartbeat, nowayout);
706 699
707 return 0; 700 return 0;
708 701
709unreg_region: 702unreg_region:
710 release_region (TCOBASE, 0x20); 703 release_region(TCOBASE, 0x20);
711out: 704out:
712 if (iTCO_wdt_private.iTCO_version == 2) 705 if (iTCO_wdt_private.iTCO_version == 2)
713 iounmap(iTCO_wdt_private.gcs); 706 iounmap(iTCO_wdt_private.gcs);
@@ -796,7 +789,8 @@ static int __init iTCO_wdt_init_module(void)
796 if (err) 789 if (err)
797 return err; 790 return err;
798 791
799 iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); 792 iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME,
793 -1, NULL, 0);
800 if (IS_ERR(iTCO_wdt_platform_device)) { 794 if (IS_ERR(iTCO_wdt_platform_device)) {
801 err = PTR_ERR(iTCO_wdt_platform_device); 795 err = PTR_ERR(iTCO_wdt_platform_device);
802 goto unreg_platform_driver; 796 goto unreg_platform_driver;
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
index 4b89f401691a..05a28106e8eb 100644
--- a/drivers/watchdog/ib700wdt.c
+++ b/drivers/watchdog/ib700wdt.c
@@ -41,9 +41,9 @@
41#include <linux/spinlock.h> 41#include <linux/spinlock.h>
42#include <linux/moduleparam.h> 42#include <linux/moduleparam.h>
43#include <linux/platform_device.h> 43#include <linux/platform_device.h>
44#include <linux/io.h>
45#include <linux/uaccess.h>
44 46
45#include <asm/io.h>
46#include <asm/uaccess.h>
47#include <asm/system.h> 47#include <asm/system.h>
48 48
49static struct platform_device *ibwdt_platform_device; 49static struct platform_device *ibwdt_platform_device;
@@ -120,15 +120,16 @@ static int wd_margin = WD_TIMO;
120 120
121static int nowayout = WATCHDOG_NOWAYOUT; 121static int nowayout = WATCHDOG_NOWAYOUT;
122module_param(nowayout, int, 0); 122module_param(nowayout, int, 0);
123MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 123MODULE_PARM_DESC(nowayout,
124 "Watchdog cannot be stopped once started (default="
125 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
124 126
125 127
126/* 128/*
127 * Watchdog Operations 129 * Watchdog Operations
128 */ 130 */
129 131
130static void 132static void ibwdt_ping(void)
131ibwdt_ping(void)
132{ 133{
133 spin_lock(&ibwdt_lock); 134 spin_lock(&ibwdt_lock);
134 135
@@ -138,16 +139,14 @@ ibwdt_ping(void)
138 spin_unlock(&ibwdt_lock); 139 spin_unlock(&ibwdt_lock);
139} 140}
140 141
141static void 142static void ibwdt_disable(void)
142ibwdt_disable(void)
143{ 143{
144 spin_lock(&ibwdt_lock); 144 spin_lock(&ibwdt_lock);
145 outb_p(0, WDT_STOP); 145 outb_p(0, WDT_STOP);
146 spin_unlock(&ibwdt_lock); 146 spin_unlock(&ibwdt_lock);
147} 147}
148 148
149static int 149static int ibwdt_set_heartbeat(int t)
150ibwdt_set_heartbeat(int t)
151{ 150{
152 int i; 151 int i;
153 152
@@ -165,8 +164,8 @@ ibwdt_set_heartbeat(int t)
165 * /dev/watchdog handling 164 * /dev/watchdog handling
166 */ 165 */
167 166
168static ssize_t 167static ssize_t ibwdt_write(struct file *file, const char __user *buf,
169ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 168 size_t count, loff_t *ppos)
170{ 169{
171 if (count) { 170 if (count) {
172 if (!nowayout) { 171 if (!nowayout) {
@@ -188,77 +187,71 @@ ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppo
188 return count; 187 return count;
189} 188}
190 189
191static int 190static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
192ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
193 unsigned long arg)
194{ 191{
195 int new_margin; 192 int new_margin;
196 void __user *argp = (void __user *)arg; 193 void __user *argp = (void __user *)arg;
197 int __user *p = argp; 194 int __user *p = argp;
198 195
199 static struct watchdog_info ident = { 196 static struct watchdog_info ident = {
200 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 197 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
198 | WDIOF_MAGICCLOSE,
201 .firmware_version = 1, 199 .firmware_version = 1,
202 .identity = "IB700 WDT", 200 .identity = "IB700 WDT",
203 }; 201 };
204 202
205 switch (cmd) { 203 switch (cmd) {
206 case WDIOC_GETSUPPORT: 204 case WDIOC_GETSUPPORT:
207 if (copy_to_user(argp, &ident, sizeof(ident))) 205 if (copy_to_user(argp, &ident, sizeof(ident)))
208 return -EFAULT; 206 return -EFAULT;
209 break; 207 break;
210 208
211 case WDIOC_GETSTATUS: 209 case WDIOC_GETSTATUS:
212 case WDIOC_GETBOOTSTATUS: 210 case WDIOC_GETBOOTSTATUS:
213 return put_user(0, p); 211 return put_user(0, p);
214
215 case WDIOC_KEEPALIVE:
216 ibwdt_ping();
217 break;
218
219 case WDIOC_SETTIMEOUT:
220 if (get_user(new_margin, p))
221 return -EFAULT;
222 if (ibwdt_set_heartbeat(new_margin))
223 return -EINVAL;
224 ibwdt_ping();
225 /* Fall */
226
227 case WDIOC_GETTIMEOUT:
228 return put_user(wd_times[wd_margin], p);
229 212
230 case WDIOC_SETOPTIONS: 213 case WDIOC_SETOPTIONS:
231 { 214 {
232 int options, retval = -EINVAL; 215 int options, retval = -EINVAL;
233 216
234 if (get_user(options, p)) 217 if (get_user(options, p))
235 return -EFAULT; 218 return -EFAULT;
236 219
237 if (options & WDIOS_DISABLECARD) { 220 if (options & WDIOS_DISABLECARD) {
238 ibwdt_disable(); 221 ibwdt_disable();
239 retval = 0; 222 retval = 0;
240 } 223 }
224 if (options & WDIOS_ENABLECARD) {
225 ibwdt_ping();
226 retval = 0;
227 }
228 return retval;
229 }
230 case WDIOC_KEEPALIVE:
231 ibwdt_ping();
232 break;
241 233
242 if (options & WDIOS_ENABLECARD) { 234 case WDIOC_SETTIMEOUT:
243 ibwdt_ping(); 235 if (get_user(new_margin, p))
244 retval = 0; 236 return -EFAULT;
245 } 237 if (ibwdt_set_heartbeat(new_margin))
238 return -EINVAL;
239 ibwdt_ping();
240 /* Fall */
246 241
247 return retval; 242 case WDIOC_GETTIMEOUT:
248 } 243 return put_user(wd_times[wd_margin], p);
249 244
250 default: 245 default:
251 return -ENOTTY; 246 return -ENOTTY;
252 } 247 }
253 return 0; 248 return 0;
254} 249}
255 250
256static int 251static int ibwdt_open(struct inode *inode, struct file *file)
257ibwdt_open(struct inode *inode, struct file *file)
258{ 252{
259 if (test_and_set_bit(0, &ibwdt_is_open)) { 253 if (test_and_set_bit(0, &ibwdt_is_open))
260 return -EBUSY; 254 return -EBUSY;
261 }
262 if (nowayout) 255 if (nowayout)
263 __module_get(THIS_MODULE); 256 __module_get(THIS_MODULE);
264 257
@@ -267,13 +260,13 @@ ibwdt_open(struct inode *inode, struct file *file)
267 return nonseekable_open(inode, file); 260 return nonseekable_open(inode, file);
268} 261}
269 262
270static int 263static int ibwdt_close(struct inode *inode, struct file *file)
271ibwdt_close(struct inode *inode, struct file *file)
272{ 264{
273 if (expect_close == 42) { 265 if (expect_close == 42) {
274 ibwdt_disable(); 266 ibwdt_disable();
275 } else { 267 } else {
276 printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); 268 printk(KERN_CRIT PFX
269 "WDT device closed unexpectedly. WDT will not stop!\n");
277 ibwdt_ping(); 270 ibwdt_ping();
278 } 271 }
279 clear_bit(0, &ibwdt_is_open); 272 clear_bit(0, &ibwdt_is_open);
@@ -289,7 +282,7 @@ static const struct file_operations ibwdt_fops = {
289 .owner = THIS_MODULE, 282 .owner = THIS_MODULE,
290 .llseek = no_llseek, 283 .llseek = no_llseek,
291 .write = ibwdt_write, 284 .write = ibwdt_write,
292 .ioctl = ibwdt_ioctl, 285 .unlocked_ioctl = ibwdt_ioctl,
293 .open = ibwdt_open, 286 .open = ibwdt_open,
294 .release = ibwdt_close, 287 .release = ibwdt_close,
295}; 288};
@@ -310,21 +303,23 @@ static int __devinit ibwdt_probe(struct platform_device *dev)
310 303
311#if WDT_START != WDT_STOP 304#if WDT_START != WDT_STOP
312 if (!request_region(WDT_STOP, 1, "IB700 WDT")) { 305 if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
313 printk (KERN_ERR PFX "STOP method I/O %X is not available.\n", WDT_STOP); 306 printk(KERN_ERR PFX "STOP method I/O %X is not available.\n",
307 WDT_STOP);
314 res = -EIO; 308 res = -EIO;
315 goto out_nostopreg; 309 goto out_nostopreg;
316 } 310 }
317#endif 311#endif
318 312
319 if (!request_region(WDT_START, 1, "IB700 WDT")) { 313 if (!request_region(WDT_START, 1, "IB700 WDT")) {
320 printk (KERN_ERR PFX "START method I/O %X is not available.\n", WDT_START); 314 printk(KERN_ERR PFX "START method I/O %X is not available.\n",
315 WDT_START);
321 res = -EIO; 316 res = -EIO;
322 goto out_nostartreg; 317 goto out_nostartreg;
323 } 318 }
324 319
325 res = misc_register(&ibwdt_miscdev); 320 res = misc_register(&ibwdt_miscdev);
326 if (res) { 321 if (res) {
327 printk (KERN_ERR PFX "failed to register misc device\n"); 322 printk(KERN_ERR PFX "failed to register misc device\n");
328 goto out_nomisc; 323 goto out_nomisc;
329 } 324 }
330 return 0; 325 return 0;
@@ -342,9 +337,9 @@ out_nostopreg:
342static int __devexit ibwdt_remove(struct platform_device *dev) 337static int __devexit ibwdt_remove(struct platform_device *dev)
343{ 338{
344 misc_deregister(&ibwdt_miscdev); 339 misc_deregister(&ibwdt_miscdev);
345 release_region(WDT_START,1); 340 release_region(WDT_START, 1);
346#if WDT_START != WDT_STOP 341#if WDT_START != WDT_STOP
347 release_region(WDT_STOP,1); 342 release_region(WDT_STOP, 1);
348#endif 343#endif
349 return 0; 344 return 0;
350} 345}
@@ -369,13 +364,15 @@ static int __init ibwdt_init(void)
369{ 364{
370 int err; 365 int err;
371 366
372 printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n"); 367 printk(KERN_INFO PFX
368 "WDT driver for IB700 single board computer initialising.\n");
373 369
374 err = platform_driver_register(&ibwdt_driver); 370 err = platform_driver_register(&ibwdt_driver);
375 if (err) 371 if (err)
376 return err; 372 return err;
377 373
378 ibwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); 374 ibwdt_platform_device = platform_device_register_simple(DRV_NAME,
375 -1, NULL, 0);
379 if (IS_ERR(ibwdt_platform_device)) { 376 if (IS_ERR(ibwdt_platform_device)) {
380 err = PTR_ERR(ibwdt_platform_device); 377 err = PTR_ERR(ibwdt_platform_device);
381 goto unreg_platform_driver; 378 goto unreg_platform_driver;
diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c
index 94155f6136c2..b82405cfb4cd 100644
--- a/drivers/watchdog/ibmasr.c
+++ b/drivers/watchdog/ibmasr.c
@@ -19,9 +19,8 @@
19#include <linux/miscdevice.h> 19#include <linux/miscdevice.h>
20#include <linux/watchdog.h> 20#include <linux/watchdog.h>
21#include <linux/dmi.h> 21#include <linux/dmi.h>
22 22#include <linux/io.h>
23#include <asm/io.h> 23#include <linux/uaccess.h>
24#include <asm/uaccess.h>
25 24
26 25
27enum { 26enum {
@@ -70,10 +69,13 @@ static char asr_expect_close;
70static unsigned int asr_type, asr_base, asr_length; 69static unsigned int asr_type, asr_base, asr_length;
71static unsigned int asr_read_addr, asr_write_addr; 70static unsigned int asr_read_addr, asr_write_addr;
72static unsigned char asr_toggle_mask, asr_disable_mask; 71static unsigned char asr_toggle_mask, asr_disable_mask;
72static spinlock_t asr_lock;
73 73
74static void asr_toggle(void) 74static void __asr_toggle(void)
75{ 75{
76 unsigned char reg = inb(asr_read_addr); 76 unsigned char reg;
77
78 reg = inb(asr_read_addr);
77 79
78 outb(reg & ~asr_toggle_mask, asr_write_addr); 80 outb(reg & ~asr_toggle_mask, asr_write_addr);
79 reg = inb(asr_read_addr); 81 reg = inb(asr_read_addr);
@@ -83,12 +85,21 @@ static void asr_toggle(void)
83 85
84 outb(reg & ~asr_toggle_mask, asr_write_addr); 86 outb(reg & ~asr_toggle_mask, asr_write_addr);
85 reg = inb(asr_read_addr); 87 reg = inb(asr_read_addr);
88 spin_unlock(&asr_lock);
89}
90
91static void asr_toggle(void)
92{
93 spin_lock(&asr_lock);
94 __asr_toggle();
95 spin_unlock(&asr_lock);
86} 96}
87 97
88static void asr_enable(void) 98static void asr_enable(void)
89{ 99{
90 unsigned char reg; 100 unsigned char reg;
91 101
102 spin_lock(&asr_lock);
92 if (asr_type == ASMTYPE_TOPAZ) { 103 if (asr_type == ASMTYPE_TOPAZ) {
93 /* asr_write_addr == asr_read_addr */ 104 /* asr_write_addr == asr_read_addr */
94 reg = inb(asr_read_addr); 105 reg = inb(asr_read_addr);
@@ -99,17 +110,21 @@ static void asr_enable(void)
99 * First make sure the hardware timer is reset by toggling 110 * First make sure the hardware timer is reset by toggling
100 * ASR hardware timer line. 111 * ASR hardware timer line.
101 */ 112 */
102 asr_toggle(); 113 __asr_toggle();
103 114
104 reg = inb(asr_read_addr); 115 reg = inb(asr_read_addr);
105 outb(reg & ~asr_disable_mask, asr_write_addr); 116 outb(reg & ~asr_disable_mask, asr_write_addr);
106 } 117 }
107 reg = inb(asr_read_addr); 118 reg = inb(asr_read_addr);
119 spin_unlock(&asr_lock);
108} 120}
109 121
110static void asr_disable(void) 122static void asr_disable(void)
111{ 123{
112 unsigned char reg = inb(asr_read_addr); 124 unsigned char reg;
125
126 spin_lock(&asr_lock);
127 reg = inb(asr_read_addr);
113 128
114 if (asr_type == ASMTYPE_TOPAZ) 129 if (asr_type == ASMTYPE_TOPAZ)
115 /* asr_write_addr == asr_read_addr */ 130 /* asr_write_addr == asr_read_addr */
@@ -122,6 +137,7 @@ static void asr_disable(void)
122 outb(reg | asr_disable_mask, asr_write_addr); 137 outb(reg | asr_disable_mask, asr_write_addr);
123 } 138 }
124 reg = inb(asr_read_addr); 139 reg = inb(asr_read_addr);
140 spin_unlock(&asr_lock);
125} 141}
126 142
127static int __init asr_get_base_address(void) 143static int __init asr_get_base_address(void)
@@ -133,7 +149,8 @@ static int __init asr_get_base_address(void)
133 149
134 switch (asr_type) { 150 switch (asr_type) {
135 case ASMTYPE_TOPAZ: 151 case ASMTYPE_TOPAZ:
136 /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */ 152 /* SELECT SuperIO CHIP FOR QUERYING
153 (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
137 outb(0x07, 0x2e); 154 outb(0x07, 0x2e);
138 outb(0x07, 0x2f); 155 outb(0x07, 0x2f);
139 156
@@ -154,14 +171,26 @@ static int __init asr_get_base_address(void)
154 171
155 case ASMTYPE_JASPER: 172 case ASMTYPE_JASPER:
156 type = "Jaspers "; 173 type = "Jaspers ";
157 174#if 0
158 /* FIXME: need to use pci_config_lock here, but it's not exported */ 175 u32 r;
176 /* Suggested fix */
177 pdev = pci_get_bus_and_slot(0, DEVFN(0x1f, 0));
178 if (pdev == NULL)
179 return -ENODEV;
180 pci_read_config_dword(pdev, 0x58, &r);
181 asr_base = r & 0xFFFE;
182 pci_dev_put(pdev);
183#else
184 /* FIXME: need to use pci_config_lock here,
185 but it's not exported */
159 186
160/* spin_lock_irqsave(&pci_config_lock, flags);*/ 187/* spin_lock_irqsave(&pci_config_lock, flags);*/
161 188
162 /* Select the SuperIO chip in the PCI I/O port register */ 189 /* Select the SuperIO chip in the PCI I/O port register */
163 outl(0x8000f858, 0xcf8); 190 outl(0x8000f858, 0xcf8);
164 191
192 /* BUS 0, Slot 1F, fnc 0, offset 58 */
193
165 /* 194 /*
166 * Read the base address for the SuperIO chip. 195 * Read the base address for the SuperIO chip.
167 * Only the lower 16 bits are valid, but the address is word 196 * Only the lower 16 bits are valid, but the address is word
@@ -170,7 +199,7 @@ static int __init asr_get_base_address(void)
170 asr_base = inl(0xcfc) & 0xfffe; 199 asr_base = inl(0xcfc) & 0xfffe;
171 200
172/* spin_unlock_irqrestore(&pci_config_lock, flags);*/ 201/* spin_unlock_irqrestore(&pci_config_lock, flags);*/
173 202#endif
174 asr_read_addr = asr_write_addr = 203 asr_read_addr = asr_write_addr =
175 asr_base + JASPER_ASR_REG_OFFSET; 204 asr_base + JASPER_ASR_REG_OFFSET;
176 asr_toggle_mask = JASPER_ASR_TOGGLE_MASK; 205 asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
@@ -241,66 +270,57 @@ static ssize_t asr_write(struct file *file, const char __user *buf,
241 return count; 270 return count;
242} 271}
243 272
244static int asr_ioctl(struct inode *inode, struct file *file, 273static long asr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
245 unsigned int cmd, unsigned long arg)
246{ 274{
247 static const struct watchdog_info ident = { 275 static const struct watchdog_info ident = {
248 .options = WDIOF_KEEPALIVEPING | 276 .options = WDIOF_KEEPALIVEPING |
249 WDIOF_MAGICCLOSE, 277 WDIOF_MAGICCLOSE,
250 .identity = "IBM ASR" 278 .identity = "IBM ASR",
251 }; 279 };
252 void __user *argp = (void __user *)arg; 280 void __user *argp = (void __user *)arg;
253 int __user *p = argp; 281 int __user *p = argp;
254 int heartbeat; 282 int heartbeat;
255 283
256 switch (cmd) { 284 switch (cmd) {
257 case WDIOC_GETSUPPORT: 285 case WDIOC_GETSUPPORT:
258 return copy_to_user(argp, &ident, sizeof(ident)) ? 286 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
259 -EFAULT : 0; 287 case WDIOC_GETSTATUS:
260 288 case WDIOC_GETBOOTSTATUS:
261 case WDIOC_GETSTATUS: 289 return put_user(0, p);
262 case WDIOC_GETBOOTSTATUS: 290 case WDIOC_SETOPTIONS:
263 return put_user(0, p); 291 {
264 292 int new_options, retval = -EINVAL;
265 case WDIOC_KEEPALIVE: 293 if (get_user(new_options, p))
294 return -EFAULT;
295 if (new_options & WDIOS_DISABLECARD) {
296 asr_disable();
297 retval = 0;
298 }
299 if (new_options & WDIOS_ENABLECARD) {
300 asr_enable();
266 asr_toggle(); 301 asr_toggle();
267 return 0; 302 retval = 0;
268
269 /*
270 * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
271 * and WDIOC_GETTIMEOUT always returns 256.
272 */
273 case WDIOC_GETTIMEOUT:
274 heartbeat = 256;
275 return put_user(heartbeat, p);
276
277 case WDIOC_SETOPTIONS: {
278 int new_options, retval = -EINVAL;
279
280 if (get_user(new_options, p))
281 return -EFAULT;
282
283 if (new_options & WDIOS_DISABLECARD) {
284 asr_disable();
285 retval = 0;
286 }
287
288 if (new_options & WDIOS_ENABLECARD) {
289 asr_enable();
290 asr_toggle();
291 retval = 0;
292 }
293
294 return retval;
295 } 303 }
304 return retval;
305 }
306 case WDIOC_KEEPALIVE:
307 asr_toggle();
308 return 0;
309 /*
310 * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
311 * and WDIOC_GETTIMEOUT always returns 256.
312 */
313 case WDIOC_GETTIMEOUT:
314 heartbeat = 256;
315 return put_user(heartbeat, p);
316 default:
317 return -ENOTTY;
296 } 318 }
297
298 return -ENOTTY;
299} 319}
300 320
301static int asr_open(struct inode *inode, struct file *file) 321static int asr_open(struct inode *inode, struct file *file)
302{ 322{
303 if(test_and_set_bit(0, &asr_is_open)) 323 if (test_and_set_bit(0, &asr_is_open))
304 return -EBUSY; 324 return -EBUSY;
305 325
306 asr_toggle(); 326 asr_toggle();
@@ -314,7 +334,8 @@ static int asr_release(struct inode *inode, struct file *file)
314 if (asr_expect_close == 42) 334 if (asr_expect_close == 42)
315 asr_disable(); 335 asr_disable();
316 else { 336 else {
317 printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n"); 337 printk(KERN_CRIT PFX
338 "unexpected close, not stopping watchdog!\n");
318 asr_toggle(); 339 asr_toggle();
319 } 340 }
320 clear_bit(0, &asr_is_open); 341 clear_bit(0, &asr_is_open);
@@ -323,12 +344,12 @@ static int asr_release(struct inode *inode, struct file *file)
323} 344}
324 345
325static const struct file_operations asr_fops = { 346static const struct file_operations asr_fops = {
326 .owner = THIS_MODULE, 347 .owner = THIS_MODULE,
327 .llseek = no_llseek, 348 .llseek = no_llseek,
328 .write = asr_write, 349 .write = asr_write,
329 .ioctl = asr_ioctl, 350 .unlocked_ioctl = asr_ioctl,
330 .open = asr_open, 351 .open = asr_open,
331 .release = asr_release, 352 .release = asr_release,
332}; 353};
333 354
334static struct miscdevice asr_miscdev = { 355static struct miscdevice asr_miscdev = {
@@ -367,6 +388,8 @@ static int __init ibmasr_init(void)
367 if (!asr_type) 388 if (!asr_type)
368 return -ENODEV; 389 return -ENODEV;
369 390
391 spin_lock_init(&asr_lock);
392
370 rc = asr_get_base_address(); 393 rc = asr_get_base_address();
371 if (rc) 394 if (rc)
372 return rc; 395 return rc;
@@ -395,7 +418,9 @@ module_init(ibmasr_init);
395module_exit(ibmasr_exit); 418module_exit(ibmasr_exit);
396 419
397module_param(nowayout, int, 0); 420module_param(nowayout, int, 0);
398MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 421MODULE_PARM_DESC(nowayout,
422 "Watchdog cannot be stopped once started (default="
423 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
399 424
400MODULE_DESCRIPTION("IBM Automatic Server Restart driver"); 425MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
401MODULE_AUTHOR("Andrey Panin"); 426MODULE_AUTHOR("Andrey Panin");
diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c
index 788245bdaa7f..73c9e7992feb 100644
--- a/drivers/watchdog/indydog.c
+++ b/drivers/watchdog/indydog.c
@@ -1,7 +1,8 @@
1/* 1/*
2 * IndyDog 0.3 A Hardware Watchdog Device for SGI IP22 2 * IndyDog 0.3 A Hardware Watchdog Device for SGI IP22
3 * 3 *
4 * (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>, All Rights Reserved. 4 * (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>,
5 * All Rights Reserved.
5 * 6 *
6 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
@@ -22,32 +23,42 @@
22#include <linux/notifier.h> 23#include <linux/notifier.h>
23#include <linux/reboot.h> 24#include <linux/reboot.h>
24#include <linux/init.h> 25#include <linux/init.h>
25#include <asm/uaccess.h> 26#include <linux/uaccess.h>
26#include <asm/sgi/mc.h> 27#include <asm/sgi/mc.h>
27 28
28#define PFX "indydog: " 29#define PFX "indydog: "
29static int indydog_alive; 30static unsigned long indydog_alive;
31static spinlock_t indydog_lock;
30 32
31#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ 33#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */
32 34
33static int nowayout = WATCHDOG_NOWAYOUT; 35static int nowayout = WATCHDOG_NOWAYOUT;
34module_param(nowayout, int, 0); 36module_param(nowayout, int, 0);
35MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 37MODULE_PARM_DESC(nowayout,
38 "Watchdog cannot be stopped once started (default="
39 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
36 40
37static void indydog_start(void) 41static void indydog_start(void)
38{ 42{
39 u32 mc_ctrl0 = sgimc->cpuctrl0; 43 u32 mc_ctrl0;
40 44
45 spin_lock(&indydog_lock);
46 mc_ctrl0 = sgimc->cpuctrl0;
41 mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG; 47 mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG;
42 sgimc->cpuctrl0 = mc_ctrl0; 48 sgimc->cpuctrl0 = mc_ctrl0;
49 spin_unlock(&indydog_lock);
43} 50}
44 51
45static void indydog_stop(void) 52static void indydog_stop(void)
46{ 53{
47 u32 mc_ctrl0 = sgimc->cpuctrl0; 54 u32 mc_ctrl0;
48 55
56 spin_lock(&indydog_lock);
57
58 mc_ctrl0 = sgimc->cpuctrl0;
49 mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG; 59 mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
50 sgimc->cpuctrl0 = mc_ctrl0; 60 sgimc->cpuctrl0 = mc_ctrl0;
61 spin_unlock(&indydog_lock);
51 62
52 printk(KERN_INFO PFX "Stopped watchdog timer.\n"); 63 printk(KERN_INFO PFX "Stopped watchdog timer.\n");
53} 64}
@@ -62,7 +73,7 @@ static void indydog_ping(void)
62 */ 73 */
63static int indydog_open(struct inode *inode, struct file *file) 74static int indydog_open(struct inode *inode, struct file *file)
64{ 75{
65 if (indydog_alive) 76 if (test_and_set_bit(0, &indydog_alive))
66 return -EBUSY; 77 return -EBUSY;
67 78
68 if (nowayout) 79 if (nowayout)
@@ -84,23 +95,21 @@ static int indydog_release(struct inode *inode, struct file *file)
84 * Lock it in if it's a module and we defined ...NOWAYOUT */ 95 * Lock it in if it's a module and we defined ...NOWAYOUT */
85 if (!nowayout) 96 if (!nowayout)
86 indydog_stop(); /* Turn the WDT off */ 97 indydog_stop(); /* Turn the WDT off */
87 98 clear_bit(0, &indydog_alive);
88 indydog_alive = 0;
89
90 return 0; 99 return 0;
91} 100}
92 101
93static ssize_t indydog_write(struct file *file, const char *data, size_t len, loff_t *ppos) 102static ssize_t indydog_write(struct file *file, const char *data,
103 size_t len, loff_t *ppos)
94{ 104{
95 /* Refresh the timer. */ 105 /* Refresh the timer. */
96 if (len) { 106 if (len)
97 indydog_ping(); 107 indydog_ping();
98 }
99 return len; 108 return len;
100} 109}
101 110
102static int indydog_ioctl(struct inode *inode, struct file *file, 111static long indydog_ioctl(struct file *file, unsigned int cmd,
103 unsigned int cmd, unsigned long arg) 112 unsigned long arg)
104{ 113{
105 int options, retval = -EINVAL; 114 int options, retval = -EINVAL;
106 static struct watchdog_info ident = { 115 static struct watchdog_info ident = {
@@ -111,42 +120,40 @@ static int indydog_ioctl(struct inode *inode, struct file *file,
111 }; 120 };
112 121
113 switch (cmd) { 122 switch (cmd) {
114 default: 123 case WDIOC_GETSUPPORT:
115 return -ENOTTY; 124 if (copy_to_user((struct watchdog_info *)arg,
116 case WDIOC_GETSUPPORT: 125 &ident, sizeof(ident)))
117 if (copy_to_user((struct watchdog_info *)arg, 126 return -EFAULT;
118 &ident, sizeof(ident))) 127 return 0;
119 return -EFAULT; 128 case WDIOC_GETSTATUS:
120 return 0; 129 case WDIOC_GETBOOTSTATUS:
121 case WDIOC_GETSTATUS: 130 return put_user(0, (int *)arg);
122 case WDIOC_GETBOOTSTATUS: 131 case WDIOC_SETOPTIONS:
123 return put_user(0,(int *)arg); 132 {
124 case WDIOC_KEEPALIVE: 133 if (get_user(options, (int *)arg))
125 indydog_ping(); 134 return -EFAULT;
126 return 0; 135 if (options & WDIOS_DISABLECARD) {
127 case WDIOC_GETTIMEOUT: 136 indydog_stop();
128 return put_user(WATCHDOG_TIMEOUT,(int *)arg); 137 retval = 0;
129 case WDIOC_SETOPTIONS:
130 {
131 if (get_user(options, (int *)arg))
132 return -EFAULT;
133
134 if (options & WDIOS_DISABLECARD) {
135 indydog_stop();
136 retval = 0;
137 }
138
139 if (options & WDIOS_ENABLECARD) {
140 indydog_start();
141 retval = 0;
142 }
143
144 return retval;
145 } 138 }
139 if (options & WDIOS_ENABLECARD) {
140 indydog_start();
141 retval = 0;
142 }
143 return retval;
144 }
145 case WDIOC_KEEPALIVE:
146 indydog_ping();
147 return 0;
148 case WDIOC_GETTIMEOUT:
149 return put_user(WATCHDOG_TIMEOUT, (int *)arg);
150 default:
151 return -ENOTTY;
146 } 152 }
147} 153}
148 154
149static int indydog_notify_sys(struct notifier_block *this, unsigned long code, void *unused) 155static int indydog_notify_sys(struct notifier_block *this,
156 unsigned long code, void *unused)
150{ 157{
151 if (code == SYS_DOWN || code == SYS_HALT) 158 if (code == SYS_DOWN || code == SYS_HALT)
152 indydog_stop(); /* Turn the WDT off */ 159 indydog_stop(); /* Turn the WDT off */
@@ -158,7 +165,7 @@ static const struct file_operations indydog_fops = {
158 .owner = THIS_MODULE, 165 .owner = THIS_MODULE,
159 .llseek = no_llseek, 166 .llseek = no_llseek,
160 .write = indydog_write, 167 .write = indydog_write,
161 .ioctl = indydog_ioctl, 168 .unlocked_ioctl = indydog_ioctl,
162 .open = indydog_open, 169 .open = indydog_open,
163 .release = indydog_release, 170 .release = indydog_release,
164}; 171};
@@ -180,17 +187,20 @@ static int __init watchdog_init(void)
180{ 187{
181 int ret; 188 int ret;
182 189
190 spin_lock_init(&indydog_lock);
191
183 ret = register_reboot_notifier(&indydog_notifier); 192 ret = register_reboot_notifier(&indydog_notifier);
184 if (ret) { 193 if (ret) {
185 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 194 printk(KERN_ERR PFX
186 ret); 195 "cannot register reboot notifier (err=%d)\n", ret);
187 return ret; 196 return ret;
188 } 197 }
189 198
190 ret = misc_register(&indydog_miscdev); 199 ret = misc_register(&indydog_miscdev);
191 if (ret) { 200 if (ret) {
192 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 201 printk(KERN_ERR PFX
193 WATCHDOG_MINOR, ret); 202 "cannot register miscdev on minor=%d (err=%d)\n",
203 WATCHDOG_MINOR, ret);
194 unregister_reboot_notifier(&indydog_notifier); 204 unregister_reboot_notifier(&indydog_notifier);
195 return ret; 205 return ret;
196 } 206 }
diff --git a/drivers/watchdog/iop_wdt.c b/drivers/watchdog/iop_wdt.c
index bbbd91af754d..8278b13f77c7 100644
--- a/drivers/watchdog/iop_wdt.c
+++ b/drivers/watchdog/iop_wdt.c
@@ -37,6 +37,7 @@
37static int nowayout = WATCHDOG_NOWAYOUT; 37static int nowayout = WATCHDOG_NOWAYOUT;
38static unsigned long wdt_status; 38static unsigned long wdt_status;
39static unsigned long boot_status; 39static unsigned long boot_status;
40static spinlock_t wdt_lock;
40 41
41#define WDT_IN_USE 0 42#define WDT_IN_USE 0
42#define WDT_OK_TO_CLOSE 1 43#define WDT_OK_TO_CLOSE 1
@@ -68,8 +69,10 @@ static void wdt_enable(void)
68 /* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF 69 /* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF
69 * Takes approx. 10.7s to timeout 70 * Takes approx. 10.7s to timeout
70 */ 71 */
72 spin_lock(&wdt_lock);
71 write_wdtcr(IOP_WDTCR_EN_ARM); 73 write_wdtcr(IOP_WDTCR_EN_ARM);
72 write_wdtcr(IOP_WDTCR_EN); 74 write_wdtcr(IOP_WDTCR_EN);
75 spin_unlock(&wdt_lock);
73} 76}
74 77
75/* returns 0 if the timer was successfully disabled */ 78/* returns 0 if the timer was successfully disabled */
@@ -77,9 +80,11 @@ static int wdt_disable(void)
77{ 80{
78 /* Stop Counting */ 81 /* Stop Counting */
79 if (wdt_supports_disable()) { 82 if (wdt_supports_disable()) {
83 spin_lock(&wdt_lock);
80 write_wdtcr(IOP_WDTCR_DIS_ARM); 84 write_wdtcr(IOP_WDTCR_DIS_ARM);
81 write_wdtcr(IOP_WDTCR_DIS); 85 write_wdtcr(IOP_WDTCR_DIS);
82 clear_bit(WDT_ENABLED, &wdt_status); 86 clear_bit(WDT_ENABLED, &wdt_status);
87 spin_unlock(&wdt_lock);
83 printk(KERN_INFO "WATCHDOG: Disabled\n"); 88 printk(KERN_INFO "WATCHDOG: Disabled\n");
84 return 0; 89 return 0;
85 } else 90 } else
@@ -92,16 +97,12 @@ static int iop_wdt_open(struct inode *inode, struct file *file)
92 return -EBUSY; 97 return -EBUSY;
93 98
94 clear_bit(WDT_OK_TO_CLOSE, &wdt_status); 99 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
95
96 wdt_enable(); 100 wdt_enable();
97
98 set_bit(WDT_ENABLED, &wdt_status); 101 set_bit(WDT_ENABLED, &wdt_status);
99
100 return nonseekable_open(inode, file); 102 return nonseekable_open(inode, file);
101} 103}
102 104
103static ssize_t 105static ssize_t iop_wdt_write(struct file *file, const char *data, size_t len,
104iop_wdt_write(struct file *file, const char *data, size_t len,
105 loff_t *ppos) 106 loff_t *ppos)
106{ 107{
107 if (len) { 108 if (len) {
@@ -121,46 +122,35 @@ iop_wdt_write(struct file *file, const char *data, size_t len,
121 } 122 }
122 wdt_enable(); 123 wdt_enable();
123 } 124 }
124
125 return len; 125 return len;
126} 126}
127 127
128static struct watchdog_info ident = { 128static const struct watchdog_info ident = {
129 .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, 129 .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
130 .identity = "iop watchdog", 130 .identity = "iop watchdog",
131}; 131};
132 132
133static int 133static long iop_wdt_ioctl(struct file *file,
134iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 134 unsigned int cmd, unsigned long arg)
135 unsigned long arg)
136{ 135{
137 int options; 136 int options;
138 int ret = -ENOTTY; 137 int ret = -ENOTTY;
138 int __user *argp = (int __user *)arg;
139 139
140 switch (cmd) { 140 switch (cmd) {
141 case WDIOC_GETSUPPORT: 141 case WDIOC_GETSUPPORT:
142 if (copy_to_user 142 if (copy_to_user(argp, &ident, sizeof ident))
143 ((struct watchdog_info *)arg, &ident, sizeof ident))
144 ret = -EFAULT; 143 ret = -EFAULT;
145 else 144 else
146 ret = 0; 145 ret = 0;
147 break; 146 break;
148 147
149 case WDIOC_GETSTATUS: 148 case WDIOC_GETSTATUS:
150 ret = put_user(0, (int *)arg); 149 ret = put_user(0, argp);
151 break; 150 break;
152 151
153 case WDIOC_GETBOOTSTATUS: 152 case WDIOC_GETBOOTSTATUS:
154 ret = put_user(boot_status, (int *)arg); 153 ret = put_user(boot_status, argp);
155 break;
156
157 case WDIOC_GETTIMEOUT:
158 ret = put_user(iop_watchdog_timeout(), (int *)arg);
159 break;
160
161 case WDIOC_KEEPALIVE:
162 wdt_enable();
163 ret = 0;
164 break; 154 break;
165 155
166 case WDIOC_SETOPTIONS: 156 case WDIOC_SETOPTIONS:
@@ -177,14 +167,21 @@ iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
177 } else 167 } else
178 ret = 0; 168 ret = 0;
179 } 169 }
180
181 if (options & WDIOS_ENABLECARD) { 170 if (options & WDIOS_ENABLECARD) {
182 wdt_enable(); 171 wdt_enable();
183 ret = 0; 172 ret = 0;
184 } 173 }
185 break; 174 break;
186 }
187 175
176 case WDIOC_KEEPALIVE:
177 wdt_enable();
178 ret = 0;
179 break;
180
181 case WDIOC_GETTIMEOUT:
182 ret = put_user(iop_watchdog_timeout(), argp);
183 break;
184 }
188 return ret; 185 return ret;
189} 186}
190 187
@@ -214,7 +211,7 @@ static const struct file_operations iop_wdt_fops = {
214 .owner = THIS_MODULE, 211 .owner = THIS_MODULE,
215 .llseek = no_llseek, 212 .llseek = no_llseek,
216 .write = iop_wdt_write, 213 .write = iop_wdt_write,
217 .ioctl = iop_wdt_ioctl, 214 .unlocked_ioctl = iop_wdt_ioctl,
218 .open = iop_wdt_open, 215 .open = iop_wdt_open,
219 .release = iop_wdt_release, 216 .release = iop_wdt_release,
220}; 217};
@@ -229,10 +226,8 @@ static int __init iop_wdt_init(void)
229{ 226{
230 int ret; 227 int ret;
231 228
232 ret = misc_register(&iop_wdt_miscdev); 229 spin_lock_init(&wdt_lock);
233 if (ret == 0) 230
234 printk("iop watchdog timer: timeout %lu sec\n",
235 iop_watchdog_timeout());
236 231
237 /* check if the reset was caused by the watchdog timer */ 232 /* check if the reset was caused by the watchdog timer */
238 boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0; 233 boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0;
@@ -242,6 +237,13 @@ static int __init iop_wdt_init(void)
242 */ 237 */
243 write_wdtsr(IOP13XX_WDTCR_IB_RESET); 238 write_wdtsr(IOP13XX_WDTCR_IB_RESET);
244 239
240 /* Register after we have the device set up so we cannot race
241 with an open */
242 ret = misc_register(&iop_wdt_miscdev);
243 if (ret == 0)
244 printk(KERN_INFO "iop watchdog timer: timeout %lu sec\n",
245 iop_watchdog_timeout());
246
245 return ret; 247 return ret;
246} 248}
247 249
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index 51bfd5721833..2270ee07c01b 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -221,7 +221,7 @@ static ssize_t it8712f_wdt_write(struct file *file, const char __user *data,
221 expect_close = 0; 221 expect_close = 0;
222 for (i = 0; i < len; ++i) { 222 for (i = 0; i < len; ++i) {
223 char c; 223 char c;
224 if (get_user(c, data+i)) 224 if (get_user(c, data + i))
225 return -EFAULT; 225 return -EFAULT;
226 if (c == 'V') 226 if (c == 'V')
227 expect_close = 42; 227 expect_close = 42;
@@ -244,8 +244,6 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
244 int value; 244 int value;
245 245
246 switch (cmd) { 246 switch (cmd) {
247 default:
248 return -ENOTTY;
249 case WDIOC_GETSUPPORT: 247 case WDIOC_GETSUPPORT:
250 if (copy_to_user(argp, &ident, sizeof(ident))) 248 if (copy_to_user(argp, &ident, sizeof(ident)))
251 return -EFAULT; 249 return -EFAULT;
@@ -284,6 +282,8 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
284 if (put_user(margin, p)) 282 if (put_user(margin, p))
285 return -EFAULT; 283 return -EFAULT;
286 return 0; 284 return 0;
285 default:
286 return -ENOTTY;
287 } 287 }
288} 288}
289 289
diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c
index dc7548dcaf35..a77f69d52877 100644
--- a/drivers/watchdog/ixp2000_wdt.c
+++ b/drivers/watchdog/ixp2000_wdt.c
@@ -25,42 +25,45 @@
25#include <linux/watchdog.h> 25#include <linux/watchdog.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/bitops.h> 27#include <linux/bitops.h>
28#include <linux/uaccess.h>
28 29
29#include <asm/hardware.h> 30#include <asm/hardware.h>
30#include <asm/uaccess.h>
31 31
32static int nowayout = WATCHDOG_NOWAYOUT; 32static int nowayout = WATCHDOG_NOWAYOUT;
33static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */ 33static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */
34static unsigned long wdt_status; 34static unsigned long wdt_status;
35static spinlock_t wdt_lock;
35 36
36#define WDT_IN_USE 0 37#define WDT_IN_USE 0
37#define WDT_OK_TO_CLOSE 1 38#define WDT_OK_TO_CLOSE 1
38 39
39static unsigned long wdt_tick_rate; 40static unsigned long wdt_tick_rate;
40 41
41static void 42static void wdt_enable(void)
42wdt_enable(void)
43{ 43{
44 spin_lock(&wdt_lock);
44 ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE); 45 ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE);
45 ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE); 46 ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE);
46 ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); 47 ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
47 ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE); 48 ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE);
49 spin_unlock(&wdt_lock);
48} 50}
49 51
50static void 52static void wdt_disable(void)
51wdt_disable(void)
52{ 53{
54 spin_lock(&wdt_lock);
53 ixp2000_reg_write(IXP2000_T4_CTL, 0); 55 ixp2000_reg_write(IXP2000_T4_CTL, 0);
56 spin_unlock(&wdt_lock);
54} 57}
55 58
56static void 59static void wdt_keepalive(void)
57wdt_keepalive(void)
58{ 60{
61 spin_lock(&wdt_lock);
59 ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); 62 ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
63 spin_unlock(&wdt_lock);
60} 64}
61 65
62static int 66static int ixp2000_wdt_open(struct inode *inode, struct file *file)
63ixp2000_wdt_open(struct inode *inode, struct file *file)
64{ 67{
65 if (test_and_set_bit(WDT_IN_USE, &wdt_status)) 68 if (test_and_set_bit(WDT_IN_USE, &wdt_status))
66 return -EBUSY; 69 return -EBUSY;
@@ -72,8 +75,8 @@ ixp2000_wdt_open(struct inode *inode, struct file *file)
72 return nonseekable_open(inode, file); 75 return nonseekable_open(inode, file);
73} 76}
74 77
75static ssize_t 78static ssize_t ixp2000_wdt_write(struct file *file, const char *data,
76ixp2000_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) 79 size_t len, loff_t *ppos)
77{ 80{
78 if (len) { 81 if (len) {
79 if (!nowayout) { 82 if (!nowayout) {
@@ -103,9 +106,8 @@ static struct watchdog_info ident = {
103 .identity = "IXP2000 Watchdog", 106 .identity = "IXP2000 Watchdog",
104}; 107};
105 108
106static int 109static long ixp2000_wdt_ioctl(struct file *file, unsigned int cmd,
107ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 110 unsigned long arg)
108 unsigned long arg)
109{ 111{
110 int ret = -ENOTTY; 112 int ret = -ENOTTY;
111 int time; 113 int time;
@@ -124,6 +126,11 @@ ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
124 ret = put_user(0, (int *)arg); 126 ret = put_user(0, (int *)arg);
125 break; 127 break;
126 128
129 case WDIOC_KEEPALIVE:
130 wdt_enable();
131 ret = 0;
132 break;
133
127 case WDIOC_SETTIMEOUT: 134 case WDIOC_SETTIMEOUT:
128 ret = get_user(time, (int *)arg); 135 ret = get_user(time, (int *)arg);
129 if (ret) 136 if (ret)
@@ -141,26 +148,18 @@ ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
141 case WDIOC_GETTIMEOUT: 148 case WDIOC_GETTIMEOUT:
142 ret = put_user(heartbeat, (int *)arg); 149 ret = put_user(heartbeat, (int *)arg);
143 break; 150 break;
144
145 case WDIOC_KEEPALIVE:
146 wdt_enable();
147 ret = 0;
148 break;
149 } 151 }
150 152
151 return ret; 153 return ret;
152} 154}
153 155
154static int 156static int ixp2000_wdt_release(struct inode *inode, struct file *file)
155ixp2000_wdt_release(struct inode *inode, struct file *file)
156{ 157{
157 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { 158 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
158 wdt_disable(); 159 wdt_disable();
159 } else { 160 else
160 printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " 161 printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
161 "timer will not stop\n"); 162 "timer will not stop\n");
162 }
163
164 clear_bit(WDT_IN_USE, &wdt_status); 163 clear_bit(WDT_IN_USE, &wdt_status);
165 clear_bit(WDT_OK_TO_CLOSE, &wdt_status); 164 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
166 165
@@ -168,18 +167,16 @@ ixp2000_wdt_release(struct inode *inode, struct file *file)
168} 167}
169 168
170 169
171static const struct file_operations ixp2000_wdt_fops = 170static const struct file_operations ixp2000_wdt_fops = {
172{
173 .owner = THIS_MODULE, 171 .owner = THIS_MODULE,
174 .llseek = no_llseek, 172 .llseek = no_llseek,
175 .write = ixp2000_wdt_write, 173 .write = ixp2000_wdt_write,
176 .ioctl = ixp2000_wdt_ioctl, 174 .unlocked_ioctl = ixp2000_wdt_ioctl,
177 .open = ixp2000_wdt_open, 175 .open = ixp2000_wdt_open,
178 .release = ixp2000_wdt_release, 176 .release = ixp2000_wdt_release,
179}; 177};
180 178
181static struct miscdevice ixp2000_wdt_miscdev = 179static struct miscdevice ixp2000_wdt_miscdev = {
182{
183 .minor = WATCHDOG_MINOR, 180 .minor = WATCHDOG_MINOR,
184 .name = "watchdog", 181 .name = "watchdog",
185 .fops = &ixp2000_wdt_fops, 182 .fops = &ixp2000_wdt_fops,
@@ -191,9 +188,8 @@ static int __init ixp2000_wdt_init(void)
191 printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n"); 188 printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
192 return -EIO; 189 return -EIO;
193 } 190 }
194
195 wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256; 191 wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
196 192 spin_lock_init(&wdt_lock);
197 return misc_register(&ixp2000_wdt_miscdev); 193 return misc_register(&ixp2000_wdt_miscdev);
198} 194}
199 195
diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c
index 5864bb865cfe..ef3157dc9ac1 100644
--- a/drivers/watchdog/ixp4xx_wdt.c
+++ b/drivers/watchdog/ixp4xx_wdt.c
@@ -22,48 +22,48 @@
22#include <linux/watchdog.h> 22#include <linux/watchdog.h>
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/bitops.h> 24#include <linux/bitops.h>
25#include <linux/uaccess.h>
25 26
26#include <asm/hardware.h> 27#include <asm/hardware.h>
27#include <asm/uaccess.h>
28 28
29static int nowayout = WATCHDOG_NOWAYOUT; 29static int nowayout = WATCHDOG_NOWAYOUT;
30static int heartbeat = 60; /* (secs) Default is 1 minute */ 30static int heartbeat = 60; /* (secs) Default is 1 minute */
31static unsigned long wdt_status; 31static unsigned long wdt_status;
32static unsigned long boot_status; 32static unsigned long boot_status;
33static spin_lock_t wdt_lock;
33 34
34#define WDT_TICK_RATE (IXP4XX_PERIPHERAL_BUS_CLOCK * 1000000UL) 35#define WDT_TICK_RATE (IXP4XX_PERIPHERAL_BUS_CLOCK * 1000000UL)
35 36
36#define WDT_IN_USE 0 37#define WDT_IN_USE 0
37#define WDT_OK_TO_CLOSE 1 38#define WDT_OK_TO_CLOSE 1
38 39
39static void 40static void wdt_enable(void)
40wdt_enable(void)
41{ 41{
42 spin_lock(&wdt_lock);
42 *IXP4XX_OSWK = IXP4XX_WDT_KEY; 43 *IXP4XX_OSWK = IXP4XX_WDT_KEY;
43 *IXP4XX_OSWE = 0; 44 *IXP4XX_OSWE = 0;
44 *IXP4XX_OSWT = WDT_TICK_RATE * heartbeat; 45 *IXP4XX_OSWT = WDT_TICK_RATE * heartbeat;
45 *IXP4XX_OSWE = IXP4XX_WDT_COUNT_ENABLE | IXP4XX_WDT_RESET_ENABLE; 46 *IXP4XX_OSWE = IXP4XX_WDT_COUNT_ENABLE | IXP4XX_WDT_RESET_ENABLE;
46 *IXP4XX_OSWK = 0; 47 *IXP4XX_OSWK = 0;
48 spin_unlock(&wdt_lock);
47} 49}
48 50
49static void 51static void wdt_disable(void)
50wdt_disable(void)
51{ 52{
53 spin_lock(&wdt_lock);
52 *IXP4XX_OSWK = IXP4XX_WDT_KEY; 54 *IXP4XX_OSWK = IXP4XX_WDT_KEY;
53 *IXP4XX_OSWE = 0; 55 *IXP4XX_OSWE = 0;
54 *IXP4XX_OSWK = 0; 56 *IXP4XX_OSWK = 0;
57 spin_unlock(&wdt_lock);
55} 58}
56 59
57static int 60static int ixp4xx_wdt_open(struct inode *inode, struct file *file)
58ixp4xx_wdt_open(struct inode *inode, struct file *file)
59{ 61{
60 if (test_and_set_bit(WDT_IN_USE, &wdt_status)) 62 if (test_and_set_bit(WDT_IN_USE, &wdt_status))
61 return -EBUSY; 63 return -EBUSY;
62 64
63 clear_bit(WDT_OK_TO_CLOSE, &wdt_status); 65 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
64
65 wdt_enable(); 66 wdt_enable();
66
67 return nonseekable_open(inode, file); 67 return nonseekable_open(inode, file);
68} 68}
69 69
@@ -87,7 +87,6 @@ ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
87 } 87 }
88 wdt_enable(); 88 wdt_enable();
89 } 89 }
90
91 return len; 90 return len;
92} 91}
93 92
@@ -98,9 +97,8 @@ static struct watchdog_info ident = {
98}; 97};
99 98
100 99
101static int 100static long ixp4xx_wdt_ioctl(struct file *file, unsigned int cmd,
102ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 101 unsigned long arg)
103 unsigned long arg)
104{ 102{
105 int ret = -ENOTTY; 103 int ret = -ENOTTY;
106 int time; 104 int time;
@@ -119,6 +117,11 @@ ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
119 ret = put_user(boot_status, (int *)arg); 117 ret = put_user(boot_status, (int *)arg);
120 break; 118 break;
121 119
120 case WDIOC_KEEPALIVE:
121 wdt_enable();
122 ret = 0;
123 break;
124
122 case WDIOC_SETTIMEOUT: 125 case WDIOC_SETTIMEOUT:
123 ret = get_user(time, (int *)arg); 126 ret = get_user(time, (int *)arg);
124 if (ret) 127 if (ret)
@@ -136,25 +139,17 @@ ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
136 case WDIOC_GETTIMEOUT: 139 case WDIOC_GETTIMEOUT:
137 ret = put_user(heartbeat, (int *)arg); 140 ret = put_user(heartbeat, (int *)arg);
138 break; 141 break;
139
140 case WDIOC_KEEPALIVE:
141 wdt_enable();
142 ret = 0;
143 break;
144 } 142 }
145 return ret; 143 return ret;
146} 144}
147 145
148static int 146static int ixp4xx_wdt_release(struct inode *inode, struct file *file)
149ixp4xx_wdt_release(struct inode *inode, struct file *file)
150{ 147{
151 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { 148 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
152 wdt_disable(); 149 wdt_disable();
153 } else { 150 else
154 printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " 151 printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
155 "timer will not stop\n"); 152 "timer will not stop\n");
156 }
157
158 clear_bit(WDT_IN_USE, &wdt_status); 153 clear_bit(WDT_IN_USE, &wdt_status);
159 clear_bit(WDT_OK_TO_CLOSE, &wdt_status); 154 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
160 155
@@ -162,18 +157,16 @@ ixp4xx_wdt_release(struct inode *inode, struct file *file)
162} 157}
163 158
164 159
165static const struct file_operations ixp4xx_wdt_fops = 160static const struct file_operations ixp4xx_wdt_fops = {
166{
167 .owner = THIS_MODULE, 161 .owner = THIS_MODULE,
168 .llseek = no_llseek, 162 .llseek = no_llseek,
169 .write = ixp4xx_wdt_write, 163 .write = ixp4xx_wdt_write,
170 .ioctl = ixp4xx_wdt_ioctl, 164 .unlocked_ioctl = ixp4xx_wdt_ioctl,
171 .open = ixp4xx_wdt_open, 165 .open = ixp4xx_wdt_open,
172 .release = ixp4xx_wdt_release, 166 .release = ixp4xx_wdt_release,
173}; 167};
174 168
175static struct miscdevice ixp4xx_wdt_miscdev = 169static struct miscdevice ixp4xx_wdt_miscdev = {
176{
177 .minor = WATCHDOG_MINOR, 170 .minor = WATCHDOG_MINOR,
178 .name = "watchdog", 171 .name = "watchdog",
179 .fops = &ixp4xx_wdt_fops, 172 .fops = &ixp4xx_wdt_fops,
@@ -186,19 +179,18 @@ static int __init ixp4xx_wdt_init(void)
186 179
187 asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(processor_id) :); 180 asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(processor_id) :);
188 if (!(processor_id & 0xf) && !cpu_is_ixp46x()) { 181 if (!(processor_id & 0xf) && !cpu_is_ixp46x()) {
189 printk("IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected - " 182 printk(KERN_ERR "IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected"
190 "watchdog disabled\n"); 183 " - watchdog disabled\n");
191 184
192 return -ENODEV; 185 return -ENODEV;
193 } 186 }
194 187 spin_lock_init(&wdt_lock);
195 ret = misc_register(&ixp4xx_wdt_miscdev);
196 if (ret == 0)
197 printk("IXP4xx Watchdog Timer: heartbeat %d sec\n", heartbeat);
198
199 boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ? 188 boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ?
200 WDIOF_CARDRESET : 0; 189 WDIOF_CARDRESET : 0;
201 190 ret = misc_register(&ixp4xx_wdt_miscdev);
191 if (ret == 0)
192 printk(KERN_INFO "IXP4xx Watchdog Timer: heartbeat %d sec\n",
193 heartbeat);
202 return ret; 194 return ret;
203} 195}
204 196
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index df5a6b811ccd..f8566d5c62fe 100644
--- a/drivers/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -19,8 +19,8 @@
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/types.h> 20#include <linux/types.h>
21#include <linux/watchdog.h> 21#include <linux/watchdog.h>
22#include <asm/io.h> 22#include <linux/io.h>
23#include <asm/uaccess.h> 23#include <linux/uaccess.h>
24#include <asm/arch/regs-timer.h> 24#include <asm/arch/regs-timer.h>
25 25
26 26
@@ -31,38 +31,44 @@ static int wdt_time = WDT_DEFAULT_TIME;
31static int nowayout = WATCHDOG_NOWAYOUT; 31static int nowayout = WATCHDOG_NOWAYOUT;
32 32
33module_param(wdt_time, int, 0); 33module_param(wdt_time, int, 0);
34MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); 34MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
35 __MODULE_STRING(WDT_DEFAULT_TIME) ")");
35 36
36#ifdef CONFIG_WATCHDOG_NOWAYOUT 37#ifdef CONFIG_WATCHDOG_NOWAYOUT
37module_param(nowayout, int, 0); 38module_param(nowayout, int, 0);
38MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 39MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
40 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
39#endif 41#endif
40 42
41 43
42static unsigned long ks8695wdt_busy; 44static unsigned long ks8695wdt_busy;
45static spinlock_t ks8695_lock;
43 46
44/* ......................................................................... */ 47/* ......................................................................... */
45 48
46/* 49/*
47 * Disable the watchdog. 50 * Disable the watchdog.
48 */ 51 */
49static void inline ks8695_wdt_stop(void) 52static inline void ks8695_wdt_stop(void)
50{ 53{
51 unsigned long tmcon; 54 unsigned long tmcon;
52 55
56 spin_lock(&ks8695_lock);
53 /* disable timer0 */ 57 /* disable timer0 */
54 tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); 58 tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
55 __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); 59 __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
60 spin_unlock(&ks8695_lock);
56} 61}
57 62
58/* 63/*
59 * Enable and reset the watchdog. 64 * Enable and reset the watchdog.
60 */ 65 */
61static void inline ks8695_wdt_start(void) 66static inline void ks8695_wdt_start(void)
62{ 67{
63 unsigned long tmcon; 68 unsigned long tmcon;
64 unsigned long tval = wdt_time * CLOCK_TICK_RATE; 69 unsigned long tval = wdt_time * CLOCK_TICK_RATE;
65 70
71 spin_lock(&ks8695_lock);
66 /* disable timer0 */ 72 /* disable timer0 */
67 tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); 73 tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
68 __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); 74 __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
@@ -73,19 +79,22 @@ static void inline ks8695_wdt_start(void)
73 /* re-enable timer0 */ 79 /* re-enable timer0 */
74 tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); 80 tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
75 __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); 81 __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
82 spin_unlock(&ks8695_lock);
76} 83}
77 84
78/* 85/*
79 * Reload the watchdog timer. (ie, pat the watchdog) 86 * Reload the watchdog timer. (ie, pat the watchdog)
80 */ 87 */
81static void inline ks8695_wdt_reload(void) 88static inline void ks8695_wdt_reload(void)
82{ 89{
83 unsigned long tmcon; 90 unsigned long tmcon;
84 91
92 spin_lock(&ks8695_lock);
85 /* disable, then re-enable timer0 */ 93 /* disable, then re-enable timer0 */
86 tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); 94 tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
87 __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); 95 __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
88 __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); 96 __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
97 spin_unlock(&ks8695_lock);
89} 98}
90 99
91/* 100/*
@@ -102,7 +111,8 @@ static int ks8695_wdt_settimeout(int new_time)
102 if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) 111 if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
103 return -EINVAL; 112 return -EINVAL;
104 113
105 /* Set new watchdog time. It will be used when ks8695_wdt_start() is called. */ 114 /* Set new watchdog time. It will be used when
115 ks8695_wdt_start() is called. */
106 wdt_time = new_time; 116 wdt_time = new_time;
107 return 0; 117 return 0;
108} 118}
@@ -128,9 +138,9 @@ static int ks8695_wdt_open(struct inode *inode, struct file *file)
128 */ 138 */
129static int ks8695_wdt_close(struct inode *inode, struct file *file) 139static int ks8695_wdt_close(struct inode *inode, struct file *file)
130{ 140{
141 /* Disable the watchdog when file is closed */
131 if (!nowayout) 142 if (!nowayout)
132 ks8695_wdt_stop(); /* Disable the watchdog when file is closed */ 143 ks8695_wdt_stop();
133
134 clear_bit(0, &ks8695wdt_busy); 144 clear_bit(0, &ks8695wdt_busy);
135 return 0; 145 return 0;
136} 146}
@@ -143,60 +153,52 @@ static struct watchdog_info ks8695_wdt_info = {
143/* 153/*
144 * Handle commands from user-space. 154 * Handle commands from user-space.
145 */ 155 */
146static int ks8695_wdt_ioctl(struct inode *inode, struct file *file, 156static long ks8695_wdt_ioctl(struct file *file, unsigned int cmd,
147 unsigned int cmd, unsigned long arg) 157 unsigned long arg)
148{ 158{
149 void __user *argp = (void __user *)arg; 159 void __user *argp = (void __user *)arg;
150 int __user *p = argp; 160 int __user *p = argp;
151 int new_value; 161 int new_value;
152 162
153 switch(cmd) { 163 switch (cmd) {
154 case WDIOC_KEEPALIVE: 164 case WDIOC_GETSUPPORT:
155 ks8695_wdt_reload(); /* pat the watchdog */ 165 return copy_to_user(argp, &ks8695_wdt_info,
156 return 0; 166 sizeof(ks8695_wdt_info)) ? -EFAULT : 0;
157 167 case WDIOC_GETSTATUS:
158 case WDIOC_GETSUPPORT: 168 case WDIOC_GETBOOTSTATUS:
159 return copy_to_user(argp, &ks8695_wdt_info, sizeof(ks8695_wdt_info)) ? -EFAULT : 0; 169 return put_user(0, p);
160 170 case WDIOC_SETOPTIONS:
161 case WDIOC_SETTIMEOUT: 171 if (get_user(new_value, p))
162 if (get_user(new_value, p)) 172 return -EFAULT;
163 return -EFAULT; 173 if (new_value & WDIOS_DISABLECARD)
164 174 ks8695_wdt_stop();
165 if (ks8695_wdt_settimeout(new_value)) 175 if (new_value & WDIOS_ENABLECARD)
166 return -EINVAL;
167
168 /* Enable new time value */
169 ks8695_wdt_start(); 176 ks8695_wdt_start();
170 177 return 0;
171 /* Return current value */ 178 case WDIOC_KEEPALIVE:
172 return put_user(wdt_time, p); 179 ks8695_wdt_reload(); /* pat the watchdog */
173 180 return 0;
174 case WDIOC_GETTIMEOUT: 181 case WDIOC_SETTIMEOUT:
175 return put_user(wdt_time, p); 182 if (get_user(new_value, p))
176 183 return -EFAULT;
177 case WDIOC_GETSTATUS: 184 if (ks8695_wdt_settimeout(new_value))
178 case WDIOC_GETBOOTSTATUS: 185 return -EINVAL;
179 return put_user(0, p); 186 /* Enable new time value */
180 187 ks8695_wdt_start();
181 case WDIOC_SETOPTIONS: 188 /* Return current value */
182 if (get_user(new_value, p)) 189 return put_user(wdt_time, p);
183 return -EFAULT; 190 case WDIOC_GETTIMEOUT:
184 191 return put_user(wdt_time, p);
185 if (new_value & WDIOS_DISABLECARD) 192 default:
186 ks8695_wdt_stop(); 193 return -ENOTTY;
187 if (new_value & WDIOS_ENABLECARD)
188 ks8695_wdt_start();
189 return 0;
190
191 default:
192 return -ENOTTY;
193 } 194 }
194} 195}
195 196
196/* 197/*
197 * Pat the watchdog whenever device is written to. 198 * Pat the watchdog whenever device is written to.
198 */ 199 */
199static ssize_t ks8695_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) 200static ssize_t ks8695_wdt_write(struct file *file, const char *data,
201 size_t len, loff_t *ppos)
200{ 202{
201 ks8695_wdt_reload(); /* pat the watchdog */ 203 ks8695_wdt_reload(); /* pat the watchdog */
202 return len; 204 return len;
@@ -207,7 +209,7 @@ static ssize_t ks8695_wdt_write(struct file *file, const char *data, size_t len,
207static const struct file_operations ks8695wdt_fops = { 209static const struct file_operations ks8695wdt_fops = {
208 .owner = THIS_MODULE, 210 .owner = THIS_MODULE,
209 .llseek = no_llseek, 211 .llseek = no_llseek,
210 .ioctl = ks8695_wdt_ioctl, 212 .unlocked_ioctl = ks8695_wdt_ioctl,
211 .open = ks8695_wdt_open, 213 .open = ks8695_wdt_open,
212 .release = ks8695_wdt_close, 214 .release = ks8695_wdt_close,
213 .write = ks8695_wdt_write, 215 .write = ks8695_wdt_write,
@@ -231,7 +233,8 @@ static int __init ks8695wdt_probe(struct platform_device *pdev)
231 if (res) 233 if (res)
232 return res; 234 return res;
233 235
234 printk("KS8695 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); 236 printk(KERN_INFO "KS8695 Watchdog Timer enabled (%d seconds%s)\n",
237 wdt_time, nowayout ? ", nowayout" : "");
235 return 0; 238 return 0;
236} 239}
237 240
@@ -285,12 +288,14 @@ static struct platform_driver ks8695wdt_driver = {
285 288
286static int __init ks8695_wdt_init(void) 289static int __init ks8695_wdt_init(void)
287{ 290{
288 /* Check that the heartbeat value is within range; if not reset to the default */ 291 spin_lock_init(&ks8695_lock);
292 /* Check that the heartbeat value is within range;
293 if not reset to the default */
289 if (ks8695_wdt_settimeout(wdt_time)) { 294 if (ks8695_wdt_settimeout(wdt_time)) {
290 ks8695_wdt_settimeout(WDT_DEFAULT_TIME); 295 ks8695_wdt_settimeout(WDT_DEFAULT_TIME);
291 pr_info("ks8695_wdt: wdt_time value must be 1 <= wdt_time <= %i, using %d\n", wdt_time, WDT_MAX_TIME); 296 pr_info("ks8695_wdt: wdt_time value must be 1 <= wdt_time <= %i, using %d\n",
297 wdt_time, WDT_MAX_TIME);
292 } 298 }
293
294 return platform_driver_register(&ks8695wdt_driver); 299 return platform_driver_register(&ks8695wdt_driver);
295} 300}
296 301
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c
index 6905135a776c..2dfc27559bf7 100644
--- a/drivers/watchdog/machzwd.c
+++ b/drivers/watchdog/machzwd.c
@@ -40,9 +40,9 @@
40#include <linux/notifier.h> 40#include <linux/notifier.h>
41#include <linux/reboot.h> 41#include <linux/reboot.h>
42#include <linux/init.h> 42#include <linux/init.h>
43#include <linux/io.h>
44#include <linux/uaccess.h>
43 45
44#include <asm/io.h>
45#include <asm/uaccess.h>
46#include <asm/system.h> 46#include <asm/system.h>
47 47
48/* ports */ 48/* ports */
@@ -95,7 +95,9 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
95 95
96static int nowayout = WATCHDOG_NOWAYOUT; 96static int nowayout = WATCHDOG_NOWAYOUT;
97module_param(nowayout, int, 0); 97module_param(nowayout, int, 0);
98MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 98MODULE_PARM_DESC(nowayout,
99 "Watchdog cannot be stopped once started (default="
100 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
99 101
100#define PFX "machzwd" 102#define PFX "machzwd"
101 103
@@ -114,7 +116,7 @@ static struct watchdog_info zf_info = {
114 * 3 = GEN_SCI 116 * 3 = GEN_SCI
115 * defaults to GEN_RESET (0) 117 * defaults to GEN_RESET (0)
116 */ 118 */
117static int action = 0; 119static int action;
118module_param(action, int, 0); 120module_param(action, int, 0);
119MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI"); 121MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI");
120 122
@@ -123,10 +125,9 @@ static void zf_ping(unsigned long data);
123static int zf_action = GEN_RESET; 125static int zf_action = GEN_RESET;
124static unsigned long zf_is_open; 126static unsigned long zf_is_open;
125static char zf_expect_close; 127static char zf_expect_close;
126static DEFINE_SPINLOCK(zf_lock);
127static DEFINE_SPINLOCK(zf_port_lock); 128static DEFINE_SPINLOCK(zf_port_lock);
128static DEFINE_TIMER(zf_timer, zf_ping, 0, 0); 129static DEFINE_TIMER(zf_timer, zf_ping, 0, 0);
129static unsigned long next_heartbeat = 0; 130static unsigned long next_heartbeat;
130 131
131 132
132/* timeout for user land heart beat (10 seconds) */ 133/* timeout for user land heart beat (10 seconds) */
@@ -171,13 +172,13 @@ static inline void zf_set_control(unsigned short new)
171 172
172static inline void zf_set_timer(unsigned short new, unsigned char n) 173static inline void zf_set_timer(unsigned short new, unsigned char n)
173{ 174{
174 switch(n){ 175 switch (n) {
175 case WD1: 176 case WD1:
176 zf_writew(COUNTER_1, new); 177 zf_writew(COUNTER_1, new);
177 case WD2: 178 case WD2:
178 zf_writeb(COUNTER_2, new > 0xff ? 0xff : new); 179 zf_writeb(COUNTER_2, new > 0xff ? 0xff : new);
179 default: 180 default:
180 return; 181 return;
181 } 182 }
182} 183}
183 184
@@ -241,10 +242,8 @@ static void zf_ping(unsigned long data)
241 242
242 zf_writeb(COUNTER_2, 0xff); 243 zf_writeb(COUNTER_2, 0xff);
243 244
244 if(time_before(jiffies, next_heartbeat)){ 245 if (time_before(jiffies, next_heartbeat)) {
245
246 dprintk("time_before: %ld\n", next_heartbeat - jiffies); 246 dprintk("time_before: %ld\n", next_heartbeat - jiffies);
247
248 /* 247 /*
249 * reset event is activated by transition from 0 to 1 on 248 * reset event is activated by transition from 0 to 1 on
250 * RESET_WD1 bit and we assume that it is already zero... 249 * RESET_WD1 bit and we assume that it is already zero...
@@ -261,24 +260,21 @@ static void zf_ping(unsigned long data)
261 spin_unlock_irqrestore(&zf_port_lock, flags); 260 spin_unlock_irqrestore(&zf_port_lock, flags);
262 261
263 mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO); 262 mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
264 }else{ 263 } else
265 printk(KERN_CRIT PFX ": I will reset your machine\n"); 264 printk(KERN_CRIT PFX ": I will reset your machine\n");
266 }
267} 265}
268 266
269static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, 267static ssize_t zf_write(struct file *file, const char __user *buf, size_t count,
270 loff_t *ppos) 268 loff_t *ppos)
271{ 269{
272 /* See if we got the magic character */ 270 /* See if we got the magic character */
273 if(count){ 271 if (count) {
274
275 /* 272 /*
276 * no need to check for close confirmation 273 * no need to check for close confirmation
277 * no way to disable watchdog ;) 274 * no way to disable watchdog ;)
278 */ 275 */
279 if (!nowayout) { 276 if (!nowayout) {
280 size_t ofs; 277 size_t ofs;
281
282 /* 278 /*
283 * note: just in case someone wrote the magic character 279 * note: just in case someone wrote the magic character
284 * five months ago... 280 * five months ago...
@@ -286,11 +282,11 @@ static ssize_t zf_write(struct file *file, const char __user *buf, size_t count,
286 zf_expect_close = 0; 282 zf_expect_close = 0;
287 283
288 /* now scan */ 284 /* now scan */
289 for (ofs = 0; ofs != count; ofs++){ 285 for (ofs = 0; ofs != count; ofs++) {
290 char c; 286 char c;
291 if (get_user(c, buf + ofs)) 287 if (get_user(c, buf + ofs))
292 return -EFAULT; 288 return -EFAULT;
293 if (c == 'V'){ 289 if (c == 'V') {
294 zf_expect_close = 42; 290 zf_expect_close = 42;
295 dprintk("zf_expect_close = 42\n"); 291 dprintk("zf_expect_close = 42\n");
296 } 292 }
@@ -303,14 +299,11 @@ static ssize_t zf_write(struct file *file, const char __user *buf, size_t count,
303 */ 299 */
304 next_heartbeat = jiffies + ZF_USER_TIMEO; 300 next_heartbeat = jiffies + ZF_USER_TIMEO;
305 dprintk("user ping at %ld\n", jiffies); 301 dprintk("user ping at %ld\n", jiffies);
306
307 } 302 }
308
309 return count; 303 return count;
310} 304}
311 305
312static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 306static long zf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
313 unsigned long arg)
314{ 307{
315 void __user *argp = (void __user *)arg; 308 void __user *argp = (void __user *)arg;
316 int __user *p = argp; 309 int __user *p = argp;
@@ -319,55 +312,38 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
319 if (copy_to_user(argp, &zf_info, sizeof(zf_info))) 312 if (copy_to_user(argp, &zf_info, sizeof(zf_info)))
320 return -EFAULT; 313 return -EFAULT;
321 break; 314 break;
322
323 case WDIOC_GETSTATUS: 315 case WDIOC_GETSTATUS:
324 case WDIOC_GETBOOTSTATUS: 316 case WDIOC_GETBOOTSTATUS:
325 return put_user(0, p); 317 return put_user(0, p);
326
327 case WDIOC_KEEPALIVE: 318 case WDIOC_KEEPALIVE:
328 zf_ping(0); 319 zf_ping(0);
329 break; 320 break;
330
331 default: 321 default:
332 return -ENOTTY; 322 return -ENOTTY;
333 } 323 }
334
335 return 0; 324 return 0;
336} 325}
337 326
338static int zf_open(struct inode *inode, struct file *file) 327static int zf_open(struct inode *inode, struct file *file)
339{ 328{
340 spin_lock(&zf_lock); 329 if (test_and_set_bit(0, &zf_is_open))
341 if(test_and_set_bit(0, &zf_is_open)) {
342 spin_unlock(&zf_lock);
343 return -EBUSY; 330 return -EBUSY;
344 }
345
346 if (nowayout) 331 if (nowayout)
347 __module_get(THIS_MODULE); 332 __module_get(THIS_MODULE);
348
349 spin_unlock(&zf_lock);
350
351 zf_timer_on(); 333 zf_timer_on();
352
353 return nonseekable_open(inode, file); 334 return nonseekable_open(inode, file);
354} 335}
355 336
356static int zf_close(struct inode *inode, struct file *file) 337static int zf_close(struct inode *inode, struct file *file)
357{ 338{
358 if(zf_expect_close == 42){ 339 if (zf_expect_close == 42)
359 zf_timer_off(); 340 zf_timer_off();
360 } else { 341 else {
361 del_timer(&zf_timer); 342 del_timer(&zf_timer);
362 printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n"); 343 printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n");
363 } 344 }
364
365 spin_lock(&zf_lock);
366 clear_bit(0, &zf_is_open); 345 clear_bit(0, &zf_is_open);
367 spin_unlock(&zf_lock);
368
369 zf_expect_close = 0; 346 zf_expect_close = 0;
370
371 return 0; 347 return 0;
372} 348}
373 349
@@ -378,23 +354,18 @@ static int zf_close(struct inode *inode, struct file *file)
378static int zf_notify_sys(struct notifier_block *this, unsigned long code, 354static int zf_notify_sys(struct notifier_block *this, unsigned long code,
379 void *unused) 355 void *unused)
380{ 356{
381 if(code == SYS_DOWN || code == SYS_HALT){ 357 if (code == SYS_DOWN || code == SYS_HALT)
382 zf_timer_off(); 358 zf_timer_off();
383 }
384
385 return NOTIFY_DONE; 359 return NOTIFY_DONE;
386} 360}
387 361
388
389
390
391static const struct file_operations zf_fops = { 362static const struct file_operations zf_fops = {
392 .owner = THIS_MODULE, 363 .owner = THIS_MODULE,
393 .llseek = no_llseek, 364 .llseek = no_llseek,
394 .write = zf_write, 365 .write = zf_write,
395 .ioctl = zf_ioctl, 366 .unlocked_ioctl = zf_ioctl,
396 .open = zf_open, 367 .open = zf_open,
397 .release = zf_close, 368 .release = zf_close,
398}; 369};
399 370
400static struct miscdevice zf_miscdev = { 371static struct miscdevice zf_miscdev = {
@@ -402,7 +373,7 @@ static struct miscdevice zf_miscdev = {
402 .name = "watchdog", 373 .name = "watchdog",
403 .fops = &zf_fops, 374 .fops = &zf_fops,
404}; 375};
405 376
406 377
407/* 378/*
408 * The device needs to learn about soft shutdowns in order to 379 * The device needs to learn about soft shutdowns in order to
@@ -423,22 +394,23 @@ static int __init zf_init(void)
423{ 394{
424 int ret; 395 int ret;
425 396
426 printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n"); 397 printk(KERN_INFO PFX
398 ": MachZ ZF-Logic Watchdog driver initializing.\n");
427 399
428 ret = zf_get_ZFL_version(); 400 ret = zf_get_ZFL_version();
429 if ((!ret) || (ret == 0xffff)) { 401 if (!ret || ret == 0xffff) {
430 printk(KERN_WARNING PFX ": no ZF-Logic found\n"); 402 printk(KERN_WARNING PFX ": no ZF-Logic found\n");
431 return -ENODEV; 403 return -ENODEV;
432 } 404 }
433 405
434 if((action <= 3) && (action >= 0)){ 406 if (action <= 3 && action >= 0)
435 zf_action = zf_action>>action; 407 zf_action = zf_action >> action;
436 } else 408 else
437 action = 0; 409 action = 0;
438 410
439 zf_show_action(action); 411 zf_show_action(action);
440 412
441 if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){ 413 if (!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")) {
442 printk(KERN_ERR "cannot reserve I/O ports at %d\n", 414 printk(KERN_ERR "cannot reserve I/O ports at %d\n",
443 ZF_IOBASE); 415 ZF_IOBASE);
444 ret = -EBUSY; 416 ret = -EBUSY;
@@ -446,14 +418,14 @@ static int __init zf_init(void)
446 } 418 }
447 419
448 ret = register_reboot_notifier(&zf_notifier); 420 ret = register_reboot_notifier(&zf_notifier);
449 if(ret){ 421 if (ret) {
450 printk(KERN_ERR "can't register reboot notifier (err=%d)\n", 422 printk(KERN_ERR "can't register reboot notifier (err=%d)\n",
451 ret); 423 ret);
452 goto no_reboot; 424 goto no_reboot;
453 } 425 }
454 426
455 ret = misc_register(&zf_miscdev); 427 ret = misc_register(&zf_miscdev);
456 if (ret){ 428 if (ret) {
457 printk(KERN_ERR "can't misc_register on minor=%d\n", 429 printk(KERN_ERR "can't misc_register on minor=%d\n",
458 WATCHDOG_MINOR); 430 WATCHDOG_MINOR);
459 goto no_misc; 431 goto no_misc;
diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c
index 1adf1d56027d..407b025cb104 100644
--- a/drivers/watchdog/mixcomwd.c
+++ b/drivers/watchdog/mixcomwd.c
@@ -29,7 +29,8 @@
29 * - support for one more type board 29 * - support for one more type board
30 * 30 *
31 * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com> 31 * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com>
32 * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT 32 * - added nowayout module option to override
33 * CONFIG_WATCHDOG_NOWAYOUT
33 * 34 *
34 * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com> 35 * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com>
35 * - make mixcomwd_opened unsigned, 36 * - make mixcomwd_opened unsigned,
@@ -53,8 +54,8 @@
53#include <linux/init.h> 54#include <linux/init.h>
54#include <linux/jiffies.h> 55#include <linux/jiffies.h>
55#include <linux/timer.h> 56#include <linux/timer.h>
56#include <asm/uaccess.h> 57#include <linux/uaccess.h>
57#include <asm/io.h> 58#include <linux/io.h>
58 59
59/* 60/*
60 * We have two types of cards that can be probed: 61 * We have two types of cards that can be probed:
@@ -108,18 +109,19 @@ static char expect_close;
108 109
109static int nowayout = WATCHDOG_NOWAYOUT; 110static int nowayout = WATCHDOG_NOWAYOUT;
110module_param(nowayout, int, 0); 111module_param(nowayout, int, 0);
111MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 112MODULE_PARM_DESC(nowayout,
113 "Watchdog cannot be stopped once started (default="
114 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
112 115
113static void mixcomwd_ping(void) 116static void mixcomwd_ping(void)
114{ 117{
115 outb_p(55,watchdog_port); 118 outb_p(55, watchdog_port);
116 return; 119 return;
117} 120}
118 121
119static void mixcomwd_timerfun(unsigned long d) 122static void mixcomwd_timerfun(unsigned long d)
120{ 123{
121 mixcomwd_ping(); 124 mixcomwd_ping();
122
123 mod_timer(&mixcomwd_timer, jiffies + 5 * HZ); 125 mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
124} 126}
125 127
@@ -129,22 +131,22 @@ static void mixcomwd_timerfun(unsigned long d)
129 131
130static int mixcomwd_open(struct inode *inode, struct file *file) 132static int mixcomwd_open(struct inode *inode, struct file *file)
131{ 133{
132 if(test_and_set_bit(0,&mixcomwd_opened)) { 134 if (test_and_set_bit(0, &mixcomwd_opened))
133 return -EBUSY; 135 return -EBUSY;
134 } 136
135 mixcomwd_ping(); 137 mixcomwd_ping();
136 138
137 if (nowayout) { 139 if (nowayout)
138 /* 140 /*
139 * fops_get() code via open() has already done 141 * fops_get() code via open() has already done
140 * a try_module_get() so it is safe to do the 142 * a try_module_get() so it is safe to do the
141 * __module_get(). 143 * __module_get().
142 */ 144 */
143 __module_get(THIS_MODULE); 145 __module_get(THIS_MODULE);
144 } else { 146 else {
145 if(mixcomwd_timer_alive) { 147 if (mixcomwd_timer_alive) {
146 del_timer(&mixcomwd_timer); 148 del_timer(&mixcomwd_timer);
147 mixcomwd_timer_alive=0; 149 mixcomwd_timer_alive = 0;
148 } 150 }
149 } 151 }
150 return nonseekable_open(inode, file); 152 return nonseekable_open(inode, file);
@@ -153,26 +155,27 @@ static int mixcomwd_open(struct inode *inode, struct file *file)
153static int mixcomwd_release(struct inode *inode, struct file *file) 155static int mixcomwd_release(struct inode *inode, struct file *file)
154{ 156{
155 if (expect_close == 42) { 157 if (expect_close == 42) {
156 if(mixcomwd_timer_alive) { 158 if (mixcomwd_timer_alive) {
157 printk(KERN_ERR PFX "release called while internal timer alive"); 159 printk(KERN_ERR PFX
160 "release called while internal timer alive");
158 return -EBUSY; 161 return -EBUSY;
159 } 162 }
160 mixcomwd_timer_alive=1; 163 mixcomwd_timer_alive = 1;
161 mod_timer(&mixcomwd_timer, jiffies + 5 * HZ); 164 mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
162 } else { 165 } else
163 printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); 166 printk(KERN_CRIT PFX
164 } 167 "WDT device closed unexpectedly. WDT will not stop!\n");
165 168
166 clear_bit(0,&mixcomwd_opened); 169 clear_bit(0, &mixcomwd_opened);
167 expect_close=0; 170 expect_close = 0;
168 return 0; 171 return 0;
169} 172}
170 173
171 174
172static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) 175static ssize_t mixcomwd_write(struct file *file, const char __user *data,
176 size_t len, loff_t *ppos)
173{ 177{
174 if(len) 178 if (len) {
175 {
176 if (!nowayout) { 179 if (!nowayout) {
177 size_t i; 180 size_t i;
178 181
@@ -192,8 +195,8 @@ static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t
192 return len; 195 return len;
193} 196}
194 197
195static int mixcomwd_ioctl(struct inode *inode, struct file *file, 198static long mixcomwd_ioctl(struct file *file,
196 unsigned int cmd, unsigned long arg) 199 unsigned int cmd, unsigned long arg)
197{ 200{
198 void __user *argp = (void __user *)arg; 201 void __user *argp = (void __user *)arg;
199 int __user *p = argp; 202 int __user *p = argp;
@@ -204,32 +207,23 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file,
204 .identity = "MixCOM watchdog", 207 .identity = "MixCOM watchdog",
205 }; 208 };
206 209
207 switch(cmd) 210 switch (cmd) {
208 { 211 case WDIOC_GETSUPPORT:
209 case WDIOC_GETSTATUS: 212 if (copy_to_user(argp, &ident, sizeof(ident)))
210 status=mixcomwd_opened; 213 return -EFAULT;
211 if (!nowayout) { 214 break;
212 status|=mixcomwd_timer_alive; 215 case WDIOC_GETSTATUS:
213 } 216 status = mixcomwd_opened;
214 if (copy_to_user(p, &status, sizeof(int))) { 217 if (!nowayout)
215 return -EFAULT; 218 status |= mixcomwd_timer_alive;
216 } 219 return put_user(status, p);
217 break; 220 case WDIOC_GETBOOTSTATUS:
218 case WDIOC_GETBOOTSTATUS: 221 return put_user(0, p);
219 if (copy_to_user(p, &status, sizeof(int))) { 222 case WDIOC_KEEPALIVE:
220 return -EFAULT; 223 mixcomwd_ping();
221 } 224 break;
222 break; 225 default:
223 case WDIOC_GETSUPPORT: 226 return -ENOTTY;
224 if (copy_to_user(argp, &ident, sizeof(ident))) {
225 return -EFAULT;
226 }
227 break;
228 case WDIOC_KEEPALIVE:
229 mixcomwd_ping();
230 break;
231 default:
232 return -ENOTTY;
233 } 227 }
234 return 0; 228 return 0;
235} 229}
@@ -238,7 +232,7 @@ static const struct file_operations mixcomwd_fops = {
238 .owner = THIS_MODULE, 232 .owner = THIS_MODULE,
239 .llseek = no_llseek, 233 .llseek = no_llseek,
240 .write = mixcomwd_write, 234 .write = mixcomwd_write,
241 .ioctl = mixcomwd_ioctl, 235 .unlocked_ioctl = mixcomwd_ioctl,
242 .open = mixcomwd_open, 236 .open = mixcomwd_open,
243 .release = mixcomwd_release, 237 .release = mixcomwd_release,
244}; 238};
@@ -253,15 +247,14 @@ static int __init checkcard(int port, int card_id)
253{ 247{
254 int id; 248 int id;
255 249
256 if (!request_region(port, 1, "MixCOM watchdog")) { 250 if (!request_region(port, 1, "MixCOM watchdog"))
257 return 0; 251 return 0;
258 }
259 252
260 id=inb_p(port); 253 id = inb_p(port);
261 if (card_id==MIXCOM_ID) 254 if (card_id == MIXCOM_ID)
262 id &= 0x3f; 255 id &= 0x3f;
263 256
264 if (id!=card_id) { 257 if (id != card_id) {
265 release_region(port, 1); 258 release_region(port, 1);
266 return 0; 259 return 0;
267 } 260 }
@@ -270,9 +263,7 @@ static int __init checkcard(int port, int card_id)
270 263
271static int __init mixcomwd_init(void) 264static int __init mixcomwd_init(void)
272{ 265{
273 int i; 266 int i, ret, found = 0;
274 int ret;
275 int found=0;
276 267
277 for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) { 268 for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) {
278 if (checkcard(mixcomwd_io_info[i].ioport, 269 if (checkcard(mixcomwd_io_info[i].ioport,
@@ -283,20 +274,22 @@ static int __init mixcomwd_init(void)
283 } 274 }
284 275
285 if (!found) { 276 if (!found) {
286 printk(KERN_ERR PFX "No card detected, or port not available.\n"); 277 printk(KERN_ERR PFX
278 "No card detected, or port not available.\n");
287 return -ENODEV; 279 return -ENODEV;
288 } 280 }
289 281
290 ret = misc_register(&mixcomwd_miscdev); 282 ret = misc_register(&mixcomwd_miscdev);
291 if (ret) 283 if (ret) {
292 { 284 printk(KERN_ERR PFX
293 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 285 "cannot register miscdev on minor=%d (err=%d)\n",
294 WATCHDOG_MINOR, ret); 286 WATCHDOG_MINOR, ret);
295 goto error_misc_register_watchdog; 287 goto error_misc_register_watchdog;
296 } 288 }
297 289
298 printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n", 290 printk(KERN_INFO
299 VERSION, watchdog_port); 291 "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",
292 VERSION, watchdog_port);
300 293
301 return 0; 294 return 0;
302 295
@@ -309,15 +302,15 @@ error_misc_register_watchdog:
309static void __exit mixcomwd_exit(void) 302static void __exit mixcomwd_exit(void)
310{ 303{
311 if (!nowayout) { 304 if (!nowayout) {
312 if(mixcomwd_timer_alive) { 305 if (mixcomwd_timer_alive) {
313 printk(KERN_WARNING PFX "I quit now, hardware will" 306 printk(KERN_WARNING PFX "I quit now, hardware will"
314 " probably reboot!\n"); 307 " probably reboot!\n");
315 del_timer_sync(&mixcomwd_timer); 308 del_timer_sync(&mixcomwd_timer);
316 mixcomwd_timer_alive=0; 309 mixcomwd_timer_alive = 0;
317 } 310 }
318 } 311 }
319 misc_deregister(&mixcomwd_miscdev); 312 misc_deregister(&mixcomwd_miscdev);
320 release_region(watchdog_port,1); 313 release_region(watchdog_port, 1);
321} 314}
322 315
323module_init(mixcomwd_init); 316module_init(mixcomwd_init);
diff --git a/drivers/watchdog/mpc5200_wdt.c b/drivers/watchdog/mpc5200_wdt.c
index 77c1c2ae2cc2..db91892558f2 100644
--- a/drivers/watchdog/mpc5200_wdt.c
+++ b/drivers/watchdog/mpc5200_wdt.c
@@ -5,7 +5,7 @@
5#include <linux/io.h> 5#include <linux/io.h>
6#include <linux/spinlock.h> 6#include <linux/spinlock.h>
7#include <linux/of_platform.h> 7#include <linux/of_platform.h>
8#include <asm/uaccess.h> 8#include <linux/uaccess.h>
9#include <asm/mpc52xx.h> 9#include <asm/mpc52xx.h>
10 10
11 11
@@ -57,7 +57,8 @@ static int mpc5200_wdt_start(struct mpc5200_wdt *wdt)
57 /* set timeout, with maximum prescaler */ 57 /* set timeout, with maximum prescaler */
58 out_be32(&wdt->regs->count, 0x0 | wdt->count); 58 out_be32(&wdt->regs->count, 0x0 | wdt->count);
59 /* enable watchdog */ 59 /* enable watchdog */
60 out_be32(&wdt->regs->mode, GPT_MODE_CE | GPT_MODE_WDT | GPT_MODE_MS_TIMER); 60 out_be32(&wdt->regs->mode, GPT_MODE_CE | GPT_MODE_WDT |
61 GPT_MODE_MS_TIMER);
61 spin_unlock(&wdt->io_lock); 62 spin_unlock(&wdt->io_lock);
62 63
63 return 0; 64 return 0;
@@ -66,7 +67,8 @@ static int mpc5200_wdt_ping(struct mpc5200_wdt *wdt)
66{ 67{
67 spin_lock(&wdt->io_lock); 68 spin_lock(&wdt->io_lock);
68 /* writing A5 to OCPW resets the watchdog */ 69 /* writing A5 to OCPW resets the watchdog */
69 out_be32(&wdt->regs->mode, 0xA5000000 | (0xffffff & in_be32(&wdt->regs->mode))); 70 out_be32(&wdt->regs->mode, 0xA5000000 |
71 (0xffffff & in_be32(&wdt->regs->mode)));
70 spin_unlock(&wdt->io_lock); 72 spin_unlock(&wdt->io_lock);
71 return 0; 73 return 0;
72} 74}
@@ -92,8 +94,8 @@ static struct watchdog_info mpc5200_wdt_info = {
92 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 94 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
93 .identity = "mpc5200 watchdog on GPT0", 95 .identity = "mpc5200 watchdog on GPT0",
94}; 96};
95static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file, 97static long mpc5200_wdt_ioctl(struct file *file, unsigned int cmd,
96 unsigned int cmd, unsigned long arg) 98 unsigned long arg)
97{ 99{
98 struct mpc5200_wdt *wdt = file->private_data; 100 struct mpc5200_wdt *wdt = file->private_data;
99 int __user *data = (int __user *)arg; 101 int __user *data = (int __user *)arg;
@@ -103,7 +105,7 @@ static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file,
103 switch (cmd) { 105 switch (cmd) {
104 case WDIOC_GETSUPPORT: 106 case WDIOC_GETSUPPORT:
105 ret = copy_to_user(data, &mpc5200_wdt_info, 107 ret = copy_to_user(data, &mpc5200_wdt_info,
106 sizeof(mpc5200_wdt_info)); 108 sizeof(mpc5200_wdt_info));
107 if (ret) 109 if (ret)
108 ret = -EFAULT; 110 ret = -EFAULT;
109 break; 111 break;
@@ -135,6 +137,7 @@ static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file,
135 } 137 }
136 return ret; 138 return ret;
137} 139}
140
138static int mpc5200_wdt_open(struct inode *inode, struct file *file) 141static int mpc5200_wdt_open(struct inode *inode, struct file *file)
139{ 142{
140 /* /dev/watchdog can only be opened once */ 143 /* /dev/watchdog can only be opened once */
@@ -161,13 +164,14 @@ static int mpc5200_wdt_release(struct inode *inode, struct file *file)
161static const struct file_operations mpc5200_wdt_fops = { 164static const struct file_operations mpc5200_wdt_fops = {
162 .owner = THIS_MODULE, 165 .owner = THIS_MODULE,
163 .write = mpc5200_wdt_write, 166 .write = mpc5200_wdt_write,
164 .ioctl = mpc5200_wdt_ioctl, 167 .unlocked_ioctl = mpc5200_wdt_ioctl,
165 .open = mpc5200_wdt_open, 168 .open = mpc5200_wdt_open,
166 .release = mpc5200_wdt_release, 169 .release = mpc5200_wdt_release,
167}; 170};
168 171
169/* module operations */ 172/* module operations */
170static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *match) 173static int mpc5200_wdt_probe(struct of_device *op,
174 const struct of_device_id *match)
171{ 175{
172 struct mpc5200_wdt *wdt; 176 struct mpc5200_wdt *wdt;
173 int err; 177 int err;
@@ -215,9 +219,9 @@ static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *ma
215 return 0; 219 return 0;
216 220
217 iounmap(wdt->regs); 221 iounmap(wdt->regs);
218 out_release: 222out_release:
219 release_mem_region(wdt->mem.start, size); 223 release_mem_region(wdt->mem.start, size);
220 out_free: 224out_free:
221 kfree(wdt); 225 kfree(wdt);
222 return err; 226 return err;
223} 227}
diff --git a/drivers/watchdog/mpc83xx_wdt.c b/drivers/watchdog/mpc83xx_wdt.c
deleted file mode 100644
index b16c5cd972eb..000000000000
--- a/drivers/watchdog/mpc83xx_wdt.c
+++ /dev/null
@@ -1,230 +0,0 @@
1/*
2 * mpc83xx_wdt.c - MPC83xx watchdog userspace interface
3 *
4 * Authors: Dave Updegraff <dave@cray.org>
5 * Kumar Gala <galak@kernel.crashing.org>
6 * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org>
7 * ..and from sc520_wdt
8 *
9 * Note: it appears that you can only actually ENABLE or DISABLE the thing
10 * once after POR. Once enabled, you cannot disable, and vice versa.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 */
17
18#include <linux/fs.h>
19#include <linux/init.h>
20#include <linux/kernel.h>
21#include <linux/miscdevice.h>
22#include <linux/platform_device.h>
23#include <linux/module.h>
24#include <linux/watchdog.h>
25#include <asm/io.h>
26#include <asm/uaccess.h>
27
28struct mpc83xx_wdt {
29 __be32 res0;
30 __be32 swcrr; /* System watchdog control register */
31#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */
32#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */
33#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/
34#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */
35 __be32 swcnr; /* System watchdog count register */
36 u8 res1[2];
37 __be16 swsrr; /* System watchdog service register */
38 u8 res2[0xF0];
39};
40
41static struct mpc83xx_wdt __iomem *wd_base;
42
43static u16 timeout = 0xffff;
44module_param(timeout, ushort, 0);
45MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0<timeout<65536, default=65535");
46
47static int reset = 1;
48module_param(reset, bool, 0);
49MODULE_PARM_DESC(reset, "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");
50
51/*
52 * We always prescale, but if someone really doesn't want to they can set this
53 * to 0
54 */
55static int prescale = 1;
56static unsigned int timeout_sec;
57
58static unsigned long wdt_is_open;
59static DEFINE_SPINLOCK(wdt_spinlock);
60
61static void mpc83xx_wdt_keepalive(void)
62{
63 /* Ping the WDT */
64 spin_lock(&wdt_spinlock);
65 out_be16(&wd_base->swsrr, 0x556c);
66 out_be16(&wd_base->swsrr, 0xaa39);
67 spin_unlock(&wdt_spinlock);
68}
69
70static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf,
71 size_t count, loff_t *ppos)
72{
73 if (count)
74 mpc83xx_wdt_keepalive();
75 return count;
76}
77
78static int mpc83xx_wdt_open(struct inode *inode, struct file *file)
79{
80 u32 tmp = SWCRR_SWEN;
81 if (test_and_set_bit(0, &wdt_is_open))
82 return -EBUSY;
83
84 /* Once we start the watchdog we can't stop it */
85 __module_get(THIS_MODULE);
86
87 /* Good, fire up the show */
88 if (prescale)
89 tmp |= SWCRR_SWPR;
90 if (reset)
91 tmp |= SWCRR_SWRI;
92
93 tmp |= timeout << 16;
94
95 out_be32(&wd_base->swcrr, tmp);
96
97 return nonseekable_open(inode, file);
98}
99
100static int mpc83xx_wdt_release(struct inode *inode, struct file *file)
101{
102 printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
103 mpc83xx_wdt_keepalive();
104 clear_bit(0, &wdt_is_open);
105 return 0;
106}
107
108static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,
109 unsigned int cmd, unsigned long arg)
110{
111 void __user *argp = (void __user *)arg;
112 int __user *p = argp;
113 static struct watchdog_info ident = {
114 .options = WDIOF_KEEPALIVEPING,
115 .firmware_version = 1,
116 .identity = "MPC83xx",
117 };
118
119 switch (cmd) {
120 case WDIOC_GETSUPPORT:
121 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
122 case WDIOC_GETSTATUS:
123 case WDIOC_GETBOOTSTATUS:
124 return put_user(0, p);
125 case WDIOC_KEEPALIVE:
126 mpc83xx_wdt_keepalive();
127 return 0;
128 case WDIOC_GETTIMEOUT:
129 return put_user(timeout_sec, p);
130 default:
131 return -ENOTTY;
132 }
133}
134
135static const struct file_operations mpc83xx_wdt_fops = {
136 .owner = THIS_MODULE,
137 .llseek = no_llseek,
138 .write = mpc83xx_wdt_write,
139 .ioctl = mpc83xx_wdt_ioctl,
140 .open = mpc83xx_wdt_open,
141 .release = mpc83xx_wdt_release,
142};
143
144static struct miscdevice mpc83xx_wdt_miscdev = {
145 .minor = WATCHDOG_MINOR,
146 .name = "watchdog",
147 .fops = &mpc83xx_wdt_fops,
148};
149
150static int __devinit mpc83xx_wdt_probe(struct platform_device *dev)
151{
152 struct resource *r;
153 int ret;
154 unsigned int *freq = dev->dev.platform_data;
155
156 /* get a pointer to the register memory */
157 r = platform_get_resource(dev, IORESOURCE_MEM, 0);
158
159 if (!r) {
160 ret = -ENODEV;
161 goto err_out;
162 }
163
164 wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt));
165
166 if (wd_base == NULL) {
167 ret = -ENOMEM;
168 goto err_out;
169 }
170
171 ret = misc_register(&mpc83xx_wdt_miscdev);
172 if (ret) {
173 printk(KERN_ERR "cannot register miscdev on minor=%d "
174 "(err=%d)\n",
175 WATCHDOG_MINOR, ret);
176 goto err_unmap;
177 }
178
179 /* Calculate the timeout in seconds */
180 if (prescale)
181 timeout_sec = (timeout * 0x10000) / (*freq);
182 else
183 timeout_sec = timeout / (*freq);
184
185 printk(KERN_INFO "WDT driver for MPC83xx initialized. "
186 "mode:%s timeout=%d (%d seconds)\n",
187 reset ? "reset":"interrupt", timeout, timeout_sec);
188 return 0;
189
190err_unmap:
191 iounmap(wd_base);
192err_out:
193 return ret;
194}
195
196static int __devexit mpc83xx_wdt_remove(struct platform_device *dev)
197{
198 misc_deregister(&mpc83xx_wdt_miscdev);
199 iounmap(wd_base);
200
201 return 0;
202}
203
204static struct platform_driver mpc83xx_wdt_driver = {
205 .probe = mpc83xx_wdt_probe,
206 .remove = __devexit_p(mpc83xx_wdt_remove),
207 .driver = {
208 .name = "mpc83xx_wdt",
209 .owner = THIS_MODULE,
210 },
211};
212
213static int __init mpc83xx_wdt_init(void)
214{
215 return platform_driver_register(&mpc83xx_wdt_driver);
216}
217
218static void __exit mpc83xx_wdt_exit(void)
219{
220 platform_driver_unregister(&mpc83xx_wdt_driver);
221}
222
223module_init(mpc83xx_wdt_init);
224module_exit(mpc83xx_wdt_exit);
225
226MODULE_AUTHOR("Dave Updegraff, Kumar Gala");
227MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor");
228MODULE_LICENSE("GPL");
229MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
230MODULE_ALIAS("platform:mpc83xx_wdt");
diff --git a/drivers/watchdog/mpc8xx_wdt.c b/drivers/watchdog/mpc8xx_wdt.c
index 85b5734403a5..1336425acf20 100644
--- a/drivers/watchdog/mpc8xx_wdt.c
+++ b/drivers/watchdog/mpc8xx_wdt.c
@@ -16,36 +16,35 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/watchdog.h> 17#include <linux/watchdog.h>
18#include <asm/8xx_immap.h> 18#include <asm/8xx_immap.h>
19#include <asm/uaccess.h> 19#include <linux/uaccess.h>
20#include <asm/io.h> 20#include <linux/io.h>
21#include <syslib/m8xx_wdt.h> 21#include <syslib/m8xx_wdt.h>
22 22
23static unsigned long wdt_opened; 23static unsigned long wdt_opened;
24static int wdt_status; 24static int wdt_status;
25static spinlock_t wdt_lock;
25 26
26static void mpc8xx_wdt_handler_disable(void) 27static void mpc8xx_wdt_handler_disable(void)
27{ 28{
28 volatile uint __iomem *piscr; 29 volatile uint __iomem *piscr;
29 piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr; 30 piscr = (uint *)&((immap_t *)IMAP_ADDR)->im_sit.sit_piscr;
30 31
31 if (!m8xx_has_internal_rtc) 32 if (!m8xx_has_internal_rtc)
32 m8xx_wdt_stop_timer(); 33 m8xx_wdt_stop_timer();
33 else 34 else
34 out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE)); 35 out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE));
35
36 printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); 36 printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
37} 37}
38 38
39static void mpc8xx_wdt_handler_enable(void) 39static void mpc8xx_wdt_handler_enable(void)
40{ 40{
41 volatile uint __iomem *piscr; 41 volatile uint __iomem *piscr;
42 piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr; 42 piscr = (uint *)&((immap_t *)IMAP_ADDR)->im_sit.sit_piscr;
43 43
44 if (!m8xx_has_internal_rtc) 44 if (!m8xx_has_internal_rtc)
45 m8xx_wdt_install_timer(); 45 m8xx_wdt_install_timer();
46 else 46 else
47 out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE); 47 out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE);
48
49 printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n"); 48 printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
50} 49}
51 50
@@ -53,37 +52,34 @@ static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
53{ 52{
54 if (test_and_set_bit(0, &wdt_opened)) 53 if (test_and_set_bit(0, &wdt_opened))
55 return -EBUSY; 54 return -EBUSY;
56
57 m8xx_wdt_reset(); 55 m8xx_wdt_reset();
58 mpc8xx_wdt_handler_disable(); 56 mpc8xx_wdt_handler_disable();
59
60 return nonseekable_open(inode, file); 57 return nonseekable_open(inode, file);
61} 58}
62 59
63static int mpc8xx_wdt_release(struct inode *inode, struct file *file) 60static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
64{ 61{
65 m8xx_wdt_reset(); 62 m8xx_wdt_reset();
66
67#if !defined(CONFIG_WATCHDOG_NOWAYOUT) 63#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
68 mpc8xx_wdt_handler_enable(); 64 mpc8xx_wdt_handler_enable();
69#endif 65#endif
70
71 clear_bit(0, &wdt_opened); 66 clear_bit(0, &wdt_opened);
72
73 return 0; 67 return 0;
74} 68}
75 69
76static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len, 70static ssize_t mpc8xx_wdt_write(struct file *file, const char *data,
77 loff_t * ppos) 71 size_t len, loff_t *ppos)
78{ 72{
79 if (len) 73 if (len) {
74 spin_lock(&wdt_lock);
80 m8xx_wdt_reset(); 75 m8xx_wdt_reset();
81 76 spin_unlock(&wdt_lock);
77 }
82 return len; 78 return len;
83} 79}
84 80
85static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file, 81static long mpc8xx_wdt_ioctl(struct file *file,
86 unsigned int cmd, unsigned long arg) 82 unsigned int cmd, unsigned long arg)
87{ 83{
88 int timeout; 84 int timeout;
89 static struct watchdog_info info = { 85 static struct watchdog_info info = {
@@ -112,15 +108,19 @@ static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
112 return -EOPNOTSUPP; 108 return -EOPNOTSUPP;
113 109
114 case WDIOC_KEEPALIVE: 110 case WDIOC_KEEPALIVE:
111 spin_lock(&wdt_lock);
115 m8xx_wdt_reset(); 112 m8xx_wdt_reset();
116 wdt_status |= WDIOF_KEEPALIVEPING; 113 wdt_status |= WDIOF_KEEPALIVEPING;
114 spin_unlock(&wdt_lock);
117 break; 115 break;
118 116
119 case WDIOC_SETTIMEOUT: 117 case WDIOC_SETTIMEOUT:
120 return -EOPNOTSUPP; 118 return -EOPNOTSUPP;
121 119
122 case WDIOC_GETTIMEOUT: 120 case WDIOC_GETTIMEOUT:
121 spin_lock(&wdt_lock);
123 timeout = m8xx_wdt_get_timeout(); 122 timeout = m8xx_wdt_get_timeout();
123 spin_unlock(&wdt_lock);
124 if (put_user(timeout, (int *)arg)) 124 if (put_user(timeout, (int *)arg))
125 return -EFAULT; 125 return -EFAULT;
126 break; 126 break;
@@ -136,7 +136,7 @@ static const struct file_operations mpc8xx_wdt_fops = {
136 .owner = THIS_MODULE, 136 .owner = THIS_MODULE,
137 .llseek = no_llseek, 137 .llseek = no_llseek,
138 .write = mpc8xx_wdt_write, 138 .write = mpc8xx_wdt_write,
139 .ioctl = mpc8xx_wdt_ioctl, 139 .unlocked_ioctl = mpc8xx_wdt_ioctl,
140 .open = mpc8xx_wdt_open, 140 .open = mpc8xx_wdt_open,
141 .release = mpc8xx_wdt_release, 141 .release = mpc8xx_wdt_release,
142}; 142};
@@ -149,6 +149,7 @@ static struct miscdevice mpc8xx_wdt_miscdev = {
149 149
150static int __init mpc8xx_wdt_init(void) 150static int __init mpc8xx_wdt_init(void)
151{ 151{
152 spin_lock_init(&wdt_lock);
152 return misc_register(&mpc8xx_wdt_miscdev); 153 return misc_register(&mpc8xx_wdt_miscdev);
153} 154}
154 155
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
new file mode 100644
index 000000000000..f2094960e662
--- /dev/null
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -0,0 +1,316 @@
1/*
2 * mpc8xxx_wdt.c - MPC8xx/MPC83xx/MPC86xx watchdog userspace interface
3 *
4 * Authors: Dave Updegraff <dave@cray.org>
5 * Kumar Gala <galak@kernel.crashing.org>
6 * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org>
7 * ..and from sc520_wdt
8 * Copyright (c) 2008 MontaVista Software, Inc.
9 * Anton Vorontsov <avorontsov@ru.mvista.com>
10 *
11 * Note: it appears that you can only actually ENABLE or DISABLE the thing
12 * once after POR. Once enabled, you cannot disable, and vice versa.
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 as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
18 */
19
20#include <linux/fs.h>
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/timer.h>
24#include <linux/miscdevice.h>
25#include <linux/of_platform.h>
26#include <linux/module.h>
27#include <linux/watchdog.h>
28#include <linux/io.h>
29#include <linux/uaccess.h>
30#include <sysdev/fsl_soc.h>
31
32struct mpc8xxx_wdt {
33 __be32 res0;
34 __be32 swcrr; /* System watchdog control register */
35#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */
36#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */
37#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/
38#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */
39 __be32 swcnr; /* System watchdog count register */
40 u8 res1[2];
41 __be16 swsrr; /* System watchdog service register */
42 u8 res2[0xF0];
43};
44
45struct mpc8xxx_wdt_type {
46 int prescaler;
47 bool hw_enabled;
48};
49
50static struct mpc8xxx_wdt __iomem *wd_base;
51
52static u16 timeout = 0xffff;
53module_param(timeout, ushort, 0);
54MODULE_PARM_DESC(timeout,
55 "Watchdog timeout in ticks. (0<timeout<65536, default=65535");
56
57static int reset = 1;
58module_param(reset, bool, 0);
59MODULE_PARM_DESC(reset,
60 "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");
61
62static int nowayout = WATCHDOG_NOWAYOUT;
63module_param(nowayout, int, 0);
64MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
65 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
66
67/*
68 * We always prescale, but if someone really doesn't want to they can set this
69 * to 0
70 */
71static int prescale = 1;
72static unsigned int timeout_sec;
73
74static unsigned long wdt_is_open;
75static DEFINE_SPINLOCK(wdt_spinlock);
76
77static void mpc8xxx_wdt_keepalive(void)
78{
79 /* Ping the WDT */
80 spin_lock(&wdt_spinlock);
81 out_be16(&wd_base->swsrr, 0x556c);
82 out_be16(&wd_base->swsrr, 0xaa39);
83 spin_unlock(&wdt_spinlock);
84}
85
86static void mpc8xxx_wdt_timer_ping(unsigned long arg);
87static DEFINE_TIMER(wdt_timer, mpc8xxx_wdt_timer_ping, 0, 0);
88
89static void mpc8xxx_wdt_timer_ping(unsigned long arg)
90{
91 mpc8xxx_wdt_keepalive();
92 /* We're pinging it twice faster than needed, just to be sure. */
93 mod_timer(&wdt_timer, jiffies + HZ * timeout_sec / 2);
94}
95
96static void mpc8xxx_wdt_pr_warn(const char *msg)
97{
98 pr_crit("mpc8xxx_wdt: %s, expect the %s soon!\n", msg,
99 reset ? "reset" : "machine check exception");
100}
101
102static ssize_t mpc8xxx_wdt_write(struct file *file, const char __user *buf,
103 size_t count, loff_t *ppos)
104{
105 if (count)
106 mpc8xxx_wdt_keepalive();
107 return count;
108}
109
110static int mpc8xxx_wdt_open(struct inode *inode, struct file *file)
111{
112 u32 tmp = SWCRR_SWEN;
113 if (test_and_set_bit(0, &wdt_is_open))
114 return -EBUSY;
115
116 /* Once we start the watchdog we can't stop it */
117 if (nowayout)
118 __module_get(THIS_MODULE);
119
120 /* Good, fire up the show */
121 if (prescale)
122 tmp |= SWCRR_SWPR;
123 if (reset)
124 tmp |= SWCRR_SWRI;
125
126 tmp |= timeout << 16;
127
128 out_be32(&wd_base->swcrr, tmp);
129
130 del_timer_sync(&wdt_timer);
131
132 return nonseekable_open(inode, file);
133}
134
135static int mpc8xxx_wdt_release(struct inode *inode, struct file *file)
136{
137 if (!nowayout)
138 mpc8xxx_wdt_timer_ping(0);
139 else
140 mpc8xxx_wdt_pr_warn("watchdog closed");
141 clear_bit(0, &wdt_is_open);
142 return 0;
143}
144
145static long mpc8xxx_wdt_ioctl(struct file *file, unsigned int cmd,
146 unsigned long arg)
147{
148 void __user *argp = (void __user *)arg;
149 int __user *p = argp;
150 static struct watchdog_info ident = {
151 .options = WDIOF_KEEPALIVEPING,
152 .firmware_version = 1,
153 .identity = "MPC8xxx",
154 };
155
156 switch (cmd) {
157 case WDIOC_GETSUPPORT:
158 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
159 case WDIOC_GETSTATUS:
160 case WDIOC_GETBOOTSTATUS:
161 return put_user(0, p);
162 case WDIOC_KEEPALIVE:
163 mpc8xxx_wdt_keepalive();
164 return 0;
165 case WDIOC_GETTIMEOUT:
166 return put_user(timeout_sec, p);
167 default:
168 return -ENOTTY;
169 }
170}
171
172static const struct file_operations mpc8xxx_wdt_fops = {
173 .owner = THIS_MODULE,
174 .llseek = no_llseek,
175 .write = mpc8xxx_wdt_write,
176 .unlocked_ioctl = mpc8xxx_wdt_ioctl,
177 .open = mpc8xxx_wdt_open,
178 .release = mpc8xxx_wdt_release,
179};
180
181static struct miscdevice mpc8xxx_wdt_miscdev = {
182 .minor = WATCHDOG_MINOR,
183 .name = "watchdog",
184 .fops = &mpc8xxx_wdt_fops,
185};
186
187static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev,
188 const struct of_device_id *match)
189{
190 int ret;
191 struct device_node *np = ofdev->node;
192 struct mpc8xxx_wdt_type *wdt_type = match->data;
193 u32 freq = fsl_get_sys_freq();
194 bool enabled;
195
196 if (!freq || freq == -1)
197 return -EINVAL;
198
199 wd_base = of_iomap(np, 0);
200 if (!wd_base)
201 return -ENOMEM;
202
203 enabled = in_be32(&wd_base->swcrr) & SWCRR_SWEN;
204 if (!enabled && wdt_type->hw_enabled) {
205 pr_info("mpc8xxx_wdt: could not be enabled in software\n");
206 ret = -ENOSYS;
207 goto err_unmap;
208 }
209
210 /* Calculate the timeout in seconds */
211 if (prescale)
212 timeout_sec = (timeout * wdt_type->prescaler) / freq;
213 else
214 timeout_sec = timeout / freq;
215
216 pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d "
217 "(%d seconds)\n", reset ? "reset" : "interrupt", timeout,
218 timeout_sec);
219
220 /*
221 * If the watchdog was previously enabled or we're running on
222 * MPC8xxx, we should ping the wdt from the kernel until the
223 * userspace handles it.
224 */
225 if (enabled)
226 mpc8xxx_wdt_timer_ping(0);
227 return 0;
228err_unmap:
229 iounmap(wd_base);
230 wd_base = NULL;
231 return ret;
232}
233
234static int __devexit mpc8xxx_wdt_remove(struct of_device *ofdev)
235{
236 mpc8xxx_wdt_pr_warn("watchdog removed");
237 del_timer_sync(&wdt_timer);
238 misc_deregister(&mpc8xxx_wdt_miscdev);
239 iounmap(wd_base);
240
241 return 0;
242}
243
244static const struct of_device_id mpc8xxx_wdt_match[] = {
245 {
246 .compatible = "mpc83xx_wdt",
247 .data = &(struct mpc8xxx_wdt_type) {
248 .prescaler = 0x10000,
249 },
250 },
251 {
252 .compatible = "fsl,mpc8610-wdt",
253 .data = &(struct mpc8xxx_wdt_type) {
254 .prescaler = 0x10000,
255 .hw_enabled = true,
256 },
257 },
258 {
259 .compatible = "fsl,mpc823-wdt",
260 .data = &(struct mpc8xxx_wdt_type) {
261 .prescaler = 0x800,
262 },
263 },
264 {},
265};
266MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match);
267
268static struct of_platform_driver mpc8xxx_wdt_driver = {
269 .match_table = mpc8xxx_wdt_match,
270 .probe = mpc8xxx_wdt_probe,
271 .remove = __devexit_p(mpc8xxx_wdt_remove),
272 .driver = {
273 .name = "mpc8xxx_wdt",
274 .owner = THIS_MODULE,
275 },
276};
277
278/*
279 * We do wdt initialization in two steps: arch_initcall probes the wdt
280 * very early to start pinging the watchdog (misc devices are not yet
281 * available), and later module_init() just registers the misc device.
282 */
283static int __init mpc8xxx_wdt_init_late(void)
284{
285 int ret;
286
287 if (!wd_base)
288 return -ENODEV;
289
290 ret = misc_register(&mpc8xxx_wdt_miscdev);
291 if (ret) {
292 pr_err("cannot register miscdev on minor=%d (err=%d)\n",
293 WATCHDOG_MINOR, ret);
294 return ret;
295 }
296 return 0;
297}
298module_init(mpc8xxx_wdt_init_late);
299
300static int __init mpc8xxx_wdt_init(void)
301{
302 return of_register_platform_driver(&mpc8xxx_wdt_driver);
303}
304arch_initcall(mpc8xxx_wdt_init);
305
306static void __exit mpc8xxx_wdt_exit(void)
307{
308 of_unregister_platform_driver(&mpc8xxx_wdt_driver);
309}
310module_exit(mpc8xxx_wdt_exit);
311
312MODULE_AUTHOR("Dave Updegraff, Kumar Gala");
313MODULE_DESCRIPTION("Driver for watchdog timer in MPC8xx/MPC83xx/MPC86xx "
314 "uProcessors");
315MODULE_LICENSE("GPL");
316MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index 009573b81496..2a9bfa81f9d6 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -29,9 +29,9 @@
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/interrupt.h> 30#include <linux/interrupt.h>
31#include <linux/platform_device.h> 31#include <linux/platform_device.h>
32#include <linux/uaccess.h>
32 33
33#include <asm/hardware/arm_twd.h> 34#include <asm/hardware/arm_twd.h>
34#include <asm/uaccess.h>
35 35
36struct mpcore_wdt { 36struct mpcore_wdt {
37 unsigned long timer_alive; 37 unsigned long timer_alive;
@@ -43,17 +43,20 @@ struct mpcore_wdt {
43}; 43};
44 44
45static struct platform_device *mpcore_wdt_dev; 45static struct platform_device *mpcore_wdt_dev;
46
47extern unsigned int mpcore_timer_rate; 46extern unsigned int mpcore_timer_rate;
48 47
49#define TIMER_MARGIN 60 48#define TIMER_MARGIN 60
50static int mpcore_margin = TIMER_MARGIN; 49static int mpcore_margin = TIMER_MARGIN;
51module_param(mpcore_margin, int, 0); 50module_param(mpcore_margin, int, 0);
52MODULE_PARM_DESC(mpcore_margin, "MPcore timer margin in seconds. (0<mpcore_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")"); 51MODULE_PARM_DESC(mpcore_margin,
52 "MPcore timer margin in seconds. (0 < mpcore_margin < 65536, default="
53 __MODULE_STRING(TIMER_MARGIN) ")");
53 54
54static int nowayout = WATCHDOG_NOWAYOUT; 55static int nowayout = WATCHDOG_NOWAYOUT;
55module_param(nowayout, int, 0); 56module_param(nowayout, int, 0);
56MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 57MODULE_PARM_DESC(nowayout,
58 "Watchdog cannot be stopped once started (default="
59 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
57 60
58#define ONLY_TESTING 0 61#define ONLY_TESTING 0
59static int mpcore_noboot = ONLY_TESTING; 62static int mpcore_noboot = ONLY_TESTING;
@@ -70,14 +73,12 @@ static irqreturn_t mpcore_wdt_fire(int irq, void *arg)
70 73
71 /* Check it really was our interrupt */ 74 /* Check it really was our interrupt */
72 if (readl(wdt->base + TWD_WDOG_INTSTAT)) { 75 if (readl(wdt->base + TWD_WDOG_INTSTAT)) {
73 dev_printk(KERN_CRIT, wdt->dev, "Triggered - Reboot ignored.\n"); 76 dev_printk(KERN_CRIT, wdt->dev,
74 77 "Triggered - Reboot ignored.\n");
75 /* Clear the interrupt on the watchdog */ 78 /* Clear the interrupt on the watchdog */
76 writel(1, wdt->base + TWD_WDOG_INTSTAT); 79 writel(1, wdt->base + TWD_WDOG_INTSTAT);
77
78 return IRQ_HANDLED; 80 return IRQ_HANDLED;
79 } 81 }
80
81 return IRQ_NONE; 82 return IRQ_NONE;
82} 83}
83 84
@@ -96,22 +97,26 @@ static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
96 count = (mpcore_timer_rate / 256) * mpcore_margin; 97 count = (mpcore_timer_rate / 256) * mpcore_margin;
97 98
98 /* Reload the counter */ 99 /* Reload the counter */
100 spin_lock(&wdt_lock);
99 writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); 101 writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
100
101 wdt->perturb = wdt->perturb ? 0 : 1; 102 wdt->perturb = wdt->perturb ? 0 : 1;
103 spin_unlock(&wdt_lock);
102} 104}
103 105
104static void mpcore_wdt_stop(struct mpcore_wdt *wdt) 106static void mpcore_wdt_stop(struct mpcore_wdt *wdt)
105{ 107{
108 spin_lock(&wdt_lock);
106 writel(0x12345678, wdt->base + TWD_WDOG_DISABLE); 109 writel(0x12345678, wdt->base + TWD_WDOG_DISABLE);
107 writel(0x87654321, wdt->base + TWD_WDOG_DISABLE); 110 writel(0x87654321, wdt->base + TWD_WDOG_DISABLE);
108 writel(0x0, wdt->base + TWD_WDOG_CONTROL); 111 writel(0x0, wdt->base + TWD_WDOG_CONTROL);
112 spin_unlock(&wdt_lock);
109} 113}
110 114
111static void mpcore_wdt_start(struct mpcore_wdt *wdt) 115static void mpcore_wdt_start(struct mpcore_wdt *wdt)
112{ 116{
113 dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); 117 dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
114 118
119 spin_lock(&wdt_lock);
115 /* This loads the count register but does NOT start the count yet */ 120 /* This loads the count register but does NOT start the count yet */
116 mpcore_wdt_keepalive(wdt); 121 mpcore_wdt_keepalive(wdt);
117 122
@@ -122,6 +127,7 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt)
122 /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ 127 /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
123 writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); 128 writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
124 } 129 }
130 spin_unlock(&wdt_lock);
125} 131}
126 132
127static int mpcore_wdt_set_heartbeat(int t) 133static int mpcore_wdt_set_heartbeat(int t)
@@ -164,10 +170,11 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file)
164 * Shut off the timer. 170 * Shut off the timer.
165 * Lock it in if it's a module and we set nowayout 171 * Lock it in if it's a module and we set nowayout
166 */ 172 */
167 if (wdt->expect_close == 42) { 173 if (wdt->expect_close == 42)
168 mpcore_wdt_stop(wdt); 174 mpcore_wdt_stop(wdt);
169 } else { 175 else {
170 dev_printk(KERN_CRIT, wdt->dev, "unexpected close, not stopping watchdog!\n"); 176 dev_printk(KERN_CRIT, wdt->dev,
177 "unexpected close, not stopping watchdog!\n");
171 mpcore_wdt_keepalive(wdt); 178 mpcore_wdt_keepalive(wdt);
172 } 179 }
173 clear_bit(0, &wdt->timer_alive); 180 clear_bit(0, &wdt->timer_alive);
@@ -175,7 +182,8 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file)
175 return 0; 182 return 0;
176} 183}
177 184
178static ssize_t mpcore_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) 185static ssize_t mpcore_wdt_write(struct file *file, const char *data,
186 size_t len, loff_t *ppos)
179{ 187{
180 struct mpcore_wdt *wdt = file->private_data; 188 struct mpcore_wdt *wdt = file->private_data;
181 189
@@ -210,8 +218,8 @@ static struct watchdog_info ident = {
210 .identity = "MPcore Watchdog", 218 .identity = "MPcore Watchdog",
211}; 219};
212 220
213static int mpcore_wdt_ioctl(struct inode *inode, struct file *file, 221static long mpcore_wdt_ioctl(struct file *file, unsigned int cmd,
214 unsigned int cmd, unsigned long arg) 222 unsigned long arg)
215{ 223{
216 struct mpcore_wdt *wdt = file->private_data; 224 struct mpcore_wdt *wdt = file->private_data;
217 int ret; 225 int ret;
@@ -235,6 +243,12 @@ static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
235 ret = 0; 243 ret = 0;
236 break; 244 break;
237 245
246 case WDIOC_GETSTATUS:
247 case WDIOC_GETBOOTSTATUS:
248 uarg.i = 0;
249 ret = 0;
250 break;
251
238 case WDIOC_SETOPTIONS: 252 case WDIOC_SETOPTIONS:
239 ret = -EINVAL; 253 ret = -EINVAL;
240 if (uarg.i & WDIOS_DISABLECARD) { 254 if (uarg.i & WDIOS_DISABLECARD) {
@@ -247,12 +261,6 @@ static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
247 } 261 }
248 break; 262 break;
249 263
250 case WDIOC_GETSTATUS:
251 case WDIOC_GETBOOTSTATUS:
252 uarg.i = 0;
253 ret = 0;
254 break;
255
256 case WDIOC_KEEPALIVE: 264 case WDIOC_KEEPALIVE:
257 mpcore_wdt_keepalive(wdt); 265 mpcore_wdt_keepalive(wdt);
258 ret = 0; 266 ret = 0;
@@ -301,7 +309,7 @@ static const struct file_operations mpcore_wdt_fops = {
301 .owner = THIS_MODULE, 309 .owner = THIS_MODULE,
302 .llseek = no_llseek, 310 .llseek = no_llseek,
303 .write = mpcore_wdt_write, 311 .write = mpcore_wdt_write,
304 .ioctl = mpcore_wdt_ioctl, 312 .unlocked_ioctl = mpcore_wdt_ioctl,
305 .open = mpcore_wdt_open, 313 .open = mpcore_wdt_open,
306 .release = mpcore_wdt_release, 314 .release = mpcore_wdt_release,
307}; 315};
@@ -349,14 +357,17 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev)
349 mpcore_wdt_miscdev.parent = &dev->dev; 357 mpcore_wdt_miscdev.parent = &dev->dev;
350 ret = misc_register(&mpcore_wdt_miscdev); 358 ret = misc_register(&mpcore_wdt_miscdev);
351 if (ret) { 359 if (ret) {
352 dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n", 360 dev_printk(KERN_ERR, _dev,
353 WATCHDOG_MINOR, ret); 361 "cannot register miscdev on minor=%d (err=%d)\n",
362 WATCHDOG_MINOR, ret);
354 goto err_misc; 363 goto err_misc;
355 } 364 }
356 365
357 ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, "mpcore_wdt", wdt); 366 ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED,
367 "mpcore_wdt", wdt);
358 if (ret) { 368 if (ret) {
359 dev_printk(KERN_ERR, _dev, "cannot register IRQ%d for watchdog\n", wdt->irq); 369 dev_printk(KERN_ERR, _dev,
370 "cannot register IRQ%d for watchdog\n", wdt->irq);
360 goto err_irq; 371 goto err_irq;
361 } 372 }
362 373
@@ -366,13 +377,13 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev)
366 377
367 return 0; 378 return 0;
368 379
369 err_irq: 380err_irq:
370 misc_deregister(&mpcore_wdt_miscdev); 381 misc_deregister(&mpcore_wdt_miscdev);
371 err_misc: 382err_misc:
372 iounmap(wdt->base); 383 iounmap(wdt->base);
373 err_free: 384err_free:
374 kfree(wdt); 385 kfree(wdt);
375 err_out: 386err_out:
376 return ret; 387 return ret;
377} 388}
378 389
@@ -415,7 +426,7 @@ static int __init mpcore_wdt_init(void)
415 */ 426 */
416 if (mpcore_wdt_set_heartbeat(mpcore_margin)) { 427 if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
417 mpcore_wdt_set_heartbeat(TIMER_MARGIN); 428 mpcore_wdt_set_heartbeat(TIMER_MARGIN);
418 printk(KERN_INFO "mpcore_margin value must be 0<mpcore_margin<65536, using %d\n", 429 printk(KERN_INFO "mpcore_margin value must be 0 < mpcore_margin < 65536, using %d\n",
419 TIMER_MARGIN); 430 TIMER_MARGIN);
420 } 431 }
421 432
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index a8e67383784e..b4b7b0a4c119 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -1,7 +1,8 @@
1/* 1/*
2 * Driver for the MTX-1 Watchdog. 2 * Driver for the MTX-1 Watchdog.
3 * 3 *
4 * (C) Copyright 2005 4G Systems <info@4g-systems.biz>, All Rights Reserved. 4 * (C) Copyright 2005 4G Systems <info@4g-systems.biz>,
5 * All Rights Reserved.
5 * http://www.4g-systems.biz 6 * http://www.4g-systems.biz
6 * 7 *
7 * (C) Copyright 2007 OpenWrt.org, Florian Fainelli <florian@openwrt.org> 8 * (C) Copyright 2007 OpenWrt.org, Florian Fainelli <florian@openwrt.org>
@@ -46,12 +47,11 @@
46#include <linux/jiffies.h> 47#include <linux/jiffies.h>
47#include <linux/watchdog.h> 48#include <linux/watchdog.h>
48#include <linux/platform_device.h> 49#include <linux/platform_device.h>
49 50#include <linux/io.h>
50#include <asm/io.h> 51#include <linux/uaccess.h>
51#include <asm/uaccess.h> 52#include <linux/gpio.h>
52 53
53#include <asm/mach-au1x00/au1000.h> 54#include <asm/mach-au1x00/au1000.h>
54#include <asm/gpio.h>
55 55
56#define MTX1_WDT_INTERVAL (5 * HZ) 56#define MTX1_WDT_INTERVAL (5 * HZ)
57 57
@@ -59,6 +59,7 @@ static int ticks = 100 * HZ;
59 59
60static struct { 60static struct {
61 struct completion stop; 61 struct completion stop;
62 spinlock_t lock;
62 int running; 63 int running;
63 struct timer_list timer; 64 struct timer_list timer;
64 int queue; 65 int queue;
@@ -71,6 +72,7 @@ static void mtx1_wdt_trigger(unsigned long unused)
71{ 72{
72 u32 tmp; 73 u32 tmp;
73 74
75 spin_lock(&mtx1_wdt_device.lock);
74 if (mtx1_wdt_device.running) 76 if (mtx1_wdt_device.running)
75 ticks--; 77 ticks--;
76 /* 78 /*
@@ -79,13 +81,13 @@ static void mtx1_wdt_trigger(unsigned long unused)
79 tmp = au_readl(GPIO2_DIR); 81 tmp = au_readl(GPIO2_DIR);
80 tmp = (tmp & ~(1 << mtx1_wdt_device.gpio)) | 82 tmp = (tmp & ~(1 << mtx1_wdt_device.gpio)) |
81 ((~tmp) & (1 << mtx1_wdt_device.gpio)); 83 ((~tmp) & (1 << mtx1_wdt_device.gpio));
82 au_writel (tmp, GPIO2_DIR); 84 au_writel(tmp, GPIO2_DIR);
83 85
84 if (mtx1_wdt_device.queue && ticks) 86 if (mtx1_wdt_device.queue && ticks)
85 mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); 87 mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
86 else { 88 else
87 complete(&mtx1_wdt_device.stop); 89 complete(&mtx1_wdt_device.stop);
88 } 90 spin_unlock(&mtx1_wdt_device.lock);
89} 91}
90 92
91static void mtx1_wdt_reset(void) 93static void mtx1_wdt_reset(void)
@@ -96,23 +98,25 @@ static void mtx1_wdt_reset(void)
96 98
97static void mtx1_wdt_start(void) 99static void mtx1_wdt_start(void)
98{ 100{
101 spin_lock_irqsave(&mtx1_wdt_device.lock, flags);
99 if (!mtx1_wdt_device.queue) { 102 if (!mtx1_wdt_device.queue) {
100 mtx1_wdt_device.queue = 1; 103 mtx1_wdt_device.queue = 1;
101 gpio_set_value(mtx1_wdt_device.gpio, 1); 104 gpio_set_value(mtx1_wdt_device.gpio, 1);
102 mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); 105 mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
103 } 106 }
104 mtx1_wdt_device.running++; 107 mtx1_wdt_device.running++;
108 spin_unlock_irqrestore(&mtx1_wdt_device.lock, flags);
105} 109}
106 110
107static int mtx1_wdt_stop(void) 111static int mtx1_wdt_stop(void)
108{ 112{
113 spin_lock_irqsave(&mtx1_wdt_device.lock, flags);
109 if (mtx1_wdt_device.queue) { 114 if (mtx1_wdt_device.queue) {
110 mtx1_wdt_device.queue = 0; 115 mtx1_wdt_device.queue = 0;
111 gpio_set_value(mtx1_wdt_device.gpio, 0); 116 gpio_set_value(mtx1_wdt_device.gpio, 0);
112 } 117 }
113
114 ticks = mtx1_wdt_device.default_ticks; 118 ticks = mtx1_wdt_device.default_ticks;
115 119 spin_unlock_irqrestore(&mtx1_wdt_device.lock, flags);
116 return 0; 120 return 0;
117} 121}
118 122
@@ -122,7 +126,6 @@ static int mtx1_wdt_open(struct inode *inode, struct file *file)
122{ 126{
123 if (test_and_set_bit(0, &mtx1_wdt_device.inuse)) 127 if (test_and_set_bit(0, &mtx1_wdt_device.inuse))
124 return -EBUSY; 128 return -EBUSY;
125
126 return nonseekable_open(inode, file); 129 return nonseekable_open(inode, file);
127} 130}
128 131
@@ -133,54 +136,51 @@ static int mtx1_wdt_release(struct inode *inode, struct file *file)
133 return 0; 136 return 0;
134} 137}
135 138
136static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 139static long mtx1_wdt_ioctl(struct file *file, unsigned int cmd,
140 unsigned long arg)
137{ 141{
138 void __user *argp = (void __user *)arg; 142 void __user *argp = (void __user *)arg;
143 int __user *p = (int __user *)argp;
139 unsigned int value; 144 unsigned int value;
140 static struct watchdog_info ident = 145 static const struct watchdog_info ident = {
141 {
142 .options = WDIOF_CARDRESET, 146 .options = WDIOF_CARDRESET,
143 .identity = "MTX-1 WDT", 147 .identity = "MTX-1 WDT",
144 }; 148 };
145 149
146 switch(cmd) { 150 switch (cmd) {
147 case WDIOC_KEEPALIVE: 151 case WDIOC_GETSUPPORT:
148 mtx1_wdt_reset(); 152 if (copy_to_user(argp, &ident, sizeof(ident)))
149 break; 153 return -EFAULT;
150 case WDIOC_GETSTATUS: 154 break;
151 case WDIOC_GETBOOTSTATUS: 155 case WDIOC_GETSTATUS:
152 if ( copy_to_user(argp, &value, sizeof(int)) ) 156 case WDIOC_GETBOOTSTATUS:
153 return -EFAULT; 157 put_user(0, p);
154 break; 158 break;
155 case WDIOC_GETSUPPORT: 159 case WDIOC_SETOPTIONS:
156 if ( copy_to_user(argp, &ident, sizeof(ident)) ) 160 if (get_user(value, p))
157 return -EFAULT; 161 return -EFAULT;
158 break; 162 if (value & WDIOS_ENABLECARD)
159 case WDIOC_SETOPTIONS: 163 mtx1_wdt_start();
160 if ( copy_from_user(&value, argp, sizeof(int)) ) 164 else if (value & WDIOS_DISABLECARD)
161 return -EFAULT; 165 mtx1_wdt_stop();
162 switch(value) { 166 else
163 case WDIOS_ENABLECARD: 167 return -EINVAL;
164 mtx1_wdt_start(); 168 return 0;
165 break; 169 case WDIOC_KEEPALIVE:
166 case WDIOS_DISABLECARD: 170 mtx1_wdt_reset();
167 return mtx1_wdt_stop(); 171 break;
168 default: 172 default:
169 return -EINVAL; 173 return -ENOTTY;
170 }
171 break;
172 default:
173 return -ENOTTY;
174 } 174 }
175 return 0; 175 return 0;
176} 176}
177 177
178 178
179static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) 179static ssize_t mtx1_wdt_write(struct file *file, const char *buf,
180 size_t count, loff_t *ppos)
180{ 181{
181 if (!count) 182 if (!count)
182 return -EIO; 183 return -EIO;
183
184 mtx1_wdt_reset(); 184 mtx1_wdt_reset();
185 return count; 185 return count;
186} 186}
@@ -188,17 +188,17 @@ static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count,
188static const struct file_operations mtx1_wdt_fops = { 188static const struct file_operations mtx1_wdt_fops = {
189 .owner = THIS_MODULE, 189 .owner = THIS_MODULE,
190 .llseek = no_llseek, 190 .llseek = no_llseek,
191 .ioctl = mtx1_wdt_ioctl, 191 .unlocked_ioctl = mtx1_wdt_ioctl,
192 .open = mtx1_wdt_open, 192 .open = mtx1_wdt_open,
193 .write = mtx1_wdt_write, 193 .write = mtx1_wdt_write,
194 .release = mtx1_wdt_release 194 .release = mtx1_wdt_release,
195}; 195};
196 196
197 197
198static struct miscdevice mtx1_wdt_misc = { 198static struct miscdevice mtx1_wdt_misc = {
199 .minor = WATCHDOG_MINOR, 199 .minor = WATCHDOG_MINOR,
200 .name = "watchdog", 200 .name = "watchdog",
201 .fops = &mtx1_wdt_fops 201 .fops = &mtx1_wdt_fops,
202}; 202};
203 203
204 204
@@ -208,29 +208,26 @@ static int mtx1_wdt_probe(struct platform_device *pdev)
208 208
209 mtx1_wdt_device.gpio = pdev->resource[0].start; 209 mtx1_wdt_device.gpio = pdev->resource[0].start;
210 210
211 if ((ret = misc_register(&mtx1_wdt_misc)) < 0) { 211 spin_lock_init(&mtx1_wdt_device.lock);
212 printk(KERN_ERR " mtx-1_wdt : failed to register\n");
213 return ret;
214 }
215
216 init_completion(&mtx1_wdt_device.stop); 212 init_completion(&mtx1_wdt_device.stop);
217 mtx1_wdt_device.queue = 0; 213 mtx1_wdt_device.queue = 0;
218
219 clear_bit(0, &mtx1_wdt_device.inuse); 214 clear_bit(0, &mtx1_wdt_device.inuse);
220
221 setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L); 215 setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L);
222
223 mtx1_wdt_device.default_ticks = ticks; 216 mtx1_wdt_device.default_ticks = ticks;
224 217
218 ret = misc_register(&mtx1_wdt_misc);
219 if (ret < 0) {
220 printk(KERN_ERR " mtx-1_wdt : failed to register\n");
221 return ret;
222 }
225 mtx1_wdt_start(); 223 mtx1_wdt_start();
226
227 printk(KERN_INFO "MTX-1 Watchdog driver\n"); 224 printk(KERN_INFO "MTX-1 Watchdog driver\n");
228
229 return 0; 225 return 0;
230} 226}
231 227
232static int mtx1_wdt_remove(struct platform_device *pdev) 228static int mtx1_wdt_remove(struct platform_device *pdev)
233{ 229{
230 /* FIXME: do we need to lock this test ? */
234 if (mtx1_wdt_device.queue) { 231 if (mtx1_wdt_device.queue) {
235 mtx1_wdt_device.queue = 0; 232 mtx1_wdt_device.queue = 0;
236 wait_for_completion(&mtx1_wdt_device.stop); 233 wait_for_completion(&mtx1_wdt_device.stop);
diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c
index b59ca3273967..acf589dc057c 100644
--- a/drivers/watchdog/mv64x60_wdt.c
+++ b/drivers/watchdog/mv64x60_wdt.c
@@ -8,7 +8,7 @@
8 * and services the watchdog. 8 * and services the watchdog.
9 * 9 *
10 * Derived from mpc8xx_wdt.c, with the following copyright. 10 * Derived from mpc8xx_wdt.c, with the following copyright.
11 * 11 *
12 * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under 12 * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
13 * the terms of the GNU General Public License version 2. This program 13 * the terms of the GNU General Public License version 2. This program
14 * is licensed "as is" without any warranty of any kind, whether express 14 * is licensed "as is" without any warranty of any kind, whether express
@@ -22,10 +22,9 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/watchdog.h> 23#include <linux/watchdog.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25
26#include <linux/mv643xx.h> 25#include <linux/mv643xx.h>
27#include <asm/uaccess.h> 26#include <linux/uaccess.h>
28#include <asm/io.h> 27#include <linux/io.h>
29 28
30#define MV64x60_WDT_WDC_OFFSET 0 29#define MV64x60_WDT_WDC_OFFSET 0
31 30
@@ -61,7 +60,9 @@ static DEFINE_SPINLOCK(mv64x60_wdt_spinlock);
61 60
62static int nowayout = WATCHDOG_NOWAYOUT; 61static int nowayout = WATCHDOG_NOWAYOUT;
63module_param(nowayout, int, 0); 62module_param(nowayout, int, 0);
64MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 63MODULE_PARM_DESC(nowayout,
64 "Watchdog cannot be stopped once started (default="
65 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
65 66
66static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift) 67static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift)
67{ 68{
@@ -150,7 +151,7 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file)
150} 151}
151 152
152static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, 153static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
153 size_t len, loff_t * ppos) 154 size_t len, loff_t *ppos)
154{ 155{
155 if (len) { 156 if (len) {
156 if (!nowayout) { 157 if (!nowayout) {
@@ -160,7 +161,7 @@ static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
160 161
161 for (i = 0; i != len; i++) { 162 for (i = 0; i != len; i++) {
162 char c; 163 char c;
163 if(get_user(c, data + i)) 164 if (get_user(c, data + i))
164 return -EFAULT; 165 return -EFAULT;
165 if (c == 'V') 166 if (c == 'V')
166 expect_close = 42; 167 expect_close = 42;
@@ -172,8 +173,8 @@ static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
172 return len; 173 return len;
173} 174}
174 175
175static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, 176static long mv64x60_wdt_ioctl(struct file *file,
176 unsigned int cmd, unsigned long arg) 177 unsigned int cmd, unsigned long arg)
177{ 178{
178 int timeout; 179 int timeout;
179 int options; 180 int options;
@@ -240,7 +241,7 @@ static const struct file_operations mv64x60_wdt_fops = {
240 .owner = THIS_MODULE, 241 .owner = THIS_MODULE,
241 .llseek = no_llseek, 242 .llseek = no_llseek,
242 .write = mv64x60_wdt_write, 243 .write = mv64x60_wdt_write,
243 .ioctl = mv64x60_wdt_ioctl, 244 .unlocked_ioctl = mv64x60_wdt_ioctl,
244 .open = mv64x60_wdt_open, 245 .open = mv64x60_wdt_open,
245 .release = mv64x60_wdt_release, 246 .release = mv64x60_wdt_release,
246}; 247};
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 74bc39aa1ce8..6f5420f478a9 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -40,10 +40,9 @@
40#include <linux/moduleparam.h> 40#include <linux/moduleparam.h>
41#include <linux/clk.h> 41#include <linux/clk.h>
42#include <linux/bitops.h> 42#include <linux/bitops.h>
43 43#include <linux/io.h>
44#include <asm/io.h> 44#include <linux/uaccess.h>
45#include <asm/uaccess.h> 45#include <linux/hardware.h>
46#include <asm/hardware.h>
47 46
48#include <asm/arch/prcm.h> 47#include <asm/arch/prcm.h>
49 48
@@ -54,11 +53,12 @@ module_param(timer_margin, uint, 0);
54MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); 53MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
55 54
56static int omap_wdt_users; 55static int omap_wdt_users;
57static struct clk *armwdt_ck = NULL; 56static struct clk *armwdt_ck;
58static struct clk *mpu_wdt_ick = NULL; 57static struct clk *mpu_wdt_ick;
59static struct clk *mpu_wdt_fck = NULL; 58static struct clk *mpu_wdt_fck;
60 59
61static unsigned int wdt_trgr_pattern = 0x1234; 60static unsigned int wdt_trgr_pattern = 0x1234;
61static spinlock_t wdt_lock;
62 62
63static void omap_wdt_ping(void) 63static void omap_wdt_ping(void)
64{ 64{
@@ -174,30 +174,29 @@ static int omap_wdt_release(struct inode *inode, struct file *file)
174 return 0; 174 return 0;
175} 175}
176 176
177static ssize_t 177static ssize_t omap_wdt_write(struct file *file, const char __user *data,
178omap_wdt_write(struct file *file, const char __user *data,
179 size_t len, loff_t *ppos) 178 size_t len, loff_t *ppos)
180{ 179{
181 /* Refresh LOAD_TIME. */ 180 /* Refresh LOAD_TIME. */
182 if (len) 181 if (len) {
182 spin_lock(&wdt_lock);
183 omap_wdt_ping(); 183 omap_wdt_ping();
184 spin_unlock(&wdt_lock);
185 }
184 return len; 186 return len;
185} 187}
186 188
187static int 189static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
188omap_wdt_ioctl(struct inode *inode, struct file *file, 190 unsigned long arg)
189 unsigned int cmd, unsigned long arg)
190{ 191{
191 int new_margin; 192 int new_margin;
192 static struct watchdog_info ident = { 193 static const struct watchdog_info ident = {
193 .identity = "OMAP Watchdog", 194 .identity = "OMAP Watchdog",
194 .options = WDIOF_SETTIMEOUT, 195 .options = WDIOF_SETTIMEOUT,
195 .firmware_version = 0, 196 .firmware_version = 0,
196 }; 197 };
197 198
198 switch (cmd) { 199 switch (cmd) {
199 default:
200 return -ENOTTY;
201 case WDIOC_GETSUPPORT: 200 case WDIOC_GETSUPPORT:
202 return copy_to_user((struct watchdog_info __user *)arg, &ident, 201 return copy_to_user((struct watchdog_info __user *)arg, &ident,
203 sizeof(ident)); 202 sizeof(ident));
@@ -211,28 +210,34 @@ omap_wdt_ioctl(struct inode *inode, struct file *file,
211 return put_user(omap_prcm_get_reset_sources(), 210 return put_user(omap_prcm_get_reset_sources(),
212 (int __user *)arg); 211 (int __user *)arg);
213 case WDIOC_KEEPALIVE: 212 case WDIOC_KEEPALIVE:
213 spin_lock(&wdt_lock);
214 omap_wdt_ping(); 214 omap_wdt_ping();
215 spin_unlock(&wdt_lock);
215 return 0; 216 return 0;
216 case WDIOC_SETTIMEOUT: 217 case WDIOC_SETTIMEOUT:
217 if (get_user(new_margin, (int __user *)arg)) 218 if (get_user(new_margin, (int __user *)arg))
218 return -EFAULT; 219 return -EFAULT;
219 omap_wdt_adjust_timeout(new_margin); 220 omap_wdt_adjust_timeout(new_margin);
220 221
222 spin_lock(&wdt_lock);
221 omap_wdt_disable(); 223 omap_wdt_disable();
222 omap_wdt_set_timeout(); 224 omap_wdt_set_timeout();
223 omap_wdt_enable(); 225 omap_wdt_enable();
224 226
225 omap_wdt_ping(); 227 omap_wdt_ping();
228 spin_unlock(&wdt_lock);
226 /* Fall */ 229 /* Fall */
227 case WDIOC_GETTIMEOUT: 230 case WDIOC_GETTIMEOUT:
228 return put_user(timer_margin, (int __user *)arg); 231 return put_user(timer_margin, (int __user *)arg);
232 default:
233 return -ENOTTY;
229 } 234 }
230} 235}
231 236
232static const struct file_operations omap_wdt_fops = { 237static const struct file_operations omap_wdt_fops = {
233 .owner = THIS_MODULE, 238 .owner = THIS_MODULE,
234 .write = omap_wdt_write, 239 .write = omap_wdt_write,
235 .ioctl = omap_wdt_ioctl, 240 .unlocked_ioctl = omap_wdt_ioctl,
236 .open = omap_wdt_open, 241 .open = omap_wdt_open,
237 .release = omap_wdt_release, 242 .release = omap_wdt_release,
238}; 243};
@@ -240,7 +245,7 @@ static const struct file_operations omap_wdt_fops = {
240static struct miscdevice omap_wdt_miscdev = { 245static struct miscdevice omap_wdt_miscdev = {
241 .minor = WATCHDOG_MINOR, 246 .minor = WATCHDOG_MINOR,
242 .name = "watchdog", 247 .name = "watchdog",
243 .fops = &omap_wdt_fops 248 .fops = &omap_wdt_fops,
244}; 249};
245 250
246static int __init omap_wdt_probe(struct platform_device *pdev) 251static int __init omap_wdt_probe(struct platform_device *pdev)
@@ -373,6 +378,7 @@ static struct platform_driver omap_wdt_driver = {
373 378
374static int __init omap_wdt_init(void) 379static int __init omap_wdt_init(void)
375{ 380{
381 spin_lock_init(&wdt_lock);
376 return platform_driver_register(&omap_wdt_driver); 382 return platform_driver_register(&omap_wdt_driver);
377} 383}
378 384
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index 15e4f8887a9e..e91ada72da1d 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -31,14 +31,14 @@
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32#include <linux/moduleparam.h> 32#include <linux/moduleparam.h>
33#include <linux/version.h> 33#include <linux/version.h>
34#include <linux/io.h>
35#include <linux/uaccess.h>
34 36
35#include <asm/io.h>
36#include <asm/uaccess.h>
37#include <asm/system.h> 37#include <asm/system.h>
38 38
39/* #define DEBUG 1 */ 39/* #define DEBUG 1 */
40 40
41#define DEFAULT_TIMEOUT 1 /* 1 minute */ 41#define DEFAULT_TIMEOUT 1 /* 1 minute */
42#define MAX_TIMEOUT 255 42#define MAX_TIMEOUT 255
43 43
44#define VERSION "1.1" 44#define VERSION "1.1"
@@ -46,22 +46,22 @@
46#define PFX MODNAME ": " 46#define PFX MODNAME ": "
47#define DPFX MODNAME " - DEBUG: " 47#define DPFX MODNAME " - DEBUG: "
48 48
49#define WDT_INDEX_IO_PORT (io+0) /* I/O port base (index register) */ 49#define WDT_INDEX_IO_PORT (io+0) /* I/O port base (index register) */
50#define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1) 50#define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1)
51#define SWC_LDN 0x04 51#define SWC_LDN 0x04
52#define SIOCFG2 0x22 /* Serial IO register */ 52#define SIOCFG2 0x22 /* Serial IO register */
53#define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */ 53#define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */
54#define WDTO 0x11 /* Watchdog timeout register */ 54#define WDTO 0x11 /* Watchdog timeout register */
55#define WDCFG 0x12 /* Watchdog config register */ 55#define WDCFG 0x12 /* Watchdog config register */
56 56
57static int io = 0x2E; /* Address used on Portwell Boards */ 57static int io = 0x2E; /* Address used on Portwell Boards */
58 58
59static int timeout = DEFAULT_TIMEOUT; /* timeout value */ 59static int timeout = DEFAULT_TIMEOUT; /* timeout value */
60static unsigned long timer_enabled = 0; /* is the timer enabled? */ 60static unsigned long timer_enabled; /* is the timer enabled? */
61 61
62static char expect_close; /* is the close expected? */ 62static char expect_close; /* is the close expected? */
63 63
64static DEFINE_SPINLOCK(io_lock);/* to guard the watchdog from io races */ 64static DEFINE_SPINLOCK(io_lock); /* to guard us from io races */
65 65
66static int nowayout = WATCHDOG_NOWAYOUT; 66static int nowayout = WATCHDOG_NOWAYOUT;
67 67
@@ -69,7 +69,7 @@ static int nowayout = WATCHDOG_NOWAYOUT;
69 69
70/* Select pins for Watchdog output */ 70/* Select pins for Watchdog output */
71 71
72static inline void pc87413_select_wdt_out (void) 72static inline void pc87413_select_wdt_out(void)
73{ 73{
74 unsigned int cr_data = 0; 74 unsigned int cr_data = 0;
75 75
@@ -77,7 +77,7 @@ static inline void pc87413_select_wdt_out (void)
77 77
78 outb_p(SIOCFG2, WDT_INDEX_IO_PORT); 78 outb_p(SIOCFG2, WDT_INDEX_IO_PORT);
79 79
80 cr_data = inb (WDT_DATA_IO_PORT); 80 cr_data = inb(WDT_DATA_IO_PORT);
81 81
82 cr_data |= 0x80; /* Set Bit7 to 1*/ 82 cr_data |= 0x80; /* Set Bit7 to 1*/
83 outb_p(SIOCFG2, WDT_INDEX_IO_PORT); 83 outb_p(SIOCFG2, WDT_INDEX_IO_PORT);
@@ -85,8 +85,9 @@ static inline void pc87413_select_wdt_out (void)
85 outb_p(cr_data, WDT_DATA_IO_PORT); 85 outb_p(cr_data, WDT_DATA_IO_PORT);
86 86
87#ifdef DEBUG 87#ifdef DEBUG
88 printk(KERN_INFO DPFX "Select multiple pin,pin55,as WDT output:" 88 printk(KERN_INFO DPFX
89 " Bit7 to 1: %d\n", cr_data); 89 "Select multiple pin,pin55,as WDT output: Bit7 to 1: %d\n",
90 cr_data);
90#endif 91#endif
91} 92}
92 93
@@ -94,18 +95,18 @@ static inline void pc87413_select_wdt_out (void)
94 95
95static inline void pc87413_enable_swc(void) 96static inline void pc87413_enable_swc(void)
96{ 97{
97 unsigned int cr_data=0; 98 unsigned int cr_data = 0;
98 99
99 /* Step 2: Enable SWC functions */ 100 /* Step 2: Enable SWC functions */
100 101
101 outb_p(0x07, WDT_INDEX_IO_PORT); /* Point SWC_LDN (LDN=4) */ 102 outb_p(0x07, WDT_INDEX_IO_PORT); /* Point SWC_LDN (LDN=4) */
102 outb_p(SWC_LDN, WDT_DATA_IO_PORT); 103 outb_p(SWC_LDN, WDT_DATA_IO_PORT);
103 104
104 outb_p(0x30, WDT_INDEX_IO_PORT); /* Read Index 0x30 First */ 105 outb_p(0x30, WDT_INDEX_IO_PORT); /* Read Index 0x30 First */
105 cr_data = inb(WDT_DATA_IO_PORT); 106 cr_data = inb(WDT_DATA_IO_PORT);
106 cr_data |= 0x01; /* Set Bit0 to 1 */ 107 cr_data |= 0x01; /* Set Bit0 to 1 */
107 outb_p(0x30, WDT_INDEX_IO_PORT); 108 outb_p(0x30, WDT_INDEX_IO_PORT);
108 outb_p(cr_data, WDT_DATA_IO_PORT); /* Index0x30_bit0P1 */ 109 outb_p(cr_data, WDT_DATA_IO_PORT); /* Index0x30_bit0P1 */
109 110
110#ifdef DEBUG 111#ifdef DEBUG
111 printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n"); 112 printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n");
@@ -121,20 +122,19 @@ static inline unsigned int pc87413_get_swc_base(void)
121 122
122 /* Step 3: Read SWC I/O Base Address */ 123 /* Step 3: Read SWC I/O Base Address */
123 124
124 outb_p(0x60, WDT_INDEX_IO_PORT); /* Read Index 0x60 */ 125 outb_p(0x60, WDT_INDEX_IO_PORT); /* Read Index 0x60 */
125 addr_h = inb(WDT_DATA_IO_PORT); 126 addr_h = inb(WDT_DATA_IO_PORT);
126 127
127 outb_p(0x61, WDT_INDEX_IO_PORT); /* Read Index 0x61 */ 128 outb_p(0x61, WDT_INDEX_IO_PORT); /* Read Index 0x61 */
128 129
129 addr_l = inb(WDT_DATA_IO_PORT); 130 addr_l = inb(WDT_DATA_IO_PORT);
130 131
131 swc_base_addr = (addr_h << 8) + addr_l; 132 swc_base_addr = (addr_h << 8) + addr_l;
132
133#ifdef DEBUG 133#ifdef DEBUG
134 printk(KERN_INFO DPFX "Read SWC I/O Base Address: low %d, high %d," 134 printk(KERN_INFO DPFX
135 " res %d\n", addr_l, addr_h, swc_base_addr); 135 "Read SWC I/O Base Address: low %d, high %d, res %d\n",
136 addr_l, addr_h, swc_base_addr);
136#endif 137#endif
137
138 return swc_base_addr; 138 return swc_base_addr;
139} 139}
140 140
@@ -143,9 +143,7 @@ static inline unsigned int pc87413_get_swc_base(void)
143static inline void pc87413_swc_bank3(unsigned int swc_base_addr) 143static inline void pc87413_swc_bank3(unsigned int swc_base_addr)
144{ 144{
145 /* Step 4: Select Bank3 of SWC */ 145 /* Step 4: Select Bank3 of SWC */
146
147 outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f); 146 outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f);
148
149#ifdef DEBUG 147#ifdef DEBUG
150 printk(KERN_INFO DPFX "Select Bank3 of SWC\n"); 148 printk(KERN_INFO DPFX "Select Bank3 of SWC\n");
151#endif 149#endif
@@ -157,9 +155,7 @@ static inline void pc87413_programm_wdto(unsigned int swc_base_addr,
157 char pc87413_time) 155 char pc87413_time)
158{ 156{
159 /* Step 5: Programm WDTO, Twd. */ 157 /* Step 5: Programm WDTO, Twd. */
160
161 outb_p(pc87413_time, swc_base_addr + WDTO); 158 outb_p(pc87413_time, swc_base_addr + WDTO);
162
163#ifdef DEBUG 159#ifdef DEBUG
164 printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time); 160 printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time);
165#endif 161#endif
@@ -170,9 +166,7 @@ static inline void pc87413_programm_wdto(unsigned int swc_base_addr,
170static inline void pc87413_enable_wden(unsigned int swc_base_addr) 166static inline void pc87413_enable_wden(unsigned int swc_base_addr)
171{ 167{
172 /* Step 6: Enable WDEN */ 168 /* Step 6: Enable WDEN */
173 169 outb_p(inb(swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL);
174 outb_p(inb (swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL);
175
176#ifdef DEBUG 170#ifdef DEBUG
177 printk(KERN_INFO DPFX "Enable WDEN\n"); 171 printk(KERN_INFO DPFX "Enable WDEN\n");
178#endif 172#endif
@@ -182,9 +176,7 @@ static inline void pc87413_enable_wden(unsigned int swc_base_addr)
182static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr) 176static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr)
183{ 177{
184 /* Enable SW_WD_TREN */ 178 /* Enable SW_WD_TREN */
185 179 outb_p(inb(swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG);
186 outb_p(inb (swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG);
187
188#ifdef DEBUG 180#ifdef DEBUG
189 printk(KERN_INFO DPFX "Enable SW_WD_TREN\n"); 181 printk(KERN_INFO DPFX "Enable SW_WD_TREN\n");
190#endif 182#endif
@@ -195,9 +187,7 @@ static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr)
195static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr) 187static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr)
196{ 188{
197 /* Disable SW_WD_TREN */ 189 /* Disable SW_WD_TREN */
198 190 outb_p(inb(swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG);
199 outb_p(inb (swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG);
200
201#ifdef DEBUG 191#ifdef DEBUG
202 printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n"); 192 printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n");
203#endif 193#endif
@@ -208,9 +198,7 @@ static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr)
208static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr) 198static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr)
209{ 199{
210 /* Enable SW_WD_TRG */ 200 /* Enable SW_WD_TRG */
211 201 outb_p(inb(swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL);
212 outb_p(inb (swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL);
213
214#ifdef DEBUG 202#ifdef DEBUG
215 printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n"); 203 printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n");
216#endif 204#endif
@@ -221,9 +209,7 @@ static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr)
221static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr) 209static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr)
222{ 210{
223 /* Disable SW_WD_TRG */ 211 /* Disable SW_WD_TRG */
224 212 outb_p(inb(swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL);
225 outb_p(inb (swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL);
226
227#ifdef DEBUG 213#ifdef DEBUG
228 printk(KERN_INFO DPFX "Disable SW_WD_TRG\n"); 214 printk(KERN_INFO DPFX "Disable SW_WD_TRG\n");
229#endif 215#endif
@@ -314,8 +300,8 @@ static int pc87413_open(struct inode *inode, struct file *file)
314 /* Reload and activate timer */ 300 /* Reload and activate timer */
315 pc87413_refresh(); 301 pc87413_refresh();
316 302
317 printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to" 303 printk(KERN_INFO MODNAME
318 " %d minute(s).\n", timeout); 304 "Watchdog enabled. Timeout set to %d minute(s).\n", timeout);
319 305
320 return nonseekable_open(inode, file); 306 return nonseekable_open(inode, file);
321} 307}
@@ -338,17 +324,15 @@ static int pc87413_release(struct inode *inode, struct file *file)
338 324
339 if (expect_close == 42) { 325 if (expect_close == 42) {
340 pc87413_disable(); 326 pc87413_disable();
341 printk(KERN_INFO MODNAME "Watchdog disabled," 327 printk(KERN_INFO MODNAME
342 " sleeping again...\n"); 328 "Watchdog disabled, sleeping again...\n");
343 } else { 329 } else {
344 printk(KERN_CRIT MODNAME "Unexpected close, not stopping" 330 printk(KERN_CRIT MODNAME
345 " watchdog!\n"); 331 "Unexpected close, not stopping watchdog!\n");
346 pc87413_refresh(); 332 pc87413_refresh();
347 } 333 }
348
349 clear_bit(0, &timer_enabled); 334 clear_bit(0, &timer_enabled);
350 expect_close = 0; 335 expect_close = 0;
351
352 return 0; 336 return 0;
353} 337}
354 338
@@ -386,10 +370,11 @@ static ssize_t pc87413_write(struct file *file, const char __user *data,
386 /* reset expect flag */ 370 /* reset expect flag */
387 expect_close = 0; 371 expect_close = 0;
388 372
389 /* scan to see whether or not we got the magic character */ 373 /* scan to see whether or not we got the
374 magic character */
390 for (i = 0; i != len; i++) { 375 for (i = 0; i != len; i++) {
391 char c; 376 char c;
392 if (get_user(c, data+i)) 377 if (get_user(c, data + i))
393 return -EFAULT; 378 return -EFAULT;
394 if (c == 'V') 379 if (c == 'V')
395 expect_close = 42; 380 expect_close = 42;
@@ -404,7 +389,6 @@ static ssize_t pc87413_write(struct file *file, const char __user *data,
404 389
405/** 390/**
406 * pc87413_ioctl: 391 * pc87413_ioctl:
407 * @inode: inode of the device
408 * @file: file handle to the device 392 * @file: file handle to the device
409 * @cmd: watchdog command 393 * @cmd: watchdog command
410 * @arg: argument pointer 394 * @arg: argument pointer
@@ -414,8 +398,8 @@ static ssize_t pc87413_write(struct file *file, const char __user *data,
414 * querying capabilities and current status. 398 * querying capabilities and current status.
415 */ 399 */
416 400
417static int pc87413_ioctl(struct inode *inode, struct file *file, 401static long pc87413_ioctl(struct file *file, unsigned int cmd,
418 unsigned int cmd, unsigned long arg) 402 unsigned long arg)
419{ 403{
420 int new_timeout; 404 int new_timeout;
421 405
@@ -426,75 +410,58 @@ static int pc87413_ioctl(struct inode *inode, struct file *file,
426 410
427 static struct watchdog_info ident = { 411 static struct watchdog_info ident = {
428 .options = WDIOF_KEEPALIVEPING | 412 .options = WDIOF_KEEPALIVEPING |
429 WDIOF_SETTIMEOUT | 413 WDIOF_SETTIMEOUT |
430 WDIOF_MAGICCLOSE, 414 WDIOF_MAGICCLOSE,
431 .firmware_version = 1, 415 .firmware_version = 1,
432 .identity = "PC87413(HF/F) watchdog" 416 .identity = "PC87413(HF/F) watchdog",
433 }; 417 };
434 418
435 uarg.i = (int __user *)arg; 419 uarg.i = (int __user *)arg;
436 420
437 switch(cmd) { 421 switch (cmd) {
438 default: 422 case WDIOC_GETSUPPORT:
439 return -ENOTTY; 423 return copy_to_user(uarg.ident, &ident,
440 424 sizeof(ident)) ? -EFAULT : 0;
441 case WDIOC_GETSUPPORT: 425 case WDIOC_GETSTATUS:
442 return copy_to_user(uarg.ident, &ident, 426 return put_user(pc87413_status(), uarg.i);
443 sizeof(ident)) ? -EFAULT : 0; 427 case WDIOC_GETBOOTSTATUS:
444 428 return put_user(0, uarg.i);
445 case WDIOC_GETSTATUS: 429 case WDIOC_SETOPTIONS:
446 return put_user(pc87413_status(), uarg.i); 430 {
447 431 int options, retval = -EINVAL;
448 case WDIOC_GETBOOTSTATUS: 432 if (get_user(options, uarg.i))
449 return put_user(0, uarg.i); 433 return -EFAULT;
450 434 if (options & WDIOS_DISABLECARD) {
451 case WDIOC_KEEPALIVE: 435 pc87413_disable();
452 pc87413_refresh(); 436 retval = 0;
437 }
438 if (options & WDIOS_ENABLECARD) {
439 pc87413_enable();
440 retval = 0;
441 }
442 return retval;
443 }
444 case WDIOC_KEEPALIVE:
445 pc87413_refresh();
453#ifdef DEBUG 446#ifdef DEBUG
454 printk(KERN_INFO DPFX "keepalive\n"); 447 printk(KERN_INFO DPFX "keepalive\n");
455#endif 448#endif
456 return 0; 449 return 0;
457 450 case WDIOC_SETTIMEOUT:
458 case WDIOC_SETTIMEOUT: 451 if (get_user(new_timeout, uarg.i))
459 if (get_user(new_timeout, uarg.i)) 452 return -EFAULT;
460 return -EFAULT; 453 /* the API states this is given in secs */
461 454 new_timeout /= 60;
462 // the API states this is given in secs 455 if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
463 new_timeout /= 60; 456 return -EINVAL;
464 457 timeout = new_timeout;
465 if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) 458 pc87413_refresh();
466 return -EINVAL; 459 /* fall through and return the new timeout... */
467 460 case WDIOC_GETTIMEOUT:
468 timeout = new_timeout; 461 new_timeout = timeout * 60;
469 pc87413_refresh(); 462 return put_user(new_timeout, uarg.i);
470 463 default:
471 // fall through and return the new timeout... 464 return -ENOTTY;
472
473 case WDIOC_GETTIMEOUT:
474
475 new_timeout = timeout * 60;
476
477 return put_user(new_timeout, uarg.i);
478
479 case WDIOC_SETOPTIONS:
480 {
481 int options, retval = -EINVAL;
482
483 if (get_user(options, uarg.i))
484 return -EFAULT;
485
486 if (options & WDIOS_DISABLECARD) {
487 pc87413_disable();
488 retval = 0;
489 }
490
491 if (options & WDIOS_ENABLECARD) {
492 pc87413_enable();
493 retval = 0;
494 }
495
496 return retval;
497 }
498 } 465 }
499} 466}
500 467
@@ -517,10 +484,8 @@ static int pc87413_notify_sys(struct notifier_block *this,
517 void *unused) 484 void *unused)
518{ 485{
519 if (code == SYS_DOWN || code == SYS_HALT) 486 if (code == SYS_DOWN || code == SYS_HALT)
520 {
521 /* Turn the card off */ 487 /* Turn the card off */
522 pc87413_disable(); 488 pc87413_disable();
523 }
524 return NOTIFY_DONE; 489 return NOTIFY_DONE;
525} 490}
526 491
@@ -530,21 +495,19 @@ static const struct file_operations pc87413_fops = {
530 .owner = THIS_MODULE, 495 .owner = THIS_MODULE,
531 .llseek = no_llseek, 496 .llseek = no_llseek,
532 .write = pc87413_write, 497 .write = pc87413_write,
533 .ioctl = pc87413_ioctl, 498 .unlocked_ioctl = pc87413_ioctl,
534 .open = pc87413_open, 499 .open = pc87413_open,
535 .release = pc87413_release, 500 .release = pc87413_release,
536}; 501};
537 502
538static struct notifier_block pc87413_notifier = 503static struct notifier_block pc87413_notifier = {
539{
540 .notifier_call = pc87413_notify_sys, 504 .notifier_call = pc87413_notify_sys,
541}; 505};
542 506
543static struct miscdevice pc87413_miscdev= 507static struct miscdevice pc87413_miscdev = {
544{
545 .minor = WATCHDOG_MINOR, 508 .minor = WATCHDOG_MINOR,
546 .name = "watchdog", 509 .name = "watchdog",
547 .fops = &pc87413_fops 510 .fops = &pc87413_fops,
548}; 511};
549 512
550/* -- Module init functions -------------------------------------*/ 513/* -- Module init functions -------------------------------------*/
@@ -561,29 +524,26 @@ static int __init pc87413_init(void)
561{ 524{
562 int ret; 525 int ret;
563 526
564 printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n", WDT_INDEX_IO_PORT); 527 printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n",
528 WDT_INDEX_IO_PORT);
565 529
566 /* request_region(io, 2, "pc87413"); */ 530 /* request_region(io, 2, "pc87413"); */
567 531
568 ret = register_reboot_notifier(&pc87413_notifier); 532 ret = register_reboot_notifier(&pc87413_notifier);
569 if (ret != 0) { 533 if (ret != 0) {
570 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 534 printk(KERN_ERR PFX
571 ret); 535 "cannot register reboot notifier (err=%d)\n", ret);
572 } 536 }
573 537
574 ret = misc_register(&pc87413_miscdev); 538 ret = misc_register(&pc87413_miscdev);
575
576 if (ret != 0) { 539 if (ret != 0) {
577 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 540 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
578 WATCHDOG_MINOR, ret); 541 WATCHDOG_MINOR, ret);
579 unregister_reboot_notifier(&pc87413_notifier); 542 unregister_reboot_notifier(&pc87413_notifier);
580 return ret; 543 return ret;
581 } 544 }
582
583 printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout); 545 printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout);
584
585 pc87413_enable(); 546 pc87413_enable();
586
587 return 0; 547 return 0;
588} 548}
589 549
@@ -600,17 +560,16 @@ static int __init pc87413_init(void)
600static void __exit pc87413_exit(void) 560static void __exit pc87413_exit(void)
601{ 561{
602 /* Stop the timer before we leave */ 562 /* Stop the timer before we leave */
603 if (!nowayout) 563 if (!nowayout) {
604 {
605 pc87413_disable(); 564 pc87413_disable();
606 printk(KERN_INFO MODNAME "Watchdog disabled.\n"); 565 printk(KERN_INFO MODNAME "Watchdog disabled.\n");
607 } 566 }
608 567
609 misc_deregister(&pc87413_miscdev); 568 misc_deregister(&pc87413_miscdev);
610 unregister_reboot_notifier(&pc87413_notifier); 569 unregister_reboot_notifier(&pc87413_notifier);
611 /* release_region(io,2); */ 570 /* release_region(io, 2); */
612 571
613 printk(MODNAME " watchdog component driver removed.\n"); 572 printk(KERN_INFO MODNAME " watchdog component driver removed.\n");
614} 573}
615 574
616module_init(pc87413_init); 575module_init(pc87413_init);
@@ -626,8 +585,12 @@ module_param(io, int, 0);
626MODULE_PARM_DESC(io, MODNAME " I/O port (default: " __MODULE_STRING(io) ")."); 585MODULE_PARM_DESC(io, MODNAME " I/O port (default: " __MODULE_STRING(io) ").");
627 586
628module_param(timeout, int, 0); 587module_param(timeout, int, 0);
629MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes (default=" __MODULE_STRING(timeout) ")."); 588MODULE_PARM_DESC(timeout,
589 "Watchdog timeout in minutes (default="
590 __MODULE_STRING(timeout) ").");
630 591
631module_param(nowayout, int, 0); 592module_param(nowayout, int, 0);
632MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 593MODULE_PARM_DESC(nowayout,
594 "Watchdog cannot be stopped once started (default="
595 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
633 596
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
index 7b41434fac8c..3b0ddc7fcf3f 100644
--- a/drivers/watchdog/pcwd.c
+++ b/drivers/watchdog/pcwd.c
@@ -40,13 +40,15 @@
40 * fairly useless proc entry. 40 * fairly useless proc entry.
41 * 990610 removed said useless proc code for the merge <alan> 41 * 990610 removed said useless proc code for the merge <alan>
42 * 000403 Removed last traces of proc code. <davej> 42 * 000403 Removed last traces of proc code. <davej>
43 * 011214 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT <Matt_Domsch@dell.com> 43 * 011214 Added nowayout module option to override
44 * CONFIG_WATCHDOG_NOWAYOUT <Matt_Domsch@dell.com>
44 * Added timeout module option to override default 45 * Added timeout module option to override default
45 */ 46 */
46 47
47/* 48/*
48 * A bells and whistles driver is available from http://www.pcwd.de/ 49 * A bells and whistles driver is available from http://www.pcwd.de/
49 * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ 50 * More info available at http://www.berkprod.com/ or
51 * http://www.pcwatchdog.com/
50 */ 52 */
51 53
52#include <linux/module.h> /* For module specific items */ 54#include <linux/module.h> /* For module specific items */
@@ -65,9 +67,8 @@
65#include <linux/isa.h> /* For isa devices */ 67#include <linux/isa.h> /* For isa devices */
66#include <linux/ioport.h> /* For io-port access */ 68#include <linux/ioport.h> /* For io-port access */
67#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ 69#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
68 70#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
69#include <asm/uaccess.h> /* For copy_to_user/put_user/... */ 71#include <linux/io.h> /* For inb/outb/... */
70#include <asm/io.h> /* For inb/outb/... */
71 72
72/* Module and version information */ 73/* Module and version information */
73#define WATCHDOG_VERSION "1.20" 74#define WATCHDOG_VERSION "1.20"
@@ -111,14 +112,16 @@ static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
111#define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ 112#define WD_REVC_WTRP 0x01 /* Watchdog Trip status */
112#define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ 113#define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */
113#define WD_REVC_TTRP 0x04 /* Temperature Trip status */ 114#define WD_REVC_TTRP 0x04 /* Temperature Trip status */
114#define WD_REVC_RL2A 0x08 /* Relay 2 activated by on-board processor */ 115#define WD_REVC_RL2A 0x08 /* Relay 2 activated by
116 on-board processor */
115#define WD_REVC_RL1A 0x10 /* Relay 1 active */ 117#define WD_REVC_RL1A 0x10 /* Relay 1 active */
116#define WD_REVC_R2DS 0x40 /* Relay 2 disable */ 118#define WD_REVC_R2DS 0x40 /* Relay 2 disable */
117#define WD_REVC_RLY2 0x80 /* Relay 2 activated? */ 119#define WD_REVC_RLY2 0x80 /* Relay 2 activated? */
118/* Port 2 : Control Status #2 */ 120/* Port 2 : Control Status #2 */
119#define WD_WDIS 0x10 /* Watchdog Disabled */ 121#define WD_WDIS 0x10 /* Watchdog Disabled */
120#define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ 122#define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */
121#define WD_SSEL 0x40 /* Watchdog Switch Select (1:SW1 <-> 0:SW2) */ 123#define WD_SSEL 0x40 /* Watchdog Switch Select
124 (1:SW1 <-> 0:SW2) */
122#define WD_WCMD 0x80 /* Watchdog Command Mode */ 125#define WD_WCMD 0x80 /* Watchdog Command Mode */
123 126
124/* max. time we give an ISA watchdog card to process a command */ 127/* max. time we give an ISA watchdog card to process a command */
@@ -142,7 +145,7 @@ static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
142#define CMD_ISA_RESET_RELAYS 0x0D 145#define CMD_ISA_RESET_RELAYS 0x0D
143 146
144/* Watchdog's Dip Switch heartbeat values */ 147/* Watchdog's Dip Switch heartbeat values */
145static const int heartbeat_tbl [] = { 148static const int heartbeat_tbl[] = {
146 20, /* OFF-OFF-OFF = 20 Sec */ 149 20, /* OFF-OFF-OFF = 20 Sec */
147 40, /* OFF-OFF-ON = 40 Sec */ 150 40, /* OFF-OFF-ON = 40 Sec */
148 60, /* OFF-ON-OFF = 1 Min */ 151 60, /* OFF-ON-OFF = 1 Min */
@@ -168,11 +171,15 @@ static int cards_found;
168static atomic_t open_allowed = ATOMIC_INIT(1); 171static atomic_t open_allowed = ATOMIC_INIT(1);
169static char expect_close; 172static char expect_close;
170static int temp_panic; 173static int temp_panic;
171static struct { /* this is private data for each ISA-PC watchdog card */ 174
175/* this is private data for each ISA-PC watchdog card */
176static struct {
172 char fw_ver_str[6]; /* The cards firmware version */ 177 char fw_ver_str[6]; /* The cards firmware version */
173 int revision; /* The card's revision */ 178 int revision; /* The card's revision */
174 int supports_temp; /* Wether or not the card has a temperature device */ 179 int supports_temp; /* Whether or not the card has
175 int command_mode; /* Wether or not the card is in command mode */ 180 a temperature device */
181 int command_mode; /* Whether or not the card is in
182 command mode */
176 int boot_status; /* The card's boot status */ 183 int boot_status; /* The card's boot status */
177 int io_addr; /* The cards I/O address */ 184 int io_addr; /* The cards I/O address */
178 spinlock_t io_lock; /* the lock for io operations */ 185 spinlock_t io_lock; /* the lock for io operations */
@@ -186,16 +193,20 @@ static struct { /* this is private data for each ISA-PC watchdog card */
186#define DEBUG 2 /* print fancy stuff too */ 193#define DEBUG 2 /* print fancy stuff too */
187static int debug = QUIET; 194static int debug = QUIET;
188module_param(debug, int, 0); 195module_param(debug, int, 0);
189MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); 196MODULE_PARM_DESC(debug,
197 "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
190 198
191#define WATCHDOG_HEARTBEAT 0 /* default heartbeat = delay-time from dip-switches */ 199/* default heartbeat = delay-time from dip-switches */
200#define WATCHDOG_HEARTBEAT 0
192static int heartbeat = WATCHDOG_HEARTBEAT; 201static int heartbeat = WATCHDOG_HEARTBEAT;
193module_param(heartbeat, int, 0); 202module_param(heartbeat, int, 0);
194MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 203MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2 <= heartbeat <= 7200 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
195 204
196static int nowayout = WATCHDOG_NOWAYOUT; 205static int nowayout = WATCHDOG_NOWAYOUT;
197module_param(nowayout, int, 0); 206module_param(nowayout, int, 0);
198MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 207MODULE_PARM_DESC(nowayout,
208 "Watchdog cannot be stopped once started (default="
209 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
199 210
200/* 211/*
201 * Internal functions 212 * Internal functions
@@ -224,7 +235,7 @@ static int send_isa_command(int cmd)
224 if (port0 == last_port0) 235 if (port0 == last_port0)
225 break; /* Data is stable */ 236 break; /* Data is stable */
226 237
227 udelay (250); 238 udelay(250);
228 } 239 }
229 240
230 if (debug >= DEBUG) 241 if (debug >= DEBUG)
@@ -236,7 +247,7 @@ static int send_isa_command(int cmd)
236 247
237static int set_command_mode(void) 248static int set_command_mode(void)
238{ 249{
239 int i, found=0, count=0; 250 int i, found = 0, count = 0;
240 251
241 /* Set the card into command mode */ 252 /* Set the card into command mode */
242 spin_lock(&pcwd_private.io_lock); 253 spin_lock(&pcwd_private.io_lock);
@@ -261,7 +272,7 @@ static int set_command_mode(void)
261 printk(KERN_DEBUG PFX "command_mode=%d\n", 272 printk(KERN_DEBUG PFX "command_mode=%d\n",
262 pcwd_private.command_mode); 273 pcwd_private.command_mode);
263 274
264 return(found); 275 return found;
265} 276}
266 277
267static void unset_command_mode(void) 278static void unset_command_mode(void)
@@ -296,7 +307,8 @@ static inline void pcwd_get_firmware(void)
296 ten = send_isa_command(CMD_ISA_VERSION_TENTH); 307 ten = send_isa_command(CMD_ISA_VERSION_TENTH);
297 hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); 308 hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
298 minor = send_isa_command(CMD_ISA_VERSION_MINOR); 309 minor = send_isa_command(CMD_ISA_VERSION_MINOR);
299 sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor); 310 sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c",
311 one, ten, hund, minor);
300 } 312 }
301 unset_command_mode(); 313 unset_command_mode();
302 314
@@ -305,7 +317,7 @@ static inline void pcwd_get_firmware(void)
305 317
306static inline int pcwd_get_option_switches(void) 318static inline int pcwd_get_option_switches(void)
307{ 319{
308 int option_switches=0; 320 int option_switches = 0;
309 321
310 if (set_command_mode()) { 322 if (set_command_mode()) {
311 /* Get switch settings */ 323 /* Get switch settings */
@@ -313,7 +325,7 @@ static inline int pcwd_get_option_switches(void)
313 } 325 }
314 326
315 unset_command_mode(); 327 unset_command_mode();
316 return(option_switches); 328 return option_switches;
317} 329}
318 330
319static void pcwd_show_card_info(void) 331static void pcwd_show_card_info(void)
@@ -322,7 +334,9 @@ static void pcwd_show_card_info(void)
322 334
323 /* Get some extra info from the hardware (in command/debug/diag mode) */ 335 /* Get some extra info from the hardware (in command/debug/diag mode) */
324 if (pcwd_private.revision == PCWD_REVISION_A) 336 if (pcwd_private.revision == PCWD_REVISION_A)
325 printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); 337 printk(KERN_INFO PFX
338 "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n",
339 pcwd_private.io_addr);
326 else if (pcwd_private.revision == PCWD_REVISION_C) { 340 else if (pcwd_private.revision == PCWD_REVISION_C) {
327 pcwd_get_firmware(); 341 pcwd_get_firmware();
328 printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", 342 printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
@@ -347,12 +361,15 @@ static void pcwd_show_card_info(void)
347 printk(KERN_INFO PFX "Previous reboot was caused by the card\n"); 361 printk(KERN_INFO PFX "Previous reboot was caused by the card\n");
348 362
349 if (pcwd_private.boot_status & WDIOF_OVERHEAT) { 363 if (pcwd_private.boot_status & WDIOF_OVERHEAT) {
350 printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n"); 364 printk(KERN_EMERG PFX
351 printk(KERN_EMERG PFX "CPU Overheat\n"); 365 "Card senses a CPU Overheat. Panicking!\n");
366 printk(KERN_EMERG PFX
367 "CPU Overheat\n");
352 } 368 }
353 369
354 if (pcwd_private.boot_status == 0) 370 if (pcwd_private.boot_status == 0)
355 printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); 371 printk(KERN_INFO PFX
372 "No previous trip detected - Cold boot or reset\n");
356} 373}
357 374
358static void pcwd_timer_ping(unsigned long data) 375static void pcwd_timer_ping(unsigned long data)
@@ -361,11 +378,12 @@ static void pcwd_timer_ping(unsigned long data)
361 378
362 /* If we got a heartbeat pulse within the WDT_INTERVAL 379 /* If we got a heartbeat pulse within the WDT_INTERVAL
363 * we agree to ping the WDT */ 380 * we agree to ping the WDT */
364 if(time_before(jiffies, pcwd_private.next_heartbeat)) { 381 if (time_before(jiffies, pcwd_private.next_heartbeat)) {
365 /* Ping the watchdog */ 382 /* Ping the watchdog */
366 spin_lock(&pcwd_private.io_lock); 383 spin_lock(&pcwd_private.io_lock);
367 if (pcwd_private.revision == PCWD_REVISION_A) { 384 if (pcwd_private.revision == PCWD_REVISION_A) {
368 /* Rev A cards are reset by setting the WD_WDRST bit in register 1 */ 385 /* Rev A cards are reset by setting the
386 WD_WDRST bit in register 1 */
369 wdrst_stat = inb_p(pcwd_private.io_addr); 387 wdrst_stat = inb_p(pcwd_private.io_addr);
370 wdrst_stat &= 0x0F; 388 wdrst_stat &= 0x0F;
371 wdrst_stat |= WD_WDRST; 389 wdrst_stat |= WD_WDRST;
@@ -381,7 +399,8 @@ static void pcwd_timer_ping(unsigned long data)
381 399
382 spin_unlock(&pcwd_private.io_lock); 400 spin_unlock(&pcwd_private.io_lock);
383 } else { 401 } else {
384 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); 402 printk(KERN_WARNING PFX
403 "Heartbeat lost! Will not ping the watchdog\n");
385 } 404 }
386} 405}
387 406
@@ -454,7 +473,7 @@ static int pcwd_keepalive(void)
454 473
455static int pcwd_set_heartbeat(int t) 474static int pcwd_set_heartbeat(int t)
456{ 475{
457 if ((t < 2) || (t > 7200)) /* arbitrary upper limit */ 476 if (t < 2 || t > 7200) /* arbitrary upper limit */
458 return -EINVAL; 477 return -EINVAL;
459 478
460 heartbeat = t; 479 heartbeat = t;
@@ -470,7 +489,7 @@ static int pcwd_get_status(int *status)
470{ 489{
471 int control_status; 490 int control_status;
472 491
473 *status=0; 492 *status = 0;
474 spin_lock(&pcwd_private.io_lock); 493 spin_lock(&pcwd_private.io_lock);
475 if (pcwd_private.revision == PCWD_REVISION_A) 494 if (pcwd_private.revision == PCWD_REVISION_A)
476 /* Rev A cards return status information from 495 /* Rev A cards return status information from
@@ -494,9 +513,9 @@ static int pcwd_get_status(int *status)
494 if (control_status & WD_T110) { 513 if (control_status & WD_T110) {
495 *status |= WDIOF_OVERHEAT; 514 *status |= WDIOF_OVERHEAT;
496 if (temp_panic) { 515 if (temp_panic) {
497 printk(KERN_INFO PFX "Temperature overheat trip!\n"); 516 printk(KERN_INFO PFX
517 "Temperature overheat trip!\n");
498 kernel_power_off(); 518 kernel_power_off();
499 /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
500 } 519 }
501 } 520 }
502 } else { 521 } else {
@@ -506,9 +525,9 @@ static int pcwd_get_status(int *status)
506 if (control_status & WD_REVC_TTRP) { 525 if (control_status & WD_REVC_TTRP) {
507 *status |= WDIOF_OVERHEAT; 526 *status |= WDIOF_OVERHEAT;
508 if (temp_panic) { 527 if (temp_panic) {
509 printk(KERN_INFO PFX "Temperature overheat trip!\n"); 528 printk(KERN_INFO PFX
529 "Temperature overheat trip!\n");
510 kernel_power_off(); 530 kernel_power_off();
511 /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
512 } 531 }
513 } 532 }
514 } 533 }
@@ -524,18 +543,21 @@ static int pcwd_clear_status(void)
524 spin_lock(&pcwd_private.io_lock); 543 spin_lock(&pcwd_private.io_lock);
525 544
526 if (debug >= VERBOSE) 545 if (debug >= VERBOSE)
527 printk(KERN_INFO PFX "clearing watchdog trip status\n"); 546 printk(KERN_INFO PFX
547 "clearing watchdog trip status\n");
528 548
529 control_status = inb_p(pcwd_private.io_addr + 1); 549 control_status = inb_p(pcwd_private.io_addr + 1);
530 550
531 if (debug >= DEBUG) { 551 if (debug >= DEBUG) {
532 printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status); 552 printk(KERN_DEBUG PFX "status was: 0x%02x\n",
553 control_status);
533 printk(KERN_DEBUG PFX "sending: 0x%02x\n", 554 printk(KERN_DEBUG PFX "sending: 0x%02x\n",
534 (control_status & WD_REVC_R2DS)); 555 (control_status & WD_REVC_R2DS));
535 } 556 }
536 557
537 /* clear reset status & Keep Relay 2 disable state as it is */ 558 /* clear reset status & Keep Relay 2 disable state as it is */
538 outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1); 559 outb_p((control_status & WD_REVC_R2DS),
560 pcwd_private.io_addr + 1);
539 561
540 spin_unlock(&pcwd_private.io_lock); 562 spin_unlock(&pcwd_private.io_lock);
541 } 563 }
@@ -572,8 +594,7 @@ static int pcwd_get_temperature(int *temperature)
572 * /dev/watchdog handling 594 * /dev/watchdog handling
573 */ 595 */
574 596
575static int pcwd_ioctl(struct inode *inode, struct file *file, 597static long pcwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
576 unsigned int cmd, unsigned long arg)
577{ 598{
578 int rv; 599 int rv;
579 int status; 600 int status;
@@ -590,12 +611,9 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
590 .identity = "PCWD", 611 .identity = "PCWD",
591 }; 612 };
592 613
593 switch(cmd) { 614 switch (cmd) {
594 default:
595 return -ENOTTY;
596
597 case WDIOC_GETSUPPORT: 615 case WDIOC_GETSUPPORT:
598 if(copy_to_user(argp, &ident, sizeof(ident))) 616 if (copy_to_user(argp, &ident, sizeof(ident)))
599 return -EFAULT; 617 return -EFAULT;
600 return 0; 618 return 0;
601 619
@@ -613,25 +631,22 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
613 return put_user(temperature, argp); 631 return put_user(temperature, argp);
614 632
615 case WDIOC_SETOPTIONS: 633 case WDIOC_SETOPTIONS:
616 if (pcwd_private.revision == PCWD_REVISION_C) 634 if (pcwd_private.revision == PCWD_REVISION_C) {
617 { 635 if (get_user(rv, argp))
618 if(copy_from_user(&rv, argp, sizeof(int)))
619 return -EFAULT; 636 return -EFAULT;
620 637
621 if (rv & WDIOS_DISABLECARD) 638 if (rv & WDIOS_DISABLECARD) {
622 { 639 status = pcwd_stop();
623 return pcwd_stop(); 640 if (status < 0)
641 return status;
624 } 642 }
625 643 if (rv & WDIOS_ENABLECARD) {
626 if (rv & WDIOS_ENABLECARD) 644 status = pcwd_start();
627 { 645 if (status < 0)
628 return pcwd_start(); 646 return status;
629 } 647 }
630
631 if (rv & WDIOS_TEMPPANIC) 648 if (rv & WDIOS_TEMPPANIC)
632 {
633 temp_panic = 1; 649 temp_panic = 1;
634 }
635 } 650 }
636 return -EINVAL; 651 return -EINVAL;
637 652
@@ -651,6 +666,9 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
651 666
652 case WDIOC_GETTIMEOUT: 667 case WDIOC_GETTIMEOUT:
653 return put_user(heartbeat, argp); 668 return put_user(heartbeat, argp);
669
670 default:
671 return -ENOTTY;
654 } 672 }
655 673
656 return 0; 674 return 0;
@@ -682,16 +700,10 @@ static ssize_t pcwd_write(struct file *file, const char __user *buf, size_t len,
682 700
683static int pcwd_open(struct inode *inode, struct file *file) 701static int pcwd_open(struct inode *inode, struct file *file)
684{ 702{
685 if (!atomic_dec_and_test(&open_allowed) ) { 703 if (test_and_set_bit(0, &open_allowed))
686 if (debug >= VERBOSE)
687 printk(KERN_ERR PFX "Attempt to open already opened device.\n");
688 atomic_inc( &open_allowed );
689 return -EBUSY; 704 return -EBUSY;
690 }
691
692 if (nowayout) 705 if (nowayout)
693 __module_get(THIS_MODULE); 706 __module_get(THIS_MODULE);
694
695 /* Activate */ 707 /* Activate */
696 pcwd_start(); 708 pcwd_start();
697 pcwd_keepalive(); 709 pcwd_keepalive();
@@ -700,14 +712,15 @@ static int pcwd_open(struct inode *inode, struct file *file)
700 712
701static int pcwd_close(struct inode *inode, struct file *file) 713static int pcwd_close(struct inode *inode, struct file *file)
702{ 714{
703 if (expect_close == 42) { 715 if (expect_close == 42)
704 pcwd_stop(); 716 pcwd_stop();
705 } else { 717 else {
706 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 718 printk(KERN_CRIT PFX
719 "Unexpected close, not stopping watchdog!\n");
707 pcwd_keepalive(); 720 pcwd_keepalive();
708 } 721 }
709 expect_close = 0; 722 expect_close = 0;
710 atomic_inc( &open_allowed ); 723 clear_bit(0, &open_allowed);
711 return 0; 724 return 0;
712} 725}
713 726
@@ -750,7 +763,7 @@ static const struct file_operations pcwd_fops = {
750 .owner = THIS_MODULE, 763 .owner = THIS_MODULE,
751 .llseek = no_llseek, 764 .llseek = no_llseek,
752 .write = pcwd_write, 765 .write = pcwd_write,
753 .ioctl = pcwd_ioctl, 766 .unlocked_ioctl = pcwd_ioctl,
754 .open = pcwd_open, 767 .open = pcwd_open,
755 .release = pcwd_close, 768 .release = pcwd_close,
756}; 769};
@@ -788,7 +801,7 @@ static inline int get_revision(void)
788 * presumes a floating bus reads as 0xff. */ 801 * presumes a floating bus reads as 0xff. */
789 if ((inb(pcwd_private.io_addr + 2) == 0xFF) || 802 if ((inb(pcwd_private.io_addr + 2) == 0xFF) ||
790 (inb(pcwd_private.io_addr + 3) == 0xFF)) 803 (inb(pcwd_private.io_addr + 3) == 0xFF))
791 r=PCWD_REVISION_A; 804 r = PCWD_REVISION_A;
792 spin_unlock(&pcwd_private.io_lock); 805 spin_unlock(&pcwd_private.io_lock);
793 806
794 return r; 807 return r;
@@ -803,7 +816,7 @@ static inline int get_revision(void)
803 */ 816 */
804static int __devinit pcwd_isa_match(struct device *dev, unsigned int id) 817static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
805{ 818{
806 int base_addr=pcwd_ioports[id]; 819 int base_addr = pcwd_ioports[id];
807 int port0, last_port0; /* Reg 0, in case it's REV A */ 820 int port0, last_port0; /* Reg 0, in case it's REV A */
808 int port1, last_port1; /* Register 1 for REV C cards */ 821 int port1, last_port1; /* Register 1 for REV C cards */
809 int i; 822 int i;
@@ -813,7 +826,7 @@ static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
813 printk(KERN_DEBUG PFX "pcwd_isa_match id=%d\n", 826 printk(KERN_DEBUG PFX "pcwd_isa_match id=%d\n",
814 id); 827 id);
815 828
816 if (!request_region (base_addr, 4, "PCWD")) { 829 if (!request_region(base_addr, 4, "PCWD")) {
817 printk(KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr); 830 printk(KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr);
818 return 0; 831 return 0;
819 } 832 }
@@ -842,7 +855,7 @@ static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
842 } 855 }
843 } 856 }
844 } 857 }
845 release_region (base_addr, 4); 858 release_region(base_addr, 4);
846 859
847 return retval; 860 return retval;
848} 861}
@@ -857,7 +870,8 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
857 870
858 cards_found++; 871 cards_found++;
859 if (cards_found == 1) 872 if (cards_found == 1)
860 printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER); 873 printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n",
874 WD_VER);
861 875
862 if (cards_found > 1) { 876 if (cards_found > 1) {
863 printk(KERN_ERR PFX "This driver only supports 1 device\n"); 877 printk(KERN_ERR PFX "This driver only supports 1 device\n");
@@ -875,10 +889,11 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
875 /* Check card's revision */ 889 /* Check card's revision */
876 pcwd_private.revision = get_revision(); 890 pcwd_private.revision = get_revision();
877 891
878 if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) { 892 if (!request_region(pcwd_private.io_addr,
893 (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
879 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", 894 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
880 pcwd_private.io_addr); 895 pcwd_private.io_addr);
881 ret=-EIO; 896 ret = -EIO;
882 goto error_request_region; 897 goto error_request_region;
883 } 898 }
884 899
@@ -908,26 +923,30 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
908 if (heartbeat == 0) 923 if (heartbeat == 0)
909 heartbeat = heartbeat_tbl[(pcwd_get_option_switches() & 0x07)]; 924 heartbeat = heartbeat_tbl[(pcwd_get_option_switches() & 0x07)];
910 925
911 /* Check that the heartbeat value is within it's range ; if not reset to the default */ 926 /* Check that the heartbeat value is within it's range;
927 if not reset to the default */
912 if (pcwd_set_heartbeat(heartbeat)) { 928 if (pcwd_set_heartbeat(heartbeat)) {
913 pcwd_set_heartbeat(WATCHDOG_HEARTBEAT); 929 pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
914 printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n", 930 printk(KERN_INFO PFX
915 WATCHDOG_HEARTBEAT); 931 "heartbeat value must be 2 <= heartbeat <= 7200, using %d\n",
932 WATCHDOG_HEARTBEAT);
916 } 933 }
917 934
918 if (pcwd_private.supports_temp) { 935 if (pcwd_private.supports_temp) {
919 ret = misc_register(&temp_miscdev); 936 ret = misc_register(&temp_miscdev);
920 if (ret) { 937 if (ret) {
921 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 938 printk(KERN_ERR PFX
922 TEMP_MINOR, ret); 939 "cannot register miscdev on minor=%d (err=%d)\n",
940 TEMP_MINOR, ret);
923 goto error_misc_register_temp; 941 goto error_misc_register_temp;
924 } 942 }
925 } 943 }
926 944
927 ret = misc_register(&pcwd_miscdev); 945 ret = misc_register(&pcwd_miscdev);
928 if (ret) { 946 if (ret) {
929 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 947 printk(KERN_ERR PFX
930 WATCHDOG_MINOR, ret); 948 "cannot register miscdev on minor=%d (err=%d)\n",
949 WATCHDOG_MINOR, ret);
931 goto error_misc_register_watchdog; 950 goto error_misc_register_watchdog;
932 } 951 }
933 952
@@ -940,7 +959,8 @@ error_misc_register_watchdog:
940 if (pcwd_private.supports_temp) 959 if (pcwd_private.supports_temp)
941 misc_deregister(&temp_miscdev); 960 misc_deregister(&temp_miscdev);
942error_misc_register_temp: 961error_misc_register_temp:
943 release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); 962 release_region(pcwd_private.io_addr,
963 (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
944error_request_region: 964error_request_region:
945 pcwd_private.io_addr = 0x0000; 965 pcwd_private.io_addr = 0x0000;
946 cards_found--; 966 cards_found--;
@@ -964,7 +984,8 @@ static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
964 misc_deregister(&pcwd_miscdev); 984 misc_deregister(&pcwd_miscdev);
965 if (pcwd_private.supports_temp) 985 if (pcwd_private.supports_temp)
966 misc_deregister(&temp_miscdev); 986 misc_deregister(&temp_miscdev);
967 release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); 987 release_region(pcwd_private.io_addr,
988 (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
968 pcwd_private.io_addr = 0x0000; 989 pcwd_private.io_addr = 0x0000;
969 cards_found--; 990 cards_found--;
970 991
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
index 61a89e959642..90eb1d4271d7 100644
--- a/drivers/watchdog/pcwd_pci.c
+++ b/drivers/watchdog/pcwd_pci.c
@@ -46,9 +46,8 @@
46#include <linux/pci.h> /* For pci functions */ 46#include <linux/pci.h> /* For pci functions */
47#include <linux/ioport.h> /* For io-port access */ 47#include <linux/ioport.h> /* For io-port access */
48#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ 48#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
49 49#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
50#include <asm/uaccess.h> /* For copy_to_user/put_user/... */ 50#include <linux/io.h> /* For inb/outb/... */
51#include <asm/io.h> /* For inb/outb/... */
52 51
53/* Module and version information */ 52/* Module and version information */
54#define WATCHDOG_VERSION "1.03" 53#define WATCHDOG_VERSION "1.03"
@@ -97,7 +96,7 @@
97#define CMD_GET_CLEAR_RESET_COUNT 0x84 96#define CMD_GET_CLEAR_RESET_COUNT 0x84
98 97
99/* Watchdog's Dip Switch heartbeat values */ 98/* Watchdog's Dip Switch heartbeat values */
100static const int heartbeat_tbl [] = { 99static const int heartbeat_tbl[] = {
101 5, /* OFF-OFF-OFF = 5 Sec */ 100 5, /* OFF-OFF-OFF = 5 Sec */
102 10, /* OFF-OFF-ON = 10 Sec */ 101 10, /* OFF-OFF-ON = 10 Sec */
103 30, /* OFF-ON-OFF = 30 Sec */ 102 30, /* OFF-ON-OFF = 30 Sec */
@@ -220,11 +219,10 @@ static void pcipcwd_show_card_info(void)
220 int option_switches; 219 int option_switches;
221 220
222 got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); 221 got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);
223 if (got_fw_rev) { 222 if (got_fw_rev)
224 sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); 223 sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
225 } else { 224 else
226 sprintf(fw_ver_str, "<card no answer>"); 225 sprintf(fw_ver_str, "<card no answer>");
227 }
228 226
229 /* Get switch settings */ 227 /* Get switch settings */
230 option_switches = pcipcwd_get_option_switches(); 228 option_switches = pcipcwd_get_option_switches();
@@ -331,7 +329,7 @@ static int pcipcwd_get_status(int *status)
331{ 329{
332 int control_status; 330 int control_status;
333 331
334 *status=0; 332 *status = 0;
335 control_status = inb_p(pcipcwd_private.io_addr + 1); 333 control_status = inb_p(pcipcwd_private.io_addr + 1);
336 if (control_status & WD_PCI_WTRP) 334 if (control_status & WD_PCI_WTRP)
337 *status |= WDIOF_CARDRESET; 335 *status |= WDIOF_CARDRESET;
@@ -369,8 +367,8 @@ static int pcipcwd_clear_status(void)
369 outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1); 367 outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1);
370 368
371 /* clear reset counter */ 369 /* clear reset counter */
372 msb=0; 370 msb = 0;
373 reset_counter=0xff; 371 reset_counter = 0xff;
374 send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter); 372 send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter);
375 373
376 if (debug >= DEBUG) { 374 if (debug >= DEBUG) {
@@ -442,7 +440,7 @@ static ssize_t pcipcwd_write(struct file *file, const char __user *data,
442 /* scan to see whether or not we got the magic character */ 440 /* scan to see whether or not we got the magic character */
443 for (i = 0; i != len; i++) { 441 for (i = 0; i != len; i++) {
444 char c; 442 char c;
445 if(get_user(c, data+i)) 443 if (get_user(c, data + i))
446 return -EFAULT; 444 return -EFAULT;
447 if (c == 'V') 445 if (c == 'V')
448 expect_release = 42; 446 expect_release = 42;
@@ -455,8 +453,8 @@ static ssize_t pcipcwd_write(struct file *file, const char __user *data,
455 return len; 453 return len;
456} 454}
457 455
458static int pcipcwd_ioctl(struct inode *inode, struct file *file, 456static long pcipcwd_ioctl(struct file *file, unsigned int cmd,
459 unsigned int cmd, unsigned long arg) 457 unsigned long arg)
460{ 458{
461 void __user *argp = (void __user *)arg; 459 void __user *argp = (void __user *)arg;
462 int __user *p = argp; 460 int __user *p = argp;
@@ -471,92 +469,89 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file,
471 }; 469 };
472 470
473 switch (cmd) { 471 switch (cmd) {
474 case WDIOC_GETSUPPORT: 472 case WDIOC_GETSUPPORT:
475 return copy_to_user(argp, &ident, 473 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
476 sizeof (ident)) ? -EFAULT : 0; 474
475 case WDIOC_GETSTATUS:
476 {
477 int status;
478 pcipcwd_get_status(&status);
479 return put_user(status, p);
480 }
477 481
478 case WDIOC_GETSTATUS: 482 case WDIOC_GETBOOTSTATUS:
479 { 483 return put_user(pcipcwd_private.boot_status, p);
480 int status;
481 484
482 pcipcwd_get_status(&status); 485 case WDIOC_GETTEMP:
486 {
487 int temperature;
483 488
484 return put_user(status, p); 489 if (pcipcwd_get_temperature(&temperature))
485 } 490 return -EFAULT;
486 491
487 case WDIOC_GETBOOTSTATUS: 492 return put_user(temperature, p);
488 return put_user(pcipcwd_private.boot_status, p); 493 }
489 494
490 case WDIOC_GETTEMP: 495 case WDIOC_SETOPTIONS:
491 { 496 {
492 int temperature; 497 int new_options, retval = -EINVAL;
493 498
494 if (pcipcwd_get_temperature(&temperature)) 499 if (get_user(new_options, p))
495 return -EFAULT; 500 return -EFAULT;
496 501
497 return put_user(temperature, p); 502 if (new_options & WDIOS_DISABLECARD) {
503 if (pcipcwd_stop())
504 return -EIO;
505 retval = 0;
498 } 506 }
499 507
500 case WDIOC_KEEPALIVE: 508 if (new_options & WDIOS_ENABLECARD) {
501 pcipcwd_keepalive(); 509 if (pcipcwd_start())
502 return 0; 510 return -EIO;
503 511 retval = 0;
504 case WDIOC_SETOPTIONS: 512 }
505 {
506 int new_options, retval = -EINVAL;
507
508 if (get_user (new_options, p))
509 return -EFAULT;
510
511 if (new_options & WDIOS_DISABLECARD) {
512 if (pcipcwd_stop())
513 return -EIO;
514 retval = 0;
515 }
516 513
517 if (new_options & WDIOS_ENABLECARD) { 514 if (new_options & WDIOS_TEMPPANIC) {
518 if (pcipcwd_start()) 515 temp_panic = 1;
519 return -EIO; 516 retval = 0;
520 retval = 0; 517 }
521 }
522 518
523 if (new_options & WDIOS_TEMPPANIC) { 519 return retval;
524 temp_panic = 1; 520 }
525 retval = 0;
526 }
527 521
528 return retval; 522 case WDIOC_KEEPALIVE:
529 } 523 pcipcwd_keepalive();
524 return 0;
530 525
531 case WDIOC_SETTIMEOUT: 526 case WDIOC_SETTIMEOUT:
532 { 527 {
533 int new_heartbeat; 528 int new_heartbeat;
534 529
535 if (get_user(new_heartbeat, p)) 530 if (get_user(new_heartbeat, p))
536 return -EFAULT; 531 return -EFAULT;
537 532
538 if (pcipcwd_set_heartbeat(new_heartbeat)) 533 if (pcipcwd_set_heartbeat(new_heartbeat))
539 return -EINVAL; 534 return -EINVAL;
540 535
541 pcipcwd_keepalive(); 536 pcipcwd_keepalive();
542 /* Fall */ 537 /* Fall */
543 } 538 }
544 539
545 case WDIOC_GETTIMEOUT: 540 case WDIOC_GETTIMEOUT:
546 return put_user(heartbeat, p); 541 return put_user(heartbeat, p);
547 542
548 case WDIOC_GETTIMELEFT: 543 case WDIOC_GETTIMELEFT:
549 { 544 {
550 int time_left; 545 int time_left;
551 546
552 if (pcipcwd_get_timeleft(&time_left)) 547 if (pcipcwd_get_timeleft(&time_left))
553 return -EFAULT; 548 return -EFAULT;
554 549
555 return put_user(time_left, p); 550 return put_user(time_left, p);
556 } 551 }
557 552
558 default: 553 default:
559 return -ENOTTY; 554 return -ENOTTY;
560 } 555 }
561} 556}
562 557
@@ -603,7 +598,7 @@ static ssize_t pcipcwd_temp_read(struct file *file, char __user *data,
603 if (pcipcwd_get_temperature(&temperature)) 598 if (pcipcwd_get_temperature(&temperature))
604 return -EFAULT; 599 return -EFAULT;
605 600
606 if (copy_to_user (data, &temperature, 1)) 601 if (copy_to_user(data, &temperature, 1))
607 return -EFAULT; 602 return -EFAULT;
608 603
609 return 1; 604 return 1;
@@ -628,10 +623,8 @@ static int pcipcwd_temp_release(struct inode *inode, struct file *file)
628 623
629static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) 624static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
630{ 625{
631 if (code==SYS_DOWN || code==SYS_HALT) { 626 if (code == SYS_DOWN || code == SYS_HALT)
632 /* Turn the WDT off */ 627 pcipcwd_stop(); /* Turn the WDT off */
633 pcipcwd_stop();
634 }
635 628
636 return NOTIFY_DONE; 629 return NOTIFY_DONE;
637} 630}
@@ -644,7 +637,7 @@ static const struct file_operations pcipcwd_fops = {
644 .owner = THIS_MODULE, 637 .owner = THIS_MODULE,
645 .llseek = no_llseek, 638 .llseek = no_llseek,
646 .write = pcipcwd_write, 639 .write = pcipcwd_write,
647 .ioctl = pcipcwd_ioctl, 640 .unlocked_ioctl = pcipcwd_ioctl,
648 .open = pcipcwd_open, 641 .open = pcipcwd_open,
649 .release = pcipcwd_release, 642 .release = pcipcwd_release,
650}; 643};
diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c
index bf443d077a1e..c1685c942de6 100644
--- a/drivers/watchdog/pcwd_usb.c
+++ b/drivers/watchdog/pcwd_usb.c
@@ -40,8 +40,7 @@
40#include <linux/slab.h> /* For kmalloc, ... */ 40#include <linux/slab.h> /* For kmalloc, ... */
41#include <linux/mutex.h> /* For mutex locking */ 41#include <linux/mutex.h> /* For mutex locking */
42#include <linux/hid.h> /* For HID_REQ_SET_REPORT & HID_DT_REPORT */ 42#include <linux/hid.h> /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
43 43#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
44#include <asm/uaccess.h> /* For copy_to_user/put_user/... */
45 44
46 45
47#ifdef CONFIG_USB_DEBUG 46#ifdef CONFIG_USB_DEBUG
@@ -88,7 +87,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" _
88#define USB_PCWD_PRODUCT_ID 0x1140 87#define USB_PCWD_PRODUCT_ID 0x1140
89 88
90/* table of devices that work with this driver */ 89/* table of devices that work with this driver */
91static struct usb_device_id usb_pcwd_table [] = { 90static struct usb_device_id usb_pcwd_table[] = {
92 { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) }, 91 { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) },
93 { } /* Terminating entry */ 92 { } /* Terminating entry */
94}; 93};
@@ -110,7 +109,7 @@ MODULE_DEVICE_TABLE (usb, usb_pcwd_table);
110#define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG 109#define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG
111 110
112/* Watchdog's Dip Switch heartbeat values */ 111/* Watchdog's Dip Switch heartbeat values */
113static const int heartbeat_tbl [] = { 112static const int heartbeat_tbl[] = {
114 5, /* OFF-OFF-OFF = 5 Sec */ 113 5, /* OFF-OFF-OFF = 5 Sec */
115 10, /* OFF-OFF-ON = 10 Sec */ 114 10, /* OFF-OFF-ON = 10 Sec */
116 30, /* OFF-ON-OFF = 30 Sec */ 115 30, /* OFF-ON-OFF = 30 Sec */
@@ -130,15 +129,15 @@ static char expect_release;
130 129
131/* Structure to hold all of our device specific stuff */ 130/* Structure to hold all of our device specific stuff */
132struct usb_pcwd_private { 131struct usb_pcwd_private {
133 struct usb_device * udev; /* save off the usb device pointer */ 132 struct usb_device *udev; /* save off the usb device pointer */
134 struct usb_interface * interface; /* the interface for this device */ 133 struct usb_interface *interface; /* the interface for this device */
135 134
136 unsigned int interface_number; /* the interface number used for cmd's */ 135 unsigned int interface_number; /* the interface number used for cmd's */
137 136
138 unsigned char * intr_buffer; /* the buffer to intr data */ 137 unsigned char *intr_buffer; /* the buffer to intr data */
139 dma_addr_t intr_dma; /* the dma address for the intr buffer */ 138 dma_addr_t intr_dma; /* the dma address for the intr buffer */
140 size_t intr_size; /* the size of the intr buffer */ 139 size_t intr_size; /* the size of the intr buffer */
141 struct urb * intr_urb; /* the urb used for the intr pipe */ 140 struct urb *intr_urb; /* the urb used for the intr pipe */
142 141
143 unsigned char cmd_command; /* The command that is reported back */ 142 unsigned char cmd_command; /* The command that is reported back */
144 unsigned char cmd_data_msb; /* The data MSB that is reported back */ 143 unsigned char cmd_data_msb; /* The data MSB that is reported back */
@@ -154,8 +153,8 @@ static struct usb_pcwd_private *usb_pcwd_device;
154static DEFINE_MUTEX(disconnect_mutex); 153static DEFINE_MUTEX(disconnect_mutex);
155 154
156/* local function prototypes */ 155/* local function prototypes */
157static int usb_pcwd_probe (struct usb_interface *interface, const struct usb_device_id *id); 156static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_device_id *id);
158static void usb_pcwd_disconnect (struct usb_interface *interface); 157static void usb_pcwd_disconnect(struct usb_interface *interface);
159 158
160/* usb specific object needed to register this driver with the usb subsystem */ 159/* usb specific object needed to register this driver with the usb subsystem */
161static struct usb_driver usb_pcwd_driver = { 160static struct usb_driver usb_pcwd_driver = {
@@ -195,10 +194,10 @@ static void usb_pcwd_intr_done(struct urb *urb)
195 usb_pcwd->cmd_data_lsb = data[2]; 194 usb_pcwd->cmd_data_lsb = data[2];
196 195
197 /* notify anyone waiting that the cmd has finished */ 196 /* notify anyone waiting that the cmd has finished */
198 atomic_set (&usb_pcwd->cmd_received, 1); 197 atomic_set(&usb_pcwd->cmd_received, 1);
199 198
200resubmit: 199resubmit:
201 retval = usb_submit_urb (urb, GFP_ATOMIC); 200 retval = usb_submit_urb(urb, GFP_ATOMIC);
202 if (retval) 201 if (retval)
203 printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n", 202 printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n",
204 retval); 203 retval);
@@ -224,7 +223,7 @@ static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned cha
224 dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x", 223 dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
225 buf[0], buf[1], buf[2]); 224 buf[0], buf[1], buf[2]);
226 225
227 atomic_set (&usb_pcwd->cmd_received, 0); 226 atomic_set(&usb_pcwd->cmd_received, 0);
228 227
229 if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0), 228 if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
230 HID_REQ_SET_REPORT, HID_DT_REPORT, 229 HID_REQ_SET_REPORT, HID_DT_REPORT,
@@ -237,7 +236,7 @@ static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned cha
237 got_response = 0; 236 got_response = 0;
238 for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) { 237 for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) {
239 mdelay(1); 238 mdelay(1);
240 if (atomic_read (&usb_pcwd->cmd_received)) 239 if (atomic_read(&usb_pcwd->cmd_received))
241 got_response = 1; 240 got_response = 1;
242 } 241 }
243 242
@@ -356,7 +355,7 @@ static ssize_t usb_pcwd_write(struct file *file, const char __user *data,
356 /* scan to see whether or not we got the magic character */ 355 /* scan to see whether or not we got the magic character */
357 for (i = 0; i != len; i++) { 356 for (i = 0; i != len; i++) {
358 char c; 357 char c;
359 if(get_user(c, data+i)) 358 if (get_user(c, data + i))
360 return -EFAULT; 359 return -EFAULT;
361 if (c == 'V') 360 if (c == 'V')
362 expect_release = 42; 361 expect_release = 42;
@@ -369,8 +368,8 @@ static ssize_t usb_pcwd_write(struct file *file, const char __user *data,
369 return len; 368 return len;
370} 369}
371 370
372static int usb_pcwd_ioctl(struct inode *inode, struct file *file, 371static long usb_pcwd_ioctl(struct file *file, unsigned int cmd,
373 unsigned int cmd, unsigned long arg) 372 unsigned long arg)
374{ 373{
375 void __user *argp = (void __user *)arg; 374 void __user *argp = (void __user *)arg;
376 int __user *p = argp; 375 int __user *p = argp;
@@ -383,77 +382,76 @@ static int usb_pcwd_ioctl(struct inode *inode, struct file *file,
383 }; 382 };
384 383
385 switch (cmd) { 384 switch (cmd) {
386 case WDIOC_GETSUPPORT: 385 case WDIOC_GETSUPPORT:
387 return copy_to_user(argp, &ident, 386 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
388 sizeof (ident)) ? -EFAULT : 0;
389 387
390 case WDIOC_GETSTATUS: 388 case WDIOC_GETSTATUS:
391 case WDIOC_GETBOOTSTATUS: 389 case WDIOC_GETBOOTSTATUS:
392 return put_user(0, p); 390 return put_user(0, p);
393 391
394 case WDIOC_GETTEMP: 392 case WDIOC_GETTEMP:
395 { 393 {
396 int temperature; 394 int temperature;
397 395
398 if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature)) 396 if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
399 return -EFAULT; 397 return -EFAULT;
400 398
401 return put_user(temperature, p); 399 return put_user(temperature, p);
402 } 400 }
403 401
404 case WDIOC_KEEPALIVE: 402 case WDIOC_SETOPTIONS:
405 usb_pcwd_keepalive(usb_pcwd_device); 403 {
406 return 0; 404 int new_options, retval = -EINVAL;
407 405
408 case WDIOC_SETOPTIONS: 406 if (get_user(new_options, p))
409 { 407 return -EFAULT;
410 int new_options, retval = -EINVAL;
411 408
412 if (get_user (new_options, p)) 409 if (new_options & WDIOS_DISABLECARD) {
413 return -EFAULT; 410 usb_pcwd_stop(usb_pcwd_device);
411 retval = 0;
412 }
414 413
415 if (new_options & WDIOS_DISABLECARD) { 414 if (new_options & WDIOS_ENABLECARD) {
416 usb_pcwd_stop(usb_pcwd_device); 415 usb_pcwd_start(usb_pcwd_device);
417 retval = 0; 416 retval = 0;
418 } 417 }
419 418
420 if (new_options & WDIOS_ENABLECARD) { 419 return retval;
421 usb_pcwd_start(usb_pcwd_device); 420 }
422 retval = 0;
423 }
424 421
425 return retval; 422 case WDIOC_KEEPALIVE:
426 } 423 usb_pcwd_keepalive(usb_pcwd_device);
424 return 0;
427 425
428 case WDIOC_SETTIMEOUT: 426 case WDIOC_SETTIMEOUT:
429 { 427 {
430 int new_heartbeat; 428 int new_heartbeat;
431 429
432 if (get_user(new_heartbeat, p)) 430 if (get_user(new_heartbeat, p))
433 return -EFAULT; 431 return -EFAULT;
434 432
435 if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat)) 433 if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat))
436 return -EINVAL; 434 return -EINVAL;
437 435
438 usb_pcwd_keepalive(usb_pcwd_device); 436 usb_pcwd_keepalive(usb_pcwd_device);
439 /* Fall */ 437 /* Fall */
440 } 438 }
441 439
442 case WDIOC_GETTIMEOUT: 440 case WDIOC_GETTIMEOUT:
443 return put_user(heartbeat, p); 441 return put_user(heartbeat, p);
444 442
445 case WDIOC_GETTIMELEFT: 443 case WDIOC_GETTIMELEFT:
446 { 444 {
447 int time_left; 445 int time_left;
448 446
449 if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left)) 447 if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left))
450 return -EFAULT; 448 return -EFAULT;
451 449
452 return put_user(time_left, p); 450 return put_user(time_left, p);
453 } 451 }
454 452
455 default: 453 default:
456 return -ENOTTY; 454 return -ENOTTY;
457 } 455 }
458} 456}
459 457
@@ -519,10 +517,8 @@ static int usb_pcwd_temperature_release(struct inode *inode, struct file *file)
519 517
520static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) 518static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
521{ 519{
522 if (code==SYS_DOWN || code==SYS_HALT) { 520 if (code == SYS_DOWN || code == SYS_HALT)
523 /* Turn the WDT off */ 521 usb_pcwd_stop(usb_pcwd_device); /* Turn the WDT off */
524 usb_pcwd_stop(usb_pcwd_device);
525 }
526 522
527 return NOTIFY_DONE; 523 return NOTIFY_DONE;
528} 524}
@@ -535,7 +531,7 @@ static const struct file_operations usb_pcwd_fops = {
535 .owner = THIS_MODULE, 531 .owner = THIS_MODULE,
536 .llseek = no_llseek, 532 .llseek = no_llseek,
537 .write = usb_pcwd_write, 533 .write = usb_pcwd_write,
538 .ioctl = usb_pcwd_ioctl, 534 .unlocked_ioctl = usb_pcwd_ioctl,
539 .open = usb_pcwd_open, 535 .open = usb_pcwd_open,
540 .release = usb_pcwd_release, 536 .release = usb_pcwd_release,
541}; 537};
@@ -567,13 +563,13 @@ static struct notifier_block usb_pcwd_notifier = {
567/** 563/**
568 * usb_pcwd_delete 564 * usb_pcwd_delete
569 */ 565 */
570static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd) 566static inline void usb_pcwd_delete(struct usb_pcwd_private *usb_pcwd)
571{ 567{
572 usb_free_urb(usb_pcwd->intr_urb); 568 usb_free_urb(usb_pcwd->intr_urb);
573 if (usb_pcwd->intr_buffer != NULL) 569 if (usb_pcwd->intr_buffer != NULL)
574 usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size, 570 usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size,
575 usb_pcwd->intr_buffer, usb_pcwd->intr_dma); 571 usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
576 kfree (usb_pcwd); 572 kfree(usb_pcwd);
577} 573}
578 574
579/** 575/**
@@ -626,7 +622,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
626 maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); 622 maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
627 623
628 /* allocate memory for our device and initialize it */ 624 /* allocate memory for our device and initialize it */
629 usb_pcwd = kzalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL); 625 usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL);
630 if (usb_pcwd == NULL) { 626 if (usb_pcwd == NULL) {
631 printk(KERN_ERR PFX "Out of memory\n"); 627 printk(KERN_ERR PFX "Out of memory\n");
632 goto error; 628 goto error;
@@ -641,7 +637,8 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
641 usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8); 637 usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8);
642 638
643 /* set up the memory buffer's */ 639 /* set up the memory buffer's */
644 if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma))) { 640 usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma);
641 if (!usb_pcwd->intr_buffer) {
645 printk(KERN_ERR PFX "Out of memory\n"); 642 printk(KERN_ERR PFX "Out of memory\n");
646 goto error; 643 goto error;
647 } 644 }
@@ -675,11 +672,10 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
675 672
676 /* Get the Firmware Version */ 673 /* Get the Firmware Version */
677 got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); 674 got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);
678 if (got_fw_rev) { 675 if (got_fw_rev)
679 sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); 676 sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
680 } else { 677 else
681 sprintf(fw_ver_str, "<card no answer>"); 678 sprintf(fw_ver_str, "<card no answer>");
682 }
683 679
684 printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n", 680 printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n",
685 fw_ver_str); 681 fw_ver_str);
@@ -725,7 +721,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
725 } 721 }
726 722
727 /* we can register the device now, as it is ready */ 723 /* we can register the device now, as it is ready */
728 usb_set_intfdata (interface, usb_pcwd); 724 usb_set_intfdata(interface, usb_pcwd);
729 725
730 printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", 726 printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
731 heartbeat, nowayout); 727 heartbeat, nowayout);
@@ -759,8 +755,8 @@ static void usb_pcwd_disconnect(struct usb_interface *interface)
759 /* prevent races with open() */ 755 /* prevent races with open() */
760 mutex_lock(&disconnect_mutex); 756 mutex_lock(&disconnect_mutex);
761 757
762 usb_pcwd = usb_get_intfdata (interface); 758 usb_pcwd = usb_get_intfdata(interface);
763 usb_set_intfdata (interface, NULL); 759 usb_set_intfdata(interface, NULL);
764 760
765 mutex_lock(&usb_pcwd->mtx); 761 mutex_lock(&usb_pcwd->mtx);
766 762
@@ -820,5 +816,5 @@ static void __exit usb_pcwd_exit(void)
820} 816}
821 817
822 818
823module_init (usb_pcwd_init); 819module_init(usb_pcwd_init);
824module_exit (usb_pcwd_exit); 820module_exit(usb_pcwd_exit);
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index 6b8483d3c783..6eadf5ebb9b3 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -28,10 +28,10 @@
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/clk.h> 29#include <linux/clk.h>
30#include <linux/spinlock.h> 30#include <linux/spinlock.h>
31#include <linux/uaccess.h>
32#include <linux/io.h>
31 33
32#include <asm/hardware.h> 34#include <asm/hardware.h>
33#include <asm/uaccess.h>
34#include <asm/io.h>
35 35
36#define MODULE_NAME "PNX4008-WDT: " 36#define MODULE_NAME "PNX4008-WDT: "
37 37
@@ -144,9 +144,8 @@ static int pnx4008_wdt_open(struct inode *inode, struct file *file)
144 return nonseekable_open(inode, file); 144 return nonseekable_open(inode, file);
145} 145}
146 146
147static ssize_t 147static ssize_t pnx4008_wdt_write(struct file *file, const char *data,
148pnx4008_wdt_write(struct file *file, const char *data, size_t len, 148 size_t len, loff_t *ppos)
149 loff_t * ppos)
150{ 149{
151 if (len) { 150 if (len) {
152 if (!nowayout) { 151 if (!nowayout) {
@@ -169,15 +168,14 @@ pnx4008_wdt_write(struct file *file, const char *data, size_t len,
169 return len; 168 return len;
170} 169}
171 170
172static struct watchdog_info ident = { 171static const struct watchdog_info ident = {
173 .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | 172 .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
174 WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 173 WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
175 .identity = "PNX4008 Watchdog", 174 .identity = "PNX4008 Watchdog",
176}; 175};
177 176
178static int 177static long pnx4008_wdt_ioctl(struct inode *inode, struct file *file,
179pnx4008_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 178 unsigned int cmd, unsigned long arg)
180 unsigned long arg)
181{ 179{
182 int ret = -ENOTTY; 180 int ret = -ENOTTY;
183 int time; 181 int time;
@@ -196,6 +194,11 @@ pnx4008_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
196 ret = put_user(boot_status, (int *)arg); 194 ret = put_user(boot_status, (int *)arg);
197 break; 195 break;
198 196
197 case WDIOC_KEEPALIVE:
198 wdt_enable();
199 ret = 0;
200 break;
201
199 case WDIOC_SETTIMEOUT: 202 case WDIOC_SETTIMEOUT:
200 ret = get_user(time, (int *)arg); 203 ret = get_user(time, (int *)arg);
201 if (ret) 204 if (ret)
@@ -213,11 +216,6 @@ pnx4008_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
213 case WDIOC_GETTIMEOUT: 216 case WDIOC_GETTIMEOUT:
214 ret = put_user(heartbeat, (int *)arg); 217 ret = put_user(heartbeat, (int *)arg);
215 break; 218 break;
216
217 case WDIOC_KEEPALIVE:
218 wdt_enable();
219 ret = 0;
220 break;
221 } 219 }
222 return ret; 220 return ret;
223} 221}
@@ -238,7 +236,7 @@ static const struct file_operations pnx4008_wdt_fops = {
238 .owner = THIS_MODULE, 236 .owner = THIS_MODULE,
239 .llseek = no_llseek, 237 .llseek = no_llseek,
240 .write = pnx4008_wdt_write, 238 .write = pnx4008_wdt_write,
241 .ioctl = pnx4008_wdt_ioctl, 239 .unlocked_ioctl = pnx4008_wdt_ioctl,
242 .open = pnx4008_wdt_open, 240 .open = pnx4008_wdt_open,
243 .release = pnx4008_wdt_release, 241 .release = pnx4008_wdt_release,
244}; 242};
diff --git a/drivers/watchdog/rm9k_wdt.c b/drivers/watchdog/rm9k_wdt.c
index 5c921e471564..f1ae3729a19e 100644
--- a/drivers/watchdog/rm9k_wdt.c
+++ b/drivers/watchdog/rm9k_wdt.c
@@ -29,10 +29,10 @@
29#include <linux/notifier.h> 29#include <linux/notifier.h>
30#include <linux/miscdevice.h> 30#include <linux/miscdevice.h>
31#include <linux/watchdog.h> 31#include <linux/watchdog.h>
32#include <asm/io.h> 32#include <linux/io.h>
33#include <linux/uaccess.h>
33#include <asm/atomic.h> 34#include <asm/atomic.h>
34#include <asm/processor.h> 35#include <asm/processor.h>
35#include <asm/uaccess.h>
36#include <asm/system.h> 36#include <asm/system.h>
37#include <asm/rm9k-ocd.h> 37#include <asm/rm9k-ocd.h>
38 38
@@ -53,10 +53,12 @@ static void wdt_gpi_stop(void);
53static void wdt_gpi_set_timeout(unsigned int); 53static void wdt_gpi_set_timeout(unsigned int);
54static int wdt_gpi_open(struct inode *, struct file *); 54static int wdt_gpi_open(struct inode *, struct file *);
55static int wdt_gpi_release(struct inode *, struct file *); 55static int wdt_gpi_release(struct inode *, struct file *);
56static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t *); 56static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t,
57 loff_t *);
57static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); 58static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long);
58static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); 59static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *);
59static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); 60static const struct resource *wdt_gpi_get_resource(struct platform_device *,
61 const char *, unsigned int);
60static int __init wdt_gpi_probe(struct device *); 62static int __init wdt_gpi_probe(struct device *);
61static int __exit wdt_gpi_remove(struct device *); 63static int __exit wdt_gpi_remove(struct device *);
62 64
@@ -68,7 +70,7 @@ static int locked;
68 70
69 71
70/* These are set from device resources */ 72/* These are set from device resources */
71static void __iomem * wd_regs; 73static void __iomem *wd_regs;
72static unsigned int wd_irq, wd_ctr; 74static unsigned int wd_irq, wd_ctr;
73 75
74 76
@@ -216,7 +218,8 @@ static int wdt_gpi_release(struct inode *inode, struct file *file)
216 if (expect_close) { 218 if (expect_close) {
217 wdt_gpi_stop(); 219 wdt_gpi_stop();
218 free_irq(wd_irq, &miscdev); 220 free_irq(wd_irq, &miscdev);
219 printk(KERN_INFO "%s: watchdog stopped\n", wdt_gpi_name); 221 printk(KERN_INFO "%s: watchdog stopped\n",
222 wdt_gpi_name);
220 } else { 223 } else {
221 printk(KERN_CRIT "%s: unexpected close() -" 224 printk(KERN_CRIT "%s: unexpected close() -"
222 " watchdog left running\n", 225 " watchdog left running\n",
@@ -231,8 +234,8 @@ static int wdt_gpi_release(struct inode *inode, struct file *file)
231 return 0; 234 return 0;
232} 235}
233 236
234static ssize_t 237static ssize_t wdt_gpi_write(struct file *f, const char __user *d, size_t s,
235wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o) 238 loff_t *o)
236{ 239{
237 char val; 240 char val;
238 241
@@ -241,8 +244,7 @@ wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o)
241 return s ? 1 : 0; 244 return s ? 1 : 0;
242} 245}
243 246
244static long 247static long wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
245wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
246{ 248{
247 long res = -ENOTTY; 249 long res = -ENOTTY;
248 const long size = _IOC_SIZE(cmd); 250 const long size = _IOC_SIZE(cmd);
@@ -271,7 +273,8 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
271 case WDIOC_GETSUPPORT: 273 case WDIOC_GETSUPPORT:
272 wdinfo.options = nowayout ? 274 wdinfo.options = nowayout ?
273 WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING : 275 WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING :
274 WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE; 276 WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
277 WDIOF_MAGICCLOSE;
275 res = __copy_to_user(argp, &wdinfo, size) ? -EFAULT : size; 278 res = __copy_to_user(argp, &wdinfo, size) ? -EFAULT : size;
276 break; 279 break;
277 280
@@ -322,8 +325,8 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
322 325
323 326
324/* Shutdown notifier */ 327/* Shutdown notifier */
325static int 328static int wdt_gpi_notify(struct notifier_block *this, unsigned long code,
326wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) 329 void *unused)
327{ 330{
328 if (code == SYS_DOWN || code == SYS_HALT) 331 if (code == SYS_DOWN || code == SYS_HALT)
329 wdt_gpi_stop(); 332 wdt_gpi_stop();
@@ -333,9 +336,8 @@ wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused)
333 336
334 337
335/* Init & exit procedures */ 338/* Init & exit procedures */
336static const struct resource * 339static const struct resource *wdt_gpi_get_resource(struct platform_device *pdv,
337wdt_gpi_get_resource(struct platform_device *pdv, const char *name, 340 const char *name, unsigned int type)
338 unsigned int type)
339{ 341{
340 char buf[80]; 342 char buf[80];
341 if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) 343 if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf)
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 97b4a2e8eb09..44bf5e4282e1 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -305,8 +305,6 @@ static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd,
305 int new_margin; 305 int new_margin;
306 306
307 switch (cmd) { 307 switch (cmd) {
308 default:
309 return -ENOTTY;
310 case WDIOC_GETSUPPORT: 308 case WDIOC_GETSUPPORT:
311 return copy_to_user(argp, &s3c2410_wdt_ident, 309 return copy_to_user(argp, &s3c2410_wdt_ident,
312 sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0; 310 sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0;
@@ -325,6 +323,8 @@ static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd,
325 return put_user(tmr_margin, p); 323 return put_user(tmr_margin, p);
326 case WDIOC_GETTIMEOUT: 324 case WDIOC_GETTIMEOUT:
327 return put_user(tmr_margin, p); 325 return put_user(tmr_margin, p);
326 default:
327 return -ENOTTY;
328 } 328 }
329} 329}
330 330
diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c
index 34a2b3b81800..27d6898a7c98 100644
--- a/drivers/watchdog/sa1100_wdt.c
+++ b/drivers/watchdog/sa1100_wdt.c
@@ -26,13 +26,13 @@
26#include <linux/watchdog.h> 26#include <linux/watchdog.h>
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/bitops.h> 28#include <linux/bitops.h>
29#include <linux/uaccess.h>
29 30
30#ifdef CONFIG_ARCH_PXA 31#ifdef CONFIG_ARCH_PXA
31#include <asm/arch/pxa-regs.h> 32#include <asm/arch/pxa-regs.h>
32#endif 33#endif
33 34
34#include <asm/hardware.h> 35#include <asm/hardware.h>
35#include <asm/uaccess.h>
36 36
37#define OSCR_FREQ CLOCK_TICK_RATE 37#define OSCR_FREQ CLOCK_TICK_RATE
38 38
@@ -45,7 +45,7 @@ static int boot_status;
45 */ 45 */
46static int sa1100dog_open(struct inode *inode, struct file *file) 46static int sa1100dog_open(struct inode *inode, struct file *file)
47{ 47{
48 if (test_and_set_bit(1,&sa1100wdt_users)) 48 if (test_and_set_bit(1, &sa1100wdt_users))
49 return -EBUSY; 49 return -EBUSY;
50 50
51 /* Activate SA1100 Watchdog timer */ 51 /* Activate SA1100 Watchdog timer */
@@ -66,28 +66,27 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
66static int sa1100dog_release(struct inode *inode, struct file *file) 66static int sa1100dog_release(struct inode *inode, struct file *file)
67{ 67{
68 printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); 68 printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");
69
70 clear_bit(1, &sa1100wdt_users); 69 clear_bit(1, &sa1100wdt_users);
71
72 return 0; 70 return 0;
73} 71}
74 72
75static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) 73static ssize_t sa1100dog_write(struct file *file, const char __user *data,
74 size_t len, loff_t *ppos)
76{ 75{
77 if (len) 76 if (len)
78 /* Refresh OSMR3 timer. */ 77 /* Refresh OSMR3 timer. */
79 OSMR3 = OSCR + pre_margin; 78 OSMR3 = OSCR + pre_margin;
80
81 return len; 79 return len;
82} 80}
83 81
84static struct watchdog_info ident = { 82static const struct watchdog_info ident = {
85 .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 83 .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT
84 | WDIOF_KEEPALIVEPING,
86 .identity = "SA1100/PXA255 Watchdog", 85 .identity = "SA1100/PXA255 Watchdog",
87}; 86};
88 87
89static int sa1100dog_ioctl(struct inode *inode, struct file *file, 88static long sa1100dog_ioctl(struct file *file, unsigned int cmd,
90 unsigned int cmd, unsigned long arg) 89 unsigned long arg)
91{ 90{
92 int ret = -ENOTTY; 91 int ret = -ENOTTY;
93 int time; 92 int time;
@@ -108,6 +107,11 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
108 ret = put_user(boot_status, p); 107 ret = put_user(boot_status, p);
109 break; 108 break;
110 109
110 case WDIOC_KEEPALIVE:
111 OSMR3 = OSCR + pre_margin;
112 ret = 0;
113 break;
114
111 case WDIOC_SETTIMEOUT: 115 case WDIOC_SETTIMEOUT:
112 ret = get_user(time, p); 116 ret = get_user(time, p);
113 if (ret) 117 if (ret)
@@ -125,27 +129,20 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
125 case WDIOC_GETTIMEOUT: 129 case WDIOC_GETTIMEOUT:
126 ret = put_user(pre_margin / OSCR_FREQ, p); 130 ret = put_user(pre_margin / OSCR_FREQ, p);
127 break; 131 break;
128
129 case WDIOC_KEEPALIVE:
130 OSMR3 = OSCR + pre_margin;
131 ret = 0;
132 break;
133 } 132 }
134 return ret; 133 return ret;
135} 134}
136 135
137static const struct file_operations sa1100dog_fops = 136static const struct file_operations sa1100dog_fops = {
138{
139 .owner = THIS_MODULE, 137 .owner = THIS_MODULE,
140 .llseek = no_llseek, 138 .llseek = no_llseek,
141 .write = sa1100dog_write, 139 .write = sa1100dog_write,
142 .ioctl = sa1100dog_ioctl, 140 .unlocked_ioctl = sa1100dog_ioctl,
143 .open = sa1100dog_open, 141 .open = sa1100dog_open,
144 .release = sa1100dog_release, 142 .release = sa1100dog_release,
145}; 143};
146 144
147static struct miscdevice sa1100dog_miscdev = 145static struct miscdevice sa1100dog_miscdev = {
148{
149 .minor = WATCHDOG_MINOR, 146 .minor = WATCHDOG_MINOR,
150 .name = "watchdog", 147 .name = "watchdog",
151 .fops = &sa1100dog_fops, 148 .fops = &sa1100dog_fops,
@@ -167,8 +164,9 @@ static int __init sa1100dog_init(void)
167 164
168 ret = misc_register(&sa1100dog_miscdev); 165 ret = misc_register(&sa1100dog_miscdev);
169 if (ret == 0) 166 if (ret == 0)
170 printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", 167 printk(KERN_INFO
171 margin); 168 "SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
169 margin);
172 return ret; 170 return ret;
173} 171}
174 172
diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c
index b94431433695..27e526a07c9a 100644
--- a/drivers/watchdog/sb_wdog.c
+++ b/drivers/watchdog/sb_wdog.c
@@ -57,6 +57,7 @@
57#include <asm/sibyte/sb1250_int.h> 57#include <asm/sibyte/sb1250_int.h>
58#include <asm/sibyte/sb1250_scd.h> 58#include <asm/sibyte/sb1250_scd.h>
59 59
60static DEFINE_SPINLOCK(sbwd_lock);
60 61
61/* 62/*
62 * set the initial count value of a timer 63 * set the initial count value of a timer
@@ -65,8 +66,10 @@
65 */ 66 */
66void sbwdog_set(char __iomem *wdog, unsigned long t) 67void sbwdog_set(char __iomem *wdog, unsigned long t)
67{ 68{
69 spin_lock(&sbwd_lock);
68 __raw_writeb(0, wdog - 0x10); 70 __raw_writeb(0, wdog - 0x10);
69 __raw_writeq(t & 0x7fffffUL, wdog); 71 __raw_writeq(t & 0x7fffffUL, wdog);
72 spin_unlock(&sbwd_lock);
70} 73}
71 74
72/* 75/*
@@ -77,7 +80,9 @@ void sbwdog_set(char __iomem *wdog, unsigned long t)
77 */ 80 */
78void sbwdog_pet(char __iomem *wdog) 81void sbwdog_pet(char __iomem *wdog)
79{ 82{
83 spin_lock(&sbwd_lock);
80 __raw_writeb(__raw_readb(wdog) | 1, wdog); 84 __raw_writeb(__raw_readb(wdog) | 1, wdog);
85 spin_unlock(&sbwd_lock);
81} 86}
82 87
83static unsigned long sbwdog_gate; /* keeps it to one thread only */ 88static unsigned long sbwdog_gate; /* keeps it to one thread only */
@@ -86,8 +91,9 @@ static char __iomem *user_dog = (char __iomem *)(IO_BASE + (A_SCD_WDOG_CFG_1));
86static unsigned long timeout = 0x7fffffUL; /* useconds: 8.3ish secs. */ 91static unsigned long timeout = 0x7fffffUL; /* useconds: 8.3ish secs. */
87static int expect_close; 92static int expect_close;
88 93
89static struct watchdog_info ident = { 94static const struct watchdog_info ident = {
90 .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 95 .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT |
96 WDIOF_KEEPALIVEPING,
91 .identity = "SiByte Watchdog", 97 .identity = "SiByte Watchdog",
92}; 98};
93 99
@@ -97,9 +103,8 @@ static struct watchdog_info ident = {
97static int sbwdog_open(struct inode *inode, struct file *file) 103static int sbwdog_open(struct inode *inode, struct file *file)
98{ 104{
99 nonseekable_open(inode, file); 105 nonseekable_open(inode, file);
100 if (test_and_set_bit(0, &sbwdog_gate)) { 106 if (test_and_set_bit(0, &sbwdog_gate))
101 return -EBUSY; 107 return -EBUSY;
102 }
103 __module_get(THIS_MODULE); 108 __module_get(THIS_MODULE);
104 109
105 /* 110 /*
@@ -120,8 +125,9 @@ static int sbwdog_release(struct inode *inode, struct file *file)
120 __raw_writeb(0, user_dog); 125 __raw_writeb(0, user_dog);
121 module_put(THIS_MODULE); 126 module_put(THIS_MODULE);
122 } else { 127 } else {
123 printk(KERN_CRIT "%s: Unexpected close, not stopping watchdog!\n", 128 printk(KERN_CRIT
124 ident.identity); 129 "%s: Unexpected close, not stopping watchdog!\n",
130 ident.identity);
125 sbwdog_pet(user_dog); 131 sbwdog_pet(user_dog);
126 } 132 }
127 clear_bit(0, &sbwdog_gate); 133 clear_bit(0, &sbwdog_gate);
@@ -147,12 +153,10 @@ static ssize_t sbwdog_write(struct file *file, const char __user *data,
147 for (i = 0; i != len; i++) { 153 for (i = 0; i != len; i++) {
148 char c; 154 char c;
149 155
150 if (get_user(c, data + i)) { 156 if (get_user(c, data + i))
151 return -EFAULT; 157 return -EFAULT;
152 } 158 if (c == 'V')
153 if (c == 'V') {
154 expect_close = 42; 159 expect_close = 42;
155 }
156 } 160 }
157 sbwdog_pet(user_dog); 161 sbwdog_pet(user_dog);
158 } 162 }
@@ -160,8 +164,8 @@ static ssize_t sbwdog_write(struct file *file, const char __user *data,
160 return len; 164 return len;
161} 165}
162 166
163static int sbwdog_ioctl(struct inode *inode, struct file *file, 167static long sbwdog_ioctl(struct file *file, unsigned int cmd,
164 unsigned int cmd, unsigned long arg) 168 unsigned long arg)
165{ 169{
166 int ret = -ENOTTY; 170 int ret = -ENOTTY;
167 unsigned long time; 171 unsigned long time;
@@ -178,11 +182,15 @@ static int sbwdog_ioctl(struct inode *inode, struct file *file,
178 ret = put_user(0, p); 182 ret = put_user(0, p);
179 break; 183 break;
180 184
185 case WDIOC_KEEPALIVE:
186 sbwdog_pet(user_dog);
187 ret = 0;
188 break;
189
181 case WDIOC_SETTIMEOUT: 190 case WDIOC_SETTIMEOUT:
182 ret = get_user(time, p); 191 ret = get_user(time, p);
183 if (ret) { 192 if (ret)
184 break; 193 break;
185 }
186 194
187 time *= 1000000; 195 time *= 1000000;
188 if (time > 0x7fffffUL) { 196 if (time > 0x7fffffUL) {
@@ -200,11 +208,6 @@ static int sbwdog_ioctl(struct inode *inode, struct file *file,
200 */ 208 */
201 ret = put_user(__raw_readq(user_dog - 8) / 1000000, p); 209 ret = put_user(__raw_readq(user_dog - 8) / 1000000, p);
202 break; 210 break;
203
204 case WDIOC_KEEPALIVE:
205 sbwdog_pet(user_dog);
206 ret = 0;
207 break;
208 } 211 }
209 return ret; 212 return ret;
210} 213}
@@ -212,8 +215,8 @@ static int sbwdog_ioctl(struct inode *inode, struct file *file,
212/* 215/*
213 * Notifier for system down 216 * Notifier for system down
214 */ 217 */
215static int 218static int sbwdog_notify_sys(struct notifier_block *this, unsigned long code,
216sbwdog_notify_sys(struct notifier_block *this, unsigned long code, void *erf) 219 void *erf)
217{ 220{
218 if (code == SYS_DOWN || code == SYS_HALT) { 221 if (code == SYS_DOWN || code == SYS_HALT) {
219 /* 222 /*
@@ -226,18 +229,16 @@ sbwdog_notify_sys(struct notifier_block *this, unsigned long code, void *erf)
226 return NOTIFY_DONE; 229 return NOTIFY_DONE;
227} 230}
228 231
229static const struct file_operations sbwdog_fops = 232static const struct file_operations sbwdog_fops = {
230{
231 .owner = THIS_MODULE, 233 .owner = THIS_MODULE,
232 .llseek = no_llseek, 234 .llseek = no_llseek,
233 .write = sbwdog_write, 235 .write = sbwdog_write,
234 .ioctl = sbwdog_ioctl, 236 .unlocked_ioctl = sbwdog_ioctl,
235 .open = sbwdog_open, 237 .open = sbwdog_open,
236 .release = sbwdog_release, 238 .release = sbwdog_release,
237}; 239};
238 240
239static struct miscdevice sbwdog_miscdev = 241static struct miscdevice sbwdog_miscdev = {
240{
241 .minor = WATCHDOG_MINOR, 242 .minor = WATCHDOG_MINOR,
242 .name = "watchdog", 243 .name = "watchdog",
243 .fops = &sbwdog_fops, 244 .fops = &sbwdog_fops,
@@ -267,13 +268,12 @@ irqreturn_t sbwdog_interrupt(int irq, void *addr)
267 /* 268 /*
268 * if it's the second watchdog timer, it's for those users 269 * if it's the second watchdog timer, it's for those users
269 */ 270 */
270 if (wd_cfg_reg == user_dog) { 271 if (wd_cfg_reg == user_dog)
271 printk(KERN_CRIT 272 printk(KERN_CRIT
272 "%s in danger of initiating system reset in %ld.%01ld seconds\n", 273 "%s in danger of initiating system reset in %ld.%01ld seconds\n",
273 ident.identity, wd_init / 1000000, (wd_init / 100000) % 10); 274 ident.identity, wd_init / 1000000, (wd_init / 100000) % 10);
274 } else { 275 else
275 cfg |= 1; 276 cfg |= 1;
276 }
277 277
278 __raw_writeb(cfg, wd_cfg_reg); 278 __raw_writeb(cfg, wd_cfg_reg);
279 279
@@ -289,28 +289,31 @@ static int __init sbwdog_init(void)
289 */ 289 */
290 ret = register_reboot_notifier(&sbwdog_notifier); 290 ret = register_reboot_notifier(&sbwdog_notifier);
291 if (ret) { 291 if (ret) {
292 printk (KERN_ERR "%s: cannot register reboot notifier (err=%d)\n", 292 printk(KERN_ERR
293 ident.identity, ret); 293 "%s: cannot register reboot notifier (err=%d)\n",
294 ident.identity, ret);
294 return ret; 295 return ret;
295 } 296 }
296 297
297 /* 298 /*
298 * get the resources 299 * get the resources
299 */ 300 */
300 ret = misc_register(&sbwdog_miscdev);
301 if (ret == 0) {
302 printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", ident.identity,
303 timeout / 1000000, (timeout / 100000) % 10);
304 }
305 301
306 ret = request_irq(1, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED, 302 ret = request_irq(1, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED,
307 ident.identity, (void *)user_dog); 303 ident.identity, (void *)user_dog);
308 if (ret) { 304 if (ret) {
309 printk(KERN_ERR "%s: failed to request irq 1 - %d\n", ident.identity, 305 printk(KERN_ERR "%s: failed to request irq 1 - %d\n",
310 ret); 306 ident.identity, ret);
311 misc_deregister(&sbwdog_miscdev); 307 return ret;
312 } 308 }
313 309
310 ret = misc_register(&sbwdog_miscdev);
311 if (ret == 0) {
312 printk(KERN_INFO "%s: timeout is %ld.%ld secs\n",
313 ident.identity,
314 timeout / 1000000, (timeout / 100000) % 10);
315 } else
316 free_irq(1, (void *)user_dog);
314 return ret; 317 return ret;
315} 318}
316 319
@@ -327,7 +330,7 @@ MODULE_DESCRIPTION("SiByte Watchdog");
327 330
328module_param(timeout, ulong, 0); 331module_param(timeout, ulong, 0);
329MODULE_PARM_DESC(timeout, 332MODULE_PARM_DESC(timeout,
330 "Watchdog timeout in microseconds (max/default 8388607 or 8.3ish secs)"); 333 "Watchdog timeout in microseconds (max/default 8388607 or 8.3ish secs)");
331 334
332MODULE_LICENSE("GPL"); 335MODULE_LICENSE("GPL");
333MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 336MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
@@ -336,16 +339,15 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
336 * example code that can be put in a platform code area to utilize the 339 * example code that can be put in a platform code area to utilize the
337 * first watchdog timer for the kernels own purpose. 340 * first watchdog timer for the kernels own purpose.
338 341
339 void 342void platform_wd_setup(void)
340platform_wd_setup(void)
341{ 343{
342 int ret; 344 int ret;
343 345
344 ret = request_irq(0, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED, 346 ret = request_irq(1, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED,
345 "Kernel Watchdog", IOADDR(A_SCD_WDOG_CFG_0)); 347 "Kernel Watchdog", IOADDR(A_SCD_WDOG_CFG_0));
346 if (ret) { 348 if (ret) {
347 printk(KERN_CRIT "Watchdog IRQ zero(0) failed to be requested - %d\n", 349 printk(KERN_CRIT
348 ret); 350 "Watchdog IRQ zero(0) failed to be requested - %d\n", ret);
349 } 351 }
350} 352}
351 353
diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c
index ef76f01625e7..3266daaaecf8 100644
--- a/drivers/watchdog/sbc60xxwdt.c
+++ b/drivers/watchdog/sbc60xxwdt.c
@@ -16,19 +16,23 @@
16 * 16 *
17 * 12/4 - 2000 [Initial revision] 17 * 12/4 - 2000 [Initial revision]
18 * 25/4 - 2000 Added /dev/watchdog support 18 * 25/4 - 2000 Added /dev/watchdog support
19 * 09/5 - 2001 [smj@oro.net] fixed fop_write to "return 1" on success 19 * 09/5 - 2001 [smj@oro.net] fixed fop_write to "return 1"
20 * on success
20 * 12/4 - 2002 [rob@osinvestor.com] eliminate fop_read 21 * 12/4 - 2002 [rob@osinvestor.com] eliminate fop_read
21 * fix possible wdt_is_open race 22 * fix possible wdt_is_open race
22 * add CONFIG_WATCHDOG_NOWAYOUT support 23 * add CONFIG_WATCHDOG_NOWAYOUT support
23 * remove lock_kernel/unlock_kernel pairs 24 * remove lock_kernel/unlock_kernel pairs
24 * added KERN_* to printk's 25 * added KERN_* to printk's
25 * got rid of extraneous comments 26 * got rid of extraneous comments
26 * changed watchdog_info to correctly reflect what the driver offers 27 * changed watchdog_info to correctly reflect what
27 * added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT, 28 * the driver offers
28 * WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls 29 * added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS,
30 * WDIOC_SETTIMEOUT, WDIOC_GETTIMEOUT, and
31 * WDIOC_SETOPTIONS ioctls
29 * 09/8 - 2003 [wim@iguana.be] cleanup of trailing spaces 32 * 09/8 - 2003 [wim@iguana.be] cleanup of trailing spaces
30 * use module_param 33 * use module_param
31 * made timeout (the emulated heartbeat) a module_param 34 * made timeout (the emulated heartbeat) a
35 * module_param
32 * made the keepalive ping an internal subroutine 36 * made the keepalive ping an internal subroutine
33 * made wdt_stop and wdt_start module params 37 * made wdt_stop and wdt_start module params
34 * added extra printk's for startup problems 38 * added extra printk's for startup problems
@@ -56,9 +60,9 @@
56#include <linux/notifier.h> 60#include <linux/notifier.h>
57#include <linux/reboot.h> 61#include <linux/reboot.h>
58#include <linux/init.h> 62#include <linux/init.h>
63#include <linux/io.h>
64#include <linux/uaccess.h>
59 65
60#include <asm/io.h>
61#include <asm/uaccess.h>
62#include <asm/system.h> 66#include <asm/system.h>
63 67
64#define OUR_NAME "sbc60xxwdt" 68#define OUR_NAME "sbc60xxwdt"
@@ -94,13 +98,18 @@ MODULE_PARM_DESC(wdt_start, "SBC60xx WDT 'start' io port (default 0x443)");
94 */ 98 */
95 99
96#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ 100#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */
97static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ 101static int timeout = WATCHDOG_TIMEOUT; /* in seconds, multiplied by HZ to
102 get seconds to wait for a ping */
98module_param(timeout, int, 0); 103module_param(timeout, int, 0);
99MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 104MODULE_PARM_DESC(timeout,
105 "Watchdog timeout in seconds. (1<=timeout<=3600, default="
106 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
100 107
101static int nowayout = WATCHDOG_NOWAYOUT; 108static int nowayout = WATCHDOG_NOWAYOUT;
102module_param(nowayout, int, 0); 109module_param(nowayout, int, 0);
103MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 110MODULE_PARM_DESC(nowayout,
111 "Watchdog cannot be stopped once started (default="
112 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
104 113
105static void wdt_timer_ping(unsigned long); 114static void wdt_timer_ping(unsigned long);
106static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0); 115static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
@@ -117,15 +126,14 @@ static void wdt_timer_ping(unsigned long data)
117 /* If we got a heartbeat pulse within the WDT_US_INTERVAL 126 /* If we got a heartbeat pulse within the WDT_US_INTERVAL
118 * we agree to ping the WDT 127 * we agree to ping the WDT
119 */ 128 */
120 if(time_before(jiffies, next_heartbeat)) 129 if (time_before(jiffies, next_heartbeat)) {
121 {
122 /* Ping the WDT by reading from wdt_start */ 130 /* Ping the WDT by reading from wdt_start */
123 inb_p(wdt_start); 131 inb_p(wdt_start);
124 /* Re-set the timer interval */ 132 /* Re-set the timer interval */
125 mod_timer(&timer, jiffies + WDT_INTERVAL); 133 mod_timer(&timer, jiffies + WDT_INTERVAL);
126 } else { 134 } else
127 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); 135 printk(KERN_WARNING PFX
128 } 136 "Heartbeat lost! Will not ping the watchdog\n");
129} 137}
130 138
131/* 139/*
@@ -159,40 +167,40 @@ static void wdt_keepalive(void)
159 * /dev/watchdog handling 167 * /dev/watchdog handling
160 */ 168 */
161 169
162static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) 170static ssize_t fop_write(struct file *file, const char __user *buf,
171 size_t count, loff_t *ppos)
163{ 172{
164 /* See if we got the magic character 'V' and reload the timer */ 173 /* See if we got the magic character 'V' and reload the timer */
165 if(count) 174 if (count) {
166 { 175 if (!nowayout) {
167 if (!nowayout)
168 {
169 size_t ofs; 176 size_t ofs;
170 177
171 /* note: just in case someone wrote the magic character 178 /* note: just in case someone wrote the
172 * five months ago... */ 179 magic character five months ago... */
173 wdt_expect_close = 0; 180 wdt_expect_close = 0;
174 181
175 /* scan to see whether or not we got the magic character */ 182 /* scan to see whether or not we got the
176 for(ofs = 0; ofs != count; ofs++) 183 magic character */
177 { 184 for (ofs = 0; ofs != count; ofs++) {
178 char c; 185 char c;
179 if(get_user(c, buf+ofs)) 186 if (get_user(c, buf + ofs))
180 return -EFAULT; 187 return -EFAULT;
181 if(c == 'V') 188 if (c == 'V')
182 wdt_expect_close = 42; 189 wdt_expect_close = 42;
183 } 190 }
184 } 191 }
185 192
186 /* Well, anyhow someone wrote to us, we should return that favour */ 193 /* Well, anyhow someone wrote to us, we should
194 return that favour */
187 wdt_keepalive(); 195 wdt_keepalive();
188 } 196 }
189 return count; 197 return count;
190} 198}
191 199
192static int fop_open(struct inode * inode, struct file * file) 200static int fop_open(struct inode *inode, struct file *file)
193{ 201{
194 /* Just in case we're already talking to someone... */ 202 /* Just in case we're already talking to someone... */
195 if(test_and_set_bit(0, &wdt_is_open)) 203 if (test_and_set_bit(0, &wdt_is_open))
196 return -EBUSY; 204 return -EBUSY;
197 205
198 if (nowayout) 206 if (nowayout)
@@ -203,78 +211,72 @@ static int fop_open(struct inode * inode, struct file * file)
203 return nonseekable_open(inode, file); 211 return nonseekable_open(inode, file);
204} 212}
205 213
206static int fop_close(struct inode * inode, struct file * file) 214static int fop_close(struct inode *inode, struct file *file)
207{ 215{
208 if(wdt_expect_close == 42) 216 if (wdt_expect_close == 42)
209 wdt_turnoff(); 217 wdt_turnoff();
210 else { 218 else {
211 del_timer(&timer); 219 del_timer(&timer);
212 printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n"); 220 printk(KERN_CRIT PFX
221 "device file closed unexpectedly. Will not stop the WDT!\n");
213 } 222 }
214 clear_bit(0, &wdt_is_open); 223 clear_bit(0, &wdt_is_open);
215 wdt_expect_close = 0; 224 wdt_expect_close = 0;
216 return 0; 225 return 0;
217} 226}
218 227
219static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 228static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
220 unsigned long arg)
221{ 229{
222 void __user *argp = (void __user *)arg; 230 void __user *argp = (void __user *)arg;
223 int __user *p = argp; 231 int __user *p = argp;
224 static struct watchdog_info ident= 232 static const struct watchdog_info ident = {
225 { 233 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
226 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 234 WDIOF_MAGICCLOSE,
227 .firmware_version = 1, 235 .firmware_version = 1,
228 .identity = "SBC60xx", 236 .identity = "SBC60xx",
229 }; 237 };
230 238
231 switch(cmd) 239 switch (cmd) {
240 case WDIOC_GETSUPPORT:
241 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
242 case WDIOC_GETSTATUS:
243 case WDIOC_GETBOOTSTATUS:
244 return put_user(0, p);
245 case WDIOC_SETOPTIONS:
232 { 246 {
233 default: 247 int new_options, retval = -EINVAL;
234 return -ENOTTY; 248 if (get_user(new_options, p))
235 case WDIOC_GETSUPPORT: 249 return -EFAULT;
236 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; 250 if (new_options & WDIOS_DISABLECARD) {
237 case WDIOC_GETSTATUS: 251 wdt_turnoff();
238 case WDIOC_GETBOOTSTATUS: 252 retval = 0;
239 return put_user(0, p);
240 case WDIOC_KEEPALIVE:
241 wdt_keepalive();
242 return 0;
243 case WDIOC_SETOPTIONS:
244 {
245 int new_options, retval = -EINVAL;
246
247 if(get_user(new_options, p))
248 return -EFAULT;
249
250 if(new_options & WDIOS_DISABLECARD) {
251 wdt_turnoff();
252 retval = 0;
253 }
254
255 if(new_options & WDIOS_ENABLECARD) {
256 wdt_startup();
257 retval = 0;
258 }
259
260 return retval;
261 } 253 }
262 case WDIOC_SETTIMEOUT: 254 if (new_options & WDIOS_ENABLECARD) {
263 { 255 wdt_startup();
264 int new_timeout; 256 retval = 0;
265
266 if(get_user(new_timeout, p))
267 return -EFAULT;
268
269 if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
270 return -EINVAL;
271
272 timeout = new_timeout;
273 wdt_keepalive();
274 /* Fall through */
275 } 257 }
276 case WDIOC_GETTIMEOUT: 258 return retval;
277 return put_user(timeout, p); 259 }
260 case WDIOC_KEEPALIVE:
261 wdt_keepalive();
262 return 0;
263 case WDIOC_SETTIMEOUT:
264 {
265 int new_timeout;
266 if (get_user(new_timeout, p))
267 return -EFAULT;
268 /* arbitrary upper limit */
269 if (new_timeout < 1 || new_timeout > 3600)
270 return -EINVAL;
271
272 timeout = new_timeout;
273 wdt_keepalive();
274 /* Fall through */
275 }
276 case WDIOC_GETTIMEOUT:
277 return put_user(timeout, p);
278 default:
279 return -ENOTTY;
278 } 280 }
279} 281}
280 282
@@ -284,7 +286,7 @@ static const struct file_operations wdt_fops = {
284 .write = fop_write, 286 .write = fop_write,
285 .open = fop_open, 287 .open = fop_open,
286 .release = fop_close, 288 .release = fop_close,
287 .ioctl = fop_ioctl, 289 .unlocked_ioctl = fop_ioctl,
288}; 290};
289 291
290static struct miscdevice wdt_miscdev = { 292static struct miscdevice wdt_miscdev = {
@@ -300,7 +302,7 @@ static struct miscdevice wdt_miscdev = {
300static int wdt_notify_sys(struct notifier_block *this, unsigned long code, 302static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
301 void *unused) 303 void *unused)
302{ 304{
303 if(code==SYS_DOWN || code==SYS_HALT) 305 if (code == SYS_DOWN || code == SYS_HALT)
304 wdt_turnoff(); 306 wdt_turnoff();
305 return NOTIFY_DONE; 307 return NOTIFY_DONE;
306} 308}
@@ -310,8 +312,7 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
310 * turn the timebomb registers off. 312 * turn the timebomb registers off.
311 */ 313 */
312 314
313static struct notifier_block wdt_notifier= 315static struct notifier_block wdt_notifier = {
314{
315 .notifier_call = wdt_notify_sys, 316 .notifier_call = wdt_notify_sys,
316}; 317};
317 318
@@ -324,23 +325,22 @@ static void __exit sbc60xxwdt_unload(void)
324 325
325 unregister_reboot_notifier(&wdt_notifier); 326 unregister_reboot_notifier(&wdt_notifier);
326 if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) 327 if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
327 release_region(wdt_stop,1); 328 release_region(wdt_stop, 1);
328 release_region(wdt_start,1); 329 release_region(wdt_start, 1);
329} 330}
330 331
331static int __init sbc60xxwdt_init(void) 332static int __init sbc60xxwdt_init(void)
332{ 333{
333 int rc = -EBUSY; 334 int rc = -EBUSY;
334 335
335 if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ 336 if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */
336 {
337 timeout = WATCHDOG_TIMEOUT; 337 timeout = WATCHDOG_TIMEOUT;
338 printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", 338 printk(KERN_INFO PFX
339 timeout); 339 "timeout value must be 1 <= x <= 3600, using %d\n",
340 } 340 timeout);
341 }
341 342
342 if (!request_region(wdt_start, 1, "SBC 60XX WDT")) 343 if (!request_region(wdt_start, 1, "SBC 60XX WDT")) {
343 {
344 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", 344 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
345 wdt_start); 345 wdt_start);
346 rc = -EIO; 346 rc = -EIO;
@@ -348,33 +348,30 @@ static int __init sbc60xxwdt_init(void)
348 } 348 }
349 349
350 /* We cannot reserve 0x45 - the kernel already has! */ 350 /* We cannot reserve 0x45 - the kernel already has! */
351 if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) 351 if (wdt_stop != 0x45 && wdt_stop != wdt_start) {
352 { 352 if (!request_region(wdt_stop, 1, "SBC 60XX WDT")) {
353 if (!request_region(wdt_stop, 1, "SBC 60XX WDT")) 353 printk(KERN_ERR PFX
354 { 354 "I/O address 0x%04x already in use\n",
355 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", 355 wdt_stop);
356 wdt_stop);
357 rc = -EIO; 356 rc = -EIO;
358 goto err_out_region1; 357 goto err_out_region1;
359 } 358 }
360 } 359 }
361 360
362 rc = register_reboot_notifier(&wdt_notifier); 361 rc = register_reboot_notifier(&wdt_notifier);
363 if (rc) 362 if (rc) {
364 { 363 printk(KERN_ERR PFX
365 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 364 "cannot register reboot notifier (err=%d)\n", rc);
366 rc);
367 goto err_out_region2; 365 goto err_out_region2;
368 } 366 }
369 367
370 rc = misc_register(&wdt_miscdev); 368 rc = misc_register(&wdt_miscdev);
371 if (rc) 369 if (rc) {
372 { 370 printk(KERN_ERR PFX
373 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 371 "cannot register miscdev on minor=%d (err=%d)\n",
374 wdt_miscdev.minor, rc); 372 wdt_miscdev.minor, rc);
375 goto err_out_reboot; 373 goto err_out_reboot;
376 } 374 }
377
378 printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n", 375 printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n",
379 timeout, nowayout); 376 timeout, nowayout);
380 377
@@ -383,10 +380,10 @@ static int __init sbc60xxwdt_init(void)
383err_out_reboot: 380err_out_reboot:
384 unregister_reboot_notifier(&wdt_notifier); 381 unregister_reboot_notifier(&wdt_notifier);
385err_out_region2: 382err_out_region2:
386 if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) 383 if (wdt_stop != 0x45 && wdt_stop != wdt_start)
387 release_region(wdt_stop,1); 384 release_region(wdt_stop, 1);
388err_out_region1: 385err_out_region1:
389 release_region(wdt_start,1); 386 release_region(wdt_start, 1);
390err_out: 387err_out:
391 return rc; 388 return rc;
392} 389}
diff --git a/drivers/watchdog/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c
index 4c8cefbd8627..67ddeb1c830a 100644
--- a/drivers/watchdog/sbc7240_wdt.c
+++ b/drivers/watchdog/sbc7240_wdt.c
@@ -27,10 +27,10 @@
27#include <linux/reboot.h> 27#include <linux/reboot.h>
28#include <linux/types.h> 28#include <linux/types.h>
29#include <linux/watchdog.h> 29#include <linux/watchdog.h>
30#include <linux/io.h>
31#include <linux/uaccess.h>
30#include <asm/atomic.h> 32#include <asm/atomic.h>
31#include <asm/io.h>
32#include <asm/system.h> 33#include <asm/system.h>
33#include <asm/uaccess.h>
34 34
35#define SBC7240_PREFIX "sbc7240_wdt: " 35#define SBC7240_PREFIX "sbc7240_wdt: "
36 36
@@ -159,7 +159,7 @@ static int fop_close(struct inode *inode, struct file *file)
159 return 0; 159 return 0;
160} 160}
161 161
162static struct watchdog_info ident = { 162static const struct watchdog_info ident = {
163 .options = WDIOF_KEEPALIVEPING| 163 .options = WDIOF_KEEPALIVEPING|
164 WDIOF_SETTIMEOUT| 164 WDIOF_SETTIMEOUT|
165 WDIOF_MAGICCLOSE, 165 WDIOF_MAGICCLOSE,
@@ -168,50 +168,50 @@ static struct watchdog_info ident = {
168}; 168};
169 169
170 170
171static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 171static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
172 unsigned long arg)
173{ 172{
174 switch (cmd) { 173 switch (cmd) {
175 case WDIOC_GETSUPPORT: 174 case WDIOC_GETSUPPORT:
176 return copy_to_user 175 return copy_to_user((void __user *)arg, &ident, sizeof(ident))
177 ((void __user *)arg, &ident, sizeof(ident)) 176 ? -EFAULT : 0;
178 ? -EFAULT : 0;
179 case WDIOC_GETSTATUS: 177 case WDIOC_GETSTATUS:
180 case WDIOC_GETBOOTSTATUS: 178 case WDIOC_GETBOOTSTATUS:
181 return put_user(0, (int __user *)arg); 179 return put_user(0, (int __user *)arg);
182 case WDIOC_KEEPALIVE: 180 case WDIOC_SETOPTIONS:
183 wdt_keepalive(); 181 {
184 return 0; 182 int options;
185 case WDIOC_SETOPTIONS:{ 183 int retval = -EINVAL;
186 int options;
187 int retval = -EINVAL;
188 184
189 if (get_user(options, (int __user *)arg)) 185 if (get_user(options, (int __user *)arg))
190 return -EFAULT; 186 return -EFAULT;
191 187
192 if (options & WDIOS_DISABLECARD) { 188 if (options & WDIOS_DISABLECARD) {
193 wdt_disable(); 189 wdt_disable();
194 retval = 0; 190 retval = 0;
195 } 191 }
196
197 if (options & WDIOS_ENABLECARD) {
198 wdt_enable();
199 retval = 0;
200 }
201 192
202 return retval; 193 if (options & WDIOS_ENABLECARD) {
194 wdt_enable();
195 retval = 0;
203 } 196 }
204 case WDIOC_SETTIMEOUT:{
205 int new_timeout;
206 197
207 if (get_user(new_timeout, (int __user *)arg)) 198 return retval;
208 return -EFAULT; 199 }
200 case WDIOC_KEEPALIVE:
201 wdt_keepalive();
202 return 0;
203 case WDIOC_SETTIMEOUT:
204 {
205 int new_timeout;
209 206
210 if (wdt_set_timeout(new_timeout)) 207 if (get_user(new_timeout, (int __user *)arg))
211 return -EINVAL; 208 return -EFAULT;
212 209
213 /* Fall through */ 210 if (wdt_set_timeout(new_timeout))
214 } 211 return -EINVAL;
212
213 /* Fall through */
214 }
215 case WDIOC_GETTIMEOUT: 215 case WDIOC_GETTIMEOUT:
216 return put_user(timeout, (int __user *)arg); 216 return put_user(timeout, (int __user *)arg);
217 default: 217 default:
@@ -225,7 +225,7 @@ static const struct file_operations wdt_fops = {
225 .write = fop_write, 225 .write = fop_write,
226 .open = fop_open, 226 .open = fop_open,
227 .release = fop_close, 227 .release = fop_close,
228 .ioctl = fop_ioctl, 228 .unlocked_ioctl = fop_ioctl,
229}; 229};
230 230
231static struct miscdevice wdt_miscdev = { 231static struct miscdevice wdt_miscdev = {
diff --git a/drivers/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c
index 2ee2677f3648..fd83dd052d8c 100644
--- a/drivers/watchdog/sbc8360.c
+++ b/drivers/watchdog/sbc8360.c
@@ -48,13 +48,12 @@
48#include <linux/init.h> 48#include <linux/init.h>
49#include <linux/spinlock.h> 49#include <linux/spinlock.h>
50#include <linux/moduleparam.h> 50#include <linux/moduleparam.h>
51#include <linux/io.h>
52#include <linux/uaccess.h>
51 53
52#include <asm/io.h>
53#include <asm/uaccess.h>
54#include <asm/system.h> 54#include <asm/system.h>
55 55
56static unsigned long sbc8360_is_open; 56static unsigned long sbc8360_is_open;
57static DEFINE_SPINLOCK(sbc8360_lock);
58static char expect_close; 57static char expect_close;
59 58
60#define PFX "sbc8360: " 59#define PFX "sbc8360: "
@@ -204,7 +203,8 @@ module_param(timeout, int, 0);
204MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))"); 203MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
205module_param(nowayout, int, 0); 204module_param(nowayout, int, 0);
206MODULE_PARM_DESC(nowayout, 205MODULE_PARM_DESC(nowayout,
207 "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 206 "Watchdog cannot be stopped once started (default="
207 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
208 208
209/* 209/*
210 * Kernel methods. 210 * Kernel methods.
@@ -231,9 +231,16 @@ static void sbc8360_ping(void)
231 outb(wd_margin, SBC8360_BASETIME); 231 outb(wd_margin, SBC8360_BASETIME);
232} 232}
233 233
234/* stop watchdog */
235static void sbc8360_stop(void)
236{
237 /* De-activate the watchdog */
238 outb(0, SBC8360_ENABLE);
239}
240
234/* Userspace pings kernel driver, or requests clean close */ 241/* Userspace pings kernel driver, or requests clean close */
235static ssize_t sbc8360_write(struct file *file, const char __user * buf, 242static ssize_t sbc8360_write(struct file *file, const char __user *buf,
236 size_t count, loff_t * ppos) 243 size_t count, loff_t *ppos)
237{ 244{
238 if (count) { 245 if (count) {
239 if (!nowayout) { 246 if (!nowayout) {
@@ -257,16 +264,12 @@ static ssize_t sbc8360_write(struct file *file, const char __user * buf,
257 264
258static int sbc8360_open(struct inode *inode, struct file *file) 265static int sbc8360_open(struct inode *inode, struct file *file)
259{ 266{
260 spin_lock(&sbc8360_lock); 267 if (test_and_set_bit(0, &sbc8360_is_open))
261 if (test_and_set_bit(0, &sbc8360_is_open)) {
262 spin_unlock(&sbc8360_lock);
263 return -EBUSY; 268 return -EBUSY;
264 }
265 if (nowayout) 269 if (nowayout)
266 __module_get(THIS_MODULE); 270 __module_get(THIS_MODULE);
267 271
268 /* Activate and ping once to start the countdown */ 272 /* Activate and ping once to start the countdown */
269 spin_unlock(&sbc8360_lock);
270 sbc8360_activate(); 273 sbc8360_activate();
271 sbc8360_ping(); 274 sbc8360_ping();
272 return nonseekable_open(inode, file); 275 return nonseekable_open(inode, file);
@@ -274,16 +277,14 @@ static int sbc8360_open(struct inode *inode, struct file *file)
274 277
275static int sbc8360_close(struct inode *inode, struct file *file) 278static int sbc8360_close(struct inode *inode, struct file *file)
276{ 279{
277 spin_lock(&sbc8360_lock);
278 if (expect_close == 42) 280 if (expect_close == 42)
279 outb(0, SBC8360_ENABLE); 281 sbc8360_stop();
280 else 282 else
281 printk(KERN_CRIT PFX 283 printk(KERN_CRIT PFX
282 "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n"); 284 "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n");
283 285
284 clear_bit(0, &sbc8360_is_open); 286 clear_bit(0, &sbc8360_is_open);
285 expect_close = 0; 287 expect_close = 0;
286 spin_unlock(&sbc8360_lock);
287 return 0; 288 return 0;
288} 289}
289 290
@@ -294,10 +295,9 @@ static int sbc8360_close(struct inode *inode, struct file *file)
294static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code, 295static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code,
295 void *unused) 296 void *unused)
296{ 297{
297 if (code == SYS_DOWN || code == SYS_HALT) { 298 if (code == SYS_DOWN || code == SYS_HALT)
298 /* Disable the SBC8360 Watchdog */ 299 sbc8360_stop(); /* Disable the SBC8360 Watchdog */
299 outb(0, SBC8360_ENABLE); 300
300 }
301 return NOTIFY_DONE; 301 return NOTIFY_DONE;
302} 302}
303 303
@@ -382,13 +382,13 @@ static int __init sbc8360_init(void)
382 382
383 return 0; 383 return 0;
384 384
385 out_nomisc: 385out_nomisc:
386 unregister_reboot_notifier(&sbc8360_notifier); 386 unregister_reboot_notifier(&sbc8360_notifier);
387 out_noreboot: 387out_noreboot:
388 release_region(SBC8360_BASETIME, 1); 388 release_region(SBC8360_BASETIME, 1);
389 out_nobasetimereg: 389out_nobasetimereg:
390 release_region(SBC8360_ENABLE, 1); 390 release_region(SBC8360_ENABLE, 1);
391 out: 391out:
392 return res; 392 return res;
393} 393}
394 394
diff --git a/drivers/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c
index 82cbd8809a69..e5e470ca7759 100644
--- a/drivers/watchdog/sbc_epx_c3.c
+++ b/drivers/watchdog/sbc_epx_c3.c
@@ -25,8 +25,8 @@
25#include <linux/reboot.h> 25#include <linux/reboot.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/ioport.h> 27#include <linux/ioport.h>
28#include <asm/uaccess.h> 28#include <linux/uaccess.h>
29#include <asm/io.h> 29#include <linux/io.h>
30 30
31#define PFX "epx_c3: " 31#define PFX "epx_c3: "
32static int epx_c3_alive; 32static int epx_c3_alive;
@@ -100,12 +100,12 @@ static ssize_t epx_c3_write(struct file *file, const char __user *data,
100 return len; 100 return len;
101} 101}
102 102
103static int epx_c3_ioctl(struct inode *inode, struct file *file, 103static long epx_c3_ioctl(struct file *file, unsigned int cmd,
104 unsigned int cmd, unsigned long arg) 104 unsigned long arg)
105{ 105{
106 int options, retval = -EINVAL; 106 int options, retval = -EINVAL;
107 int __user *argp = (void __user *)arg; 107 int __user *argp = (void __user *)arg;
108 static struct watchdog_info ident = { 108 static const struct watchdog_info ident = {
109 .options = WDIOF_KEEPALIVEPING | 109 .options = WDIOF_KEEPALIVEPING |
110 WDIOF_MAGICCLOSE, 110 WDIOF_MAGICCLOSE,
111 .firmware_version = 0, 111 .firmware_version = 0,
@@ -120,11 +120,6 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file,
120 case WDIOC_GETSTATUS: 120 case WDIOC_GETSTATUS:
121 case WDIOC_GETBOOTSTATUS: 121 case WDIOC_GETBOOTSTATUS:
122 return put_user(0, argp); 122 return put_user(0, argp);
123 case WDIOC_KEEPALIVE:
124 epx_c3_pet();
125 return 0;
126 case WDIOC_GETTIMEOUT:
127 return put_user(WATCHDOG_TIMEOUT, argp);
128 case WDIOC_SETOPTIONS: 123 case WDIOC_SETOPTIONS:
129 if (get_user(options, argp)) 124 if (get_user(options, argp))
130 return -EFAULT; 125 return -EFAULT;
@@ -140,6 +135,11 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file,
140 } 135 }
141 136
142 return retval; 137 return retval;
138 case WDIOC_KEEPALIVE:
139 epx_c3_pet();
140 return 0;
141 case WDIOC_GETTIMEOUT:
142 return put_user(WATCHDOG_TIMEOUT, argp);
143 default: 143 default:
144 return -ENOTTY; 144 return -ENOTTY;
145 } 145 }
@@ -158,7 +158,7 @@ static const struct file_operations epx_c3_fops = {
158 .owner = THIS_MODULE, 158 .owner = THIS_MODULE,
159 .llseek = no_llseek, 159 .llseek = no_llseek,
160 .write = epx_c3_write, 160 .write = epx_c3_write,
161 .ioctl = epx_c3_ioctl, 161 .unlocked_ioctl = epx_c3_ioctl,
162 .open = epx_c3_open, 162 .open = epx_c3_open,
163 .release = epx_c3_release, 163 .release = epx_c3_release,
164}; 164};
diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c
index 621ebad56d86..23da3ccd832a 100644
--- a/drivers/watchdog/sc1200wdt.c
+++ b/drivers/watchdog/sc1200wdt.c
@@ -196,7 +196,6 @@ static long sc1200wdt_ioctl(struct file *file, unsigned int cmd,
196 }; 196 };
197 197
198 switch (cmd) { 198 switch (cmd) {
199
200 case WDIOC_GETSUPPORT: 199 case WDIOC_GETSUPPORT:
201 if (copy_to_user(argp, &ident, sizeof ident)) 200 if (copy_to_user(argp, &ident, sizeof ident))
202 return -EFAULT; 201 return -EFAULT;
@@ -208,24 +207,6 @@ static long sc1200wdt_ioctl(struct file *file, unsigned int cmd,
208 case WDIOC_GETBOOTSTATUS: 207 case WDIOC_GETBOOTSTATUS:
209 return put_user(0, p); 208 return put_user(0, p);
210 209
211 case WDIOC_KEEPALIVE:
212 sc1200wdt_write_data(WDTO, timeout);
213 return 0;
214
215 case WDIOC_SETTIMEOUT:
216 if (get_user(new_timeout, p))
217 return -EFAULT;
218 /* the API states this is given in secs */
219 new_timeout /= 60;
220 if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
221 return -EINVAL;
222 timeout = new_timeout;
223 sc1200wdt_write_data(WDTO, timeout);
224 /* fall through and return the new timeout */
225
226 case WDIOC_GETTIMEOUT:
227 return put_user(timeout * 60, p);
228
229 case WDIOC_SETOPTIONS: 210 case WDIOC_SETOPTIONS:
230 { 211 {
231 int options, retval = -EINVAL; 212 int options, retval = -EINVAL;
@@ -245,6 +226,24 @@ static long sc1200wdt_ioctl(struct file *file, unsigned int cmd,
245 226
246 return retval; 227 return retval;
247 } 228 }
229 case WDIOC_KEEPALIVE:
230 sc1200wdt_write_data(WDTO, timeout);
231 return 0;
232
233 case WDIOC_SETTIMEOUT:
234 if (get_user(new_timeout, p))
235 return -EFAULT;
236 /* the API states this is given in secs */
237 new_timeout /= 60;
238 if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
239 return -EINVAL;
240 timeout = new_timeout;
241 sc1200wdt_write_data(WDTO, timeout);
242 /* fall through and return the new timeout */
243
244 case WDIOC_GETTIMEOUT:
245 return put_user(timeout * 60, p);
246
248 default: 247 default:
249 return -ENOTTY; 248 return -ENOTTY;
250 } 249 }
@@ -280,7 +279,7 @@ static ssize_t sc1200wdt_write(struct file *file, const char __user *data,
280 for (i = 0; i != len; i++) { 279 for (i = 0; i != len; i++) {
281 char c; 280 char c;
282 281
283 if (get_user(c, data+i)) 282 if (get_user(c, data + i))
284 return -EFAULT; 283 return -EFAULT;
285 if (c == 'V') 284 if (c == 'V')
286 expect_close = 42; 285 expect_close = 42;
diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c
index 2847324a2be2..a2b6c1067ec5 100644
--- a/drivers/watchdog/sc520_wdt.c
+++ b/drivers/watchdog/sc520_wdt.c
@@ -64,9 +64,9 @@
64#include <linux/reboot.h> 64#include <linux/reboot.h>
65#include <linux/init.h> 65#include <linux/init.h>
66#include <linux/jiffies.h> 66#include <linux/jiffies.h>
67#include <linux/io.h>
68#include <linux/uaccess.h>
67 69
68#include <asm/io.h>
69#include <asm/uaccess.h>
70#include <asm/system.h> 70#include <asm/system.h>
71 71
72#define OUR_NAME "sc520_wdt" 72#define OUR_NAME "sc520_wdt"
@@ -91,13 +91,18 @@
91 */ 91 */
92 92
93#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ 93#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */
94static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ 94/* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
95static int timeout = WATCHDOG_TIMEOUT;
95module_param(timeout, int, 0); 96module_param(timeout, int, 0);
96MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 97MODULE_PARM_DESC(timeout,
98 "Watchdog timeout in seconds. (1 <= timeout <= 3600, default="
99 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
97 100
98static int nowayout = WATCHDOG_NOWAYOUT; 101static int nowayout = WATCHDOG_NOWAYOUT;
99module_param(nowayout, int, 0); 102module_param(nowayout, int, 0);
100MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 103MODULE_PARM_DESC(nowayout,
104 "Watchdog cannot be stopped once started (default="
105 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
101 106
102/* 107/*
103 * AMD Elan SC520 - Watchdog Timer Registers 108 * AMD Elan SC520 - Watchdog Timer Registers
@@ -136,8 +141,7 @@ static void wdt_timer_ping(unsigned long data)
136 /* If we got a heartbeat pulse within the WDT_US_INTERVAL 141 /* If we got a heartbeat pulse within the WDT_US_INTERVAL
137 * we agree to ping the WDT 142 * we agree to ping the WDT
138 */ 143 */
139 if(time_before(jiffies, next_heartbeat)) 144 if (time_before(jiffies, next_heartbeat)) {
140 {
141 /* Ping the WDT */ 145 /* Ping the WDT */
142 spin_lock(&wdt_spinlock); 146 spin_lock(&wdt_spinlock);
143 writew(0xAAAA, wdtmrctl); 147 writew(0xAAAA, wdtmrctl);
@@ -146,9 +150,9 @@ static void wdt_timer_ping(unsigned long data)
146 150
147 /* Re-set the timer interval */ 151 /* Re-set the timer interval */
148 mod_timer(&timer, jiffies + WDT_INTERVAL); 152 mod_timer(&timer, jiffies + WDT_INTERVAL);
149 } else { 153 } else
150 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); 154 printk(KERN_WARNING PFX
151 } 155 "Heartbeat lost! Will not ping the watchdog\n");
152} 156}
153 157
154/* 158/*
@@ -162,7 +166,7 @@ static void wdt_config(int writeval)
162 166
163 /* buy some time (ping) */ 167 /* buy some time (ping) */
164 spin_lock_irqsave(&wdt_spinlock, flags); 168 spin_lock_irqsave(&wdt_spinlock, flags);
165 dummy=readw(wdtmrctl); /* ensure write synchronization */ 169 dummy = readw(wdtmrctl); /* ensure write synchronization */
166 writew(0xAAAA, wdtmrctl); 170 writew(0xAAAA, wdtmrctl);
167 writew(0x5555, wdtmrctl); 171 writew(0x5555, wdtmrctl);
168 /* unlock WDT = make WDT configuration register writable one time */ 172 /* unlock WDT = make WDT configuration register writable one time */
@@ -219,10 +223,11 @@ static int wdt_set_heartbeat(int t)
219 * /dev/watchdog handling 223 * /dev/watchdog handling
220 */ 224 */
221 225
222static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) 226static ssize_t fop_write(struct file *file, const char __user *buf,
227 size_t count, loff_t *ppos)
223{ 228{
224 /* See if we got the magic character 'V' and reload the timer */ 229 /* See if we got the magic character 'V' and reload the timer */
225 if(count) { 230 if (count) {
226 if (!nowayout) { 231 if (!nowayout) {
227 size_t ofs; 232 size_t ofs;
228 233
@@ -231,25 +236,26 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou
231 wdt_expect_close = 0; 236 wdt_expect_close = 0;
232 237
233 /* now scan */ 238 /* now scan */
234 for(ofs = 0; ofs != count; ofs++) { 239 for (ofs = 0; ofs != count; ofs++) {
235 char c; 240 char c;
236 if (get_user(c, buf + ofs)) 241 if (get_user(c, buf + ofs))
237 return -EFAULT; 242 return -EFAULT;
238 if(c == 'V') 243 if (c == 'V')
239 wdt_expect_close = 42; 244 wdt_expect_close = 42;
240 } 245 }
241 } 246 }
242 247
243 /* Well, anyhow someone wrote to us, we should return that favour */ 248 /* Well, anyhow someone wrote to us, we should
249 return that favour */
244 wdt_keepalive(); 250 wdt_keepalive();
245 } 251 }
246 return count; 252 return count;
247} 253}
248 254
249static int fop_open(struct inode * inode, struct file * file) 255static int fop_open(struct inode *inode, struct file *file)
250{ 256{
251 /* Just in case we're already talking to someone... */ 257 /* Just in case we're already talking to someone... */
252 if(test_and_set_bit(0, &wdt_is_open)) 258 if (test_and_set_bit(0, &wdt_is_open))
253 return -EBUSY; 259 return -EBUSY;
254 if (nowayout) 260 if (nowayout)
255 __module_get(THIS_MODULE); 261 __module_get(THIS_MODULE);
@@ -259,12 +265,13 @@ static int fop_open(struct inode * inode, struct file * file)
259 return nonseekable_open(inode, file); 265 return nonseekable_open(inode, file);
260} 266}
261 267
262static int fop_close(struct inode * inode, struct file * file) 268static int fop_close(struct inode *inode, struct file *file)
263{ 269{
264 if(wdt_expect_close == 42) { 270 if (wdt_expect_close == 42)
265 wdt_turnoff(); 271 wdt_turnoff();
266 } else { 272 else {
267 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 273 printk(KERN_CRIT PFX
274 "Unexpected close, not stopping watchdog!\n");
268 wdt_keepalive(); 275 wdt_keepalive();
269 } 276 }
270 clear_bit(0, &wdt_is_open); 277 clear_bit(0, &wdt_is_open);
@@ -272,63 +279,62 @@ static int fop_close(struct inode * inode, struct file * file)
272 return 0; 279 return 0;
273} 280}
274 281
275static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 282static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
276 unsigned long arg)
277{ 283{
278 void __user *argp = (void __user *)arg; 284 void __user *argp = (void __user *)arg;
279 int __user *p = argp; 285 int __user *p = argp;
280 static struct watchdog_info ident = { 286 static const struct watchdog_info ident = {
281 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 287 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
288 | WDIOF_MAGICCLOSE,
282 .firmware_version = 1, 289 .firmware_version = 1,
283 .identity = "SC520", 290 .identity = "SC520",
284 }; 291 };
285 292
286 switch(cmd) 293 switch (cmd) {
294 case WDIOC_GETSUPPORT:
295 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
296 case WDIOC_GETSTATUS:
297 case WDIOC_GETBOOTSTATUS:
298 return put_user(0, p);
299 case WDIOC_SETOPTIONS:
287 { 300 {
288 default: 301 int new_options, retval = -EINVAL;
289 return -ENOTTY;
290 case WDIOC_GETSUPPORT:
291 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
292 case WDIOC_GETSTATUS:
293 case WDIOC_GETBOOTSTATUS:
294 return put_user(0, p);
295 case WDIOC_KEEPALIVE:
296 wdt_keepalive();
297 return 0;
298 case WDIOC_SETOPTIONS:
299 {
300 int new_options, retval = -EINVAL;
301
302 if(get_user(new_options, p))
303 return -EFAULT;
304
305 if(new_options & WDIOS_DISABLECARD) {
306 wdt_turnoff();
307 retval = 0;
308 }
309 302
310 if(new_options & WDIOS_ENABLECARD) { 303 if (get_user(new_options, p))
311 wdt_startup(); 304 return -EFAULT;
312 retval = 0;
313 }
314 305
315 return retval; 306 if (new_options & WDIOS_DISABLECARD) {
307 wdt_turnoff();
308 retval = 0;
316 } 309 }
317 case WDIOC_SETTIMEOUT:
318 {
319 int new_timeout;
320 310
321 if(get_user(new_timeout, p)) 311 if (new_options & WDIOS_ENABLECARD) {
322 return -EFAULT; 312 wdt_startup();
313 retval = 0;
314 }
323 315
324 if(wdt_set_heartbeat(new_timeout)) 316 return retval;
325 return -EINVAL; 317 }
318 case WDIOC_KEEPALIVE:
319 wdt_keepalive();
320 return 0;
321 case WDIOC_SETTIMEOUT:
322 {
323 int new_timeout;
326 324
327 wdt_keepalive(); 325 if (get_user(new_timeout, p))
328 /* Fall through */ 326 return -EFAULT;
329 } 327
330 case WDIOC_GETTIMEOUT: 328 if (wdt_set_heartbeat(new_timeout))
331 return put_user(timeout, p); 329 return -EINVAL;
330
331 wdt_keepalive();
332 /* Fall through */
333 }
334 case WDIOC_GETTIMEOUT:
335 return put_user(timeout, p);
336 default:
337 return -ENOTTY;
332 } 338 }
333} 339}
334 340
@@ -338,7 +344,7 @@ static const struct file_operations wdt_fops = {
338 .write = fop_write, 344 .write = fop_write,
339 .open = fop_open, 345 .open = fop_open,
340 .release = fop_close, 346 .release = fop_close,
341 .ioctl = fop_ioctl, 347 .unlocked_ioctl = fop_ioctl,
342}; 348};
343 349
344static struct miscdevice wdt_miscdev = { 350static struct miscdevice wdt_miscdev = {
@@ -354,7 +360,7 @@ static struct miscdevice wdt_miscdev = {
354static int wdt_notify_sys(struct notifier_block *this, unsigned long code, 360static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
355 void *unused) 361 void *unused)
356{ 362{
357 if(code==SYS_DOWN || code==SYS_HALT) 363 if (code == SYS_DOWN || code == SYS_HALT)
358 wdt_turnoff(); 364 wdt_turnoff();
359 return NOTIFY_DONE; 365 return NOTIFY_DONE;
360} 366}
@@ -383,11 +389,13 @@ static int __init sc520_wdt_init(void)
383{ 389{
384 int rc = -EBUSY; 390 int rc = -EBUSY;
385 391
386 /* Check that the timeout value is within it's range ; if not reset to the default */ 392 /* Check that the timeout value is within it's range ;
393 if not reset to the default */
387 if (wdt_set_heartbeat(timeout)) { 394 if (wdt_set_heartbeat(timeout)) {
388 wdt_set_heartbeat(WATCHDOG_TIMEOUT); 395 wdt_set_heartbeat(WATCHDOG_TIMEOUT);
389 printk(KERN_INFO PFX "timeout value must be 1<=timeout<=3600, using %d\n", 396 printk(KERN_INFO PFX
390 WATCHDOG_TIMEOUT); 397 "timeout value must be 1 <= timeout <= 3600, using %d\n",
398 WATCHDOG_TIMEOUT);
391 } 399 }
392 400
393 wdtmrctl = ioremap((unsigned long)(MMCR_BASE + OFFS_WDTMRCTL), 2); 401 wdtmrctl = ioremap((unsigned long)(MMCR_BASE + OFFS_WDTMRCTL), 2);
@@ -399,20 +407,22 @@ static int __init sc520_wdt_init(void)
399 407
400 rc = register_reboot_notifier(&wdt_notifier); 408 rc = register_reboot_notifier(&wdt_notifier);
401 if (rc) { 409 if (rc) {
402 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 410 printk(KERN_ERR PFX
403 rc); 411 "cannot register reboot notifier (err=%d)\n", rc);
404 goto err_out_ioremap; 412 goto err_out_ioremap;
405 } 413 }
406 414
407 rc = misc_register(&wdt_miscdev); 415 rc = misc_register(&wdt_miscdev);
408 if (rc) { 416 if (rc) {
409 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 417 printk(KERN_ERR PFX
410 WATCHDOG_MINOR, rc); 418 "cannot register miscdev on minor=%d (err=%d)\n",
419 WATCHDOG_MINOR, rc);
411 goto err_out_notifier; 420 goto err_out_notifier;
412 } 421 }
413 422
414 printk(KERN_INFO PFX "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n", 423 printk(KERN_INFO PFX
415 timeout,nowayout); 424 "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n",
425 timeout, nowayout);
416 426
417 return 0; 427 return 0;
418 428
diff --git a/drivers/watchdog/scx200_wdt.c b/drivers/watchdog/scx200_wdt.c
index d55882bca319..9e19a10a5bb9 100644
--- a/drivers/watchdog/scx200_wdt.c
+++ b/drivers/watchdog/scx200_wdt.c
@@ -27,9 +27,8 @@
27#include <linux/fs.h> 27#include <linux/fs.h>
28#include <linux/ioport.h> 28#include <linux/ioport.h>
29#include <linux/scx200.h> 29#include <linux/scx200.h>
30 30#include <linux/uaccess.h>
31#include <asm/uaccess.h> 31#include <linux/io.h>
32#include <asm/io.h>
33 32
34#define NAME "scx200_wdt" 33#define NAME "scx200_wdt"
35 34
@@ -47,8 +46,9 @@ module_param(nowayout, int, 0);
47MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); 46MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
48 47
49static u16 wdto_restart; 48static u16 wdto_restart;
50static struct semaphore open_semaphore;
51static char expect_close; 49static char expect_close;
50static unsigned long open_lock;
51static DEFINE_SPINLOCK(scx_lock);
52 52
53/* Bits of the WDCNFG register */ 53/* Bits of the WDCNFG register */
54#define W_ENABLE 0x00fa /* Enable watchdog */ 54#define W_ENABLE 0x00fa /* Enable watchdog */
@@ -59,7 +59,9 @@ static char expect_close;
59 59
60static void scx200_wdt_ping(void) 60static void scx200_wdt_ping(void)
61{ 61{
62 spin_lock(&scx_lock);
62 outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO); 63 outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO);
64 spin_unlock(&scx_lock);
63} 65}
64 66
65static void scx200_wdt_update_margin(void) 67static void scx200_wdt_update_margin(void)
@@ -73,9 +75,11 @@ static void scx200_wdt_enable(void)
73 printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n", 75 printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n",
74 wdto_restart); 76 wdto_restart);
75 77
78 spin_lock(&scx_lock);
76 outw(0, scx200_cb_base + SCx200_WDT_WDTO); 79 outw(0, scx200_cb_base + SCx200_WDT_WDTO);
77 outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS); 80 outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
78 outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG); 81 outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
82 spin_unlock(&scx_lock);
79 83
80 scx200_wdt_ping(); 84 scx200_wdt_ping();
81} 85}
@@ -84,15 +88,17 @@ static void scx200_wdt_disable(void)
84{ 88{
85 printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); 89 printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
86 90
91 spin_lock(&scx_lock);
87 outw(0, scx200_cb_base + SCx200_WDT_WDTO); 92 outw(0, scx200_cb_base + SCx200_WDT_WDTO);
88 outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS); 93 outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
89 outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG); 94 outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
95 spin_unlock(&scx_lock);
90} 96}
91 97
92static int scx200_wdt_open(struct inode *inode, struct file *file) 98static int scx200_wdt_open(struct inode *inode, struct file *file)
93{ 99{
94 /* only allow one at a time */ 100 /* only allow one at a time */
95 if (down_trylock(&open_semaphore)) 101 if (test_and_set_bit(0, &open_lock))
96 return -EBUSY; 102 return -EBUSY;
97 scx200_wdt_enable(); 103 scx200_wdt_enable();
98 104
@@ -101,13 +107,12 @@ static int scx200_wdt_open(struct inode *inode, struct file *file)
101 107
102static int scx200_wdt_release(struct inode *inode, struct file *file) 108static int scx200_wdt_release(struct inode *inode, struct file *file)
103{ 109{
104 if (expect_close != 42) { 110 if (expect_close != 42)
105 printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n"); 111 printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n");
106 } else if (!nowayout) { 112 else if (!nowayout)
107 scx200_wdt_disable(); 113 scx200_wdt_disable();
108 }
109 expect_close = 0; 114 expect_close = 0;
110 up(&open_semaphore); 115 clear_bit(0, &open_lock);
111 116
112 return 0; 117 return 0;
113} 118}
@@ -122,8 +127,7 @@ static int scx200_wdt_notify_sys(struct notifier_block *this,
122 return NOTIFY_DONE; 127 return NOTIFY_DONE;
123} 128}
124 129
125static struct notifier_block scx200_wdt_notifier = 130static struct notifier_block scx200_wdt_notifier = {
126{
127 .notifier_call = scx200_wdt_notify_sys, 131 .notifier_call = scx200_wdt_notify_sys,
128}; 132};
129 133
@@ -131,8 +135,7 @@ static ssize_t scx200_wdt_write(struct file *file, const char __user *data,
131 size_t len, loff_t *ppos) 135 size_t len, loff_t *ppos)
132{ 136{
133 /* check for a magic close character */ 137 /* check for a magic close character */
134 if (len) 138 if (len) {
135 {
136 size_t i; 139 size_t i;
137 140
138 scx200_wdt_ping(); 141 scx200_wdt_ping();
@@ -140,7 +143,7 @@ static ssize_t scx200_wdt_write(struct file *file, const char __user *data,
140 expect_close = 0; 143 expect_close = 0;
141 for (i = 0; i < len; ++i) { 144 for (i = 0; i < len; ++i) {
142 char c; 145 char c;
143 if (get_user(c, data+i)) 146 if (get_user(c, data + i))
144 return -EFAULT; 147 return -EFAULT;
145 if (c == 'V') 148 if (c == 'V')
146 expect_close = 42; 149 expect_close = 42;
@@ -152,23 +155,21 @@ static ssize_t scx200_wdt_write(struct file *file, const char __user *data,
152 return 0; 155 return 0;
153} 156}
154 157
155static int scx200_wdt_ioctl(struct inode *inode, struct file *file, 158static long scx200_wdt_ioctl(struct file *file, unsigned int cmd,
156 unsigned int cmd, unsigned long arg) 159 unsigned long arg)
157{ 160{
158 void __user *argp = (void __user *)arg; 161 void __user *argp = (void __user *)arg;
159 int __user *p = argp; 162 int __user *p = argp;
160 static struct watchdog_info ident = { 163 static const struct watchdog_info ident = {
161 .identity = "NatSemi SCx200 Watchdog", 164 .identity = "NatSemi SCx200 Watchdog",
162 .firmware_version = 1, 165 .firmware_version = 1,
163 .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING), 166 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
164 }; 167 };
165 int new_margin; 168 int new_margin;
166 169
167 switch (cmd) { 170 switch (cmd) {
168 default:
169 return -ENOTTY;
170 case WDIOC_GETSUPPORT: 171 case WDIOC_GETSUPPORT:
171 if(copy_to_user(argp, &ident, sizeof(ident))) 172 if (copy_to_user(argp, &ident, sizeof(ident)))
172 return -EFAULT; 173 return -EFAULT;
173 return 0; 174 return 0;
174 case WDIOC_GETSTATUS: 175 case WDIOC_GETSTATUS:
@@ -191,22 +192,24 @@ static int scx200_wdt_ioctl(struct inode *inode, struct file *file,
191 if (put_user(margin, p)) 192 if (put_user(margin, p))
192 return -EFAULT; 193 return -EFAULT;
193 return 0; 194 return 0;
195 default:
196 return -ENOTTY;
194 } 197 }
195} 198}
196 199
197static const struct file_operations scx200_wdt_fops = { 200static const struct file_operations scx200_wdt_fops = {
198 .owner = THIS_MODULE, 201 .owner = THIS_MODULE,
199 .llseek = no_llseek, 202 .llseek = no_llseek,
200 .write = scx200_wdt_write, 203 .write = scx200_wdt_write,
201 .ioctl = scx200_wdt_ioctl, 204 .unlocked_ioctl = scx200_wdt_ioctl,
202 .open = scx200_wdt_open, 205 .open = scx200_wdt_open,
203 .release = scx200_wdt_release, 206 .release = scx200_wdt_release,
204}; 207};
205 208
206static struct miscdevice scx200_wdt_miscdev = { 209static struct miscdevice scx200_wdt_miscdev = {
207 .minor = WATCHDOG_MINOR, 210 .minor = WATCHDOG_MINOR,
208 .name = "watchdog", 211 .name = "watchdog",
209 .fops = &scx200_wdt_fops, 212 .fops = &scx200_wdt_fops,
210}; 213};
211 214
212static int __init scx200_wdt_init(void) 215static int __init scx200_wdt_init(void)
@@ -229,8 +232,6 @@ static int __init scx200_wdt_init(void)
229 scx200_wdt_update_margin(); 232 scx200_wdt_update_margin();
230 scx200_wdt_disable(); 233 scx200_wdt_disable();
231 234
232 sema_init(&open_semaphore, 1);
233
234 r = register_reboot_notifier(&scx200_wdt_notifier); 235 r = register_reboot_notifier(&scx200_wdt_notifier);
235 if (r) { 236 if (r) {
236 printk(KERN_ERR NAME ": unable to register reboot notifier"); 237 printk(KERN_ERR NAME ": unable to register reboot notifier");
@@ -263,7 +264,7 @@ module_exit(scx200_wdt_cleanup);
263 264
264/* 265/*
265 Local variables: 266 Local variables:
266 compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules" 267 compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules"
267 c-basic-offset: 8 268 c-basic-offset: 8
268 End: 269 End:
269*/ 270*/
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index 1277f7e9cc54..824125adf90a 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -28,9 +28,9 @@
28#include <linux/ioport.h> 28#include <linux/ioport.h>
29#include <linux/fs.h> 29#include <linux/fs.h>
30#include <linux/mm.h> 30#include <linux/mm.h>
31#include <asm/io.h> 31#include <linux/io.h>
32#include <asm/uaccess.h> 32#include <linux/uaccess.h>
33#include <asm/watchdog.h> 33#include <linux/watchdog.h>
34 34
35#define PFX "shwdt: " 35#define PFX "shwdt: "
36 36
@@ -72,6 +72,7 @@ static struct watchdog_info sh_wdt_info;
72static char shwdt_expect_close; 72static char shwdt_expect_close;
73static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0); 73static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0);
74static unsigned long next_heartbeat; 74static unsigned long next_heartbeat;
75static DEFINE_SPINLOCK(shwdt_lock);
75 76
76#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ 77#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
77static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 78static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
@@ -86,6 +87,9 @@ static int nowayout = WATCHDOG_NOWAYOUT;
86static void sh_wdt_start(void) 87static void sh_wdt_start(void)
87{ 88{
88 __u8 csr; 89 __u8 csr;
90 unsigned long flags;
91
92 spin_lock_irqsave(&wdt_lock, flags);
89 93
90 next_heartbeat = jiffies + (heartbeat * HZ); 94 next_heartbeat = jiffies + (heartbeat * HZ);
91 mod_timer(&timer, next_ping_period(clock_division_ratio)); 95 mod_timer(&timer, next_ping_period(clock_division_ratio));
@@ -123,6 +127,7 @@ static void sh_wdt_start(void)
123 csr &= ~RSTCSR_RSTS; 127 csr &= ~RSTCSR_RSTS;
124 sh_wdt_write_rstcsr(csr); 128 sh_wdt_write_rstcsr(csr);
125#endif 129#endif
130 spin_unlock_irqrestore(&wdt_lock, flags);
126} 131}
127 132
128/** 133/**
@@ -132,12 +137,16 @@ static void sh_wdt_start(void)
132static void sh_wdt_stop(void) 137static void sh_wdt_stop(void)
133{ 138{
134 __u8 csr; 139 __u8 csr;
140 unsigned long flags;
141
142 spin_lock_irqsave(&wdt_lock, flags);
135 143
136 del_timer(&timer); 144 del_timer(&timer);
137 145
138 csr = sh_wdt_read_csr(); 146 csr = sh_wdt_read_csr();
139 csr &= ~WTCSR_TME; 147 csr &= ~WTCSR_TME;
140 sh_wdt_write_csr(csr); 148 sh_wdt_write_csr(csr);
149 spin_unlock_irqrestore(&wdt_lock, flags);
141} 150}
142 151
143/** 152/**
@@ -146,7 +155,11 @@ static void sh_wdt_stop(void)
146 */ 155 */
147static inline void sh_wdt_keepalive(void) 156static inline void sh_wdt_keepalive(void)
148{ 157{
158 unsigned long flags;
159
160 spin_lock_irqsave(&wdt_lock, flags);
149 next_heartbeat = jiffies + (heartbeat * HZ); 161 next_heartbeat = jiffies + (heartbeat * HZ);
162 spin_unlock_irqrestore(&wdt_lock, flags);
150} 163}
151 164
152/** 165/**
@@ -155,10 +168,14 @@ static inline void sh_wdt_keepalive(void)
155 */ 168 */
156static int sh_wdt_set_heartbeat(int t) 169static int sh_wdt_set_heartbeat(int t)
157{ 170{
158 if (unlikely((t < 1) || (t > 3600))) /* arbitrary upper limit */ 171 unsigned long flags;
172
173 if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */
159 return -EINVAL; 174 return -EINVAL;
160 175
176 spin_lock_irqsave(&wdt_lock, flags);
161 heartbeat = t; 177 heartbeat = t;
178 spin_unlock_irqrestore(&wdt_lock, flags);
162 return 0; 179 return 0;
163} 180}
164 181
@@ -170,6 +187,9 @@ static int sh_wdt_set_heartbeat(int t)
170 */ 187 */
171static void sh_wdt_ping(unsigned long data) 188static void sh_wdt_ping(unsigned long data)
172{ 189{
190 unsigned long flags;
191
192 spin_lock_irqsave(&wdt_lock, flags);
173 if (time_before(jiffies, next_heartbeat)) { 193 if (time_before(jiffies, next_heartbeat)) {
174 __u8 csr; 194 __u8 csr;
175 195
@@ -183,6 +203,7 @@ static void sh_wdt_ping(unsigned long data)
183 } else 203 } else
184 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping " 204 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
185 "the watchdog\n"); 205 "the watchdog\n");
206 spin_unlock_irqrestore(&wdt_lock, flags);
186} 207}
187 208
188/** 209/**
@@ -310,7 +331,6 @@ static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
310 331
311/** 332/**
312 * sh_wdt_ioctl - Query Device 333 * sh_wdt_ioctl - Query Device
313 * @inode: inode of device
314 * @file: file handle of device 334 * @file: file handle of device
315 * @cmd: watchdog command 335 * @cmd: watchdog command
316 * @arg: argument 336 * @arg: argument
@@ -318,53 +338,51 @@ static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
318 * Query basic information from the device or ping it, as outlined by the 338 * Query basic information from the device or ping it, as outlined by the
319 * watchdog API. 339 * watchdog API.
320 */ 340 */
321static int sh_wdt_ioctl(struct inode *inode, struct file *file, 341static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
322 unsigned int cmd, unsigned long arg) 342 unsigned long arg)
323{ 343{
324 int new_heartbeat; 344 int new_heartbeat;
325 int options, retval = -EINVAL; 345 int options, retval = -EINVAL;
326 346
327 switch (cmd) { 347 switch (cmd) {
328 case WDIOC_GETSUPPORT: 348 case WDIOC_GETSUPPORT:
329 return copy_to_user((struct watchdog_info *)arg, 349 return copy_to_user((struct watchdog_info *)arg,
330 &sh_wdt_info, 350 &sh_wdt_info, sizeof(sh_wdt_info)) ? -EFAULT : 0;
331 sizeof(sh_wdt_info)) ? -EFAULT : 0; 351 case WDIOC_GETSTATUS:
332 case WDIOC_GETSTATUS: 352 case WDIOC_GETBOOTSTATUS:
333 case WDIOC_GETBOOTSTATUS: 353 return put_user(0, (int *)arg);
334 return put_user(0, (int *)arg); 354 case WDIOC_SETOPTIONS:
335 case WDIOC_KEEPALIVE: 355 if (get_user(options, (int *)arg))
336 sh_wdt_keepalive(); 356 return -EFAULT;
337 return 0; 357
338 case WDIOC_SETTIMEOUT: 358 if (options & WDIOS_DISABLECARD) {
339 if (get_user(new_heartbeat, (int *)arg)) 359 sh_wdt_stop();
340 return -EFAULT; 360 retval = 0;
341 361 }
342 if (sh_wdt_set_heartbeat(new_heartbeat))
343 return -EINVAL;
344
345 sh_wdt_keepalive();
346 /* Fall */
347 case WDIOC_GETTIMEOUT:
348 return put_user(heartbeat, (int *)arg);
349 case WDIOC_SETOPTIONS:
350 if (get_user(options, (int *)arg))
351 return -EFAULT;
352
353 if (options & WDIOS_DISABLECARD) {
354 sh_wdt_stop();
355 retval = 0;
356 }
357 362
358 if (options & WDIOS_ENABLECARD) { 363 if (options & WDIOS_ENABLECARD) {
359 sh_wdt_start(); 364 sh_wdt_start();
360 retval = 0; 365 retval = 0;
361 } 366 }
362 367
363 return retval; 368 return retval;
364 default: 369 case WDIOC_KEEPALIVE:
365 return -ENOTTY; 370 sh_wdt_keepalive();
366 } 371 return 0;
372 case WDIOC_SETTIMEOUT:
373 if (get_user(new_heartbeat, (int *)arg))
374 return -EFAULT;
375
376 if (sh_wdt_set_heartbeat(new_heartbeat))
377 return -EINVAL;
367 378
379 sh_wdt_keepalive();
380 /* Fall */
381 case WDIOC_GETTIMEOUT:
382 return put_user(heartbeat, (int *)arg);
383 default:
384 return -ENOTTY;
385 }
368 return 0; 386 return 0;
369} 387}
370 388
@@ -390,13 +408,13 @@ static const struct file_operations sh_wdt_fops = {
390 .owner = THIS_MODULE, 408 .owner = THIS_MODULE,
391 .llseek = no_llseek, 409 .llseek = no_llseek,
392 .write = sh_wdt_write, 410 .write = sh_wdt_write,
393 .ioctl = sh_wdt_ioctl, 411 .unlocked_ioctl = sh_wdt_ioctl,
394 .open = sh_wdt_open, 412 .open = sh_wdt_open,
395 .release = sh_wdt_close, 413 .release = sh_wdt_close,
396 .mmap = sh_wdt_mmap, 414 .mmap = sh_wdt_mmap,
397}; 415};
398 416
399static struct watchdog_info sh_wdt_info = { 417static const struct watchdog_info sh_wdt_info = {
400 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | 418 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
401 WDIOF_MAGICCLOSE, 419 WDIOF_MAGICCLOSE,
402 .firmware_version = 1, 420 .firmware_version = 1,
@@ -422,30 +440,33 @@ static int __init sh_wdt_init(void)
422{ 440{
423 int rc; 441 int rc;
424 442
425 if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) { 443 if (clock_division_ratio < 0x5 || clock_division_ratio > 0x7) {
426 clock_division_ratio = WTCSR_CKS_4096; 444 clock_division_ratio = WTCSR_CKS_4096;
427 printk(KERN_INFO PFX "clock_division_ratio value must " 445 printk(KERN_INFO PFX
428 "be 0x5<=x<=0x7, using %d\n", clock_division_ratio); 446 "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n",
447 clock_division_ratio);
429 } 448 }
430 449
431 rc = sh_wdt_set_heartbeat(heartbeat); 450 rc = sh_wdt_set_heartbeat(heartbeat);
432 if (unlikely(rc)) { 451 if (unlikely(rc)) {
433 heartbeat = WATCHDOG_HEARTBEAT; 452 heartbeat = WATCHDOG_HEARTBEAT;
434 printk(KERN_INFO PFX "heartbeat value must " 453 printk(KERN_INFO PFX
435 "be 1<=x<=3600, using %d\n", heartbeat); 454 "heartbeat value must be 1<=x<=3600, using %d\n",
455 heartbeat);
436 } 456 }
437 457
438 rc = register_reboot_notifier(&sh_wdt_notifier); 458 rc = register_reboot_notifier(&sh_wdt_notifier);
439 if (unlikely(rc)) { 459 if (unlikely(rc)) {
440 printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n", 460 printk(KERN_ERR PFX
441 rc); 461 "Can't register reboot notifier (err=%d)\n", rc);
442 return rc; 462 return rc;
443 } 463 }
444 464
445 rc = misc_register(&sh_wdt_miscdev); 465 rc = misc_register(&sh_wdt_miscdev);
446 if (unlikely(rc)) { 466 if (unlikely(rc)) {
447 printk(KERN_ERR PFX "Can't register miscdev on " 467 printk(KERN_ERR PFX
448 "minor=%d (err=%d)\n", sh_wdt_miscdev.minor, rc); 468 "Can't register miscdev on minor=%d (err=%d)\n",
469 sh_wdt_miscdev.minor, rc);
449 unregister_reboot_notifier(&sh_wdt_notifier); 470 unregister_reboot_notifier(&sh_wdt_notifier);
450 return rc; 471 return rc;
451 } 472 }
@@ -476,10 +497,14 @@ module_param(clock_division_ratio, int, 0);
476MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")"); 497MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")");
477 498
478module_param(heartbeat, int, 0); 499module_param(heartbeat, int, 0);
479MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 500MODULE_PARM_DESC(heartbeat,
501 "Watchdog heartbeat in seconds. (1 <= heartbeat <= 3600, default="
502 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
480 503
481module_param(nowayout, int, 0); 504module_param(nowayout, int, 0);
482MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 505MODULE_PARM_DESC(nowayout,
506 "Watchdog cannot be stopped once started (default="
507 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
483 508
484module_init(sh_wdt_init); 509module_init(sh_wdt_init);
485module_exit(sh_wdt_exit); 510module_exit(sh_wdt_exit);
diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c
index 5d2b5ba61414..988ff1d5b4be 100644
--- a/drivers/watchdog/smsc37b787_wdt.c
+++ b/drivers/watchdog/smsc37b787_wdt.c
@@ -18,7 +18,7 @@
18 * History: 18 * History:
19 * 2003 - Created version 1.0 for Linux 2.4.x. 19 * 2003 - Created version 1.0 for Linux 2.4.x.
20 * 2006 - Ported to Linux 2.6, added nowayout and MAGICCLOSE 20 * 2006 - Ported to Linux 2.6, added nowayout and MAGICCLOSE
21 * features. Released version 1.1 21 * features. Released version 1.1
22 * 22 *
23 * Theory of operation: 23 * Theory of operation:
24 * 24 *
@@ -55,9 +55,9 @@
55#include <linux/reboot.h> 55#include <linux/reboot.h>
56#include <linux/init.h> 56#include <linux/init.h>
57#include <linux/spinlock.h> 57#include <linux/spinlock.h>
58#include <linux/io.h>
59#include <linux/uaccess.h>
58 60
59#include <asm/io.h>
60#include <asm/uaccess.h>
61#include <asm/system.h> 61#include <asm/system.h>
62 62
63/* enable support for minutes as units? */ 63/* enable support for minutes as units? */
@@ -71,15 +71,15 @@
71#define UNIT_MINUTE 1 71#define UNIT_MINUTE 1
72 72
73#define MODNAME "smsc37b787_wdt: " 73#define MODNAME "smsc37b787_wdt: "
74#define VERSION "1.1" 74#define VERSION "1.1"
75 75
76#define IOPORT 0x3F0 76#define IOPORT 0x3F0
77#define IOPORT_SIZE 2 77#define IOPORT_SIZE 2
78#define IODEV_NO 8 78#define IODEV_NO 8
79 79
80static int unit = UNIT_SECOND; /* timer's unit */ 80static int unit = UNIT_SECOND; /* timer's unit */
81static int timeout = 60; /* timeout value: default is 60 "units" */ 81static int timeout = 60; /* timeout value: default is 60 "units" */
82static unsigned long timer_enabled = 0; /* is the timer enabled? */ 82static unsigned long timer_enabled; /* is the timer enabled? */
83 83
84static char expect_close; /* is the close expected? */ 84static char expect_close; /* is the close expected? */
85 85
@@ -93,114 +93,121 @@ static int nowayout = WATCHDOG_NOWAYOUT;
93 93
94static inline void open_io_config(void) 94static inline void open_io_config(void)
95{ 95{
96 outb(0x55, IOPORT); 96 outb(0x55, IOPORT);
97 mdelay(1); 97 mdelay(1);
98 outb(0x55, IOPORT); 98 outb(0x55, IOPORT);
99} 99}
100 100
101/* lock the IO chip */ 101/* lock the IO chip */
102static inline void close_io_config(void) 102static inline void close_io_config(void)
103{ 103{
104 outb(0xAA, IOPORT); 104 outb(0xAA, IOPORT);
105} 105}
106 106
107/* select the IO device */ 107/* select the IO device */
108static inline void select_io_device(unsigned char devno) 108static inline void select_io_device(unsigned char devno)
109{ 109{
110 outb(0x07, IOPORT); 110 outb(0x07, IOPORT);
111 outb(devno, IOPORT+1); 111 outb(devno, IOPORT+1);
112} 112}
113 113
114/* write to the control register */ 114/* write to the control register */
115static inline void write_io_cr(unsigned char reg, unsigned char data) 115static inline void write_io_cr(unsigned char reg, unsigned char data)
116{ 116{
117 outb(reg, IOPORT); 117 outb(reg, IOPORT);
118 outb(data, IOPORT+1); 118 outb(data, IOPORT+1);
119} 119}
120 120
121/* read from the control register */ 121/* read from the control register */
122static inline char read_io_cr(unsigned char reg) 122static inline char read_io_cr(unsigned char reg)
123{ 123{
124 outb(reg, IOPORT); 124 outb(reg, IOPORT);
125 return inb(IOPORT+1); 125 return inb(IOPORT+1);
126} 126}
127 127
128/* -- Medium level functions ------------------------------------*/ 128/* -- Medium level functions ------------------------------------*/
129 129
130static inline void gpio_bit12(unsigned char reg) 130static inline void gpio_bit12(unsigned char reg)
131{ 131{
132 // -- General Purpose I/O Bit 1.2 -- 132 /* -- General Purpose I/O Bit 1.2 --
133 // Bit 0, In/Out: 0 = Output, 1 = Input 133 * Bit 0, In/Out: 0 = Output, 1 = Input
134 // Bit 1, Polarity: 0 = No Invert, 1 = Invert 134 * Bit 1, Polarity: 0 = No Invert, 1 = Invert
135 // Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable 135 * Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable
136 // Bit 3/4, Function select: 00 = GPI/O, 01 = WDT, 10 = P17, 136 * Bit 3/4, Function select: 00 = GPI/O, 01 = WDT, 10 = P17,
137 // 11 = Either Edge Triggered Intr. 2 137 * 11 = Either Edge Triggered Intr. 2
138 // Bit 5/6 (Reserved) 138 * Bit 5/6 (Reserved)
139 // Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain 139 * Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain
140 write_io_cr(0xE2, reg); 140 */
141 write_io_cr(0xE2, reg);
141} 142}
142 143
143static inline void gpio_bit13(unsigned char reg) 144static inline void gpio_bit13(unsigned char reg)
144{ 145{
145 // -- General Purpose I/O Bit 1.3 -- 146 /* -- General Purpose I/O Bit 1.3 --
146 // Bit 0, In/Out: 0 = Output, 1 = Input 147 * Bit 0, In/Out: 0 = Output, 1 = Input
147 // Bit 1, Polarity: 0 = No Invert, 1 = Invert 148 * Bit 1, Polarity: 0 = No Invert, 1 = Invert
148 // Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable 149 * Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable
149 // Bit 3, Function select: 0 = GPI/O, 1 = LED 150 * Bit 3, Function select: 0 = GPI/O, 1 = LED
150 // Bit 4-6 (Reserved) 151 * Bit 4-6 (Reserved)
151 // Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain 152 * Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain
152 write_io_cr(0xE3, reg); 153 */
154 write_io_cr(0xE3, reg);
153} 155}
154 156
155static inline void wdt_timer_units(unsigned char new_units) 157static inline void wdt_timer_units(unsigned char new_units)
156{ 158{
157 // -- Watchdog timer units -- 159 /* -- Watchdog timer units --
158 // Bit 0-6 (Reserved) 160 * Bit 0-6 (Reserved)
159 // Bit 7, WDT Time-out Value Units Select 161 * Bit 7, WDT Time-out Value Units Select
160 // (0 = Minutes, 1 = Seconds) 162 * (0 = Minutes, 1 = Seconds)
161 write_io_cr(0xF1, new_units); 163 */
164 write_io_cr(0xF1, new_units);
162} 165}
163 166
164static inline void wdt_timeout_value(unsigned char new_timeout) 167static inline void wdt_timeout_value(unsigned char new_timeout)
165{ 168{
166 // -- Watchdog Timer Time-out Value -- 169 /* -- Watchdog Timer Time-out Value --
167 // Bit 0-7 Binary coded units (0=Disabled, 1..255) 170 * Bit 0-7 Binary coded units (0=Disabled, 1..255)
168 write_io_cr(0xF2, new_timeout); 171 */
172 write_io_cr(0xF2, new_timeout);
169} 173}
170 174
171static inline void wdt_timer_conf(unsigned char conf) 175static inline void wdt_timer_conf(unsigned char conf)
172{ 176{
173 // -- Watchdog timer configuration -- 177 /* -- Watchdog timer configuration --
174 // Bit 0 Joystick enable: 0* = No Reset, 1 = Reset WDT upon Gameport I/O 178 * Bit 0 Joystick enable: 0* = No Reset, 1 = Reset WDT upon
175 // Bit 1 Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr. 179 * Gameport I/O
176 // Bit 2 Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr. 180 * Bit 1 Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr.
177 // Bit 3 Reset the timer 181 * Bit 2 Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr
178 // (Wrong in SMsC documentation? Given as: PowerLED Timout Enabled) 182 * Bit 3 Reset the timer
179 // Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled, 183 * (Wrong in SMsC documentation? Given as: PowerLED Timout
180 // 0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15) 184 * Enabled)
181 write_io_cr(0xF3, conf); 185 * Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled,
186 * 0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15)
187 */
188 write_io_cr(0xF3, conf);
182} 189}
183 190
184static inline void wdt_timer_ctrl(unsigned char reg) 191static inline void wdt_timer_ctrl(unsigned char reg)
185{ 192{
186 // -- Watchdog timer control -- 193 /* -- Watchdog timer control --
187 // Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured 194 * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured
188 // Bit 1 Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz 195 * Bit 1 Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz
189 // Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) 196 * Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning)
190 // Bit 3 P20 Force Timeout enabled: 197 * Bit 3 P20 Force Timeout enabled:
191 // 0 = P20 activity does not generate the WD timeout event 198 * 0 = P20 activity does not generate the WD timeout event
192 // 1 = P20 Allows rising edge of P20, from the keyboard 199 * 1 = P20 Allows rising edge of P20, from the keyboard
193 // controller, to force the WD timeout event. 200 * controller, to force the WD timeout event.
194 // Bit 4 (Reserved) 201 * Bit 4 (Reserved)
195 // -- Soft power management -- 202 * -- Soft power management --
196 // Bit 5 Stop Counter: 1 = Stop software power down counter 203 * Bit 5 Stop Counter: 1 = Stop software power down counter
197 // set via register 0xB8, (self-cleaning) 204 * set via register 0xB8, (self-cleaning)
198 // (Upon read: 0 = Counter running, 1 = Counter stopped) 205 * (Upon read: 0 = Counter running, 1 = Counter stopped)
199 // Bit 6 Restart Counter: 1 = Restart software power down counter 206 * Bit 6 Restart Counter: 1 = Restart software power down counter
200 // set via register 0xB8, (self-cleaning) 207 * set via register 0xB8, (self-cleaning)
201 // Bit 7 SPOFF: 1 = Force software power down (self-cleaning) 208 * Bit 7 SPOFF: 1 = Force software power down (self-cleaning)
202 209 */
203 write_io_cr(0xF4, reg); 210 write_io_cr(0xF4, reg);
204} 211}
205 212
206/* -- Higher level functions ------------------------------------*/ 213/* -- Higher level functions ------------------------------------*/
@@ -209,33 +216,34 @@ static inline void wdt_timer_ctrl(unsigned char reg)
209 216
210static void wb_smsc_wdt_initialize(void) 217static void wb_smsc_wdt_initialize(void)
211{ 218{
212 unsigned char old; 219 unsigned char old;
213 220
214 spin_lock(&io_lock); 221 spin_lock(&io_lock);
215 open_io_config(); 222 open_io_config();
216 select_io_device(IODEV_NO); 223 select_io_device(IODEV_NO);
217 224
218 // enable the watchdog 225 /* enable the watchdog */
219 gpio_bit13(0x08); // Select pin 80 = LED not GPIO 226 gpio_bit13(0x08); /* Select pin 80 = LED not GPIO */
220 gpio_bit12(0x0A); // Set pin 79 = WDT not GPIO/Output/Polarity=Invert 227 gpio_bit12(0x0A); /* Set pin 79 = WDT not
228 GPIO/Output/Polarity=Invert */
229 /* disable the timeout */
230 wdt_timeout_value(0);
221 231
222 // disable the timeout 232 /* reset control register */
223 wdt_timeout_value(0); 233 wdt_timer_ctrl(0x00);
224 234
225 // reset control register 235 /* reset configuration register */
226 wdt_timer_ctrl(0x00);
227
228 // reset configuration register
229 wdt_timer_conf(0x00); 236 wdt_timer_conf(0x00);
230 237
231 // read old (timer units) register 238 /* read old (timer units) register */
232 old = read_io_cr(0xF1) & 0x7F; 239 old = read_io_cr(0xF1) & 0x7F;
233 if (unit == UNIT_SECOND) old |= 0x80; // set to seconds 240 if (unit == UNIT_SECOND)
241 old |= 0x80; /* set to seconds */
234 242
235 // set the watchdog timer units 243 /* set the watchdog timer units */
236 wdt_timer_units(old); 244 wdt_timer_units(old);
237 245
238 close_io_config(); 246 close_io_config();
239 spin_unlock(&io_lock); 247 spin_unlock(&io_lock);
240} 248}
241 249
@@ -244,23 +252,23 @@ static void wb_smsc_wdt_initialize(void)
244static void wb_smsc_wdt_shutdown(void) 252static void wb_smsc_wdt_shutdown(void)
245{ 253{
246 spin_lock(&io_lock); 254 spin_lock(&io_lock);
247 open_io_config(); 255 open_io_config();
248 select_io_device(IODEV_NO); 256 select_io_device(IODEV_NO);
249 257
250 // disable the watchdog 258 /* disable the watchdog */
251 gpio_bit13(0x09); 259 gpio_bit13(0x09);
252 gpio_bit12(0x09); 260 gpio_bit12(0x09);
253 261
254 // reset watchdog config register 262 /* reset watchdog config register */
255 wdt_timer_conf(0x00); 263 wdt_timer_conf(0x00);
256 264
257 // reset watchdog control register 265 /* reset watchdog control register */
258 wdt_timer_ctrl(0x00); 266 wdt_timer_ctrl(0x00);
259 267
260 // disable timeout 268 /* disable timeout */
261 wdt_timeout_value(0x00); 269 wdt_timeout_value(0x00);
262 270
263 close_io_config(); 271 close_io_config();
264 spin_unlock(&io_lock); 272 spin_unlock(&io_lock);
265} 273}
266 274
@@ -269,16 +277,16 @@ static void wb_smsc_wdt_shutdown(void)
269static void wb_smsc_wdt_set_timeout(unsigned char new_timeout) 277static void wb_smsc_wdt_set_timeout(unsigned char new_timeout)
270{ 278{
271 spin_lock(&io_lock); 279 spin_lock(&io_lock);
272 open_io_config(); 280 open_io_config();
273 select_io_device(IODEV_NO); 281 select_io_device(IODEV_NO);
274 282
275 // set Power LED to blink, if we enable the timeout 283 /* set Power LED to blink, if we enable the timeout */
276 wdt_timer_ctrl((new_timeout == 0) ? 0x00 : 0x02); 284 wdt_timer_ctrl((new_timeout == 0) ? 0x00 : 0x02);
277 285
278 // set timeout value 286 /* set timeout value */
279 wdt_timeout_value(new_timeout); 287 wdt_timeout_value(new_timeout);
280 288
281 close_io_config(); 289 close_io_config();
282 spin_unlock(&io_lock); 290 spin_unlock(&io_lock);
283} 291}
284 292
@@ -286,32 +294,32 @@ static void wb_smsc_wdt_set_timeout(unsigned char new_timeout)
286 294
287static unsigned char wb_smsc_wdt_get_timeout(void) 295static unsigned char wb_smsc_wdt_get_timeout(void)
288{ 296{
289 unsigned char set_timeout; 297 unsigned char set_timeout;
290 298
291 spin_lock(&io_lock); 299 spin_lock(&io_lock);
292 open_io_config(); 300 open_io_config();
293 select_io_device(IODEV_NO); 301 select_io_device(IODEV_NO);
294 set_timeout = read_io_cr(0xF2); 302 set_timeout = read_io_cr(0xF2);
295 close_io_config(); 303 close_io_config();
296 spin_unlock(&io_lock); 304 spin_unlock(&io_lock);
297 305
298 return set_timeout; 306 return set_timeout;
299} 307}
300 308
301/* disable watchdog */ 309/* disable watchdog */
302 310
303static void wb_smsc_wdt_disable(void) 311static void wb_smsc_wdt_disable(void)
304{ 312{
305 // set the timeout to 0 to disable the watchdog 313 /* set the timeout to 0 to disable the watchdog */
306 wb_smsc_wdt_set_timeout(0); 314 wb_smsc_wdt_set_timeout(0);
307} 315}
308 316
309/* enable watchdog by setting the current timeout */ 317/* enable watchdog by setting the current timeout */
310 318
311static void wb_smsc_wdt_enable(void) 319static void wb_smsc_wdt_enable(void)
312{ 320{
313 // set the current timeout... 321 /* set the current timeout... */
314 wb_smsc_wdt_set_timeout(timeout); 322 wb_smsc_wdt_set_timeout(timeout);
315} 323}
316 324
317/* reset the timer */ 325/* reset the timer */
@@ -319,14 +327,14 @@ static void wb_smsc_wdt_enable(void)
319static void wb_smsc_wdt_reset_timer(void) 327static void wb_smsc_wdt_reset_timer(void)
320{ 328{
321 spin_lock(&io_lock); 329 spin_lock(&io_lock);
322 open_io_config(); 330 open_io_config();
323 select_io_device(IODEV_NO); 331 select_io_device(IODEV_NO);
324 332
325 // reset the timer 333 /* reset the timer */
326 wdt_timeout_value(timeout); 334 wdt_timeout_value(timeout);
327 wdt_timer_conf(0x08); 335 wdt_timer_conf(0x08);
328 336
329 close_io_config(); 337 close_io_config();
330 spin_unlock(&io_lock); 338 spin_unlock(&io_lock);
331} 339}
332 340
@@ -355,7 +363,9 @@ static int wb_smsc_wdt_open(struct inode *inode, struct file *file)
355 /* Reload and activate timer */ 363 /* Reload and activate timer */
356 wb_smsc_wdt_enable(); 364 wb_smsc_wdt_enable();
357 365
358 printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); 366 printk(KERN_INFO MODNAME
367 "Watchdog enabled. Timeout set to %d %s.\n",
368 timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
359 369
360 return nonseekable_open(inode, file); 370 return nonseekable_open(inode, file);
361} 371}
@@ -367,10 +377,12 @@ static int wb_smsc_wdt_release(struct inode *inode, struct file *file)
367 /* Shut off the timer. */ 377 /* Shut off the timer. */
368 378
369 if (expect_close == 42) { 379 if (expect_close == 42) {
370 wb_smsc_wdt_disable(); 380 wb_smsc_wdt_disable();
371 printk(KERN_INFO MODNAME "Watchdog disabled, sleeping again...\n"); 381 printk(KERN_INFO MODNAME
382 "Watchdog disabled, sleeping again...\n");
372 } else { 383 } else {
373 printk(KERN_CRIT MODNAME "Unexpected close, not stopping watchdog!\n"); 384 printk(KERN_CRIT MODNAME
385 "Unexpected close, not stopping watchdog!\n");
374 wb_smsc_wdt_reset_timer(); 386 wb_smsc_wdt_reset_timer();
375 } 387 }
376 388
@@ -392,10 +404,11 @@ static ssize_t wb_smsc_wdt_write(struct file *file, const char __user *data,
392 /* reset expect flag */ 404 /* reset expect flag */
393 expect_close = 0; 405 expect_close = 0;
394 406
395 /* scan to see whether or not we got the magic character */ 407 /* scan to see whether or not we got the
408 magic character */
396 for (i = 0; i != len; i++) { 409 for (i = 0; i != len; i++) {
397 char c; 410 char c;
398 if (get_user(c, data+i)) 411 if (get_user(c, data + i))
399 return -EFAULT; 412 return -EFAULT;
400 if (c == 'V') 413 if (c == 'V')
401 expect_close = 42; 414 expect_close = 42;
@@ -410,8 +423,8 @@ static ssize_t wb_smsc_wdt_write(struct file *file, const char __user *data,
410 423
411/* ioctl => control interface */ 424/* ioctl => control interface */
412 425
413static int wb_smsc_wdt_ioctl(struct inode *inode, struct file *file, 426static long wb_smsc_wdt_ioctl(struct file *file,
414 unsigned int cmd, unsigned long arg) 427 unsigned int cmd, unsigned long arg)
415{ 428{
416 int new_timeout; 429 int new_timeout;
417 430
@@ -420,89 +433,73 @@ static int wb_smsc_wdt_ioctl(struct inode *inode, struct file *file,
420 int __user *i; 433 int __user *i;
421 } uarg; 434 } uarg;
422 435
423 static struct watchdog_info ident = { 436 static const struct watchdog_info ident = {
424 .options = WDIOF_KEEPALIVEPING | 437 .options = WDIOF_KEEPALIVEPING |
425 WDIOF_SETTIMEOUT | 438 WDIOF_SETTIMEOUT |
426 WDIOF_MAGICCLOSE, 439 WDIOF_MAGICCLOSE,
427 .firmware_version = 0, 440 .firmware_version = 0,
428 .identity = "SMsC 37B787 Watchdog" 441 .identity = "SMsC 37B787 Watchdog",
429 }; 442 };
430 443
431 uarg.i = (int __user *)arg; 444 uarg.i = (int __user *)arg;
432 445
433 switch (cmd) { 446 switch (cmd) {
434 default: 447 case WDIOC_GETSUPPORT:
435 return -ENOTTY; 448 return copy_to_user(uarg.ident, &ident, sizeof(ident))
436 449 ? -EFAULT : 0;
437 case WDIOC_GETSUPPORT: 450 case WDIOC_GETSTATUS:
438 return copy_to_user(uarg.ident, &ident, 451 return put_user(wb_smsc_wdt_status(), uarg.i);
439 sizeof(ident)) ? -EFAULT : 0; 452 case WDIOC_GETBOOTSTATUS:
440 453 return put_user(0, uarg.i);
441 case WDIOC_GETSTATUS: 454 case WDIOC_SETOPTIONS:
442 return put_user(wb_smsc_wdt_status(), uarg.i); 455 {
443 456 int options, retval = -EINVAL;
444 case WDIOC_GETBOOTSTATUS:
445 return put_user(0, uarg.i);
446
447 case WDIOC_KEEPALIVE:
448 wb_smsc_wdt_reset_timer();
449 return 0;
450
451 case WDIOC_SETTIMEOUT:
452 if (get_user(new_timeout, uarg.i))
453 return -EFAULT;
454
455 // the API states this is given in secs
456 if (unit == UNIT_MINUTE)
457 new_timeout /= 60;
458
459 if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
460 return -EINVAL;
461
462 timeout = new_timeout;
463 wb_smsc_wdt_set_timeout(timeout);
464
465 // fall through and return the new timeout...
466
467 case WDIOC_GETTIMEOUT:
468
469 new_timeout = timeout;
470
471 if (unit == UNIT_MINUTE)
472 new_timeout *= 60;
473
474 return put_user(new_timeout, uarg.i);
475
476 case WDIOC_SETOPTIONS:
477 {
478 int options, retval = -EINVAL;
479
480 if (get_user(options, uarg.i))
481 return -EFAULT;
482
483 if (options & WDIOS_DISABLECARD) {
484 wb_smsc_wdt_disable();
485 retval = 0;
486 }
487 457
488 if (options & WDIOS_ENABLECARD) { 458 if (get_user(options, uarg.i))
489 wb_smsc_wdt_enable(); 459 return -EFAULT;
490 retval = 0;
491 }
492 460
493 return retval; 461 if (options & WDIOS_DISABLECARD) {
462 wb_smsc_wdt_disable();
463 retval = 0;
464 }
465 if (options & WDIOS_ENABLECARD) {
466 wb_smsc_wdt_enable();
467 retval = 0;
494 } 468 }
469 return retval;
470 }
471 case WDIOC_KEEPALIVE:
472 wb_smsc_wdt_reset_timer();
473 return 0;
474 case WDIOC_SETTIMEOUT:
475 if (get_user(new_timeout, uarg.i))
476 return -EFAULT;
477 /* the API states this is given in secs */
478 if (unit == UNIT_MINUTE)
479 new_timeout /= 60;
480 if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
481 return -EINVAL;
482 timeout = new_timeout;
483 wb_smsc_wdt_set_timeout(timeout);
484 /* fall through and return the new timeout... */
485 case WDIOC_GETTIMEOUT:
486 new_timeout = timeout;
487 if (unit == UNIT_MINUTE)
488 new_timeout *= 60;
489 return put_user(new_timeout, uarg.i);
490 default:
491 return -ENOTTY;
495 } 492 }
496} 493}
497 494
498/* -- Notifier funtions -----------------------------------------*/ 495/* -- Notifier funtions -----------------------------------------*/
499 496
500static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) 497static int wb_smsc_wdt_notify_sys(struct notifier_block *this,
498 unsigned long code, void *unused)
501{ 499{
502 if (code == SYS_DOWN || code == SYS_HALT) 500 if (code == SYS_DOWN || code == SYS_HALT) {
503 { 501 /* set timeout to 0, to avoid possible race-condition */
504 // set timeout to 0, to avoid possible race-condition 502 timeout = 0;
505 timeout = 0;
506 wb_smsc_wdt_disable(); 503 wb_smsc_wdt_disable();
507 } 504 }
508 return NOTIFY_DONE; 505 return NOTIFY_DONE;
@@ -510,23 +507,20 @@ static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long cod
510 507
511/* -- Module's structures ---------------------------------------*/ 508/* -- Module's structures ---------------------------------------*/
512 509
513static const struct file_operations wb_smsc_wdt_fops = 510static const struct file_operations wb_smsc_wdt_fops = {
514{ 511 .owner = THIS_MODULE,
515 .owner = THIS_MODULE,
516 .llseek = no_llseek, 512 .llseek = no_llseek,
517 .write = wb_smsc_wdt_write, 513 .write = wb_smsc_wdt_write,
518 .ioctl = wb_smsc_wdt_ioctl, 514 .unlocked_ioctl = wb_smsc_wdt_ioctl,
519 .open = wb_smsc_wdt_open, 515 .open = wb_smsc_wdt_open,
520 .release = wb_smsc_wdt_release, 516 .release = wb_smsc_wdt_release,
521}; 517};
522 518
523static struct notifier_block wb_smsc_wdt_notifier = 519static struct notifier_block wb_smsc_wdt_notifier = {
524{
525 .notifier_call = wb_smsc_wdt_notify_sys, 520 .notifier_call = wb_smsc_wdt_notify_sys,
526}; 521};
527 522
528static struct miscdevice wb_smsc_wdt_miscdev = 523static struct miscdevice wb_smsc_wdt_miscdev = {
529{
530 .minor = WATCHDOG_MINOR, 524 .minor = WATCHDOG_MINOR,
531 .name = "watchdog", 525 .name = "watchdog",
532 .fops = &wb_smsc_wdt_fops, 526 .fops = &wb_smsc_wdt_fops,
@@ -540,39 +534,44 @@ static int __init wb_smsc_wdt_init(void)
540{ 534{
541 int ret; 535 int ret;
542 536
543 printk("SMsC 37B787 watchdog component driver " VERSION " initialising...\n"); 537 printk(KERN_INFO "SMsC 37B787 watchdog component driver "
538 VERSION " initialising...\n");
544 539
545 if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) { 540 if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) {
546 printk(KERN_ERR MODNAME "Unable to register IO port %#x\n", IOPORT); 541 printk(KERN_ERR MODNAME "Unable to register IO port %#x\n",
542 IOPORT);
547 ret = -EBUSY; 543 ret = -EBUSY;
548 goto out_pnp; 544 goto out_pnp;
549 } 545 }
550 546
551 // set new maximum, if it's too big 547 /* set new maximum, if it's too big */
552 if (timeout > MAX_TIMEOUT) 548 if (timeout > MAX_TIMEOUT)
553 timeout = MAX_TIMEOUT; 549 timeout = MAX_TIMEOUT;
554 550
555 // init the watchdog timer 551 /* init the watchdog timer */
556 wb_smsc_wdt_initialize(); 552 wb_smsc_wdt_initialize();
557 553
558 ret = register_reboot_notifier(&wb_smsc_wdt_notifier); 554 ret = register_reboot_notifier(&wb_smsc_wdt_notifier);
559 if (ret) { 555 if (ret) {
560 printk(KERN_ERR MODNAME "Unable to register reboot notifier err = %d\n", ret); 556 printk(KERN_ERR MODNAME
557 "Unable to register reboot notifier err = %d\n", ret);
561 goto out_io; 558 goto out_io;
562 } 559 }
563 560
564 ret = misc_register(&wb_smsc_wdt_miscdev); 561 ret = misc_register(&wb_smsc_wdt_miscdev);
565 if (ret) { 562 if (ret) {
566 printk(KERN_ERR MODNAME "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR); 563 printk(KERN_ERR MODNAME
564 "Unable to register miscdev on minor %d\n",
565 WATCHDOG_MINOR);
567 goto out_rbt; 566 goto out_rbt;
568 } 567 }
569 568
570 // output info 569 /* output info */
571 printk(KERN_INFO MODNAME "Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); 570 printk(KERN_INFO MODNAME "Timeout set to %d %s.\n",
572 printk(KERN_INFO MODNAME "Watchdog initialized and sleeping (nowayout=%d)...\n", nowayout); 571 timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
573 572 printk(KERN_INFO MODNAME
574 // ret = 0 573 "Watchdog initialized and sleeping (nowayout=%d)...\n",
575 574 nowayout);
576out_clean: 575out_clean:
577 return ret; 576 return ret;
578 577
@@ -591,8 +590,7 @@ out_pnp:
591static void __exit wb_smsc_wdt_exit(void) 590static void __exit wb_smsc_wdt_exit(void)
592{ 591{
593 /* Stop the timer before we leave */ 592 /* Stop the timer before we leave */
594 if (!nowayout) 593 if (!nowayout) {
595 {
596 wb_smsc_wdt_shutdown(); 594 wb_smsc_wdt_shutdown();
597 printk(KERN_INFO MODNAME "Watchdog disabled.\n"); 595 printk(KERN_INFO MODNAME "Watchdog disabled.\n");
598 } 596 }
@@ -601,25 +599,29 @@ static void __exit wb_smsc_wdt_exit(void)
601 unregister_reboot_notifier(&wb_smsc_wdt_notifier); 599 unregister_reboot_notifier(&wb_smsc_wdt_notifier);
602 release_region(IOPORT, IOPORT_SIZE); 600 release_region(IOPORT, IOPORT_SIZE);
603 601
604 printk("SMsC 37B787 watchdog component driver removed.\n"); 602 printk(KERN_INFO "SMsC 37B787 watchdog component driver removed.\n");
605} 603}
606 604
607module_init(wb_smsc_wdt_init); 605module_init(wb_smsc_wdt_init);
608module_exit(wb_smsc_wdt_exit); 606module_exit(wb_smsc_wdt_exit);
609 607
610MODULE_AUTHOR("Sven Anders <anders@anduras.de>"); 608MODULE_AUTHOR("Sven Anders <anders@anduras.de>");
611MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version " VERSION ")"); 609MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version "
610 VERSION ")");
612MODULE_LICENSE("GPL"); 611MODULE_LICENSE("GPL");
613 612
614MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 613MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
615 614
616#ifdef SMSC_SUPPORT_MINUTES 615#ifdef SMSC_SUPPORT_MINUTES
617module_param(unit, int, 0); 616module_param(unit, int, 0);
618MODULE_PARM_DESC(unit, "set unit to use, 0=seconds or 1=minutes, default is 0"); 617MODULE_PARM_DESC(unit,
618 "set unit to use, 0=seconds or 1=minutes, default is 0");
619#endif 619#endif
620 620
621module_param(timeout, int, 0); 621module_param(timeout, int, 0);
622MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60"); 622MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60");
623 623
624module_param(nowayout, int, 0); 624module_param(nowayout, int, 0);
625MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 625MODULE_PARM_DESC(nowayout,
626 "Watchdog cannot be stopped once started (default="
627 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c
index 9c3694909243..c650464c5c63 100644
--- a/drivers/watchdog/softdog.c
+++ b/drivers/watchdog/softdog.c
@@ -47,19 +47,22 @@
47#include <linux/reboot.h> 47#include <linux/reboot.h>
48#include <linux/init.h> 48#include <linux/init.h>
49#include <linux/jiffies.h> 49#include <linux/jiffies.h>
50 50#include <linux/uaccess.h>
51#include <asm/uaccess.h>
52 51
53#define PFX "SoftDog: " 52#define PFX "SoftDog: "
54 53
55#define TIMER_MARGIN 60 /* Default is 60 seconds */ 54#define TIMER_MARGIN 60 /* Default is 60 seconds */
56static int soft_margin = TIMER_MARGIN; /* in seconds */ 55static int soft_margin = TIMER_MARGIN; /* in seconds */
57module_param(soft_margin, int, 0); 56module_param(soft_margin, int, 0);
58MODULE_PARM_DESC(soft_margin, "Watchdog soft_margin in seconds. (0<soft_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")"); 57MODULE_PARM_DESC(soft_margin,
58 "Watchdog soft_margin in seconds. (0 < soft_margin < 65536, default="
59 __MODULE_STRING(TIMER_MARGIN) ")");
59 60
60static int nowayout = WATCHDOG_NOWAYOUT; 61static int nowayout = WATCHDOG_NOWAYOUT;
61module_param(nowayout, int, 0); 62module_param(nowayout, int, 0);
62MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 63MODULE_PARM_DESC(nowayout,
64 "Watchdog cannot be stopped once started (default="
65 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
63 66
64#ifdef ONLY_TESTING 67#ifdef ONLY_TESTING
65static int soft_noboot = 1; 68static int soft_noboot = 1;
@@ -93,8 +96,7 @@ static void watchdog_fire(unsigned long data)
93 96
94 if (soft_noboot) 97 if (soft_noboot)
95 printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n"); 98 printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n");
96 else 99 else {
97 {
98 printk(KERN_CRIT PFX "Initiating system reboot.\n"); 100 printk(KERN_CRIT PFX "Initiating system reboot.\n");
99 emergency_restart(); 101 emergency_restart();
100 printk(KERN_CRIT PFX "Reboot didn't ?????\n"); 102 printk(KERN_CRIT PFX "Reboot didn't ?????\n");
@@ -153,7 +155,8 @@ static int softdog_release(struct inode *inode, struct file *file)
153 softdog_stop(); 155 softdog_stop();
154 module_put(THIS_MODULE); 156 module_put(THIS_MODULE);
155 } else { 157 } else {
156 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 158 printk(KERN_CRIT PFX
159 "Unexpected close, not stopping watchdog!\n");
157 set_bit(0, &orphan_timer); 160 set_bit(0, &orphan_timer);
158 softdog_keepalive(); 161 softdog_keepalive();
159 } 162 }
@@ -162,12 +165,13 @@ static int softdog_release(struct inode *inode, struct file *file)
162 return 0; 165 return 0;
163} 166}
164 167
165static ssize_t softdog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) 168static ssize_t softdog_write(struct file *file, const char __user *data,
169 size_t len, loff_t *ppos)
166{ 170{
167 /* 171 /*
168 * Refresh the timer. 172 * Refresh the timer.
169 */ 173 */
170 if(len) { 174 if (len) {
171 if (!nowayout) { 175 if (!nowayout) {
172 size_t i; 176 size_t i;
173 177
@@ -188,13 +192,13 @@ static ssize_t softdog_write(struct file *file, const char __user *data, size_t
188 return len; 192 return len;
189} 193}
190 194
191static int softdog_ioctl(struct inode *inode, struct file *file, 195static long softdog_ioctl(struct file *file, unsigned int cmd,
192 unsigned int cmd, unsigned long arg) 196 unsigned long arg)
193{ 197{
194 void __user *argp = (void __user *)arg; 198 void __user *argp = (void __user *)arg;
195 int __user *p = argp; 199 int __user *p = argp;
196 int new_margin; 200 int new_margin;
197 static struct watchdog_info ident = { 201 static const struct watchdog_info ident = {
198 .options = WDIOF_SETTIMEOUT | 202 .options = WDIOF_SETTIMEOUT |
199 WDIOF_KEEPALIVEPING | 203 WDIOF_KEEPALIVEPING |
200 WDIOF_MAGICCLOSE, 204 WDIOF_MAGICCLOSE,
@@ -202,26 +206,25 @@ static int softdog_ioctl(struct inode *inode, struct file *file,
202 .identity = "Software Watchdog", 206 .identity = "Software Watchdog",
203 }; 207 };
204 switch (cmd) { 208 switch (cmd) {
205 default: 209 case WDIOC_GETSUPPORT:
206 return -ENOTTY; 210 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
207 case WDIOC_GETSUPPORT: 211 case WDIOC_GETSTATUS:
208 return copy_to_user(argp, &ident, 212 case WDIOC_GETBOOTSTATUS:
209 sizeof(ident)) ? -EFAULT : 0; 213 return put_user(0, p);
210 case WDIOC_GETSTATUS: 214 case WDIOC_KEEPALIVE:
211 case WDIOC_GETBOOTSTATUS: 215 softdog_keepalive();
212 return put_user(0, p); 216 return 0;
213 case WDIOC_KEEPALIVE: 217 case WDIOC_SETTIMEOUT:
214 softdog_keepalive(); 218 if (get_user(new_margin, p))
215 return 0; 219 return -EFAULT;
216 case WDIOC_SETTIMEOUT: 220 if (softdog_set_heartbeat(new_margin))
217 if (get_user(new_margin, p)) 221 return -EINVAL;
218 return -EFAULT; 222 softdog_keepalive();
219 if (softdog_set_heartbeat(new_margin)) 223 /* Fall */
220 return -EINVAL; 224 case WDIOC_GETTIMEOUT:
221 softdog_keepalive(); 225 return put_user(soft_margin, p);
222 /* Fall */ 226 default:
223 case WDIOC_GETTIMEOUT: 227 return -ENOTTY;
224 return put_user(soft_margin, p);
225 } 228 }
226} 229}
227 230
@@ -232,10 +235,9 @@ static int softdog_ioctl(struct inode *inode, struct file *file,
232static int softdog_notify_sys(struct notifier_block *this, unsigned long code, 235static int softdog_notify_sys(struct notifier_block *this, unsigned long code,
233 void *unused) 236 void *unused)
234{ 237{
235 if(code==SYS_DOWN || code==SYS_HALT) { 238 if (code == SYS_DOWN || code == SYS_HALT)
236 /* Turn the WDT off */ 239 /* Turn the WDT off */
237 softdog_stop(); 240 softdog_stop();
238 }
239 return NOTIFY_DONE; 241 return NOTIFY_DONE;
240} 242}
241 243
@@ -247,7 +249,7 @@ static const struct file_operations softdog_fops = {
247 .owner = THIS_MODULE, 249 .owner = THIS_MODULE,
248 .llseek = no_llseek, 250 .llseek = no_llseek,
249 .write = softdog_write, 251 .write = softdog_write,
250 .ioctl = softdog_ioctl, 252 .unlocked_ioctl = softdog_ioctl,
251 .open = softdog_open, 253 .open = softdog_open,
252 .release = softdog_release, 254 .release = softdog_release,
253}; 255};
@@ -268,24 +270,27 @@ static int __init watchdog_init(void)
268{ 270{
269 int ret; 271 int ret;
270 272
271 /* Check that the soft_margin value is within it's range ; if not reset to the default */ 273 /* Check that the soft_margin value is within it's range;
274 if not reset to the default */
272 if (softdog_set_heartbeat(soft_margin)) { 275 if (softdog_set_heartbeat(soft_margin)) {
273 softdog_set_heartbeat(TIMER_MARGIN); 276 softdog_set_heartbeat(TIMER_MARGIN);
274 printk(KERN_INFO PFX "soft_margin value must be 0<soft_margin<65536, using %d\n", 277 printk(KERN_INFO PFX
278 "soft_margin must be 0 < soft_margin < 65536, using %d\n",
275 TIMER_MARGIN); 279 TIMER_MARGIN);
276 } 280 }
277 281
278 ret = register_reboot_notifier(&softdog_notifier); 282 ret = register_reboot_notifier(&softdog_notifier);
279 if (ret) { 283 if (ret) {
280 printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 284 printk(KERN_ERR PFX
281 ret); 285 "cannot register reboot notifier (err=%d)\n", ret);
282 return ret; 286 return ret;
283 } 287 }
284 288
285 ret = misc_register(&softdog_miscdev); 289 ret = misc_register(&softdog_miscdev);
286 if (ret) { 290 if (ret) {
287 printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 291 printk(KERN_ERR PFX
288 WATCHDOG_MINOR, ret); 292 "cannot register miscdev on minor=%d (err=%d)\n",
293 WATCHDOG_MINOR, ret);
289 unregister_reboot_notifier(&softdog_notifier); 294 unregister_reboot_notifier(&softdog_notifier);
290 return ret; 295 return ret;
291 } 296 }
diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c
index 57cefef27ce3..dbbc018a5f46 100644
--- a/drivers/watchdog/txx9wdt.c
+++ b/drivers/watchdog/txx9wdt.c
@@ -45,27 +45,34 @@ static unsigned long txx9wdt_alive;
45static int expect_close; 45static int expect_close;
46static struct txx9_tmr_reg __iomem *txx9wdt_reg; 46static struct txx9_tmr_reg __iomem *txx9wdt_reg;
47static struct clk *txx9_imclk; 47static struct clk *txx9_imclk;
48static DECLARE_LOCK(txx9_lock);
48 49
49static void txx9wdt_ping(void) 50static void txx9wdt_ping(void)
50{ 51{
52 spin_lock(&txx9_lock);
51 __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); 53 __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr);
54 spin_unlock(&txx9_lock);
52} 55}
53 56
54static void txx9wdt_start(void) 57static void txx9wdt_start(void)
55{ 58{
59 spin_lock(&txx9_lock);
56 __raw_writel(WD_TIMER_CLK * timeout, &txx9wdt_reg->cpra); 60 __raw_writel(WD_TIMER_CLK * timeout, &txx9wdt_reg->cpra);
57 __raw_writel(WD_TIMER_CCD, &txx9wdt_reg->ccdr); 61 __raw_writel(WD_TIMER_CCD, &txx9wdt_reg->ccdr);
58 __raw_writel(0, &txx9wdt_reg->tisr); /* clear pending interrupt */ 62 __raw_writel(0, &txx9wdt_reg->tisr); /* clear pending interrupt */
59 __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, 63 __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG,
60 &txx9wdt_reg->tcr); 64 &txx9wdt_reg->tcr);
61 __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); 65 __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr);
66 spin_unlock(&txx9_lock);
62} 67}
63 68
64static void txx9wdt_stop(void) 69static void txx9wdt_stop(void)
65{ 70{
71 spin_lock(&txx9_lock);
66 __raw_writel(TXx9_TMWTMR_WDIS, &txx9wdt_reg->wtmr); 72 __raw_writel(TXx9_TMWTMR_WDIS, &txx9wdt_reg->wtmr);
67 __raw_writel(__raw_readl(&txx9wdt_reg->tcr) & ~TXx9_TMTCR_TCE, 73 __raw_writel(__raw_readl(&txx9wdt_reg->tcr) & ~TXx9_TMTCR_TCE,
68 &txx9wdt_reg->tcr); 74 &txx9wdt_reg->tcr);
75 spin_unlock(&txx9_lock);
69} 76}
70 77
71static int txx9wdt_open(struct inode *inode, struct file *file) 78static int txx9wdt_open(struct inode *inode, struct file *file)
@@ -120,13 +127,13 @@ static ssize_t txx9wdt_write(struct file *file, const char __user *data,
120 return len; 127 return len;
121} 128}
122 129
123static int txx9wdt_ioctl(struct inode *inode, struct file *file, 130static long txx9wdt_ioctl(struct file *file, unsigned int cmd,
124 unsigned int cmd, unsigned long arg) 131 unsigned long arg)
125{ 132{
126 void __user *argp = (void __user *)arg; 133 void __user *argp = (void __user *)arg;
127 int __user *p = argp; 134 int __user *p = argp;
128 int new_timeout; 135 int new_timeout;
129 static struct watchdog_info ident = { 136 static const struct watchdog_info ident = {
130 .options = WDIOF_SETTIMEOUT | 137 .options = WDIOF_SETTIMEOUT |
131 WDIOF_KEEPALIVEPING | 138 WDIOF_KEEPALIVEPING |
132 WDIOF_MAGICCLOSE, 139 WDIOF_MAGICCLOSE,
@@ -135,8 +142,6 @@ static int txx9wdt_ioctl(struct inode *inode, struct file *file,
135 }; 142 };
136 143
137 switch (cmd) { 144 switch (cmd) {
138 default:
139 return -ENOTTY;
140 case WDIOC_GETSUPPORT: 145 case WDIOC_GETSUPPORT:
141 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 146 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
142 case WDIOC_GETSTATUS: 147 case WDIOC_GETSTATUS:
@@ -156,6 +161,8 @@ static int txx9wdt_ioctl(struct inode *inode, struct file *file,
156 /* Fall */ 161 /* Fall */
157 case WDIOC_GETTIMEOUT: 162 case WDIOC_GETTIMEOUT:
158 return put_user(timeout, p); 163 return put_user(timeout, p);
164 default:
165 return -ENOTTY;
159 } 166 }
160} 167}
161 168
@@ -168,22 +175,22 @@ static int txx9wdt_notify_sys(struct notifier_block *this, unsigned long code,
168} 175}
169 176
170static const struct file_operations txx9wdt_fops = { 177static const struct file_operations txx9wdt_fops = {
171 .owner = THIS_MODULE, 178 .owner = THIS_MODULE,
172 .llseek = no_llseek, 179 .llseek = no_llseek,
173 .write = txx9wdt_write, 180 .write = txx9wdt_write,
174 .ioctl = txx9wdt_ioctl, 181 .unlocked_ioctl = txx9wdt_ioctl,
175 .open = txx9wdt_open, 182 .open = txx9wdt_open,
176 .release = txx9wdt_release, 183 .release = txx9wdt_release,
177}; 184};
178 185
179static struct miscdevice txx9wdt_miscdev = { 186static struct miscdevice txx9wdt_miscdev = {
180 .minor = WATCHDOG_MINOR, 187 .minor = WATCHDOG_MINOR,
181 .name = "watchdog", 188 .name = "watchdog",
182 .fops = &txx9wdt_fops, 189 .fops = &txx9wdt_fops,
183}; 190};
184 191
185static struct notifier_block txx9wdt_notifier = { 192static struct notifier_block txx9wdt_notifier = {
186 .notifier_call = txx9wdt_notify_sys 193 .notifier_call = txx9wdt_notify_sys,
187}; 194};
188 195
189static int __init txx9wdt_probe(struct platform_device *dev) 196static int __init txx9wdt_probe(struct platform_device *dev)
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index 386492821fc2..69396adaa5c3 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -37,9 +37,9 @@
37#include <linux/reboot.h> 37#include <linux/reboot.h>
38#include <linux/init.h> 38#include <linux/init.h>
39#include <linux/spinlock.h> 39#include <linux/spinlock.h>
40#include <linux/io.h>
41#include <linux/uaccess.h>
40 42
41#include <asm/io.h>
42#include <asm/uaccess.h>
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 WDT"
@@ -57,22 +57,26 @@ MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)");
57 57
58static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ 58static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
59module_param(timeout, int, 0); 59module_param(timeout, int, 0);
60MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); 60MODULE_PARM_DESC(timeout,
61 "Watchdog timeout in seconds. 1 <= timeout <= 255, default="
62 __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
61 63
62static int nowayout = WATCHDOG_NOWAYOUT; 64static int nowayout = WATCHDOG_NOWAYOUT;
63module_param(nowayout, int, 0); 65module_param(nowayout, int, 0);
64MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 66MODULE_PARM_DESC(nowayout,
67 "Watchdog cannot be stopped once started (default="
68 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
65 69
66/* 70/*
67 * Kernel methods. 71 * Kernel methods.
68 */ 72 */
69 73
70#define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */ 74#define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */
71#define WDT_EFIR (wdt_io+0) /* Extended Function Index Register (same as EFER) */ 75#define WDT_EFIR (wdt_io+0) /* Extended Function Index Register
76 (same as EFER) */
72#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ 77#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
73 78
74static void 79static void w83627hf_select_wd_register(void)
75w83627hf_select_wd_register(void)
76{ 80{
77 unsigned char c; 81 unsigned char c;
78 outb_p(0x87, WDT_EFER); /* Enter extended function mode */ 82 outb_p(0x87, WDT_EFER); /* Enter extended function mode */
@@ -93,43 +97,45 @@ w83627hf_select_wd_register(void)
93 outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ 97 outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
94} 98}
95 99
96static void 100static void w83627hf_unselect_wd_register(void)
97w83627hf_unselect_wd_register(void)
98{ 101{
99 outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ 102 outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
100} 103}
101 104
102/* tyan motherboards seem to set F5 to 0x4C ? 105/* tyan motherboards seem to set F5 to 0x4C ?
103 * So explicitly init to appropriate value. */ 106 * So explicitly init to appropriate value. */
104static void 107
105w83627hf_init(void) 108static void w83627hf_init(void)
106{ 109{
107 unsigned char t; 110 unsigned char t;
108 111
109 w83627hf_select_wd_register(); 112 w83627hf_select_wd_register();
110 113
111 outb_p(0xF6, WDT_EFER); /* Select CRF6 */ 114 outb_p(0xF6, WDT_EFER); /* Select CRF6 */
112 t=inb_p(WDT_EFDR); /* read CRF6 */ 115 t = inb_p(WDT_EFDR); /* read CRF6 */
113 if (t != 0) { 116 if (t != 0) {
114 printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); 117 printk(KERN_INFO PFX
118 "Watchdog already running. Resetting timeout to %d sec\n",
119 timeout);
115 outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ 120 outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */
116 } 121 }
117 122
118 outb_p(0xF5, WDT_EFER); /* Select CRF5 */ 123 outb_p(0xF5, WDT_EFER); /* Select CRF5 */
119 t=inb_p(WDT_EFDR); /* read CRF5 */ 124 t = inb_p(WDT_EFDR); /* read CRF5 */
120 t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ 125 t &= ~0x0C; /* set second mode & disable keyboard
126 turning off watchdog */
121 outb_p(t, WDT_EFDR); /* Write back to CRF5 */ 127 outb_p(t, WDT_EFDR); /* Write back to CRF5 */
122 128
123 outb_p(0xF7, WDT_EFER); /* Select CRF7 */ 129 outb_p(0xF7, WDT_EFER); /* Select CRF7 */
124 t=inb_p(WDT_EFDR); /* read CRF7 */ 130 t = inb_p(WDT_EFDR); /* read CRF7 */
125 t&=~0xC0; /* disable keyboard & mouse turning off watchdog */ 131 t &= ~0xC0; /* disable keyboard & mouse turning off
132 watchdog */
126 outb_p(t, WDT_EFDR); /* Write back to CRF7 */ 133 outb_p(t, WDT_EFDR); /* Write back to CRF7 */
127 134
128 w83627hf_unselect_wd_register(); 135 w83627hf_unselect_wd_register();
129} 136}
130 137
131static void 138static void wdt_ctrl(int timeout)
132wdt_ctrl(int timeout)
133{ 139{
134 spin_lock(&io_lock); 140 spin_lock(&io_lock);
135 141
@@ -143,32 +149,28 @@ wdt_ctrl(int timeout)
143 spin_unlock(&io_lock); 149 spin_unlock(&io_lock);
144} 150}
145 151
146static int 152static int wdt_ping(void)
147wdt_ping(void)
148{ 153{
149 wdt_ctrl(timeout); 154 wdt_ctrl(timeout);
150 return 0; 155 return 0;
151} 156}
152 157
153static int 158static int wdt_disable(void)
154wdt_disable(void)
155{ 159{
156 wdt_ctrl(0); 160 wdt_ctrl(0);
157 return 0; 161 return 0;
158} 162}
159 163
160static int 164static int wdt_set_heartbeat(int t)
161wdt_set_heartbeat(int t)
162{ 165{
163 if ((t < 1) || (t > 255)) 166 if (t < 1 || t > 255)
164 return -EINVAL; 167 return -EINVAL;
165
166 timeout = t; 168 timeout = t;
167 return 0; 169 return 0;
168} 170}
169 171
170static ssize_t 172static ssize_t wdt_write(struct file *file, const char __user *buf,
171wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 173 size_t count, loff_t *ppos)
172{ 174{
173 if (count) { 175 if (count) {
174 if (!nowayout) { 176 if (!nowayout) {
@@ -178,7 +180,7 @@ wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
178 180
179 for (i = 0; i != count; i++) { 181 for (i = 0; i != count; i++) {
180 char c; 182 char c;
181 if (get_user(c, buf+i)) 183 if (get_user(c, buf + i))
182 return -EFAULT; 184 return -EFAULT;
183 if (c == 'V') 185 if (c == 'V')
184 expect_close = 42; 186 expect_close = 42;
@@ -189,72 +191,61 @@ wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
189 return count; 191 return count;
190} 192}
191 193
192static int 194static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
193wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
194 unsigned long arg)
195{ 195{
196 void __user *argp = (void __user *)arg; 196 void __user *argp = (void __user *)arg;
197 int __user *p = argp; 197 int __user *p = argp;
198 int new_timeout; 198 int new_timeout;
199 static struct watchdog_info ident = { 199 static struct watchdog_info ident = {
200 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 200 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
201 WDIOF_MAGICCLOSE,
201 .firmware_version = 1, 202 .firmware_version = 1,
202 .identity = "W83627HF WDT", 203 .identity = "W83627HF WDT",
203 }; 204 };
204 205
205 switch (cmd) { 206 switch (cmd) {
206 case WDIOC_GETSUPPORT: 207 case WDIOC_GETSUPPORT:
207 if (copy_to_user(argp, &ident, sizeof(ident))) 208 if (copy_to_user(argp, &ident, sizeof(ident)))
208 return -EFAULT; 209 return -EFAULT;
209 break; 210 break;
210
211 case WDIOC_GETSTATUS: 211 case WDIOC_GETSTATUS:
212 case WDIOC_GETBOOTSTATUS: 212 case WDIOC_GETBOOTSTATUS:
213 return put_user(0, p); 213 return put_user(0, p);
214
215 case WDIOC_KEEPALIVE:
216 wdt_ping();
217 break;
218
219 case WDIOC_SETTIMEOUT:
220 if (get_user(new_timeout, p))
221 return -EFAULT;
222 if (wdt_set_heartbeat(new_timeout))
223 return -EINVAL;
224 wdt_ping();
225 /* Fall */
226
227 case WDIOC_GETTIMEOUT:
228 return put_user(timeout, p);
229
230 case WDIOC_SETOPTIONS: 214 case WDIOC_SETOPTIONS:
231 { 215 {
232 int options, retval = -EINVAL; 216 int options, retval = -EINVAL;
233
234 if (get_user(options, p))
235 return -EFAULT;
236
237 if (options & WDIOS_DISABLECARD) {
238 wdt_disable();
239 retval = 0;
240 }
241
242 if (options & WDIOS_ENABLECARD) {
243 wdt_ping();
244 retval = 0;
245 }
246 217
247 return retval; 218 if (get_user(options, p))
219 return -EFAULT;
220 if (options & WDIOS_DISABLECARD) {
221 wdt_disable();
222 retval = 0;
223 }
224 if (options & WDIOS_ENABLECARD) {
225 wdt_ping();
226 retval = 0;
227 }
228 return retval;
248 } 229 }
249 230 case WDIOC_KEEPALIVE:
231 wdt_ping();
232 break;
233 case WDIOC_SETTIMEOUT:
234 if (get_user(new_timeout, p))
235 return -EFAULT;
236 if (wdt_set_heartbeat(new_timeout))
237 return -EINVAL;
238 wdt_ping();
239 /* Fall */
240 case WDIOC_GETTIMEOUT:
241 return put_user(timeout, p);
250 default: 242 default:
251 return -ENOTTY; 243 return -ENOTTY;
252 } 244 }
253 return 0; 245 return 0;
254} 246}
255 247
256static int 248static int wdt_open(struct inode *inode, struct file *file)
257wdt_open(struct inode *inode, struct file *file)
258{ 249{
259 if (test_and_set_bit(0, &wdt_is_open)) 250 if (test_and_set_bit(0, &wdt_is_open))
260 return -EBUSY; 251 return -EBUSY;
@@ -266,13 +257,13 @@ wdt_open(struct inode *inode, struct file *file)
266 return nonseekable_open(inode, file); 257 return nonseekable_open(inode, file);
267} 258}
268 259
269static int 260static int wdt_close(struct inode *inode, struct file *file)
270wdt_close(struct inode *inode, struct file *file)
271{ 261{
272 if (expect_close == 42) { 262 if (expect_close == 42)
273 wdt_disable(); 263 wdt_disable();
274 } else { 264 else {
275 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 265 printk(KERN_CRIT PFX
266 "Unexpected close, not stopping watchdog!\n");
276 wdt_ping(); 267 wdt_ping();
277 } 268 }
278 expect_close = 0; 269 expect_close = 0;
@@ -284,14 +275,12 @@ wdt_close(struct inode *inode, struct file *file)
284 * Notifier for system down 275 * Notifier for system down
285 */ 276 */
286 277
287static int 278static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
288wdt_notify_sys(struct notifier_block *this, unsigned long code,
289 void *unused) 279 void *unused)
290{ 280{
291 if (code == SYS_DOWN || code == SYS_HALT) { 281 if (code == SYS_DOWN || code == SYS_HALT)
292 /* Turn the WDT off */ 282 wdt_disable(); /* Turn the WDT off */
293 wdt_disable(); 283
294 }
295 return NOTIFY_DONE; 284 return NOTIFY_DONE;
296} 285}
297 286
@@ -303,7 +292,7 @@ static const struct file_operations wdt_fops = {
303 .owner = THIS_MODULE, 292 .owner = THIS_MODULE,
304 .llseek = no_llseek, 293 .llseek = no_llseek,
305 .write = wdt_write, 294 .write = wdt_write,
306 .ioctl = wdt_ioctl, 295 .unlocked_ioctl = wdt_ioctl,
307 .open = wdt_open, 296 .open = wdt_open,
308 .release = wdt_close, 297 .release = wdt_close,
309}; 298};
@@ -323,8 +312,7 @@ static struct notifier_block wdt_notifier = {
323 .notifier_call = wdt_notify_sys, 312 .notifier_call = wdt_notify_sys,
324}; 313};
325 314
326static int __init 315static int __init wdt_init(void)
327wdt_init(void)
328{ 316{
329 int ret; 317 int ret;
330 318
@@ -332,12 +320,13 @@ wdt_init(void)
332 320
333 if (wdt_set_heartbeat(timeout)) { 321 if (wdt_set_heartbeat(timeout)) {
334 wdt_set_heartbeat(WATCHDOG_TIMEOUT); 322 wdt_set_heartbeat(WATCHDOG_TIMEOUT);
335 printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", 323 printk(KERN_INFO PFX
336 WATCHDOG_TIMEOUT); 324 "timeout value must be 1 <= timeout <= 255, using %d\n",
325 WATCHDOG_TIMEOUT);
337 } 326 }
338 327
339 if (!request_region(wdt_io, 1, WATCHDOG_NAME)) { 328 if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
340 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", 329 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
341 wdt_io); 330 wdt_io);
342 ret = -EIO; 331 ret = -EIO;
343 goto out; 332 goto out;
@@ -347,20 +336,22 @@ wdt_init(void)
347 336
348 ret = register_reboot_notifier(&wdt_notifier); 337 ret = register_reboot_notifier(&wdt_notifier);
349 if (ret != 0) { 338 if (ret != 0) {
350 printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 339 printk(KERN_ERR PFX
351 ret); 340 "cannot register reboot notifier (err=%d)\n", ret);
352 goto unreg_regions; 341 goto unreg_regions;
353 } 342 }
354 343
355 ret = misc_register(&wdt_miscdev); 344 ret = misc_register(&wdt_miscdev);
356 if (ret != 0) { 345 if (ret != 0) {
357 printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 346 printk(KERN_ERR PFX
358 WATCHDOG_MINOR, ret); 347 "cannot register miscdev on minor=%d (err=%d)\n",
348 WATCHDOG_MINOR, ret);
359 goto unreg_reboot; 349 goto unreg_reboot;
360 } 350 }
361 351
362 printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", 352 printk(KERN_INFO PFX
363 timeout, nowayout); 353 "initialized. timeout=%d sec (nowayout=%d)\n",
354 timeout, nowayout);
364 355
365out: 356out:
366 return ret; 357 return ret;
@@ -371,12 +362,11 @@ unreg_regions:
371 goto out; 362 goto out;
372} 363}
373 364
374static void __exit 365static void __exit wdt_exit(void)
375wdt_exit(void)
376{ 366{
377 misc_deregister(&wdt_miscdev); 367 misc_deregister(&wdt_miscdev);
378 unregister_reboot_notifier(&wdt_notifier); 368 unregister_reboot_notifier(&wdt_notifier);
379 release_region(wdt_io,1); 369 release_region(wdt_io, 1);
380} 370}
381 371
382module_init(wdt_init); 372module_init(wdt_init);
diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c
index 528b882420b6..445d30a01ed3 100644
--- a/drivers/watchdog/w83697hf_wdt.c
+++ b/drivers/watchdog/w83697hf_wdt.c
@@ -36,9 +36,9 @@
36#include <linux/reboot.h> 36#include <linux/reboot.h>
37#include <linux/init.h> 37#include <linux/init.h>
38#include <linux/spinlock.h> 38#include <linux/spinlock.h>
39#include <linux/io.h>
40#include <linux/uaccess.h>
39 41
40#include <asm/io.h>
41#include <asm/uaccess.h>
42#include <asm/system.h> 42#include <asm/system.h>
43 43
44#define WATCHDOG_NAME "w83697hf/hg WDT" 44#define WATCHDOG_NAME "w83697hf/hg WDT"
@@ -53,37 +53,43 @@ static DEFINE_SPINLOCK(io_lock);
53/* You must set this - there is no sane way to probe for this board. */ 53/* You must set this - there is no sane way to probe for this board. */
54static int wdt_io = 0x2e; 54static int wdt_io = 0x2e;
55module_param(wdt_io, int, 0); 55module_param(wdt_io, int, 0);
56MODULE_PARM_DESC(wdt_io, "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect)"); 56MODULE_PARM_DESC(wdt_io,
57 "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect)");
57 58
58static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ 59static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
59module_param(timeout, int, 0); 60module_param(timeout, int, 0);
60MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255 (default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 61MODULE_PARM_DESC(timeout,
62 "Watchdog timeout in seconds. 1<= timeout <=255 (default="
63 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
61 64
62static int nowayout = WATCHDOG_NOWAYOUT; 65static int nowayout = WATCHDOG_NOWAYOUT;
63module_param(nowayout, int, 0); 66module_param(nowayout, int, 0);
64MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 67MODULE_PARM_DESC(nowayout,
68 "Watchdog cannot be stopped once started (default="
69 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
65 70
66static int early_disable = WATCHDOG_EARLY_DISABLE; 71static int early_disable = WATCHDOG_EARLY_DISABLE;
67module_param(early_disable, int, 0); 72module_param(early_disable, int, 0);
68MODULE_PARM_DESC(early_disable, "Watchdog gets disabled at boot time (default=" __MODULE_STRING(WATCHDOG_EARLY_DISABLE) ")"); 73MODULE_PARM_DESC(early_disable,
74 "Watchdog gets disabled at boot time (default="
75 __MODULE_STRING(WATCHDOG_EARLY_DISABLE) ")");
69 76
70/* 77/*
71 * Kernel methods. 78 * Kernel methods.
72 */ 79 */
73 80
74#define W83697HF_EFER (wdt_io+0) /* Extended Function Enable Register */ 81#define W83697HF_EFER (wdt_io + 0) /* Extended Function Enable Register */
75#define W83697HF_EFIR (wdt_io+0) /* Extended Function Index Register (same as EFER) */ 82#define W83697HF_EFIR (wdt_io + 0) /* Extended Function Index Register
76#define W83697HF_EFDR (wdt_io+1) /* Extended Function Data Register */ 83 (same as EFER) */
84#define W83697HF_EFDR (wdt_io + 1) /* Extended Function Data Register */
77 85
78static inline void 86static inline void w83697hf_unlock(void)
79w83697hf_unlock(void)
80{ 87{
81 outb_p(0x87, W83697HF_EFER); /* Enter extended function mode */ 88 outb_p(0x87, W83697HF_EFER); /* Enter extended function mode */
82 outb_p(0x87, W83697HF_EFER); /* Again according to manual */ 89 outb_p(0x87, W83697HF_EFER); /* Again according to manual */
83} 90}
84 91
85static inline void 92static inline void w83697hf_lock(void)
86w83697hf_lock(void)
87{ 93{
88 outb_p(0xAA, W83697HF_EFER); /* Leave extended function mode */ 94 outb_p(0xAA, W83697HF_EFER); /* Leave extended function mode */
89} 95}
@@ -93,41 +99,36 @@ w83697hf_lock(void)
93 * w83697hf_write_timeout() must be called with the device unlocked. 99 * w83697hf_write_timeout() must be called with the device unlocked.
94 */ 100 */
95 101
96static unsigned char 102static unsigned char w83697hf_get_reg(unsigned char reg)
97w83697hf_get_reg(unsigned char reg)
98{ 103{
99 outb_p(reg, W83697HF_EFIR); 104 outb_p(reg, W83697HF_EFIR);
100 return inb_p(W83697HF_EFDR); 105 return inb_p(W83697HF_EFDR);
101} 106}
102 107
103static void 108static void w83697hf_set_reg(unsigned char reg, unsigned char data)
104w83697hf_set_reg(unsigned char reg, unsigned char data)
105{ 109{
106 outb_p(reg, W83697HF_EFIR); 110 outb_p(reg, W83697HF_EFIR);
107 outb_p(data, W83697HF_EFDR); 111 outb_p(data, W83697HF_EFDR);
108} 112}
109 113
110static void 114static void w83697hf_write_timeout(int timeout)
111w83697hf_write_timeout(int timeout)
112{ 115{
113 w83697hf_set_reg(0xF4, timeout); /* Write Timeout counter to CRF4 */ 116 /* Write Timeout counter to CRF4 */
117 w83697hf_set_reg(0xF4, timeout);
114} 118}
115 119
116static void 120static void w83697hf_select_wdt(void)
117w83697hf_select_wdt(void)
118{ 121{
119 w83697hf_unlock(); 122 w83697hf_unlock();
120 w83697hf_set_reg(0x07, 0x08); /* Switch to logic device 8 (GPIO2) */ 123 w83697hf_set_reg(0x07, 0x08); /* Switch to logic device 8 (GPIO2) */
121} 124}
122 125
123static inline void 126static inline void w83697hf_deselect_wdt(void)
124w83697hf_deselect_wdt(void)
125{ 127{
126 w83697hf_lock(); 128 w83697hf_lock();
127} 129}
128 130
129static void 131static void w83697hf_init(void)
130w83697hf_init(void)
131{ 132{
132 unsigned char bbuf; 133 unsigned char bbuf;
133 134
@@ -136,7 +137,9 @@ w83697hf_init(void)
136 bbuf = w83697hf_get_reg(0x29); 137 bbuf = w83697hf_get_reg(0x29);
137 bbuf &= ~0x60; 138 bbuf &= ~0x60;
138 bbuf |= 0x20; 139 bbuf |= 0x20;
139 w83697hf_set_reg(0x29, bbuf); /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ 140
141 /* Set pin 119 to WDTO# mode (= CR29, WDT0) */
142 w83697hf_set_reg(0x29, bbuf);
140 143
141 bbuf = w83697hf_get_reg(0xF3); 144 bbuf = w83697hf_get_reg(0xF3);
142 bbuf &= ~0x04; 145 bbuf &= ~0x04;
@@ -145,8 +148,7 @@ w83697hf_init(void)
145 w83697hf_deselect_wdt(); 148 w83697hf_deselect_wdt();
146} 149}
147 150
148static void 151static void wdt_ping(void)
149wdt_ping(void)
150{ 152{
151 spin_lock(&io_lock); 153 spin_lock(&io_lock);
152 w83697hf_select_wdt(); 154 w83697hf_select_wdt();
@@ -157,8 +159,7 @@ wdt_ping(void)
157 spin_unlock(&io_lock); 159 spin_unlock(&io_lock);
158} 160}
159 161
160static void 162static void wdt_enable(void)
161wdt_enable(void)
162{ 163{
163 spin_lock(&io_lock); 164 spin_lock(&io_lock);
164 w83697hf_select_wdt(); 165 w83697hf_select_wdt();
@@ -170,8 +171,7 @@ wdt_enable(void)
170 spin_unlock(&io_lock); 171 spin_unlock(&io_lock);
171} 172}
172 173
173static void 174static void wdt_disable(void)
174wdt_disable(void)
175{ 175{
176 spin_lock(&io_lock); 176 spin_lock(&io_lock);
177 w83697hf_select_wdt(); 177 w83697hf_select_wdt();
@@ -183,8 +183,7 @@ wdt_disable(void)
183 spin_unlock(&io_lock); 183 spin_unlock(&io_lock);
184} 184}
185 185
186static unsigned char 186static unsigned char wdt_running(void)
187wdt_running(void)
188{ 187{
189 unsigned char t; 188 unsigned char t;
190 189
@@ -199,18 +198,17 @@ wdt_running(void)
199 return t; 198 return t;
200} 199}
201 200
202static int 201static int wdt_set_heartbeat(int t)
203wdt_set_heartbeat(int t)
204{ 202{
205 if ((t < 1) || (t > 255)) 203 if (t < 1 || t > 255)
206 return -EINVAL; 204 return -EINVAL;
207 205
208 timeout = t; 206 timeout = t;
209 return 0; 207 return 0;
210} 208}
211 209
212static ssize_t 210static ssize_t wdt_write(struct file *file, const char __user *buf,
213wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 211 size_t count, loff_t *ppos)
214{ 212{
215 if (count) { 213 if (count) {
216 if (!nowayout) { 214 if (!nowayout) {
@@ -220,7 +218,7 @@ wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
220 218
221 for (i = 0; i != count; i++) { 219 for (i = 0; i != count; i++) {
222 char c; 220 char c;
223 if (get_user(c, buf+i)) 221 if (get_user(c, buf + i))
224 return -EFAULT; 222 return -EFAULT;
225 if (c == 'V') 223 if (c == 'V')
226 expect_close = 42; 224 expect_close = 42;
@@ -231,15 +229,14 @@ wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
231 return count; 229 return count;
232} 230}
233 231
234static int 232static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
235wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
236 unsigned long arg)
237{ 233{
238 void __user *argp = (void __user *)arg; 234 void __user *argp = (void __user *)arg;
239 int __user *p = argp; 235 int __user *p = argp;
240 int new_timeout; 236 int new_timeout;
241 static struct watchdog_info ident = { 237 static const struct watchdog_info ident = {
242 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 238 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
239 | WDIOF_MAGICCLOSE,
243 .firmware_version = 1, 240 .firmware_version = 1,
244 .identity = "W83697HF WDT", 241 .identity = "W83697HF WDT",
245 }; 242 };
@@ -254,21 +251,6 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
254 case WDIOC_GETBOOTSTATUS: 251 case WDIOC_GETBOOTSTATUS:
255 return put_user(0, p); 252 return put_user(0, p);
256 253
257 case WDIOC_KEEPALIVE:
258 wdt_ping();
259 break;
260
261 case WDIOC_SETTIMEOUT:
262 if (get_user(new_timeout, p))
263 return -EFAULT;
264 if (wdt_set_heartbeat(new_timeout))
265 return -EINVAL;
266 wdt_ping();
267 /* Fall */
268
269 case WDIOC_GETTIMEOUT:
270 return put_user(timeout, p);
271
272 case WDIOC_SETOPTIONS: 254 case WDIOC_SETOPTIONS:
273 { 255 {
274 int options, retval = -EINVAL; 256 int options, retval = -EINVAL;
@@ -289,14 +271,28 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
289 return retval; 271 return retval;
290 } 272 }
291 273
274 case WDIOC_KEEPALIVE:
275 wdt_ping();
276 break;
277
278 case WDIOC_SETTIMEOUT:
279 if (get_user(new_timeout, p))
280 return -EFAULT;
281 if (wdt_set_heartbeat(new_timeout))
282 return -EINVAL;
283 wdt_ping();
284 /* Fall */
285
286 case WDIOC_GETTIMEOUT:
287 return put_user(timeout, p);
288
292 default: 289 default:
293 return -ENOTTY; 290 return -ENOTTY;
294 } 291 }
295 return 0; 292 return 0;
296} 293}
297 294
298static int 295static int wdt_open(struct inode *inode, struct file *file)
299wdt_open(struct inode *inode, struct file *file)
300{ 296{
301 if (test_and_set_bit(0, &wdt_is_open)) 297 if (test_and_set_bit(0, &wdt_is_open))
302 return -EBUSY; 298 return -EBUSY;
@@ -308,13 +304,13 @@ wdt_open(struct inode *inode, struct file *file)
308 return nonseekable_open(inode, file); 304 return nonseekable_open(inode, file);
309} 305}
310 306
311static int 307static int wdt_close(struct inode *inode, struct file *file)
312wdt_close(struct inode *inode, struct file *file)
313{ 308{
314 if (expect_close == 42) { 309 if (expect_close == 42)
315 wdt_disable(); 310 wdt_disable();
316 } else { 311 else {
317 printk (KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 312 printk(KERN_CRIT PFX
313 "Unexpected close, not stopping watchdog!\n");
318 wdt_ping(); 314 wdt_ping();
319 } 315 }
320 expect_close = 0; 316 expect_close = 0;
@@ -326,14 +322,12 @@ wdt_close(struct inode *inode, struct file *file)
326 * Notifier for system down 322 * Notifier for system down
327 */ 323 */
328 324
329static int 325static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
330wdt_notify_sys(struct notifier_block *this, unsigned long code,
331 void *unused) 326 void *unused)
332{ 327{
333 if (code == SYS_DOWN || code == SYS_HALT) { 328 if (code == SYS_DOWN || code == SYS_HALT)
334 /* Turn the WDT off */ 329 wdt_disable(); /* Turn the WDT off */
335 wdt_disable(); 330
336 }
337 return NOTIFY_DONE; 331 return NOTIFY_DONE;
338} 332}
339 333
@@ -345,7 +339,7 @@ static const struct file_operations wdt_fops = {
345 .owner = THIS_MODULE, 339 .owner = THIS_MODULE,
346 .llseek = no_llseek, 340 .llseek = no_llseek,
347 .write = wdt_write, 341 .write = wdt_write,
348 .ioctl = wdt_ioctl, 342 .unlocked_ioctl = wdt_ioctl,
349 .open = wdt_open, 343 .open = wdt_open,
350 .release = wdt_close, 344 .release = wdt_close,
351}; 345};
@@ -365,36 +359,38 @@ static struct notifier_block wdt_notifier = {
365 .notifier_call = wdt_notify_sys, 359 .notifier_call = wdt_notify_sys,
366}; 360};
367 361
368static int 362static int w83697hf_check_wdt(void)
369w83697hf_check_wdt(void)
370{ 363{
371 if (!request_region(wdt_io, 2, WATCHDOG_NAME)) { 364 if (!request_region(wdt_io, 2, WATCHDOG_NAME)) {
372 printk (KERN_ERR PFX "I/O address 0x%x already in use\n", wdt_io); 365 printk(KERN_ERR PFX
366 "I/O address 0x%x already in use\n", wdt_io);
373 return -EIO; 367 return -EIO;
374 } 368 }
375 369
376 printk (KERN_DEBUG PFX "Looking for watchdog at address 0x%x\n", wdt_io); 370 printk(KERN_DEBUG PFX
371 "Looking for watchdog at address 0x%x\n", wdt_io);
377 w83697hf_unlock(); 372 w83697hf_unlock();
378 if (w83697hf_get_reg(0x20) == 0x60) { 373 if (w83697hf_get_reg(0x20) == 0x60) {
379 printk (KERN_INFO PFX "watchdog found at address 0x%x\n", wdt_io); 374 printk(KERN_INFO PFX
375 "watchdog found at address 0x%x\n", wdt_io);
380 w83697hf_lock(); 376 w83697hf_lock();
381 return 0; 377 return 0;
382 } 378 }
383 w83697hf_lock(); /* Reprotect in case it was a compatible device */ 379 /* Reprotect in case it was a compatible device */
380 w83697hf_lock();
384 381
385 printk (KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io); 382 printk(KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io);
386 release_region(wdt_io, 2); 383 release_region(wdt_io, 2);
387 return -EIO; 384 return -EIO;
388} 385}
389 386
390static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 }; 387static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 };
391 388
392static int __init 389static int __init wdt_init(void)
393wdt_init(void)
394{ 390{
395 int ret, i, found = 0; 391 int ret, i, found = 0;
396 392
397 printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n"); 393 printk(KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n");
398 394
399 if (wdt_io == 0) { 395 if (wdt_io == 0) {
400 /* we will autodetect the W83697HF/HG watchdog */ 396 /* we will autodetect the W83697HF/HG watchdog */
@@ -409,7 +405,7 @@ wdt_init(void)
409 } 405 }
410 406
411 if (!found) { 407 if (!found) {
412 printk (KERN_ERR PFX "No W83697HF/HG could be found\n"); 408 printk(KERN_ERR PFX "No W83697HF/HG could be found\n");
413 ret = -EIO; 409 ret = -EIO;
414 goto out; 410 goto out;
415 } 411 }
@@ -417,31 +413,33 @@ wdt_init(void)
417 w83697hf_init(); 413 w83697hf_init();
418 if (early_disable) { 414 if (early_disable) {
419 if (wdt_running()) 415 if (wdt_running())
420 printk (KERN_WARNING PFX "Stopping previously enabled watchdog until userland kicks in\n"); 416 printk(KERN_WARNING PFX "Stopping previously enabled watchdog until userland kicks in\n");
421 wdt_disable(); 417 wdt_disable();
422 } 418 }
423 419
424 if (wdt_set_heartbeat(timeout)) { 420 if (wdt_set_heartbeat(timeout)) {
425 wdt_set_heartbeat(WATCHDOG_TIMEOUT); 421 wdt_set_heartbeat(WATCHDOG_TIMEOUT);
426 printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", 422 printk(KERN_INFO PFX
427 WATCHDOG_TIMEOUT); 423 "timeout value must be 1 <= timeout <= 255, using %d\n",
424 WATCHDOG_TIMEOUT);
428 } 425 }
429 426
430 ret = register_reboot_notifier(&wdt_notifier); 427 ret = register_reboot_notifier(&wdt_notifier);
431 if (ret != 0) { 428 if (ret != 0) {
432 printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 429 printk(KERN_ERR PFX
433 ret); 430 "cannot register reboot notifier (err=%d)\n", ret);
434 goto unreg_regions; 431 goto unreg_regions;
435 } 432 }
436 433
437 ret = misc_register(&wdt_miscdev); 434 ret = misc_register(&wdt_miscdev);
438 if (ret != 0) { 435 if (ret != 0) {
439 printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 436 printk(KERN_ERR PFX
440 WATCHDOG_MINOR, ret); 437 "cannot register miscdev on minor=%d (err=%d)\n",
438 WATCHDOG_MINOR, ret);
441 goto unreg_reboot; 439 goto unreg_reboot;
442 } 440 }
443 441
444 printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", 442 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
445 timeout, nowayout); 443 timeout, nowayout);
446 444
447out: 445out:
@@ -453,8 +451,7 @@ unreg_regions:
453 goto out; 451 goto out;
454} 452}
455 453
456static void __exit 454static void __exit wdt_exit(void)
457wdt_exit(void)
458{ 455{
459 misc_deregister(&wdt_miscdev); 456 misc_deregister(&wdt_miscdev);
460 unregister_reboot_notifier(&wdt_notifier); 457 unregister_reboot_notifier(&wdt_notifier);
diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c
index f510a3a595e6..24587d2060c4 100644
--- a/drivers/watchdog/w83877f_wdt.c
+++ b/drivers/watchdog/w83877f_wdt.c
@@ -23,13 +23,16 @@
23 * Added KERN_* tags to printks 23 * Added KERN_* tags to printks
24 * add CONFIG_WATCHDOG_NOWAYOUT support 24 * add CONFIG_WATCHDOG_NOWAYOUT support
25 * fix possible wdt_is_open race 25 * fix possible wdt_is_open race
26 * changed watchdog_info to correctly reflect what the driver offers 26 * changed watchdog_info to correctly reflect what
27 * added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT, 27 * the driver offers
28 * added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS,
29 * WDIOC_SETTIMEOUT,
28 * WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls 30 * WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls
29 * 09/8 - 2003 [wim@iguana.be] cleanup of trailing spaces 31 * 09/8 - 2003 [wim@iguana.be] cleanup of trailing spaces
30 * added extra printk's for startup problems 32 * added extra printk's for startup problems
31 * use module_param 33 * use module_param
32 * made timeout (the emulated heartbeat) a module_param 34 * made timeout (the emulated heartbeat) a
35 * module_param
33 * made the keepalive ping an internal subroutine 36 * made the keepalive ping an internal subroutine
34 * 37 *
35 * This WDT driver is different from most other Linux WDT 38 * This WDT driver is different from most other Linux WDT
@@ -51,8 +54,8 @@
51#include <linux/notifier.h> 54#include <linux/notifier.h>
52#include <linux/reboot.h> 55#include <linux/reboot.h>
53#include <linux/init.h> 56#include <linux/init.h>
54#include <asm/io.h> 57#include <linux/io.h>
55#include <asm/uaccess.h> 58#include <linux/uaccess.h>
56#include <asm/system.h> 59#include <asm/system.h>
57 60
58#define OUR_NAME "w83877f_wdt" 61#define OUR_NAME "w83877f_wdt"
@@ -80,14 +83,19 @@
80 */ 83 */
81 84
82#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ 85#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */
83static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ 86/* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
87static int timeout = WATCHDOG_TIMEOUT;
84module_param(timeout, int, 0); 88module_param(timeout, int, 0);
85MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 89MODULE_PARM_DESC(timeout,
90 "Watchdog timeout in seconds. (1<=timeout<=3600, default="
91 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
86 92
87 93
88static int nowayout = WATCHDOG_NOWAYOUT; 94static int nowayout = WATCHDOG_NOWAYOUT;
89module_param(nowayout, int, 0); 95module_param(nowayout, int, 0);
90MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 96MODULE_PARM_DESC(nowayout,
97 "Watchdog cannot be stopped once started (default="
98 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
91 99
92static void wdt_timer_ping(unsigned long); 100static void wdt_timer_ping(unsigned long);
93static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0); 101static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
@@ -105,8 +113,7 @@ static void wdt_timer_ping(unsigned long data)
105 /* If we got a heartbeat pulse within the WDT_US_INTERVAL 113 /* If we got a heartbeat pulse within the WDT_US_INTERVAL
106 * we agree to ping the WDT 114 * we agree to ping the WDT
107 */ 115 */
108 if(time_before(jiffies, next_heartbeat)) 116 if (time_before(jiffies, next_heartbeat)) {
109 {
110 /* Ping the WDT */ 117 /* Ping the WDT */
111 spin_lock(&wdt_spinlock); 118 spin_lock(&wdt_spinlock);
112 119
@@ -118,9 +125,9 @@ static void wdt_timer_ping(unsigned long data)
118 125
119 spin_unlock(&wdt_spinlock); 126 spin_unlock(&wdt_spinlock);
120 127
121 } else { 128 } else
122 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); 129 printk(KERN_WARNING PFX
123 } 130 "Heartbeat lost! Will not ping the watchdog\n");
124} 131}
125 132
126/* 133/*
@@ -181,22 +188,21 @@ static void wdt_keepalive(void)
181 * /dev/watchdog handling 188 * /dev/watchdog handling
182 */ 189 */
183 190
184static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) 191static ssize_t fop_write(struct file *file, const char __user *buf,
192 size_t count, loff_t *ppos)
185{ 193{
186 /* See if we got the magic character 'V' and reload the timer */ 194 /* See if we got the magic character 'V' and reload the timer */
187 if(count) 195 if (count) {
188 { 196 if (!nowayout) {
189 if (!nowayout)
190 {
191 size_t ofs; 197 size_t ofs;
192 198
193 /* note: just in case someone wrote the magic character 199 /* note: just in case someone wrote the magic
194 * five months ago... */ 200 character five months ago... */
195 wdt_expect_close = 0; 201 wdt_expect_close = 0;
196 202
197 /* scan to see whether or not we got the magic character */ 203 /* scan to see whether or not we got the
198 for(ofs = 0; ofs != count; ofs++) 204 magic character */
199 { 205 for (ofs = 0; ofs != count; ofs++) {
200 char c; 206 char c;
201 if (get_user(c, buf + ofs)) 207 if (get_user(c, buf + ofs))
202 return -EFAULT; 208 return -EFAULT;
@@ -211,10 +217,10 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou
211 return count; 217 return count;
212} 218}
213 219
214static int fop_open(struct inode * inode, struct file * file) 220static int fop_open(struct inode *inode, struct file *file)
215{ 221{
216 /* Just in case we're already talking to someone... */ 222 /* Just in case we're already talking to someone... */
217 if(test_and_set_bit(0, &wdt_is_open)) 223 if (test_and_set_bit(0, &wdt_is_open))
218 return -EBUSY; 224 return -EBUSY;
219 225
220 /* Good, fire up the show */ 226 /* Good, fire up the show */
@@ -222,78 +228,78 @@ static int fop_open(struct inode * inode, struct file * file)
222 return nonseekable_open(inode, file); 228 return nonseekable_open(inode, file);
223} 229}
224 230
225static int fop_close(struct inode * inode, struct file * file) 231static int fop_close(struct inode *inode, struct file *file)
226{ 232{
227 if(wdt_expect_close == 42) 233 if (wdt_expect_close == 42)
228 wdt_turnoff(); 234 wdt_turnoff();
229 else { 235 else {
230 del_timer(&timer); 236 del_timer(&timer);
231 printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n"); 237 printk(KERN_CRIT PFX
238 "device file closed unexpectedly. Will not stop the WDT!\n");
232 } 239 }
233 clear_bit(0, &wdt_is_open); 240 clear_bit(0, &wdt_is_open);
234 wdt_expect_close = 0; 241 wdt_expect_close = 0;
235 return 0; 242 return 0;
236} 243}
237 244
238static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 245static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
239 unsigned long arg)
240{ 246{
241 void __user *argp = (void __user *)arg; 247 void __user *argp = (void __user *)arg;
242 int __user *p = argp; 248 int __user *p = argp;
243 static struct watchdog_info ident= 249 static const struct watchdog_info ident = {
244 { 250 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
245 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 251 | WDIOF_MAGICCLOSE,
246 .firmware_version = 1, 252 .firmware_version = 1,
247 .identity = "W83877F", 253 .identity = "W83877F",
248 }; 254 };
249 255
250 switch(cmd) 256 switch (cmd) {
257 case WDIOC_GETSUPPORT:
258 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
259 case WDIOC_GETSTATUS:
260 case WDIOC_GETBOOTSTATUS:
261 return put_user(0, p);
262 case WDIOC_SETOPTIONS:
251 { 263 {
252 default: 264 int new_options, retval = -EINVAL;
253 return -ENOTTY;
254 case WDIOC_GETSUPPORT:
255 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
256 case WDIOC_GETSTATUS:
257 case WDIOC_GETBOOTSTATUS:
258 return put_user(0, p);
259 case WDIOC_KEEPALIVE:
260 wdt_keepalive();
261 return 0;
262 case WDIOC_SETOPTIONS:
263 {
264 int new_options, retval = -EINVAL;
265
266 if(get_user(new_options, p))
267 return -EFAULT;
268
269 if(new_options & WDIOS_DISABLECARD) {
270 wdt_turnoff();
271 retval = 0;
272 }
273 265
274 if(new_options & WDIOS_ENABLECARD) { 266 if (get_user(new_options, p))
275 wdt_startup(); 267 return -EFAULT;
276 retval = 0;
277 }
278 268
279 return retval; 269 if (new_options & WDIOS_DISABLECARD) {
270 wdt_turnoff();
271 retval = 0;
280 } 272 }
281 case WDIOC_SETTIMEOUT:
282 {
283 int new_timeout;
284 273
285 if(get_user(new_timeout, p)) 274 if (new_options & WDIOS_ENABLECARD) {
286 return -EFAULT; 275 wdt_startup();
276 retval = 0;
277 }
287 278
288 if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ 279 return retval;
289 return -EINVAL; 280 }
281 case WDIOC_KEEPALIVE:
282 wdt_keepalive();
283 return 0;
284 case WDIOC_SETTIMEOUT:
285 {
286 int new_timeout;
290 287
291 timeout = new_timeout; 288 if (get_user(new_timeout, p))
292 wdt_keepalive(); 289 return -EFAULT;
293 /* Fall through */ 290
294 } 291 /* arbitrary upper limit */
295 case WDIOC_GETTIMEOUT: 292 if (new_timeout < 1 || new_timeout > 3600)
296 return put_user(timeout, p); 293 return -EINVAL;
294
295 timeout = new_timeout;
296 wdt_keepalive();
297 /* Fall through */
298 }
299 case WDIOC_GETTIMEOUT:
300 return put_user(timeout, p);
301 default:
302 return -ENOTTY;
297 } 303 }
298} 304}
299 305
@@ -303,7 +309,7 @@ static const struct file_operations wdt_fops = {
303 .write = fop_write, 309 .write = fop_write,
304 .open = fop_open, 310 .open = fop_open,
305 .release = fop_close, 311 .release = fop_close,
306 .ioctl = fop_ioctl, 312 .unlocked_ioctl = fop_ioctl,
307}; 313};
308 314
309static struct miscdevice wdt_miscdev = { 315static struct miscdevice wdt_miscdev = {
@@ -319,7 +325,7 @@ static struct miscdevice wdt_miscdev = {
319static int wdt_notify_sys(struct notifier_block *this, unsigned long code, 325static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
320 void *unused) 326 void *unused)
321{ 327{
322 if(code==SYS_DOWN || code==SYS_HALT) 328 if (code == SYS_DOWN || code == SYS_HALT)
323 wdt_turnoff(); 329 wdt_turnoff();
324 return NOTIFY_DONE; 330 return NOTIFY_DONE;
325} 331}
@@ -329,8 +335,7 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
329 * turn the timebomb registers off. 335 * turn the timebomb registers off.
330 */ 336 */
331 337
332static struct notifier_block wdt_notifier= 338static struct notifier_block wdt_notifier = {
333{
334 .notifier_call = wdt_notify_sys, 339 .notifier_call = wdt_notify_sys,
335}; 340};
336 341
@@ -342,31 +347,29 @@ static void __exit w83877f_wdt_unload(void)
342 misc_deregister(&wdt_miscdev); 347 misc_deregister(&wdt_miscdev);
343 348
344 unregister_reboot_notifier(&wdt_notifier); 349 unregister_reboot_notifier(&wdt_notifier);
345 release_region(WDT_PING,1); 350 release_region(WDT_PING, 1);
346 release_region(ENABLE_W83877F_PORT,2); 351 release_region(ENABLE_W83877F_PORT, 2);
347} 352}
348 353
349static int __init w83877f_wdt_init(void) 354static int __init w83877f_wdt_init(void)
350{ 355{
351 int rc = -EBUSY; 356 int rc = -EBUSY;
352 357
353 if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ 358 if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */
354 {
355 timeout = WATCHDOG_TIMEOUT; 359 timeout = WATCHDOG_TIMEOUT;
356 printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", 360 printk(KERN_INFO PFX
357 timeout); 361 "timeout value must be 1 <= x <= 3600, using %d\n",
362 timeout);
358 } 363 }
359 364
360 if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) 365 if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) {
361 {
362 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", 366 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
363 ENABLE_W83877F_PORT); 367 ENABLE_W83877F_PORT);
364 rc = -EIO; 368 rc = -EIO;
365 goto err_out; 369 goto err_out;
366 } 370 }
367 371
368 if (!request_region(WDT_PING, 1, "W8387FF WDT")) 372 if (!request_region(WDT_PING, 1, "W8387FF WDT")) {
369 {
370 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", 373 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
371 WDT_PING); 374 WDT_PING);
372 rc = -EIO; 375 rc = -EIO;
@@ -374,22 +377,22 @@ static int __init w83877f_wdt_init(void)
374 } 377 }
375 378
376 rc = register_reboot_notifier(&wdt_notifier); 379 rc = register_reboot_notifier(&wdt_notifier);
377 if (rc) 380 if (rc) {
378 { 381 printk(KERN_ERR PFX
379 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 382 "cannot register reboot notifier (err=%d)\n", rc);
380 rc);
381 goto err_out_region2; 383 goto err_out_region2;
382 } 384 }
383 385
384 rc = misc_register(&wdt_miscdev); 386 rc = misc_register(&wdt_miscdev);
385 if (rc) 387 if (rc) {
386 { 388 printk(KERN_ERR PFX
387 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 389 "cannot register miscdev on minor=%d (err=%d)\n",
388 wdt_miscdev.minor, rc); 390 wdt_miscdev.minor, rc);
389 goto err_out_reboot; 391 goto err_out_reboot;
390 } 392 }
391 393
392 printk(KERN_INFO PFX "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n", 394 printk(KERN_INFO PFX
395 "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n",
393 timeout, nowayout); 396 timeout, nowayout);
394 397
395 return 0; 398 return 0;
@@ -397,9 +400,9 @@ static int __init w83877f_wdt_init(void)
397err_out_reboot: 400err_out_reboot:
398 unregister_reboot_notifier(&wdt_notifier); 401 unregister_reboot_notifier(&wdt_notifier);
399err_out_region2: 402err_out_region2:
400 release_region(WDT_PING,1); 403 release_region(WDT_PING, 1);
401err_out_region1: 404err_out_region1:
402 release_region(ENABLE_W83877F_PORT,2); 405 release_region(ENABLE_W83877F_PORT, 2);
403err_out: 406err_out:
404 return rc; 407 return rc;
405} 408}
diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c
index b209bcd7f789..2525da5080ca 100644
--- a/drivers/watchdog/w83977f_wdt.c
+++ b/drivers/watchdog/w83977f_wdt.c
@@ -26,10 +26,10 @@
26#include <linux/watchdog.h> 26#include <linux/watchdog.h>
27#include <linux/notifier.h> 27#include <linux/notifier.h>
28#include <linux/reboot.h> 28#include <linux/reboot.h>
29#include <linux/uaccess.h>
30#include <linux/io.h>
29 31
30#include <asm/io.h>
31#include <asm/system.h> 32#include <asm/system.h>
32#include <asm/uaccess.h>
33 33
34#define WATCHDOG_VERSION "1.00" 34#define WATCHDOG_VERSION "1.00"
35#define WATCHDOG_NAME "W83977F WDT" 35#define WATCHDOG_NAME "W83977F WDT"
@@ -53,13 +53,17 @@ static char expect_close;
53static DEFINE_SPINLOCK(spinlock); 53static DEFINE_SPINLOCK(spinlock);
54 54
55module_param(timeout, int, 0); 55module_param(timeout, int, 0);
56MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); 56MODULE_PARM_DESC(timeout,
57 "Watchdog timeout in seconds (15..7635), default="
58 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
57module_param(testmode, int, 0); 59module_param(testmode, int, 0);
58MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); 60MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0");
59 61
60static int nowayout = WATCHDOG_NOWAYOUT; 62static int nowayout = WATCHDOG_NOWAYOUT;
61module_param(nowayout, int, 0); 63module_param(nowayout, int, 0);
62MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 64MODULE_PARM_DESC(nowayout,
65 "Watchdog cannot be stopped once started (default="
66 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
63 67
64/* 68/*
65 * Start the watchdog 69 * Start the watchdog
@@ -72,8 +76,8 @@ static int wdt_start(void)
72 spin_lock_irqsave(&spinlock, flags); 76 spin_lock_irqsave(&spinlock, flags);
73 77
74 /* Unlock the SuperIO chip */ 78 /* Unlock the SuperIO chip */
75 outb_p(UNLOCK_DATA,IO_INDEX_PORT); 79 outb_p(UNLOCK_DATA, IO_INDEX_PORT);
76 outb_p(UNLOCK_DATA,IO_INDEX_PORT); 80 outb_p(UNLOCK_DATA, IO_INDEX_PORT);
77 81
78 /* 82 /*
79 * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4. 83 * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
@@ -81,50 +85,49 @@ static int wdt_start(void)
81 * F3 is set to enable watchdog LED blink at timeout. 85 * F3 is set to enable watchdog LED blink at timeout.
82 * F4 is used to just clear the TIMEOUT'ed state (bit 0). 86 * F4 is used to just clear the TIMEOUT'ed state (bit 0).
83 */ 87 */
84 outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 88 outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
85 outb_p(0x08,IO_DATA_PORT); 89 outb_p(0x08, IO_DATA_PORT);
86 outb_p(0xF2,IO_INDEX_PORT); 90 outb_p(0xF2, IO_INDEX_PORT);
87 outb_p(timeoutW,IO_DATA_PORT); 91 outb_p(timeoutW, IO_DATA_PORT);
88 outb_p(0xF3,IO_INDEX_PORT); 92 outb_p(0xF3, IO_INDEX_PORT);
89 outb_p(0x08,IO_DATA_PORT); 93 outb_p(0x08, IO_DATA_PORT);
90 outb_p(0xF4,IO_INDEX_PORT); 94 outb_p(0xF4, IO_INDEX_PORT);
91 outb_p(0x00,IO_DATA_PORT); 95 outb_p(0x00, IO_DATA_PORT);
92 96
93 /* Set device Aux2 active */ 97 /* Set device Aux2 active */
94 outb_p(0x30,IO_INDEX_PORT); 98 outb_p(0x30, IO_INDEX_PORT);
95 outb_p(0x01,IO_DATA_PORT); 99 outb_p(0x01, IO_DATA_PORT);
96 100
97 /* 101 /*
98 * Select device Aux1 (dev=7) to set GP16 as the watchdog output 102 * Select device Aux1 (dev=7) to set GP16 as the watchdog output
99 * (in reg E6) and GP13 as the watchdog LED output (in reg E3). 103 * (in reg E6) and GP13 as the watchdog LED output (in reg E3).
100 * Map GP16 at pin 119. 104 * Map GP16 at pin 119.
101 * In test mode watch the bit 0 on F4 to indicate "triggered" or 105 * In test mode watch the bit 0 on F4 to indicate "triggered" or
102 * check watchdog LED on SBC. 106 * check watchdog LED on SBC.
103 */ 107 */
104 outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 108 outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
105 outb_p(0x07,IO_DATA_PORT); 109 outb_p(0x07, IO_DATA_PORT);
106 if (!testmode) 110 if (!testmode) {
107 {
108 unsigned pin_map; 111 unsigned pin_map;
109 112
110 outb_p(0xE6,IO_INDEX_PORT); 113 outb_p(0xE6, IO_INDEX_PORT);
111 outb_p(0x0A,IO_DATA_PORT); 114 outb_p(0x0A, IO_DATA_PORT);
112 outb_p(0x2C,IO_INDEX_PORT); 115 outb_p(0x2C, IO_INDEX_PORT);
113 pin_map = inb_p(IO_DATA_PORT); 116 pin_map = inb_p(IO_DATA_PORT);
114 pin_map |= 0x10; 117 pin_map |= 0x10;
115 pin_map &= ~(0x20); 118 pin_map &= ~(0x20);
116 outb_p(0x2C,IO_INDEX_PORT); 119 outb_p(0x2C, IO_INDEX_PORT);
117 outb_p(pin_map,IO_DATA_PORT); 120 outb_p(pin_map, IO_DATA_PORT);
118 } 121 }
119 outb_p(0xE3,IO_INDEX_PORT); 122 outb_p(0xE3, IO_INDEX_PORT);
120 outb_p(0x08,IO_DATA_PORT); 123 outb_p(0x08, IO_DATA_PORT);
121 124
122 /* Set device Aux1 active */ 125 /* Set device Aux1 active */
123 outb_p(0x30,IO_INDEX_PORT); 126 outb_p(0x30, IO_INDEX_PORT);
124 outb_p(0x01,IO_DATA_PORT); 127 outb_p(0x01, IO_DATA_PORT);
125 128
126 /* Lock the SuperIO chip */ 129 /* Lock the SuperIO chip */
127 outb_p(LOCK_DATA,IO_INDEX_PORT); 130 outb_p(LOCK_DATA, IO_INDEX_PORT);
128 131
129 spin_unlock_irqrestore(&spinlock, flags); 132 spin_unlock_irqrestore(&spinlock, flags);
130 133
@@ -144,42 +147,41 @@ static int wdt_stop(void)
144 spin_lock_irqsave(&spinlock, flags); 147 spin_lock_irqsave(&spinlock, flags);
145 148
146 /* Unlock the SuperIO chip */ 149 /* Unlock the SuperIO chip */
147 outb_p(UNLOCK_DATA,IO_INDEX_PORT); 150 outb_p(UNLOCK_DATA, IO_INDEX_PORT);
148 outb_p(UNLOCK_DATA,IO_INDEX_PORT); 151 outb_p(UNLOCK_DATA, IO_INDEX_PORT);
149 152
150 /* 153 /*
151 * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4. 154 * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
152 * F2 is reset to its default value (watchdog timer disabled). 155 * F2 is reset to its default value (watchdog timer disabled).
153 * F3 is reset to its default state. 156 * F3 is reset to its default state.
154 * F4 clears the TIMEOUT'ed state (bit 0) - back to default. 157 * F4 clears the TIMEOUT'ed state (bit 0) - back to default.
155 */ 158 */
156 outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 159 outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
157 outb_p(0x08,IO_DATA_PORT); 160 outb_p(0x08, IO_DATA_PORT);
158 outb_p(0xF2,IO_INDEX_PORT); 161 outb_p(0xF2, IO_INDEX_PORT);
159 outb_p(0xFF,IO_DATA_PORT); 162 outb_p(0xFF, IO_DATA_PORT);
160 outb_p(0xF3,IO_INDEX_PORT); 163 outb_p(0xF3, IO_INDEX_PORT);
161 outb_p(0x00,IO_DATA_PORT); 164 outb_p(0x00, IO_DATA_PORT);
162 outb_p(0xF4,IO_INDEX_PORT); 165 outb_p(0xF4, IO_INDEX_PORT);
163 outb_p(0x00,IO_DATA_PORT); 166 outb_p(0x00, IO_DATA_PORT);
164 outb_p(0xF2,IO_INDEX_PORT); 167 outb_p(0xF2, IO_INDEX_PORT);
165 outb_p(0x00,IO_DATA_PORT); 168 outb_p(0x00, IO_DATA_PORT);
166 169
167 /* 170 /*
168 * Select device Aux1 (dev=7) to set GP16 (in reg E6) and 171 * Select device Aux1 (dev=7) to set GP16 (in reg E6) and
169 * Gp13 (in reg E3) as inputs. 172 * Gp13 (in reg E3) as inputs.
170 */ 173 */
171 outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 174 outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
172 outb_p(0x07,IO_DATA_PORT); 175 outb_p(0x07, IO_DATA_PORT);
173 if (!testmode) 176 if (!testmode) {
174 { 177 outb_p(0xE6, IO_INDEX_PORT);
175 outb_p(0xE6,IO_INDEX_PORT); 178 outb_p(0x01, IO_DATA_PORT);
176 outb_p(0x01,IO_DATA_PORT);
177 } 179 }
178 outb_p(0xE3,IO_INDEX_PORT); 180 outb_p(0xE3, IO_INDEX_PORT);
179 outb_p(0x01,IO_DATA_PORT); 181 outb_p(0x01, IO_DATA_PORT);
180 182
181 /* Lock the SuperIO chip */ 183 /* Lock the SuperIO chip */
182 outb_p(LOCK_DATA,IO_INDEX_PORT); 184 outb_p(LOCK_DATA, IO_INDEX_PORT);
183 185
184 spin_unlock_irqrestore(&spinlock, flags); 186 spin_unlock_irqrestore(&spinlock, flags);
185 187
@@ -200,17 +202,17 @@ static int wdt_keepalive(void)
200 spin_lock_irqsave(&spinlock, flags); 202 spin_lock_irqsave(&spinlock, flags);
201 203
202 /* Unlock the SuperIO chip */ 204 /* Unlock the SuperIO chip */
203 outb_p(UNLOCK_DATA,IO_INDEX_PORT); 205 outb_p(UNLOCK_DATA, IO_INDEX_PORT);
204 outb_p(UNLOCK_DATA,IO_INDEX_PORT); 206 outb_p(UNLOCK_DATA, IO_INDEX_PORT);
205 207
206 /* Select device Aux2 (device=8) to kick watchdog reg F2 */ 208 /* Select device Aux2 (device=8) to kick watchdog reg F2 */
207 outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 209 outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
208 outb_p(0x08,IO_DATA_PORT); 210 outb_p(0x08, IO_DATA_PORT);
209 outb_p(0xF2,IO_INDEX_PORT); 211 outb_p(0xF2, IO_INDEX_PORT);
210 outb_p(timeoutW,IO_DATA_PORT); 212 outb_p(timeoutW, IO_DATA_PORT);
211 213
212 /* Lock the SuperIO chip */ 214 /* Lock the SuperIO chip */
213 outb_p(LOCK_DATA,IO_INDEX_PORT); 215 outb_p(LOCK_DATA, IO_INDEX_PORT);
214 216
215 spin_unlock_irqrestore(&spinlock, flags); 217 spin_unlock_irqrestore(&spinlock, flags);
216 218
@@ -227,7 +229,7 @@ static int wdt_set_timeout(int t)
227 229
228 /* 230 /*
229 * Convert seconds to watchdog counter time units, rounding up. 231 * Convert seconds to watchdog counter time units, rounding up.
230 * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup 232 * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup
231 * value. This information is supplied in the PCM-5335 manual and was 233 * value. This information is supplied in the PCM-5335 manual and was
232 * checked by me on a real board. This is a bit strange because W83977f 234 * checked by me on a real board. This is a bit strange because W83977f
233 * datasheet says counter unit is in minutes! 235 * datasheet says counter unit is in minutes!
@@ -241,7 +243,7 @@ static int wdt_set_timeout(int t)
241 return -EINVAL; 243 return -EINVAL;
242 244
243 /* 245 /*
244 * timeout is the timeout in seconds, 246 * timeout is the timeout in seconds,
245 * timeoutW is the timeout in watchdog counter units. 247 * timeoutW is the timeout in watchdog counter units.
246 */ 248 */
247 timeoutW = tmrval; 249 timeoutW = tmrval;
@@ -261,17 +263,17 @@ static int wdt_get_status(int *status)
261 spin_lock_irqsave(&spinlock, flags); 263 spin_lock_irqsave(&spinlock, flags);
262 264
263 /* Unlock the SuperIO chip */ 265 /* Unlock the SuperIO chip */
264 outb_p(UNLOCK_DATA,IO_INDEX_PORT); 266 outb_p(UNLOCK_DATA, IO_INDEX_PORT);
265 outb_p(UNLOCK_DATA,IO_INDEX_PORT); 267 outb_p(UNLOCK_DATA, IO_INDEX_PORT);
266 268
267 /* Select device Aux2 (device=8) to read watchdog reg F4 */ 269 /* Select device Aux2 (device=8) to read watchdog reg F4 */
268 outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 270 outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
269 outb_p(0x08,IO_DATA_PORT); 271 outb_p(0x08, IO_DATA_PORT);
270 outb_p(0xF4,IO_INDEX_PORT); 272 outb_p(0xF4, IO_INDEX_PORT);
271 new_status = inb_p(IO_DATA_PORT); 273 new_status = inb_p(IO_DATA_PORT);
272 274
273 /* Lock the SuperIO chip */ 275 /* Lock the SuperIO chip */
274 outb_p(LOCK_DATA,IO_INDEX_PORT); 276 outb_p(LOCK_DATA, IO_INDEX_PORT);
275 277
276 spin_unlock_irqrestore(&spinlock, flags); 278 spin_unlock_irqrestore(&spinlock, flags);
277 279
@@ -290,7 +292,7 @@ static int wdt_get_status(int *status)
290static int wdt_open(struct inode *inode, struct file *file) 292static int wdt_open(struct inode *inode, struct file *file)
291{ 293{
292 /* If the watchdog is alive we don't need to start it again */ 294 /* If the watchdog is alive we don't need to start it again */
293 if( test_and_set_bit(0, &timer_alive) ) 295 if (test_and_set_bit(0, &timer_alive))
294 return -EBUSY; 296 return -EBUSY;
295 297
296 if (nowayout) 298 if (nowayout)
@@ -306,13 +308,13 @@ static int wdt_release(struct inode *inode, struct file *file)
306 * Shut off the timer. 308 * Shut off the timer.
307 * Lock it in if it's a module and we set nowayout 309 * Lock it in if it's a module and we set nowayout
308 */ 310 */
309 if (expect_close == 42) 311 if (expect_close == 42) {
310 {
311 wdt_stop(); 312 wdt_stop();
312 clear_bit(0, &timer_alive); 313 clear_bit(0, &timer_alive);
313 } else { 314 } else {
314 wdt_keepalive(); 315 wdt_keepalive();
315 printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n"); 316 printk(KERN_CRIT PFX
317 "unexpected close, not stopping watchdog!\n");
316 } 318 }
317 expect_close = 0; 319 expect_close = 0;
318 return 0; 320 return 0;
@@ -333,24 +335,22 @@ static ssize_t wdt_write(struct file *file, const char __user *buf,
333 size_t count, loff_t *ppos) 335 size_t count, loff_t *ppos)
334{ 336{
335 /* See if we got the magic character 'V' and reload the timer */ 337 /* See if we got the magic character 'V' and reload the timer */
336 if(count) 338 if (count) {
337 { 339 if (!nowayout) {
338 if (!nowayout)
339 {
340 size_t ofs; 340 size_t ofs;
341 341
342 /* note: just in case someone wrote the magic character long ago */ 342 /* note: just in case someone wrote the
343 magic character long ago */
343 expect_close = 0; 344 expect_close = 0;
344 345
345 /* scan to see whether or not we got the magic character */ 346 /* scan to see whether or not we got the
346 for(ofs = 0; ofs != count; ofs++) 347 magic character */
347 { 348 for (ofs = 0; ofs != count; ofs++) {
348 char c; 349 char c;
349 if (get_user(c, buf + ofs)) 350 if (get_user(c, buf + ofs))
350 return -EFAULT; 351 return -EFAULT;
351 if (c == 'V') { 352 if (c == 'V')
352 expect_close = 42; 353 expect_close = 42;
353 }
354 } 354 }
355 } 355 }
356 356
@@ -377,8 +377,7 @@ static struct watchdog_info ident = {
377 .identity = WATCHDOG_NAME, 377 .identity = WATCHDOG_NAME,
378}; 378};
379 379
380static int wdt_ioctl(struct inode *inode, struct file *file, 380static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
381 unsigned int cmd, unsigned long arg)
382{ 381{
383 int status; 382 int status;
384 int new_options, retval = -EINVAL; 383 int new_options, retval = -EINVAL;
@@ -390,13 +389,10 @@ static int wdt_ioctl(struct inode *inode, struct file *file,
390 389
391 uarg.i = (int __user *)arg; 390 uarg.i = (int __user *)arg;
392 391
393 switch(cmd) 392 switch (cmd) {
394 {
395 default:
396 return -ENOTTY;
397
398 case WDIOC_GETSUPPORT: 393 case WDIOC_GETSUPPORT:
399 return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0; 394 return copy_to_user(uarg.ident, &ident,
395 sizeof(ident)) ? -EFAULT : 0;
400 396
401 case WDIOC_GETSTATUS: 397 case WDIOC_GETSTATUS:
402 wdt_get_status(&status); 398 wdt_get_status(&status);
@@ -405,12 +401,8 @@ static int wdt_ioctl(struct inode *inode, struct file *file,
405 case WDIOC_GETBOOTSTATUS: 401 case WDIOC_GETBOOTSTATUS:
406 return put_user(0, uarg.i); 402 return put_user(0, uarg.i);
407 403
408 case WDIOC_KEEPALIVE:
409 wdt_keepalive();
410 return 0;
411
412 case WDIOC_SETOPTIONS: 404 case WDIOC_SETOPTIONS:
413 if (get_user (new_options, uarg.i)) 405 if (get_user(new_options, uarg.i))
414 return -EFAULT; 406 return -EFAULT;
415 407
416 if (new_options & WDIOS_DISABLECARD) { 408 if (new_options & WDIOS_DISABLECARD) {
@@ -425,6 +417,10 @@ static int wdt_ioctl(struct inode *inode, struct file *file,
425 417
426 return retval; 418 return retval;
427 419
420 case WDIOC_KEEPALIVE:
421 wdt_keepalive();
422 return 0;
423
428 case WDIOC_SETTIMEOUT: 424 case WDIOC_SETTIMEOUT:
429 if (get_user(new_timeout, uarg.i)) 425 if (get_user(new_timeout, uarg.i))
430 return -EFAULT; 426 return -EFAULT;
@@ -438,29 +434,30 @@ static int wdt_ioctl(struct inode *inode, struct file *file,
438 case WDIOC_GETTIMEOUT: 434 case WDIOC_GETTIMEOUT:
439 return put_user(timeout, uarg.i); 435 return put_user(timeout, uarg.i);
440 436
437 default:
438 return -ENOTTY;
439
441 } 440 }
442} 441}
443 442
444static int wdt_notify_sys(struct notifier_block *this, unsigned long code, 443static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
445 void *unused) 444 void *unused)
446{ 445{
447 if (code==SYS_DOWN || code==SYS_HALT) 446 if (code == SYS_DOWN || code == SYS_HALT)
448 wdt_stop(); 447 wdt_stop();
449 return NOTIFY_DONE; 448 return NOTIFY_DONE;
450} 449}
451 450
452static const struct file_operations wdt_fops= 451static const struct file_operations wdt_fops = {
453{
454 .owner = THIS_MODULE, 452 .owner = THIS_MODULE,
455 .llseek = no_llseek, 453 .llseek = no_llseek,
456 .write = wdt_write, 454 .write = wdt_write,
457 .ioctl = wdt_ioctl, 455 .unlocked_ioctl = wdt_ioctl,
458 .open = wdt_open, 456 .open = wdt_open,
459 .release = wdt_release, 457 .release = wdt_release,
460}; 458};
461 459
462static struct miscdevice wdt_miscdev= 460static struct miscdevice wdt_miscdev = {
463{
464 .minor = WATCHDOG_MINOR, 461 .minor = WATCHDOG_MINOR,
465 .name = "watchdog", 462 .name = "watchdog",
466 .fops = &wdt_fops, 463 .fops = &wdt_fops,
@@ -474,20 +471,20 @@ static int __init w83977f_wdt_init(void)
474{ 471{
475 int rc; 472 int rc;
476 473
477 printk(KERN_INFO PFX DRIVER_VERSION); 474 printk(KERN_INFO PFX DRIVER_VERSION);
478 475
479 /* 476 /*
480 * Check that the timeout value is within it's range ; 477 * Check that the timeout value is within it's range;
481 * if not reset to the default 478 * if not reset to the default
482 */ 479 */
483 if (wdt_set_timeout(timeout)) { 480 if (wdt_set_timeout(timeout)) {
484 wdt_set_timeout(DEFAULT_TIMEOUT); 481 wdt_set_timeout(DEFAULT_TIMEOUT);
485 printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n", 482 printk(KERN_INFO PFX
486 DEFAULT_TIMEOUT); 483 "timeout value must be 15 <= timeout <= 7635, using %d\n",
484 DEFAULT_TIMEOUT);
487 } 485 }
488 486
489 if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) 487 if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) {
490 {
491 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", 488 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
492 IO_INDEX_PORT); 489 IO_INDEX_PORT);
493 rc = -EIO; 490 rc = -EIO;
@@ -495,30 +492,30 @@ static int __init w83977f_wdt_init(void)
495 } 492 }
496 493
497 rc = register_reboot_notifier(&wdt_notifier); 494 rc = register_reboot_notifier(&wdt_notifier);
498 if (rc) 495 if (rc) {
499 { 496 printk(KERN_ERR PFX
500 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 497 "cannot register reboot notifier (err=%d)\n", rc);
501 rc);
502 goto err_out_region; 498 goto err_out_region;
503 } 499 }
504 500
505 rc = misc_register(&wdt_miscdev); 501 rc = misc_register(&wdt_miscdev);
506 if (rc) 502 if (rc) {
507 { 503 printk(KERN_ERR PFX
508 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 504 "cannot register miscdev on minor=%d (err=%d)\n",
509 wdt_miscdev.minor, rc); 505 wdt_miscdev.minor, rc);
510 goto err_out_reboot; 506 goto err_out_reboot;
511 } 507 }
512 508
513 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n", 509 printk(KERN_INFO PFX
514 timeout, nowayout, testmode); 510 "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
511 timeout, nowayout, testmode);
515 512
516 return 0; 513 return 0;
517 514
518err_out_reboot: 515err_out_reboot:
519 unregister_reboot_notifier(&wdt_notifier); 516 unregister_reboot_notifier(&wdt_notifier);
520err_out_region: 517err_out_region:
521 release_region(IO_INDEX_PORT,2); 518 release_region(IO_INDEX_PORT, 2);
522err_out: 519err_out:
523 return rc; 520 return rc;
524} 521}
@@ -528,7 +525,7 @@ static void __exit w83977f_wdt_exit(void)
528 wdt_stop(); 525 wdt_stop();
529 misc_deregister(&wdt_miscdev); 526 misc_deregister(&wdt_miscdev);
530 unregister_reboot_notifier(&wdt_notifier); 527 unregister_reboot_notifier(&wdt_notifier);
531 release_region(IO_INDEX_PORT,2); 528 release_region(IO_INDEX_PORT, 2);
532} 529}
533 530
534module_init(w83977f_wdt_init); 531module_init(w83977f_wdt_init);
diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c
index 9e368091f799..68377ae171ff 100644
--- a/drivers/watchdog/wafer5823wdt.c
+++ b/drivers/watchdog/wafer5823wdt.c
@@ -1,11 +1,11 @@
1/* 1/*
2 * ICP Wafer 5823 Single Board Computer WDT driver 2 * ICP Wafer 5823 Single Board Computer WDT driver
3 * http://www.icpamerica.com/wafer_5823.php 3 * http://www.icpamerica.com/wafer_5823.php
4 * May also work on other similar models 4 * May also work on other similar models
5 * 5 *
6 * (c) Copyright 2002 Justin Cormack <justin@street-vision.com> 6 * (c) Copyright 2002 Justin Cormack <justin@street-vision.com>
7 * 7 *
8 * Release 0.02 8 * Release 0.02
9 * 9 *
10 * Based on advantechwdt.c which is based on wdt.c. 10 * Based on advantechwdt.c which is based on wdt.c.
11 * Original copyright messages: 11 * Original copyright messages:
@@ -36,8 +36,8 @@
36#include <linux/reboot.h> 36#include <linux/reboot.h>
37#include <linux/init.h> 37#include <linux/init.h>
38#include <linux/spinlock.h> 38#include <linux/spinlock.h>
39#include <asm/io.h> 39#include <linux/io.h>
40#include <asm/uaccess.h> 40#include <linux/uaccess.h>
41 41
42#define WATCHDOG_NAME "Wafer 5823 WDT" 42#define WATCHDOG_NAME "Wafer 5823 WDT"
43#define PFX WATCHDOG_NAME ": " 43#define PFX WATCHDOG_NAME ": "
@@ -50,10 +50,10 @@ static DEFINE_SPINLOCK(wafwdt_lock);
50/* 50/*
51 * You must set these - there is no sane way to probe for this board. 51 * You must set these - there is no sane way to probe for this board.
52 * 52 *
53 * To enable, write the timeout value in seconds (1 to 255) to I/O 53 * To enable, write the timeout value in seconds (1 to 255) to I/O
54 * port WDT_START, then read the port to start the watchdog. To pat 54 * port WDT_START, then read the port to start the watchdog. To pat
55 * the dog, read port WDT_STOP to stop the timer, then read WDT_START 55 * the dog, read port WDT_STOP to stop the timer, then read WDT_START
56 * to restart it again. 56 * to restart it again.
57 */ 57 */
58 58
59static int wdt_stop = 0x843; 59static int wdt_stop = 0x843;
@@ -61,11 +61,15 @@ static int wdt_start = 0x443;
61 61
62static int timeout = WD_TIMO; /* in seconds */ 62static int timeout = WD_TIMO; /* in seconds */
63module_param(timeout, int, 0); 63module_param(timeout, int, 0);
64MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WD_TIMO) "."); 64MODULE_PARM_DESC(timeout,
65 "Watchdog timeout in seconds. 1 <= timeout <= 255, default="
66 __MODULE_STRING(WD_TIMO) ".");
65 67
66static int nowayout = WATCHDOG_NOWAYOUT; 68static int nowayout = WATCHDOG_NOWAYOUT;
67module_param(nowayout, int, 0); 69module_param(nowayout, int, 0);
68MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 70MODULE_PARM_DESC(nowayout,
71 "Watchdog cannot be stopped once started (default="
72 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
69 73
70static void wafwdt_ping(void) 74static void wafwdt_ping(void)
71{ 75{
@@ -83,14 +87,14 @@ static void wafwdt_start(void)
83 inb_p(wdt_start); 87 inb_p(wdt_start);
84} 88}
85 89
86static void 90static void wafwdt_stop(void)
87wafwdt_stop(void)
88{ 91{
89 /* stop watchdog */ 92 /* stop watchdog */
90 inb_p(wdt_stop); 93 inb_p(wdt_stop);
91} 94}
92 95
93static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) 96static ssize_t wafwdt_write(struct file *file, const char __user *buf,
97 size_t count, loff_t *ppos)
94{ 98{
95 /* See if we got the magic character 'V' and reload the timer */ 99 /* See if we got the magic character 'V' and reload the timer */
96 if (count) { 100 if (count) {
@@ -100,7 +104,8 @@ static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t co
100 /* In case it was set long ago */ 104 /* In case it was set long ago */
101 expect_close = 0; 105 expect_close = 0;
102 106
103 /* scan to see whether or not we got the magic character */ 107 /* scan to see whether or not we got the magic
108 character */
104 for (i = 0; i != count; i++) { 109 for (i = 0; i != count; i++) {
105 char c; 110 char c;
106 if (get_user(c, buf + i)) 111 if (get_user(c, buf + i))
@@ -109,27 +114,29 @@ static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t co
109 expect_close = 42; 114 expect_close = 42;
110 } 115 }
111 } 116 }
112 /* Well, anyhow someone wrote to us, we should return that favour */ 117 /* Well, anyhow someone wrote to us, we should
118 return that favour */
113 wafwdt_ping(); 119 wafwdt_ping();
114 } 120 }
115 return count; 121 return count;
116} 122}
117 123
118static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 124static long wafwdt_ioctl(struct file *file, unsigned int cmd,
119 unsigned long arg) 125 unsigned long arg)
120{ 126{
121 int new_timeout; 127 int new_timeout;
122 void __user *argp = (void __user *)arg; 128 void __user *argp = (void __user *)arg;
123 int __user *p = argp; 129 int __user *p = argp;
124 static struct watchdog_info ident = { 130 static const struct watchdog_info ident = {
125 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 131 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
132 WDIOF_MAGICCLOSE,
126 .firmware_version = 1, 133 .firmware_version = 1,
127 .identity = "Wafer 5823 WDT", 134 .identity = "Wafer 5823 WDT",
128 }; 135 };
129 136
130 switch (cmd) { 137 switch (cmd) {
131 case WDIOC_GETSUPPORT: 138 case WDIOC_GETSUPPORT:
132 if (copy_to_user(argp, &ident, sizeof (ident))) 139 if (copy_to_user(argp, &ident, sizeof(ident)))
133 return -EFAULT; 140 return -EFAULT;
134 break; 141 break;
135 142
@@ -137,22 +144,6 @@ static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd
137 case WDIOC_GETBOOTSTATUS: 144 case WDIOC_GETBOOTSTATUS:
138 return put_user(0, p); 145 return put_user(0, p);
139 146
140 case WDIOC_KEEPALIVE:
141 wafwdt_ping();
142 break;
143
144 case WDIOC_SETTIMEOUT:
145 if (get_user(new_timeout, p))
146 return -EFAULT;
147 if ((new_timeout < 1) || (new_timeout > 255))
148 return -EINVAL;
149 timeout = new_timeout;
150 wafwdt_stop();
151 wafwdt_start();
152 /* Fall */
153 case WDIOC_GETTIMEOUT:
154 return put_user(timeout, p);
155
156 case WDIOC_SETOPTIONS: 147 case WDIOC_SETOPTIONS:
157 { 148 {
158 int options, retval = -EINVAL; 149 int options, retval = -EINVAL;
@@ -173,6 +164,22 @@ static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd
173 return retval; 164 return retval;
174 } 165 }
175 166
167 case WDIOC_KEEPALIVE:
168 wafwdt_ping();
169 break;
170
171 case WDIOC_SETTIMEOUT:
172 if (get_user(new_timeout, p))
173 return -EFAULT;
174 if ((new_timeout < 1) || (new_timeout > 255))
175 return -EINVAL;
176 timeout = new_timeout;
177 wafwdt_stop();
178 wafwdt_start();
179 /* Fall */
180 case WDIOC_GETTIMEOUT:
181 return put_user(timeout, p);
182
176 default: 183 default:
177 return -ENOTTY; 184 return -ENOTTY;
178 } 185 }
@@ -191,13 +198,13 @@ static int wafwdt_open(struct inode *inode, struct file *file)
191 return nonseekable_open(inode, file); 198 return nonseekable_open(inode, file);
192} 199}
193 200
194static int 201static int wafwdt_close(struct inode *inode, struct file *file)
195wafwdt_close(struct inode *inode, struct file *file)
196{ 202{
197 if (expect_close == 42) { 203 if (expect_close == 42)
198 wafwdt_stop(); 204 wafwdt_stop();
199 } else { 205 else {
200 printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); 206 printk(KERN_CRIT PFX
207 "WDT device closed unexpectedly. WDT will not stop!\n");
201 wafwdt_ping(); 208 wafwdt_ping();
202 } 209 }
203 clear_bit(0, &wafwdt_is_open); 210 clear_bit(0, &wafwdt_is_open);
@@ -209,12 +216,11 @@ wafwdt_close(struct inode *inode, struct file *file)
209 * Notifier for system down 216 * Notifier for system down
210 */ 217 */
211 218
212static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) 219static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code,
220 void *unused)
213{ 221{
214 if (code == SYS_DOWN || code == SYS_HALT) { 222 if (code == SYS_DOWN || code == SYS_HALT)
215 /* Turn the WDT off */
216 wafwdt_stop(); 223 wafwdt_stop();
217 }
218 return NOTIFY_DONE; 224 return NOTIFY_DONE;
219} 225}
220 226
@@ -226,7 +232,7 @@ static const struct file_operations wafwdt_fops = {
226 .owner = THIS_MODULE, 232 .owner = THIS_MODULE,
227 .llseek = no_llseek, 233 .llseek = no_llseek,
228 .write = wafwdt_write, 234 .write = wafwdt_write,
229 .ioctl = wafwdt_ioctl, 235 .unlocked_ioctl = wafwdt_ioctl,
230 .open = wafwdt_open, 236 .open = wafwdt_open,
231 .release = wafwdt_close, 237 .release = wafwdt_close,
232}; 238};
@@ -250,25 +256,28 @@ static int __init wafwdt_init(void)
250{ 256{
251 int ret; 257 int ret;
252 258
253 printk(KERN_INFO "WDT driver for Wafer 5823 single board computer initialising.\n"); 259 printk(KERN_INFO
260 "WDT driver for Wafer 5823 single board computer initialising.\n");
254 261
255 if (timeout < 1 || timeout > 255) { 262 if (timeout < 1 || timeout > 255) {
256 timeout = WD_TIMO; 263 timeout = WD_TIMO;
257 printk (KERN_INFO PFX "timeout value must be 1<=x<=255, using %d\n", 264 printk(KERN_INFO PFX
258 timeout); 265 "timeout value must be 1 <= x <= 255, using %d\n",
266 timeout);
259 } 267 }
260 268
261 if (wdt_stop != wdt_start) { 269 if (wdt_stop != wdt_start) {
262 if(!request_region(wdt_stop, 1, "Wafer 5823 WDT")) { 270 if (!request_region(wdt_stop, 1, "Wafer 5823 WDT")) {
263 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", 271 printk(KERN_ERR PFX
264 wdt_stop); 272 "I/O address 0x%04x already in use\n",
273 wdt_stop);
265 ret = -EIO; 274 ret = -EIO;
266 goto error; 275 goto error;
267 } 276 }
268 } 277 }
269 278
270 if(!request_region(wdt_start, 1, "Wafer 5823 WDT")) { 279 if (!request_region(wdt_start, 1, "Wafer 5823 WDT")) {
271 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", 280 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
272 wdt_start); 281 wdt_start);
273 ret = -EIO; 282 ret = -EIO;
274 goto error2; 283 goto error2;
@@ -276,19 +285,20 @@ static int __init wafwdt_init(void)
276 285
277 ret = register_reboot_notifier(&wafwdt_notifier); 286 ret = register_reboot_notifier(&wafwdt_notifier);
278 if (ret != 0) { 287 if (ret != 0) {
279 printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 288 printk(KERN_ERR PFX
280 ret); 289 "cannot register reboot notifier (err=%d)\n", ret);
281 goto error3; 290 goto error3;
282 } 291 }
283 292
284 ret = misc_register(&wafwdt_miscdev); 293 ret = misc_register(&wafwdt_miscdev);
285 if (ret != 0) { 294 if (ret != 0) {
286 printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 295 printk(KERN_ERR PFX
287 WATCHDOG_MINOR, ret); 296 "cannot register miscdev on minor=%d (err=%d)\n",
297 WATCHDOG_MINOR, ret);
288 goto error4; 298 goto error4;
289 } 299 }
290 300
291 printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", 301 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
292 timeout, nowayout); 302 timeout, nowayout);
293 303
294 return ret; 304 return ret;
@@ -307,7 +317,7 @@ static void __exit wafwdt_exit(void)
307{ 317{
308 misc_deregister(&wafwdt_miscdev); 318 misc_deregister(&wafwdt_miscdev);
309 unregister_reboot_notifier(&wafwdt_notifier); 319 unregister_reboot_notifier(&wafwdt_notifier);
310 if(wdt_stop != wdt_start) 320 if (wdt_stop != wdt_start)
311 release_region(wdt_stop, 1); 321 release_region(wdt_stop, 1);
312 release_region(wdt_start, 1); 322 release_region(wdt_start, 1);
313} 323}
diff --git a/drivers/watchdog/wd501p.h b/drivers/watchdog/wd501p.h
index a4504f40394d..db34853c28ae 100644
--- a/drivers/watchdog/wd501p.h
+++ b/drivers/watchdog/wd501p.h
@@ -12,7 +12,7 @@
12 * http://www.cymru.net 12 * http://www.cymru.net
13 * 13 *
14 * This driver is provided under the GNU General Public License, incorporated 14 * This driver is provided under the GNU General Public License, incorporated
15 * herein by reference. The driver is provided without warranty or 15 * herein by reference. The driver is provided without warranty or
16 * support. 16 * support.
17 * 17 *
18 * Release 0.04. 18 * Release 0.04.
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c
index 1d64e277567d..5d3b1a8e28b0 100644
--- a/drivers/watchdog/wdrtas.c
+++ b/drivers/watchdog/wdrtas.c
@@ -35,9 +35,9 @@
35#include <linux/reboot.h> 35#include <linux/reboot.h>
36#include <linux/types.h> 36#include <linux/types.h>
37#include <linux/watchdog.h> 37#include <linux/watchdog.h>
38#include <linux/uaccess.h>
38 39
39#include <asm/rtas.h> 40#include <asm/rtas.h>
40#include <asm/uaccess.h>
41 41
42#define WDRTAS_MAGIC_CHAR 42 42#define WDRTAS_MAGIC_CHAR 42
43#define WDRTAS_SUPPORTED_MASK (WDIOF_SETTIMEOUT | \ 43#define WDRTAS_SUPPORTED_MASK (WDIOF_SETTIMEOUT | \
@@ -56,7 +56,7 @@ static int wdrtas_nowayout = 0;
56#endif 56#endif
57 57
58static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0); 58static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
59static char wdrtas_expect_close = 0; 59static char wdrtas_expect_close;
60 60
61static int wdrtas_interval; 61static int wdrtas_interval;
62 62
@@ -86,8 +86,8 @@ static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];
86 * RTAS function set-indicator (surveillance). The unit of interval is 86 * RTAS function set-indicator (surveillance). The unit of interval is
87 * seconds. 87 * seconds.
88 */ 88 */
89static int 89
90wdrtas_set_interval(int interval) 90static int wdrtas_set_interval(int interval)
91{ 91{
92 long result; 92 long result;
93 static int print_msg = 10; 93 static int print_msg = 10;
@@ -97,7 +97,7 @@ wdrtas_set_interval(int interval)
97 97
98 result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL, 98 result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
99 WDRTAS_SURVEILLANCE_IND, 0, interval); 99 WDRTAS_SURVEILLANCE_IND, 0, interval);
100 if ( (result < 0) && (print_msg) ) { 100 if (result < 0 && print_msg) {
101 printk(KERN_ERR "wdrtas: setting the watchdog to %i " 101 printk(KERN_ERR "wdrtas: setting the watchdog to %i "
102 "timeout failed: %li\n", interval, result); 102 "timeout failed: %li\n", interval, result);
103 print_msg--; 103 print_msg--;
@@ -116,16 +116,14 @@ wdrtas_set_interval(int interval)
116 * as reported by the RTAS function ibm,get-system-parameter. The unit 116 * as reported by the RTAS function ibm,get-system-parameter. The unit
117 * of the return value is seconds. 117 * of the return value is seconds.
118 */ 118 */
119static int 119static int wdrtas_get_interval(int fallback_value)
120wdrtas_get_interval(int fallback_value)
121{ 120{
122 long result; 121 long result;
123 char value[4]; 122 char value[4];
124 123
125 result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL, 124 result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,
126 WDRTAS_SP_SPI, (void *)__pa(&value), 4); 125 WDRTAS_SP_SPI, (void *)__pa(&value), 4);
127 if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) || 126 if (value[0] != 0 || value[1] != 2 || value[3] != 0 || result < 0) {
128 (result < 0) ) {
129 printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog " 127 printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "
130 "timeout (%li). Continuing\n", result); 128 "timeout (%li). Continuing\n", result);
131 return fallback_value; 129 return fallback_value;
@@ -141,8 +139,7 @@ wdrtas_get_interval(int fallback_value)
141 * wdrtas_timer_start starts the watchdog by calling the RTAS function 139 * wdrtas_timer_start starts the watchdog by calling the RTAS function
142 * set-interval (surveillance) 140 * set-interval (surveillance)
143 */ 141 */
144static void 142static void wdrtas_timer_start(void)
145wdrtas_timer_start(void)
146{ 143{
147 wdrtas_set_interval(wdrtas_interval); 144 wdrtas_set_interval(wdrtas_interval);
148} 145}
@@ -153,8 +150,7 @@ wdrtas_timer_start(void)
153 * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function 150 * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function
154 * set-interval (surveillance) 151 * set-interval (surveillance)
155 */ 152 */
156static void 153static void wdrtas_timer_stop(void)
157wdrtas_timer_stop(void)
158{ 154{
159 wdrtas_set_interval(0); 155 wdrtas_set_interval(0);
160} 156}
@@ -165,8 +161,7 @@ wdrtas_timer_stop(void)
165 * wdrtas_log_scanned_event prints a message to the log buffer dumping 161 * wdrtas_log_scanned_event prints a message to the log buffer dumping
166 * the results of the last event-scan call 162 * the results of the last event-scan call
167 */ 163 */
168static void 164static void wdrtas_log_scanned_event(void)
169wdrtas_log_scanned_event(void)
170{ 165{
171 int i; 166 int i;
172 167
@@ -175,13 +170,13 @@ wdrtas_log_scanned_event(void)
175 "%02x %02x %02x %02x %02x %02x %02x %02x " 170 "%02x %02x %02x %02x %02x %02x %02x %02x "
176 "%02x %02x %02x %02x %02x %02x %02x %02x\n", 171 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
177 (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16), 172 (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
178 wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1], 173 wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1],
179 wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3], 174 wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3],
180 wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5], 175 wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5],
181 wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7], 176 wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7],
182 wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9], 177 wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9],
183 wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11], 178 wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11],
184 wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13], 179 wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13],
185 wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]); 180 wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
186} 181}
187 182
@@ -192,8 +187,7 @@ wdrtas_log_scanned_event(void)
192 * RTAS function event-scan and repeats these calls as long as there are 187 * RTAS function event-scan and repeats these calls as long as there are
193 * events available. All events will be dumped. 188 * events available. All events will be dumped.
194 */ 189 */
195static void 190static void wdrtas_timer_keepalive(void)
196wdrtas_timer_keepalive(void)
197{ 191{
198 long result; 192 long result;
199 193
@@ -218,8 +212,7 @@ wdrtas_timer_keepalive(void)
218 * wdrtas_get_temperature returns the current temperature in Fahrenheit. It 212 * wdrtas_get_temperature returns the current temperature in Fahrenheit. It
219 * uses the RTAS call get-sensor-state, token 3 to do so 213 * uses the RTAS call get-sensor-state, token 3 to do so
220 */ 214 */
221static int 215static int wdrtas_get_temperature(void)
222wdrtas_get_temperature(void)
223{ 216{
224 long result; 217 long result;
225 int temperature = 0; 218 int temperature = 0;
@@ -243,8 +236,7 @@ wdrtas_get_temperature(void)
243 * returns a bitmask of defines WDIOF_... as defined in 236 * returns a bitmask of defines WDIOF_... as defined in
244 * include/linux/watchdog.h 237 * include/linux/watchdog.h
245 */ 238 */
246static int 239static int wdrtas_get_status(void)
247wdrtas_get_status(void)
248{ 240{
249 return 0; /* TODO */ 241 return 0; /* TODO */
250} 242}
@@ -255,8 +247,7 @@ wdrtas_get_status(void)
255 * returns a bitmask of defines WDIOF_... as defined in 247 * returns a bitmask of defines WDIOF_... as defined in
256 * include/linux/watchdog.h, indicating why the watchdog rebooted the system 248 * include/linux/watchdog.h, indicating why the watchdog rebooted the system
257 */ 249 */
258static int 250static int wdrtas_get_boot_status(void)
259wdrtas_get_boot_status(void)
260{ 251{
261 return 0; /* TODO */ 252 return 0; /* TODO */
262} 253}
@@ -276,8 +267,7 @@ wdrtas_get_boot_status(void)
276 * character 'V'. This character allows the watchdog device to be closed 267 * character 'V'. This character allows the watchdog device to be closed
277 * properly. 268 * properly.
278 */ 269 */
279static ssize_t 270static ssize_t wdrtas_write(struct file *file, const char __user *buf,
280wdrtas_write(struct file *file, const char __user *buf,
281 size_t len, loff_t *ppos) 271 size_t len, loff_t *ppos)
282{ 272{
283 int i; 273 int i;
@@ -306,7 +296,6 @@ out:
306 296
307/** 297/**
308 * wdrtas_ioctl - ioctl function for the watchdog device 298 * wdrtas_ioctl - ioctl function for the watchdog device
309 * @inode: inode structure
310 * @file: file structure 299 * @file: file structure
311 * @cmd: command for ioctl 300 * @cmd: command for ioctl
312 * @arg: argument pointer 301 * @arg: argument pointer
@@ -315,16 +304,16 @@ out:
315 * 304 *
316 * wdrtas_ioctl implements the watchdog API ioctls 305 * wdrtas_ioctl implements the watchdog API ioctls
317 */ 306 */
318static int 307
319wdrtas_ioctl(struct inode *inode, struct file *file, 308static long wdrtas_ioctl(struct file *file, unsigned int cmd,
320 unsigned int cmd, unsigned long arg) 309 unsigned long arg)
321{ 310{
322 int __user *argp = (void __user *)arg; 311 int __user *argp = (void __user *)arg;
323 int i; 312 int i;
324 static struct watchdog_info wdinfo = { 313 static struct watchdog_info wdinfo = {
325 .options = WDRTAS_SUPPORTED_MASK, 314 .options = WDRTAS_SUPPORTED_MASK,
326 .firmware_version = 0, 315 .firmware_version = 0,
327 .identity = "wdrtas" 316 .identity = "wdrtas",
328 }; 317 };
329 318
330 switch (cmd) { 319 switch (cmd) {
@@ -357,9 +346,9 @@ wdrtas_ioctl(struct inode *inode, struct file *file,
357 wdrtas_timer_keepalive(); 346 wdrtas_timer_keepalive();
358 wdrtas_timer_start(); 347 wdrtas_timer_start();
359 } 348 }
349 /* not implemented. Done by H8
360 if (i & WDIOS_TEMPPANIC) { 350 if (i & WDIOS_TEMPPANIC) {
361 /* not implemented. Done by H8 */ 351 } */
362 }
363 return 0; 352 return 0;
364 353
365 case WDIOC_KEEPALIVE: 354 case WDIOC_KEEPALIVE:
@@ -399,8 +388,7 @@ wdrtas_ioctl(struct inode *inode, struct file *file,
399 * 388 *
400 * function called when watchdog device is opened 389 * function called when watchdog device is opened
401 */ 390 */
402static int 391static int wdrtas_open(struct inode *inode, struct file *file)
403wdrtas_open(struct inode *inode, struct file *file)
404{ 392{
405 /* only open once */ 393 /* only open once */
406 if (atomic_inc_return(&wdrtas_miscdev_open) > 1) { 394 if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {
@@ -423,8 +411,7 @@ wdrtas_open(struct inode *inode, struct file *file)
423 * 411 *
424 * close function. Always succeeds 412 * close function. Always succeeds
425 */ 413 */
426static int 414static int wdrtas_close(struct inode *inode, struct file *file)
427wdrtas_close(struct inode *inode, struct file *file)
428{ 415{
429 /* only stop watchdog, if this was announced using 'V' before */ 416 /* only stop watchdog, if this was announced using 'V' before */
430 if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR) 417 if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
@@ -453,8 +440,7 @@ wdrtas_close(struct inode *inode, struct file *file)
453 * wdrtas_temp_read gives the temperature to the users by copying this 440 * wdrtas_temp_read gives the temperature to the users by copying this
454 * value as one byte into the user space buffer. The unit is Fahrenheit... 441 * value as one byte into the user space buffer. The unit is Fahrenheit...
455 */ 442 */
456static ssize_t 443static ssize_t wdrtas_temp_read(struct file *file, char __user *buf,
457wdrtas_temp_read(struct file *file, char __user *buf,
458 size_t count, loff_t *ppos) 444 size_t count, loff_t *ppos)
459{ 445{
460 int temperature = 0; 446 int temperature = 0;
@@ -478,8 +464,7 @@ wdrtas_temp_read(struct file *file, char __user *buf,
478 * 464 *
479 * function called when temperature device is opened 465 * function called when temperature device is opened
480 */ 466 */
481static int 467static int wdrtas_temp_open(struct inode *inode, struct file *file)
482wdrtas_temp_open(struct inode *inode, struct file *file)
483{ 468{
484 return nonseekable_open(inode, file); 469 return nonseekable_open(inode, file);
485} 470}
@@ -493,8 +478,7 @@ wdrtas_temp_open(struct inode *inode, struct file *file)
493 * 478 *
494 * close function. Always succeeds 479 * close function. Always succeeds
495 */ 480 */
496static int 481static int wdrtas_temp_close(struct inode *inode, struct file *file)
497wdrtas_temp_close(struct inode *inode, struct file *file)
498{ 482{
499 return 0; 483 return 0;
500} 484}
@@ -509,10 +493,10 @@ wdrtas_temp_close(struct inode *inode, struct file *file)
509 * 493 *
510 * wdrtas_reboot stops the watchdog in case of a reboot 494 * wdrtas_reboot stops the watchdog in case of a reboot
511 */ 495 */
512static int 496static int wdrtas_reboot(struct notifier_block *this,
513wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr) 497 unsigned long code, void *ptr)
514{ 498{
515 if ( (code==SYS_DOWN) || (code==SYS_HALT) ) 499 if (code == SYS_DOWN || code == SYS_HALT)
516 wdrtas_timer_stop(); 500 wdrtas_timer_stop();
517 501
518 return NOTIFY_DONE; 502 return NOTIFY_DONE;
@@ -524,7 +508,7 @@ static const struct file_operations wdrtas_fops = {
524 .owner = THIS_MODULE, 508 .owner = THIS_MODULE,
525 .llseek = no_llseek, 509 .llseek = no_llseek,
526 .write = wdrtas_write, 510 .write = wdrtas_write,
527 .ioctl = wdrtas_ioctl, 511 .unlocked_ioctl = wdrtas_ioctl,
528 .open = wdrtas_open, 512 .open = wdrtas_open,
529 .release = wdrtas_close, 513 .release = wdrtas_close,
530}; 514};
@@ -562,8 +546,7 @@ static struct notifier_block wdrtas_notifier = {
562 * this watchdog driver. It tolerates, if "get-sensor-state" and 546 * this watchdog driver. It tolerates, if "get-sensor-state" and
563 * "ibm,get-system-parameter" are not available. 547 * "ibm,get-system-parameter" are not available.
564 */ 548 */
565static int 549static int wdrtas_get_tokens(void)
566wdrtas_get_tokens(void)
567{ 550{
568 wdrtas_token_get_sensor_state = rtas_token("get-sensor-state"); 551 wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
569 if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) { 552 if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
@@ -603,8 +586,7 @@ wdrtas_get_tokens(void)
603 * wdrtas_register_devs unregisters the watchdog and temperature watchdog 586 * wdrtas_register_devs unregisters the watchdog and temperature watchdog
604 * misc devs 587 * misc devs
605 */ 588 */
606static void 589static void wdrtas_unregister_devs(void)
607wdrtas_unregister_devs(void)
608{ 590{
609 misc_deregister(&wdrtas_miscdev); 591 misc_deregister(&wdrtas_miscdev);
610 if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) 592 if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)
@@ -619,8 +601,7 @@ wdrtas_unregister_devs(void)
619 * wdrtas_register_devs registers the watchdog and temperature watchdog 601 * wdrtas_register_devs registers the watchdog and temperature watchdog
620 * misc devs 602 * misc devs
621 */ 603 */
622static int 604static int wdrtas_register_devs(void)
623wdrtas_register_devs(void)
624{ 605{
625 int result; 606 int result;
626 607
@@ -651,8 +632,7 @@ wdrtas_register_devs(void)
651 * 632 *
652 * registers the file handlers and the reboot notifier 633 * registers the file handlers and the reboot notifier
653 */ 634 */
654static int __init 635static int __init wdrtas_init(void)
655wdrtas_init(void)
656{ 636{
657 if (wdrtas_get_tokens()) 637 if (wdrtas_get_tokens())
658 return -ENODEV; 638 return -ENODEV;
@@ -680,8 +660,7 @@ wdrtas_init(void)
680 * 660 *
681 * unregisters the file handlers and the reboot notifier 661 * unregisters the file handlers and the reboot notifier
682 */ 662 */
683static void __exit 663static void __exit wdrtas_exit(void)
684wdrtas_exit(void)
685{ 664{
686 if (!wdrtas_nowayout) 665 if (!wdrtas_nowayout)
687 wdrtas_timer_stop(); 666 wdrtas_timer_stop();
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c
index 53a6b18bcb9a..deeebb2b13ea 100644
--- a/drivers/watchdog/wdt.c
+++ b/drivers/watchdog/wdt.c
@@ -373,8 +373,6 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
373#endif /* CONFIG_WDT_501 */ 373#endif /* CONFIG_WDT_501 */
374 374
375 switch (cmd) { 375 switch (cmd) {
376 default:
377 return -ENOTTY;
378 case WDIOC_GETSUPPORT: 376 case WDIOC_GETSUPPORT:
379 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 377 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
380 case WDIOC_GETSTATUS: 378 case WDIOC_GETSTATUS:
@@ -394,6 +392,8 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
394 /* Fall */ 392 /* Fall */
395 case WDIOC_GETTIMEOUT: 393 case WDIOC_GETTIMEOUT:
396 return put_user(heartbeat, p); 394 return put_user(heartbeat, p);
395 default:
396 return -ENOTTY;
397 } 397 }
398} 398}
399 399
diff --git a/drivers/watchdog/wdt285.c b/drivers/watchdog/wdt285.c
index e4cf661dc890..fea398a4ca32 100644
--- a/drivers/watchdog/wdt285.c
+++ b/drivers/watchdog/wdt285.c
@@ -26,9 +26,9 @@
26#include <linux/reboot.h> 26#include <linux/reboot.h>
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29#include <linux/uaccess.h>
30#include <linux/irq.h>
29 31
30#include <asm/irq.h>
31#include <asm/uaccess.h>
32#include <asm/hardware.h> 32#include <asm/hardware.h>
33#include <asm/mach-types.h> 33#include <asm/mach-types.h>
34#include <asm/hardware/dec21285.h> 34#include <asm/hardware/dec21285.h>
@@ -115,8 +115,8 @@ static int watchdog_release(struct inode *inode, struct file *file)
115 return 0; 115 return 0;
116} 116}
117 117
118static ssize_t 118static ssize_t watchdog_write(struct file *file, const char *data,
119watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) 119 size_t len, loff_t *ppos)
120{ 120{
121 /* 121 /*
122 * Refresh the timer. 122 * Refresh the timer.
@@ -127,19 +127,18 @@ watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
127 return len; 127 return len;
128} 128}
129 129
130static struct watchdog_info ident = { 130static const struct watchdog_info ident = {
131 .options = WDIOF_SETTIMEOUT, 131 .options = WDIOF_SETTIMEOUT,
132 .identity = "Footbridge Watchdog", 132 .identity = "Footbridge Watchdog",
133}; 133};
134 134
135static int 135static long watchdog_ioctl(struct file *file, unsigned int cmd,
136watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 136 unsigned long arg)
137 unsigned long arg)
138{ 137{
139 unsigned int new_margin; 138 unsigned int new_margin;
140 int ret = -ENOTTY; 139 int ret = -ENOTTY;
141 140
142 switch(cmd) { 141 switch (cmd) {
143 case WDIOC_GETSUPPORT: 142 case WDIOC_GETSUPPORT:
144 ret = 0; 143 ret = 0;
145 if (copy_to_user((void *)arg, &ident, sizeof(ident))) 144 if (copy_to_user((void *)arg, &ident, sizeof(ident)))
@@ -148,7 +147,7 @@ watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
148 147
149 case WDIOC_GETSTATUS: 148 case WDIOC_GETSTATUS:
150 case WDIOC_GETBOOTSTATUS: 149 case WDIOC_GETBOOTSTATUS:
151 ret = put_user(0,(int *)arg); 150 ret = put_user(0, (int *)arg);
152 break; 151 break;
153 152
154 case WDIOC_KEEPALIVE: 153 case WDIOC_KEEPALIVE:
@@ -182,7 +181,7 @@ static const struct file_operations watchdog_fops = {
182 .owner = THIS_MODULE, 181 .owner = THIS_MODULE,
183 .llseek = no_llseek, 182 .llseek = no_llseek,
184 .write = watchdog_write, 183 .write = watchdog_write,
185 .ioctl = watchdog_ioctl, 184 .unlocked_ioctl = watchdog_ioctl,
186 .open = watchdog_open, 185 .open = watchdog_open,
187 .release = watchdog_release, 186 .release = watchdog_release,
188}; 187};
@@ -204,11 +203,13 @@ static int __init footbridge_watchdog_init(void)
204 if (retval < 0) 203 if (retval < 0)
205 return retval; 204 return retval;
206 205
207 printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", 206 printk(KERN_INFO
208 soft_margin); 207 "Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n",
208 soft_margin);
209 209
210 if (machine_is_cats()) 210 if (machine_is_cats())
211 printk("Warning: Watchdog reset may not work on this machine.\n"); 211 printk(KERN_WARN
212 "Warning: Watchdog reset may not work on this machine.\n");
212 return 0; 213 return 0;
213} 214}
214 215
@@ -223,7 +224,7 @@ MODULE_LICENSE("GPL");
223MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 224MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
224 225
225module_param(soft_margin, int, 0); 226module_param(soft_margin, int, 0);
226MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds"); 227MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds");
227 228
228module_init(footbridge_watchdog_init); 229module_init(footbridge_watchdog_init);
229module_exit(footbridge_watchdog_exit); 230module_exit(footbridge_watchdog_exit);
diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c
index fb4b876c9fda..60e28d49ff52 100644
--- a/drivers/watchdog/wdt977.c
+++ b/drivers/watchdog/wdt977.c
@@ -19,7 +19,8 @@
19 * 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in 19 * 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in
20 * nwwatchdog_init. 20 * nwwatchdog_init.
21 * 25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks 21 * 25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks
22 * remove limitiation to be used on Netwinders only 22 * remove limitiation to be used on
23 * Netwinders only
23 */ 24 */
24 25
25#include <linux/module.h> 26#include <linux/module.h>
@@ -33,11 +34,11 @@
33#include <linux/watchdog.h> 34#include <linux/watchdog.h>
34#include <linux/notifier.h> 35#include <linux/notifier.h>
35#include <linux/reboot.h> 36#include <linux/reboot.h>
37#include <linux/io.h>
38#include <linux/uaccess.h>
36 39
37#include <asm/io.h>
38#include <asm/system.h> 40#include <asm/system.h>
39#include <asm/mach-types.h> 41#include <asm/mach-types.h>
40#include <asm/uaccess.h>
41 42
42#define WATCHDOG_VERSION "0.04" 43#define WATCHDOG_VERSION "0.04"
43#define WATCHDOG_NAME "Wdt977" 44#define WATCHDOG_NAME "Wdt977"
@@ -45,7 +46,7 @@
45#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" 46#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
46 47
47#define IO_INDEX_PORT 0x370 /* on some systems it can be 0x3F0 */ 48#define IO_INDEX_PORT 0x370 /* on some systems it can be 0x3F0 */
48#define IO_DATA_PORT (IO_INDEX_PORT+1) 49#define IO_DATA_PORT (IO_INDEX_PORT + 1)
49 50
50#define UNLOCK_DATA 0x87 51#define UNLOCK_DATA 0x87
51#define LOCK_DATA 0xAA 52#define LOCK_DATA 0xAA
@@ -62,13 +63,16 @@ static char expect_close;
62static DEFINE_SPINLOCK(spinlock); 63static DEFINE_SPINLOCK(spinlock);
63 64
64module_param(timeout, int, 0); 65module_param(timeout, int, 0);
65MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); 66MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (60..15300), default="
67 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
66module_param(testmode, int, 0); 68module_param(testmode, int, 0);
67MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); 69MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0");
68 70
69static int nowayout = WATCHDOG_NOWAYOUT; 71static int nowayout = WATCHDOG_NOWAYOUT;
70module_param(nowayout, int, 0); 72module_param(nowayout, int, 0);
71MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 73MODULE_PARM_DESC(nowayout,
74 "Watchdog cannot be stopped once started (default="
75 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
72 76
73/* 77/*
74 * Start the watchdog 78 * Start the watchdog
@@ -95,14 +99,16 @@ static int wdt977_start(void)
95 outb_p(0xF2, IO_INDEX_PORT); 99 outb_p(0xF2, IO_INDEX_PORT);
96 outb_p(timeoutM, IO_DATA_PORT); 100 outb_p(timeoutM, IO_DATA_PORT);
97 outb_p(0xF3, IO_INDEX_PORT); 101 outb_p(0xF3, IO_INDEX_PORT);
98 outb_p(0x00, IO_DATA_PORT); /* another setting is 0E for kbd/mouse/LED */ 102 outb_p(0x00, IO_DATA_PORT); /* another setting is 0E for
103 kbd/mouse/LED */
99 outb_p(0xF4, IO_INDEX_PORT); 104 outb_p(0xF4, IO_INDEX_PORT);
100 outb_p(0x00, IO_DATA_PORT); 105 outb_p(0x00, IO_DATA_PORT);
101 106
102 /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ 107 /* At last select device Aux1 (dev=7) and set GP16 as a
103 /* in test mode watch the bit 1 on F4 to indicate "triggered" */ 108 * watchdog output. In test mode watch the bit 1 on F4 to
104 if (!testmode) 109 * indicate "triggered"
105 { 110 */
111 if (!testmode) {
106 outb_p(DEVICE_REGISTER, IO_INDEX_PORT); 112 outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
107 outb_p(0x07, IO_DATA_PORT); 113 outb_p(0x07, IO_DATA_PORT);
108 outb_p(0xE6, IO_INDEX_PORT); 114 outb_p(0xE6, IO_INDEX_PORT);
@@ -147,7 +153,8 @@ static int wdt977_stop(void)
147 outb_p(0xF2, IO_INDEX_PORT); 153 outb_p(0xF2, IO_INDEX_PORT);
148 outb_p(0x00, IO_DATA_PORT); 154 outb_p(0x00, IO_DATA_PORT);
149 155
150 /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ 156 /* at last select device Aux1 (dev=7) and set
157 GP16 as a watchdog output */
151 outb_p(DEVICE_REGISTER, IO_INDEX_PORT); 158 outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
152 outb_p(0x07, IO_DATA_PORT); 159 outb_p(0x07, IO_DATA_PORT);
153 outb_p(0xE6, IO_INDEX_PORT); 160 outb_p(0xE6, IO_INDEX_PORT);
@@ -202,16 +209,18 @@ static int wdt977_set_timeout(int t)
202 tmrval = (t + 59) / 60; 209 tmrval = (t + 59) / 60;
203 210
204 if (machine_is_netwinder()) { 211 if (machine_is_netwinder()) {
205 /* we have a hw bug somewhere, so each 977 minute is actually only 30sec 212 /* we have a hw bug somewhere, so each 977 minute is actually
206 * this limits the max timeout to half of device max of 255 minutes... 213 * only 30sec. This limits the max timeout to half of device
214 * max of 255 minutes...
207 */ 215 */
208 tmrval += tmrval; 216 tmrval += tmrval;
209 } 217 }
210 218
211 if ((tmrval < 1) || (tmrval > 255)) 219 if (tmrval < 1 || tmrval > 255)
212 return -EINVAL; 220 return -EINVAL;
213 221
214 /* timeout is the timeout in seconds, timeoutM is the timeout in minutes) */ 222 /* timeout is the timeout in seconds, timeoutM is
223 the timeout in minutes) */
215 timeout = t; 224 timeout = t;
216 timeoutM = tmrval; 225 timeoutM = tmrval;
217 return 0; 226 return 0;
@@ -243,7 +252,7 @@ static int wdt977_get_status(int *status)
243 252
244 spin_unlock_irqrestore(&spinlock, flags); 253 spin_unlock_irqrestore(&spinlock, flags);
245 254
246 *status=0; 255 *status = 0;
247 if (new_status & 1) 256 if (new_status & 1)
248 *status |= WDIOF_CARDRESET; 257 *status |= WDIOF_CARDRESET;
249 258
@@ -258,7 +267,7 @@ static int wdt977_get_status(int *status)
258static int wdt977_open(struct inode *inode, struct file *file) 267static int wdt977_open(struct inode *inode, struct file *file)
259{ 268{
260 /* If the watchdog is alive we don't need to start it again */ 269 /* If the watchdog is alive we don't need to start it again */
261 if( test_and_set_bit(0,&timer_alive) ) 270 if (test_and_set_bit(0, &timer_alive))
262 return -EBUSY; 271 return -EBUSY;
263 272
264 if (nowayout) 273 if (nowayout)
@@ -274,13 +283,13 @@ static int wdt977_release(struct inode *inode, struct file *file)
274 * Shut off the timer. 283 * Shut off the timer.
275 * Lock it in if it's a module and we set nowayout 284 * Lock it in if it's a module and we set nowayout
276 */ 285 */
277 if (expect_close == 42) 286 if (expect_close == 42) {
278 {
279 wdt977_stop(); 287 wdt977_stop();
280 clear_bit(0,&timer_alive); 288 clear_bit(0, &timer_alive);
281 } else { 289 } else {
282 wdt977_keepalive(); 290 wdt977_keepalive();
283 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 291 printk(KERN_CRIT PFX
292 "Unexpected close, not stopping watchdog!\n");
284 } 293 }
285 expect_close = 0; 294 expect_close = 0;
286 return 0; 295 return 0;
@@ -301,17 +310,14 @@ static int wdt977_release(struct inode *inode, struct file *file)
301static ssize_t wdt977_write(struct file *file, const char __user *buf, 310static ssize_t wdt977_write(struct file *file, const char __user *buf,
302 size_t count, loff_t *ppos) 311 size_t count, loff_t *ppos)
303{ 312{
304 if (count) 313 if (count) {
305 { 314 if (!nowayout) {
306 if (!nowayout)
307 {
308 size_t i; 315 size_t i;
309 316
310 /* In case it was set long ago */ 317 /* In case it was set long ago */
311 expect_close = 0; 318 expect_close = 0;
312 319
313 for (i = 0; i != count; i++) 320 for (i = 0; i != count; i++) {
314 {
315 char c; 321 char c;
316 if (get_user(c, buf + i)) 322 if (get_user(c, buf + i))
317 return -EFAULT; 323 return -EFAULT;
@@ -326,6 +332,14 @@ static ssize_t wdt977_write(struct file *file, const char __user *buf,
326 return count; 332 return count;
327} 333}
328 334
335static const struct watchdog_info ident = {
336 .options = WDIOF_SETTIMEOUT |
337 WDIOF_MAGICCLOSE |
338 WDIOF_KEEPALIVEPING,
339 .firmware_version = 1,
340 .identity = WATCHDOG_NAME,
341};
342
329/* 343/*
330 * wdt977_ioctl: 344 * wdt977_ioctl:
331 * @inode: inode of the device 345 * @inode: inode of the device
@@ -337,16 +351,8 @@ static ssize_t wdt977_write(struct file *file, const char __user *buf,
337 * according to their available features. 351 * according to their available features.
338 */ 352 */
339 353
340static struct watchdog_info ident = { 354static long wdt977_ioctl(struct file *file, unsigned int cmd,
341 .options = WDIOF_SETTIMEOUT | 355 unsigned long arg)
342 WDIOF_MAGICCLOSE |
343 WDIOF_KEEPALIVEPING,
344 .firmware_version = 1,
345 .identity = WATCHDOG_NAME,
346};
347
348static int wdt977_ioctl(struct inode *inode, struct file *file,
349 unsigned int cmd, unsigned long arg)
350{ 356{
351 int status; 357 int status;
352 int new_options, retval = -EINVAL; 358 int new_options, retval = -EINVAL;
@@ -358,11 +364,7 @@ static int wdt977_ioctl(struct inode *inode, struct file *file,
358 364
359 uarg.i = (int __user *)arg; 365 uarg.i = (int __user *)arg;
360 366
361 switch(cmd) 367 switch (cmd) {
362 {
363 default:
364 return -ENOTTY;
365
366 case WDIOC_GETSUPPORT: 368 case WDIOC_GETSUPPORT:
367 return copy_to_user(uarg.ident, &ident, 369 return copy_to_user(uarg.ident, &ident,
368 sizeof(ident)) ? -EFAULT : 0; 370 sizeof(ident)) ? -EFAULT : 0;
@@ -374,12 +376,8 @@ static int wdt977_ioctl(struct inode *inode, struct file *file,
374 case WDIOC_GETBOOTSTATUS: 376 case WDIOC_GETBOOTSTATUS:
375 return put_user(0, uarg.i); 377 return put_user(0, uarg.i);
376 378
377 case WDIOC_KEEPALIVE:
378 wdt977_keepalive();
379 return 0;
380
381 case WDIOC_SETOPTIONS: 379 case WDIOC_SETOPTIONS:
382 if (get_user (new_options, uarg.i)) 380 if (get_user(new_options, uarg.i))
383 return -EFAULT; 381 return -EFAULT;
384 382
385 if (new_options & WDIOS_DISABLECARD) { 383 if (new_options & WDIOS_DISABLECARD) {
@@ -394,6 +392,10 @@ static int wdt977_ioctl(struct inode *inode, struct file *file,
394 392
395 return retval; 393 return retval;
396 394
395 case WDIOC_KEEPALIVE:
396 wdt977_keepalive();
397 return 0;
398
397 case WDIOC_SETTIMEOUT: 399 case WDIOC_SETTIMEOUT:
398 if (get_user(new_timeout, uarg.i)) 400 if (get_user(new_timeout, uarg.i))
399 return -EFAULT; 401 return -EFAULT;
@@ -407,29 +409,30 @@ static int wdt977_ioctl(struct inode *inode, struct file *file,
407 case WDIOC_GETTIMEOUT: 409 case WDIOC_GETTIMEOUT:
408 return put_user(timeout, uarg.i); 410 return put_user(timeout, uarg.i);
409 411
412 default:
413 return -ENOTTY;
414
410 } 415 }
411} 416}
412 417
413static int wdt977_notify_sys(struct notifier_block *this, unsigned long code, 418static int wdt977_notify_sys(struct notifier_block *this, unsigned long code,
414 void *unused) 419 void *unused)
415{ 420{
416 if(code==SYS_DOWN || code==SYS_HALT) 421 if (code == SYS_DOWN || code == SYS_HALT)
417 wdt977_stop(); 422 wdt977_stop();
418 return NOTIFY_DONE; 423 return NOTIFY_DONE;
419} 424}
420 425
421static const struct file_operations wdt977_fops= 426static const struct file_operations wdt977_fops = {
422{
423 .owner = THIS_MODULE, 427 .owner = THIS_MODULE,
424 .llseek = no_llseek, 428 .llseek = no_llseek,
425 .write = wdt977_write, 429 .write = wdt977_write,
426 .ioctl = wdt977_ioctl, 430 .unlocked_ioctl = wdt977_ioctl,
427 .open = wdt977_open, 431 .open = wdt977_open,
428 .release = wdt977_release, 432 .release = wdt977_release,
429}; 433};
430 434
431static struct miscdevice wdt977_miscdev= 435static struct miscdevice wdt977_miscdev = {
432{
433 .minor = WATCHDOG_MINOR, 436 .minor = WATCHDOG_MINOR,
434 .name = "watchdog", 437 .name = "watchdog",
435 .fops = &wdt977_fops, 438 .fops = &wdt977_fops,
@@ -443,51 +446,48 @@ static int __init wd977_init(void)
443{ 446{
444 int rc; 447 int rc;
445 448
446 //if (!machine_is_netwinder())
447 // return -ENODEV;
448
449 printk(KERN_INFO PFX DRIVER_VERSION); 449 printk(KERN_INFO PFX DRIVER_VERSION);
450 450
451 /* Check that the timeout value is within it's range ; if not reset to the default */ 451 /* Check that the timeout value is within its range;
452 if (wdt977_set_timeout(timeout)) 452 if not reset to the default */
453 { 453 if (wdt977_set_timeout(timeout)) {
454 wdt977_set_timeout(DEFAULT_TIMEOUT); 454 wdt977_set_timeout(DEFAULT_TIMEOUT);
455 printk(KERN_INFO PFX "timeout value must be 60<timeout<15300, using %d\n", 455 printk(KERN_INFO PFX
456 DEFAULT_TIMEOUT); 456 "timeout value must be 60 < timeout < 15300, using %d\n",
457 DEFAULT_TIMEOUT);
457 } 458 }
458 459
459 /* on Netwinder the IOports are already reserved by 460 /* on Netwinder the IOports are already reserved by
460 * arch/arm/mach-footbridge/netwinder-hw.c 461 * arch/arm/mach-footbridge/netwinder-hw.c
461 */ 462 */
462 if (!machine_is_netwinder()) 463 if (!machine_is_netwinder()) {
463 { 464 if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) {
464 if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) 465 printk(KERN_ERR PFX
465 { 466 "I/O address 0x%04x already in use\n",
466 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", 467 IO_INDEX_PORT);
467 IO_INDEX_PORT);
468 rc = -EIO; 468 rc = -EIO;
469 goto err_out; 469 goto err_out;
470 } 470 }
471 } 471 }
472 472
473 rc = register_reboot_notifier(&wdt977_notifier); 473 rc = register_reboot_notifier(&wdt977_notifier);
474 if (rc) 474 if (rc) {
475 { 475 printk(KERN_ERR PFX
476 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 476 "cannot register reboot notifier (err=%d)\n", rc);
477 rc);
478 goto err_out_region; 477 goto err_out_region;
479 } 478 }
480 479
481 rc = misc_register(&wdt977_miscdev); 480 rc = misc_register(&wdt977_miscdev);
482 if (rc) 481 if (rc) {
483 { 482 printk(KERN_ERR PFX
484 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 483 "cannot register miscdev on minor=%d (err=%d)\n",
485 wdt977_miscdev.minor, rc); 484 wdt977_miscdev.minor, rc);
486 goto err_out_reboot; 485 goto err_out_reboot;
487 } 486 }
488 487
489 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n", 488 printk(KERN_INFO PFX
490 timeout, nowayout, testmode); 489 "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
490 timeout, nowayout, testmode);
491 491
492 return 0; 492 return 0;
493 493
@@ -495,7 +495,7 @@ err_out_reboot:
495 unregister_reboot_notifier(&wdt977_notifier); 495 unregister_reboot_notifier(&wdt977_notifier);
496err_out_region: 496err_out_region:
497 if (!machine_is_netwinder()) 497 if (!machine_is_netwinder())
498 release_region(IO_INDEX_PORT,2); 498 release_region(IO_INDEX_PORT, 2);
499err_out: 499err_out:
500 return rc; 500 return rc;
501} 501}
@@ -505,7 +505,7 @@ static void __exit wd977_exit(void)
505 wdt977_stop(); 505 wdt977_stop();
506 misc_deregister(&wdt977_miscdev); 506 misc_deregister(&wdt977_miscdev);
507 unregister_reboot_notifier(&wdt977_notifier); 507 unregister_reboot_notifier(&wdt977_notifier);
508 release_region(IO_INDEX_PORT,2); 508 release_region(IO_INDEX_PORT, 2);
509} 509}
510 510
511module_init(wd977_init); 511module_init(wd977_init);
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index 5d922fd6eafc..ed02bdb38c09 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -381,7 +381,7 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf,
381 381
382 for (i = 0; i != count; i++) { 382 for (i = 0; i != count; i++) {
383 char c; 383 char c;
384 if (get_user(c, buf+i)) 384 if (get_user(c, buf + i))
385 return -EFAULT; 385 return -EFAULT;
386 if (c == 'V') 386 if (c == 'V')
387 expect_close = 42; 387 expect_close = 42;
@@ -428,8 +428,6 @@ static long wdtpci_ioctl(struct file *file, unsigned int cmd,
428#endif /* CONFIG_WDT_501_PCI */ 428#endif /* CONFIG_WDT_501_PCI */
429 429
430 switch (cmd) { 430 switch (cmd) {
431 default:
432 return -ENOTTY;
433 case WDIOC_GETSUPPORT: 431 case WDIOC_GETSUPPORT:
434 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 432 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
435 case WDIOC_GETSTATUS: 433 case WDIOC_GETSTATUS:
@@ -449,7 +447,9 @@ static long wdtpci_ioctl(struct file *file, unsigned int cmd,
449 /* Fall */ 447 /* Fall */
450 case WDIOC_GETTIMEOUT: 448 case WDIOC_GETTIMEOUT:
451 return put_user(heartbeat, p); 449 return put_user(heartbeat, p);
452 } 450 default:
451 return -ENOTTY;
452 }
453} 453}
454 454
455/** 455/**
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 1de98f150e99..d548de326722 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -14,6 +14,7 @@
14 14
15#include <linux/videodev2.h> 15#include <linux/videodev2.h>
16#include <media/videobuf-core.h> 16#include <media/videobuf-core.h>
17#include <linux/pm.h>
17 18
18struct soc_camera_device { 19struct soc_camera_device {
19 struct list_head list; 20 struct list_head list;
@@ -63,6 +64,8 @@ struct soc_camera_host_ops {
63 struct module *owner; 64 struct module *owner;
64 int (*add)(struct soc_camera_device *); 65 int (*add)(struct soc_camera_device *);
65 void (*remove)(struct soc_camera_device *); 66 void (*remove)(struct soc_camera_device *);
67 int (*suspend)(struct soc_camera_device *, pm_message_t state);
68 int (*resume)(struct soc_camera_device *);
66 int (*set_fmt_cap)(struct soc_camera_device *, __u32, 69 int (*set_fmt_cap)(struct soc_camera_device *, __u32,
67 struct v4l2_rect *); 70 struct v4l2_rect *);
68 int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); 71 int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
@@ -111,6 +114,8 @@ struct soc_camera_ops {
111 struct module *owner; 114 struct module *owner;
112 int (*probe)(struct soc_camera_device *); 115 int (*probe)(struct soc_camera_device *);
113 void (*remove)(struct soc_camera_device *); 116 void (*remove)(struct soc_camera_device *);
117 int (*suspend)(struct soc_camera_device *, pm_message_t state);
118 int (*resume)(struct soc_camera_device *);
114 int (*init)(struct soc_camera_device *); 119 int (*init)(struct soc_camera_device *);
115 int (*release)(struct soc_camera_device *); 120 int (*release)(struct soc_camera_device *);
116 int (*start_capture)(struct soc_camera_device *); 121 int (*start_capture)(struct soc_camera_device *);
diff --git a/init/Kconfig b/init/Kconfig
index 7e6dae1ae727..b678803deccf 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -845,9 +845,10 @@ menuconfig MODULES
845 845
846 If unsure, say Y. 846 If unsure, say Y.
847 847
848if MODULES
849
848config MODULE_FORCE_LOAD 850config MODULE_FORCE_LOAD
849 bool "Forced module loading" 851 bool "Forced module loading"
850 depends on MODULES
851 default n 852 default n
852 help 853 help
853 Allow loading of modules without version information (ie. modprobe 854 Allow loading of modules without version information (ie. modprobe
@@ -856,7 +857,6 @@ config MODULE_FORCE_LOAD
856 857
857config MODULE_UNLOAD 858config MODULE_UNLOAD
858 bool "Module unloading" 859 bool "Module unloading"
859 depends on MODULES
860 help 860 help
861 Without this option you will not be able to unload any 861 Without this option you will not be able to unload any
862 modules (note that some modules may not be unloadable 862 modules (note that some modules may not be unloadable
@@ -875,7 +875,6 @@ config MODULE_FORCE_UNLOAD
875 875
876config MODVERSIONS 876config MODVERSIONS
877 bool "Module versioning support" 877 bool "Module versioning support"
878 depends on MODULES
879 help 878 help
880 Usually, you have to use modules compiled with your kernel. 879 Usually, you have to use modules compiled with your kernel.
881 Saying Y here makes it sometimes possible to use modules 880 Saying Y here makes it sometimes possible to use modules
@@ -886,7 +885,6 @@ config MODVERSIONS
886 885
887config MODULE_SRCVERSION_ALL 886config MODULE_SRCVERSION_ALL
888 bool "Source checksum for all modules" 887 bool "Source checksum for all modules"
889 depends on MODULES
890 help 888 help
891 Modules which contain a MODULE_VERSION get an extra "srcversion" 889 Modules which contain a MODULE_VERSION get an extra "srcversion"
892 field inserted into their modinfo section, which contains a 890 field inserted into their modinfo section, which contains a
@@ -898,11 +896,12 @@ config MODULE_SRCVERSION_ALL
898 896
899config KMOD 897config KMOD
900 def_bool y 898 def_bool y
901 depends on MODULES
902 help 899 help
903 This is being removed soon. These days, CONFIG_MODULES 900 This is being removed soon. These days, CONFIG_MODULES
904 implies CONFIG_KMOD, so use that instead. 901 implies CONFIG_KMOD, so use that instead.
905 902
903endif # MODULES
904
906config STOP_MACHINE 905config STOP_MACHINE
907 bool 906 bool
908 default y 907 default y
diff --git a/scripts/patch-kernel b/scripts/patch-kernel
index ece46ef0ba54..46a59cae3a0a 100755
--- a/scripts/patch-kernel
+++ b/scripts/patch-kernel
@@ -213,6 +213,7 @@ fi
213if [ $stopvers != "default" ]; then 213if [ $stopvers != "default" ]; then
214 STOPSUBLEVEL=`echo $stopvers | cut -d. -f3` 214 STOPSUBLEVEL=`echo $stopvers | cut -d. -f3`
215 STOPEXTRA=`echo $stopvers | cut -d. -f4` 215 STOPEXTRA=`echo $stopvers | cut -d. -f4`
216 STOPFULLVERSION=${stopvers%%.$STOPEXTRA}
216 #echo "#___STOPSUBLEVEL=/$STOPSUBLEVEL/, STOPEXTRA=/$STOPEXTRA/" 217 #echo "#___STOPSUBLEVEL=/$STOPSUBLEVEL/, STOPEXTRA=/$STOPEXTRA/"
217else 218else
218 STOPSUBLEVEL=9999 219 STOPSUBLEVEL=9999
@@ -249,7 +250,7 @@ while : # incrementing SUBLEVEL (s in v.p.s)
249do 250do
250 CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" 251 CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
251 EXTRAVER= 252 EXTRAVER=
252 if [ $stopvers = $CURRENTFULLVERSION ]; then 253 if [ $STOPFULLVERSION = $CURRENTFULLVERSION ]; then
253 echo "Stopping at $CURRENTFULLVERSION base as requested." 254 echo "Stopping at $CURRENTFULLVERSION base as requested."
254 break 255 break
255 fi 256 fi