Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Watchdog Timer Driver
0004  *     for ITE IT87xx Environment Control - Low Pin Count Input / Output
0005  *
0006  *  (c) Copyright 2007  Oliver Schuster <olivers137@aol.com>
0007  *
0008  *  Based on softdog.c  by Alan Cox,
0009  *       83977f_wdt.c   by Jose Goncalves,
0010  *       it87.c     by Chris Gauthron, Jean Delvare
0011  *
0012  *  Data-sheets: Publicly available at the ITE website
0013  *          http://www.ite.com.tw/
0014  *
0015  *  Support of the watchdog timers, which are available on
0016  *  IT8607, IT8620, IT8622, IT8625, IT8628, IT8655, IT8665, IT8686,
0017  *  IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726, IT8728,
0018  *  IT8772, IT8783 and IT8784.
0019  */
0020 
0021 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0022 
0023 #include <linux/init.h>
0024 #include <linux/io.h>
0025 #include <linux/kernel.h>
0026 #include <linux/module.h>
0027 #include <linux/moduleparam.h>
0028 #include <linux/types.h>
0029 #include <linux/watchdog.h>
0030 
0031 #define WATCHDOG_NAME       "IT87 WDT"
0032 
0033 /* Defaults for Module Parameter */
0034 #define DEFAULT_TIMEOUT     60
0035 #define DEFAULT_TESTMODE    0
0036 #define DEFAULT_NOWAYOUT    WATCHDOG_NOWAYOUT
0037 
0038 /* IO Ports */
0039 #define REG     0x2e
0040 #define VAL     0x2f
0041 
0042 /* Logical device Numbers LDN */
0043 #define GPIO        0x07
0044 
0045 /* Configuration Registers and Functions */
0046 #define LDNREG      0x07
0047 #define CHIPID      0x20
0048 #define CHIPREV     0x22
0049 
0050 /* Chip Id numbers */
0051 #define NO_DEV_ID   0xffff
0052 #define IT8607_ID   0x8607
0053 #define IT8620_ID   0x8620
0054 #define IT8622_ID   0x8622
0055 #define IT8625_ID   0x8625
0056 #define IT8628_ID   0x8628
0057 #define IT8655_ID   0x8655
0058 #define IT8665_ID   0x8665
0059 #define IT8686_ID   0x8686
0060 #define IT8702_ID   0x8702
0061 #define IT8705_ID   0x8705
0062 #define IT8712_ID   0x8712
0063 #define IT8716_ID   0x8716
0064 #define IT8718_ID   0x8718
0065 #define IT8720_ID   0x8720
0066 #define IT8721_ID   0x8721
0067 #define IT8726_ID   0x8726  /* the data sheet suggest wrongly 0x8716 */
0068 #define IT8728_ID   0x8728
0069 #define IT8772_ID   0x8772
0070 #define IT8783_ID   0x8783
0071 #define IT8784_ID   0x8784
0072 #define IT8786_ID   0x8786
0073 
0074 /* GPIO Configuration Registers LDN=0x07 */
0075 #define WDTCTRL     0x71
0076 #define WDTCFG      0x72
0077 #define WDTVALLSB   0x73
0078 #define WDTVALMSB   0x74
0079 
0080 /* GPIO Bits WDTCFG */
0081 #define WDT_TOV1    0x80
0082 #define WDT_KRST    0x40
0083 #define WDT_TOVE    0x20
0084 #define WDT_PWROK   0x10 /* not in it8721 */
0085 #define WDT_INT_MASK    0x0f
0086 
0087 static unsigned int max_units, chip_type;
0088 
0089 static unsigned int timeout = DEFAULT_TIMEOUT;
0090 static int testmode = DEFAULT_TESTMODE;
0091 static bool nowayout = DEFAULT_NOWAYOUT;
0092 
0093 module_param(timeout, int, 0);
0094 MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default="
0095         __MODULE_STRING(DEFAULT_TIMEOUT));
0096 module_param(testmode, int, 0);
0097 MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default="
0098         __MODULE_STRING(DEFAULT_TESTMODE));
0099 module_param(nowayout, bool, 0);
0100 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default="
0101         __MODULE_STRING(WATCHDOG_NOWAYOUT));
0102 
0103 /* Superio Chip */
0104 
0105 static inline int superio_enter(void)
0106 {
0107     /*
0108      * Try to reserve REG and REG + 1 for exclusive access.
0109      */
0110     if (!request_muxed_region(REG, 2, WATCHDOG_NAME))
0111         return -EBUSY;
0112 
0113     outb(0x87, REG);
0114     outb(0x01, REG);
0115     outb(0x55, REG);
0116     outb(0x55, REG);
0117     return 0;
0118 }
0119 
0120 static inline void superio_exit(void)
0121 {
0122     outb(0x02, REG);
0123     outb(0x02, VAL);
0124     release_region(REG, 2);
0125 }
0126 
0127 static inline void superio_select(int ldn)
0128 {
0129     outb(LDNREG, REG);
0130     outb(ldn, VAL);
0131 }
0132 
0133 static inline int superio_inb(int reg)
0134 {
0135     outb(reg, REG);
0136     return inb(VAL);
0137 }
0138 
0139 static inline void superio_outb(int val, int reg)
0140 {
0141     outb(reg, REG);
0142     outb(val, VAL);
0143 }
0144 
0145 static inline int superio_inw(int reg)
0146 {
0147     int val;
0148     outb(reg++, REG);
0149     val = inb(VAL) << 8;
0150     outb(reg, REG);
0151     val |= inb(VAL);
0152     return val;
0153 }
0154 
0155 /* Internal function, should be called after superio_select(GPIO) */
0156 static void _wdt_update_timeout(unsigned int t)
0157 {
0158     unsigned char cfg = WDT_KRST;
0159 
0160     if (testmode)
0161         cfg = 0;
0162 
0163     if (t <= max_units)
0164         cfg |= WDT_TOV1;
0165     else
0166         t /= 60;
0167 
0168     if (chip_type != IT8721_ID)
0169         cfg |= WDT_PWROK;
0170 
0171     superio_outb(cfg, WDTCFG);
0172     superio_outb(t, WDTVALLSB);
0173     if (max_units > 255)
0174         superio_outb(t >> 8, WDTVALMSB);
0175 }
0176 
0177 static int wdt_update_timeout(unsigned int t)
0178 {
0179     int ret;
0180 
0181     ret = superio_enter();
0182     if (ret)
0183         return ret;
0184 
0185     superio_select(GPIO);
0186     _wdt_update_timeout(t);
0187     superio_exit();
0188 
0189     return 0;
0190 }
0191 
0192 static int wdt_round_time(int t)
0193 {
0194     t += 59;
0195     t -= t % 60;
0196     return t;
0197 }
0198 
0199 /* watchdog timer handling */
0200 
0201 static int wdt_start(struct watchdog_device *wdd)
0202 {
0203     return wdt_update_timeout(wdd->timeout);
0204 }
0205 
0206 static int wdt_stop(struct watchdog_device *wdd)
0207 {
0208     return wdt_update_timeout(0);
0209 }
0210 
0211 /**
0212  *  wdt_set_timeout - set a new timeout value with watchdog ioctl
0213  *  @t: timeout value in seconds
0214  *
0215  *  The hardware device has a 8 or 16 bit watchdog timer (depends on
0216  *  chip version) that can be configured to count seconds or minutes.
0217  *
0218  *  Used within WDIOC_SETTIMEOUT watchdog device ioctl.
0219  */
0220 
0221 static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
0222 {
0223     int ret = 0;
0224 
0225     if (t > max_units)
0226         t = wdt_round_time(t);
0227 
0228     wdd->timeout = t;
0229 
0230     if (watchdog_hw_running(wdd))
0231         ret = wdt_update_timeout(t);
0232 
0233     return ret;
0234 }
0235 
0236 static const struct watchdog_info ident = {
0237     .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
0238     .firmware_version = 1,
0239     .identity = WATCHDOG_NAME,
0240 };
0241 
0242 static const struct watchdog_ops wdt_ops = {
0243     .owner = THIS_MODULE,
0244     .start = wdt_start,
0245     .stop = wdt_stop,
0246     .set_timeout = wdt_set_timeout,
0247 };
0248 
0249 static struct watchdog_device wdt_dev = {
0250     .info = &ident,
0251     .ops = &wdt_ops,
0252     .min_timeout = 1,
0253 };
0254 
0255 static int __init it87_wdt_init(void)
0256 {
0257     u8  chip_rev;
0258     int rc;
0259 
0260     rc = superio_enter();
0261     if (rc)
0262         return rc;
0263 
0264     chip_type = superio_inw(CHIPID);
0265     chip_rev  = superio_inb(CHIPREV) & 0x0f;
0266     superio_exit();
0267 
0268     switch (chip_type) {
0269     case IT8702_ID:
0270         max_units = 255;
0271         break;
0272     case IT8712_ID:
0273         max_units = (chip_rev < 8) ? 255 : 65535;
0274         break;
0275     case IT8716_ID:
0276     case IT8726_ID:
0277         max_units = 65535;
0278         break;
0279     case IT8607_ID:
0280     case IT8620_ID:
0281     case IT8622_ID:
0282     case IT8625_ID:
0283     case IT8628_ID:
0284     case IT8655_ID:
0285     case IT8665_ID:
0286     case IT8686_ID:
0287     case IT8718_ID:
0288     case IT8720_ID:
0289     case IT8721_ID:
0290     case IT8728_ID:
0291     case IT8772_ID:
0292     case IT8783_ID:
0293     case IT8784_ID:
0294     case IT8786_ID:
0295         max_units = 65535;
0296         break;
0297     case IT8705_ID:
0298         pr_err("Unsupported Chip found, Chip %04x Revision %02x\n",
0299                chip_type, chip_rev);
0300         return -ENODEV;
0301     case NO_DEV_ID:
0302         pr_err("no device\n");
0303         return -ENODEV;
0304     default:
0305         pr_err("Unknown Chip found, Chip %04x Revision %04x\n",
0306                chip_type, chip_rev);
0307         return -ENODEV;
0308     }
0309 
0310     rc = superio_enter();
0311     if (rc)
0312         return rc;
0313 
0314     superio_select(GPIO);
0315     superio_outb(WDT_TOV1, WDTCFG);
0316     superio_outb(0x00, WDTCTRL);
0317     superio_exit();
0318 
0319     if (timeout < 1 || timeout > max_units * 60) {
0320         timeout = DEFAULT_TIMEOUT;
0321         pr_warn("Timeout value out of range, use default %d sec\n",
0322             DEFAULT_TIMEOUT);
0323     }
0324 
0325     if (timeout > max_units)
0326         timeout = wdt_round_time(timeout);
0327 
0328     wdt_dev.timeout = timeout;
0329     wdt_dev.max_timeout = max_units * 60;
0330 
0331     watchdog_stop_on_reboot(&wdt_dev);
0332     rc = watchdog_register_device(&wdt_dev);
0333     if (rc) {
0334         pr_err("Cannot register watchdog device (err=%d)\n", rc);
0335         return rc;
0336     }
0337 
0338     pr_info("Chip IT%04x revision %d initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
0339         chip_type, chip_rev, timeout, nowayout, testmode);
0340 
0341     return 0;
0342 }
0343 
0344 static void __exit it87_wdt_exit(void)
0345 {
0346     watchdog_unregister_device(&wdt_dev);
0347 }
0348 
0349 module_init(it87_wdt_init);
0350 module_exit(it87_wdt_exit);
0351 
0352 MODULE_AUTHOR("Oliver Schuster");
0353 MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O");
0354 MODULE_LICENSE("GPL");