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

stpmic1_wdt.c (3593B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (C) STMicroelectronics 2018
      3// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
      4
      5#include <linux/kernel.h>
      6#include <linux/mfd/stpmic1.h>
      7#include <linux/module.h>
      8#include <linux/platform_device.h>
      9#include <linux/of.h>
     10#include <linux/regmap.h>
     11#include <linux/slab.h>
     12#include <linux/watchdog.h>
     13
     14/* WATCHDOG CONTROL REGISTER bit */
     15#define WDT_START		BIT(0)
     16#define WDT_PING		BIT(1)
     17#define WDT_START_MASK		BIT(0)
     18#define WDT_PING_MASK		BIT(1)
     19#define WDT_STOP		0
     20
     21#define PMIC_WDT_MIN_TIMEOUT 1
     22#define PMIC_WDT_MAX_TIMEOUT 256
     23#define PMIC_WDT_DEFAULT_TIMEOUT 30
     24
     25static bool nowayout = WATCHDOG_NOWAYOUT;
     26module_param(nowayout, bool, 0);
     27MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
     28		 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
     29
     30struct stpmic1_wdt {
     31	struct stpmic1 *pmic;
     32	struct watchdog_device wdtdev;
     33};
     34
     35static int pmic_wdt_start(struct watchdog_device *wdd)
     36{
     37	struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
     38
     39	return regmap_update_bits(wdt->pmic->regmap,
     40				  WCHDG_CR, WDT_START_MASK, WDT_START);
     41}
     42
     43static int pmic_wdt_stop(struct watchdog_device *wdd)
     44{
     45	struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
     46
     47	return regmap_update_bits(wdt->pmic->regmap,
     48				  WCHDG_CR, WDT_START_MASK, WDT_STOP);
     49}
     50
     51static int pmic_wdt_ping(struct watchdog_device *wdd)
     52{
     53	struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
     54
     55	return regmap_update_bits(wdt->pmic->regmap,
     56				  WCHDG_CR, WDT_PING_MASK, WDT_PING);
     57}
     58
     59static int pmic_wdt_set_timeout(struct watchdog_device *wdd,
     60				unsigned int timeout)
     61{
     62	struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
     63
     64	wdd->timeout = timeout;
     65	/* timeout is equal to register value + 1 */
     66	return regmap_write(wdt->pmic->regmap, WCHDG_TIMER_CR, timeout - 1);
     67}
     68
     69static const struct watchdog_info pmic_watchdog_info = {
     70	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
     71	.identity = "STPMIC1 PMIC Watchdog",
     72};
     73
     74static const struct watchdog_ops pmic_watchdog_ops = {
     75	.owner = THIS_MODULE,
     76	.start = pmic_wdt_start,
     77	.stop = pmic_wdt_stop,
     78	.ping = pmic_wdt_ping,
     79	.set_timeout = pmic_wdt_set_timeout,
     80};
     81
     82static int pmic_wdt_probe(struct platform_device *pdev)
     83{
     84	struct device *dev = &pdev->dev;
     85	int ret;
     86	struct stpmic1 *pmic;
     87	struct stpmic1_wdt *wdt;
     88
     89	if (!dev->parent)
     90		return -EINVAL;
     91
     92	pmic = dev_get_drvdata(dev->parent);
     93	if (!pmic)
     94		return -EINVAL;
     95
     96	wdt = devm_kzalloc(dev, sizeof(struct stpmic1_wdt), GFP_KERNEL);
     97	if (!wdt)
     98		return -ENOMEM;
     99
    100	wdt->pmic = pmic;
    101
    102	wdt->wdtdev.info = &pmic_watchdog_info;
    103	wdt->wdtdev.ops = &pmic_watchdog_ops;
    104	wdt->wdtdev.min_timeout = PMIC_WDT_MIN_TIMEOUT;
    105	wdt->wdtdev.max_timeout = PMIC_WDT_MAX_TIMEOUT;
    106	wdt->wdtdev.parent = dev;
    107
    108	wdt->wdtdev.timeout = PMIC_WDT_DEFAULT_TIMEOUT;
    109	watchdog_init_timeout(&wdt->wdtdev, 0, dev);
    110
    111	watchdog_set_nowayout(&wdt->wdtdev, nowayout);
    112	watchdog_set_drvdata(&wdt->wdtdev, wdt);
    113
    114	ret = devm_watchdog_register_device(dev, &wdt->wdtdev);
    115	if (ret)
    116		return ret;
    117
    118	dev_dbg(wdt->pmic->dev, "PMIC Watchdog driver probed\n");
    119	return 0;
    120}
    121
    122static const struct of_device_id of_pmic_wdt_match[] = {
    123	{ .compatible = "st,stpmic1-wdt" },
    124	{ },
    125};
    126
    127MODULE_DEVICE_TABLE(of, of_pmic_wdt_match);
    128
    129static struct platform_driver stpmic1_wdt_driver = {
    130	.probe = pmic_wdt_probe,
    131	.driver = {
    132		.name = "stpmic1-wdt",
    133		.of_match_table = of_pmic_wdt_match,
    134	},
    135};
    136module_platform_driver(stpmic1_wdt_driver);
    137
    138MODULE_DESCRIPTION("Watchdog driver for STPMIC1 device");
    139MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
    140MODULE_LICENSE("GPL v2");