it87_wdt.c revision a134b825608df6382dbcf4fe2c54232ba8f7355f
1e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* 2e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Watchdog Timer Driver 3e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * for ITE IT87xx Environment Control - Low Pin Count Input / Output 4e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 5e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * (c) Copyright 2007 Oliver Schuster <olivers137@aol.com> 6e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 7e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Based on softdog.c by Alan Cox, 8e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 83977f_wdt.c by Jose Goncalves, 9e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * it87.c by Chris Gauthron, Jean Delvare 10e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 11e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Data-sheets: Publicly available at the ITE website 12e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * http://www.ite.com.tw/ 13e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 14e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Support of the watchdog timers, which are available on 154bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomita * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721 and IT8726. 16e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 17e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * This program is free software; you can redistribute it and/or 18e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * modify it under the terms of the GNU General Public License 19e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * as published by the Free Software Foundation; either version 20e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 2 of the License, or (at your option) any later version. 21e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 22e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * This program is distributed in the hope that it will be useful, 23e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * but WITHOUT ANY WARRANTY; without even the implied warranty of 24e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * GNU General Public License for more details. 26e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 27e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * You should have received a copy of the GNU General Public License 28e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * along with this program; if not, write to the Free Software 29e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 30e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster */ 31e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 32e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/module.h> 33e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/moduleparam.h> 34e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/types.h> 35e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/kernel.h> 36e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/fs.h> 37e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/miscdevice.h> 38e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/init.h> 39e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/ioport.h> 40e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/watchdog.h> 41e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/notifier.h> 42e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/reboot.h> 43e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/uaccess.h> 44e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <linux/io.h> 45e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 46e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#include <asm/system.h> 47e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 484bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomita#define WATCHDOG_VERSION "1.14" 49e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WATCHDOG_NAME "IT87 WDT" 50e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define PFX WATCHDOG_NAME ": " 51e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" 52e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WD_MAGIC 'V' 53e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 54e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* Defaults for Module Parameter */ 55e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define DEFAULT_NOGAMEPORT 0 56e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define DEFAULT_EXCLUSIVE 1 575f3b27569fc0286a51f8d0655c7fb4f5b36aea65Wim Van Sebroeck#define DEFAULT_TIMEOUT 60 58e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define DEFAULT_TESTMODE 0 59e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define DEFAULT_NOWAYOUT WATCHDOG_NOWAYOUT 60e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 61e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* IO Ports */ 62e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define REG 0x2e 63e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define VAL 0x2f 64e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 65e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* Logical device Numbers LDN */ 66e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define GPIO 0x07 67e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define GAMEPORT 0x09 68e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR 0x0a 69e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 70e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* Configuration Registers and Functions */ 71e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define LDNREG 0x07 72e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CHIPID 0x20 735f3b27569fc0286a51f8d0655c7fb4f5b36aea65Wim Van Sebroeck#define CHIPREV 0x22 74e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define ACTREG 0x30 755f3b27569fc0286a51f8d0655c7fb4f5b36aea65Wim Van Sebroeck#define BASEREG 0x60 76e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 77e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* Chip Id numbers */ 78e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define NO_DEV_ID 0xffff 79dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek#define IT8702_ID 0x8702 80e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define IT8705_ID 0x8705 81e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define IT8712_ID 0x8712 82e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define IT8716_ID 0x8716 83e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define IT8718_ID 0x8718 84ee3e96583e42dcb4bd406ce4e5f824bd5bb80013Ondrej Zajicek#define IT8720_ID 0x8720 854bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomita#define IT8721_ID 0x8721 86e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ 87e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 88e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* GPIO Configuration Registers LDN=0x07 */ 895f3b27569fc0286a51f8d0655c7fb4f5b36aea65Wim Van Sebroeck#define WDTCTRL 0x71 90e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDTCFG 0x72 91e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDTVALLSB 0x73 92e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDTVALMSB 0x74 93e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 94e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* GPIO Bits WDTCTRL */ 95e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDT_CIRINT 0x80 96e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDT_MOUSEINT 0x40 97e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDT_KYBINT 0x20 984bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomita#define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721 */ 99e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDT_FORCE 0x02 100e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDT_ZERO 0x01 101e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 102e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* GPIO Bits WDTCFG */ 103e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDT_TOV1 0x80 104e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDT_KRST 0x40 105e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDT_TOVE 0x20 1064bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomita#define WDT_PWROK 0x10 /* not in it8721 */ 107e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDT_INT_MASK 0x0f 108e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 109e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* CIR Configuration Register LDN=0x0a */ 1105f3b27569fc0286a51f8d0655c7fb4f5b36aea65Wim Van Sebroeck#define CIR_ILS 0x70 111e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 112e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* The default Base address is not always available, we use this */ 113e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_BASE 0x0208 114e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 115e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* CIR Controller */ 116e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_DR(b) (b) 117e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_IER(b) (b + 1) 118e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_RCR(b) (b + 2) 119e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_TCR1(b) (b + 3) 120e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_TCR2(b) (b + 4) 121e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_TSR(b) (b + 5) 122e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_RSR(b) (b + 6) 123e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_BDLR(b) (b + 5) 124e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_BDHR(b) (b + 6) 125e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define CIR_IIR(b) (b + 7) 126e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 127e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* Default Base address of Game port */ 128e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define GP_BASE_DEFAULT 0x0201 129e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 130e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* wdt_status */ 131e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDTS_TIMER_RUN 0 132e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDTS_DEV_OPEN 1 133e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDTS_KEEPALIVE 2 134e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDTS_LOCKED 3 135e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDTS_USE_GP 4 136e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster#define WDTS_EXPECTED 5 137e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 1384bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomitastatic unsigned int base, gpact, ciract, max_units, chip_type; 139e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic unsigned long wdt_status; 140e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 141e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int nogameport = DEFAULT_NOGAMEPORT; 142e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int exclusive = DEFAULT_EXCLUSIVE; 143e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int timeout = DEFAULT_TIMEOUT; 144e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int testmode = DEFAULT_TESTMODE; 145e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int nowayout = DEFAULT_NOWAYOUT; 146e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 147e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schustermodule_param(nogameport, int, 0); 148e1fee94f346387739e683b31815ab54dc0a30bd6Oliver SchusterMODULE_PARM_DESC(nogameport, "Forbid the activation of game port, default=" 149e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster __MODULE_STRING(DEFAULT_NOGAMEPORT)); 150e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schustermodule_param(exclusive, int, 0); 151e1fee94f346387739e683b31815ab54dc0a30bd6Oliver SchusterMODULE_PARM_DESC(exclusive, "Watchdog exclusive device open, default=" 152e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster __MODULE_STRING(DEFAULT_EXCLUSIVE)); 153e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schustermodule_param(timeout, int, 0); 154e1fee94f346387739e683b31815ab54dc0a30bd6Oliver SchusterMODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default=" 155e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster __MODULE_STRING(DEFAULT_TIMEOUT)); 156e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schustermodule_param(testmode, int, 0); 157e1fee94f346387739e683b31815ab54dc0a30bd6Oliver SchusterMODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default=" 158e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster __MODULE_STRING(DEFAULT_TESTMODE)); 159e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schustermodule_param(nowayout, int, 0); 160e1fee94f346387739e683b31815ab54dc0a30bd6Oliver SchusterMODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default=" 161e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster __MODULE_STRING(WATCHDOG_NOWAYOUT)); 162e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 163e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* Superio Chip */ 164e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 165a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthystatic inline int superio_enter(void) 166e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 167a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy /* 168a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy * Try to reserve REG and REG + 1 for exclusive access. 169a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy */ 170a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (!request_muxed_region(REG, 2, WATCHDOG_NAME)) 171a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return -EBUSY; 172a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy 173e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x87, REG); 174e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x01, REG); 175e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x55, REG); 176e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x55, REG); 177a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return 0; 178e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 179e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 180e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic inline void superio_exit(void) 181e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 182e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x02, REG); 183e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x02, VAL); 184a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy release_region(REG, 2); 185e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 186e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 187e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic inline void superio_select(int ldn) 188e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 189e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(LDNREG, REG); 190e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(ldn, VAL); 191e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 192e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 193e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic inline int superio_inb(int reg) 194e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 195e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(reg, REG); 196e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return inb(VAL); 197e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 198e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 199e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic inline void superio_outb(int val, int reg) 200e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 201143a2e54bf53216674eada16e8953f48b159e08aWim Van Sebroeck outb(reg, REG); 202143a2e54bf53216674eada16e8953f48b159e08aWim Van Sebroeck outb(val, VAL); 203e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 204e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 205e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic inline int superio_inw(int reg) 206e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 207e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster int val; 208e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(reg++, REG); 209e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster val = inb(VAL) << 8; 210e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(reg, REG); 211e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster val |= inb(VAL); 212e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return val; 213e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 214e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 215e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic inline void superio_outw(int val, int reg) 216e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 217143a2e54bf53216674eada16e8953f48b159e08aWim Van Sebroeck outb(reg++, REG); 218143a2e54bf53216674eada16e8953f48b159e08aWim Van Sebroeck outb(val >> 8, VAL); 219143a2e54bf53216674eada16e8953f48b159e08aWim Van Sebroeck outb(reg, REG); 220143a2e54bf53216674eada16e8953f48b159e08aWim Van Sebroeck outb(val, VAL); 221e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 222e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 223dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek/* Internal function, should be called after superio_select(GPIO) */ 224dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicekstatic void wdt_update_timeout(void) 225dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek{ 2264bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomita unsigned char cfg = WDT_KRST; 227dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek int tm = timeout; 228dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek 229dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek if (testmode) 230dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek cfg = 0; 231dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek 232dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek if (tm <= max_units) 233dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek cfg |= WDT_TOV1; 234dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek else 235dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek tm /= 60; 236dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek 2374bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomita if (chip_type != IT8721_ID) 2384bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomita cfg |= WDT_PWROK; 2394bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomita 240dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek superio_outb(cfg, WDTCFG); 241dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek superio_outb(tm, WDTVALLSB); 242dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek if (max_units > 255) 243dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek superio_outb(tm>>8, WDTVALMSB); 244dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek} 245dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek 246dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicekstatic int wdt_round_time(int t) 247dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek{ 248dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek t += 59; 249dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek t -= t % 60; 250dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek return t; 251dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek} 252dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek 253e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* watchdog timer handling */ 254e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 255e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic void wdt_keepalive(void) 256e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 257e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (test_bit(WDTS_USE_GP, &wdt_status)) 258e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster inb(base); 259e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster else 260e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster /* The timer reloads with around 5 msec delay */ 261e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x55, CIR_DR(base)); 262e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster set_bit(WDTS_KEEPALIVE, &wdt_status); 263e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 264e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 265a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthystatic int wdt_start(void) 266e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 267a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy int ret = superio_enter(); 268a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (ret) 269a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return ret; 270e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 271e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_select(GPIO); 272e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (test_bit(WDTS_USE_GP, &wdt_status)) 273e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(WDT_GAMEPORT, WDTCTRL); 274e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster else 275e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(WDT_CIRINT, WDTCTRL); 276dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek wdt_update_timeout(); 277e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 278e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_exit(); 279a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy 280a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return 0; 281e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 282e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 283a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthystatic int wdt_stop(void) 284e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 285a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy int ret = superio_enter(); 286a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (ret) 287a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return ret; 288e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 289e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_select(GPIO); 290e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(0x00, WDTCTRL); 291e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(WDT_TOV1, WDTCFG); 292e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(0x00, WDTVALLSB); 293dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek if (max_units > 255) 294dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek superio_outb(0x00, WDTVALMSB); 295e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 296e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_exit(); 297a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return 0; 298e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 299e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 300e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/** 301e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * wdt_set_timeout - set a new timeout value with watchdog ioctl 302e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @t: timeout value in seconds 303e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 304dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek * The hardware device has a 8 or 16 bit watchdog timer (depends on 305dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek * chip version) that can be configured to count seconds or minutes. 306e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 307e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Used within WDIOC_SETTIMEOUT watchdog device ioctl. 308e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster */ 309e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 310e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int wdt_set_timeout(int t) 311e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 312dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek if (t < 1 || t > max_units * 60) 313e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -EINVAL; 314e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 315dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek if (t > max_units) 316dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek timeout = wdt_round_time(t); 317dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek else 318dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek timeout = t; 319e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 320e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { 321a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy int ret = superio_enter(); 322a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (ret) 323a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return ret; 324a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy 325e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_select(GPIO); 326dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek wdt_update_timeout(); 327e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_exit(); 328e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 329e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return 0; 330e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 331e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 332e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/** 333e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * wdt_get_status - determines the status supported by watchdog ioctl 334e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @status: status returned to user space 335e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 336e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * The status bit of the device does not allow to distinguish 337e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * between a regular system reset and a watchdog forced reset. 338e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * But, in test mode it is useful, so it is supported through 339e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * WDIOC_GETSTATUS watchdog ioctl. Additionally the driver 340e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * reports the keepalive signal and the acception of the magic. 341e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 342e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Used within WDIOC_GETSTATUS watchdog device ioctl. 343e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster */ 344e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 345e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int wdt_get_status(int *status) 346e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 347e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster *status = 0; 348e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (testmode) { 349a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy int ret = superio_enter(); 350a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (ret) 351a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return ret; 352a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy 353e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_select(GPIO); 354e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (superio_inb(WDTCTRL) & WDT_ZERO) { 355e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(0x00, WDTCTRL); 356e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster clear_bit(WDTS_TIMER_RUN, &wdt_status); 357e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster *status |= WDIOF_CARDRESET; 358e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 359e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 360e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_exit(); 361e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 362e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (test_and_clear_bit(WDTS_KEEPALIVE, &wdt_status)) 363e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster *status |= WDIOF_KEEPALIVEPING; 364e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (test_bit(WDTS_EXPECTED, &wdt_status)) 365e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster *status |= WDIOF_MAGICCLOSE; 366e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return 0; 367e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 368e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 369e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/* /dev/watchdog handling */ 370e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 371e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/** 372e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * wdt_open - watchdog file_operations .open 373e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @inode: inode of the device 374e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @file: file handle to the device 375e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 376e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * The watchdog timer starts by opening the device. 377e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 378e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Used within the file operation of the watchdog device. 379e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster */ 380e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 381e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int wdt_open(struct inode *inode, struct file *file) 382e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 383e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (exclusive && test_and_set_bit(WDTS_DEV_OPEN, &wdt_status)) 384e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -EBUSY; 385e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) { 386a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy int ret; 387e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (nowayout && !test_and_set_bit(WDTS_LOCKED, &wdt_status)) 388e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster __module_get(THIS_MODULE); 389a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy 390a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy ret = wdt_start(); 391a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (ret) { 392a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy clear_bit(WDTS_LOCKED, &wdt_status); 393a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy clear_bit(WDTS_TIMER_RUN, &wdt_status); 394a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy clear_bit(WDTS_DEV_OPEN, &wdt_status); 395a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return ret; 396a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy } 397e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 398e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return nonseekable_open(inode, file); 399e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 400e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 401e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/** 402e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * wdt_release - watchdog file_operations .release 403e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @inode: inode of the device 404e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @file: file handle to the device 405e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 406e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Closing the watchdog device either stops the watchdog timer 407e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * or in the case, that nowayout is set or the magic character 408e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * wasn't written, a critical warning about an running watchdog 409e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * timer is given. 410e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 411e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Used within the file operation of the watchdog device. 412e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster */ 413e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 414e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int wdt_release(struct inode *inode, struct file *file) 415e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 416e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { 417e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (test_and_clear_bit(WDTS_EXPECTED, &wdt_status)) { 418a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy int ret = wdt_stop(); 419a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (ret) { 420a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy /* 421a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy * Stop failed. Just keep the watchdog alive 422a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy * and hope nothing bad happens. 423a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy */ 424a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy set_bit(WDTS_EXPECTED, &wdt_status); 425a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy wdt_keepalive(); 426a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return ret; 427a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy } 428e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster clear_bit(WDTS_TIMER_RUN, &wdt_status); 429e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } else { 430e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster wdt_keepalive(); 431e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster printk(KERN_CRIT PFX 432e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster "unexpected close, not stopping watchdog!\n"); 433e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 434e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 435e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster clear_bit(WDTS_DEV_OPEN, &wdt_status); 436e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return 0; 437e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 438e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 439e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/** 440e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * wdt_write - watchdog file_operations .write 441e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @file: file handle to the watchdog 442e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @buf: buffer to write 443e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @count: count of bytes 444e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @ppos: pointer to the position to write. No seeks allowed 445e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 446e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * A write to a watchdog device is defined as a keepalive signal. Any 447e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * write of data will do, as we don't define content meaning. 448e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 449e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Used within the file operation of the watchdog device. 450e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster */ 451e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 452e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic ssize_t wdt_write(struct file *file, const char __user *buf, 453e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster size_t count, loff_t *ppos) 454e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 455e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (count) { 456e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster clear_bit(WDTS_EXPECTED, &wdt_status); 457e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster wdt_keepalive(); 458e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 459e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (!nowayout) { 460e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster size_t ofs; 461e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 462e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster /* note: just in case someone wrote the magic character long ago */ 463e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster for (ofs = 0; ofs != count; ofs++) { 464e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster char c; 465e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (get_user(c, buf + ofs)) 466e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -EFAULT; 467e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (c == WD_MAGIC) 468e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster set_bit(WDTS_EXPECTED, &wdt_status); 469e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 470e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 471e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return count; 472e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 473e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 47442747d712de56cf2087b702d2ad90af114c53138Wim Van Sebroeckstatic const struct watchdog_info ident = { 475e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, 476e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .firmware_version = 1, 477e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .identity = WATCHDOG_NAME, 478e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster}; 479e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 480e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster/** 481e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * wdt_ioctl - watchdog file_operations .unlocked_ioctl 482e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @file: file handle to the device 483e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @cmd: watchdog command 484e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * @arg: argument pointer 485e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 486e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * The watchdog API defines a common set of functions for all watchdogs 487e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * according to their available features. 488e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * 489e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster * Used within the file operation of the watchdog device. 490e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster */ 491e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 492e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 493e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 494e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster int rc = 0, status, new_options, new_timeout; 495e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster union { 496e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster struct watchdog_info __user *ident; 497e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster int __user *i; 498e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } uarg; 499e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 500e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster uarg.i = (int __user *)arg; 501e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 502e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster switch (cmd) { 503e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case WDIOC_GETSUPPORT: 504e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return copy_to_user(uarg.ident, 505e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster &ident, sizeof(ident)) ? -EFAULT : 0; 506e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 507e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case WDIOC_GETSTATUS: 508a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy rc = wdt_get_status(&status); 509a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (rc) 510a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return rc; 511e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return put_user(status, uarg.i); 512e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 513e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case WDIOC_GETBOOTSTATUS: 514e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return put_user(0, uarg.i); 515e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 516e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case WDIOC_KEEPALIVE: 517e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster wdt_keepalive(); 518e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return 0; 519e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 520e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case WDIOC_SETOPTIONS: 521e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (get_user(new_options, uarg.i)) 522e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -EFAULT; 523e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 524e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster switch (new_options) { 525e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case WDIOS_DISABLECARD: 526a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { 527a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy rc = wdt_stop(); 528a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (rc) 529a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return rc; 530a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy } 531e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster clear_bit(WDTS_TIMER_RUN, &wdt_status); 532e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return 0; 533e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 534e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case WDIOS_ENABLECARD: 535a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) { 536a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy rc = wdt_start(); 537a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (rc) { 538a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy clear_bit(WDTS_TIMER_RUN, &wdt_status); 539a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return rc; 540a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy } 541a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy } 542e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return 0; 543e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 544e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster default: 545e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -EFAULT; 546e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 547e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 548e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case WDIOC_SETTIMEOUT: 549e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (get_user(new_timeout, uarg.i)) 550e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -EFAULT; 551e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster rc = wdt_set_timeout(new_timeout); 552e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case WDIOC_GETTIMEOUT: 553e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (put_user(timeout, uarg.i)) 554e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -EFAULT; 555e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return rc; 556e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 557e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster default: 558e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -ENOTTY; 559e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 560e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 561e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 562e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int wdt_notify_sys(struct notifier_block *this, unsigned long code, 563e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster void *unused) 564e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 565e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (code == SYS_DOWN || code == SYS_HALT) 566e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster wdt_stop(); 567e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return NOTIFY_DONE; 568e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 569e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 570e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic const struct file_operations wdt_fops = { 571e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .owner = THIS_MODULE, 572e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .llseek = no_llseek, 573e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .write = wdt_write, 574e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .unlocked_ioctl = wdt_ioctl, 575e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .open = wdt_open, 576e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .release = wdt_release, 577e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster}; 578e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 579e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic struct miscdevice wdt_miscdev = { 580e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .minor = WATCHDOG_MINOR, 581e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .name = "watchdog", 582e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .fops = &wdt_fops, 583e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster}; 584e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 585e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic struct notifier_block wdt_notifier = { 586e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster .notifier_call = wdt_notify_sys, 587e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster}; 588e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 589e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic int __init it87_wdt_init(void) 590e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 591e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster int rc = 0; 592ee3e96583e42dcb4bd406ce4e5f824bd5bb80013Ondrej Zajicek int try_gameport = !nogameport; 593e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster u8 chip_rev; 594a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy int gp_rreq_fail = 0; 595e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 596dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek wdt_status = 0; 597dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek 598a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy rc = superio_enter(); 599a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (rc) 600a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return rc; 601a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy 602e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster chip_type = superio_inw(CHIPID); 603e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster chip_rev = superio_inb(CHIPREV) & 0x0f; 604e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_exit(); 605e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 606e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster switch (chip_type) { 607dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek case IT8702_ID: 608dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek max_units = 255; 609dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek break; 610dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek case IT8712_ID: 611dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek max_units = (chip_rev < 8) ? 255 : 65535; 612dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek break; 613e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case IT8716_ID: 614e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case IT8726_ID: 615dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek max_units = 65535; 616e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster break; 617ee3e96583e42dcb4bd406ce4e5f824bd5bb80013Ondrej Zajicek case IT8718_ID: 618ee3e96583e42dcb4bd406ce4e5f824bd5bb80013Ondrej Zajicek case IT8720_ID: 6194bc30272a15c58fc358bde093703d23bc0cf8e66Huaro Tomita case IT8721_ID: 620dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek max_units = 65535; 621ee3e96583e42dcb4bd406ce4e5f824bd5bb80013Ondrej Zajicek try_gameport = 0; 622ee3e96583e42dcb4bd406ce4e5f824bd5bb80013Ondrej Zajicek break; 623e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case IT8705_ID: 624e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster printk(KERN_ERR PFX 625e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster "Unsupported Chip found, Chip %04x Revision %02x\n", 626e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster chip_type, chip_rev); 627e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -ENODEV; 628e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster case NO_DEV_ID: 629e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster printk(KERN_ERR PFX "no device\n"); 630e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -ENODEV; 631e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster default: 632e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster printk(KERN_ERR PFX 633e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster "Unknown Chip found, Chip %04x Revision %04x\n", 634e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster chip_type, chip_rev); 635e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return -ENODEV; 636e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 637e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 638a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy rc = superio_enter(); 639a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (rc) 640a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy return rc; 641e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 642e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_select(GPIO); 643e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(WDT_TOV1, WDTCFG); 644e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(0x00, WDTCTRL); 645e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 646e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster /* First try to get Gameport support */ 647ee3e96583e42dcb4bd406ce4e5f824bd5bb80013Ondrej Zajicek if (try_gameport) { 648e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_select(GAMEPORT); 649e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster base = superio_inw(BASEREG); 650e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (!base) { 651e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster base = GP_BASE_DEFAULT; 652e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outw(base, BASEREG); 653e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 654e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster gpact = superio_inb(ACTREG); 655e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(0x01, ACTREG); 656e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (request_region(base, 1, WATCHDOG_NAME)) 657e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster set_bit(WDTS_USE_GP, &wdt_status); 658e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster else 659a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy gp_rreq_fail = 1; 660e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 661e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 662e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster /* If we haven't Gameport support, try to get CIR support */ 663e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (!test_bit(WDTS_USE_GP, &wdt_status)) { 664e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) { 665a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (gp_rreq_fail) 666e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster printk(KERN_ERR PFX 667e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster "I/O Address 0x%04x and 0x%04x" 668e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster " already in use\n", base, CIR_BASE); 669e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster else 670e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster printk(KERN_ERR PFX 671e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster "I/O Address 0x%04x already in use\n", 672e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster CIR_BASE); 673e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster rc = -EIO; 674e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster goto err_out; 675e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 676e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster base = CIR_BASE; 677e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 678e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_select(CIR); 679e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outw(base, BASEREG); 680e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(0x00, CIR_ILS); 681e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster ciract = superio_inb(ACTREG); 682e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(0x01, ACTREG); 683a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (gp_rreq_fail) { 684e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_select(GAMEPORT); 685e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(gpact, ACTREG); 686e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 687e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 688e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 689dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek if (timeout < 1 || timeout > max_units * 60) { 690e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster timeout = DEFAULT_TIMEOUT; 691e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster printk(KERN_WARNING PFX 692e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster "Timeout value out of range, use default %d sec\n", 693e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster DEFAULT_TIMEOUT); 694e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 695e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 696dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek if (timeout > max_units) 697dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek timeout = wdt_round_time(timeout); 698dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek 699e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster rc = register_reboot_notifier(&wdt_notifier); 700e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (rc) { 701e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster printk(KERN_ERR PFX 702e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster "Cannot register reboot notifier (err=%d)\n", rc); 703e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster goto err_out_region; 704e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 705e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 706e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster rc = misc_register(&wdt_miscdev); 707e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (rc) { 708e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster printk(KERN_ERR PFX 709e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster "Cannot register miscdev on minor=%d (err=%d)\n", 710e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster wdt_miscdev.minor, rc); 711e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster goto err_out_reboot; 712e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 713e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 714e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster /* Initialize CIR to use it as keepalive source */ 715e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (!test_bit(WDTS_USE_GP, &wdt_status)) { 716e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x00, CIR_RCR(base)); 717e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0xc0, CIR_TCR1(base)); 718e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x5c, CIR_TCR2(base)); 719e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x10, CIR_IER(base)); 720e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x00, CIR_BDHR(base)); 721e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x01, CIR_BDLR(base)); 722e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster outb(0x09, CIR_IER(base)); 723e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 724e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 725dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50eOndrej Zajicek printk(KERN_INFO PFX "Chip IT%04x revision %d initialized. " 726e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d " 727e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster "nogameport=%d)\n", chip_type, chip_rev, timeout, 728e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster nowayout, testmode, exclusive, nogameport); 729e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 730a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_exit(); 731e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return 0; 732e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 733e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schustererr_out_reboot: 734e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster unregister_reboot_notifier(&wdt_notifier); 735e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schustererr_out_region: 736e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8); 737e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster if (!test_bit(WDTS_USE_GP, &wdt_status)) { 738e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_select(CIR); 739e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(ciract, ACTREG); 740e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 741e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schustererr_out: 742ee3e96583e42dcb4bd406ce4e5f824bd5bb80013Ondrej Zajicek if (try_gameport) { 743e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_select(GAMEPORT); 744e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster superio_outb(gpact, ACTREG); 745e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 746e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 747a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_exit(); 748e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster return rc; 749e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 750e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 751e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schusterstatic void __exit it87_wdt_exit(void) 752e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster{ 753a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (superio_enter() == 0) { 754a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_select(GPIO); 755a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_outb(0x00, WDTCTRL); 756a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_outb(0x00, WDTCFG); 757a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_outb(0x00, WDTVALLSB); 758a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (max_units > 255) 759a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_outb(0x00, WDTVALMSB); 760a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy if (test_bit(WDTS_USE_GP, &wdt_status)) { 761a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_select(GAMEPORT); 762a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_outb(gpact, ACTREG); 763a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy } else { 764a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_select(CIR); 765a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_outb(ciract, ACTREG); 766a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy } 767a134b825608df6382dbcf4fe2c54232ba8f7355fNat Gurumoorthy superio_exit(); 768e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster } 769e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 770e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster misc_deregister(&wdt_miscdev); 771e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster unregister_reboot_notifier(&wdt_notifier); 772e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8); 773e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster} 774e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 775e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schustermodule_init(it87_wdt_init); 776e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schustermodule_exit(it87_wdt_exit); 777e1fee94f346387739e683b31815ab54dc0a30bd6Oliver Schuster 778e1fee94f346387739e683b31815ab54dc0a30bd6Oliver SchusterMODULE_AUTHOR("Oliver Schuster"); 779e1fee94f346387739e683b31815ab54dc0a30bd6Oliver SchusterMODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O"); 780e1fee94f346387739e683b31815ab54dc0a30bd6Oliver SchusterMODULE_LICENSE("GPL"); 781e1fee94f346387739e683b31815ab54dc0a30bd6Oliver SchusterMODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 782