brintos

brintos / linux-shallow public Read only

0
0
Text · 3.5 KiB · 45d0c54 Raw
141 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) STMicroelectronics 20183// 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		020 21#define PMIC_WDT_MIN_TIMEOUT 122#define PMIC_WDT_MAX_TIMEOUT 25623#define PMIC_WDT_DEFAULT_TIMEOUT 3024 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");141