diff options
| -rw-r--r-- | Documentation/watchdog/pcwd-watchdog.txt | 8 | ||||
| -rw-r--r-- | Documentation/watchdog/watchdog-api.txt | 236 | ||||
| -rw-r--r-- | Documentation/watchdog/watchdog.txt | 94 | ||||
| -rw-r--r-- | Documentation/watchdog/wdt.txt | 43 | ||||
| -rw-r--r-- | drivers/char/watchdog/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/char/watchdog/Makefile | 1 | ||||
| -rw-r--r-- | drivers/char/watchdog/ks8695_wdt.c | 308 |
7 files changed, 376 insertions, 321 deletions
diff --git a/Documentation/watchdog/pcwd-watchdog.txt b/Documentation/watchdog/pcwd-watchdog.txt index d9ee6336c1d4..4f68052395c0 100644 --- a/Documentation/watchdog/pcwd-watchdog.txt +++ b/Documentation/watchdog/pcwd-watchdog.txt | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | Last reviewed: 10/05/2007 | ||
| 2 | |||
| 1 | Berkshire Products PC Watchdog Card | 3 | Berkshire Products PC Watchdog Card |
| 2 | Support for ISA Cards Revision A and C | 4 | Support for ISA Cards Revision A and C |
| 3 | Documentation and Driver by Ken Hollis <kenji@bitgate.com> | 5 | Documentation and Driver by Ken Hollis <kenji@bitgate.com> |
| @@ -14,8 +16,8 @@ | |||
| 14 | 16 | ||
| 15 | The Watchdog Driver will automatically find your watchdog card, and will | 17 | The Watchdog Driver will automatically find your watchdog card, and will |
| 16 | attach a running driver for use with that card. After the watchdog | 18 | attach a running driver for use with that card. After the watchdog |
| 17 | drivers have initialized, you can then talk to the card using the PC | 19 | drivers have initialized, you can then talk to the card using a PC |
| 18 | Watchdog program, available from http://ftp.bitgate.com/pcwd/. | 20 | Watchdog program. |
| 19 | 21 | ||
| 20 | I suggest putting a "watchdog -d" before the beginning of an fsck, and | 22 | I suggest putting a "watchdog -d" before the beginning of an fsck, and |
| 21 | a "watchdog -e -t 1" immediately after the end of an fsck. (Remember | 23 | a "watchdog -e -t 1" immediately after the end of an fsck. (Remember |
| @@ -62,5 +64,3 @@ | |||
| 62 | -- Ken Hollis | 64 | -- Ken Hollis |
| 63 | (kenji@bitgate.com) | 65 | (kenji@bitgate.com) |
| 64 | 66 | ||
| 65 | (This documentation may be out of date. Check | ||
| 66 | http://ftp.bitgate.com/pcwd/ for the absolute latest additions.) | ||
diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt index 8d16f6f3c4ec..bb7cb1d31ec7 100644 --- a/Documentation/watchdog/watchdog-api.txt +++ b/Documentation/watchdog/watchdog-api.txt | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | Last reviewed: 10/05/2007 | ||
| 2 | |||
| 3 | |||
| 1 | The Linux Watchdog driver API. | 4 | The Linux Watchdog driver API. |
| 2 | 5 | ||
| 3 | Copyright 2002 Christer Weingel <wingel@nano-system.com> | 6 | Copyright 2002 Christer Weingel <wingel@nano-system.com> |
| @@ -22,7 +25,7 @@ the system. If userspace fails (RAM error, kernel bug, whatever), the | |||
| 22 | notifications cease to occur, and the hardware watchdog will reset the | 25 | notifications cease to occur, and the hardware watchdog will reset the |
| 23 | system (causing a reboot) after the timeout occurs. | 26 | system (causing a reboot) after the timeout occurs. |
| 24 | 27 | ||
| 25 | The Linux watchdog API is a rather AD hoc construction and different | 28 | The Linux watchdog API is a rather ad-hoc construction and different |
| 26 | drivers implement different, and sometimes incompatible, parts of it. | 29 | drivers implement different, and sometimes incompatible, parts of it. |
| 27 | This file is an attempt to document the existing usage and allow | 30 | This file is an attempt to document the existing usage and allow |
| 28 | future driver writers to use it as a reference. | 31 | future driver writers to use it as a reference. |
| @@ -46,14 +49,16 @@ some of the drivers support the configuration option "Disable watchdog | |||
| 46 | shutdown on close", CONFIG_WATCHDOG_NOWAYOUT. If it is set to Y when | 49 | shutdown on close", CONFIG_WATCHDOG_NOWAYOUT. If it is set to Y when |
| 47 | compiling the kernel, there is no way of disabling the watchdog once | 50 | compiling the kernel, there is no way of disabling the watchdog once |
| 48 | it has been started. So, if the watchdog daemon crashes, the system | 51 | it has been started. So, if the watchdog daemon crashes, the system |
| 49 | will reboot after the timeout has passed. | 52 | will reboot after the timeout has passed. Watchdog devices also usually |
| 53 | support the nowayout module parameter so that this option can be controlled | ||
| 54 | at runtime. | ||
| 50 | 55 | ||
| 51 | Some other drivers will not disable the watchdog, unless a specific | 56 | Drivers will not disable the watchdog, unless a specific magic character 'V' |
| 52 | magic character 'V' has been sent /dev/watchdog just before closing | 57 | has been sent /dev/watchdog just before closing the file. If the userspace |
| 53 | the file. If the userspace daemon closes the file without sending | 58 | daemon closes the file without sending this special character, the driver |
| 54 | this special character, the driver will assume that the daemon (and | 59 | will assume that the daemon (and userspace in general) died, and will stop |
| 55 | userspace in general) died, and will stop pinging the watchdog without | 60 | pinging the watchdog without disabling it first. This will then cause a |
| 56 | disabling it first. This will then cause a reboot. | 61 | reboot if the watchdog is not re-opened in sufficient time. |
| 57 | 62 | ||
| 58 | The ioctl API: | 63 | The ioctl API: |
| 59 | 64 | ||
| @@ -227,218 +232,3 @@ The following options are available: | |||
| 227 | 232 | ||
| 228 | [FIXME -- better explanations] | 233 | [FIXME -- better explanations] |
| 229 | 234 | ||
| 230 | Implementations in the current drivers in the kernel tree: | ||
| 231 | |||
| 232 | Here I have tried to summarize what the different drivers support and | ||
| 233 | where they do strange things compared to the other drivers. | ||
| 234 | |||
| 235 | acquirewdt.c -- Acquire Single Board Computer | ||
| 236 | |||
| 237 | This driver has a hardcoded timeout of 1 minute | ||
| 238 | |||
| 239 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 240 | |||
| 241 | GETSUPPORT returns KEEPALIVEPING. GETSTATUS will return 1 if | ||
| 242 | the device is open, 0 if not. [FIXME -- isn't this rather | ||
| 243 | silly? To be able to use the ioctl, the device must be open | ||
| 244 | and so GETSTATUS will always return 1]. | ||
| 245 | |||
| 246 | advantechwdt.c -- Advantech Single Board Computer | ||
| 247 | |||
| 248 | Timeout that defaults to 60 seconds, supports SETTIMEOUT. | ||
| 249 | |||
| 250 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 251 | |||
| 252 | GETSUPPORT returns WDIOF_KEEPALIVEPING and WDIOF_SETTIMEOUT. | ||
| 253 | The GETSTATUS call returns if the device is open or not. | ||
| 254 | [FIXME -- silliness again?] | ||
| 255 | |||
| 256 | booke_wdt.c -- PowerPC BookE Watchdog Timer | ||
| 257 | |||
| 258 | Timeout default varies according to frequency, supports | ||
| 259 | SETTIMEOUT | ||
| 260 | |||
| 261 | Watchdog cannot be turned off, CONFIG_WATCHDOG_NOWAYOUT | ||
| 262 | does not make sense | ||
| 263 | |||
| 264 | GETSUPPORT returns the watchdog_info struct, and | ||
| 265 | GETSTATUS returns the supported options. GETBOOTSTATUS | ||
| 266 | returns a 1 if the last reset was caused by the | ||
| 267 | watchdog and a 0 otherwise. This watchdog cannot be | ||
| 268 | disabled once it has been started. The wdt_period kernel | ||
| 269 | parameter selects which bit of the time base changing | ||
| 270 | from 0->1 will trigger the watchdog exception. Changing | ||
| 271 | the timeout from the ioctl calls will change the | ||
| 272 | wdt_period as defined above. Finally if you would like to | ||
| 273 | replace the default Watchdog Handler you can implement the | ||
| 274 | WatchdogHandler() function in your own code. | ||
| 275 | |||
| 276 | eurotechwdt.c -- Eurotech CPU-1220/1410 | ||
| 277 | |||
| 278 | The timeout can be set using the SETTIMEOUT ioctl and defaults | ||
| 279 | to 60 seconds. | ||
| 280 | |||
| 281 | Also has a module parameter "ev", event type which controls | ||
| 282 | what should happen on a timeout, the string "int" or anything | ||
| 283 | else that causes a reboot. [FIXME -- better description] | ||
| 284 | |||
| 285 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 286 | |||
| 287 | GETSUPPORT returns CARDRESET and WDIOF_SETTIMEOUT but | ||
| 288 | GETSTATUS is not supported and GETBOOTSTATUS just returns 0. | ||
| 289 | |||
| 290 | i810-tco.c -- Intel 810 chipset | ||
| 291 | |||
| 292 | Also has support for a lot of other i8x0 stuff, but the | ||
| 293 | watchdog is one of the things. | ||
| 294 | |||
| 295 | The timeout is set using the module parameter "i810_margin", | ||
| 296 | which is in steps of 0.6 seconds where 2<i810_margin<64. The | ||
| 297 | driver supports the SETTIMEOUT ioctl. | ||
| 298 | |||
| 299 | Supports CONFIG_WATCHDOG_NOWAYOUT. | ||
| 300 | |||
| 301 | GETSUPPORT returns WDIOF_SETTIMEOUT. The GETSTATUS call | ||
| 302 | returns some kind of timer value which ist not compatible with | ||
| 303 | the other drivers. GETBOOT status returns some kind of | ||
| 304 | hardware specific boot status. [FIXME -- describe this] | ||
| 305 | |||
| 306 | ib700wdt.c -- IB700 Single Board Computer | ||
| 307 | |||
| 308 | Default timeout of 30 seconds and the timeout is settable | ||
| 309 | using the SETTIMEOUT ioctl. Note that only a few timeout | ||
| 310 | values are supported. | ||
| 311 | |||
| 312 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 313 | |||
| 314 | GETSUPPORT returns WDIOF_KEEPALIVEPING and WDIOF_SETTIMEOUT. | ||
| 315 | The GETSTATUS call returns if the device is open or not. | ||
| 316 | [FIXME -- silliness again?] | ||
| 317 | |||
| 318 | machzwd.c -- MachZ ZF-Logic | ||
| 319 | |||
| 320 | Hardcoded timeout of 10 seconds | ||
| 321 | |||
| 322 | Has a module parameter "action" that controls what happens | ||
| 323 | when the timeout runs out which can be 0 = RESET (default), | ||
| 324 | 1 = SMI, 2 = NMI, 3 = SCI. | ||
| 325 | |||
| 326 | Supports CONFIG_WATCHDOG_NOWAYOUT and the magic character | ||
| 327 | 'V' close handling. | ||
| 328 | |||
| 329 | GETSUPPORT returns WDIOF_KEEPALIVEPING, and the GETSTATUS call | ||
| 330 | returns if the device is open or not. [FIXME -- silliness | ||
| 331 | again?] | ||
| 332 | |||
| 333 | mixcomwd.c -- MixCom Watchdog | ||
| 334 | |||
| 335 | [FIXME -- I'm unable to tell what the timeout is] | ||
| 336 | |||
| 337 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 338 | |||
| 339 | GETSUPPORT returns WDIOF_KEEPALIVEPING, GETSTATUS returns if | ||
| 340 | the device is opened or not [FIXME -- I'm not really sure how | ||
| 341 | this works, there seems to be some magic connected to | ||
| 342 | CONFIG_WATCHDOG_NOWAYOUT] | ||
| 343 | |||
| 344 | pcwd.c -- Berkshire PC Watchdog | ||
| 345 | |||
| 346 | Hardcoded timeout of 1.5 seconds | ||
| 347 | |||
| 348 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 349 | |||
| 350 | GETSUPPORT returns WDIOF_OVERHEAT|WDIOF_CARDRESET and both | ||
| 351 | GETSTATUS and GETBOOTSTATUS return something useful. | ||
| 352 | |||
| 353 | The SETOPTIONS call can be used to enable and disable the card | ||
| 354 | and to ask the driver to call panic if the system overheats. | ||
| 355 | |||
| 356 | sbc60xxwdt.c -- 60xx Single Board Computer | ||
| 357 | |||
| 358 | Hardcoded timeout of 10 seconds | ||
| 359 | |||
| 360 | Does not support CONFIG_WATCHDOG_NOWAYOUT, but has the magic | ||
| 361 | character 'V' close handling. | ||
| 362 | |||
| 363 | No bits set in GETSUPPORT | ||
| 364 | |||
| 365 | scx200.c -- National SCx200 CPUs | ||
| 366 | |||
| 367 | Not in the kernel yet. | ||
| 368 | |||
| 369 | The timeout is set using a module parameter "margin" which | ||
| 370 | defaults to 60 seconds. The timeout can also be set using | ||
| 371 | SETTIMEOUT and read using GETTIMEOUT. | ||
| 372 | |||
| 373 | Supports a module parameter "nowayout" that is initialized | ||
| 374 | with the value of CONFIG_WATCHDOG_NOWAYOUT. Also supports the | ||
| 375 | magic character 'V' handling. | ||
| 376 | |||
| 377 | shwdt.c -- SuperH 3/4 processors | ||
| 378 | |||
| 379 | [FIXME -- I'm unable to tell what the timeout is] | ||
| 380 | |||
| 381 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 382 | |||
| 383 | GETSUPPORT returns WDIOF_KEEPALIVEPING, and the GETSTATUS call | ||
| 384 | returns if the device is open or not. [FIXME -- silliness | ||
| 385 | again?] | ||
| 386 | |||
| 387 | softdog.c -- Software watchdog | ||
| 388 | |||
| 389 | The timeout is set with the module parameter "soft_margin" | ||
| 390 | which defaults to 60 seconds, the timeout is also settable | ||
| 391 | using the SETTIMEOUT ioctl. | ||
| 392 | |||
| 393 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 394 | |||
| 395 | WDIOF_SETTIMEOUT bit set in GETSUPPORT | ||
| 396 | |||
| 397 | w83877f_wdt.c -- W83877F Computer | ||
| 398 | |||
| 399 | Hardcoded timeout of 30 seconds | ||
| 400 | |||
| 401 | Does not support CONFIG_WATCHDOG_NOWAYOUT, but has the magic | ||
| 402 | character 'V' close handling. | ||
| 403 | |||
| 404 | No bits set in GETSUPPORT | ||
| 405 | |||
| 406 | w83627hf_wdt.c -- w83627hf watchdog | ||
| 407 | |||
| 408 | Timeout that defaults to 60 seconds, supports SETTIMEOUT. | ||
| 409 | |||
| 410 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 411 | |||
| 412 | GETSUPPORT returns WDIOF_KEEPALIVEPING and WDIOF_SETTIMEOUT. | ||
| 413 | The GETSTATUS call returns if the device is open or not. | ||
| 414 | |||
| 415 | wdt.c -- ICS WDT500/501 ISA and | ||
| 416 | wdt_pci.c -- ICS WDT500/501 PCI | ||
| 417 | |||
| 418 | Default timeout of 60 seconds. The timeout is also settable | ||
| 419 | using the SETTIMEOUT ioctl. | ||
| 420 | |||
| 421 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 422 | |||
| 423 | GETSUPPORT returns with bits set depending on the actual | ||
| 424 | card. The WDT501 supports a lot of external monitoring, the | ||
| 425 | WDT500 much less. | ||
| 426 | |||
| 427 | wdt285.c -- Footbridge watchdog | ||
| 428 | |||
| 429 | The timeout is set with the module parameter "soft_margin" | ||
| 430 | which defaults to 60 seconds. The timeout is also settable | ||
| 431 | using the SETTIMEOUT ioctl. | ||
| 432 | |||
| 433 | Does not support CONFIG_WATCHDOG_NOWAYOUT | ||
| 434 | |||
| 435 | WDIOF_SETTIMEOUT bit set in GETSUPPORT | ||
| 436 | |||
| 437 | wdt977.c -- Netwinder W83977AF chip | ||
| 438 | |||
| 439 | Hardcoded timeout of 3 minutes | ||
| 440 | |||
| 441 | Supports CONFIG_WATCHDOG_NOWAYOUT | ||
| 442 | |||
| 443 | Does not support any ioctls at all. | ||
| 444 | |||
diff --git a/Documentation/watchdog/watchdog.txt b/Documentation/watchdog/watchdog.txt deleted file mode 100644 index 4b1ff69cc19a..000000000000 --- a/Documentation/watchdog/watchdog.txt +++ /dev/null | |||
| @@ -1,94 +0,0 @@ | |||
| 1 | Watchdog Timer Interfaces For The Linux Operating System | ||
| 2 | |||
| 3 | Alan Cox <alan@lxorguk.ukuu.org.uk> | ||
| 4 | |||
| 5 | Custom Linux Driver And Program Development | ||
| 6 | |||
| 7 | |||
| 8 | The following watchdog drivers are currently implemented: | ||
| 9 | |||
| 10 | ICS WDT501-P | ||
| 11 | ICS WDT501-P (no fan tachometer) | ||
| 12 | ICS WDT500-P | ||
| 13 | Software Only | ||
| 14 | SA1100 Internal Watchdog | ||
| 15 | Berkshire Products PC Watchdog Revision A & C (by Ken Hollis) | ||
| 16 | |||
| 17 | |||
| 18 | All six interfaces provide /dev/watchdog, which when open must be written | ||
| 19 | to within a timeout or the machine will reboot. Each write delays the reboot | ||
| 20 | time another timeout. In the case of the software watchdog the ability to | ||
| 21 | reboot will depend on the state of the machines and interrupts. The hardware | ||
| 22 | boards physically pull the machine down off their own onboard timers and | ||
| 23 | will reboot from almost anything. | ||
| 24 | |||
| 25 | A second temperature monitoring interface is available on the WDT501P cards | ||
| 26 | and some Berkshire cards. This provides /dev/temperature. This is the machine | ||
| 27 | internal temperature in degrees Fahrenheit. Each read returns a single byte | ||
| 28 | giving the temperature. | ||
| 29 | |||
| 30 | The third interface logs kernel messages on additional alert events. | ||
| 31 | |||
| 32 | Both software and hardware watchdog drivers are available in the standard | ||
| 33 | kernel. If you are using the software watchdog, you probably also want | ||
| 34 | to use "panic=60" as a boot argument as well. | ||
| 35 | |||
| 36 | The wdt card cannot be safely probed for. Instead you need to pass | ||
| 37 | wdt=ioaddr,irq as a boot parameter - eg "wdt=0x240,11". | ||
| 38 | |||
| 39 | The SA1100 watchdog module can be configured with the "sa1100_margin" | ||
| 40 | commandline argument which specifies timeout value in seconds. | ||
| 41 | |||
| 42 | The i810 TCO watchdog modules can be configured with the "i810_margin" | ||
| 43 | commandline argument which specifies the counter initial value. The counter | ||
| 44 | is decremented every 0.6 seconds and default to 50 (30 seconds). Values can | ||
| 45 | range between 3 and 63. | ||
| 46 | |||
| 47 | The i810 TCO watchdog driver also implements the WDIOC_GETSTATUS and | ||
| 48 | WDIOC_GETBOOTSTATUS ioctl()s. WDIOC_GETSTATUS returns the actual counter value | ||
| 49 | and WDIOC_GETBOOTSTATUS returns the value of TCO2 Status Register (see Intel's | ||
| 50 | documentation for the 82801AA and 82801AB datasheet). | ||
| 51 | |||
| 52 | Features | ||
| 53 | -------- | ||
| 54 | WDT501P WDT500P Software Berkshire i810 TCO SA1100WD | ||
| 55 | Reboot Timer X X X X X X | ||
| 56 | External Reboot X X o o o X | ||
| 57 | I/O Port Monitor o o o X o o | ||
| 58 | Temperature X o o X o o | ||
| 59 | Fan Speed X o o o o o | ||
| 60 | Power Under X o o o o o | ||
| 61 | Power Over X o o o o o | ||
| 62 | Overheat X o o o o o | ||
| 63 | |||
| 64 | The external event interfaces on the WDT boards are not currently supported. | ||
| 65 | Minor numbers are however allocated for it. | ||
| 66 | |||
| 67 | |||
| 68 | Example Watchdog Driver: see Documentation/watchdog/src/watchdog-simple.c | ||
| 69 | |||
| 70 | |||
| 71 | Contact Information | ||
| 72 | |||
| 73 | People keep asking about the WDT watchdog timer hardware: The phone contacts | ||
| 74 | for Industrial Computer Source are: | ||
| 75 | |||
| 76 | Industrial Computer Source | ||
| 77 | http://www.indcompsrc.com | ||
| 78 | ICS Advent, San Diego | ||
| 79 | 6260 Sequence Dr. | ||
| 80 | San Diego, CA 92121-4371 | ||
| 81 | Phone (858) 677-0877 | ||
| 82 | FAX: (858) 677-0895 | ||
| 83 | > | ||
| 84 | ICS Advent Europe, UK | ||
| 85 | Oving Road | ||
| 86 | Chichester, | ||
| 87 | West Sussex, | ||
| 88 | PO19 4ET, UK | ||
| 89 | Phone: 00.44.1243.533900 | ||
| 90 | |||
| 91 | |||
| 92 | and please mention Linux when enquiring. | ||
| 93 | |||
| 94 | For full information about the PCWD cards see the pcwd-watchdog.txt document. | ||
diff --git a/Documentation/watchdog/wdt.txt b/Documentation/watchdog/wdt.txt new file mode 100644 index 000000000000..03fd756d976d --- /dev/null +++ b/Documentation/watchdog/wdt.txt | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | Last Reviewed: 10/05/2007 | ||
| 2 | |||
| 3 | WDT Watchdog Timer Interfaces For The Linux Operating System | ||
| 4 | Alan Cox <alan@lxorguk.ukuu.org.uk> | ||
| 5 | |||
| 6 | ICS WDT501-P | ||
| 7 | ICS WDT501-P (no fan tachometer) | ||
| 8 | ICS WDT500-P | ||
| 9 | |||
| 10 | All the interfaces provide /dev/watchdog, which when open must be written | ||
| 11 | to within a timeout or the machine will reboot. Each write delays the reboot | ||
| 12 | time another timeout. In the case of the software watchdog the ability to | ||
| 13 | reboot will depend on the state of the machines and interrupts. The hardware | ||
| 14 | boards physically pull the machine down off their own onboard timers and | ||
| 15 | will reboot from almost anything. | ||
| 16 | |||
| 17 | A second temperature monitoring interface is available on the WDT501P cards | ||
| 18 | This provides /dev/temperature. This is the machine internal temperature in | ||
| 19 | degrees Fahrenheit. Each read returns a single byte giving the temperature. | ||
| 20 | |||
| 21 | The third interface logs kernel messages on additional alert events. | ||
| 22 | |||
| 23 | The wdt card cannot be safely probed for. Instead you need to pass | ||
| 24 | wdt=ioaddr,irq as a boot parameter - eg "wdt=0x240,11". | ||
| 25 | |||
| 26 | Features | ||
| 27 | -------- | ||
| 28 | WDT501P WDT500P | ||
| 29 | Reboot Timer X X | ||
| 30 | External Reboot X X | ||
| 31 | I/O Port Monitor o o | ||
| 32 | Temperature X o | ||
| 33 | Fan Speed X o | ||
| 34 | Power Under X o | ||
| 35 | Power Over X o | ||
| 36 | Overheat X o | ||
| 37 | |||
| 38 | The external event interfaces on the WDT boards are not currently supported. | ||
| 39 | Minor numbers are however allocated for it. | ||
| 40 | |||
| 41 | |||
| 42 | Example Watchdog Driver: see Documentation/watchdog/src/watchdog-simple.c | ||
| 43 | |||
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 1cad32c62ed3..53f5538c0c05 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
| @@ -115,6 +115,13 @@ config IXP4XX_WATCHDOG | |||
| 115 | 115 | ||
| 116 | Say N if you are unsure. | 116 | Say N if you are unsure. |
| 117 | 117 | ||
| 118 | config KS8695_WATCHDOG | ||
| 119 | tristate "KS8695 watchdog" | ||
| 120 | depends on ARCH_KS8695 | ||
| 121 | help | ||
| 122 | Watchdog timer embedded into KS8695 processor. This will reboot your | ||
| 123 | system when the timeout is reached. | ||
| 124 | |||
| 118 | config S3C2410_WATCHDOG | 125 | config S3C2410_WATCHDOG |
| 119 | tristate "S3C2410 Watchdog" | 126 | tristate "S3C2410 Watchdog" |
| 120 | depends on ARCH_S3C2410 | 127 | depends on ARCH_S3C2410 |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 8bfc00cc7c2b..d90f649038c2 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
| @@ -29,6 +29,7 @@ obj-$(CONFIG_21285_WATCHDOG) += wdt285.o | |||
| 29 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o | 29 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o |
| 30 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o | 30 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o |
| 31 | obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o | 31 | obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o |
| 32 | obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o | ||
| 32 | obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o | 33 | obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o |
| 33 | obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o | 34 | obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o |
| 34 | obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o | 35 | obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o |
diff --git a/drivers/char/watchdog/ks8695_wdt.c b/drivers/char/watchdog/ks8695_wdt.c new file mode 100644 index 000000000000..7150fb945eaf --- /dev/null +++ b/drivers/char/watchdog/ks8695_wdt.c | |||
| @@ -0,0 +1,308 @@ | |||
| 1 | /* | ||
| 2 | * Watchdog driver for Kendin/Micrel KS8695. | ||
| 3 | * | ||
| 4 | * (C) 2007 Andrew Victor | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/errno.h> | ||
| 12 | #include <linux/fs.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/miscdevice.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/moduleparam.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | #include <linux/watchdog.h> | ||
| 21 | #include <asm/bitops.h> | ||
| 22 | #include <asm/io.h> | ||
| 23 | #include <asm/uaccess.h> | ||
| 24 | #include <asm/arch/regs-timer.h> | ||
| 25 | |||
| 26 | |||
| 27 | #define WDT_DEFAULT_TIME 5 /* seconds */ | ||
| 28 | #define WDT_MAX_TIME 171 /* seconds */ | ||
| 29 | |||
| 30 | static int wdt_time = WDT_DEFAULT_TIME; | ||
| 31 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
| 32 | |||
| 33 | module_param(wdt_time, int, 0); | ||
| 34 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); | ||
| 35 | |||
| 36 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | ||
| 37 | module_param(nowayout, int, 0); | ||
| 38 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
| 39 | #endif | ||
| 40 | |||
| 41 | |||
| 42 | static unsigned long ks8695wdt_busy; | ||
| 43 | |||
| 44 | /* ......................................................................... */ | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Disable the watchdog. | ||
| 48 | */ | ||
| 49 | static void inline ks8695_wdt_stop(void) | ||
| 50 | { | ||
| 51 | unsigned long tmcon; | ||
| 52 | |||
| 53 | /* disable timer0 */ | ||
| 54 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); | ||
| 55 | __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); | ||
| 56 | } | ||
| 57 | |||
| 58 | /* | ||
| 59 | * Enable and reset the watchdog. | ||
| 60 | */ | ||
| 61 | static void inline ks8695_wdt_start(void) | ||
| 62 | { | ||
| 63 | unsigned long tmcon; | ||
| 64 | unsigned long tval = wdt_time * CLOCK_TICK_RATE; | ||
| 65 | |||
| 66 | /* disable timer0 */ | ||
| 67 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); | ||
| 68 | __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); | ||
| 69 | |||
| 70 | /* program timer0 */ | ||
| 71 | __raw_writel(tval | T0TC_WATCHDOG, KS8695_TMR_VA + KS8695_T0TC); | ||
| 72 | |||
| 73 | /* re-enable timer0 */ | ||
| 74 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); | ||
| 75 | __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); | ||
| 76 | } | ||
| 77 | |||
| 78 | /* | ||
| 79 | * Reload the watchdog timer. (ie, pat the watchdog) | ||
| 80 | */ | ||
| 81 | static void inline ks8695_wdt_reload(void) | ||
| 82 | { | ||
| 83 | unsigned long tmcon; | ||
| 84 | |||
| 85 | /* disable, then re-enable timer0 */ | ||
| 86 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); | ||
| 87 | __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); | ||
| 88 | __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); | ||
| 89 | } | ||
| 90 | |||
| 91 | /* | ||
| 92 | * Change the watchdog time interval. | ||
| 93 | */ | ||
| 94 | static int ks8695_wdt_settimeout(int new_time) | ||
| 95 | { | ||
| 96 | /* | ||
| 97 | * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz | ||
| 98 | * | ||
| 99 | * Since WDV is a 16-bit counter, the maximum period is | ||
| 100 | * 65536 / 0.256 = 256 seconds. | ||
| 101 | */ | ||
| 102 | if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) | ||
| 103 | return -EINVAL; | ||
| 104 | |||
| 105 | /* Set new watchdog time. It will be used when ks8695_wdt_start() is called. */ | ||
| 106 | wdt_time = new_time; | ||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | /* ......................................................................... */ | ||
| 111 | |||
| 112 | /* | ||
| 113 | * Watchdog device is opened, and watchdog starts running. | ||
| 114 | */ | ||
| 115 | static int ks8695_wdt_open(struct inode *inode, struct file *file) | ||
| 116 | { | ||
| 117 | if (test_and_set_bit(0, &ks8695wdt_busy)) | ||
| 118 | return -EBUSY; | ||
| 119 | |||
| 120 | ks8695_wdt_start(); | ||
| 121 | return nonseekable_open(inode, file); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Close the watchdog device. | ||
| 126 | * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also | ||
| 127 | * disabled. | ||
| 128 | */ | ||
| 129 | static int ks8695_wdt_close(struct inode *inode, struct file *file) | ||
| 130 | { | ||
| 131 | if (!nowayout) | ||
| 132 | ks8695_wdt_stop(); /* Disable the watchdog when file is closed */ | ||
| 133 | |||
| 134 | clear_bit(0, &ks8695wdt_busy); | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | static struct watchdog_info ks8695_wdt_info = { | ||
| 139 | .identity = "ks8695 watchdog", | ||
| 140 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | ||
| 141 | }; | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Handle commands from user-space. | ||
| 145 | */ | ||
| 146 | static int ks8695_wdt_ioctl(struct inode *inode, struct file *file, | ||
| 147 | unsigned int cmd, unsigned long arg) | ||
| 148 | { | ||
| 149 | void __user *argp = (void __user *)arg; | ||
| 150 | int __user *p = argp; | ||
| 151 | int new_value; | ||
| 152 | |||
| 153 | switch(cmd) { | ||
| 154 | case WDIOC_KEEPALIVE: | ||
| 155 | ks8695_wdt_reload(); /* pat the watchdog */ | ||
| 156 | return 0; | ||
| 157 | |||
| 158 | case WDIOC_GETSUPPORT: | ||
| 159 | return copy_to_user(argp, &ks8695_wdt_info, sizeof(ks8695_wdt_info)) ? -EFAULT : 0; | ||
| 160 | |||
| 161 | case WDIOC_SETTIMEOUT: | ||
| 162 | if (get_user(new_value, p)) | ||
| 163 | return -EFAULT; | ||
| 164 | |||
| 165 | if (ks8695_wdt_settimeout(new_value)) | ||
| 166 | return -EINVAL; | ||
| 167 | |||
| 168 | /* Enable new time value */ | ||
| 169 | ks8695_wdt_start(); | ||
| 170 | |||
| 171 | /* Return current value */ | ||
| 172 | return put_user(wdt_time, p); | ||
| 173 | |||
| 174 | case WDIOC_GETTIMEOUT: | ||
| 175 | return put_user(wdt_time, p); | ||
| 176 | |||
| 177 | case WDIOC_GETSTATUS: | ||
| 178 | case WDIOC_GETBOOTSTATUS: | ||
| 179 | return put_user(0, p); | ||
| 180 | |||
| 181 | case WDIOC_SETOPTIONS: | ||
| 182 | if (get_user(new_value, p)) | ||
| 183 | return -EFAULT; | ||
| 184 | |||
| 185 | if (new_value & WDIOS_DISABLECARD) | ||
| 186 | ks8695_wdt_stop(); | ||
| 187 | if (new_value & WDIOS_ENABLECARD) | ||
| 188 | ks8695_wdt_start(); | ||
| 189 | return 0; | ||
| 190 | |||
| 191 | default: | ||
| 192 | return -ENOTTY; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | /* | ||
| 197 | * Pat the watchdog whenever device is written to. | ||
| 198 | */ | ||
| 199 | static ssize_t ks8695_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | ||
| 200 | { | ||
| 201 | ks8695_wdt_reload(); /* pat the watchdog */ | ||
| 202 | return len; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* ......................................................................... */ | ||
| 206 | |||
| 207 | static const struct file_operations ks8695wdt_fops = { | ||
| 208 | .owner = THIS_MODULE, | ||
| 209 | .llseek = no_llseek, | ||
| 210 | .ioctl = ks8695_wdt_ioctl, | ||
| 211 | .open = ks8695_wdt_open, | ||
| 212 | .release = ks8695_wdt_close, | ||
| 213 | .write = ks8695_wdt_write, | ||
| 214 | }; | ||
| 215 | |||
| 216 | static struct miscdevice ks8695wdt_miscdev = { | ||
| 217 | .minor = WATCHDOG_MINOR, | ||
| 218 | .name = "watchdog", | ||
| 219 | .fops = &ks8695wdt_fops, | ||
| 220 | }; | ||
| 221 | |||
| 222 | static int __init ks8695wdt_probe(struct platform_device *pdev) | ||
| 223 | { | ||
| 224 | int res; | ||
| 225 | |||
| 226 | if (ks8695wdt_miscdev.parent) | ||
| 227 | return -EBUSY; | ||
| 228 | ks8695wdt_miscdev.parent = &pdev->dev; | ||
| 229 | |||
| 230 | res = misc_register(&ks8695wdt_miscdev); | ||
| 231 | if (res) | ||
| 232 | return res; | ||
| 233 | |||
| 234 | printk("KS8695 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); | ||
| 235 | return 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | static int __exit ks8695wdt_remove(struct platform_device *pdev) | ||
| 239 | { | ||
| 240 | int res; | ||
| 241 | |||
| 242 | res = misc_deregister(&ks8695wdt_miscdev); | ||
| 243 | if (!res) | ||
| 244 | ks8695wdt_miscdev.parent = NULL; | ||
| 245 | |||
| 246 | return res; | ||
| 247 | } | ||
| 248 | |||
| 249 | static void ks8695wdt_shutdown(struct platform_device *pdev) | ||
| 250 | { | ||
| 251 | ks8695_wdt_stop(); | ||
| 252 | } | ||
| 253 | |||
| 254 | #ifdef CONFIG_PM | ||
| 255 | |||
| 256 | static int ks8695wdt_suspend(struct platform_device *pdev, pm_message_t message) | ||
| 257 | { | ||
| 258 | ks8695_wdt_stop(); | ||
| 259 | return 0; | ||
| 260 | } | ||
| 261 | |||
| 262 | static int ks8695wdt_resume(struct platform_device *pdev) | ||
| 263 | { | ||
| 264 | if (ks8695wdt_busy) | ||
| 265 | ks8695_wdt_start(); | ||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | #else | ||
| 270 | #define ks8695wdt_suspend NULL | ||
| 271 | #define ks8695wdt_resume NULL | ||
| 272 | #endif | ||
| 273 | |||
| 274 | static struct platform_driver ks8695wdt_driver = { | ||
| 275 | .probe = ks8695wdt_probe, | ||
| 276 | .remove = __exit_p(ks8695wdt_remove), | ||
| 277 | .shutdown = ks8695wdt_shutdown, | ||
| 278 | .suspend = ks8695wdt_suspend, | ||
| 279 | .resume = ks8695wdt_resume, | ||
| 280 | .driver = { | ||
| 281 | .name = "ks8695_wdt", | ||
| 282 | .owner = THIS_MODULE, | ||
| 283 | }, | ||
| 284 | }; | ||
| 285 | |||
| 286 | static int __init ks8695_wdt_init(void) | ||
| 287 | { | ||
| 288 | /* Check that the heartbeat value is within range; if not reset to the default */ | ||
| 289 | if (ks8695_wdt_settimeout(wdt_time)) { | ||
| 290 | 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); | ||
| 292 | } | ||
| 293 | |||
| 294 | return platform_driver_register(&ks8695wdt_driver); | ||
| 295 | } | ||
| 296 | |||
| 297 | static void __exit ks8695_wdt_exit(void) | ||
| 298 | { | ||
| 299 | platform_driver_unregister(&ks8695wdt_driver); | ||
| 300 | } | ||
| 301 | |||
| 302 | module_init(ks8695_wdt_init); | ||
| 303 | module_exit(ks8695_wdt_exit); | ||
| 304 | |||
| 305 | MODULE_AUTHOR("Andrew Victor"); | ||
| 306 | MODULE_DESCRIPTION("Watchdog driver for KS8695"); | ||
| 307 | MODULE_LICENSE("GPL"); | ||
| 308 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
