Commit 0c8cfbad authored by Linus Torvalds's avatar Linus Torvalds

Merge git://www.linux-watchdog.org/linux-watchdog

Pull watchdog updates from Wim Van Sebroeck:
 "This patchset contains:
   - Various small clean-ups and fixes
   - boot logic hanegs for mpc8xxx_wdt
   - it87_wdt: Work around non-working CIR interrupts
   - iTCO_wdt: Fix the parent device
   - Kconfig dependencies
   - simplification of code with devm_ioremap_resource() or
     platform_driver_probe()
   - conversion of xilinx watchdog driver to Generic watchdog Framework
   - addition of extra functionality and devices for the xilinx watchdog
     driver
   - Addition of Tegra watchdog"

* git://www.linux-watchdog.org/linux-watchdog: (38 commits)
  watchdog: Fix Elan SC520 dependencies
  watchdog: ib700wdt: Use platform_driver_probe
  watchdog: geodewdt: Use platform_driver_probe
  watchdog: advantechwdt: Use platform_driver_probe
  watchdog: acquirewdt: Use platform_driver_probe
  watchdog: iTCO_wdt: Fix the parent device
  watchdog: it87_wdt: Work around non-working CIR interrupts
  watchdog: bcm281xx: Fix Kconfig dependency
  watchdog: s3c2410_wdt: Check return value of clk_prepare_enable
  watchdog: s3c2410_wdt: Remove unneeded initialization
  watchdog: sunxi: Change compatibles
  watchdog: orion: prepare new Dove DT Kconfig variable
  watchdog: fix checkpatch warnings and error
  watchdog: Add tegra watchdog
  watchdog: xilinx: Remove no_timeout variable
  watchdog: xilinx: Enable this driver for Zynq
  watchdog: xilinx: Add missing binding
  watchdog: xilinx: Use correct comment indentation
  watchdog: xilinx: Use of_property_read_u32
  watchdog: xilinx: Fix all printk messages
  ...
parents c12ac9f9 6d956e42
Xilinx AXI/PLB soft-core watchdog Device Tree Bindings
---------------------------------------------------------
Required properties:
- compatible : Should be "xlnx,xps-timebase-wdt-1.00.a" or
"xlnx,xps-timebase-wdt-1.01.a".
- reg : Physical base address and size
Optional properties:
- clock-frequency : Frequency of clock in Hz
- xlnx,wdt-enable-once : 0 - Watchdog can be restarted
1 - Watchdog can be enabled just once
- xlnx,wdt-interval : Watchdog timeout interval in 2^<val> clock cycles,
<val> is integer from 8 to 31.
Example:
axi-timebase-wdt@40100000 {
clock-frequency = <50000000>;
compatible = "xlnx,xps-timebase-wdt-1.00.a";
reg = <0x40100000 0x10000>;
xlnx,wdt-enable-once = <0x0>;
xlnx,wdt-interval = <0x1b>;
} ;
......@@ -2,13 +2,13 @@ Allwinner SoCs Watchdog timer
Required properties:
- compatible : should be "allwinner,<soc-family>-wdt", the currently supported
SoC families being sun4i and sun6i
- compatible : should be either "allwinner,sun4i-a10-wdt" or
"allwinner,sun6i-a31-wdt"
- reg : Specifies base physical address and size of the registers.
Example:
wdt: watchdog@01c20c90 {
compatible = "allwinner,sun4i-wdt";
compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
};
......@@ -150,6 +150,8 @@ nowayout: Disable watchdog shutdown on close
-------------------------------------------------
it87_wdt:
nogameport: Forbid the activation of game port, default=0
nocir: Forbid the use of CIR (workaround for some buggy setups); set to 1 if
system resets despite watchdog daemon running, default=0
exclusive: Watchdog exclusive device open, default=1
timeout: Watchdog timeout in seconds, default=60
testmode: Watchdog test mode (1 = no reboot), default=0
......@@ -325,6 +327,11 @@ soft_noboot: Softdog action, set to 1 to ignore reboots, 0 to reboot
stmp3xxx_wdt:
heartbeat: Watchdog heartbeat period in seconds from 1 to 4194304, default 19
-------------------------------------------------
tegra_wdt:
heartbeat: Watchdog heartbeats in seconds. (default = 120)
nowayout: Watchdog cannot be stopped once started
(default=kernel config parameter)
-------------------------------------------------
ts72xx_wdt:
timeout: Watchdog timeout in seconds. (1 <= timeout <= 8, default=8)
nowayout: Disable watchdog shutdown on close
......
......@@ -111,6 +111,15 @@ config WM8350_WATCHDOG
Support for the watchdog in the WM8350 AudioPlus PMIC. When
the watchdog triggers the system will be reset.
config XILINX_WATCHDOG
tristate "Xilinx Watchdog timer"
select WATCHDOG_CORE
help
Watchdog driver for the xps_timebase_wdt ip core.
To compile this driver as a module, choose M here: the
module will be called of_xilinx_wdt.
# ALPHA Architecture
# ARM Architecture
......@@ -292,7 +301,7 @@ config DAVINCI_WATCHDOG
config ORION_WATCHDOG
tristate "Orion watchdog"
depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE
depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE
select WATCHDOG_CORE
help
Say Y here if to include support for the watchdog timer
......@@ -421,6 +430,17 @@ config SIRFSOC_WATCHDOG
Support for CSR SiRFprimaII and SiRFatlasVI watchdog. When
the watchdog triggers the system will be reset.
config TEGRA_WATCHDOG
tristate "Tegra watchdog"
depends on ARCH_TEGRA || COMPILE_TEST
select WATCHDOG_CORE
help
Say Y here to include support for the watchdog timer
embedded in NVIDIA Tegra SoCs.
To compile this driver as a module, choose M here: the
module will be called tegra_wdt.
# AVR32 Architecture
config AT32AP700X_WDT
......@@ -533,7 +553,7 @@ config GEODE_WDT
config SC520_WDT
tristate "AMD Elan SC520 processor Watchdog"
depends on X86
depends on MELAN
help
This is the driver for the hardware watchdog built in to the
AMD "Elan" SC520 microcomputer commonly used in embedded systems.
......@@ -1023,18 +1043,6 @@ config M54xx_WATCHDOG
# MicroBlaze Architecture
config XILINX_WATCHDOG
tristate "Xilinx Watchdog timer"
depends on MICROBLAZE
---help---
Watchdog driver for the xps_timebase_wdt ip core.
IMPORTANT: The xps_timebase_wdt parent must have the property
"clock-frequency" at device tree.
To compile this driver as a module, choose M here: the
module will be called of_xilinx_wdt.
# MIPS Architecture
config ATH79_WDT
......@@ -1160,7 +1168,7 @@ config BCM2835_WDT
config BCM_KONA_WDT
tristate "BCM Kona Watchdog"
depends on ARCH_BCM
depends on ARCH_BCM_MOBILE
select WATCHDOG_CORE
help
Support for the watchdog timer on the following Broadcom BCM281xx
......
......@@ -58,6 +58,7 @@ obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
obj-$(CONFIG_MOXART_WDT) += moxart_wdt.o
obj-$(CONFIG_SIRFSOC_WATCHDOG) += sirfsoc_wdt.o
obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
......
......@@ -239,7 +239,7 @@ static struct miscdevice acq_miscdev = {
* Init & exit routines
*/
static int acq_probe(struct platform_device *dev)
static int __init acq_probe(struct platform_device *dev)
{
int ret;
......@@ -291,7 +291,6 @@ static void acq_shutdown(struct platform_device *dev)
}
static struct platform_driver acquirewdt_driver = {
.probe = acq_probe,
.remove = acq_remove,
.shutdown = acq_shutdown,
.driver = {
......@@ -306,20 +305,18 @@ static int __init acq_init(void)
pr_info("WDT driver for Acquire single board computer initialising\n");
err = platform_driver_register(&acquirewdt_driver);
if (err)
return err;
acq_platform_device = platform_device_register_simple(DRV_NAME,
-1, NULL, 0);
if (IS_ERR(acq_platform_device)) {
err = PTR_ERR(acq_platform_device);
goto unreg_platform_driver;
}
if (IS_ERR(acq_platform_device))
return PTR_ERR(acq_platform_device);
err = platform_driver_probe(&acquirewdt_driver, acq_probe);
if (err)
goto unreg_platform_device;
return 0;
unreg_platform_driver:
platform_driver_unregister(&acquirewdt_driver);
unreg_platform_device:
platform_device_unregister(acq_platform_device);
return err;
}
......
......@@ -238,7 +238,7 @@ static struct miscdevice advwdt_miscdev = {
* Init & exit routines
*/
static int advwdt_probe(struct platform_device *dev)
static int __init advwdt_probe(struct platform_device *dev)
{
int ret;
......@@ -299,7 +299,6 @@ static void advwdt_shutdown(struct platform_device *dev)
}
static struct platform_driver advwdt_driver = {
.probe = advwdt_probe,
.remove = advwdt_remove,
.shutdown = advwdt_shutdown,
.driver = {
......@@ -314,21 +313,19 @@ static int __init advwdt_init(void)
pr_info("WDT driver for Advantech single board computer initialising\n");
err = platform_driver_register(&advwdt_driver);
if (err)
return err;
advwdt_platform_device = platform_device_register_simple(DRV_NAME,
-1, NULL, 0);
if (IS_ERR(advwdt_platform_device)) {
err = PTR_ERR(advwdt_platform_device);
goto unreg_platform_driver;
}
if (IS_ERR(advwdt_platform_device))
return PTR_ERR(advwdt_platform_device);
err = platform_driver_probe(&advwdt_driver, advwdt_probe);
if (err)
goto unreg_platform_device;
return 0;
unreg_platform_driver:
platform_driver_unregister(&advwdt_driver);
unreg_platform_device:
platform_device_unregister(advwdt_platform_device);
return err;
}
......
......@@ -28,7 +28,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>
......
......@@ -323,10 +323,8 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
wdt = devm_kzalloc(&pdev->dev, sizeof(struct wdt_at32ap700x),
GFP_KERNEL);
if (!wdt) {
dev_dbg(&pdev->dev, "no memory for wdt structure\n");
if (!wdt)
return -ENOMEM;
}
wdt->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
if (!wdt->regs) {
......
......@@ -22,7 +22,6 @@
#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
......
......@@ -114,10 +114,8 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
int err;
wdt = devm_kzalloc(dev, sizeof(struct bcm2835_wdt), GFP_KERNEL);
if (!wdt) {
dev_err(dev, "Failed to allocate memory for watchdog device");
if (!wdt)
return -ENOMEM;
}
platform_set_drvdata(pdev, wdt);
spin_lock_init(&wdt->lock);
......
......@@ -16,7 +16,6 @@
#include <linux/bcm47xx_wdt.h>
#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
......
......@@ -15,7 +15,6 @@
#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
......@@ -45,7 +44,6 @@
static struct {
void __iomem *regs;
struct timer_list timer;
int default_ticks;
unsigned long inuse;
atomic_t ticks;
} bcm63xx_wdt_device;
......
......@@ -27,7 +27,6 @@
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/completion.h>
......
......@@ -21,7 +21,6 @@
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/major.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
......
......@@ -185,7 +185,6 @@ static int da9052_wdt_probe(struct platform_device *pdev)
driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
GFP_KERNEL);
if (!driver_data) {
dev_err(da9052->dev, "Unable to alloacate watchdog device\n");
ret = -ENOMEM;
goto err;
}
......
......@@ -151,10 +151,8 @@ static int da9055_wdt_probe(struct platform_device *pdev)
driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
GFP_KERNEL);
if (!driver_data) {
dev_err(da9055->dev, "Failed to allocate watchdog device\n");
if (!driver_data)
return -ENOMEM;
}
driver_data->da9055 = da9055;
......
......@@ -16,7 +16,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/device.h>
......
......@@ -118,16 +118,9 @@ static int ep93xx_wdt_probe(struct platform_device *pdev)
int err;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENXIO;
if (!devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), pdev->name))
return -EBUSY;
mmio_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!mmio_base)
return -ENXIO;
mmio_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mmio_base))
return PTR_ERR(mmio_base);
if (timeout < 1 || timeout > 3600) {
timeout = WDT_TIMEOUT;
......@@ -172,9 +165,9 @@ static struct platform_driver ep93xx_wdt_driver = {
module_platform_driver(ep93xx_wdt_driver);
MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"
"Alessandro Zummo <a.zummo@towertech.it>,"
"H Hartley Sweeten <hsweeten@visionengravers.com>");
MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>");
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
MODULE_DESCRIPTION("EP93xx Watchdog");
MODULE_LICENSE("GPL");
MODULE_VERSION(WDT_VERSION);
......@@ -215,7 +215,7 @@ static struct miscdevice geodewdt_miscdev = {
.fops = &geodewdt_fops,
};
static int geodewdt_probe(struct platform_device *dev)
static int __init geodewdt_probe(struct platform_device *dev)
{
int ret;
......@@ -255,7 +255,6 @@ static void geodewdt_shutdown(struct platform_device *dev)
}
static struct platform_driver geodewdt_driver = {
.probe = geodewdt_probe,
.remove = geodewdt_remove,
.shutdown = geodewdt_shutdown,
.driver = {
......@@ -268,20 +267,18 @@ static int __init geodewdt_init(void)
{
int ret;
ret = platform_driver_register(&geodewdt_driver);
if (ret)
return ret;
geodewdt_platform_device = platform_device_register_simple(DRV_NAME,
-1, NULL, 0);
if (IS_ERR(geodewdt_platform_device)) {
ret = PTR_ERR(geodewdt_platform_device);
if (IS_ERR(geodewdt_platform_device))
return PTR_ERR(geodewdt_platform_device);
ret = platform_driver_probe(&geodewdt_driver, geodewdt_probe);
if (ret)
goto err;
}
return 0;
err:
platform_driver_unregister(&geodewdt_driver);
platform_device_unregister(geodewdt_platform_device);
return ret;
}
......
......@@ -17,7 +17,6 @@
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
......
......@@ -36,7 +36,6 @@
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/uaccess.h>
......
......@@ -347,15 +347,15 @@ static const struct watchdog_info ident = {
static const struct watchdog_ops iTCO_wdt_ops = {
.owner = THIS_MODULE,
.start = iTCO_wdt_start,
.stop = iTCO_wdt_stop,
.ping = iTCO_wdt_ping,
.stop = iTCO_wdt_stop,
.ping = iTCO_wdt_ping,
.set_timeout = iTCO_wdt_set_timeout,
.get_timeleft = iTCO_wdt_get_timeleft,
};
static struct watchdog_device iTCO_wdt_watchdog_dev = {
.info = &ident,
.ops = &iTCO_wdt_ops,
.ops = &iTCO_wdt_ops,
};
/*
......@@ -485,7 +485,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
iTCO_wdt_watchdog_dev.bootstatus = 0;
iTCO_wdt_watchdog_dev.timeout = WATCHDOG_TIMEOUT;
watchdog_set_nowayout(&iTCO_wdt_watchdog_dev, nowayout);
iTCO_wdt_watchdog_dev.parent = dev->dev.parent;
iTCO_wdt_watchdog_dev.parent = &dev->dev;
/* Make sure the watchdog is not running */
iTCO_wdt_stop(&iTCO_wdt_watchdog_dev);
......
......@@ -277,7 +277,7 @@ static struct miscdevice ibwdt_miscdev = {
* Init & exit routines
*/
static int ibwdt_probe(struct platform_device *dev)
static int __init ibwdt_probe(struct platform_device *dev)
{
int res;
......@@ -336,7 +336,6 @@ static void ibwdt_shutdown(struct platform_device *dev)
}
static struct platform_driver ibwdt_driver = {
.probe = ibwdt_probe,
.remove = ibwdt_remove,
.shutdown = ibwdt_shutdown,
.driver = {
......@@ -351,21 +350,19 @@ static int __init ibwdt_init(void)
pr_info("WDT driver for IB700 single board computer initialising\n");
err = platform_driver_register(&ibwdt_driver);
if (err)
return err;
ibwdt_platform_device = platform_device_register_simple(DRV_NAME,
-1, NULL, 0);
if (IS_ERR(ibwdt_platform_device)) {
err = PTR_ERR(ibwdt_platform_device);
goto unreg_platform_driver;
}
if (IS_ERR(ibwdt_platform_device))
return PTR_ERR(ibwdt_platform_device);
err = platform_driver_probe(&ibwdt_driver, ibwdt_probe);
if (err)
goto unreg_platform_device;
return 0;
unreg_platform_driver:
platform_driver_unregister(&ibwdt_driver);
unreg_platform_device:
platform_device_unregister(ibwdt_platform_device);
return err;
}
......
......@@ -360,7 +360,7 @@ struct ibmasr_id {
int type;
};
static struct ibmasr_id __initdata ibmasr_id_table[] = {
static struct ibmasr_id ibmasr_id_table[] __initdata = {
{ "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
{ "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
{ "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
......
......@@ -41,24 +41,15 @@ MODULE_PARM_DESC(nowayout,
static void indydog_start(void)
{
u32 mc_ctrl0;
spin_lock(&indydog_lock);
mc_ctrl0 = sgimc->cpuctrl0;
mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG;
sgimc->cpuctrl0 = mc_ctrl0;
sgimc->cpuctrl0 |= SGIMC_CCTRL0_WDOG;
spin_unlock(&indydog_lock);
}
static void indydog_stop(void)
{
u32 mc_ctrl0;
spin_lock(&indydog_lock);
mc_ctrl0 = sgimc->cpuctrl0;
mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
sgimc->cpuctrl0 = mc_ctrl0;
sgimc->cpuctrl0 &= ~SGIMC_CCTRL0_WDOG;
spin_unlock(&indydog_lock);
pr_info("Stopped watchdog timer\n");
......
......@@ -211,7 +211,6 @@ static int intel_scu_set_heartbeat(u32 t)
int ipc_ret;
int retry_count;
u32 soft_value;
u32 hw_pre_value;
u32 hw_value;
watchdog_device.timer_set = t;
......@@ -273,8 +272,7 @@ static int intel_scu_set_heartbeat(u32 t)
watchdog_device.timer_load_count_addr);
/* read count value before starting timer */
hw_pre_value = ioread32(watchdog_device.timer_load_count_addr);
hw_pre_value = hw_pre_value & 0xFFFF0000;
ioread32(watchdog_device.timer_load_count_addr);
/* Start the timer */
iowrite32(0x00000003, watchdog_device.timer_control_addr);
......
......@@ -54,6 +54,7 @@
/* Defaults for Module Parameter */
#define DEFAULT_NOGAMEPORT 0
#define DEFAULT_NOCIR 0
#define DEFAULT_EXCLUSIVE 1
#define DEFAULT_TIMEOUT 60
#define DEFAULT_TESTMODE 0
......@@ -136,11 +137,13 @@
#define WDTS_LOCKED 3
#define WDTS_USE_GP 4
#define WDTS_EXPECTED 5
#define WDTS_USE_CIR 6
static unsigned int base, gpact, ciract, max_units, chip_type;
static unsigned long wdt_status;
static int nogameport = DEFAULT_NOGAMEPORT;
static int nocir = DEFAULT_NOCIR;
static int exclusive = DEFAULT_EXCLUSIVE;
static int timeout = DEFAULT_TIMEOUT;
static int testmode = DEFAULT_TESTMODE;
......@@ -149,6 +152,9 @@ static bool nowayout = DEFAULT_NOWAYOUT;
module_param(nogameport, int, 0);
MODULE_PARM_DESC(nogameport, "Forbid the activation of game port, default="
__MODULE_STRING(DEFAULT_NOGAMEPORT));
module_param(nocir, int, 0);
MODULE_PARM_DESC(nocir, "Forbid the use of Consumer IR interrupts to reset timer, default="
__MODULE_STRING(DEFAULT_NOCIR));
module_param(exclusive, int, 0);
MODULE_PARM_DESC(exclusive, "Watchdog exclusive device open, default="
__MODULE_STRING(DEFAULT_EXCLUSIVE));
......@@ -258,9 +264,17 @@ static void wdt_keepalive(void)
{
if (test_bit(WDTS_USE_GP, &wdt_status))
inb(base);
else
else if (test_bit(WDTS_USE_CIR, &wdt_status))
/* The timer reloads with around 5 msec delay */
outb(0x55, CIR_DR(base));
else {
if (superio_enter())
return;
superio_select(GPIO);
wdt_update_timeout();
superio_exit();
}
set_bit(WDTS_KEEPALIVE, &wdt_status);
}
......@@ -273,7 +287,7 @@ static int wdt_start(void)
superio_select(GPIO);
if (test_bit(WDTS_USE_GP, &wdt_status))
superio_outb(WDT_GAMEPORT, WDTCTRL);
else
else if (test_bit(WDTS_USE_CIR, &wdt_status))
superio_outb(WDT_CIRINT, WDTCTRL);
wdt_update_timeout();
......@@ -660,7 +674,7 @@ static int __init it87_wdt_init(void)
}
/* If we haven't Gameport support, try to get CIR support */
if (!test_bit(WDTS_USE_GP, &wdt_status)) {
if (!nocir && !test_bit(WDTS_USE_GP, &wdt_status)) {
if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) {
if (gp_rreq_fail)
pr_err("I/O Address 0x%04x and 0x%04x already in use\n",
......@@ -682,6 +696,7 @@ static int __init it87_wdt_init(void)
superio_select(GAMEPORT);
superio_outb(gpact, ACTREG);
}
set_bit(WDTS_USE_CIR, &wdt_status);
}
if (timeout < 1 || timeout > max_units * 60) {
......@@ -707,7 +722,7 @@ static int __init it87_wdt_init(void)
}
/* Initialize CIR to use it as keepalive source */
if (!test_bit(WDTS_USE_GP, &wdt_status)) {
if (test_bit(WDTS_USE_CIR, &wdt_status)) {
outb(0x00, CIR_RCR(base));
outb(0xc0, CIR_TCR1(base));
outb(0x5c, CIR_TCR2(base));
......@@ -717,9 +732,9 @@ static int __init it87_wdt_init(void)
outb(0x09, CIR_IER(base));
}
pr_info("Chip IT%04x revision %d initialized. timeout=%d sec (nowayout=%d testmode=%d exclusive=%d nogameport=%d)\n",
pr_info("Chip IT%04x revision %d initialized. timeout=%d sec (nowayout=%d testmode=%d exclusive=%d nogameport=%d nocir=%d)\n",
chip_type, chip_rev, timeout,
nowayout, testmode, exclusive, nogameport);
nowayout, testmode, exclusive, nogameport, nocir);
superio_exit();
return 0;
......@@ -727,8 +742,10 @@ static int __init it87_wdt_init(void)
err_out_reboot:
unregister_reboot_notifier(&wdt_notifier);
err_out_region:
release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
if (!test_bit(WDTS_USE_GP, &wdt_status)) {
if (test_bit(WDTS_USE_GP, &wdt_status))
release_region(base, 1);
else if (test_bit(WDTS_USE_CIR, &wdt_status)) {
release_region(base, 8);
superio_select(CIR);
superio_outb(ciract, ACTREG);
}
......@@ -754,7 +771,7 @@ static void __exit it87_wdt_exit(void)
if (test_bit(WDTS_USE_GP, &wdt_status)) {
superio_select(GAMEPORT);
superio_outb(gpact, ACTREG);
} else {
} else if (test_bit(WDTS_USE_CIR, &wdt_status)) {
superio_select(CIR);
superio_outb(ciract, ACTREG);
}
......@@ -763,7 +780,11 @@ static void __exit it87_wdt_exit(void)
misc_deregister(&wdt_miscdev);
unregister_reboot_notifier(&wdt_notifier);
release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
if (test_bit(WDTS_USE_GP, &wdt_status))
release_region(base, 1);
else if (test_bit(WDTS_USE_CIR, &wdt_status))
release_region(base, 8);
}
module_init(it87_wdt_init);
......
......@@ -18,7 +18,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/device.h>
......
......@@ -20,7 +20,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
......
......@@ -237,6 +237,7 @@ static const struct of_device_id mpc8xxx_wdt_match[] = {
.compatible = "fsl,mpc823-wdt",
.data = &(struct mpc8xxx_wdt_type) {
.prescaler = 0x800,
.hw_enabled = true,
},
},
{},
......
......@@ -40,7 +40,6 @@
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/completion.h>
......
......@@ -12,7 +12,6 @@
#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/kernel.h>
......
/*
* Watchdog Device Driver for Xilinx axi/xps_timebase_wdt
*
* (C) Copyright 2013 - 2014 Xilinx, Inc.
* (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.com>)
*
* This program is free software; you can redistribute it and/or
......@@ -9,18 +10,13 @@
* 2 of the License, or (at your option) any later version.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/err.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/watchdog.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
......@@ -43,102 +39,103 @@
#define XWT_TIMER_FAILED 0xFFFFFFFF
#define WATCHDOG_NAME "Xilinx Watchdog"
#define PFX WATCHDOG_NAME ": "
struct xwdt_device {
struct resource res;
void __iomem *base;
u32 nowayout;
u32 wdt_interval;
u32 boot_status;
spinlock_t spinlock;
struct watchdog_device xilinx_wdt_wdd;
};
static struct xwdt_device xdev;
static u32 timeout;
static u32 control_status_reg;
static u8 expect_close;
static u8 no_timeout;
static unsigned long driver_open;
static DEFINE_SPINLOCK(spinlock);
static void xwdt_start(void)
static int xilinx_wdt_start(struct watchdog_device *wdd)
{
spin_lock(&spinlock);
u32 control_status_reg;
struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
spin_lock(&xdev->spinlock);
/* Clean previous status and enable the watchdog timer */
control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET);
control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
iowrite32((control_status_reg | XWT_CSR0_EWDT1_MASK),
xdev.base + XWT_TWCSR0_OFFSET);
xdev->base + XWT_TWCSR0_OFFSET);
iowrite32(XWT_CSRX_EWDT2_MASK, xdev->base + XWT_TWCSR1_OFFSET);
iowrite32(XWT_CSRX_EWDT2_MASK, xdev.base + XWT_TWCSR1_OFFSET);
spin_unlock(&xdev->spinlock);
spin_unlock(&spinlock);
return 0;
}
static void xwdt_stop(void)
static int xilinx_wdt_stop(struct watchdog_device *wdd)
{
spin_lock(&spinlock);
u32 control_status_reg;
struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
spin_lock(&xdev->spinlock);
control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET);
iowrite32((control_status_reg & ~XWT_CSR0_EWDT1_MASK),
xdev.base + XWT_TWCSR0_OFFSET);
xdev->base + XWT_TWCSR0_OFFSET);
iowrite32(0, xdev.base + XWT_TWCSR1_OFFSET);
iowrite32(0, xdev->base + XWT_TWCSR1_OFFSET);
spin_unlock(&spinlock);
spin_unlock(&xdev->spinlock);
pr_info("Stopped!\n");
return 0;
}
static void xwdt_keepalive(void)
static int xilinx_wdt_keepalive(struct watchdog_device *wdd)
{
spin_lock(&spinlock);
u32 control_status_reg;
struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
iowrite32(control_status_reg, xdev.base + XWT_TWCSR0_OFFSET);
spin_lock(&xdev->spinlock);
spin_unlock(&spinlock);
}
control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET);
control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
iowrite32(control_status_reg, xdev->base + XWT_TWCSR0_OFFSET);
static void xwdt_get_status(int *status)
{
int new_status;
spin_unlock(&xdev->spinlock);
spin_lock(&spinlock);
return 0;
}
control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
new_status = ((control_status_reg &
(XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK)) != 0);
spin_unlock(&spinlock);
static const struct watchdog_info xilinx_wdt_ident = {
.options = WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
.firmware_version = 1,
.identity = WATCHDOG_NAME,
};
*status = 0;
if (new_status & 1)
*status |= WDIOF_CARDRESET;
}
static const struct watchdog_ops xilinx_wdt_ops = {
.owner = THIS_MODULE,
.start = xilinx_wdt_start,
.stop = xilinx_wdt_stop,
.ping = xilinx_wdt_keepalive,
};
static u32 xwdt_selftest(void)
static u32 xwdt_selftest(struct xwdt_device *xdev)
{
int i;
u32 timer_value1;
u32 timer_value2;
spin_lock(&spinlock);
spin_lock(&xdev->spinlock);
timer_value1 = ioread32(xdev.base + XWT_TBR_OFFSET);
timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET);
timer_value1 = ioread32(xdev->base + XWT_TBR_OFFSET);
timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET);
for (i = 0;
((i <= XWT_MAX_SELFTEST_LOOP_COUNT) &&
(timer_value2 == timer_value1)); i++) {
timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET);
timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET);
}
spin_unlock(&spinlock);
spin_unlock(&xdev->spinlock);
if (timer_value2 != timer_value1)
return ~XWT_TIMER_FAILED;
......@@ -146,238 +143,83 @@ static u32 xwdt_selftest(void)
return XWT_TIMER_FAILED;
}
static int xwdt_open(struct inode *inode, struct file *file)
{
/* Only one process can handle the wdt at a time */
if (test_and_set_bit(0, &driver_open))
return -EBUSY;
/* Make sure that the module are always loaded...*/
if (xdev.nowayout)
__module_get(THIS_MODULE);
xwdt_start();
pr_info("Started...\n");
return nonseekable_open(inode, file);
}
static int xwdt_release(struct inode *inode, struct file *file)
{
if (expect_close == 42) {
xwdt_stop();
} else {
pr_crit("Unexpected close, not stopping watchdog!\n");
xwdt_keepalive();
}
clear_bit(0, &driver_open);
expect_close = 0;
return 0;
}
/*
* xwdt_write:
* @file: file handle to the watchdog
* @buf: buffer to write (unused as data does not matter here
* @count: count of bytes
* @ppos: pointer to the position to write. No seeks allowed
*
* A write to a watchdog device is defined as a keepalive signal. Any
* write of data will do, as we don't define content meaning.
*/
static ssize_t xwdt_write(struct file *file, const char __user *buf,
size_t len, loff_t *ppos)
{
if (len) {
if (!xdev.nowayout) {
size_t i;
/* In case it was set long ago */
expect_close = 0;
for (i = 0; i != len; i++) {
char c;
if (get_user(c, buf + i))
return -EFAULT;
if (c == 'V')
expect_close = 42;
}
}
xwdt_keepalive();
}
return len;
}
static const struct watchdog_info ident = {
.options = WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
.firmware_version = 1,
.identity = WATCHDOG_NAME,
};
/*
* xwdt_ioctl:
* @file: file handle to the device
* @cmd: watchdog command
* @arg: argument pointer
*
* The watchdog API defines a common set of functions for all watchdogs
* according to their available features.
*/
static long xwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int status;
union {
struct watchdog_info __user *ident;
int __user *i;
} uarg;
uarg.i = (int __user *)arg;
switch (cmd) {
case WDIOC_GETSUPPORT:
return copy_to_user(uarg.ident, &ident,
sizeof(ident)) ? -EFAULT : 0;
case WDIOC_GETBOOTSTATUS:
return put_user(xdev.boot_status, uarg.i);
case WDIOC_GETSTATUS:
xwdt_get_status(&status);
return put_user(status, uarg.i);
case WDIOC_KEEPALIVE:
xwdt_keepalive();
return 0;
case WDIOC_GETTIMEOUT:
if (no_timeout)
return -ENOTTY;
else
return put_user(timeout, uarg.i);
default:
return -ENOTTY;
}
}
static const struct file_operations xwdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = xwdt_write,
.open = xwdt_open,
.release = xwdt_release,
.unlocked_ioctl = xwdt_ioctl,
};
static struct miscdevice xwdt_miscdev = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &xwdt_fops,
};
static int xwdt_probe(struct platform_device *pdev)
{
int rc;
u32 *tmptr;
u32 *pfreq;
no_timeout = 0;
pfreq = (u32 *)of_get_property(pdev->dev.of_node,
"clock-frequency", NULL);
if (pfreq == NULL) {
pr_warn("The watchdog clock frequency cannot be obtained!\n");
no_timeout = 1;
}
rc = of_address_to_resource(pdev->dev.of_node, 0, &xdev.res);
if (rc) {
pr_warn("invalid address!\n");
return rc;
}
tmptr = (u32 *)of_get_property(pdev->dev.of_node,
"xlnx,wdt-interval", NULL);
if (tmptr == NULL) {
pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n");
no_timeout = 1;
} else {
xdev.wdt_interval = *tmptr;
}
tmptr = (u32 *)of_get_property(pdev->dev.of_node,
"xlnx,wdt-enable-once", NULL);
if (tmptr == NULL) {
pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n");
xdev.nowayout = WATCHDOG_NOWAYOUT;
}
/*
* Twice of the 2^wdt_interval / freq because the first wdt overflow is
* ignored (interrupt), reset is only generated at second wdt overflow
*/
if (!no_timeout)
timeout = 2 * ((1<<xdev.wdt_interval) / *pfreq);
if (!request_mem_region(xdev.res.start,
xdev.res.end - xdev.res.start + 1, WATCHDOG_NAME)) {
rc = -ENXIO;
pr_err("memory request failure!\n");
goto err_out;
}
xdev.base = ioremap(xdev.res.start, xdev.res.end - xdev.res.start + 1);
if (xdev.base == NULL) {
rc = -ENOMEM;
pr_err("ioremap failure!\n");
goto release_mem;
}
rc = xwdt_selftest();
u32 pfreq = 0, enable_once = 0;
struct resource *res;
struct xwdt_device *xdev;
struct watchdog_device *xilinx_wdt_wdd;
xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);
if (!xdev)
return -ENOMEM;
xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
xilinx_wdt_wdd->info = &xilinx_wdt_ident;
xilinx_wdt_wdd->ops = &xilinx_wdt_ops;
xilinx_wdt_wdd->parent = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
xdev->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(xdev->base))
return PTR_ERR(xdev->base);
rc = of_property_read_u32(pdev->dev.of_node, "clock-frequency", &pfreq);
if (rc)
dev_warn(&pdev->dev,
"The watchdog clock frequency cannot be obtained\n");
rc = of_property_read_u32(pdev->dev.of_node, "xlnx,wdt-interval",
&xdev->wdt_interval);
if (rc)
dev_warn(&pdev->dev,
"Parameter \"xlnx,wdt-interval\" not found\n");
rc = of_property_read_u32(pdev->dev.of_node, "xlnx,wdt-enable-once",
&enable_once);
if (rc)
dev_warn(&pdev->dev,
"Parameter \"xlnx,wdt-enable-once\" not found\n");
watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
/*
* Twice of the 2^wdt_interval / freq because the first wdt overflow is
* ignored (interrupt), reset is only generated at second wdt overflow
*/
if (pfreq && xdev->wdt_interval)
xilinx_wdt_wdd->timeout = 2 * ((1 << xdev->wdt_interval) /
pfreq);
spin_lock_init(&xdev->spinlock);
watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
rc = xwdt_selftest(xdev);
if (rc == XWT_TIMER_FAILED) {
pr_err("SelfTest routine error!\n");
goto unmap_io;
dev_err(&pdev->dev, "SelfTest routine error\n");
return rc;
}
xwdt_get_status(&xdev.boot_status);
rc = misc_register(&xwdt_miscdev);
rc = watchdog_register_device(xilinx_wdt_wdd);
if (rc) {
pr_err("cannot register miscdev on minor=%d (err=%d)\n",
xwdt_miscdev.minor, rc);
goto unmap_io;
dev_err(&pdev->dev, "Cannot register watchdog (err=%d)\n", rc);
return rc;
}
if (no_timeout)
pr_info("driver loaded (timeout=? sec, nowayout=%d)\n",
xdev.nowayout);
else
pr_info("driver loaded (timeout=%d sec, nowayout=%d)\n",
timeout, xdev.nowayout);
dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n",
xdev->base, xilinx_wdt_wdd->timeout);
expect_close = 0;
clear_bit(0, &driver_open);
platform_set_drvdata(pdev, xdev);
return 0;
unmap_io:
iounmap(xdev.base);
release_mem:
release_mem_region(xdev.res.start, resource_size(&xdev.res));
err_out:
return rc;
}
static int xwdt_remove(struct platform_device *dev)
static int xwdt_remove(struct platform_device *pdev)
{
misc_deregister(&xwdt_miscdev);
iounmap(xdev.base);
release_mem_region(xdev.res.start, resource_size(&xdev.res));
struct xwdt_device *xdev = platform_get_drvdata(pdev);
watchdog_unregister_device(&xdev->xilinx_wdt_wdd);
return 0;
}
......
......@@ -34,7 +34,6 @@
#include <linux/mm.h>
#include <linux/watchdog.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/moduleparam.h>
......@@ -58,7 +57,6 @@ struct omap_wdt_dev {
void __iomem *base; /* physical */
struct device *dev;
bool omap_wdt_users;
struct resource *mem;
int wdt_trgr_pattern;
struct mutex lock; /* to avoid races with PM */
};
......@@ -207,7 +205,7 @@ static int omap_wdt_probe(struct platform_device *pdev)
{
struct omap_wd_timer_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct watchdog_device *omap_wdt;
struct resource *res, *mem;
struct resource *res;
struct omap_wdt_dev *wdev;
u32 rs;
int ret;
......@@ -216,29 +214,20 @@ static int omap_wdt_probe(struct platform_device *pdev)
if (!omap_wdt)
return -ENOMEM;
/* reserve static register mappings */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENOENT;
mem = devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), pdev->name);
if (!mem)
return -EBUSY;
wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
if (!wdev)
return -ENOMEM;
wdev->omap_wdt_users = false;
wdev->mem = mem;
wdev->dev = &pdev->dev;
wdev->wdt_trgr_pattern = 0x1234;
mutex_init(&wdev->lock);
wdev->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!wdev->base)
return -ENOMEM;
/* reserve static register mappings */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
wdev->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(wdev->base))
return PTR_ERR(wdev->base);
omap_wdt->info = &omap_wdt_info;
omap_wdt->ops = &omap_wdt_ops;
......
......@@ -18,7 +18,6 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/clk.h>
......
......@@ -512,9 +512,8 @@ static int __init pc87413_init(void)
return -EBUSY;
ret = register_reboot_notifier(&pc87413_notifier);
if (ret != 0) {
if (ret != 0)
pr_err("cannot register reboot notifier (err=%d)\n", ret);
}
ret = misc_register(&pc87413_miscdev);
if (ret != 0) {
......@@ -575,8 +574,8 @@ static void __exit pc87413_exit(void)
module_init(pc87413_init);
module_exit(pc87413_exit);
MODULE_AUTHOR("Sven Anders <anders@anduras.de>, "
"Marcus Junker <junker@anduras.de>,");
MODULE_AUTHOR("Sven Anders <anders@anduras.de>");
MODULE_AUTHOR("Marcus Junker <junker@anduras.de>");
MODULE_DESCRIPTION("PC87413 WDT driver");
MODULE_LICENSE("GPL");
......
......@@ -645,10 +645,8 @@ static int usb_pcwd_probe(struct usb_interface *interface,
/* allocate memory for our device and initialize it */
usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL);
if (usb_pcwd == NULL) {
pr_err("Out of memory\n");
if (usb_pcwd == NULL)
goto error;
}
usb_pcwd_device = usb_pcwd;
......
......@@ -24,7 +24,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/spinlock.h>
......
......@@ -27,7 +27,6 @@
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/completion.h>
......
......@@ -16,7 +16,6 @@
* GNU General Public License for more details.
*/
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/device.h>
......
......@@ -10,7 +10,6 @@
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/of.h>
......
......@@ -30,7 +30,6 @@
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
......@@ -526,7 +525,11 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
goto err;
}
clk_prepare_enable(wdt->clock);
ret = clk_prepare_enable(wdt->clock);
if (ret < 0) {
dev_err(dev, "failed to enable clock\n");
return ret;
}
ret = s3c2410wdt_cpufreq_register(wdt);
if (ret < 0) {
......@@ -608,7 +611,6 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
err_clk:
clk_disable_unprepare(wdt->clock);
wdt->clock = NULL;
err:
return ret;
......@@ -628,7 +630,6 @@ static int s3c2410wdt_remove(struct platform_device *dev)
s3c2410wdt_cpufreq_deregister(wdt);
clk_disable_unprepare(wdt->clock);
wdt->clock = NULL;
return 0;
}
......
......@@ -158,12 +158,11 @@ static void wdt_timer_ping(unsigned long data)
static void wdt_config(int writeval)
{
__u16 dummy;
unsigned long flags;
/* buy some time (ping) */
spin_lock_irqsave(&wdt_spinlock, flags);
dummy = readw(wdtmrctl); /* ensure write synchronization */
readw(wdtmrctl); /* ensure write synchronization */
writew(0xAAAA, wdtmrctl);
writew(0x5555, wdtmrctl);
/* unlock WDT = make WDT configuration register writable one time */
......
......@@ -293,8 +293,6 @@ static int sh_wdt_probe(struct platform_device *pdev)
static int sh_wdt_remove(struct platform_device *pdev)
{
struct sh_wdt *wdt = platform_get_drvdata(pdev);
watchdog_unregister_device(&sh_wdt_dev);
pm_runtime_disable(&pdev->dev);
......
......@@ -62,7 +62,7 @@ MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static int soft_noboot = 0;
static int soft_noboot;
module_param(soft_noboot, int, 0);
MODULE_PARM_DESC(soft_noboot,
"Softdog action, set to 1 to ignore reboots, 0 to reboot (default=0)");
......
......@@ -16,7 +16,6 @@
#include <linux/amba/bus.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
......@@ -209,27 +208,15 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
struct sp805_wdt *wdt;
int ret = 0;
if (!devm_request_mem_region(&adev->dev, adev->res.start,
resource_size(&adev->res), "sp805_wdt")) {
dev_warn(&adev->dev, "Failed to get memory region resource\n");
ret = -ENOENT;
goto err;
}
wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL);
if (!wdt) {
dev_warn(&adev->dev, "Kzalloc failed\n");
ret = -ENOMEM;
goto err;
}
wdt->base = devm_ioremap(&adev->dev, adev->res.start,
resource_size(&adev->res));
if (!wdt->base) {
ret = -ENOMEM;
dev_warn(&adev->dev, "ioremap fail\n");
goto err;
}
wdt->base = devm_ioremap_resource(&adev->dev, &adev->res);
if (IS_ERR(wdt->base))
return PTR_ERR(wdt->base);
wdt->clk = devm_clk_get(&adev->dev, NULL);
if (IS_ERR(wdt->clk)) {
......
......@@ -9,7 +9,6 @@
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/watchdog.h>
......
......@@ -205,7 +205,7 @@ static void sunxi_wdt_shutdown(struct platform_device *pdev)
}
static const struct of_device_id sunxi_wdt_dt_ids[] = {
{ .compatible = "allwinner,sun4i-wdt" },
{ .compatible = "allwinner,sun4i-a10-wdt" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids);
......
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>
/* minimum and maximum watchdog trigger timeout, in seconds */
#define MIN_WDT_TIMEOUT 1
#define MAX_WDT_TIMEOUT 255
/*
* Base of the WDT registers, from the timer base address. There are
* actually 5 watchdogs that can be configured (by pairing with an available
* timer), at bases 0x100 + (WDT ID) * 0x20, where WDT ID is 0 through 4.
* This driver only configures the first watchdog (WDT ID 0).
*/
#define WDT_BASE 0x100
#define WDT_ID 0
/*
* Register base of the timer that's selected for pairing with the watchdog.
* This driver arbitrarily uses timer 5, which is currently unused by
* other drivers (in particular, the Tegra clocksource driver). If this
* needs to change, take care that the new timer is not used by the
* clocksource driver.
*/
#define WDT_TIMER_BASE 0x60
#define WDT_TIMER_ID 5
/* WDT registers */
#define WDT_CFG 0x0
#define WDT_CFG_PERIOD_SHIFT 4
#define WDT_CFG_PERIOD_MASK 0xff
#define WDT_CFG_INT_EN (1 << 12)
#define WDT_CFG_PMC2CAR_RST_EN (1 << 15)
#define WDT_STS 0x4
#define WDT_STS_COUNT_SHIFT 4
#define WDT_STS_COUNT_MASK 0xff
#define WDT_STS_EXP_SHIFT 12
#define WDT_STS_EXP_MASK 0x3
#define WDT_CMD 0x8
#define WDT_CMD_START_COUNTER (1 << 0)
#define WDT_CMD_DISABLE_COUNTER (1 << 1)
#define WDT_UNLOCK (0xc)
#define WDT_UNLOCK_PATTERN (0xc45a << 0)
/* Timer registers */
#define TIMER_PTV 0x0
#define TIMER_EN (1 << 31)
#define TIMER_PERIODIC (1 << 30)
struct tegra_wdt {
struct watchdog_device wdd;
void __iomem *wdt_regs;
void __iomem *tmr_regs;
};
#define WDT_HEARTBEAT 120
static int heartbeat = WDT_HEARTBEAT;
module_param(heartbeat, int, 0);
MODULE_PARM_DESC(heartbeat,
"Watchdog heartbeats in seconds. (default = "
__MODULE_STRING(WDT_HEARTBEAT) ")");
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) ")");
static int tegra_wdt_start(struct watchdog_device *wdd)
{
struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
u32 val;
/*
* This thing has a fixed 1MHz clock. Normally, we would set the
* period to 1 second by writing 1000000ul, but the watchdog system
* reset actually occurs on the 4th expiration of this counter,
* so we set the period to 1/4 of this amount.
*/
val = 1000000ul / 4;
val |= (TIMER_EN | TIMER_PERIODIC);
writel(val, wdt->tmr_regs + TIMER_PTV);
/*
* Set number of periods and start counter.
*
* Interrupt handler is not required for user space
* WDT accesses, since the caller is responsible to ping the
* WDT to reset the counter before expiration, through ioctls.
*/
val = WDT_TIMER_ID |
(wdd->timeout << WDT_CFG_PERIOD_SHIFT) |
WDT_CFG_PMC2CAR_RST_EN;
writel(val, wdt->wdt_regs + WDT_CFG);
writel(WDT_CMD_START_COUNTER, wdt->wdt_regs + WDT_CMD);
return 0;
}
static int tegra_wdt_stop(struct watchdog_device *wdd)
{
struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
writel(WDT_UNLOCK_PATTERN, wdt->wdt_regs + WDT_UNLOCK);
writel(WDT_CMD_DISABLE_COUNTER, wdt->wdt_regs + WDT_CMD);
writel(0, wdt->tmr_regs + TIMER_PTV);
return 0;
}
static int tegra_wdt_ping(struct watchdog_device *wdd)
{
struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
writel(WDT_CMD_START_COUNTER, wdt->wdt_regs + WDT_CMD);
return 0;
}
static int tegra_wdt_set_timeout(struct watchdog_device *wdd,
unsigned int timeout)
{
wdd->timeout = timeout;
if (watchdog_active(wdd))
return tegra_wdt_start(wdd);
return 0;
}
static unsigned int tegra_wdt_get_timeleft(struct watchdog_device *wdd)
{
struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
u32 val;
int count;
int exp;
val = readl(wdt->wdt_regs + WDT_STS);
/* Current countdown (from timeout) */
count = (val >> WDT_STS_COUNT_SHIFT) & WDT_STS_COUNT_MASK;
/* Number of expirations (we are waiting for the 4th expiration) */
exp = (val >> WDT_STS_EXP_SHIFT) & WDT_STS_EXP_MASK;
/*
* The entire thing is divided by 4 because we are ticking down 4 times
* faster due to needing to wait for the 4th expiration.
*/
return (((3 - exp) * wdd->timeout) + count) / 4;
}
static const struct watchdog_info tegra_wdt_info = {
.options = WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
.firmware_version = 0,
.identity = "Tegra Watchdog",
};
static struct watchdog_ops tegra_wdt_ops = {
.owner = THIS_MODULE,
.start = tegra_wdt_start,
.stop = tegra_wdt_stop,
.ping = tegra_wdt_ping,
.set_timeout = tegra_wdt_set_timeout,
.get_timeleft = tegra_wdt_get_timeleft,
};
static int tegra_wdt_probe(struct platform_device *pdev)
{
struct watchdog_device *wdd;
struct tegra_wdt *wdt;
struct resource *res;
void __iomem *regs;
int ret;
/* This is the timer base. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(regs))
return PTR_ERR(regs);
/*
* Allocate our watchdog driver data, which has the
* struct watchdog_device nested within it.
*/
wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
if (!wdt)
return -ENOMEM;
/* Initialize struct tegra_wdt. */
wdt->wdt_regs = regs + WDT_BASE;
wdt->tmr_regs = regs + WDT_TIMER_BASE;
/* Initialize struct watchdog_device. */
wdd = &wdt->wdd;
wdd->timeout = heartbeat;
wdd->info = &tegra_wdt_info;
wdd->ops = &tegra_wdt_ops;
wdd->min_timeout = MIN_WDT_TIMEOUT;
wdd->max_timeout = MAX_WDT_TIMEOUT;
watchdog_set_drvdata(wdd, wdt);
watchdog_set_nowayout(wdd, nowayout);
ret = watchdog_register_device(wdd);
if (ret) {
dev_err(&pdev->dev,
"failed to register watchdog device\n");
return ret;
}
platform_set_drvdata(pdev, wdt);
dev_info(&pdev->dev,
"initialized (heartbeat = %d sec, nowayout = %d)\n",
heartbeat, nowayout);
return 0;
}
static int tegra_wdt_remove(struct platform_device *pdev)
{
struct tegra_wdt *wdt = platform_get_drvdata(pdev);
tegra_wdt_stop(&wdt->wdd);
watchdog_unregister_device(&wdt->wdd);
dev_info(&pdev->dev, "removed wdt\n");
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int tegra_wdt_runtime_suspend(struct device *dev)
{
struct tegra_wdt *wdt = dev_get_drvdata(dev);
if (watchdog_active(&wdt->wdd))
tegra_wdt_stop(&wdt->wdd);
return 0;
}
static int tegra_wdt_runtime_resume(struct device *dev)
{
struct tegra_wdt *wdt = dev_get_drvdata(dev);
if (watchdog_active(&wdt->wdd))
tegra_wdt_start(&wdt->wdd);
return 0;
}
#endif
static const struct of_device_id tegra_wdt_of_match[] = {
{ .compatible = "nvidia,tegra30-timer", },
{ },
};
MODULE_DEVICE_TABLE(of, tegra_wdt_of_match);
static const struct dev_pm_ops tegra_wdt_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(tegra_wdt_runtime_suspend,
tegra_wdt_runtime_resume)
};
static struct platform_driver tegra_wdt_driver = {
.probe = tegra_wdt_probe,
.remove = tegra_wdt_remove,
.driver = {
.owner = THIS_MODULE,
.name = "tegra-wdt",
.pm = &tegra_wdt_pm_ops,
.of_match_table = tegra_wdt_of_match,
},
};
module_platform_driver(tegra_wdt_driver);
MODULE_AUTHOR("NVIDIA Corporation");
MODULE_DESCRIPTION("Tegra Watchdog Driver");
MODULE_LICENSE("GPL v2");
......@@ -61,7 +61,7 @@ struct ts72xx_wdt {
struct platform_device *pdev;
};
struct platform_device *ts72xx_wdt_pdev;
static struct platform_device *ts72xx_wdt_pdev;
/*
* TS-72xx Watchdog supports following timeouts (value written
......@@ -394,10 +394,8 @@ static int ts72xx_wdt_probe(struct platform_device *pdev)
int error = 0;
wdt = devm_kzalloc(&pdev->dev, sizeof(struct ts72xx_wdt), GFP_KERNEL);
if (!wdt) {
dev_err(&pdev->dev, "failed to allocate memory\n");
if (!wdt)
return -ENOMEM;
}
r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
wdt->control_reg = devm_ioremap_resource(&pdev->dev, r1);
......
......@@ -455,6 +455,6 @@ module_init(wdt_init);
module_exit(wdt_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marcus Junker <junker@anduras.de>, "
"Samuel Tardieu <sam@rfc1149.net>");
MODULE_AUTHOR("Marcus Junker <junker@anduras.de>");
MODULE_AUTHOR("Samuel Tardieu <sam@rfc1149.net>");
MODULE_DESCRIPTION("w83697hf/hg WDT driver");
......@@ -139,9 +139,8 @@ static const struct watchdog_info ident = {
static long watchdog_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
unsigned int new_margin;
int __user *int_arg = (int __user *)arg;
int ret = -ENOTTY;
int new_margin, ret = -ENOTTY;
switch (cmd) {
case WDIOC_GETSUPPORT:
......
......@@ -49,7 +49,6 @@
#include <linux/delay.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/pci.h>
#include <linux/io.h>
......
......@@ -204,7 +204,6 @@ static int wm831x_wdt_probe(struct platform_device *pdev)
driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
GFP_KERNEL);
if (!driver_data) {
dev_err(wm831x->dev, "Unable to alloacate watchdog device\n");
ret = -ENOMEM;
goto err;
}
......
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