Watchdog updates for v4.10
New driver for Add Loongson1 SoC. Minor cleanup and fixes in various drivers. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYXB6QAAoJEMsfJm/On5mBbHkP/3gZFuTGMR0Yb+NCSKvOK1DD 0OgKVA2jrZ4hl4vZUvKwREOo+oiV25AJcN2ISARaWuRqCiA+b4hNZwBamoC+IaP1 Ah3X5lbgUww20JFOVhf0mqsE96S2f9Pd+Vs4QUXr0pPokpRUibwDHMdxKOtivDR4 lGbvUm3rBpfApuimhDpDXQCOx+0dSK2sLMHRn/tq07/uCiRvKvTx8XY1V+OrIEm7 ZGVkaKcPA5f+QBTobfce/numwYNAvCZrR8pnmotSApQtlzl1S/3irdQ0rBAEoRFJ 1F3a2AMoP18CltdsjNG4EhUcd9LbrQstdKRgLVejIs+6/hP4E+kQW0zczNXu6qVk GQVZF8O3Xehp04eaiHt5DKrEg35JcYox/nTfTWA09jg4KNXvKjfrzpNfiIhd2nab 0uqjqGrgP0c6E261JvwPwoXEeCTL3mElP0s8egDWRMlKGIqzAHeuiiUuf7/1ddib vt72j87V4qyoCb1xGD5Xu4+OprvvNtO8jGIjZBqT1JS4Te5ZDa9d8l4s2WkMlNcg FoMVhn0JTyFfKMnbN5y39tRB5/kzCvWlWzH7J3wAWnIVe6I0Vtn64RJrvLj0hm1q UUbVQJRZvQ0akdPz6EOUi1q65++2rhuLvOc6/FITyvKc3nLzp+Q0I3wtyLyW4GCH SheC2fxDnJevmxm0PDln =iGOO -----END PGP SIGNATURE----- Merge tag 'watchdog-for-linus-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull watchdog updates from Wim Van Sebroeck and Guenter Roeck: - new driver for Add Loongson1 SoC - minor cleanup and fixes in various drivers * tag 'watchdog-for-linus-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: watchdog: it87_wdt: add IT8620E ID watchdog: mpc8xxx: Remove unneeded linux/miscdevice.h include watchdog: octeon: Remove unneeded linux/miscdevice.h include watchdog: bcm2835_wdt: set WDOG_HW_RUNNING bit when appropriate watchdog: loongson1: Add Loongson1 SoC watchdog driver watchdog: cpwd: remove memory allocate failure message watchdog: da9062/61: watchdog driver intel-mid_wdt: Error code is just an integer intel-mid_wdt: make sure watchdog is not running at startup watchdog: mei_wdt: request stop on reboot to prevent false positive event watchdog: hpwdt: changed maintainer information watchdog: jz4740: Fix modular build watchdog: qcom: fix kernel panic due to external abort on non-linefetch watchdog: davinci: add support for deferred probing watchdog: meson: Remove unneeded platform MODULE_ALIAS watchdog: Standardize leading tabs and spaces in Kconfig file watchdog: max77620_wdt: fix module autoload watchdog: bcm7038_wdt: fix module autoload
This commit is contained in:
Коммит
3a77fa8544
|
@ -5735,7 +5735,7 @@ S: Maintained
|
|||
F: drivers/media/dvb-frontends/hd29l2*
|
||||
|
||||
HEWLETT PACKARD ENTERPRISE ILO NMI WATCHDOG DRIVER
|
||||
M: Brian Boylston <brian.boylston@hpe.com>
|
||||
M: Jimmy Vance <jimmy.vance@hpe.com>
|
||||
S: Supported
|
||||
F: Documentation/watchdog/hpwdt.txt
|
||||
F: drivers/watchdog/hpwdt.c
|
||||
|
|
|
@ -72,16 +72,16 @@ config SOFT_WATCHDOG
|
|||
module will be called softdog.
|
||||
|
||||
config DA9052_WATCHDOG
|
||||
tristate "Dialog DA9052 Watchdog"
|
||||
depends on PMIC_DA9052
|
||||
select WATCHDOG_CORE
|
||||
help
|
||||
Support for the watchdog in the DA9052 PMIC. Watchdog trigger
|
||||
cause system reset.
|
||||
tristate "Dialog DA9052 Watchdog"
|
||||
depends on PMIC_DA9052
|
||||
select WATCHDOG_CORE
|
||||
help
|
||||
Support for the watchdog in the DA9052 PMIC. Watchdog trigger
|
||||
cause system reset.
|
||||
|
||||
Say Y here to include support for the DA9052 watchdog.
|
||||
Alternatively say M to compile the driver as a module,
|
||||
which will be called da9052_wdt.
|
||||
Say Y here to include support for the DA9052 watchdog.
|
||||
Alternatively say M to compile the driver as a module,
|
||||
which will be called da9052_wdt.
|
||||
|
||||
config DA9055_WATCHDOG
|
||||
tristate "Dialog Semiconductor DA9055 Watchdog"
|
||||
|
@ -104,11 +104,11 @@ config DA9063_WATCHDOG
|
|||
This driver can be built as a module. The module name is da9063_wdt.
|
||||
|
||||
config DA9062_WATCHDOG
|
||||
tristate "Dialog DA9062 Watchdog"
|
||||
tristate "Dialog DA9062/61 Watchdog"
|
||||
depends on MFD_DA9062
|
||||
select WATCHDOG_CORE
|
||||
help
|
||||
Support for the watchdog in the DA9062 PMIC.
|
||||
Support for the watchdog in the DA9062 and DA9061 PMICs.
|
||||
|
||||
This driver can be built as a module. The module name is da9062_wdt.
|
||||
|
||||
|
@ -1008,8 +1008,8 @@ config IT87_WDT
|
|||
tristate "IT87 Watchdog Timer"
|
||||
depends on X86
|
||||
---help---
|
||||
This is the driver for the hardware watchdog on the ITE IT8702,
|
||||
IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 and IT8728
|
||||
This is the driver for the hardware watchdog on the ITE IT8620,
|
||||
IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 and IT8728
|
||||
Super I/O chips.
|
||||
|
||||
If the driver does not work, then make sure that the game port in
|
||||
|
@ -1514,6 +1514,13 @@ config LANTIQ_WDT
|
|||
help
|
||||
Hardware driver for the Lantiq SoC Watchdog Timer.
|
||||
|
||||
config LOONGSON1_WDT
|
||||
tristate "Loongson1 SoC hardware watchdog"
|
||||
depends on MACH_LOONGSON32
|
||||
select WATCHDOG_CORE
|
||||
help
|
||||
Hardware driver for the Loongson1 SoC Watchdog Timer.
|
||||
|
||||
config RALINK_WDT
|
||||
tristate "Ralink SoC watchdog"
|
||||
select WATCHDOG_CORE
|
||||
|
@ -1624,16 +1631,16 @@ config BOOKE_WDT_DEFAULT_TIMEOUT
|
|||
The value can be overridden by the wdt_period command-line parameter.
|
||||
|
||||
config MEN_A21_WDT
|
||||
tristate "MEN A21 VME CPU Carrier Board Watchdog Timer"
|
||||
select WATCHDOG_CORE
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
help
|
||||
Watchdog driver for MEN A21 VMEbus CPU Carrier Boards.
|
||||
tristate "MEN A21 VME CPU Carrier Board Watchdog Timer"
|
||||
select WATCHDOG_CORE
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
help
|
||||
Watchdog driver for MEN A21 VMEbus CPU Carrier Boards.
|
||||
|
||||
The driver can also be built as a module. If so, the module will be
|
||||
called mena21_wdt.
|
||||
The driver can also be built as a module. If so, the module will be
|
||||
called mena21_wdt.
|
||||
|
||||
If unsure select N here.
|
||||
If unsure select N here.
|
||||
|
||||
# PPC64 Architecture
|
||||
|
||||
|
|
|
@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
|
|||
obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
|
||||
octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
|
||||
obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
|
||||
obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
|
||||
obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
|
||||
obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
|
||||
obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
|
||||
|
|
|
@ -55,6 +55,15 @@ struct bcm2835_wdt {
|
|||
static unsigned int heartbeat;
|
||||
static bool nowayout = WATCHDOG_NOWAYOUT;
|
||||
|
||||
static bool bcm2835_wdt_is_running(struct bcm2835_wdt *wdt)
|
||||
{
|
||||
uint32_t cur;
|
||||
|
||||
cur = readl(wdt->base + PM_RSTC);
|
||||
|
||||
return !!(cur & PM_RSTC_WRCFG_FULL_RESET);
|
||||
}
|
||||
|
||||
static int bcm2835_wdt_start(struct watchdog_device *wdog)
|
||||
{
|
||||
struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog);
|
||||
|
@ -181,6 +190,17 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
|
|||
watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
|
||||
watchdog_set_nowayout(&bcm2835_wdt_wdd, nowayout);
|
||||
bcm2835_wdt_wdd.parent = &pdev->dev;
|
||||
if (bcm2835_wdt_is_running(wdt)) {
|
||||
/*
|
||||
* The currently active timeout value (set by the
|
||||
* bootloader) may be different from the module
|
||||
* heartbeat parameter or the value in device
|
||||
* tree. But we just need to set WDOG_HW_RUNNING,
|
||||
* because then the framework will "immediately" ping
|
||||
* the device, updating the timeout.
|
||||
*/
|
||||
set_bit(WDOG_HW_RUNNING, &bcm2835_wdt_wdd.status);
|
||||
}
|
||||
err = watchdog_register_device(&bcm2835_wdt_wdd);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to register watchdog device");
|
||||
|
|
|
@ -216,6 +216,7 @@ static const struct of_device_id bcm7038_wdt_match[] = {
|
|||
{ .compatible = "brcm,bcm7038-wdt" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bcm7038_wdt_match);
|
||||
|
||||
static struct platform_driver bcm7038_wdt_driver = {
|
||||
.probe = bcm7038_wdt_probe,
|
||||
|
|
|
@ -538,12 +538,9 @@ static int cpwd_probe(struct platform_device *op)
|
|||
if (cpwd_device)
|
||||
return -EINVAL;
|
||||
|
||||
p = kzalloc(sizeof(*p), GFP_KERNEL);
|
||||
err = -ENOMEM;
|
||||
if (!p) {
|
||||
pr_err("Unable to allocate struct cpwd\n");
|
||||
goto out;
|
||||
}
|
||||
p = devm_kzalloc(&op->dev, sizeof(*p), GFP_KERNEL);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
p->irq = op->archdata.irqs[0];
|
||||
|
||||
|
@ -553,12 +550,12 @@ static int cpwd_probe(struct platform_device *op)
|
|||
4 * WD_TIMER_REGSZ, DRIVER_NAME);
|
||||
if (!p->regs) {
|
||||
pr_err("Unable to map registers\n");
|
||||
goto out_free;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
options = of_find_node_by_path("/options");
|
||||
err = -ENODEV;
|
||||
if (!options) {
|
||||
err = -ENODEV;
|
||||
pr_err("Unable to find /options node\n");
|
||||
goto out_iounmap;
|
||||
}
|
||||
|
@ -620,10 +617,7 @@ static int cpwd_probe(struct platform_device *op)
|
|||
|
||||
platform_set_drvdata(op, p);
|
||||
cpwd_device = p;
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
return err;
|
||||
return 0;
|
||||
|
||||
out_unregister:
|
||||
for (i--; i >= 0; i--)
|
||||
|
@ -632,9 +626,7 @@ out_unregister:
|
|||
out_iounmap:
|
||||
of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ);
|
||||
|
||||
out_free:
|
||||
kfree(p);
|
||||
goto out;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cpwd_remove(struct platform_device *op)
|
||||
|
@ -659,7 +651,6 @@ static int cpwd_remove(struct platform_device *op)
|
|||
free_irq(p->irq, p);
|
||||
|
||||
of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ);
|
||||
kfree(p);
|
||||
|
||||
cpwd_device = NULL;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* da9062_wdt.c - WDT device driver for DA9062
|
||||
* Watchdog device driver for DA9062 and DA9061 PMICs
|
||||
* Copyright (C) 2015 Dialog Semiconductor Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -188,6 +188,13 @@ static const struct watchdog_ops da9062_watchdog_ops = {
|
|||
.set_timeout = da9062_wdt_set_timeout,
|
||||
};
|
||||
|
||||
static const struct of_device_id da9062_compatible_id_table[] = {
|
||||
{ .compatible = "dlg,da9062-watchdog", },
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, da9062_compatible_id_table);
|
||||
|
||||
static int da9062_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
@ -244,11 +251,12 @@ static struct platform_driver da9062_wdt_driver = {
|
|||
.remove = da9062_wdt_remove,
|
||||
.driver = {
|
||||
.name = "da9062-watchdog",
|
||||
.of_match_table = da9062_compatible_id_table,
|
||||
},
|
||||
};
|
||||
module_platform_driver(da9062_wdt_driver);
|
||||
|
||||
MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
|
||||
MODULE_DESCRIPTION("WDT device driver for Dialog DA9062");
|
||||
MODULE_DESCRIPTION("WDT device driver for Dialog DA9062 and DA9061");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:da9062-watchdog");
|
||||
|
|
|
@ -166,8 +166,12 @@ static int davinci_wdt_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
|
||||
davinci_wdt->clk = devm_clk_get(dev, NULL);
|
||||
if (WARN_ON(IS_ERR(davinci_wdt->clk)))
|
||||
|
||||
if (IS_ERR(davinci_wdt->clk)) {
|
||||
if (PTR_ERR(davinci_wdt->clk) != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "failed to get clock node\n");
|
||||
return PTR_ERR(davinci_wdt->clk);
|
||||
}
|
||||
|
||||
clk_prepare_enable(davinci_wdt->clk);
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ static inline int wdt_command(int sub, u32 *in, int inlen)
|
|||
|
||||
static int wdt_start(struct watchdog_device *wd)
|
||||
{
|
||||
struct device *dev = watchdog_get_drvdata(wd);
|
||||
int ret, in_size;
|
||||
int timeout = wd->timeout;
|
||||
struct ipc_wd_start {
|
||||
|
@ -57,36 +58,32 @@ static int wdt_start(struct watchdog_device *wd)
|
|||
in_size = DIV_ROUND_UP(sizeof(ipc_wd_start), 4);
|
||||
|
||||
ret = wdt_command(SCU_WATCHDOG_START, (u32 *)&ipc_wd_start, in_size);
|
||||
if (ret) {
|
||||
struct device *dev = watchdog_get_drvdata(wd);
|
||||
if (ret)
|
||||
dev_crit(dev, "error starting watchdog: %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wdt_ping(struct watchdog_device *wd)
|
||||
{
|
||||
struct device *dev = watchdog_get_drvdata(wd);
|
||||
int ret;
|
||||
|
||||
ret = wdt_command(SCU_WATCHDOG_KEEPALIVE, NULL, 0);
|
||||
if (ret) {
|
||||
struct device *dev = watchdog_get_drvdata(wd);
|
||||
dev_crit(dev, "Error executing keepalive: 0x%x\n", ret);
|
||||
}
|
||||
if (ret)
|
||||
dev_crit(dev, "Error executing keepalive: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wdt_stop(struct watchdog_device *wd)
|
||||
{
|
||||
struct device *dev = watchdog_get_drvdata(wd);
|
||||
int ret;
|
||||
|
||||
ret = wdt_command(SCU_WATCHDOG_STOP, NULL, 0);
|
||||
if (ret) {
|
||||
struct device *dev = watchdog_get_drvdata(wd);
|
||||
dev_crit(dev, "Error stopping watchdog: 0x%x\n", ret);
|
||||
}
|
||||
if (ret)
|
||||
dev_crit(dev, "Error stopping watchdog: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -151,6 +148,9 @@ static int mid_wdt_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Make sure the watchdog is not running */
|
||||
wdt_stop(wdt_dev);
|
||||
|
||||
ret = watchdog_register_device(wdt_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "error registering watchdog device\n");
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
* http://www.ite.com.tw/
|
||||
*
|
||||
* Support of the watchdog timers, which are available on
|
||||
* IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726,
|
||||
* IT8620, IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726,
|
||||
* IT8728 and IT8783.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -78,6 +78,7 @@
|
|||
|
||||
/* Chip Id numbers */
|
||||
#define NO_DEV_ID 0xffff
|
||||
#define IT8620_ID 0x8620
|
||||
#define IT8702_ID 0x8702
|
||||
#define IT8705_ID 0x8705
|
||||
#define IT8712_ID 0x8712
|
||||
|
@ -630,6 +631,7 @@ static int __init it87_wdt_init(void)
|
|||
case IT8726_ID:
|
||||
max_units = 65535;
|
||||
break;
|
||||
case IT8620_ID:
|
||||
case IT8718_ID:
|
||||
case IT8720_ID:
|
||||
case IT8721_ID:
|
||||
|
|
|
@ -148,7 +148,7 @@ static const struct of_device_id jz4740_wdt_of_matches[] = {
|
|||
{ .compatible = "ingenic,jz4740-watchdog", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, jz4740_wdt_of_matches)
|
||||
MODULE_DEVICE_TABLE(of, jz4740_wdt_of_matches);
|
||||
#endif
|
||||
|
||||
static int jz4740_wdt_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Yang Ling <gnaygnil@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <loongson1.h>
|
||||
|
||||
#define DEFAULT_HEARTBEAT 30
|
||||
|
||||
static bool nowayout = WATCHDOG_NOWAYOUT;
|
||||
module_param(nowayout, bool, 0444);
|
||||
|
||||
static unsigned int heartbeat;
|
||||
module_param(heartbeat, uint, 0444);
|
||||
|
||||
struct ls1x_wdt_drvdata {
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
unsigned long clk_rate;
|
||||
struct watchdog_device wdt;
|
||||
};
|
||||
|
||||
static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
|
||||
{
|
||||
struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
|
||||
|
||||
writel(0x1, drvdata->base + WDT_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
|
||||
unsigned int timeout)
|
||||
{
|
||||
struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
|
||||
unsigned int max_hw_heartbeat = wdt_dev->max_hw_heartbeat_ms / 1000;
|
||||
unsigned int counts;
|
||||
|
||||
wdt_dev->timeout = timeout;
|
||||
|
||||
counts = drvdata->clk_rate * min(timeout, max_hw_heartbeat);
|
||||
writel(counts, drvdata->base + WDT_TIMER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
|
||||
{
|
||||
struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
|
||||
|
||||
writel(0x1, drvdata->base + WDT_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
|
||||
{
|
||||
struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
|
||||
|
||||
writel(0x0, drvdata->base + WDT_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct watchdog_info ls1x_wdt_info = {
|
||||
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
|
||||
.identity = "Loongson1 Watchdog",
|
||||
};
|
||||
|
||||
static const struct watchdog_ops ls1x_wdt_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = ls1x_wdt_start,
|
||||
.stop = ls1x_wdt_stop,
|
||||
.ping = ls1x_wdt_ping,
|
||||
.set_timeout = ls1x_wdt_set_timeout,
|
||||
};
|
||||
|
||||
static int ls1x_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ls1x_wdt_drvdata *drvdata;
|
||||
struct watchdog_device *ls1x_wdt;
|
||||
unsigned long clk_rate;
|
||||
struct resource *res;
|
||||
int err;
|
||||
|
||||
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
drvdata->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(drvdata->base))
|
||||
return PTR_ERR(drvdata->base);
|
||||
|
||||
drvdata->clk = devm_clk_get(&pdev->dev, pdev->name);
|
||||
if (IS_ERR(drvdata->clk))
|
||||
return PTR_ERR(drvdata->clk);
|
||||
|
||||
err = clk_prepare_enable(drvdata->clk);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "clk enable failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
clk_rate = clk_get_rate(drvdata->clk);
|
||||
if (!clk_rate) {
|
||||
err = -EINVAL;
|
||||
goto err0;
|
||||
}
|
||||
drvdata->clk_rate = clk_rate;
|
||||
|
||||
ls1x_wdt = &drvdata->wdt;
|
||||
ls1x_wdt->info = &ls1x_wdt_info;
|
||||
ls1x_wdt->ops = &ls1x_wdt_ops;
|
||||
ls1x_wdt->timeout = DEFAULT_HEARTBEAT;
|
||||
ls1x_wdt->min_timeout = 1;
|
||||
ls1x_wdt->max_hw_heartbeat_ms = U32_MAX / clk_rate * 1000;
|
||||
ls1x_wdt->parent = &pdev->dev;
|
||||
|
||||
watchdog_init_timeout(ls1x_wdt, heartbeat, &pdev->dev);
|
||||
watchdog_set_nowayout(ls1x_wdt, nowayout);
|
||||
watchdog_set_drvdata(ls1x_wdt, drvdata);
|
||||
|
||||
err = watchdog_register_device(&drvdata->wdt);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to register watchdog device\n");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
dev_info(&pdev->dev, "Loongson1 Watchdog driver registered\n");
|
||||
|
||||
return 0;
|
||||
err0:
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ls1x_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ls1x_wdt_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
watchdog_unregister_device(&drvdata->wdt);
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ls1x_wdt_driver = {
|
||||
.probe = ls1x_wdt_probe,
|
||||
.remove = ls1x_wdt_remove,
|
||||
.driver = {
|
||||
.name = "ls1x-wdt",
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(ls1x_wdt_driver);
|
||||
|
||||
MODULE_AUTHOR("Yang Ling <gnaygnil@gmail.com>");
|
||||
MODULE_DESCRIPTION("Loongson1 Watchdog Driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -205,6 +205,7 @@ static struct platform_device_id max77620_wdt_devtype[] = {
|
|||
{ .name = "max77620-watchdog", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, max77620_wdt_devtype);
|
||||
|
||||
static struct platform_driver max77620_wdt_driver = {
|
||||
.driver = {
|
||||
|
|
|
@ -389,6 +389,8 @@ static int mei_wdt_register(struct mei_wdt *wdt)
|
|||
wdt->wdd.max_timeout = MEI_WDT_MAX_TIMEOUT;
|
||||
|
||||
watchdog_set_drvdata(&wdt->wdd, wdt);
|
||||
watchdog_stop_on_reboot(&wdt->wdd);
|
||||
|
||||
ret = watchdog_register_device(&wdt->wdd);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to register watchdog device = %d.\n", ret);
|
||||
|
|
|
@ -264,7 +264,6 @@ static struct platform_driver meson_gxbb_wdt_driver = {
|
|||
|
||||
module_platform_driver(meson_gxbb_wdt_driver);
|
||||
|
||||
MODULE_ALIAS("platform:meson-gxbb-wdt");
|
||||
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
|
||||
MODULE_DESCRIPTION("Amlogic Meson GXBB Watchdog timer driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <linux/cpumask.h>
|
||||
|
|
|
@ -209,7 +209,7 @@ static int qcom_wdt_probe(struct platform_device *pdev)
|
|||
wdt->wdd.parent = &pdev->dev;
|
||||
wdt->layout = regs;
|
||||
|
||||
if (readl(wdt->base + WDT_STS) & 1)
|
||||
if (readl(wdt_addr(wdt, WDT_STS)) & 1)
|
||||
wdt->wdd.bootstatus = WDIOF_CARDRESET;
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче