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

db8500_wdt.c (3729B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) ST-Ericsson SA 2011-2013
      4 *
      5 * Author: Mathieu Poirier <mathieu.poirier@linaro.org> for ST-Ericsson
      6 * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
      7 */
      8
      9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     10
     11#include <linux/module.h>
     12#include <linux/kernel.h>
     13#include <linux/moduleparam.h>
     14#include <linux/err.h>
     15#include <linux/uaccess.h>
     16#include <linux/watchdog.h>
     17#include <linux/platform_device.h>
     18
     19#include <linux/mfd/dbx500-prcmu.h>
     20
     21#define WATCHDOG_TIMEOUT 600 /* 10 minutes */
     22
     23#define WATCHDOG_MIN	0
     24#define WATCHDOG_MAX28	268435  /* 28 bit resolution in ms == 268435.455 s */
     25
     26static unsigned int timeout = WATCHDOG_TIMEOUT;
     27module_param(timeout, uint, 0);
     28MODULE_PARM_DESC(timeout,
     29	"Watchdog timeout in seconds. default="
     30				__MODULE_STRING(WATCHDOG_TIMEOUT) ".");
     31
     32static bool nowayout = WATCHDOG_NOWAYOUT;
     33module_param(nowayout, bool, 0);
     34MODULE_PARM_DESC(nowayout,
     35	"Watchdog cannot be stopped once started (default="
     36				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
     37
     38static int db8500_wdt_start(struct watchdog_device *wdd)
     39{
     40	return prcmu_enable_a9wdog(PRCMU_WDOG_ALL);
     41}
     42
     43static int db8500_wdt_stop(struct watchdog_device *wdd)
     44{
     45	return prcmu_disable_a9wdog(PRCMU_WDOG_ALL);
     46}
     47
     48static int db8500_wdt_keepalive(struct watchdog_device *wdd)
     49{
     50	return prcmu_kick_a9wdog(PRCMU_WDOG_ALL);
     51}
     52
     53static int db8500_wdt_set_timeout(struct watchdog_device *wdd,
     54				 unsigned int timeout)
     55{
     56	db8500_wdt_stop(wdd);
     57	prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
     58	db8500_wdt_start(wdd);
     59
     60	return 0;
     61}
     62
     63static const struct watchdog_info db8500_wdt_info = {
     64	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
     65	.identity = "DB8500 WDT",
     66	.firmware_version = 1,
     67};
     68
     69static const struct watchdog_ops db8500_wdt_ops = {
     70	.owner = THIS_MODULE,
     71	.start = db8500_wdt_start,
     72	.stop  = db8500_wdt_stop,
     73	.ping  = db8500_wdt_keepalive,
     74	.set_timeout = db8500_wdt_set_timeout,
     75};
     76
     77static struct watchdog_device db8500_wdt = {
     78	.info = &db8500_wdt_info,
     79	.ops = &db8500_wdt_ops,
     80	.min_timeout = WATCHDOG_MIN,
     81	.max_timeout = WATCHDOG_MAX28,
     82};
     83
     84static int db8500_wdt_probe(struct platform_device *pdev)
     85{
     86	struct device *dev = &pdev->dev;
     87	int ret;
     88
     89	timeout = 600; /* Default to 10 minutes */
     90	db8500_wdt.parent = dev;
     91	watchdog_set_nowayout(&db8500_wdt, nowayout);
     92
     93	/* disable auto off on sleep */
     94	prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
     95
     96	/* set HW initial value */
     97	prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
     98
     99	ret = devm_watchdog_register_device(dev, &db8500_wdt);
    100	if (ret)
    101		return ret;
    102
    103	dev_info(dev, "initialized\n");
    104
    105	return 0;
    106}
    107
    108#ifdef CONFIG_PM
    109static int db8500_wdt_suspend(struct platform_device *pdev,
    110			     pm_message_t state)
    111{
    112	if (watchdog_active(&db8500_wdt)) {
    113		db8500_wdt_stop(&db8500_wdt);
    114		prcmu_config_a9wdog(PRCMU_WDOG_CPU1, true);
    115
    116		prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
    117		db8500_wdt_start(&db8500_wdt);
    118	}
    119	return 0;
    120}
    121
    122static int db8500_wdt_resume(struct platform_device *pdev)
    123{
    124	if (watchdog_active(&db8500_wdt)) {
    125		db8500_wdt_stop(&db8500_wdt);
    126		prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
    127
    128		prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
    129		db8500_wdt_start(&db8500_wdt);
    130	}
    131	return 0;
    132}
    133#else
    134#define db8500_wdt_suspend NULL
    135#define db8500_wdt_resume NULL
    136#endif
    137
    138static struct platform_driver db8500_wdt_driver = {
    139	.probe		= db8500_wdt_probe,
    140	.suspend	= db8500_wdt_suspend,
    141	.resume		= db8500_wdt_resume,
    142	.driver		= {
    143		.name	= "db8500_wdt",
    144	},
    145};
    146
    147module_platform_driver(db8500_wdt_driver);
    148
    149MODULE_AUTHOR("Jonas Aaberg <jonas.aberg@stericsson.com>");
    150MODULE_DESCRIPTION("DB8500 Watchdog Driver");
    151MODULE_LICENSE("GPL");
    152MODULE_ALIAS("platform:db8500_wdt");