11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 20e94f2ee0d1947ba6c2c00c3e971ff93ce8edec1Vlad Drukker * w83627hf/thf WDT driver 30e94f2ee0d1947ba6c2c00c3e971ff93ce8edec1Vlad Drukker * 430a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck * (c) Copyright 2013 Guenter Roeck 530a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck * converted to watchdog infrastructure 630a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck * 70e94f2ee0d1947ba6c2c00c3e971ff93ce8edec1Vlad Drukker * (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com> 80e94f2ee0d1947ba6c2c00c3e971ff93ce8edec1Vlad Drukker * added support for W83627THF. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10d36b691077dc59c74efec0d54ed21b86f7a2a21aAl Viro * (c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Based on advantechwdt.c which is based on wdt.c. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Original copyright messages: 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1729fa0586de4fe518f122a915b8c6e92d12e8ca7fAlan Cox * (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>, 1829fa0586de4fe518f122a915b8c6e92d12e8ca7fAlan Cox * All Rights Reserved. 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as published by the Free Software Foundation; either version 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 of the License, or (at your option) any later version. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * warranty for any of this software. This material is provided 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "AS-IS" and at no charge. 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2929fa0586de4fe518f122a915b8c6e92d12e8ca7fAlan Cox * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3227c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 3327c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/watchdog.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/notifier.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/reboot.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 4246a3949ddc422882cc27c88d078838cd31885d78Alan Cox#include <linux/io.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 449c67bea419c384561eeb84bdf251d521a3234e45Benny Loenstrup Ammitzboell#define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT" 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeckstatic int wdt_io; 487b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeckstatic int cr_wdt_timeout; /* WDT timeout register */ 497b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeckstatic int cr_wdt_control; /* WDT control register */ 50962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck 517b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeckenum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf, 527b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p, 537b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck w83667hg_b, nct6775, nct6776, nct6779 }; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5530a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeckstatic int timeout; /* in seconds */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(timeout, int, 0); 5746a3949ddc422882cc27c88d078838cd31885d78Alan CoxMODULE_PARM_DESC(timeout, 5846a3949ddc422882cc27c88d078838cd31885d78Alan Cox "Watchdog timeout in seconds. 1 <= timeout <= 255, default=" 5946a3949ddc422882cc27c88d078838cd31885d78Alan Cox __MODULE_STRING(WATCHDOG_TIMEOUT) "."); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6186a1e1896c2710402e29a875d8d830244274244dWim Van Sebroeckstatic bool nowayout = WATCHDOG_NOWAYOUT; 6286a1e1896c2710402e29a875d8d830244274244dWim Van Sebroeckmodule_param(nowayout, bool, 0); 6346a3949ddc422882cc27c88d078838cd31885d78Alan CoxMODULE_PARM_DESC(nowayout, 6446a3949ddc422882cc27c88d078838cd31885d78Alan Cox "Watchdog cannot be stopped once started (default=" 6546a3949ddc422882cc27c88d078838cd31885d78Alan Cox __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeckstatic int early_disable; 68be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeckmodule_param(early_disable, int, 0); 69be281588d0bb21ccb07b1747939e0c919c2203fcGuenter RoeckMODULE_PARM_DESC(early_disable, "Disable watchdog at boot time (default=0)"); 70be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeck 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Kernel methods. 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */ 7646a3949ddc422882cc27c88d078838cd31885d78Alan Cox#define WDT_EFIR (wdt_io+0) /* Extended Function Index Register 7746a3949ddc422882cc27c88d078838cd31885d78Alan Cox (same as EFER) */ 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 80ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck#define W83627HF_LD_WDT 0x08 81ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck 82962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83627HF_ID 0x52 83962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83627S_ID 0x59 847b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck#define W83697HF_ID 0x60 857b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck#define W83697UG_ID 0x68 86962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83637HF_ID 0x70 87962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83627THF_ID 0x82 88962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83687THF_ID 0x85 89962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83627EHF_ID 0x88 90962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83627DHG_ID 0xa0 91962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83627UHG_ID 0xa2 92962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83667HG_ID 0xa5 93962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83627DHG_P_ID 0xb0 94962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define W83667HG_B_ID 0xb3 95962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define NCT6775_ID 0xb4 96962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define NCT6776_ID 0xc3 97962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck#define NCT6779_ID 0xc5 98962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck 997b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck#define W83627HF_WDT_TIMEOUT 0xf6 1007b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck#define W83697HF_WDT_TIMEOUT 0xf4 1017b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck 1027b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck#define W83627HF_WDT_CONTROL 0xf5 1037b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck#define W83697HF_WDT_CONTROL 0xf3 1047b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck 105ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeckstatic void superio_outb(int reg, int val) 106ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck{ 107ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck outb(reg, WDT_EFER); 108ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck outb(val, WDT_EFDR); 109ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck} 110ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck 111ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeckstatic inline int superio_inb(int reg) 112ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck{ 113ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck outb(reg, WDT_EFER); 114ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck return inb(WDT_EFDR); 115ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck} 116ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck 117ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeckstatic int superio_enter(void) 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 119ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck if (!request_muxed_region(wdt_io, 2, WATCHDOG_NAME)) 120ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck return -EBUSY; 121ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(0x87, WDT_EFER); /* Enter extended function mode */ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(0x87, WDT_EFER); /* Again according to manual */ 124ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck 125ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck return 0; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 128ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeckstatic void superio_select(int ld) 129ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck{ 130ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck superio_outb(0x07, ld); 131ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck} 132ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck 133ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeckstatic void superio_exit(void) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ 136ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck release_region(wdt_io, 2); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 139962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeckstatic int w83627hf_init(struct watchdog_device *wdog, enum chips chip) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 141ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck int ret; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char t; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 144ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck ret = superio_enter(); 145ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck if (ret) 146ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck return ret; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 148ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck superio_select(W83627HF_LD_WDT); 1498f526389599fc543b204c12a36de8345eb298085Guenter Roeck 150ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck /* set CR30 bit 0 to activate GPIO2 */ 151ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck t = superio_inb(0x30); 152ac461103c57ac46cd6778f1fd0352ff0e4a2d38eGuenter Roeck if (!(t & 0x01)) 153ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck superio_outb(0x30, t | 0x01); 1548f526389599fc543b204c12a36de8345eb298085Guenter Roeck 155962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck switch (chip) { 156962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83627hf: 157962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83627s: 158962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck t = superio_inb(0x2B) & ~0x10; 159962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck superio_outb(0x2B, t); /* set GPIO24 to WDT0 */ 160962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 1617b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck case w83697hf: 1627b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ 1637b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck t = superio_inb(0x29) & ~0x60; 1647b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck t |= 0x20; 1657b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck superio_outb(0x29, t); 1667b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck break; 1677b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck case w83697ug: 1687b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck /* Set pin 118 to WDTO# mode */ 1697b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck t = superio_inb(0x2b) & ~0x04; 1707b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck superio_outb(0x2b, t); 1717b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck break; 172962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83627thf: 173962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck t = (superio_inb(0x2B) & ~0x08) | 0x04; 174962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck superio_outb(0x2B, t); /* set GPIO3 to WDT0 */ 175962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 176962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83627dhg: 177962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83627dhg_p: 178962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck t = superio_inb(0x2D) & ~0x01; /* PIN77 -> WDT0# */ 179962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck superio_outb(0x2D, t); /* set GPIO5 to WDT0 */ 1807b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck t = superio_inb(cr_wdt_control); 181962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck t |= 0x02; /* enable the WDTO# output low pulse 182962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck * to the KBRST# pin */ 1837b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck superio_outb(cr_wdt_control, t); 184962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 185962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83637hf: 186962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 187962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83687thf: 188962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck t = superio_inb(0x2C) & ~0x80; /* PIN47 -> WDT0# */ 189962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck superio_outb(0x2C, t); 190962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 191962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83627ehf: 192962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83627uhg: 193962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83667hg: 194962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case w83667hg_b: 195962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case nct6775: 196962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case nct6776: 197962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case nct6779: 198962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck /* 199962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck * These chips have a fixed WDTO# output pin (W83627UHG), 200962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck * or support more than one WDTO# output pin. 201962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck * Don't touch its configuration, and hope the BIOS 202962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck * does the right thing. 203962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck */ 2047b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck t = superio_inb(cr_wdt_control); 205962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck t |= 0x02; /* enable the WDTO# output low pulse 206962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck * to the KBRST# pin */ 2077b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck superio_outb(cr_wdt_control, t); 208962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 209962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck default: 210962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 211962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck } 212962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck 2137b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck t = superio_inb(cr_wdt_timeout); 21493642ecd463df30d032da8ac37c2676cee4ad876P@Draig Brady if (t != 0) { 215be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeck if (early_disable) { 216be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeck pr_warn("Stopping previously enabled watchdog until userland kicks in\n"); 217be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeck superio_outb(cr_wdt_timeout, 0); 218be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeck } else { 219be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeck pr_info("Watchdog already running. Resetting timeout to %d sec\n", 220be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeck wdog->timeout); 221be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeck superio_outb(cr_wdt_timeout, wdog->timeout); 222be281588d0bb21ccb07b1747939e0c919c2203fcGuenter Roeck } 22393642ecd463df30d032da8ac37c2676cee4ad876P@Draig Brady } 22428dd1b0b9191ac9cd0b96fa4d09d951498bfbadbPďż˝draig Brady 225ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck /* set second mode & disable keyboard turning off watchdog */ 2267b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck t = superio_inb(cr_wdt_control) & ~0x0C; 2277b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck superio_outb(cr_wdt_control, t); 228ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck 229ea3d4011a871e1802e201086195c61e6dbeaf6d5Guenter Roeck /* reset trigger, disable keyboard & mouse turning off watchdog */ 230ea3d4011a871e1802e201086195c61e6dbeaf6d5Guenter Roeck t = superio_inb(0xF7) & ~0xD0; 231ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck superio_outb(0xF7, t); 232ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck 233ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck superio_exit(); 234ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck 235ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck return 0; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23830a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeckstatic int wdt_set_time(unsigned int timeout) 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 240ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck int ret; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 242ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck ret = superio_enter(); 243ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck if (ret) 244ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck return ret; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 246ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck superio_select(W83627HF_LD_WDT); 2477b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck superio_outb(cr_wdt_timeout, timeout); 248ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck superio_exit(); 249ab9d441425559aa035ba6327f21e8922e8a13927Wim Van Sebroeck 25030a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck return 0; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25330a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeckstatic int wdt_start(struct watchdog_device *wdog) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25530a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck return wdt_set_time(wdog->timeout); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25830a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeckstatic int wdt_stop(struct watchdog_device *wdog) 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26030a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck return wdt_set_time(0); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26330a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeckstatic int wdt_set_timeout(struct watchdog_device *wdog, unsigned int timeout) 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26530a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck wdog->timeout = timeout; 26630a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27030a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeckstatic unsigned int wdt_get_time(struct watchdog_device *wdog) 271c63b6d02be22899a5c8d47b8ee40e0534cd01a43Greg Lee{ 27230a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck unsigned int timeleft; 273ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck int ret; 274c63b6d02be22899a5c8d47b8ee40e0534cd01a43Greg Lee 275ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck ret = superio_enter(); 276ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck if (ret) 277ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck return 0; 278c63b6d02be22899a5c8d47b8ee40e0534cd01a43Greg Lee 279ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck superio_select(W83627HF_LD_WDT); 2807b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck timeleft = superio_inb(cr_wdt_timeout); 281ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck superio_exit(); 282c63b6d02be22899a5c8d47b8ee40e0534cd01a43Greg Lee 283c63b6d02be22899a5c8d47b8ee40e0534cd01a43Greg Lee return timeleft; 284c63b6d02be22899a5c8d47b8ee40e0534cd01a43Greg Lee} 285c63b6d02be22899a5c8d47b8ee40e0534cd01a43Greg Lee 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Notifier for system down 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 28946a3949ddc422882cc27c88d078838cd31885d78Alan Coxstatic int wdt_notify_sys(struct notifier_block *this, unsigned long code, 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *unused) 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2927944d3a5a70ee5c1904ed1e8b1d71ff0af2854d9Wim Van Sebroeck if (code == SYS_DOWN || code == SYS_HALT) 29330a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck wdt_set_time(0); /* Turn the WDT off */ 2947944d3a5a70ee5c1904ed1e8b1d71ff0af2854d9Wim Van Sebroeck 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NOTIFY_DONE; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Kernel Interfaces 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30230a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeckstatic struct watchdog_info wdt_info = { 30330a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 30430a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .identity = "W83627HF Watchdog", 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30730a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeckstatic struct watchdog_ops wdt_ops = { 30830a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .owner = THIS_MODULE, 30930a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .start = wdt_start, 31030a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .stop = wdt_stop, 31130a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .set_timeout = wdt_set_timeout, 31230a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .get_timeleft = wdt_get_time, 31330a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck}; 31430a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck 31530a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeckstatic struct watchdog_device wdt_dev = { 31630a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .info = &wdt_info, 31730a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .ops = &wdt_ops, 31830a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .timeout = WATCHDOG_TIMEOUT, 31930a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .min_timeout = 1, 32030a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck .max_timeout = 255, 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The WDT needs to learn about soft shutdowns in order to 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * turn the timebomb registers off. 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct notifier_block wdt_notifier = { 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .notifier_call = wdt_notify_sys, 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 332962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeckstatic int wdt_find(int addr) 333962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck{ 334962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck u8 val; 335962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck int ret; 336962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck 3377b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck cr_wdt_timeout = W83627HF_WDT_TIMEOUT; 3387b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck cr_wdt_control = W83627HF_WDT_CONTROL; 3397b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck 340962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = superio_enter(); 341962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck if (ret) 342962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck return ret; 343962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck superio_select(W83627HF_LD_WDT); 344962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck val = superio_inb(0x20); 345962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck switch (val) { 346962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83627HF_ID: 347962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83627hf; 348962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 349962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83627S_ID: 350962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83627s; 351962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 3527b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck case W83697HF_ID: 3537b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck ret = w83697hf; 3547b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck cr_wdt_timeout = W83697HF_WDT_TIMEOUT; 3557b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck cr_wdt_control = W83697HF_WDT_CONTROL; 3567b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck break; 3577b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck case W83697UG_ID: 3587b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck ret = w83697ug; 3597b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck cr_wdt_timeout = W83697HF_WDT_TIMEOUT; 3607b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck cr_wdt_control = W83697HF_WDT_CONTROL; 3617b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck break; 362962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83637HF_ID: 363962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83637hf; 364962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 365962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83627THF_ID: 366962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83627thf; 367962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 368962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83687THF_ID: 369962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83687thf; 370962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 371962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83627EHF_ID: 372962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83627ehf; 373962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 374962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83627DHG_ID: 375962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83627dhg; 376962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 377962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83627DHG_P_ID: 378962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83627dhg_p; 379962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 380962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83627UHG_ID: 381962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83627uhg; 382962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 383962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83667HG_ID: 384962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83667hg; 385962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 386962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case W83667HG_B_ID: 387962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83667hg_b; 388962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 389962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case NCT6775_ID: 390962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = nct6775; 391962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 392962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case NCT6776_ID: 393962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = nct6776; 394962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 395962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case NCT6779_ID: 396962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = nct6779; 397962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 398962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck case 0xff: 399962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = -ENODEV; 400962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 401962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck default: 402962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = -ENODEV; 403962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck pr_err("Unsupported chip ID: 0x%02x\n", val); 404962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck break; 405962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck } 406962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck superio_exit(); 407962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck return ret; 408962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck} 409962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck 41046a3949ddc422882cc27c88d078838cd31885d78Alan Coxstatic int __init wdt_init(void) 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 413962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck int chip; 414962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck const char * const chip_name[] = { 415962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83627HF", 416962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83627S", 4177b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck "W83697HF", 4187b6d0b6ad49e55f8b82dbf233ece4e091417a738Guenter Roeck "W83697UG", 419962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83637HF", 420962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83627THF", 421962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83687THF", 422962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83627EHF", 423962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83627DHG", 424962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83627UHG", 425962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83667HG", 426962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83667DHG-P", 427962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "W83667HG-B", 428962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "NCT6775", 429962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "NCT6776", 430962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck "NCT6779", 431962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck }; 432962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck 433962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck wdt_io = 0x2e; 434962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck chip = wdt_find(0x2e); 435962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck if (chip < 0) { 436962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck wdt_io = 0x4e; 437962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck chip = wdt_find(0x4e); 438962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck if (chip < 0) 439962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck return chip; 440962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck } 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 442962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck pr_info("WDT driver for %s Super I/O chip initialising\n", 443962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck chip_name[chip]); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44530a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck watchdog_init_timeout(&wdt_dev, timeout, NULL); 44630a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck watchdog_set_nowayout(&wdt_dev, nowayout); 44730a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck 448962c04f54e4a3c322d19b47256f9aec0b9c8124eGuenter Roeck ret = w83627hf_init(&wdt_dev, chip); 449ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck if (ret) { 450ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck pr_err("failed to initialize watchdog (err=%d)\n", ret); 451ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck return ret; 452ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck } 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = register_reboot_notifier(&wdt_notifier); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret != 0) { 45627c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches pr_err("cannot register reboot notifier (err=%d)\n", ret); 457ef0c1a6b1b05f85f0a1cf6ef283512fd25d86ad4Guenter Roeck return ret; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46030a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck ret = watchdog_register_device(&wdt_dev); 46130a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck if (ret) 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto unreg_reboot; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46427c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches pr_info("initialized. timeout=%d sec (nowayout=%d)\n", 46530a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck wdt_dev.timeout, nowayout); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 46830a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunreg_reboot: 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_reboot_notifier(&wdt_notifier); 47130a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck return ret; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47446a3949ddc422882cc27c88d078838cd31885d78Alan Coxstatic void __exit wdt_exit(void) 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 47630a83695aa2ed3ffb1445d6daef1e620c3ca4e6dGuenter Roeck watchdog_unregister_device(&wdt_dev); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_reboot_notifier(&wdt_notifier); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(wdt_init); 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(wdt_exit); 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 484d36b691077dc59c74efec0d54ed21b86f7a2a21aAl ViroMODULE_AUTHOR("Pádraig Brady <P@draigBrady.com>"); 4850e94f2ee0d1947ba6c2c00c3e971ff93ce8edec1Vlad DrukkerMODULE_DESCRIPTION("w83627hf/thf WDT driver"); 486