root/drivers/watchdog/it87_wdt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. superio_enter
  2. superio_exit
  3. superio_select
  4. superio_inb
  5. superio_outb
  6. superio_inw
  7. superio_outw
  8. _wdt_update_timeout
  9. wdt_update_timeout
  10. wdt_round_time
  11. wdt_start
  12. wdt_stop
  13. wdt_set_timeout
  14. it87_wdt_init
  15. it87_wdt_exit

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

/* [<][>][^][v][top][bottom][index][help] */