linux/drivers/watchdog/iTCO_wdt.c
<<
>>
Prefs
   1/*
   2 *      intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
   3 *
   4 *      (c) Copyright 2006-2008 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.04"
  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. (2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 277
 278static int nowayout = WATCHDOG_NOWAYOUT;
 279module_param(nowayout, int, 0);
 280MODULE_PARM_DESC(nowayout,
 281        "Watchdog cannot be stopped once started (default="
 282                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 283
 284/*
 285 * Some TCO specific functions
 286 */
 287
 288static inline unsigned int seconds_to_ticks(int seconds)
 289{
 290        /* the internal timer is stored as ticks which decrement
 291         * every 0.6 seconds */
 292        return (seconds * 10) / 6;
 293}
 294
 295static void iTCO_wdt_set_NO_REBOOT_bit(void)
 296{
 297        u32 val32;
 298
 299        /* Set the NO_REBOOT bit: this disables reboots */
 300        if (iTCO_wdt_private.iTCO_version == 2) {
 301                val32 = readl(iTCO_wdt_private.gcs);
 302                val32 |= 0x00000020;
 303                writel(val32, iTCO_wdt_private.gcs);
 304        } else if (iTCO_wdt_private.iTCO_version == 1) {
 305                pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
 306                val32 |= 0x00000002;
 307                pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
 308        }
 309}
 310
 311static int iTCO_wdt_unset_NO_REBOOT_bit(void)
 312{
 313        int ret = 0;
 314        u32 val32;
 315
 316        /* Unset the NO_REBOOT bit: this enables reboots */
 317        if (iTCO_wdt_private.iTCO_version == 2) {
 318                val32 = readl(iTCO_wdt_private.gcs);
 319                val32 &= 0xffffffdf;
 320                writel(val32, iTCO_wdt_private.gcs);
 321
 322                val32 = readl(iTCO_wdt_private.gcs);
 323                if (val32 & 0x00000020)
 324                        ret = -EIO;
 325        } else if (iTCO_wdt_private.iTCO_version == 1) {
 326                pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
 327                val32 &= 0xfffffffd;
 328                pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
 329
 330                pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
 331                if (val32 & 0x00000002)
 332                        ret = -EIO;
 333        }
 334
 335        return ret; /* returns: 0 = OK, -EIO = Error */
 336}
 337
 338static int iTCO_wdt_start(void)
 339{
 340        unsigned int val;
 341        unsigned long val32;
 342
 343        spin_lock(&iTCO_wdt_private.io_lock);
 344
 345        iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat);
 346
 347        /* disable chipset's NO_REBOOT bit */
 348        if (iTCO_wdt_unset_NO_REBOOT_bit()) {
 349                spin_unlock(&iTCO_wdt_private.io_lock);
 350                printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
 351                return -EIO;
 352        }
 353
 354        /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
 355        val32 = inl(SMI_EN);
 356        val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
 357        outl(val32, SMI_EN);
 358
 359        /* Force the timer to its reload value by writing to the TCO_RLD
 360           register */
 361        if (iTCO_wdt_private.iTCO_version == 2)
 362                outw(0x01, TCO_RLD);
 363        else if (iTCO_wdt_private.iTCO_version == 1)
 364                outb(0x01, TCO_RLD);
 365
 366        /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
 367        val = inw(TCO1_CNT);
 368        val &= 0xf7ff;
 369        outw(val, TCO1_CNT);
 370        val = inw(TCO1_CNT);
 371        spin_unlock(&iTCO_wdt_private.io_lock);
 372
 373        if (val & 0x0800)
 374                return -1;
 375        return 0;
 376}
 377
 378static int iTCO_wdt_stop(void)
 379{
 380        unsigned int val;
 381        unsigned long val32;
 382
 383        spin_lock(&iTCO_wdt_private.io_lock);
 384
 385        iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE);
 386
 387        /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
 388        val = inw(TCO1_CNT);
 389        val |= 0x0800;
 390        outw(val, TCO1_CNT);
 391        val = inw(TCO1_CNT);
 392
 393        /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */
 394        val32 = inl(SMI_EN);
 395        val32 |= 0x00002000;
 396        outl(val32, SMI_EN);
 397
 398        /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
 399        iTCO_wdt_set_NO_REBOOT_bit();
 400
 401        spin_unlock(&iTCO_wdt_private.io_lock);
 402
 403        if ((val & 0x0800) == 0)
 404                return -1;
 405        return 0;
 406}
 407
 408static int iTCO_wdt_keepalive(void)
 409{
 410        spin_lock(&iTCO_wdt_private.io_lock);
 411
 412        iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
 413
 414        /* Reload the timer by writing to the TCO Timer Counter register */
 415        if (iTCO_wdt_private.iTCO_version == 2)
 416                outw(0x01, TCO_RLD);
 417        else if (iTCO_wdt_private.iTCO_version == 1)
 418                outb(0x01, TCO_RLD);
 419
 420        spin_unlock(&iTCO_wdt_private.io_lock);
 421        return 0;
 422}
 423
 424static int iTCO_wdt_set_heartbeat(int t)
 425{
 426        unsigned int val16;
 427        unsigned char val8;
 428        unsigned int tmrval;
 429
 430        tmrval = seconds_to_ticks(t);
 431        /* from the specs: */
 432        /* "Values of 0h-3h are ignored and should not be attempted" */
 433        if (tmrval < 0x04)
 434                return -EINVAL;
 435        if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
 436            ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
 437                return -EINVAL;
 438
 439        iTCO_vendor_pre_set_heartbeat(tmrval);
 440
 441        /* Write new heartbeat to watchdog */
 442        if (iTCO_wdt_private.iTCO_version == 2) {
 443                spin_lock(&iTCO_wdt_private.io_lock);
 444                val16 = inw(TCOv2_TMR);
 445                val16 &= 0xfc00;
 446                val16 |= tmrval;
 447                outw(val16, TCOv2_TMR);
 448                val16 = inw(TCOv2_TMR);
 449                spin_unlock(&iTCO_wdt_private.io_lock);
 450
 451                if ((val16 & 0x3ff) != tmrval)
 452                        return -EINVAL;
 453        } else if (iTCO_wdt_private.iTCO_version == 1) {
 454                spin_lock(&iTCO_wdt_private.io_lock);
 455                val8 = inb(TCOv1_TMR);
 456                val8 &= 0xc0;
 457                val8 |= (tmrval & 0xff);
 458                outb(val8, TCOv1_TMR);
 459                val8 = inb(TCOv1_TMR);
 460                spin_unlock(&iTCO_wdt_private.io_lock);
 461
 462                if ((val8 & 0x3f) != tmrval)
 463                        return -EINVAL;
 464        }
 465
 466        heartbeat = t;
 467        return 0;
 468}
 469
 470static int iTCO_wdt_get_timeleft(int *time_left)
 471{
 472        unsigned int val16;
 473        unsigned char val8;
 474
 475        /* read the TCO Timer */
 476        if (iTCO_wdt_private.iTCO_version == 2) {
 477                spin_lock(&iTCO_wdt_private.io_lock);
 478                val16 = inw(TCO_RLD);
 479                val16 &= 0x3ff;
 480                spin_unlock(&iTCO_wdt_private.io_lock);
 481
 482                *time_left = (val16 * 6) / 10;
 483        } else if (iTCO_wdt_private.iTCO_version == 1) {
 484                spin_lock(&iTCO_wdt_private.io_lock);
 485                val8 = inb(TCO_RLD);
 486                val8 &= 0x3f;
 487                spin_unlock(&iTCO_wdt_private.io_lock);
 488
 489                *time_left = (val8 * 6) / 10;
 490        } else
 491                return -EINVAL;
 492        return 0;
 493}
 494
 495/*
 496 *      /dev/watchdog handling
 497 */
 498
 499static int iTCO_wdt_open(struct inode *inode, struct file *file)
 500{
 501        /* /dev/watchdog can only be opened once */
 502        if (test_and_set_bit(0, &is_active))
 503                return -EBUSY;
 504
 505        /*
 506         *      Reload and activate timer
 507         */
 508        iTCO_wdt_start();
 509        return nonseekable_open(inode, file);
 510}
 511
 512static int iTCO_wdt_release(struct inode *inode, struct file *file)
 513{
 514        /*
 515         *      Shut off the timer.
 516         */
 517        if (expect_release == 42) {
 518                iTCO_wdt_stop();
 519        } else {
 520                printk(KERN_CRIT PFX
 521                        "Unexpected close, not stopping watchdog!\n");
 522                iTCO_wdt_keepalive();
 523        }
 524        clear_bit(0, &is_active);
 525        expect_release = 0;
 526        return 0;
 527}
 528
 529static ssize_t iTCO_wdt_write(struct file *file, const char __user *data,
 530                              size_t len, loff_t *ppos)
 531{
 532        /* See if we got the magic character 'V' and reload the timer */
 533        if (len) {
 534                if (!nowayout) {
 535                        size_t i;
 536
 537                        /* note: just in case someone wrote the magic
 538                           character five months ago... */
 539                        expect_release = 0;
 540
 541                        /* scan to see whether or not we got the
 542                           magic character */
 543                        for (i = 0; i != len; i++) {
 544                                char c;
 545                                if (get_user(c, data + i))
 546                                        return -EFAULT;
 547                                if (c == 'V')
 548                                        expect_release = 42;
 549                        }
 550                }
 551
 552                /* someone wrote to us, we should reload the timer */
 553                iTCO_wdt_keepalive();
 554        }
 555        return len;
 556}
 557
 558static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd,
 559                                                        unsigned long arg)
 560{
 561        int new_options, retval = -EINVAL;
 562        int new_heartbeat;
 563        void __user *argp = (void __user *)arg;
 564        int __user *p = argp;
 565        static struct watchdog_info ident = {
 566                .options =              WDIOF_SETTIMEOUT |
 567                                        WDIOF_KEEPALIVEPING |
 568                                        WDIOF_MAGICCLOSE,
 569                .firmware_version =     0,
 570                .identity =             DRV_NAME,
 571        };
 572
 573        switch (cmd) {
 574        case WDIOC_GETSUPPORT:
 575                return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
 576        case WDIOC_GETSTATUS:
 577        case WDIOC_GETBOOTSTATUS:
 578                return put_user(0, p);
 579
 580        case WDIOC_SETOPTIONS:
 581        {
 582                if (get_user(new_options, p))
 583                        return -EFAULT;
 584
 585                if (new_options & WDIOS_DISABLECARD) {
 586                        iTCO_wdt_stop();
 587                        retval = 0;
 588                }
 589                if (new_options & WDIOS_ENABLECARD) {
 590                        iTCO_wdt_keepalive();
 591                        iTCO_wdt_start();
 592                        retval = 0;
 593                }
 594                return retval;
 595        }
 596        case WDIOC_KEEPALIVE:
 597                iTCO_wdt_keepalive();
 598                return 0;
 599
 600        case WDIOC_SETTIMEOUT:
 601        {
 602                if (get_user(new_heartbeat, p))
 603                        return -EFAULT;
 604                if (iTCO_wdt_set_heartbeat(new_heartbeat))
 605                        return -EINVAL;
 606                iTCO_wdt_keepalive();
 607                /* Fall */
 608        }
 609        case WDIOC_GETTIMEOUT:
 610                return put_user(heartbeat, p);
 611        case WDIOC_GETTIMELEFT:
 612        {
 613                int time_left;
 614                if (iTCO_wdt_get_timeleft(&time_left))
 615                        return -EINVAL;
 616                return put_user(time_left, p);
 617        }
 618        default:
 619                return -ENOTTY;
 620        }
 621}
 622
 623/*
 624 *      Kernel Interfaces
 625 */
 626
 627static const struct file_operations iTCO_wdt_fops = {
 628        .owner =                THIS_MODULE,
 629        .llseek =               no_llseek,
 630        .write =                iTCO_wdt_write,
 631        .unlocked_ioctl =       iTCO_wdt_ioctl,
 632        .open =                 iTCO_wdt_open,
 633        .release =              iTCO_wdt_release,
 634};
 635
 636static struct miscdevice iTCO_wdt_miscdev = {
 637        .minor =        WATCHDOG_MINOR,
 638        .name =         "watchdog",
 639        .fops =         &iTCO_wdt_fops,
 640};
 641
 642/*
 643 *      Init & exit routines
 644 */
 645
 646static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
 647                const struct pci_device_id *ent, struct platform_device *dev)
 648{
 649        int ret;
 650        u32 base_address;
 651        unsigned long RCBA;
 652
 653        /*
 654         *      Find the ACPI/PM base I/O address which is the base
 655         *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
 656         *      ACPIBASE is bits [15:7] from 0x40-0x43
 657         */
 658        pci_read_config_dword(pdev, 0x40, &base_address);
 659        base_address &= 0x0000ff80;
 660        if (base_address == 0x00000000) {
 661                /* Something's wrong here, ACPIBASE has to be set */
 662                printk(KERN_ERR PFX "failed to get TCOBASE address\n");
 663                pci_dev_put(pdev);
 664                return -ENODEV;
 665        }
 666        iTCO_wdt_private.iTCO_version =
 667                        iTCO_chipset_info[ent->driver_data].iTCO_version;
 668        iTCO_wdt_private.ACPIBASE = base_address;
 669        iTCO_wdt_private.pdev = pdev;
 670
 671        /* Get the Memory-Mapped GCS register, we need it for the
 672           NO_REBOOT flag (TCO v2). To get access to it you have to
 673           read RCBA from PCI Config space 0xf0 and use it as base.
 674           GCS = RCBA + ICH6_GCS(0x3410). */
 675        if (iTCO_wdt_private.iTCO_version == 2) {
 676                pci_read_config_dword(pdev, 0xf0, &base_address);
 677                RCBA = base_address & 0xffffc000;
 678                iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4);
 679        }
 680
 681        /* Check chipset's NO_REBOOT bit */
 682        if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
 683                printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
 684                ret = -ENODEV;  /* Cannot reset NO_REBOOT bit */
 685                goto out;
 686        }
 687
 688        /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
 689        iTCO_wdt_set_NO_REBOOT_bit();
 690
 691        /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
 692        if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
 693                printk(KERN_ERR PFX
 694                        "I/O address 0x%04lx already in use\n", SMI_EN);
 695                ret = -EIO;
 696                goto out;
 697        }
 698
 699        /* The TCO I/O registers reside in a 32-byte range pointed to
 700           by the TCOBASE value */
 701        if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
 702                printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n",
 703                        TCOBASE);
 704                ret = -EIO;
 705                goto unreg_smi_en;
 706        }
 707
 708        printk(KERN_INFO PFX
 709                "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
 710                        iTCO_chipset_info[ent->driver_data].name,
 711                        iTCO_chipset_info[ent->driver_data].iTCO_version,
 712                        TCOBASE);
 713
 714        /* Clear out the (probably old) status */
 715        outb(8, TCO1_STS);      /* Clear the Time Out Status bit */
 716        outb(2, TCO2_STS);      /* Clear SECOND_TO_STS bit */
 717        outb(4, TCO2_STS);      /* Clear BOOT_STS bit */
 718
 719        /* Make sure the watchdog is not running */
 720        iTCO_wdt_stop();
 721
 722        /* Check that the heartbeat value is within it's range;
 723           if not reset to the default */
 724        if (iTCO_wdt_set_heartbeat(heartbeat)) {
 725                iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
 726                printk(KERN_INFO PFX "heartbeat value must be 2 < heartbeat < 39 (TCO v1) or 613 (TCO v2), using %d\n",
 727                                                        heartbeat);
 728        }
 729
 730        ret = misc_register(&iTCO_wdt_miscdev);
 731        if (ret != 0) {
 732                printk(KERN_ERR PFX
 733                        "cannot register miscdev on minor=%d (err=%d)\n",
 734                                                        WATCHDOG_MINOR, ret);
 735                goto unreg_region;
 736        }
 737
 738        printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
 739                                                        heartbeat, nowayout);
 740
 741        return 0;
 742
 743unreg_region:
 744        release_region(TCOBASE, 0x20);
 745unreg_smi_en:
 746        release_region(SMI_EN, 4);
 747out:
 748        if (iTCO_wdt_private.iTCO_version == 2)
 749                iounmap(iTCO_wdt_private.gcs);
 750        pci_dev_put(iTCO_wdt_private.pdev);
 751        iTCO_wdt_private.ACPIBASE = 0;
 752        return ret;
 753}
 754
 755static void __devexit iTCO_wdt_cleanup(void)
 756{
 757        /* Stop the timer before we leave */
 758        if (!nowayout)
 759                iTCO_wdt_stop();
 760
 761        /* Deregister */
 762        misc_deregister(&iTCO_wdt_miscdev);
 763        release_region(TCOBASE, 0x20);
 764        release_region(SMI_EN, 4);
 765        if (iTCO_wdt_private.iTCO_version == 2)
 766                iounmap(iTCO_wdt_private.gcs);
 767        pci_dev_put(iTCO_wdt_private.pdev);
 768        iTCO_wdt_private.ACPIBASE = 0;
 769}
 770
 771static int __devinit iTCO_wdt_probe(struct platform_device *dev)
 772{
 773        int found = 0;
 774        struct pci_dev *pdev = NULL;
 775        const struct pci_device_id *ent;
 776
 777        spin_lock_init(&iTCO_wdt_private.io_lock);
 778
 779        for_each_pci_dev(pdev) {
 780                ent = pci_match_id(iTCO_wdt_pci_tbl, pdev);
 781                if (ent) {
 782                        if (!(iTCO_wdt_init(pdev, ent, dev))) {
 783                                found++;
 784                                break;
 785                        }
 786                }
 787        }
 788
 789        if (!found) {
 790                printk(KERN_INFO PFX "No card detected\n");
 791                return -ENODEV;
 792        }
 793
 794        return 0;
 795}
 796
 797static int __devexit iTCO_wdt_remove(struct platform_device *dev)
 798{
 799        if (iTCO_wdt_private.ACPIBASE)
 800                iTCO_wdt_cleanup();
 801
 802        return 0;
 803}
 804
 805static void iTCO_wdt_shutdown(struct platform_device *dev)
 806{
 807        iTCO_wdt_stop();
 808}
 809
 810#define iTCO_wdt_suspend NULL
 811#define iTCO_wdt_resume  NULL
 812
 813static struct platform_driver iTCO_wdt_driver = {
 814        .probe          = iTCO_wdt_probe,
 815        .remove         = __devexit_p(iTCO_wdt_remove),
 816        .shutdown       = iTCO_wdt_shutdown,
 817        .suspend        = iTCO_wdt_suspend,
 818        .resume         = iTCO_wdt_resume,
 819        .driver         = {
 820                .owner  = THIS_MODULE,
 821                .name   = DRV_NAME,
 822        },
 823};
 824
 825static int __init iTCO_wdt_init_module(void)
 826{
 827        int err;
 828
 829        printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s\n",
 830                DRV_VERSION);
 831
 832        err = platform_driver_register(&iTCO_wdt_driver);
 833        if (err)
 834                return err;
 835
 836        iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME,
 837                                                                -1, NULL, 0);
 838        if (IS_ERR(iTCO_wdt_platform_device)) {
 839                err = PTR_ERR(iTCO_wdt_platform_device);
 840                goto unreg_platform_driver;
 841        }
 842
 843        return 0;
 844
 845unreg_platform_driver:
 846        platform_driver_unregister(&iTCO_wdt_driver);
 847        return err;
 848}
 849
 850static void __exit iTCO_wdt_cleanup_module(void)
 851{
 852        platform_device_unregister(iTCO_wdt_platform_device);
 853        platform_driver_unregister(&iTCO_wdt_driver);
 854        printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 855}
 856
 857module_init(iTCO_wdt_init_module);
 858module_exit(iTCO_wdt_cleanup_module);
 859
 860MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
 861MODULE_DESCRIPTION("Intel TCO WatchDog Timer Driver");
 862MODULE_VERSION(DRV_VERSION);
 863MODULE_LICENSE("GPL");
 864MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 865