linux/drivers/watchdog/it87_wdt.c
<<
>>
Prefs
   1/*
   2 *      Watchdog Timer Driver
   3 *         for ITE IT87xx Environment Control - Low Pin Count Input / Output
   4 *
   5 *      (c) Copyright 2007  Oliver Schuster <olivers137@aol.com>
   6 *
   7 *      Based on softdog.c      by Alan Cox,
   8 *               83977f_wdt.c   by Jose Goncalves,
   9 *               it87.c         by Chris Gauthron, Jean Delvare
  10 *
  11 *      Data-sheets: Publicly available at the ITE website
  12 *                  http://www.ite.com.tw/
  13 *
  14 *      Support of the watchdog timers, which are available on
  15 *      IT8607, IT8620, IT8622, IT8625, IT8628, IT8655, IT8665, IT8686,
  16 *      IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726, IT8728,
  17 *      and IT8783.
  18 *
  19 *      This program is free software; you can redistribute it and/or
  20 *      modify it under the terms of the GNU General Public License
  21 *      as published by the Free Software Foundation; either version
  22 *      2 of the License, or (at your option) any later version.
  23 *
  24 *      This program is distributed in the hope that it will be useful,
  25 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  26 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27 *      GNU General Public License for more details.
  28 */
  29
  30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  31
  32#include <linux/init.h>
  33#include <linux/io.h>
  34#include <linux/kernel.h>
  35#include <linux/module.h>
  36#include <linux/moduleparam.h>
  37#include <linux/types.h>
  38#include <linux/watchdog.h>
  39
  40#define WATCHDOG_NAME           "IT87 WDT"
  41
  42/* Defaults for Module Parameter */
  43#define DEFAULT_TIMEOUT         60
  44#define DEFAULT_TESTMODE        0
  45#define DEFAULT_NOWAYOUT        WATCHDOG_NOWAYOUT
  46
  47/* IO Ports */
  48#define REG             0x2e
  49#define VAL             0x2f
  50
  51/* Logical device Numbers LDN */
  52#define GPIO            0x07
  53
  54/* Configuration Registers and Functions */
  55#define LDNREG          0x07
  56#define CHIPID          0x20
  57#define CHIPREV         0x22
  58
  59/* Chip Id numbers */
  60#define NO_DEV_ID       0xffff
  61#define IT8607_ID       0x8607
  62#define IT8620_ID       0x8620
  63#define IT8622_ID       0x8622
  64#define IT8625_ID       0x8625
  65#define IT8628_ID       0x8628
  66#define IT8655_ID       0x8655
  67#define IT8665_ID       0x8665
  68#define IT8686_ID       0x8686
  69#define IT8702_ID       0x8702
  70#define IT8705_ID       0x8705
  71#define IT8712_ID       0x8712
  72#define IT8716_ID       0x8716
  73#define IT8718_ID       0x8718
  74#define IT8720_ID       0x8720
  75#define IT8721_ID       0x8721
  76#define IT8726_ID       0x8726  /* the data sheet suggest wrongly 0x8716 */
  77#define IT8728_ID       0x8728
  78#define IT8783_ID       0x8783
  79
  80/* GPIO Configuration Registers LDN=0x07 */
  81#define WDTCTRL         0x71
  82#define WDTCFG          0x72
  83#define WDTVALLSB       0x73
  84#define WDTVALMSB       0x74
  85
  86/* GPIO Bits WDTCFG */
  87#define WDT_TOV1        0x80
  88#define WDT_KRST        0x40
  89#define WDT_TOVE        0x20
  90#define WDT_PWROK       0x10 /* not in it8721 */
  91#define WDT_INT_MASK    0x0f
  92
  93static unsigned int max_units, chip_type;
  94
  95static unsigned int timeout = DEFAULT_TIMEOUT;
  96static int testmode = DEFAULT_TESTMODE;
  97static bool nowayout = DEFAULT_NOWAYOUT;
  98
  99module_param(timeout, int, 0);
 100MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default="
 101                __MODULE_STRING(DEFAULT_TIMEOUT));
 102module_param(testmode, int, 0);
 103MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default="
 104                __MODULE_STRING(DEFAULT_TESTMODE));
 105module_param(nowayout, bool, 0);
 106MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default="
 107                __MODULE_STRING(WATCHDOG_NOWAYOUT));
 108
 109/* Superio Chip */
 110
 111static inline int superio_enter(void)
 112{
 113        /*
 114         * Try to reserve REG and REG + 1 for exclusive access.
 115         */
 116        if (!request_muxed_region(REG, 2, WATCHDOG_NAME))
 117                return -EBUSY;
 118
 119        outb(0x87, REG);
 120        outb(0x01, REG);
 121        outb(0x55, REG);
 122        outb(0x55, REG);
 123        return 0;
 124}
 125
 126static inline void superio_exit(void)
 127{
 128        outb(0x02, REG);
 129        outb(0x02, VAL);
 130        release_region(REG, 2);
 131}
 132
 133static inline void superio_select(int ldn)
 134{
 135        outb(LDNREG, REG);
 136        outb(ldn, VAL);
 137}
 138
 139static inline int superio_inb(int reg)
 140{
 141        outb(reg, REG);
 142        return inb(VAL);
 143}
 144
 145static inline void superio_outb(int val, int reg)
 146{
 147        outb(reg, REG);
 148        outb(val, VAL);
 149}
 150
 151static inline int superio_inw(int reg)
 152{
 153        int val;
 154        outb(reg++, REG);
 155        val = inb(VAL) << 8;
 156        outb(reg, REG);
 157        val |= inb(VAL);
 158        return val;
 159}
 160
 161static inline void superio_outw(int val, int reg)
 162{
 163        outb(reg++, REG);
 164        outb(val >> 8, VAL);
 165        outb(reg, REG);
 166        outb(val, VAL);
 167}
 168
 169/* Internal function, should be called after superio_select(GPIO) */
 170static void _wdt_update_timeout(unsigned int t)
 171{
 172        unsigned char cfg = WDT_KRST;
 173
 174        if (testmode)
 175                cfg = 0;
 176
 177        if (t <= max_units)
 178                cfg |= WDT_TOV1;
 179        else
 180                t /= 60;
 181
 182        if (chip_type != IT8721_ID)
 183                cfg |= WDT_PWROK;
 184
 185        superio_outb(cfg, WDTCFG);
 186        superio_outb(t, WDTVALLSB);
 187        if (max_units > 255)
 188                superio_outb(t >> 8, WDTVALMSB);
 189}
 190
 191static int wdt_update_timeout(unsigned int t)
 192{
 193        int ret;
 194
 195        ret = superio_enter();
 196        if (ret)
 197                return ret;
 198
 199        superio_select(GPIO);
 200        _wdt_update_timeout(t);
 201        superio_exit();
 202
 203        return 0;
 204}
 205
 206static int wdt_round_time(int t)
 207{
 208        t += 59;
 209        t -= t % 60;
 210        return t;
 211}
 212
 213/* watchdog timer handling */
 214
 215static int wdt_start(struct watchdog_device *wdd)
 216{
 217        return wdt_update_timeout(wdd->timeout);
 218}
 219
 220static int wdt_stop(struct watchdog_device *wdd)
 221{
 222        return wdt_update_timeout(0);
 223}
 224
 225/**
 226 *      wdt_set_timeout - set a new timeout value with watchdog ioctl
 227 *      @t: timeout value in seconds
 228 *
 229 *      The hardware device has a 8 or 16 bit watchdog timer (depends on
 230 *      chip version) that can be configured to count seconds or minutes.
 231 *
 232 *      Used within WDIOC_SETTIMEOUT watchdog device ioctl.
 233 */
 234
 235static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
 236{
 237        int ret = 0;
 238
 239        if (t > max_units)
 240                t = wdt_round_time(t);
 241
 242        wdd->timeout = t;
 243
 244        if (watchdog_hw_running(wdd))
 245                ret = wdt_update_timeout(t);
 246
 247        return ret;
 248}
 249
 250static const struct watchdog_info ident = {
 251        .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
 252        .firmware_version = 1,
 253        .identity = WATCHDOG_NAME,
 254};
 255
 256static const struct watchdog_ops wdt_ops = {
 257        .owner = THIS_MODULE,
 258        .start = wdt_start,
 259        .stop = wdt_stop,
 260        .set_timeout = wdt_set_timeout,
 261};
 262
 263static struct watchdog_device wdt_dev = {
 264        .info = &ident,
 265        .ops = &wdt_ops,
 266        .min_timeout = 1,
 267};
 268
 269static int __init it87_wdt_init(void)
 270{
 271        u8  chip_rev;
 272        int rc;
 273
 274        rc = superio_enter();
 275        if (rc)
 276                return rc;
 277
 278        chip_type = superio_inw(CHIPID);
 279        chip_rev  = superio_inb(CHIPREV) & 0x0f;
 280        superio_exit();
 281
 282        switch (chip_type) {
 283        case IT8702_ID:
 284                max_units = 255;
 285                break;
 286        case IT8712_ID:
 287                max_units = (chip_rev < 8) ? 255 : 65535;
 288                break;
 289        case IT8716_ID:
 290        case IT8726_ID:
 291                max_units = 65535;
 292                break;
 293        case IT8607_ID:
 294        case IT8620_ID:
 295        case IT8622_ID:
 296        case IT8625_ID:
 297        case IT8628_ID:
 298        case IT8655_ID:
 299        case IT8665_ID:
 300        case IT8686_ID:
 301        case IT8718_ID:
 302        case IT8720_ID:
 303        case IT8721_ID:
 304        case IT8728_ID:
 305        case IT8783_ID:
 306                max_units = 65535;
 307                break;
 308        case IT8705_ID:
 309                pr_err("Unsupported Chip found, Chip %04x Revision %02x\n",
 310                       chip_type, chip_rev);
 311                return -ENODEV;
 312        case NO_DEV_ID:
 313                pr_err("no device\n");
 314                return -ENODEV;
 315        default:
 316                pr_err("Unknown Chip found, Chip %04x Revision %04x\n",
 317                       chip_type, chip_rev);
 318                return -ENODEV;
 319        }
 320
 321        rc = superio_enter();
 322        if (rc)
 323                return rc;
 324
 325        superio_select(GPIO);
 326        superio_outb(WDT_TOV1, WDTCFG);
 327        superio_outb(0x00, WDTCTRL);
 328        superio_exit();
 329
 330        if (timeout < 1 || timeout > max_units * 60) {
 331                timeout = DEFAULT_TIMEOUT;
 332                pr_warn("Timeout value out of range, use default %d sec\n",
 333                        DEFAULT_TIMEOUT);
 334        }
 335
 336        if (timeout > max_units)
 337                timeout = wdt_round_time(timeout);
 338
 339        wdt_dev.timeout = timeout;
 340        wdt_dev.max_timeout = max_units * 60;
 341
 342        watchdog_stop_on_reboot(&wdt_dev);
 343        rc = watchdog_register_device(&wdt_dev);
 344        if (rc) {
 345                pr_err("Cannot register watchdog device (err=%d)\n", rc);
 346                return rc;
 347        }
 348
 349        pr_info("Chip IT%04x revision %d initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
 350                chip_type, chip_rev, timeout, nowayout, testmode);
 351
 352        return 0;
 353}
 354
 355static void __exit it87_wdt_exit(void)
 356{
 357        watchdog_unregister_device(&wdt_dev);
 358}
 359
 360module_init(it87_wdt_init);
 361module_exit(it87_wdt_exit);
 362
 363MODULE_AUTHOR("Oliver Schuster");
 364MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O");
 365MODULE_LICENSE("GPL");
 366