mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
linux-watchdog 5.11-rc1 tag
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iEYEABECAAYFAl/jfRcACgkQ+iyteGJfRspXnQCfYAyqptMHDHGC98z5kFpsIcxg R6MAmQG3jN5aUiwrKcGG2NxQlEGeGVLq =bHWM -----END PGP SIGNATURE----- Merge tag 'linux-watchdog-5.11-rc1' of git://www.linux-watchdog.org/linux-watchdog Pull watchdog updates from Wim Van Sebroeck: - Removal of the pnx83xx driver - Add a binding for A100's watchdog controller - Add Rockchip compatibles to snps,dw-wdt.yaml - hpwdt: Disable NMI in Crash Kernel - Fix potential dereferencing of null pointer in watchdog_core - Several other small fixes and improvements * tag 'linux-watchdog-5.11-rc1' of git://www.linux-watchdog.org/linux-watchdog: (23 commits) watchdog: convert comma to semicolon watchdog: iTCO_wdt: use dev_*() instead of pr_*() for logging dt-binding: watchdog: add Rockchip compatibles to snps,dw-wdt.yaml watchdog: coh901327: add COMMON_CLK dependency dt-bindings: watchdog: sun4i: Add A100 compatible watchdog: qcom: Avoid context switch in restart handler watchdog: iTCO_wdt: use module_platform_device() macro watchdog: Fix potential dereferencing of null pointer watchdog: wdat_wdt: Fix missing kerneldoc reported by W=1 watchdog/hpwdt: Reflect changes watchdog/hpwdt: Disable NMI in Crash Kernel wdt: sp805: add watchdog_stop on reboot watchdog: sbc_fitpc2_wdt: add __user annotations watchdog: geodewdt: remove unneeded break watchdog: rti-wdt: fix reference leak in rti_wdt_probe watchdog: qcom_wdt: set WDOG_HW_RUNNING bit when appropriate watchdog: remove pnx83xx driver watchdog: stm32_iwdg: don't print an error on probe deferral watchdog: sprd: change to use usleep_range() instead of busy loop watchdog: sprd: check busy bit before new loading rather than after that ...
This commit is contained in:
commit
6755f45631
|
@ -21,6 +21,9 @@ properties:
|
|||
- items:
|
||||
- const: allwinner,sun50i-a64-wdt
|
||||
- const: allwinner,sun6i-a31-wdt
|
||||
- items:
|
||||
- const: allwinner,sun50i-a100-wdt
|
||||
- const: allwinner,sun6i-a31-wdt
|
||||
- items:
|
||||
- const: allwinner,sun50i-h6-wdt
|
||||
- const: allwinner,sun6i-a31-wdt
|
||||
|
|
|
@ -14,7 +14,15 @@ maintainers:
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
const: snps,dw-wdt
|
||||
oneOf:
|
||||
- const: snps,dw-wdt
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,rk3066-wdt
|
||||
- rockchip,rk3188-wdt
|
||||
- rockchip,rk3288-wdt
|
||||
- rockchip,rk3368-wdt
|
||||
- const: snps,dw-wdt
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -386,6 +386,7 @@ config ARM_SBSA_WATCHDOG
|
|||
config ARMADA_37XX_WATCHDOG
|
||||
tristate "Armada 37xx watchdog"
|
||||
depends on ARCH_MVEBU || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
select MFD_SYSCON
|
||||
select WATCHDOG_CORE
|
||||
help
|
||||
|
@ -631,7 +632,7 @@ config SUNXI_WATCHDOG
|
|||
|
||||
config COH901327_WATCHDOG
|
||||
bool "ST-Ericsson COH 901 327 watchdog"
|
||||
depends on ARCH_U300 || (ARM && COMPILE_TEST)
|
||||
depends on ARCH_U300 || (ARM && COMMON_CLK && COMPILE_TEST)
|
||||
default y if MACH_U300
|
||||
select WATCHDOG_CORE
|
||||
help
|
||||
|
@ -789,6 +790,7 @@ config MOXART_WDT
|
|||
|
||||
config SIRFSOC_WATCHDOG
|
||||
tristate "SiRFSOC watchdog"
|
||||
depends on HAS_IOMEM
|
||||
depends on ARCH_SIRF || COMPILE_TEST
|
||||
select WATCHDOG_CORE
|
||||
default y
|
||||
|
@ -1696,16 +1698,6 @@ config WDT_MTX1
|
|||
Hardware driver for the MTX-1 boards. This is a watchdog timer that
|
||||
will reboot the machine after a 100 seconds timer expired.
|
||||
|
||||
config PNX833X_WDT
|
||||
tristate "PNX833x Hardware Watchdog"
|
||||
depends on SOC_PNX8335
|
||||
depends on BROKEN
|
||||
help
|
||||
Hardware driver for the PNX833x's watchdog. This is a
|
||||
watchdog timer that will reboot the machine after a programmable
|
||||
timer has expired and no process has written to /dev/watchdog during
|
||||
that time.
|
||||
|
||||
config SIBYTE_WDOG
|
||||
tristate "Sibyte SoC hardware watchdog"
|
||||
depends on CPU_SB1 || (MIPS && COMPILE_TEST)
|
||||
|
|
|
@ -161,7 +161,6 @@ obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o
|
|||
obj-$(CONFIG_INDYDOG) += indydog.o
|
||||
obj-$(CONFIG_JZ4740_WDT) += jz4740_wdt.o
|
||||
obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
|
||||
obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o
|
||||
obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
|
||||
obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
|
||||
obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
|
||||
|
|
|
@ -150,8 +150,6 @@ static long geodewdt_ioctl(struct file *file, unsigned int cmd,
|
|||
case WDIOC_GETSUPPORT:
|
||||
return copy_to_user(argp, &ident,
|
||||
sizeof(ident)) ? -EFAULT : 0;
|
||||
break;
|
||||
|
||||
case WDIOC_GETSTATUS:
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
return put_user(0, p);
|
||||
|
|
|
@ -21,8 +21,9 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <asm/nmi.h>
|
||||
#include <linux/crash_dump.h>
|
||||
|
||||
#define HPWDT_VERSION "2.0.3"
|
||||
#define HPWDT_VERSION "2.0.4"
|
||||
#define SECS_TO_TICKS(secs) ((secs) * 1000 / 128)
|
||||
#define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000)
|
||||
#define HPWDT_MAX_TICKS 65535
|
||||
|
@ -334,6 +335,11 @@ static int hpwdt_init_one(struct pci_dev *dev,
|
|||
watchdog_set_nowayout(&hpwdt_dev, nowayout);
|
||||
watchdog_init_timeout(&hpwdt_dev, soft_margin, NULL);
|
||||
|
||||
if (is_kdump_kernel()) {
|
||||
pretimeout = 0;
|
||||
kdumptimeout = 0;
|
||||
}
|
||||
|
||||
if (pretimeout && hpwdt_dev.timeout <= PRETIMEOUT_SEC) {
|
||||
dev_warn(&dev->dev, "timeout <= pretimeout. Setting pretimeout to zero\n");
|
||||
pretimeout = 0;
|
||||
|
|
|
@ -40,8 +40,6 @@
|
|||
* Includes, defines, variables, module parameters, ...
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
/* Module and version information */
|
||||
#define DRV_NAME "iTCO_wdt"
|
||||
#define DRV_VERSION "1.11"
|
||||
|
@ -279,7 +277,7 @@ static int iTCO_wdt_start(struct watchdog_device *wd_dev)
|
|||
/* disable chipset's NO_REBOOT bit */
|
||||
if (p->update_no_reboot_bit(p->no_reboot_priv, false)) {
|
||||
spin_unlock(&p->io_lock);
|
||||
pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n");
|
||||
dev_err(wd_dev->parent, "failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -510,7 +508,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
|
|||
/* Check chipset's NO_REBOOT bit */
|
||||
if (p->update_no_reboot_bit(p->no_reboot_priv, false) &&
|
||||
iTCO_vendor_check_noreboot_on()) {
|
||||
pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
|
||||
dev_info(dev, "unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
|
||||
return -ENODEV; /* Cannot reset NO_REBOOT bit */
|
||||
}
|
||||
|
||||
|
@ -530,12 +528,12 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
|
|||
if (!devm_request_region(dev, p->tco_res->start,
|
||||
resource_size(p->tco_res),
|
||||
pdev->name)) {
|
||||
pr_err("I/O address 0x%04llx already in use, device disabled\n",
|
||||
dev_err(dev, "I/O address 0x%04llx already in use, device disabled\n",
|
||||
(u64)TCOBASE(p));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n",
|
||||
dev_info(dev, "Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n",
|
||||
pdata->name, pdata->version, (u64)TCOBASE(p));
|
||||
|
||||
/* Clear out the (probably old) status */
|
||||
|
@ -558,7 +556,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
|
|||
break;
|
||||
}
|
||||
|
||||
p->wddev.info = &ident,
|
||||
p->wddev.info = &ident,
|
||||
p->wddev.ops = &iTCO_wdt_ops,
|
||||
p->wddev.bootstatus = 0;
|
||||
p->wddev.timeout = WATCHDOG_TIMEOUT;
|
||||
|
@ -575,7 +573,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
|
|||
if not reset to the default */
|
||||
if (iTCO_wdt_set_timeout(&p->wddev, heartbeat)) {
|
||||
iTCO_wdt_set_timeout(&p->wddev, WATCHDOG_TIMEOUT);
|
||||
pr_info("timeout value out of range, using %d\n",
|
||||
dev_info(dev, "timeout value out of range, using %d\n",
|
||||
WATCHDOG_TIMEOUT);
|
||||
}
|
||||
|
||||
|
@ -583,11 +581,11 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
|
|||
watchdog_stop_on_unregister(&p->wddev);
|
||||
ret = devm_watchdog_register_device(dev, &p->wddev);
|
||||
if (ret != 0) {
|
||||
pr_err("cannot register watchdog device (err=%d)\n", ret);
|
||||
dev_err(dev, "cannot register watchdog device (err=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
|
||||
dev_info(dev, "initialized. heartbeat=%d sec (nowayout=%d)\n",
|
||||
heartbeat, nowayout);
|
||||
|
||||
return 0;
|
||||
|
@ -651,21 +649,7 @@ static struct platform_driver iTCO_wdt_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init iTCO_wdt_init_module(void)
|
||||
{
|
||||
pr_info("Intel TCO WatchDog Timer Driver v%s\n", DRV_VERSION);
|
||||
|
||||
return platform_driver_register(&iTCO_wdt_driver);
|
||||
}
|
||||
|
||||
static void __exit iTCO_wdt_cleanup_module(void)
|
||||
{
|
||||
platform_driver_unregister(&iTCO_wdt_driver);
|
||||
pr_info("Watchdog Module Unloaded\n");
|
||||
}
|
||||
|
||||
module_init(iTCO_wdt_init_module);
|
||||
module_exit(iTCO_wdt_cleanup_module);
|
||||
module_platform_driver(iTCO_wdt_driver);
|
||||
|
||||
MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
|
||||
MODULE_DESCRIPTION("Intel TCO WatchDog Timer Driver");
|
||||
|
|
|
@ -175,8 +175,8 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
|
|||
|
||||
spin_lock_init(&ddata->lock);
|
||||
|
||||
ddata->wdd.info = &mpc8xxx_wdt_info,
|
||||
ddata->wdd.ops = &mpc8xxx_wdt_ops,
|
||||
ddata->wdd.info = &mpc8xxx_wdt_info;
|
||||
ddata->wdd.ops = &mpc8xxx_wdt_ops;
|
||||
|
||||
ddata->wdd.timeout = WATCHDOG_TIMEOUT;
|
||||
watchdog_init_timeout(&ddata->wdd, timeout, dev);
|
||||
|
|
|
@ -1,277 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* PNX833x Hardware Watchdog Driver
|
||||
* Copyright 2008 NXP Semiconductors
|
||||
* Daniel Laird <daniel.j.laird@nxp.com>
|
||||
* Andre McCurdy <andre.mccurdy@nxp.com>
|
||||
*
|
||||
* Heavily based upon - IndyDog 0.3
|
||||
* A Hardware Watchdog Device for SGI IP22
|
||||
*
|
||||
* (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>, All Rights Reserved.
|
||||
*
|
||||
* based on softdog.c by Alan Cox <alan@redhat.com>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/mach-pnx833x/pnx833x.h>
|
||||
|
||||
#define WATCHDOG_TIMEOUT 30 /* 30 sec Maximum timeout */
|
||||
#define WATCHDOG_COUNT_FREQUENCY 68000000U /* Watchdog counts at 68MHZ. */
|
||||
#define PNX_WATCHDOG_TIMEOUT (WATCHDOG_TIMEOUT * WATCHDOG_COUNT_FREQUENCY)
|
||||
#define PNX_TIMEOUT_VALUE 2040000000U
|
||||
|
||||
/** CONFIG block */
|
||||
#define PNX833X_CONFIG (0x07000U)
|
||||
#define PNX833X_CONFIG_CPU_WATCHDOG (0x54)
|
||||
#define PNX833X_CONFIG_CPU_WATCHDOG_COMPARE (0x58)
|
||||
#define PNX833X_CONFIG_CPU_COUNTERS_CONTROL (0x1c)
|
||||
|
||||
/** RESET block */
|
||||
#define PNX833X_RESET (0x08000U)
|
||||
#define PNX833X_RESET_CONFIG (0x08)
|
||||
|
||||
static int pnx833x_wdt_alive;
|
||||
|
||||
/* Set default timeout in MHZ.*/
|
||||
static int pnx833x_wdt_timeout = PNX_WATCHDOG_TIMEOUT;
|
||||
module_param(pnx833x_wdt_timeout, int, 0);
|
||||
MODULE_PARM_DESC(timeout, "Watchdog timeout in Mhz. (68Mhz clock), default="
|
||||
__MODULE_STRING(PNX_TIMEOUT_VALUE) "(30 seconds).");
|
||||
|
||||
static bool nowayout = WATCHDOG_NOWAYOUT;
|
||||
module_param(nowayout, bool, 0);
|
||||
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
|
||||
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
||||
#define START_DEFAULT 1
|
||||
static int start_enabled = START_DEFAULT;
|
||||
module_param(start_enabled, int, 0);
|
||||
MODULE_PARM_DESC(start_enabled, "Watchdog is started on module insertion "
|
||||
"(default=" __MODULE_STRING(START_DEFAULT) ")");
|
||||
|
||||
static void pnx833x_wdt_start(void)
|
||||
{
|
||||
/* Enable watchdog causing reset. */
|
||||
PNX833X_REG(PNX833X_RESET + PNX833X_RESET_CONFIG) |= 0x1;
|
||||
/* Set timeout.*/
|
||||
PNX833X_REG(PNX833X_CONFIG +
|
||||
PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = pnx833x_wdt_timeout;
|
||||
/* Enable watchdog. */
|
||||
PNX833X_REG(PNX833X_CONFIG +
|
||||
PNX833X_CONFIG_CPU_COUNTERS_CONTROL) |= 0x1;
|
||||
|
||||
pr_info("Started watchdog timer\n");
|
||||
}
|
||||
|
||||
static void pnx833x_wdt_stop(void)
|
||||
{
|
||||
/* Disable watchdog causing reset. */
|
||||
PNX833X_REG(PNX833X_RESET + PNX833X_CONFIG) &= 0xFFFFFFFE;
|
||||
/* Disable watchdog.*/
|
||||
PNX833X_REG(PNX833X_CONFIG +
|
||||
PNX833X_CONFIG_CPU_COUNTERS_CONTROL) &= 0xFFFFFFFE;
|
||||
|
||||
pr_info("Stopped watchdog timer\n");
|
||||
}
|
||||
|
||||
static void pnx833x_wdt_ping(void)
|
||||
{
|
||||
PNX833X_REG(PNX833X_CONFIG +
|
||||
PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = pnx833x_wdt_timeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow only one person to hold it open
|
||||
*/
|
||||
static int pnx833x_wdt_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (test_and_set_bit(0, &pnx833x_wdt_alive))
|
||||
return -EBUSY;
|
||||
|
||||
if (nowayout)
|
||||
__module_get(THIS_MODULE);
|
||||
|
||||
/* Activate timer */
|
||||
if (!start_enabled)
|
||||
pnx833x_wdt_start();
|
||||
|
||||
pnx833x_wdt_ping();
|
||||
|
||||
pr_info("Started watchdog timer\n");
|
||||
|
||||
return stream_open(inode, file);
|
||||
}
|
||||
|
||||
static int pnx833x_wdt_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
/* Shut off the timer.
|
||||
* Lock it in if it's a module and we defined ...NOWAYOUT */
|
||||
if (!nowayout)
|
||||
pnx833x_wdt_stop(); /* Turn the WDT off */
|
||||
|
||||
clear_bit(0, &pnx833x_wdt_alive);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t pnx833x_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
|
||||
{
|
||||
/* Refresh the timer. */
|
||||
if (len)
|
||||
pnx833x_wdt_ping();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static long pnx833x_wdt_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int options, new_timeout = 0;
|
||||
uint32_t timeout, timeout_left = 0;
|
||||
|
||||
static const struct watchdog_info ident = {
|
||||
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
|
||||
.firmware_version = 0,
|
||||
.identity = "Hardware Watchdog for PNX833x",
|
||||
};
|
||||
|
||||
switch (cmd) {
|
||||
default:
|
||||
return -ENOTTY;
|
||||
|
||||
case WDIOC_GETSUPPORT:
|
||||
if (copy_to_user((struct watchdog_info *)arg,
|
||||
&ident, sizeof(ident)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case WDIOC_GETSTATUS:
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
return put_user(0, (int *)arg);
|
||||
|
||||
case WDIOC_SETOPTIONS:
|
||||
if (get_user(options, (int *)arg))
|
||||
return -EFAULT;
|
||||
|
||||
if (options & WDIOS_DISABLECARD)
|
||||
pnx833x_wdt_stop();
|
||||
|
||||
if (options & WDIOS_ENABLECARD)
|
||||
pnx833x_wdt_start();
|
||||
|
||||
return 0;
|
||||
|
||||
case WDIOC_KEEPALIVE:
|
||||
pnx833x_wdt_ping();
|
||||
return 0;
|
||||
|
||||
case WDIOC_SETTIMEOUT:
|
||||
{
|
||||
if (get_user(new_timeout, (int *)arg))
|
||||
return -EFAULT;
|
||||
|
||||
pnx833x_wdt_timeout = new_timeout;
|
||||
PNX833X_REG(PNX833X_CONFIG +
|
||||
PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = new_timeout;
|
||||
return put_user(new_timeout, (int *)arg);
|
||||
}
|
||||
|
||||
case WDIOC_GETTIMEOUT:
|
||||
timeout = PNX833X_REG(PNX833X_CONFIG +
|
||||
PNX833X_CONFIG_CPU_WATCHDOG_COMPARE);
|
||||
return put_user(timeout, (int *)arg);
|
||||
|
||||
case WDIOC_GETTIMELEFT:
|
||||
timeout_left = PNX833X_REG(PNX833X_CONFIG +
|
||||
PNX833X_CONFIG_CPU_WATCHDOG);
|
||||
return put_user(timeout_left, (int *)arg);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int pnx833x_wdt_notify_sys(struct notifier_block *this,
|
||||
unsigned long code, void *unused)
|
||||
{
|
||||
if (code == SYS_DOWN || code == SYS_HALT)
|
||||
pnx833x_wdt_stop(); /* Turn the WDT off */
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static const struct file_operations pnx833x_wdt_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.write = pnx833x_wdt_write,
|
||||
.unlocked_ioctl = pnx833x_wdt_ioctl,
|
||||
.compat_ioctl = compat_ptr_ioctl,
|
||||
.open = pnx833x_wdt_open,
|
||||
.release = pnx833x_wdt_release,
|
||||
};
|
||||
|
||||
static struct miscdevice pnx833x_wdt_miscdev = {
|
||||
.minor = WATCHDOG_MINOR,
|
||||
.name = "watchdog",
|
||||
.fops = &pnx833x_wdt_fops,
|
||||
};
|
||||
|
||||
static struct notifier_block pnx833x_wdt_notifier = {
|
||||
.notifier_call = pnx833x_wdt_notify_sys,
|
||||
};
|
||||
|
||||
static int __init watchdog_init(void)
|
||||
{
|
||||
int ret, cause;
|
||||
|
||||
/* Lets check the reason for the reset.*/
|
||||
cause = PNX833X_REG(PNX833X_RESET);
|
||||
/*If bit 31 is set then watchdog was cause of reset.*/
|
||||
if (cause & 0x80000000) {
|
||||
pr_info("The system was previously reset due to the watchdog firing - please investigate...\n");
|
||||
}
|
||||
|
||||
ret = register_reboot_notifier(&pnx833x_wdt_notifier);
|
||||
if (ret) {
|
||||
pr_err("cannot register reboot notifier (err=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = misc_register(&pnx833x_wdt_miscdev);
|
||||
if (ret) {
|
||||
pr_err("cannot register miscdev on minor=%d (err=%d)\n",
|
||||
WATCHDOG_MINOR, ret);
|
||||
unregister_reboot_notifier(&pnx833x_wdt_notifier);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pr_info("Hardware Watchdog Timer for PNX833x: Version 0.1\n");
|
||||
|
||||
if (start_enabled)
|
||||
pnx833x_wdt_start();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit watchdog_exit(void)
|
||||
{
|
||||
misc_deregister(&pnx833x_wdt_miscdev);
|
||||
unregister_reboot_notifier(&pnx833x_wdt_notifier);
|
||||
}
|
||||
|
||||
module_init(watchdog_init);
|
||||
module_exit(watchdog_exit);
|
||||
|
||||
MODULE_AUTHOR("Daniel Laird/Andre McCurdy");
|
||||
MODULE_DESCRIPTION("Hardware Watchdog Device for PNX833x");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -148,10 +148,17 @@ static int qcom_wdt_restart(struct watchdog_device *wdd, unsigned long action,
|
|||
*/
|
||||
wmb();
|
||||
|
||||
msleep(150);
|
||||
mdelay(150);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_wdt_is_running(struct watchdog_device *wdd)
|
||||
{
|
||||
struct qcom_wdt *wdt = to_qcom_wdt(wdd);
|
||||
|
||||
return (readl(wdt_addr(wdt, WDT_EN)) & QCOM_WDT_ENABLE);
|
||||
}
|
||||
|
||||
static const struct watchdog_ops qcom_wdt_ops = {
|
||||
.start = qcom_wdt_start,
|
||||
.stop = qcom_wdt_stop,
|
||||
|
@ -294,6 +301,17 @@ static int qcom_wdt_probe(struct platform_device *pdev)
|
|||
wdt->wdd.timeout = min(wdt->wdd.max_timeout, 30U);
|
||||
watchdog_init_timeout(&wdt->wdd, 0, dev);
|
||||
|
||||
/*
|
||||
* If WDT is already running, call WDT start which
|
||||
* will stop the WDT, set timeouts as bootloader
|
||||
* might use different ones and set running bit
|
||||
* to inform the WDT subsystem to ping the WDT
|
||||
*/
|
||||
if (qcom_wdt_is_running(&wdt->wdd)) {
|
||||
qcom_wdt_start(&wdt->wdd);
|
||||
set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
|
||||
}
|
||||
|
||||
ret = devm_watchdog_register_device(dev, &wdt->wdd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -227,8 +227,10 @@ static int rti_wdt_probe(struct platform_device *pdev)
|
|||
|
||||
pm_runtime_enable(dev);
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
pm_runtime_put_noidle(dev);
|
||||
return dev_err_probe(dev, ret, "runtime pm failed\n");
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, wdt);
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ static int fitpc2_wdt_open(struct inode *inode, struct file *file)
|
|||
return stream_open(inode, file);
|
||||
}
|
||||
|
||||
static ssize_t fitpc2_wdt_write(struct file *file, const char *data,
|
||||
static ssize_t fitpc2_wdt_write(struct file *file, const char __user *data,
|
||||
size_t len, loff_t *ppos)
|
||||
{
|
||||
size_t i;
|
||||
|
@ -125,16 +125,16 @@ static long fitpc2_wdt_ioctl(struct file *file, unsigned int cmd,
|
|||
|
||||
switch (cmd) {
|
||||
case WDIOC_GETSUPPORT:
|
||||
ret = copy_to_user((struct watchdog_info *)arg, &ident,
|
||||
ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
|
||||
sizeof(ident)) ? -EFAULT : 0;
|
||||
break;
|
||||
|
||||
case WDIOC_GETSTATUS:
|
||||
ret = put_user(0, (int *)arg);
|
||||
ret = put_user(0, (int __user *)arg);
|
||||
break;
|
||||
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
ret = put_user(0, (int *)arg);
|
||||
ret = put_user(0, (int __user *)arg);
|
||||
break;
|
||||
|
||||
case WDIOC_KEEPALIVE:
|
||||
|
@ -143,7 +143,7 @@ static long fitpc2_wdt_ioctl(struct file *file, unsigned int cmd,
|
|||
break;
|
||||
|
||||
case WDIOC_SETTIMEOUT:
|
||||
ret = get_user(time, (int *)arg);
|
||||
ret = get_user(time, (int __user *)arg);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
|
@ -157,7 +157,7 @@ static long fitpc2_wdt_ioctl(struct file *file, unsigned int cmd,
|
|||
fallthrough;
|
||||
|
||||
case WDIOC_GETTIMEOUT:
|
||||
ret = put_user(margin, (int *)arg);
|
||||
ret = put_user(margin, (int __user *)arg);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -291,6 +291,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
|
||||
}
|
||||
|
||||
watchdog_stop_on_reboot(&wdt->wdd);
|
||||
ret = watchdog_register_device(&wdt->wdd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
@ -53,7 +54,7 @@
|
|||
|
||||
#define SPRD_WDT_CNT_HIGH_SHIFT 16
|
||||
#define SPRD_WDT_LOW_VALUE_MASK GENMASK(15, 0)
|
||||
#define SPRD_WDT_LOAD_TIMEOUT 1000
|
||||
#define SPRD_WDT_LOAD_TIMEOUT 11
|
||||
|
||||
struct sprd_wdt {
|
||||
void __iomem *base;
|
||||
|
@ -108,6 +109,23 @@ static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 timeout,
|
|||
u32 tmr_step = timeout * SPRD_WDT_CNT_STEP;
|
||||
u32 prtmr_step = pretimeout * SPRD_WDT_CNT_STEP;
|
||||
|
||||
/*
|
||||
* Checking busy bit to make sure the previous loading operation is
|
||||
* done. According to the specification, the busy bit would be set
|
||||
* after a new loading operation and last 2 or 3 RTC clock
|
||||
* cycles (about 60us~92us).
|
||||
*/
|
||||
do {
|
||||
val = readl_relaxed(wdt->base + SPRD_WDT_INT_RAW);
|
||||
if (!(val & SPRD_WDT_LD_BUSY_BIT))
|
||||
break;
|
||||
|
||||
usleep_range(10, 100);
|
||||
} while (delay_cnt++ < SPRD_WDT_LOAD_TIMEOUT);
|
||||
|
||||
if (delay_cnt >= SPRD_WDT_LOAD_TIMEOUT)
|
||||
return -EBUSY;
|
||||
|
||||
sprd_wdt_unlock(wdt->base);
|
||||
writel_relaxed((tmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) &
|
||||
SPRD_WDT_LOW_VALUE_MASK, wdt->base + SPRD_WDT_LOAD_HIGH);
|
||||
|
@ -120,20 +138,6 @@ static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 timeout,
|
|||
wdt->base + SPRD_WDT_IRQ_LOAD_LOW);
|
||||
sprd_wdt_lock(wdt->base);
|
||||
|
||||
/*
|
||||
* Waiting the load value operation done,
|
||||
* it needs two or three RTC clock cycles.
|
||||
*/
|
||||
do {
|
||||
val = readl_relaxed(wdt->base + SPRD_WDT_INT_RAW);
|
||||
if (!(val & SPRD_WDT_LD_BUSY_BIT))
|
||||
break;
|
||||
|
||||
cpu_relax();
|
||||
} while (delay_cnt++ < SPRD_WDT_LOAD_TIMEOUT);
|
||||
|
||||
if (delay_cnt >= SPRD_WDT_LOAD_TIMEOUT)
|
||||
return -EBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -345,15 +349,10 @@ static int __maybe_unused sprd_wdt_pm_resume(struct device *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (watchdog_active(&wdt->wdd)) {
|
||||
if (watchdog_active(&wdt->wdd))
|
||||
ret = sprd_wdt_start(&wdt->wdd);
|
||||
if (ret) {
|
||||
sprd_wdt_disable(wdt);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops sprd_wdt_pm_ops = {
|
||||
|
|
|
@ -162,18 +162,15 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev,
|
|||
u32 ret;
|
||||
|
||||
wdt->clk_lsi = devm_clk_get(dev, "lsi");
|
||||
if (IS_ERR(wdt->clk_lsi)) {
|
||||
dev_err(dev, "Unable to get lsi clock\n");
|
||||
return PTR_ERR(wdt->clk_lsi);
|
||||
}
|
||||
if (IS_ERR(wdt->clk_lsi))
|
||||
return dev_err_probe(dev, PTR_ERR(wdt->clk_lsi), "Unable to get lsi clock\n");
|
||||
|
||||
/* optional peripheral clock */
|
||||
if (wdt->data->has_pclk) {
|
||||
wdt->clk_pclk = devm_clk_get(dev, "pclk");
|
||||
if (IS_ERR(wdt->clk_pclk)) {
|
||||
dev_err(dev, "Unable to get pclk clock\n");
|
||||
return PTR_ERR(wdt->clk_pclk);
|
||||
}
|
||||
if (IS_ERR(wdt->clk_pclk))
|
||||
return dev_err_probe(dev, PTR_ERR(wdt->clk_pclk),
|
||||
"Unable to get pclk clock\n");
|
||||
|
||||
ret = clk_prepare_enable(wdt->clk_pclk);
|
||||
if (ret) {
|
||||
|
|
|
@ -267,15 +267,19 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
|
|||
}
|
||||
|
||||
if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) {
|
||||
wdd->reboot_nb.notifier_call = watchdog_reboot_notifier;
|
||||
if (!wdd->ops->stop)
|
||||
pr_warn("watchdog%d: stop_on_reboot not supported\n", wdd->id);
|
||||
else {
|
||||
wdd->reboot_nb.notifier_call = watchdog_reboot_notifier;
|
||||
|
||||
ret = register_reboot_notifier(&wdd->reboot_nb);
|
||||
if (ret) {
|
||||
pr_err("watchdog%d: Cannot register reboot notifier (%d)\n",
|
||||
wdd->id, ret);
|
||||
watchdog_dev_unregister(wdd);
|
||||
ida_simple_remove(&watchdog_ida, id);
|
||||
return ret;
|
||||
ret = register_reboot_notifier(&wdd->reboot_nb);
|
||||
if (ret) {
|
||||
pr_err("watchdog%d: Cannot register reboot notifier (%d)\n",
|
||||
wdd->id, ret);
|
||||
watchdog_dev_unregister(wdd);
|
||||
ida_simple_remove(&watchdog_ida, id);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,9 +34,9 @@ struct wdat_instruction {
|
|||
* @period: How long is one watchdog period in ms
|
||||
* @stopped_in_sleep: Is this watchdog stopped by the firmware in S1-S5
|
||||
* @stopped: Was the watchdog stopped by the driver in suspend
|
||||
* @actions: An array of instruction lists indexed by an action number from
|
||||
* the WDAT table. There can be %NULL entries for not implemented
|
||||
* actions.
|
||||
* @instructions: An array of instruction lists indexed by an action number from
|
||||
* the WDAT table. There can be %NULL entries for not implemented
|
||||
* actions.
|
||||
*/
|
||||
struct wdat_wdt {
|
||||
struct platform_device *pdev;
|
||||
|
|
Loading…
Reference in a new issue