cregit-Linux how code gets into the kernel

Release 4.14 drivers/watchdog/it87_wdt.c

Directory: drivers/watchdog
/*
 *      Watchdog Timer Driver
 *         for ITE IT87xx Environment Control - Low Pin Count Input / Output
 *
 *      (c) Copyright 2007  Oliver Schuster <olivers137@aol.com>
 *
 *      Based on softdog.c      by Alan Cox,
 *               83977f_wdt.c   by Jose Goncalves,
 *               it87.c         by Chris Gauthron, Jean Delvare
 *
 *      Data-sheets: Publicly available at the ITE website
 *                  http://www.ite.com.tw/
 *
 *      Support of the watchdog timers, which are available on
 *      IT8607, IT8620, IT8622, IT8625, IT8628, IT8655, IT8665, IT8686,
 *      IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726, IT8728,
 *      and IT8783.
 *
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/watchdog.h>


#define WATCHDOG_NAME		"IT87 WDT"

/* Defaults for Module Parameter */

#define DEFAULT_TIMEOUT		60

#define DEFAULT_TESTMODE	0

#define DEFAULT_NOWAYOUT	WATCHDOG_NOWAYOUT

/* IO Ports */

#define REG		0x2e

#define VAL		0x2f

/* Logical device Numbers LDN */

#define GPIO		0x07

/* Configuration Registers and Functions */

#define LDNREG		0x07

#define CHIPID		0x20

#define CHIPREV		0x22

/* Chip Id numbers */

#define NO_DEV_ID	0xffff

#define IT8607_ID	0x8607

#define IT8620_ID	0x8620

#define IT8622_ID	0x8622

#define IT8625_ID	0x8625

#define IT8628_ID	0x8628

#define IT8655_ID	0x8655

#define IT8665_ID	0x8665

#define IT8686_ID	0x8686

#define IT8702_ID	0x8702

#define IT8705_ID	0x8705

#define IT8712_ID	0x8712

#define IT8716_ID	0x8716

#define IT8718_ID	0x8718

#define IT8720_ID	0x8720

#define IT8721_ID	0x8721

#define IT8726_ID	0x8726	
/* the data sheet suggest wrongly 0x8716 */

#define IT8728_ID	0x8728

#define IT8783_ID	0x8783

/* GPIO Configuration Registers LDN=0x07 */

#define WDTCTRL		0x71

#define WDTCFG		0x72

#define WDTVALLSB	0x73

#define WDTVALMSB	0x74

/* GPIO Bits WDTCFG */

#define WDT_TOV1	0x80

#define WDT_KRST	0x40

#define WDT_TOVE	0x20

#define WDT_PWROK	0x10 
/* not in it8721 */

#define WDT_INT_MASK	0x0f



static unsigned int max_units, chip_type;


static unsigned int timeout = DEFAULT_TIMEOUT;

static int testmode = DEFAULT_TESTMODE;

static bool nowayout = DEFAULT_NOWAYOUT;

module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default="
		__MODULE_STRING(DEFAULT_TIMEOUT));
module_param(testmode, int, 0);
MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default="
		__MODULE_STRING(DEFAULT_TESTMODE));
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default="
		__MODULE_STRING(WATCHDOG_NOWAYOUT));

/* Superio Chip */


static inline int superio_enter(void) { /* * Try to reserve REG and REG + 1 for exclusive access. */ if (!request_muxed_region(REG, 2, WATCHDOG_NAME)) return -EBUSY; outb(0x87, REG); outb(0x01, REG); outb(0x55, REG); outb(0x55, REG); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster3663.16%150.00%
Nat Gurumoorthy2136.84%150.00%
Total57100.00%2100.00%


static inline void superio_exit(void) { outb(0x02, REG); outb(0x02, VAL); release_region(REG, 2); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster2376.67%150.00%
Nat Gurumoorthy723.33%150.00%
Total30100.00%2100.00%


static inline void superio_select(int ldn) { outb(LDNREG, REG); outb(ldn, VAL); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster24100.00%1100.00%
Total24100.00%1100.00%


static inline int superio_inb(int reg) { outb(reg, REG); return inb(VAL); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster23100.00%1100.00%
Total23100.00%1100.00%


static inline void superio_outb(int val, int reg) { outb(reg, REG); outb(val, VAL); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster27100.00%1100.00%
Total27100.00%1100.00%


static inline int superio_inw(int reg) { int val; outb(reg++, REG); val = inb(VAL) << 8; outb(reg, REG); val |= inb(VAL); return val; }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster47100.00%1100.00%
Total47100.00%1100.00%


static inline void superio_outw(int val, int reg) { outb(reg++, REG); outb(val >> 8, VAL); outb(reg, REG); outb(val, VAL); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster44100.00%1100.00%
Total44100.00%1100.00%

/* Internal function, should be called after superio_select(GPIO) */
static void _wdt_update_timeout(unsigned int t) { unsigned char cfg = WDT_KRST; if (testmode) cfg = 0; if (t <= max_units) cfg |= WDT_TOV1; else t /= 60; if (chip_type != IT8721_ID) cfg |= WDT_PWROK; superio_outb(cfg, WDTCFG); superio_outb(t, WDTVALLSB); if (max_units > 255) superio_outb(t >> 8, WDTVALMSB); }

Contributors

PersonTokensPropCommitsCommitProp
Ondrej Zajicek6076.92%125.00%
Huaro Tomita1012.82%125.00%
Guenter Roeck810.26%250.00%
Total78100.00%4100.00%


static int wdt_update_timeout(unsigned int t) { int ret; ret = superio_enter(); if (ret) return ret; superio_select(GPIO); _wdt_update_timeout(t); superio_exit(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Guenter Roeck41100.00%2100.00%
Total41100.00%2100.00%


static int wdt_round_time(int t) { t += 59; t -= t % 60; return t; }

Contributors

PersonTokensPropCommitsCommitProp
Ondrej Zajicek22100.00%1100.00%
Total22100.00%1100.00%

/* watchdog timer handling */
static int wdt_start(struct watchdog_device *wdd) { return wdt_update_timeout(wdd->timeout); }

Contributors

PersonTokensPropCommitsCommitProp
Guenter Roeck842.11%250.00%
Oliver Schuster842.11%125.00%
Nat Gurumoorthy315.79%125.00%
Total19100.00%4100.00%


static int wdt_stop(struct watchdog_device *wdd) { return wdt_update_timeout(0); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster741.18%125.00%
Guenter Roeck635.29%250.00%
Nat Gurumoorthy423.53%125.00%
Total17100.00%4100.00%

/** * wdt_set_timeout - set a new timeout value with watchdog ioctl * @t: timeout value in seconds * * The hardware device has a 8 or 16 bit watchdog timer (depends on * chip version) that can be configured to count seconds or minutes. * * Used within WDIOC_SETTIMEOUT watchdog device ioctl. */
static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) { int ret = 0; if (t > max_units) t = wdt_round_time(t); wdd->timeout = t; if (watchdog_hw_running(wdd)) ret = wdt_update_timeout(t); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster2646.43%120.00%
Guenter Roeck2035.71%240.00%
Ondrej Zajicek916.07%120.00%
Nat Gurumoorthy11.79%120.00%
Total56100.00%5100.00%

static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .firmware_version = 1, .identity = WATCHDOG_NAME, }; static const struct watchdog_ops wdt_ops = { .owner = THIS_MODULE, .start = wdt_start, .stop = wdt_stop, .set_timeout = wdt_set_timeout, }; static struct watchdog_device wdt_dev = { .info = &ident, .ops = &wdt_ops, .min_timeout = 1, };
static int __init it87_wdt_init(void) { u8 chip_rev; int rc; rc = superio_enter(); if (rc) return rc; chip_type = superio_inw(CHIPID); chip_rev = superio_inb(CHIPREV) & 0x0f; superio_exit(); switch (chip_type) { case IT8702_ID: max_units = 255; break; case IT8712_ID: max_units = (chip_rev < 8) ? 255 : 65535; break; case IT8716_ID: case IT8726_ID: max_units = 65535; break; case IT8607_ID: case IT8620_ID: case IT8622_ID: case IT8625_ID: case IT8628_ID: case IT8655_ID: case IT8665_ID: case IT8686_ID: case IT8718_ID: case IT8720_ID: case IT8721_ID: case IT8728_ID: case IT8783_ID: max_units = 65535; break; case IT8705_ID: pr_err("Unsupported Chip found, Chip %04x Revision %02x\n", chip_type, chip_rev); return -ENODEV; case NO_DEV_ID: pr_err("no device\n"); return -ENODEV; default: pr_err("Unknown Chip found, Chip %04x Revision %04x\n", chip_type, chip_rev); return -ENODEV; } rc = superio_enter(); if (rc) return rc; superio_select(GPIO); superio_outb(WDT_TOV1, WDTCFG); superio_outb(0x00, WDTCTRL); superio_exit(); if (timeout < 1 || timeout > max_units * 60) { timeout = DEFAULT_TIMEOUT; pr_warn("Timeout value out of range, use default %d sec\n", DEFAULT_TIMEOUT); } if (timeout > max_units) timeout = wdt_round_time(timeout); wdt_dev.timeout = timeout; wdt_dev.max_timeout = max_units * 60; watchdog_stop_on_reboot(&wdt_dev); rc = watchdog_register_device(&wdt_dev); if (rc) { pr_err("Cannot register watchdog device (err=%d)\n", rc); return rc; } pr_info("Chip IT%04x revision %d initialized. timeout=%d sec (nowayout=%d testmode=%d)\n", chip_type, chip_rev, timeout, nowayout, testmode); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster13343.32%17.69%
Guenter Roeck8828.66%430.77%
Ondrej Zajicek3712.05%215.38%
Nat Gurumoorthy196.19%17.69%
Joe Perches185.86%17.69%
Diego Elio 'Flameeyes' Pettenò30.98%17.69%
Huaro Tomita30.98%17.69%
Maciej S. Szmigiero30.98%17.69%
Paolo Teti30.98%17.69%
Total307100.00%13100.00%


static void __exit it87_wdt_exit(void) { watchdog_unregister_device(&wdt_dev); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster1386.67%150.00%
Guenter Roeck213.33%150.00%
Total15100.00%2100.00%

module_init(it87_wdt_init); module_exit(it87_wdt_exit); MODULE_AUTHOR("Oliver Schuster"); MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Oliver Schuster65254.74%16.67%
Guenter Roeck27122.75%426.67%
Ondrej Zajicek13911.67%213.33%
Nat Gurumoorthy605.04%16.67%
Joe Perches252.10%16.67%
Huaro Tomita201.68%16.67%
Maciej S. Szmigiero70.59%16.67%
Paolo Teti70.59%16.67%
Diego Elio 'Flameeyes' Pettenò70.59%16.67%
Wim Van Sebroeck20.17%16.67%
Gustavo A. R. Silva10.08%16.67%
Total1191100.00%15100.00%
Directory: drivers/watchdog
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.