Commit 3a77fa85 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'watchdog-for-linus-v4.10' of...

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
parents 01e0d603 06716128
...@@ -5735,7 +5735,7 @@ S: Maintained ...@@ -5735,7 +5735,7 @@ S: Maintained
F: drivers/media/dvb-frontends/hd29l2* F: drivers/media/dvb-frontends/hd29l2*
HEWLETT PACKARD ENTERPRISE ILO NMI WATCHDOG DRIVER HEWLETT PACKARD ENTERPRISE ILO NMI WATCHDOG DRIVER
M: Brian Boylston <brian.boylston@hpe.com> M: Jimmy Vance <jimmy.vance@hpe.com>
S: Supported S: Supported
F: Documentation/watchdog/hpwdt.txt F: Documentation/watchdog/hpwdt.txt
F: drivers/watchdog/hpwdt.c F: drivers/watchdog/hpwdt.c
......
...@@ -72,16 +72,16 @@ config SOFT_WATCHDOG ...@@ -72,16 +72,16 @@ config SOFT_WATCHDOG
module will be called softdog. module will be called softdog.
config DA9052_WATCHDOG config DA9052_WATCHDOG
tristate "Dialog DA9052 Watchdog" tristate "Dialog DA9052 Watchdog"
depends on PMIC_DA9052 depends on PMIC_DA9052
select WATCHDOG_CORE select WATCHDOG_CORE
help help
Support for the watchdog in the DA9052 PMIC. Watchdog trigger Support for the watchdog in the DA9052 PMIC. Watchdog trigger
cause system reset. cause system reset.
Say Y here to include support for the DA9052 watchdog. Say Y here to include support for the DA9052 watchdog.
Alternatively say M to compile the driver as a module, Alternatively say M to compile the driver as a module,
which will be called da9052_wdt. which will be called da9052_wdt.
config DA9055_WATCHDOG config DA9055_WATCHDOG
tristate "Dialog Semiconductor DA9055 Watchdog" tristate "Dialog Semiconductor DA9055 Watchdog"
...@@ -104,11 +104,11 @@ config DA9063_WATCHDOG ...@@ -104,11 +104,11 @@ config DA9063_WATCHDOG
This driver can be built as a module. The module name is da9063_wdt. This driver can be built as a module. The module name is da9063_wdt.
config DA9062_WATCHDOG config DA9062_WATCHDOG
tristate "Dialog DA9062 Watchdog" tristate "Dialog DA9062/61 Watchdog"
depends on MFD_DA9062 depends on MFD_DA9062
select WATCHDOG_CORE select WATCHDOG_CORE
help 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. This driver can be built as a module. The module name is da9062_wdt.
...@@ -1008,8 +1008,8 @@ config IT87_WDT ...@@ -1008,8 +1008,8 @@ config IT87_WDT
tristate "IT87 Watchdog Timer" tristate "IT87 Watchdog Timer"
depends on X86 depends on X86
---help--- ---help---
This is the driver for the hardware watchdog on the ITE IT8702, This is the driver for the hardware watchdog on the ITE IT8620,
IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 and IT8728 IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 and IT8728
Super I/O chips. Super I/O chips.
If the driver does not work, then make sure that the game port in If the driver does not work, then make sure that the game port in
...@@ -1514,6 +1514,13 @@ config LANTIQ_WDT ...@@ -1514,6 +1514,13 @@ config LANTIQ_WDT
help help
Hardware driver for the Lantiq SoC Watchdog Timer. 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 config RALINK_WDT
tristate "Ralink SoC watchdog" tristate "Ralink SoC watchdog"
select WATCHDOG_CORE select WATCHDOG_CORE
...@@ -1624,16 +1631,16 @@ config BOOKE_WDT_DEFAULT_TIMEOUT ...@@ -1624,16 +1631,16 @@ config BOOKE_WDT_DEFAULT_TIMEOUT
The value can be overridden by the wdt_period command-line parameter. The value can be overridden by the wdt_period command-line parameter.
config MEN_A21_WDT config MEN_A21_WDT
tristate "MEN A21 VME CPU Carrier Board Watchdog Timer" tristate "MEN A21 VME CPU Carrier Board Watchdog Timer"
select WATCHDOG_CORE select WATCHDOG_CORE
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
help help
Watchdog driver for MEN A21 VMEbus CPU Carrier Boards. Watchdog driver for MEN A21 VMEbus CPU Carrier Boards.
The driver can also be built as a module. If so, the module will be The driver can also be built as a module. If so, the module will be
called mena21_wdt. called mena21_wdt.
If unsure select N here. If unsure select N here.
# PPC64 Architecture # PPC64 Architecture
......
...@@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o ...@@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
......
...@@ -55,6 +55,15 @@ struct bcm2835_wdt { ...@@ -55,6 +55,15 @@ struct bcm2835_wdt {
static unsigned int heartbeat; static unsigned int heartbeat;
static bool nowayout = WATCHDOG_NOWAYOUT; 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) static int bcm2835_wdt_start(struct watchdog_device *wdog)
{ {
struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog); struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog);
...@@ -181,6 +190,17 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) ...@@ -181,6 +190,17 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev); watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
watchdog_set_nowayout(&bcm2835_wdt_wdd, nowayout); watchdog_set_nowayout(&bcm2835_wdt_wdd, nowayout);
bcm2835_wdt_wdd.parent = &pdev->dev; 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); err = watchdog_register_device(&bcm2835_wdt_wdd);
if (err) { if (err) {
dev_err(dev, "Failed to register watchdog device"); dev_err(dev, "Failed to register watchdog device");
......
...@@ -216,6 +216,7 @@ static const struct of_device_id bcm7038_wdt_match[] = { ...@@ -216,6 +216,7 @@ static const struct of_device_id bcm7038_wdt_match[] = {
{ .compatible = "brcm,bcm7038-wdt" }, { .compatible = "brcm,bcm7038-wdt" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, bcm7038_wdt_match);
static struct platform_driver bcm7038_wdt_driver = { static struct platform_driver bcm7038_wdt_driver = {
.probe = bcm7038_wdt_probe, .probe = bcm7038_wdt_probe,
......
...@@ -538,12 +538,9 @@ static int cpwd_probe(struct platform_device *op) ...@@ -538,12 +538,9 @@ static int cpwd_probe(struct platform_device *op)
if (cpwd_device) if (cpwd_device)
return -EINVAL; return -EINVAL;
p = kzalloc(sizeof(*p), GFP_KERNEL); p = devm_kzalloc(&op->dev, sizeof(*p), GFP_KERNEL);
err = -ENOMEM; if (!p)
if (!p) { return -ENOMEM;
pr_err("Unable to allocate struct cpwd\n");
goto out;
}
p->irq = op->archdata.irqs[0]; p->irq = op->archdata.irqs[0];
...@@ -553,12 +550,12 @@ static int cpwd_probe(struct platform_device *op) ...@@ -553,12 +550,12 @@ static int cpwd_probe(struct platform_device *op)
4 * WD_TIMER_REGSZ, DRIVER_NAME); 4 * WD_TIMER_REGSZ, DRIVER_NAME);
if (!p->regs) { if (!p->regs) {
pr_err("Unable to map registers\n"); pr_err("Unable to map registers\n");
goto out_free; return -ENOMEM;
} }
options = of_find_node_by_path("/options"); options = of_find_node_by_path("/options");
err = -ENODEV;
if (!options) { if (!options) {
err = -ENODEV;
pr_err("Unable to find /options node\n"); pr_err("Unable to find /options node\n");
goto out_iounmap; goto out_iounmap;
} }
...@@ -620,10 +617,7 @@ static int cpwd_probe(struct platform_device *op) ...@@ -620,10 +617,7 @@ static int cpwd_probe(struct platform_device *op)
platform_set_drvdata(op, p); platform_set_drvdata(op, p);
cpwd_device = p; cpwd_device = p;
err = 0; return 0;
out:
return err;
out_unregister: out_unregister:
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
...@@ -632,9 +626,7 @@ static int cpwd_probe(struct platform_device *op) ...@@ -632,9 +626,7 @@ static int cpwd_probe(struct platform_device *op)
out_iounmap: out_iounmap:
of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ); of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ);
out_free: return err;
kfree(p);
goto out;
} }
static int cpwd_remove(struct platform_device *op) static int cpwd_remove(struct platform_device *op)
...@@ -659,7 +651,6 @@ 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); free_irq(p->irq, p);
of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ); of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ);
kfree(p);
cpwd_device = NULL; cpwd_device = NULL;
......
/* /*
* da9062_wdt.c - WDT device driver for DA9062 * Watchdog device driver for DA9062 and DA9061 PMICs
* Copyright (C) 2015 Dialog Semiconductor Ltd. * Copyright (C) 2015 Dialog Semiconductor Ltd.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -188,6 +188,13 @@ static const struct watchdog_ops da9062_watchdog_ops = { ...@@ -188,6 +188,13 @@ static const struct watchdog_ops da9062_watchdog_ops = {
.set_timeout = da9062_wdt_set_timeout, .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) static int da9062_wdt_probe(struct platform_device *pdev)
{ {
int ret; int ret;
...@@ -244,11 +251,12 @@ static struct platform_driver da9062_wdt_driver = { ...@@ -244,11 +251,12 @@ static struct platform_driver da9062_wdt_driver = {
.remove = da9062_wdt_remove, .remove = da9062_wdt_remove,
.driver = { .driver = {
.name = "da9062-watchdog", .name = "da9062-watchdog",
.of_match_table = da9062_compatible_id_table,
}, },
}; };
module_platform_driver(da9062_wdt_driver); module_platform_driver(da9062_wdt_driver);
MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>"); 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_LICENSE("GPL");
MODULE_ALIAS("platform:da9062-watchdog"); MODULE_ALIAS("platform:da9062-watchdog");
...@@ -166,8 +166,12 @@ static int davinci_wdt_probe(struct platform_device *pdev) ...@@ -166,8 +166,12 @@ static int davinci_wdt_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
davinci_wdt->clk = devm_clk_get(dev, NULL); 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); return PTR_ERR(davinci_wdt->clk);
}
clk_prepare_enable(davinci_wdt->clk); clk_prepare_enable(davinci_wdt->clk);
......
...@@ -43,6 +43,7 @@ static inline int wdt_command(int sub, u32 *in, int inlen) ...@@ -43,6 +43,7 @@ static inline int wdt_command(int sub, u32 *in, int inlen)
static int wdt_start(struct watchdog_device *wd) static int wdt_start(struct watchdog_device *wd)
{ {
struct device *dev = watchdog_get_drvdata(wd);
int ret, in_size; int ret, in_size;
int timeout = wd->timeout; int timeout = wd->timeout;
struct ipc_wd_start { struct ipc_wd_start {
...@@ -57,36 +58,32 @@ static int wdt_start(struct watchdog_device *wd) ...@@ -57,36 +58,32 @@ static int wdt_start(struct watchdog_device *wd)
in_size = DIV_ROUND_UP(sizeof(ipc_wd_start), 4); in_size = DIV_ROUND_UP(sizeof(ipc_wd_start), 4);
ret = wdt_command(SCU_WATCHDOG_START, (u32 *)&ipc_wd_start, in_size); ret = wdt_command(SCU_WATCHDOG_START, (u32 *)&ipc_wd_start, in_size);
if (ret) { if (ret)
struct device *dev = watchdog_get_drvdata(wd);
dev_crit(dev, "error starting watchdog: %d\n", ret); dev_crit(dev, "error starting watchdog: %d\n", ret);
}
return ret; return ret;
} }
static int wdt_ping(struct watchdog_device *wd) static int wdt_ping(struct watchdog_device *wd)
{ {
struct device *dev = watchdog_get_drvdata(wd);
int ret; int ret;
ret = wdt_command(SCU_WATCHDOG_KEEPALIVE, NULL, 0); ret = wdt_command(SCU_WATCHDOG_KEEPALIVE, NULL, 0);
if (ret) { if (ret)
struct device *dev = watchdog_get_drvdata(wd); dev_crit(dev, "Error executing keepalive: %d\n", ret);
dev_crit(dev, "Error executing keepalive: 0x%x\n", ret);
}
return ret; return ret;
} }
static int wdt_stop(struct watchdog_device *wd) static int wdt_stop(struct watchdog_device *wd)
{ {
struct device *dev = watchdog_get_drvdata(wd);
int ret; int ret;
ret = wdt_command(SCU_WATCHDOG_STOP, NULL, 0); ret = wdt_command(SCU_WATCHDOG_STOP, NULL, 0);
if (ret) { if (ret)
struct device *dev = watchdog_get_drvdata(wd); dev_crit(dev, "Error stopping watchdog: %d\n", ret);
dev_crit(dev, "Error stopping watchdog: 0x%x\n", ret);
}
return ret; return ret;
} }
...@@ -151,6 +148,9 @@ static int mid_wdt_probe(struct platform_device *pdev) ...@@ -151,6 +148,9 @@ static int mid_wdt_probe(struct platform_device *pdev)
return ret; return ret;
} }
/* Make sure the watchdog is not running */
wdt_stop(wdt_dev);
ret = watchdog_register_device(wdt_dev); ret = watchdog_register_device(wdt_dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "error registering watchdog device\n"); dev_err(&pdev->dev, "error registering watchdog device\n");
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* http://www.ite.com.tw/ * http://www.ite.com.tw/
* *
* Support of the watchdog timers, which are available on * 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. * IT8728 and IT8783.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
/* Chip Id numbers */ /* Chip Id numbers */
#define NO_DEV_ID 0xffff #define NO_DEV_ID 0xffff
#define IT8620_ID 0x8620
#define IT8702_ID 0x8702 #define IT8702_ID 0x8702
#define IT8705_ID 0x8705 #define IT8705_ID 0x8705
#define IT8712_ID 0x8712 #define IT8712_ID 0x8712
...@@ -630,6 +631,7 @@ static int __init it87_wdt_init(void) ...@@ -630,6 +631,7 @@ static int __init it87_wdt_init(void)
case IT8726_ID: case IT8726_ID:
max_units = 65535; max_units = 65535;
break; break;
case IT8620_ID:
case IT8718_ID: case IT8718_ID:
case IT8720_ID: case IT8720_ID:
case IT8721_ID: case IT8721_ID:
......
...@@ -148,7 +148,7 @@ static const struct of_device_id jz4740_wdt_of_matches[] = { ...@@ -148,7 +148,7 @@ static const struct of_device_id jz4740_wdt_of_matches[] = {
{ .compatible = "ingenic,jz4740-watchdog", }, { .compatible = "ingenic,jz4740-watchdog", },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, jz4740_wdt_of_matches) MODULE_DEVICE_TABLE(of, jz4740_wdt_of_matches);
#endif #endif
static int jz4740_wdt_probe(struct platform_device *pdev) static int jz4740_wdt_probe(struct platform_device *pdev)
......
/*
* 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[] = { ...@@ -205,6 +205,7 @@ static struct platform_device_id max77620_wdt_devtype[] = {
{ .name = "max77620-watchdog", }, { .name = "max77620-watchdog", },
{ }, { },
}; };
MODULE_DEVICE_TABLE(platform, max77620_wdt_devtype);
static struct platform_driver max77620_wdt_driver = { static struct platform_driver max77620_wdt_driver = {
.driver = { .driver = {
......
...@@ -389,6 +389,8 @@ static int mei_wdt_register(struct mei_wdt *wdt) ...@@ -389,6 +389,8 @@ static int mei_wdt_register(struct mei_wdt *wdt)
wdt->wdd.max_timeout = MEI_WDT_MAX_TIMEOUT; wdt->wdd.max_timeout = MEI_WDT_MAX_TIMEOUT;
watchdog_set_drvdata(&wdt->wdd, wdt); watchdog_set_drvdata(&wdt->wdd, wdt);
watchdog_stop_on_reboot(&wdt->wdd);
ret = watchdog_register_device(&wdt->wdd); ret = watchdog_register_device(&wdt->wdd);
if (ret) { if (ret) {
dev_err(dev, "unable to register watchdog device = %d.\n", ret); dev_err(dev, "unable to register watchdog device = %d.\n", ret);
......
...@@ -264,7 +264,6 @@ static struct platform_driver meson_gxbb_wdt_driver = { ...@@ -264,7 +264,6 @@ static struct platform_driver meson_gxbb_wdt_driver = {
module_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_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
MODULE_DESCRIPTION("Amlogic Meson GXBB Watchdog timer driver"); MODULE_DESCRIPTION("Amlogic Meson GXBB Watchdog timer driver");
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/miscdevice.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/module.h> #include <linux/module.h>
......
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/miscdevice.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
......
...@@ -209,7 +209,7 @@ static int qcom_wdt_probe(struct platform_device *pdev) ...@@ -209,7 +209,7 @@ static int qcom_wdt_probe(struct platform_device *pdev)
wdt->wdd.parent = &pdev->dev; wdt->wdd.parent = &pdev->dev;
wdt->layout = regs; wdt->layout = regs;
if (readl(wdt->base + WDT_STS) & 1) if (readl(wdt_addr(wdt, WDT_STS)) & 1)
wdt->wdd.bootstatus = WDIOF_CARDRESET; wdt->wdd.bootstatus = WDIOF_CARDRESET;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment