cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ts72xx_wdt.c (4283B)


      1/*
      2 * Watchdog driver for Technologic Systems TS-72xx based SBCs
      3 * (TS-7200, TS-7250 and TS-7260). These boards have external
      4 * glue logic CPLD chip, which includes programmable watchdog
      5 * timer.
      6 *
      7 * Copyright (c) 2009 Mika Westerberg <mika.westerberg@iki.fi>
      8 *
      9 * This driver is based on ep93xx_wdt and wm831x_wdt drivers.
     10 *
     11 * This file is licensed under the terms of the GNU General Public
     12 * License version 2. This program is licensed "as is" without any
     13 * warranty of any kind, whether express or implied.
     14 */
     15
     16#include <linux/platform_device.h>
     17#include <linux/module.h>
     18#include <linux/watchdog.h>
     19#include <linux/io.h>
     20
     21#define TS72XX_WDT_DEFAULT_TIMEOUT	30
     22
     23static int timeout;
     24module_param(timeout, int, 0);
     25MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds.");
     26
     27static bool nowayout = WATCHDOG_NOWAYOUT;
     28module_param(nowayout, bool, 0);
     29MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
     30
     31/* priv->control_reg */
     32#define TS72XX_WDT_CTRL_DISABLE		0x00
     33#define TS72XX_WDT_CTRL_250MS		0x01
     34#define TS72XX_WDT_CTRL_500MS		0x02
     35#define TS72XX_WDT_CTRL_1SEC		0x03
     36#define TS72XX_WDT_CTRL_RESERVED	0x04
     37#define TS72XX_WDT_CTRL_2SEC		0x05
     38#define TS72XX_WDT_CTRL_4SEC		0x06
     39#define TS72XX_WDT_CTRL_8SEC		0x07
     40
     41/* priv->feed_reg */
     42#define TS72XX_WDT_FEED_VAL		0x05
     43
     44struct ts72xx_wdt_priv {
     45	void __iomem	*control_reg;
     46	void __iomem	*feed_reg;
     47	struct watchdog_device wdd;
     48	unsigned char regval;
     49};
     50
     51static int ts72xx_wdt_start(struct watchdog_device *wdd)
     52{
     53	struct ts72xx_wdt_priv *priv = watchdog_get_drvdata(wdd);
     54
     55	writeb(TS72XX_WDT_FEED_VAL, priv->feed_reg);
     56	writeb(priv->regval, priv->control_reg);
     57
     58	return 0;
     59}
     60
     61static int ts72xx_wdt_stop(struct watchdog_device *wdd)
     62{
     63	struct ts72xx_wdt_priv *priv = watchdog_get_drvdata(wdd);
     64
     65	writeb(TS72XX_WDT_FEED_VAL, priv->feed_reg);
     66	writeb(TS72XX_WDT_CTRL_DISABLE, priv->control_reg);
     67
     68	return 0;
     69}
     70
     71static int ts72xx_wdt_ping(struct watchdog_device *wdd)
     72{
     73	struct ts72xx_wdt_priv *priv = watchdog_get_drvdata(wdd);
     74
     75	writeb(TS72XX_WDT_FEED_VAL, priv->feed_reg);
     76
     77	return 0;
     78}
     79
     80static int ts72xx_wdt_settimeout(struct watchdog_device *wdd, unsigned int to)
     81{
     82	struct ts72xx_wdt_priv *priv = watchdog_get_drvdata(wdd);
     83
     84	if (to == 1) {
     85		priv->regval = TS72XX_WDT_CTRL_1SEC;
     86	} else if (to == 2) {
     87		priv->regval = TS72XX_WDT_CTRL_2SEC;
     88	} else if (to <= 4) {
     89		priv->regval = TS72XX_WDT_CTRL_4SEC;
     90		to = 4;
     91	} else {
     92		priv->regval = TS72XX_WDT_CTRL_8SEC;
     93		if (to <= 8)
     94			to = 8;
     95	}
     96
     97	wdd->timeout = to;
     98
     99	if (watchdog_active(wdd)) {
    100		ts72xx_wdt_stop(wdd);
    101		ts72xx_wdt_start(wdd);
    102	}
    103
    104	return 0;
    105}
    106
    107static const struct watchdog_info ts72xx_wdt_ident = {
    108	.options		= WDIOF_KEEPALIVEPING |
    109				  WDIOF_SETTIMEOUT |
    110				  WDIOF_MAGICCLOSE,
    111	.firmware_version	= 1,
    112	.identity		= "TS-72XX WDT",
    113};
    114
    115static const struct watchdog_ops ts72xx_wdt_ops = {
    116	.owner		= THIS_MODULE,
    117	.start		= ts72xx_wdt_start,
    118	.stop		= ts72xx_wdt_stop,
    119	.ping		= ts72xx_wdt_ping,
    120	.set_timeout	= ts72xx_wdt_settimeout,
    121};
    122
    123static int ts72xx_wdt_probe(struct platform_device *pdev)
    124{
    125	struct device *dev = &pdev->dev;
    126	struct ts72xx_wdt_priv *priv;
    127	struct watchdog_device *wdd;
    128	int ret;
    129
    130	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    131	if (!priv)
    132		return -ENOMEM;
    133
    134	priv->control_reg = devm_platform_ioremap_resource(pdev, 0);
    135	if (IS_ERR(priv->control_reg))
    136		return PTR_ERR(priv->control_reg);
    137
    138	priv->feed_reg = devm_platform_ioremap_resource(pdev, 1);
    139	if (IS_ERR(priv->feed_reg))
    140		return PTR_ERR(priv->feed_reg);
    141
    142	wdd = &priv->wdd;
    143	wdd->info = &ts72xx_wdt_ident;
    144	wdd->ops = &ts72xx_wdt_ops;
    145	wdd->min_timeout = 1;
    146	wdd->max_hw_heartbeat_ms = 8000;
    147	wdd->parent = dev;
    148
    149	watchdog_set_nowayout(wdd, nowayout);
    150
    151	wdd->timeout = TS72XX_WDT_DEFAULT_TIMEOUT;
    152	watchdog_init_timeout(wdd, timeout, dev);
    153
    154	watchdog_set_drvdata(wdd, priv);
    155
    156	ret = devm_watchdog_register_device(dev, wdd);
    157	if (ret)
    158		return ret;
    159
    160	dev_info(dev, "TS-72xx Watchdog driver\n");
    161
    162	return 0;
    163}
    164
    165static struct platform_driver ts72xx_wdt_driver = {
    166	.probe		= ts72xx_wdt_probe,
    167	.driver		= {
    168		.name	= "ts72xx-wdt",
    169	},
    170};
    171
    172module_platform_driver(ts72xx_wdt_driver);
    173
    174MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
    175MODULE_DESCRIPTION("TS-72xx SBC Watchdog");
    176MODULE_LICENSE("GPL");
    177MODULE_ALIAS("platform:ts72xx-wdt");