linux/drivers/watchdog/iTCO_wdt.c
<<
>>
Prefs
   1/*
   2 *      intel TCO Watchdog Driver (Used in i82801 and i63xxESB chipsets)
   3 *
   4 *      (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>.
   5 *
   6 *      This program is free software; you can redistribute it and/or
   7 *      modify it under the terms of the GNU General Public License
   8 *      as published by the Free Software Foundation; either version
   9 *      2 of the License, or (at your option) any later version.
  10 *
  11 *      Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
  12 *      provide warranty for any of this software. This material is
  13 *      provided "AS-IS" and at no charge.
  14 *
  15 *      The TCO watchdog is implemented in the following I/O controller hubs:
  16 *      (See the intel documentation on http://developer.intel.com.)
  17 *      82801AA  (ICH)       : document number 290655-003, 290677-014,
  18 *      82801AB  (ICHO)      : document number 290655-003, 290677-014,
  19 *      82801BA  (ICH2)      : document number 290687-002, 298242-027,
  20 *      82801BAM (ICH2-M)    : document number 290687-002, 298242-027,
  21 *      82801CA  (ICH3-S)    : document number 290733-003, 290739-013,
  22 *      82801CAM (ICH3-M)    : document number 290716-001, 290718-007,
  23 *      82801DB  (ICH4)      : document number 290744-001, 290745-025,
  24 *      82801DBM (ICH4-M)    : document number 252337-001, 252663-008,
  25 *      82801E   (C-ICH)     : document number 273599-001, 273645-002,
  26 *      82801EB  (ICH5)      : document number 252516-001, 252517-028,
  27 *      82801ER  (ICH5R)     : document number 252516-001, 252517-028,
  28 *      6300ESB  (6300ESB)   : document number 300641-004, 300884-013,
  29 *      82801FB  (ICH6)      : document number 301473-002, 301474-026,
  30 *      82801FR  (ICH6R)     : document number 301473-002, 301474-026,
  31 *      82801FBM (ICH6-M)    : document number 301473-002, 301474-026,
  32 *      82801FW  (ICH6W)     : document number 301473-001, 301474-026,
  33 *      82801FRW (ICH6RW)    : document number 301473-001, 301474-026,
  34 *      631xESB  (631xESB)   : document number 313082-001, 313075-006,
  35 *      632xESB  (632xESB)   : document number 313082-001, 313075-006,
  36 *      82801GB  (ICH7)      : document number 307013-003, 307014-024,
  37 *      82801GR  (ICH7R)     : document number 307013-003, 307014-024,
  38 *      82801GDH (ICH7DH)    : document number 307013-003, 307014-024,
  39 *      82801GBM (ICH7-M)    : document number 307013-003, 307014-024,
  40 *      82801GHM (ICH7-M DH) : document number 307013-003, 307014-024,
  41 *      82801GU  (ICH7-U)    : document number 307013-003, 307014-024,
  42 *      82801HB  (ICH8)      : document number 313056-003, 313057-017,
  43 *      82801HR  (ICH8R)     : document number 313056-003, 313057-017,
  44 *      82801HBM (ICH8M)     : document number 313056-003, 313057-017,
  45 *      82801HH  (ICH8DH)    : document number 313056-003, 313057-017,
  46 *      82801HO  (ICH8DO)    : document number 313056-003, 313057-017,
  47 *      82801HEM (ICH8M-E)   : document number 313056-003, 313057-017,
  48 *      82801IB  (ICH9)      : document number 316972-004, 316973-012,
  49 *      82801IR  (ICH9R)     : document number 316972-004, 316973-012,
  50 *      82801IH  (ICH9DH)    : document number 316972-004, 316973-012,
  51 *      82801IO  (ICH9DO)    : document number 316972-004, 316973-012,
  52 *      82801IBM (ICH9M)     : document number 316972-004, 316973-012,
  53 *      82801IEM (ICH9M-E)   : document number 316972-004, 316973-012,
  54 *      82801JIB (ICH10)     : document number 319973-002, 319974-002,
  55 *      82801JIR (ICH10R)    : document number 319973-002, 319974-002,
  56 *      82801JD  (ICH10D)    : document number 319973-002, 319974-002,
  57 *      82801JDO (ICH10DO)   : document number 319973-002, 319974-002
  58 */
  59
  60/*
  61 *      Includes, defines, variables, module parameters, ...
  62 */
  63
  64/* Module and version information */
  65#define DRV_NAME        "iTCO_wdt"
  66#define DRV_VERSION     "1.05"
  67#define PFX             DRV_NAME ": "
  68
  69/* Includes */
  70#include <linux/module.h>               /* For module specific items */
  71#include <linux/moduleparam.h>          /* For new moduleparam's */
  72#include <linux/types.h>                /* For standard types (like size_t) */
  73#include <linux/errno.h>                /* For the -ENODEV/... values */
  74#include <linux/kernel.h>               /* For printk/panic/... */
  75#include <linux/miscdevice.h>           /* For MODULE_ALIAS_MISCDEV
  76                                                        (WATCHDOG_MINOR) */
  77#include <linux/watchdog.h>             /* For the watchdog specific items */
  78#include <linux/init.h>                 /* For __init/__exit/... */
  79#include <linux/fs.h>                   /* For file operations */
  80#include <linux/platform_device.h>      /* For platform_driver framework */
  81#include <linux/pci.h>                  /* For pci functions */
  82#include <linux/ioport.h>               /* For io-port access */
  83#include <linux/spinlock.h>             /* For spin_lock/spin_unlock/... */
  84#include <linux/uaccess.h>              /* For copy_to_user/put_user/... */
  85#include <linux/io.h>                   /* For inb/outb/... */
  86
  87#include "iTCO_vendor.h"
  88
  89/* TCO related info */
  90enum iTCO_chipsets {
  91        TCO_ICH = 0,    /* ICH */
  92        TCO_ICH0,       /* ICH0 */
  93        TCO_ICH2,       /* ICH2 */
  94        TCO_ICH2M,      /* ICH2-M */
  95        TCO_ICH3,       /* ICH3-S */
  96        TCO_ICH3M,      /* ICH3-M */
  97        TCO_ICH4,       /* ICH4 */
  98        TCO_ICH4M,      /* ICH4-M */
  99        TCO_CICH,       /* C-ICH */
 100        TCO_ICH5,       /* ICH5 & ICH5R */
 101        TCO_6300ESB,    /* 6300ESB */
 102        TCO_ICH6,       /* ICH6 & ICH6R */
 103        TCO_ICH6M,      /* ICH6-M */
 104        TCO_ICH6W,      /* ICH6W & ICH6RW */
 105        TCO_631XESB,    /* 631xESB/632xESB */
 106        TCO_ICH7,       /* ICH7 & ICH7R */
 107        TCO_ICH7DH,     /* ICH7DH */
 108        TCO_ICH7M,      /* ICH7-M & ICH7-U */
 109        TCO_ICH7MDH,    /* ICH7-M DH */
 110        TCO_ICH8,       /* ICH8 & ICH8R */
 111        TCO_ICH8DH,     /* ICH8DH */
 112        TCO_ICH8DO,     /* ICH8DO */
 113        TCO_ICH8M,      /* ICH8M */
 114        TCO_ICH8ME,     /* ICH8M-E */
 115        TCO_ICH9,       /* ICH9 */
 116        TCO_ICH9R,      /* ICH9R */
 117        TCO_ICH9DH,     /* ICH9DH */
 118        TCO_ICH9DO,     /* ICH9DO */
 119        TCO_ICH9M,      /* ICH9M */
 120        TCO_ICH9ME,     /* ICH9M-E */
 121        TCO_ICH10,      /* ICH10 */
 122        TCO_ICH10R,     /* ICH10R */
 123        TCO_ICH10D,     /* ICH10D */
 124        TCO_ICH10DO,    /* ICH10DO */
 125};
 126
 127static struct {
 128        char *name;
 129        unsigned int iTCO_version;
 130} iTCO_chipset_info[] __devinitdata = {
 131        {"ICH", 1},
 132        {"ICH0", 1},
 133        {"ICH2", 1},
 134        {"ICH2-M", 1},
 135        {"ICH3-S", 1},
 136        {"ICH3-M", 1},
 137        {"ICH4", 1},
 138        {"ICH4-M", 1},
 139        {"C-ICH", 1},
 140        {"ICH5 or ICH5R", 1},
 141        {"6300ESB", 1},
 142        {"ICH6 or ICH6R", 2},
 143        {"ICH6-M", 2},
 144        {"ICH6W or ICH6RW", 2},
 145        {"631xESB/632xESB", 2},
 146        {"ICH7 or ICH7R", 2},
 147        {"ICH7DH", 2},
 148        {"ICH7-M or ICH7-U", 2},
 149        {"ICH7-M DH", 2},
 150        {"ICH8 or ICH8R", 2},
 151        {"ICH8DH", 2},
 152        {"ICH8DO", 2},
 153        {"ICH8M", 2},
 154        {"ICH8M-E", 2},
 155        {"ICH9", 2},
 156        {"ICH9R", 2},
 157        {"ICH9DH", 2},
 158        {"ICH9DO", 2},
 159        {"ICH9M", 2},
 160        {"ICH9M-E", 2},
 161        {"ICH10", 2},
 162        {"ICH10R", 2},
 163        {"ICH10D", 2},
 164        {"ICH10DO", 2},
 165        {NULL, 0}
 166};
 167
 168#define ITCO_PCI_DEVICE(dev, data)      \
 169        .vendor = PCI_VENDOR_ID_INTEL,  \
 170        .device = dev,                  \
 171        .subvendor = PCI_ANY_ID,        \
 172        .subdevice = PCI_ANY_ID,        \
 173        .class = 0,                     \
 174        .class_mask = 0,                \
 175        .driver_data = data
 176
 177/*
 178 * This data only exists for exporting the supported PCI ids
 179 * via MODULE_DEVICE_TABLE.  We do not actually register a
 180 * pci_driver, because the I/O Controller Hub has also other
 181 * functions that probably will be registered by other drivers.
 182 */
 183static struct pci_device_id iTCO_wdt_pci_tbl[] = {
 184        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0,        TCO_ICH)},
 185        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0,        TCO_ICH0)},
 186        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0,        TCO_ICH2)},
 187        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_10,       TCO_ICH2M)},
 188        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_0,        TCO_ICH3)},
 189        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_12,       TCO_ICH3M)},
 190        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_0,        TCO_ICH4)},
 191        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_12,       TCO_ICH4M)},
 192        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801E_0,         TCO_CICH)},
 193        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801EB_0,        TCO_ICH5)},
 194        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB_1,            TCO_6300ESB)},
 195        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0,           TCO_ICH6)},
 196        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1,           TCO_ICH6M)},
 197        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2,           TCO_ICH6W)},
 198        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0,           TCO_631XESB)},
 199        { ITCO_PCI_DEVICE(0x2671,                               TCO_631XESB)},
 200        { ITCO_PCI_DEVICE(0x2672,                               TCO_631XESB)},
 201        { ITCO_PCI_DEVICE(0x2673,                               TCO_631XESB)},
 202        { ITCO_PCI_DEVICE(0x2674,                               TCO_631XESB)},
 203        { ITCO_PCI_DEVICE(0x2675,                               TCO_631XESB)},
 204        { ITCO_PCI_DEVICE(0x2676,                               TCO_631XESB)},
 205        { ITCO_PCI_DEVICE(0x2677,                               TCO_631XESB)},
 206        { ITCO_PCI_DEVICE(0x2678,                               TCO_631XESB)},
 207        { ITCO_PCI_DEVICE(0x2679,                               TCO_631XESB)},
 208        { ITCO_PCI_DEVICE(0x267a,                               TCO_631XESB)},
 209        { ITCO_PCI_DEVICE(0x267b,                               TCO_631XESB)},
 210        { ITCO_PCI_DEVICE(0x267c,                               TCO_631XESB)},
 211        { ITCO_PCI_DEVICE(0x267d,                               TCO_631XESB)},
 212        { ITCO_PCI_DEVICE(0x267e,                               TCO_631XESB)},
 213        { ITCO_PCI_DEVICE(0x267f,                               TCO_631XESB)},
 214        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0,           TCO_ICH7)},
 215        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30,          TCO_ICH7DH)},
 216        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1,           TCO_ICH7M)},
 217        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31,          TCO_ICH7MDH)},
 218        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0,           TCO_ICH8)},
 219        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2,           TCO_ICH8DH)},
 220        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3,           TCO_ICH8DO)},
 221        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4,           TCO_ICH8M)},
 222        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1,           TCO_ICH8ME)},
 223        { ITCO_PCI_DEVICE(0x2918,                               TCO_ICH9)},
 224        { ITCO_PCI_DEVICE(0x2916,                               TCO_ICH9R)},
 225        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2,           TCO_ICH9DH)},
 226        { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4,           TCO_ICH9DO)},
 227        { ITCO_PCI_DEVICE(0x2919,                               TCO_ICH9M)},
 228        { ITCO_PCI_DEVICE(0x2917,                               TCO_ICH9ME)},
 229        { ITCO_PCI_DEVICE(0x3a18,                               TCO_ICH10)},
 230        { ITCO_PCI_DEVICE(0x3a16,                               TCO_ICH10R)},
 231        { ITCO_PCI_DEVICE(0x3a1a,                               TCO_ICH10D)},
 232        { ITCO_PCI_DEVICE(0x3a14,                               TCO_ICH10DO)},
 233        { 0, },                 /* End of list */
 234};
 235MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
 236
 237/* Address definitions for the TCO */
 238/* TCO base address */
 239#define TCOBASE         iTCO_wdt_private.ACPIBASE + 0x60
 240/* SMI Control and Enable Register */
 241#define SMI_EN          iTCO_wdt_private.ACPIBASE + 0x30
 242
 243#define TCO_RLD         TCOBASE + 0x00  /* TCO Timer Reload and Curr. Value */
 244#define TCOv1_TMR       TCOBASE + 0x01  /* TCOv1 Timer Initial Value    */
 245#define TCO_DAT_IN      TCOBASE + 0x02  /* TCO Data In Register         */
 246#define TCO_DAT_OUT     TCOBASE + 0x03  /* TCO Data Out Register        */
 247#define TCO1_STS        TCOBASE + 0x04  /* TCO1 Status Register         */
 248#define TCO2_STS        TCOBASE + 0x06  /* TCO2 Status Register         */
 249#define TCO1_CNT        TCOBASE + 0x08  /* TCO1 Control Register        */
 250#define TCO2_CNT        TCOBASE + 0x0a  /* TCO2 Control Register        */
 251#define TCOv2_TMR       TCOBASE + 0x12  /* TCOv2 Timer Initial Value    */
 252
 253/* internal variables */
 254static unsigned long is_active;
 255static char expect_release;
 256static struct {         /* this is private data for the iTCO_wdt device */
 257        /* TCO version/generation */
 258        unsigned int iTCO_version;
 259        /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
 260        unsigned long ACPIBASE;
 261        /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
 262        unsigned long __iomem *gcs;
 263        /* the lock for io operations */
 264        spinlock_t io_lock;
 265        /* the PCI-device */
 266        struct pci_dev *pdev;
 267} iTCO_wdt_private;
 268
 269/* the watchdog platform device */
 270static struct platform_device *iTCO_wdt_platform_device;
 271
 272/* module parameters */
 273#define WATCHDOG_HEARTBEAT 30   /* 30 sec default heartbeat */
 274static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
 275module_param(heartbeat, int, 0);
 276MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
 277        "(2<heartbeat<39 (TCO v1) or 613 (TCO v2), default="
 278                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 279
 280static int nowayout = WATCHDOG_NOWAYOUT;
 281module_param(nowayout, int, 0);
 282MODULE_PARM_DESC(nowayout,
 283        "Watchdog cannot be stopped once started (default="
 284                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 285
 286/*
 287 * Some TCO specific functions
 288 */
 289
 290static inline unsigned int seconds_to_ticks(int seconds)
 291{
 292        /* the internal timer is stored as ticks which decrement
 293         * every 0.6 seconds */
 294        return (seconds * 10) / 6;
 295}
 296
 297static void iTCO_wdt_set_NO_REBOOT_bit(void)
 298{
 299        u32 val32;
 300
 301        /* Set the NO_REBOOT bit: this disables reboots */
 302        if (iTCO_wdt_private.iTCO_version == 2) {
 303                val32 = readl(iTCO_wdt_private.gcs);
 304                val32 |= 0x00000020;
 305                writel(val32, iTCO_wdt_private.gcs);
 306        } else if (iTCO_wdt_private.iTCO_version == 1) {
 307                pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
 308                val32 |= 0x00000002;
 309                pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
 310        }
 311}
 312
 313static int iTCO_wdt_unset_NO_REBOOT_bit(void)
 314{
 315        int ret = 0;
 316        u32 val32;
 317
 318        /* Unset the NO_REBOOT bit: this enables reboots */
 319        if (iTCO_wdt_private.iTCO_version == 2) {
 320                val32 = readl(iTCO_wdt_private.gcs);
 321                val32 &= 0xffffffdf;
 322                writel(val32, iTCO_wdt_private.gcs);
 323
 324                val32 = readl(iTCO_wdt_private.gcs);
 325                if (val32 & 0x00000020)
 326                        ret = -EIO;
 327        } else if (iTCO_wdt_private.iTCO_version == 1) {
 328                pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
 329                val32 &= 0xfffffffd;
 330                pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
 331
 332                pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
 333                if (val32 & 0x00000002)
 334                        ret = -EIO;
 335        }
 336
 337        return ret; /* returns: 0 = OK, -EIO = Error */
 338}
 339
 340static int iTCO_wdt_start(void)
 341{
 342        unsigned int val;
 343
 344        spin_lock(&iTCO_wdt_private.io_lock);
 345
 346        iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat);
 347
 348        /* disable chipset's NO_REBOOT bit */
 349        if (iTCO_wdt_unset_NO_REBOOT_bit()) {
 350                spin_unlock(&iTCO_wdt_private.io_lock);
 351                printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
 352                                        "reboot disabled by hardware\n");
 353                return -EIO;
 354        }
 355
 356        /* Force the timer to its reload value by writing to the TCO_RLD
 357           register */
 358        if (iTCO_wdt_private.iTCO_version == 2)
 359                outw(0x01, TCO_RLD);
 360        else if (iTCO_wdt_private.iTCO_version == 1)
 361                outb(0x01, TCO_RLD);
 362
 363        /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
 364        val = inw(TCO1_CNT);
 365        val &= 0xf7ff;
 366        outw(val, TCO1_CNT);
 367        val = inw(TCO1_CNT);
 368        spin_unlock(&iTCO_wdt_private.io_lock);
 369
 370        if (val & 0x0800)
 371                return -1;
 372        return 0;
 373}
 374
 375static int iTCO_wdt_stop(void)
 376{
 377        unsigned int val;
 378
 379        spin_lock(&iTCO_wdt_private.io_lock);
 380
 381        iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE);
 382
 383        /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
 384        val = inw(TCO1_CNT);
 385        val |= 0x0800;
 386        outw(val, TCO1_CNT);
 387        val = inw(TCO1_CNT);
 388
 389        /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
 390        iTCO_wdt_set_NO_REBOOT_bit();
 391
 392        spin_unlock(&iTCO_wdt_private.io_lock);
 393
 394        if ((val & 0x0800) == 0)
 395                return -1;
 396        return 0;
 397}
 398
 399static int iTCO_wdt_keepalive(void)
 400{
 401        spin_lock(&iTCO_wdt_private.io_lock);
 402
 403        iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
 404
 405        /* Reload the timer by writing to the TCO Timer Counter register */
 406        if (iTCO_wdt_private.iTCO_version == 2)
 407                outw(0x01, TCO_RLD);
 408        else if (iTCO_wdt_private.iTCO_version == 1)
 409                outb(0x01, TCO_RLD);
 410
 411        spin_unlock(&iTCO_wdt_private.io_lock);
 412        return 0;
 413}
 414
 415static int iTCO_wdt_set_heartbeat(int t)
 416{
 417        unsigned int val16;
 418        unsigned char val8;
 419        unsigned int tmrval;
 420
 421        tmrval = seconds_to_ticks(t);
 422        /* from the specs: */
 423        /* "Values of 0h-3h are ignored and should not be attempted" */
 424        if (tmrval < 0x04)
 425                return -EINVAL;
 426        if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
 427            ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
 428                return -EINVAL;
 429
 430        iTCO_vendor_pre_set_heartbeat(tmrval);
 431
 432        /* Write new heartbeat to watchdog */
 433        if (iTCO_wdt_private.iTCO_version == 2) {
 434                spin_lock(&iTCO_wdt_private.io_lock);
 435                val16 = inw(TCOv2_TMR);
 436                val16 &= 0xfc00;
 437                val16 |= tmrval;
 438                outw(val16, TCOv2_TMR);
 439                val16 = inw(TCOv2_TMR);
 440                spin_unlock(&iTCO_wdt_private.io_lock);
 441
 442                if ((val16 & 0x3ff) != tmrval)
 443                        return -EINVAL;
 444        } else if (iTCO_wdt_private.iTCO_version == 1) {
 445                spin_lock(&iTCO_wdt_private.io_lock);
 446                val8 = inb(TCOv1_TMR);
 447                val8 &= 0xc0;
 448                val8 |= (tmrval & 0xff);
 449                outb(val8, TCOv1_TMR);
 450                val8 = inb(TCOv1_TMR);
 451                spin_unlock(&iTCO_wdt_private.io_lock);
 452
 453                if ((val8 & 0x3f) != tmrval)
 454                        return -EINVAL;
 455        }
 456
 457        heartbeat = t;
 458        return 0;
 459}
 460
 461static int iTCO_wdt_get_timeleft(int *time_left)
 462{
 463        unsigned int val16;
 464        unsigned char val8;
 465
 466        /* read the TCO Timer */
 467        if (iTCO_wdt_private.iTCO_version == 2) {
 468                spin_lock(&iTCO_wdt_private.io_lock);
 469                val16 = inw(TCO_RLD);
 470                val16 &= 0x3ff;
 471                spin_unlock(&iTCO_wdt_private.io_lock);
 472
 473                *time_left = (val16 * 6) / 10;
 474        } else if (iTCO_wdt_private.iTCO_version == 1) {
 475                spin_lock(&iTCO_wdt_private.io_lock);
 476                val8 = inb(TCO_RLD);
 477                val8 &= 0x3f;
 478                spin_unlock(&iTCO_wdt_private.io_lock);
 479
 480                *time_left = (val8 * 6) / 10;
 481        } else
 482                return -EINVAL;
 483        return 0;
 484}
 485
 486/*
 487 *      /dev/watchdog handling
 488 */
 489
 490static int iTCO_wdt_open(struct inode *inode, struct file *file)
 491{
 492        /* /dev/watchdog can only be opened once */
 493        if (test_and_set_bit(0, &is_active))
 494                return -EBUSY;
 495
 496        /*
 497         *      Reload and activate timer
 498         */
 499        iTCO_wdt_start();
 500        return nonseekable_open(inode, file);
 501}
 502
 503static int iTCO_wdt_release(struct inode *inode, struct file *file)
 504{
 505        /*
 506         *      Shut off the timer.
 507         */
 508        if (expect_release == 42) {
 509                iTCO_wdt_stop();
 510        } else {
 511                printk(KERN_CRIT PFX
 512                        "Unexpected close, not stopping watchdog!\n");
 513                iTCO_wdt_keepalive();
 514        }
 515        clear_bit(0, &is_active);
 516        expect_release = 0;
 517        return 0;
 518}
 519
 520static ssize_t iTCO_wdt_write(struct file *file, const char __user *data,
 521                              size_t len, loff_t *ppos)
 522{
 523        /* See if we got the magic character 'V' and reload the timer */
 524        if (len) {
 525                if (!nowayout) {
 526                        size_t i;
 527
 528                        /* note: just in case someone wrote the magic
 529                           character five months ago... */
 530                        expect_release = 0;
 531
 532                        /* scan to see whether or not we got the
 533                           magic character */
 534                        for (i = 0; i != len; i++) {
 535                                char c;
 536                                if (get_user(c, data + i))
 537                                        return -EFAULT;
 538                                if (c == 'V')
 539                                        expect_release = 42;
 540                        }
 541                }
 542
 543                /* someone wrote to us, we should reload the timer */
 544                iTCO_wdt_keepalive();
 545        }
 546        return len;
 547}
 548
 549static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd,
 550                                                        unsigned long arg)
 551{
 552        int new_options, retval = -EINVAL;
 553        int new_heartbeat;
 554        void __user *argp = (void __user *)arg;
 555        int __user *p = argp;
 556        static struct watchdog_info ident = {
 557                .options =              WDIOF_SETTIMEOUT |
 558                                        WDIOF_KEEPALIVEPING |
 559                                        WDIOF_MAGICCLOSE,
 560                .firmware_version =     0,
 561                .identity =             DRV_NAME,
 562        };
 563
 564        switch (cmd) {
 565        case WDIOC_GETSUPPORT:
 566                return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
 567        case WDIOC_GETSTATUS:
 568        case WDIOC_GETBOOTSTATUS:
 569                return put_user(0, p);
 570
 571        case WDIOC_SETOPTIONS:
 572        {
 573                if (get_user(new_options, p))
 574                        return -EFAULT;
 575
 576                if (new_options & WDIOS_DISABLECARD) {
 577                        iTCO_wdt_stop();
 578                        retval = 0;
 579                }
 580                if (new_options & WDIOS_ENABLECARD) {
 581                        iTCO_wdt_keepalive();
 582                        iTCO_wdt_start();
 583                        retval = 0;
 584                }
 585                return retval;
 586        }
 587        case WDIOC_KEEPALIVE:
 588                iTCO_wdt_keepalive();
 589                return 0;
 590
 591        case WDIOC_SETTIMEOUT:
 592        {
 593                if (get_user(new_heartbeat, p))
 594                        return -EFAULT;
 595                if (iTCO_wdt_set_heartbeat(new_heartbeat))
 596                        return -EINVAL;
 597                iTCO_wdt_keepalive();
 598                /* Fall */
 599        }
 600        case WDIOC_GETTIMEOUT:
 601                return put_user(heartbeat, p);
 602        case WDIOC_GETTIMELEFT:
 603        {
 604                int time_left;
 605                if (iTCO_wdt_get_timeleft(&time_left))
 606                        return -EINVAL;
 607                return put_user(time_left, p);
 608        }
 609        default:
 610                return -ENOTTY;
 611        }
 612}
 613
 614/*
 615 *      Kernel Interfaces
 616 */
 617
 618static const struct file_operations iTCO_wdt_fops = {
 619        .owner =                THIS_MODULE,
 620        .llseek =               no_llseek,
 621        .write =                iTCO_wdt_write,
 622        .unlocked_ioctl =       iTCO_wdt_ioctl,
 623        .open =                 iTCO_wdt_open,
 624        .release =              iTCO_wdt_release,
 625};
 626
 627static struct miscdevice iTCO_wdt_miscdev = {
 628        .minor =        WATCHDOG_MINOR,
 629        .name =         "watchdog",
 630        .fops =         &iTCO_wdt_fops,
 631};
 632
 633/*
 634 *      Init & exit routines
 635 */
 636
 637static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
 638                const struct pci_device_id *ent, struct platform_device *dev)
 639{
 640        int ret;
 641        u32 base_address;
 642        unsigned long RCBA;
 643        unsigned long val32;
 644
 645        /*
 646         *      Find the ACPI/PM base I/O address which is the base
 647         *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
 648         *      ACPIBASE is bits [15:7] from 0x40-0x43
 649         */
 650        pci_read_config_dword(pdev, 0x40, &base_address);
 651        base_address &= 0x0000ff80;
 652        if (base_address == 0x00000000) {
 653                /* Something's wrong here, ACPIBASE has to be set */
 654                printk(KERN_ERR PFX "failed to get TCOBASE address\n");
 655                pci_dev_put(pdev);
 656                return -ENODEV;
 657        }
 658        iTCO_wdt_private.iTCO_version =
 659                        iTCO_chipset_info[ent->driver_data].iTCO_version;
 660        iTCO_wdt_private.ACPIBASE = base_address;
 661        iTCO_wdt_private.pdev = pdev;
 662
 663        /* Get the Memory-Mapped GCS register, we need it for the
 664           NO_REBOOT flag (TCO v2). To get access to it you have to
 665           read RCBA from PCI Config space 0xf0 and use it as base.
 666           GCS = RCBA + ICH6_GCS(0x3410). */
 667        if (iTCO_wdt_private.iTCO_version == 2) {
 668                pci_read_config_dword(pdev, 0xf0, &base_address);
 669                RCBA = base_address & 0xffffc000;
 670                iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4);
 671        }
 672
 673        /* Check chipset's NO_REBOOT bit */
 674        if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
 675                printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
 676                                        "reboot disabled by hardware\n");
 677                ret = -ENODEV;  /* Cannot reset NO_REBOOT bit */
 678                goto out;
 679        }
 680
 681        /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
 682        iTCO_wdt_set_NO_REBOOT_bit();
 683
 684        /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
 685        if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
 686                printk(KERN_ERR PFX
 687                        "I/O address 0x%04lx already in use\n", SMI_EN);
 688                ret = -EIO;
 689                goto out;
 690        }
 691        /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
 692        val32 = inl(SMI_EN);
 693        val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
 694        outl(val32, SMI_EN);
 695
 696        /* The TCO I/O registers reside in a 32-byte range pointed to
 697           by the TCOBASE value */
 698        if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
 699                printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n",
 700                        TCOBASE);
 701                ret = -EIO;
 702                goto unreg_smi_en;
 703        }
 704
 705        printk(KERN_INFO PFX
 706                "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
 707                        iTCO_chipset_info[ent->driver_data].name,
 708                        iTCO_chipset_info[ent->driver_data].iTCO_version,
 709                        TCOBASE);
 710
 711        /* Clear out the (probably old) status */
 712        outb(8, TCO1_STS);      /* Clear the Time Out Status bit */
 713        outb(2, TCO2_STS);      /* Clear SECOND_TO_STS bit */
 714        outb(4, TCO2_STS);      /* Clear BOOT_STS bit */
 715
 716        /* Make sure the watchdog is not running */
 717        iTCO_wdt_stop();
 718
 719        /* Check that the heartbeat value is within it's range;
 720           if not reset to the default */
 721        if (iTCO_wdt_set_heartbeat(heartbeat)) {
 722                iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
 723                printk(KERN_INFO PFX
 724                        "heartbeat value must be 2 < heartbeat < 39 (TCO v1) "
 725                                "or 613 (TCO v2), using %d\n", heartbeat);
 726        }
 727
 728        ret = misc_register(&iTCO_wdt_miscdev);
 729        if (ret != 0) {
 730                printk(KERN_ERR PFX
 731                        "cannot register miscdev on minor=%d (err=%d)\n",
 732                                                        WATCHDOG_MINOR, ret);
 733                goto unreg_region;
 734        }
 735
 736        printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
 737                                                        heartbeat, nowayout);
 738
 739        return 0;
 740
 741unreg_region:
 742        release_region(TCOBASE, 0x20);
 743unreg_smi_en:
 744        release_region(SMI_EN, 4);
 745out:
 746        if (iTCO_wdt_private.iTCO_version == 2)
 747                iounmap(iTCO_wdt_private.gcs);
 748        pci_dev_put(iTCO_wdt_private.pdev);
 749        iTCO_wdt_private.ACPIBASE = 0;
 750        return ret;
 751}
 752
 753static void __devexit iTCO_wdt_cleanup(void)
 754{
 755        /* Stop the timer before we leave */
 756        if (!nowayout)
 757                iTCO_wdt_stop();
 758
 759        /* Deregister */
 760        misc_deregister(&iTCO_wdt_miscdev);
 761        release_region(TCOBASE, 0x20);
 762        release_region(SMI_EN, 4);
 763        if (iTCO_wdt_private.iTCO_version == 2)
 764                iounmap(iTCO_wdt_private.gcs);
 765        pci_dev_put(iTCO_wdt_private.pdev);
 766        iTCO_wdt_private.ACPIBASE = 0;
 767}
 768
 769static int __devinit iTCO_wdt_probe(struct platform_device *dev)
 770{
 771        int found = 0;
 772        struct pci_dev *pdev = NULL;
 773        const struct pci_device_id *ent;
 774
 775        spin_lock_init(&iTCO_wdt_private.io_lock);
 776
 777        for_each_pci_dev(pdev) {
 778                ent = pci_match_id(iTCO_wdt_pci_tbl, pdev);
 779                if (ent) {
 780                        if (!(iTCO_wdt_init(pdev, ent, dev))) {
 781                                found++;
 782                                break;
 783                        }
 784                }
 785        }
 786
 787        if (!found) {
 788                printk(KERN_INFO PFX "No card detected\n");
 789                return -ENODEV;
 790        }
 791
 792        return 0;
 793}
 794
 795static int __devexit iTCO_wdt_remove(struct platform_device *dev)
 796{
 797        if (iTCO_wdt_private.ACPIBASE)
 798                iTCO_wdt_cleanup();
 799
 800        return 0;
 801}
 802
 803static void iTCO_wdt_shutdown(struct platform_device *dev)
 804{
 805        iTCO_wdt_stop();
 806}
 807
 808#define iTCO_wdt_suspend NULL
 809#define iTCO_wdt_resume  NULL
 810
 811static struct platform_driver iTCO_wdt_driver = {
 812        .probe          = iTCO_wdt_probe,
 813        .remove         = __devexit_p(iTCO_wdt_remove),
 814        .shutdown       = iTCO_wdt_shutdown,
 815        .suspend        = iTCO_wdt_suspend,
 816        .resume         = iTCO_wdt_resume,
 817        .driver         = {
 818                .owner  = THIS_MODULE,
 819                .name   = DRV_NAME,
 820        },
 821};
 822
 823static int __init iTCO_wdt_init_module(void)
 824{
 825        int err;
 826
 827        printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s\n",
 828                DRV_VERSION);
 829
 830        err = platform_driver_register(&iTCO_wdt_driver);
 831        if (err)
 832                return err;
 833
 834        iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME,
 835                                                                -1, NULL, 0);
 836        if (IS_ERR(iTCO_wdt_platform_device)) {
 837                err = PTR_ERR(iTCO_wdt_platform_device);
 838                goto unreg_platform_driver;
 839        }
 840
 841        return 0;
 842
 843unreg_platform_driver:
 844        platform_driver_unregister(&iTCO_wdt_driver);
 845        return err;
 846}
 847
 848static void __exit iTCO_wdt_cleanup_module(void)
 849{
 850        platform_device_unregister(iTCO_wdt_platform_device);
 851        platform_driver_unregister(&iTCO_wdt_driver);
 852        printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 853}
 854
 855module_init(iTCO_wdt_init_module);
 856module_exit(iTCO_wdt_cleanup_module);
 857
 858MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
 859MODULE_DESCRIPTION("Intel TCO WatchDog Timer Driver");
 860MODULE_VERSION(DRV_VERSION);
 861MODULE_LICENSE("GPL");
 862MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 863