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

* git://www.linux-watchdog.org/linux-watchdog:
  watchdog: omap_wdt.c: fix the WDIOC_GETBOOTSTATUS ioctl if not implemented.
  watchdog: new driver for VIA chipsets
  watchdog: ath79_wdt: flush register writes
  drivers/watchdog/lantiq_wdt.c: drop iounmap for devm_ allocated data
  watchdog: documentation: describe nowayout in coversion-guide
  watchdog: documentation: update index file
  watchdog: Convert wm831x driver to devm_kzalloc()
  watchdog: add nowayout helpers to Watchdog Timer Driver Kernel API
  watchdog: convert drivers/watchdog/* to use module_platform_driver()
  watchdog: Use DEFINE_SPINLOCK() for static spinlocks
  watchdog: Convert Wolfson drivers to module_platform_driver
This commit is contained in:
Linus Torvalds 2012-01-10 10:29:23 -08:00
commit 88266917b5
39 changed files with 371 additions and 290 deletions

View File

@ -1,5 +1,7 @@
00-INDEX 00-INDEX
- this file. - this file.
convert_drivers_to_kernel_api.txt
- how-to for converting old watchdog drivers to the new kernel API.
hpwdt.txt hpwdt.txt
- information on the HP iLO2 NMI watchdog - information on the HP iLO2 NMI watchdog
pcwd-watchdog.txt pcwd-watchdog.txt

View File

@ -163,6 +163,25 @@ Here is a simple example for a watchdog device:
+}; +};
Handle the 'nowayout' feature
-----------------------------
A few drivers use nowayout statically, i.e. there is no module parameter for it
and only CONFIG_WATCHDOG_NOWAYOUT determines if the feature is going to be
used. This needs to be converted by initializing the status variable of the
watchdog_device like this:
.status = WATCHDOG_NOWAYOUT_INIT_STATUS,
Most drivers, however, also allow runtime configuration of nowayout, usually
by adding a module parameter. The conversion for this would be something like:
watchdog_set_nowayout(&s3c2410_wdd, nowayout);
The module parameter itself needs to stay, everything else related to nowayout
can go, though. This will likely be some code in open(), close() or write().
Register the watchdog device Register the watchdog device
---------------------------- ----------------------------

View File

@ -1,6 +1,6 @@
The Linux WatchDog Timer Driver Core kernel API. The Linux WatchDog Timer Driver Core kernel API.
=============================================== ===============================================
Last reviewed: 22-Jul-2011 Last reviewed: 29-Nov-2011
Wim Van Sebroeck <wim@iguana.be> Wim Van Sebroeck <wim@iguana.be>
@ -142,6 +142,14 @@ bit-operations. The status bits that are defined are:
* WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog. * WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog.
If this bit is set then the watchdog timer will not be able to stop. If this bit is set then the watchdog timer will not be able to stop.
To set the WDOG_NO_WAY_OUT status bit (before registering your watchdog
timer device) you can either:
* set it statically in your watchdog_device struct with
.status = WATCHDOG_NOWAYOUT_INIT_STATUS,
(this will set the value the same as CONFIG_WATCHDOG_NOWAYOUT) or
* use the following helper function:
static inline void watchdog_set_nowayout(struct watchdog_device *wdd, int nowayout)
Note: The WatchDog Timer Driver Core supports the magic close feature and Note: The WatchDog Timer Driver Core supports the magic close feature and
the nowayout feature. To use the magic close feature you must set the the nowayout feature. To use the magic close feature you must set the
WDIOF_MAGICCLOSE bit in the options field of the watchdog's info structure. WDIOF_MAGICCLOSE bit in the options field of the watchdog's info structure.

View File

@ -772,6 +772,19 @@ config SMSC37B787_WDT
Most people will say N. Most people will say N.
config VIA_WDT
tristate "VIA Watchdog Timer"
depends on X86
select WATCHDOG_CORE
---help---
This is the driver for the hardware watchdog timer on VIA
southbridge chipset CX700, VX800/VX820 or VX855/VX875.
To compile this driver as a module, choose M here; the module
will be called via_wdt.
Most people will say N.
config W83627HF_WDT config W83627HF_WDT
tristate "W83627HF/W83627DHG Watchdog Timer" tristate "W83627HF/W83627DHG Watchdog Timer"
depends on X86 depends on X86

View File

@ -99,6 +99,7 @@ obj-$(CONFIG_SBC7240_WDT) += sbc7240_wdt.o
obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
obj-$(CONFIG_SMSC_SCH311X_WDT) += sch311x_wdt.o obj-$(CONFIG_SMSC_SCH311X_WDT) += sch311x_wdt.o
obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o
obj-$(CONFIG_VIA_WDT) += via_wdt.o
obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o
obj-$(CONFIG_W83697UG_WDT) += w83697ug_wdt.o obj-$(CONFIG_W83697UG_WDT) += w83697ug_wdt.o

View File

@ -70,8 +70,8 @@ struct ar7_wdt {
}; };
static unsigned long wdt_is_open; static unsigned long wdt_is_open;
static spinlock_t wdt_lock;
static unsigned expect_close; static unsigned expect_close;
static DEFINE_SPINLOCK(wdt_lock);
/* XXX currently fixed, allows max margin ~68.72 secs */ /* XXX currently fixed, allows max margin ~68.72 secs */
#define prescale_value 0xffff #define prescale_value 0xffff
@ -280,8 +280,6 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev)
{ {
int rc; int rc;
spin_lock_init(&wdt_lock);
ar7_regs_wdt = ar7_regs_wdt =
platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
if (!ar7_regs_wdt) { if (!ar7_regs_wdt) {
@ -355,15 +353,4 @@ static struct platform_driver ar7_wdt_driver = {
}, },
}; };
static int __init ar7_wdt_init(void) module_platform_driver(ar7_wdt_driver);
{
return platform_driver_register(&ar7_wdt_driver);
}
static void __exit ar7_wdt_cleanup(void)
{
platform_driver_unregister(&ar7_wdt_driver);
}
module_init(ar7_wdt_init);
module_exit(ar7_wdt_cleanup);

View File

@ -68,17 +68,23 @@ static int max_timeout;
static inline void ath79_wdt_keepalive(void) static inline void ath79_wdt_keepalive(void)
{ {
ath79_reset_wr(AR71XX_RESET_REG_WDOG, wdt_freq * timeout); ath79_reset_wr(AR71XX_RESET_REG_WDOG, wdt_freq * timeout);
/* flush write */
ath79_reset_rr(AR71XX_RESET_REG_WDOG);
} }
static inline void ath79_wdt_enable(void) static inline void ath79_wdt_enable(void)
{ {
ath79_wdt_keepalive(); ath79_wdt_keepalive();
ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR); ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR);
/* flush write */
ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL);
} }
static inline void ath79_wdt_disable(void) static inline void ath79_wdt_disable(void)
{ {
ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_NONE); ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_NONE);
/* flush write */
ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL);
} }
static int ath79_wdt_set_timeout(int val) static int ath79_wdt_set_timeout(int val)

View File

@ -311,18 +311,7 @@ static struct platform_driver bcm63xx_wdt = {
} }
}; };
static int __init bcm63xx_wdt_init(void) module_platform_driver(bcm63xx_wdt);
{
return platform_driver_register(&bcm63xx_wdt);
}
static void __exit bcm63xx_wdt_exit(void)
{
platform_driver_unregister(&bcm63xx_wdt);
}
module_init(bcm63xx_wdt_init);
module_exit(bcm63xx_wdt_exit);
MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>"); MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");

View File

@ -39,7 +39,7 @@
static int verbose; static int verbose;
static int port = 0x91; static int port = 0x91;
static int ticks = 10000; static int ticks = 10000;
static spinlock_t cpu5wdt_lock; static DEFINE_SPINLOCK(cpu5wdt_lock);
#define PFX "cpu5wdt: " #define PFX "cpu5wdt: "
@ -223,7 +223,6 @@ static int __devinit cpu5wdt_init(void)
"port=0x%x, verbose=%i\n", port, verbose); "port=0x%x, verbose=%i\n", port, verbose);
init_completion(&cpu5wdt_device.stop); init_completion(&cpu5wdt_device.stop);
spin_lock_init(&cpu5wdt_lock);
cpu5wdt_device.queue = 0; cpu5wdt_device.queue = 0;
setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0); setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
cpu5wdt_device.default_ticks = ticks; cpu5wdt_device.default_ticks = ticks;

View File

@ -687,15 +687,4 @@ static struct platform_driver cpwd_driver = {
.remove = __devexit_p(cpwd_remove), .remove = __devexit_p(cpwd_remove),
}; };
static int __init cpwd_init(void) module_platform_driver(cpwd_driver);
{
return platform_driver_register(&cpwd_driver);
}
static void __exit cpwd_exit(void)
{
platform_driver_unregister(&cpwd_driver);
}
module_init(cpwd_init);
module_exit(cpwd_exit);

View File

@ -271,18 +271,7 @@ static struct platform_driver platform_wdt_driver = {
.remove = __devexit_p(davinci_wdt_remove), .remove = __devexit_p(davinci_wdt_remove),
}; };
static int __init davinci_wdt_init(void) module_platform_driver(platform_wdt_driver);
{
return platform_driver_register(&platform_wdt_driver);
}
static void __exit davinci_wdt_exit(void)
{
platform_driver_unregister(&platform_wdt_driver);
}
module_init(davinci_wdt_init);
module_exit(davinci_wdt_exit);
MODULE_AUTHOR("Texas Instruments"); MODULE_AUTHOR("Texas Instruments");
MODULE_DESCRIPTION("DaVinci Watchdog Driver"); MODULE_DESCRIPTION("DaVinci Watchdog Driver");

View File

@ -358,17 +358,7 @@ static struct platform_driver dw_wdt_driver = {
}, },
}; };
static int __init dw_wdt_watchdog_init(void) module_platform_driver(dw_wdt_driver);
{
return platform_driver_register(&dw_wdt_driver);
}
module_init(dw_wdt_watchdog_init);
static void __exit dw_wdt_watchdog_exit(void)
{
platform_driver_unregister(&dw_wdt_driver);
}
module_exit(dw_wdt_watchdog_exit);
MODULE_AUTHOR("Jamie Iles"); MODULE_AUTHOR("Jamie Iles");
MODULE_DESCRIPTION("Synopsys DesignWare Watchdog Driver"); MODULE_DESCRIPTION("Synopsys DesignWare Watchdog Driver");

View File

@ -64,7 +64,7 @@
static unsigned long eurwdt_is_open; static unsigned long eurwdt_is_open;
static int eurwdt_timeout; static int eurwdt_timeout;
static char eur_expect_close; static char eur_expect_close;
static spinlock_t eurwdt_lock; static DEFINE_SPINLOCK(eurwdt_lock);
/* /*
* You must set these - there is no sane way to probe for this board. * You must set these - there is no sane way to probe for this board.
@ -446,8 +446,6 @@ static int __init eurwdt_init(void)
goto outreg; goto outreg;
} }
spin_lock_init(&eurwdt_lock);
ret = misc_register(&eurwdt_miscdev); ret = misc_register(&eurwdt_miscdev);
if (ret) { if (ret) {
printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",

View File

@ -68,7 +68,7 @@ static char asr_expect_close;
static unsigned int asr_type, asr_base, asr_length; static unsigned int asr_type, asr_base, asr_length;
static unsigned int asr_read_addr, asr_write_addr; static unsigned int asr_read_addr, asr_write_addr;
static unsigned char asr_toggle_mask, asr_disable_mask; static unsigned char asr_toggle_mask, asr_disable_mask;
static spinlock_t asr_lock; static DEFINE_SPINLOCK(asr_lock);
static void __asr_toggle(void) static void __asr_toggle(void)
{ {
@ -386,8 +386,6 @@ static int __init ibmasr_init(void)
if (!asr_type) if (!asr_type)
return -ENODEV; return -ENODEV;
spin_lock_init(&asr_lock);
rc = asr_get_base_address(); rc = asr_get_base_address();
if (rc) if (rc)
return rc; return rc;

View File

@ -28,7 +28,7 @@
#define PFX "indydog: " #define PFX "indydog: "
static unsigned long indydog_alive; static unsigned long indydog_alive;
static spinlock_t indydog_lock; static DEFINE_SPINLOCK(indydog_lock);
#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */
@ -185,8 +185,6 @@ static int __init watchdog_init(void)
{ {
int ret; int ret;
spin_lock_init(&indydog_lock);
ret = register_reboot_notifier(&indydog_notifier); ret = register_reboot_notifier(&indydog_notifier);
if (ret) { if (ret) {
printk(KERN_ERR PFX printk(KERN_ERR PFX

View File

@ -37,7 +37,7 @@
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
static unsigned long wdt_status; static unsigned long wdt_status;
static unsigned long boot_status; static unsigned long boot_status;
static spinlock_t wdt_lock; static DEFINE_SPINLOCK(wdt_lock);
#define WDT_IN_USE 0 #define WDT_IN_USE 0
#define WDT_OK_TO_CLOSE 1 #define WDT_OK_TO_CLOSE 1
@ -226,9 +226,6 @@ static int __init iop_wdt_init(void)
{ {
int ret; int ret;
spin_lock_init(&wdt_lock);
/* check if the reset was caused by the watchdog timer */ /* check if the reset was caused by the watchdog timer */
boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0; boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0;

View File

@ -32,7 +32,7 @@
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */ static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */
static unsigned long wdt_status; static unsigned long wdt_status;
static spinlock_t wdt_lock; static DEFINE_SPINLOCK(wdt_lock);
#define WDT_IN_USE 0 #define WDT_IN_USE 0
#define WDT_OK_TO_CLOSE 1 #define WDT_OK_TO_CLOSE 1
@ -189,7 +189,6 @@ static int __init ixp2000_wdt_init(void)
return -EIO; return -EIO;
} }
wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256; wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
spin_lock_init(&wdt_lock);
return misc_register(&ixp2000_wdt_miscdev); return misc_register(&ixp2000_wdt_miscdev);
} }

View File

@ -181,7 +181,6 @@ static int __init ixp4xx_wdt_init(void)
return -ENODEV; return -ENODEV;
} }
spin_lock_init(&wdt_lock);
boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ? boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ?
WDIOF_CARDRESET : 0; WDIOF_CARDRESET : 0;
ret = misc_register(&ixp4xx_wdt_miscdev); ret = misc_register(&ixp4xx_wdt_miscdev);

View File

@ -295,18 +295,7 @@ static struct platform_driver jz4740_wdt_driver = {
}, },
}; };
module_platform_driver(jz4740_wdt_driver);
static int __init jz4740_wdt_init(void)
{
return platform_driver_register(&jz4740_wdt_driver);
}
module_init(jz4740_wdt_init);
static void __exit jz4740_wdt_exit(void)
{
platform_driver_unregister(&jz4740_wdt_driver);
}
module_exit(jz4740_wdt_exit);
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_DESCRIPTION("jz4740 Watchdog Driver"); MODULE_DESCRIPTION("jz4740 Watchdog Driver");

View File

@ -42,7 +42,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
static unsigned long ks8695wdt_busy; static unsigned long ks8695wdt_busy;
static spinlock_t ks8695_lock; static DEFINE_SPINLOCK(ks8695_lock);
/* ......................................................................... */ /* ......................................................................... */
@ -288,7 +288,6 @@ static struct platform_driver ks8695wdt_driver = {
static int __init ks8695_wdt_init(void) static int __init ks8695_wdt_init(void)
{ {
spin_lock_init(&ks8695_lock);
/* Check that the heartbeat value is within range; /* Check that the heartbeat value is within range;
if not reset to the default */ if not reset to the default */
if (ks8695_wdt_settimeout(wdt_time)) { if (ks8695_wdt_settimeout(wdt_time)) {

View File

@ -222,9 +222,6 @@ ltq_wdt_remove(struct platform_device *pdev)
{ {
misc_deregister(&ltq_wdt_miscdev); misc_deregister(&ltq_wdt_miscdev);
if (ltq_wdt_membase)
iounmap(ltq_wdt_membase);
return 0; return 0;
} }

View File

@ -364,18 +364,7 @@ static struct platform_driver max63xx_wdt_driver = {
}, },
}; };
static int __init max63xx_wdt_init(void) module_platform_driver(max63xx_wdt_driver);
{
return platform_driver_register(&max63xx_wdt_driver);
}
static void __exit max63xx_wdt_exit(void)
{
platform_driver_unregister(&max63xx_wdt_driver);
}
module_init(max63xx_wdt_init);
module_exit(max63xx_wdt_exit);
MODULE_AUTHOR("Marc Zyngier <maz@misterjones.org>"); MODULE_AUTHOR("Marc Zyngier <maz@misterjones.org>");
MODULE_DESCRIPTION("max63xx Watchdog Driver"); MODULE_DESCRIPTION("max63xx Watchdog Driver");

View File

@ -253,18 +253,7 @@ static struct platform_driver mtx1_wdt_driver = {
.driver.owner = THIS_MODULE, .driver.owner = THIS_MODULE,
}; };
static int __init mtx1_wdt_init(void) module_platform_driver(mtx1_wdt_driver);
{
return platform_driver_register(&mtx1_wdt_driver);
}
static void __exit mtx1_wdt_exit(void)
{
platform_driver_unregister(&mtx1_wdt_driver);
}
module_init(mtx1_wdt_init);
module_exit(mtx1_wdt_exit);
MODULE_AUTHOR("Michael Stickel, Florian Fainelli"); MODULE_AUTHOR("Michael Stickel, Florian Fainelli");
MODULE_DESCRIPTION("Driver for the MTX-1 watchdog"); MODULE_DESCRIPTION("Driver for the MTX-1 watchdog");

View File

@ -334,18 +334,7 @@ static struct platform_driver nuc900wdt_driver = {
}, },
}; };
static int __init nuc900_wdt_init(void) module_platform_driver(nuc900wdt_driver);
{
return platform_driver_register(&nuc900wdt_driver);
}
static void __exit nuc900_wdt_exit(void)
{
platform_driver_unregister(&nuc900wdt_driver);
}
module_init(nuc900_wdt_init);
module_exit(nuc900_wdt_exit);
MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
MODULE_DESCRIPTION("Watchdog driver for NUC900"); MODULE_DESCRIPTION("Watchdog driver for NUC900");

View File

@ -414,18 +414,7 @@ static struct platform_driver xwdt_driver = {
}, },
}; };
static int __init xwdt_init(void) module_platform_driver(xwdt_driver);
{
return platform_driver_register(&xwdt_driver);
}
static void __exit xwdt_exit(void)
{
platform_driver_unregister(&xwdt_driver);
}
module_init(xwdt_init);
module_exit(xwdt_exit);
MODULE_AUTHOR("Alejandro Cabrera <aldaya@gmail.com>"); MODULE_AUTHOR("Alejandro Cabrera <aldaya@gmail.com>");
MODULE_DESCRIPTION("Xilinx Watchdog driver"); MODULE_DESCRIPTION("Xilinx Watchdog driver");

View File

@ -55,7 +55,7 @@ module_param(timer_margin, uint, 0);
MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
static unsigned int wdt_trgr_pattern = 0x1234; static unsigned int wdt_trgr_pattern = 0x1234;
static spinlock_t wdt_lock; static DEFINE_SPINLOCK(wdt_lock);
struct omap_wdt_dev { struct omap_wdt_dev {
void __iomem *base; /* physical */ void __iomem *base; /* physical */
@ -232,6 +232,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
if (cpu_is_omap24xx()) if (cpu_is_omap24xx())
return put_user(omap_prcm_get_reset_sources(), return put_user(omap_prcm_get_reset_sources(),
(int __user *)arg); (int __user *)arg);
return put_user(0, (int __user *)arg);
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
pm_runtime_get_sync(wdev->dev); pm_runtime_get_sync(wdev->dev);
spin_lock(&wdt_lock); spin_lock(&wdt_lock);
@ -437,19 +438,7 @@ static struct platform_driver omap_wdt_driver = {
}, },
}; };
static int __init omap_wdt_init(void) module_platform_driver(omap_wdt_driver);
{
spin_lock_init(&wdt_lock);
return platform_driver_register(&omap_wdt_driver);
}
static void __exit omap_wdt_exit(void)
{
platform_driver_unregister(&omap_wdt_driver);
}
module_init(omap_wdt_init);
module_exit(omap_wdt_exit);
MODULE_AUTHOR("George G. Davis"); MODULE_AUTHOR("George G. Davis");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -41,7 +41,7 @@ static int heartbeat = -1; /* module parameter (seconds) */
static unsigned int wdt_max_duration; /* (seconds) */ static unsigned int wdt_max_duration; /* (seconds) */
static unsigned int wdt_tclk; static unsigned int wdt_tclk;
static unsigned long wdt_status; static unsigned long wdt_status;
static spinlock_t wdt_lock; static DEFINE_SPINLOCK(wdt_lock);
static void orion_wdt_ping(void) static void orion_wdt_ping(void)
{ {
@ -294,19 +294,7 @@ static struct platform_driver orion_wdt_driver = {
}, },
}; };
static int __init orion_wdt_init(void) module_platform_driver(orion_wdt_driver);
{
spin_lock_init(&wdt_lock);
return platform_driver_register(&orion_wdt_driver);
}
static void __exit orion_wdt_exit(void)
{
platform_driver_unregister(&orion_wdt_driver);
}
module_init(orion_wdt_init);
module_exit(orion_wdt_exit);
MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>"); MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>");
MODULE_DESCRIPTION("Orion Processor Watchdog"); MODULE_DESCRIPTION("Orion Processor Watchdog");

View File

@ -334,18 +334,7 @@ static struct platform_driver platform_wdt_driver = {
.remove = __devexit_p(pnx4008_wdt_remove), .remove = __devexit_p(pnx4008_wdt_remove),
}; };
static int __init pnx4008_wdt_init(void) module_platform_driver(platform_wdt_driver);
{
return platform_driver_register(&platform_wdt_driver);
}
static void __exit pnx4008_wdt_exit(void)
{
platform_driver_unregister(&platform_wdt_driver);
}
module_init(pnx4008_wdt_init);
module_exit(pnx4008_wdt_exit);
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("PNX4008 Watchdog Driver"); MODULE_DESCRIPTION("PNX4008 Watchdog Driver");

View File

@ -332,18 +332,7 @@ static struct platform_driver rc32434_wdt_driver = {
} }
}; };
static int __init rc32434_wdt_init(void) module_platform_driver(rc32434_wdt_driver);
{
return platform_driver_register(&rc32434_wdt_driver);
}
static void __exit rc32434_wdt_exit(void)
{
platform_driver_unregister(&rc32434_wdt_driver);
}
module_init(rc32434_wdt_init);
module_exit(rc32434_wdt_exit);
MODULE_AUTHOR("Ondrej Zajicek <santiago@crfreenet.org>," MODULE_AUTHOR("Ondrej Zajicek <santiago@crfreenet.org>,"
"Florian Fainelli <florian@openwrt.org>"); "Florian Fainelli <florian@openwrt.org>");

View File

@ -293,18 +293,7 @@ static struct platform_driver rdc321x_wdt_driver = {
}, },
}; };
static int __init rdc321x_wdt_init(void) module_platform_driver(rdc321x_wdt_driver);
{
return platform_driver_register(&rdc321x_wdt_driver);
}
static void __exit rdc321x_wdt_exit(void)
{
platform_driver_unregister(&rdc321x_wdt_driver);
}
module_init(rdc321x_wdt_init);
module_exit(rdc321x_wdt_exit);
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
MODULE_DESCRIPTION("RDC321x watchdog driver"); MODULE_DESCRIPTION("RDC321x watchdog driver");

View File

@ -247,15 +247,4 @@ static struct platform_driver riowd_driver = {
.remove = __devexit_p(riowd_remove), .remove = __devexit_p(riowd_remove),
}; };
static int __init riowd_init(void) module_platform_driver(riowd_driver);
{
return platform_driver_register(&riowd_driver);
}
static void __exit riowd_exit(void)
{
platform_driver_unregister(&riowd_driver);
}
module_init(riowd_init);
module_exit(riowd_exit);

View File

@ -378,6 +378,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
"cannot start\n"); "cannot start\n");
} }
watchdog_set_nowayout(&s3c2410_wdd, nowayout);
ret = watchdog_register_device(&s3c2410_wdd); ret = watchdog_register_device(&s3c2410_wdd);
if (ret) { if (ret) {
dev_err(dev, "cannot register watchdog (%d)\n", ret); dev_err(dev, "cannot register watchdog (%d)\n", ret);

View File

@ -272,18 +272,7 @@ static struct platform_driver platform_wdt_driver = {
.resume = stmp3xxx_wdt_resume, .resume = stmp3xxx_wdt_resume,
}; };
static int __init stmp3xxx_wdt_init(void) module_platform_driver(platform_wdt_driver);
{
return platform_driver_register(&platform_wdt_driver);
}
static void __exit stmp3xxx_wdt_exit(void)
{
return platform_driver_unregister(&platform_wdt_driver);
}
module_init(stmp3xxx_wdt_init);
module_exit(stmp3xxx_wdt_exit);
MODULE_DESCRIPTION("STMP3XXX Watchdog Driver"); MODULE_DESCRIPTION("STMP3XXX Watchdog Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -506,17 +506,7 @@ static struct platform_driver ts72xx_wdt_driver = {
}, },
}; };
static __init int ts72xx_wdt_init(void) module_platform_driver(ts72xx_wdt_driver);
{
return platform_driver_register(&ts72xx_wdt_driver);
}
module_init(ts72xx_wdt_init);
static __exit void ts72xx_wdt_exit(void)
{
platform_driver_unregister(&ts72xx_wdt_driver);
}
module_exit(ts72xx_wdt_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
MODULE_DESCRIPTION("TS-72xx SBC Watchdog"); MODULE_DESCRIPTION("TS-72xx SBC Watchdog");

View File

@ -256,17 +256,7 @@ static struct platform_driver twl4030_wdt_driver = {
}, },
}; };
static int __devinit twl4030_wdt_init(void) module_platform_driver(twl4030_wdt_driver);
{
return platform_driver_register(&twl4030_wdt_driver);
}
module_init(twl4030_wdt_init);
static void __devexit twl4030_wdt_exit(void)
{
platform_driver_unregister(&twl4030_wdt_driver);
}
module_exit(twl4030_wdt_exit);
MODULE_AUTHOR("Nokia Corporation"); MODULE_AUTHOR("Nokia Corporation");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

267
drivers/watchdog/via_wdt.c Normal file
View File

@ -0,0 +1,267 @@
/*
* VIA Chipset Watchdog Driver
*
* Copyright (C) 2011 Sigfox
* License terms: GNU General Public License (GPL) version 2
* Author: Marc Vertes <marc.vertes@sigfox.com>
* Based on a preliminary version from Harald Welte <HaraldWelte@viatech.com>
* Timer code by Wim Van Sebroeck <wim@iguana.be>
*
* Caveat: PnP must be enabled in BIOS to allow full access to watchdog
* control registers. If not, the watchdog must be configured in BIOS manually.
*/
#include <linux/device.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/timer.h>
#include <linux/watchdog.h>
/* Configuration registers relative to the pci device */
#define VIA_WDT_MMIO_BASE 0xe8 /* MMIO region base address */
#define VIA_WDT_CONF 0xec /* watchdog enable state */
/* Relevant bits for the VIA_WDT_CONF register */
#define VIA_WDT_CONF_ENABLE 0x01 /* 1: enable watchdog */
#define VIA_WDT_CONF_MMIO 0x02 /* 1: enable watchdog MMIO */
/*
* The MMIO region contains the watchog control register and the
* hardware timer counter.
*/
#define VIA_WDT_MMIO_LEN 8 /* MMIO region length in bytes */
#define VIA_WDT_CTL 0 /* MMIO addr+0: state/control reg. */
#define VIA_WDT_COUNT 4 /* MMIO addr+4: timer counter reg. */
/* Bits for the VIA_WDT_CTL register */
#define VIA_WDT_RUNNING 0x01 /* 0: stop, 1: running */
#define VIA_WDT_FIRED 0x02 /* 1: restarted by expired watchdog */
#define VIA_WDT_PWROFF 0x04 /* 0: reset, 1: poweroff */
#define VIA_WDT_DISABLED 0x08 /* 1: timer is disabled */
#define VIA_WDT_TRIGGER 0x80 /* 1: start a new countdown */
/* Hardware heartbeat in seconds */
#define WDT_HW_HEARTBEAT 1
/* Timer heartbeat (500ms) */
#define WDT_HEARTBEAT (HZ/2) /* should be <= ((WDT_HW_HEARTBEAT*HZ)/2) */
/* User space timeout in seconds */
#define WDT_TIMEOUT_MAX 1023 /* approx. 17 min. */
#define WDT_TIMEOUT 60
static int timeout = WDT_TIMEOUT;
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, between 1 and 1023 "
"(default = " __MODULE_STRING(WDT_TIMEOUT) ")");
static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
"(default = " __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static struct watchdog_device wdt_dev;
static struct resource wdt_res;
static void __iomem *wdt_mem;
static unsigned int mmio;
static void wdt_timer_tick(unsigned long data);
static DEFINE_TIMER(timer, wdt_timer_tick, 0, 0);
/* The timer that pings the watchdog */
static unsigned long next_heartbeat; /* the next_heartbeat for the timer */
static inline void wdt_reset(void)
{
unsigned int ctl = readl(wdt_mem);
writel(ctl | VIA_WDT_TRIGGER, wdt_mem);
}
/*
* Timer tick: the timer will make sure that the watchdog timer hardware
* is being reset in time. The conditions to do this are:
* 1) the watchog timer has been started and /dev/watchdog is open
* and there is still time left before userspace should send the
* next heartbeat/ping. (note: the internal heartbeat is much smaller
* then the external/userspace heartbeat).
* 2) the watchdog timer has been stopped by userspace.
*/
static void wdt_timer_tick(unsigned long data)
{
if (time_before(jiffies, next_heartbeat) ||
(!test_bit(WDOG_ACTIVE, &wdt_dev.status))) {
wdt_reset();
mod_timer(&timer, jiffies + WDT_HEARTBEAT);
} else
pr_crit("I will reboot your machine !\n");
}
static int wdt_ping(struct watchdog_device *wdd)
{
/* calculate when the next userspace timeout will be */
next_heartbeat = jiffies + timeout * HZ;
return 0;
}
static int wdt_start(struct watchdog_device *wdd)
{
unsigned int ctl = readl(wdt_mem);
writel(timeout, wdt_mem + VIA_WDT_COUNT);
writel(ctl | VIA_WDT_RUNNING | VIA_WDT_TRIGGER, wdt_mem);
wdt_ping(wdd);
mod_timer(&timer, jiffies + WDT_HEARTBEAT);
return 0;
}
static int wdt_stop(struct watchdog_device *wdd)
{
unsigned int ctl = readl(wdt_mem);
writel(ctl & ~VIA_WDT_RUNNING, wdt_mem);
return 0;
}
static int wdt_set_timeout(struct watchdog_device *wdd,
unsigned int new_timeout)
{
if (new_timeout < 1 || new_timeout > WDT_TIMEOUT_MAX)
return -EINVAL;
writel(new_timeout, wdt_mem + VIA_WDT_COUNT);
timeout = new_timeout;
return 0;
}
static const struct watchdog_info wdt_info = {
.identity = "VIA watchdog",
.options = WDIOF_CARDRESET |
WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
};
static const struct watchdog_ops wdt_ops = {
.owner = THIS_MODULE,
.start = wdt_start,
.stop = wdt_stop,
.ping = wdt_ping,
.set_timeout = wdt_set_timeout,
};
static struct watchdog_device wdt_dev = {
.info = &wdt_info,
.ops = &wdt_ops,
};
static int __devinit wdt_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
unsigned char conf;
int ret = -ENODEV;
if (pci_enable_device(pdev)) {
dev_err(&pdev->dev, "cannot enable PCI device\n");
return -ENODEV;
}
/*
* Allocate a MMIO region which contains watchdog control register
* and counter, then configure the watchdog to use this region.
* This is possible only if PnP is properly enabled in BIOS.
* If not, the watchdog must be configured in BIOS manually.
*/
if (allocate_resource(&iomem_resource, &wdt_res, VIA_WDT_MMIO_LEN,
0xf0000000, 0xffffff00, 0xff, NULL, NULL)) {
dev_err(&pdev->dev, "MMIO allocation failed\n");
goto err_out_disable_device;
}
pci_write_config_dword(pdev, VIA_WDT_MMIO_BASE, wdt_res.start);
pci_read_config_byte(pdev, VIA_WDT_CONF, &conf);
conf |= VIA_WDT_CONF_ENABLE | VIA_WDT_CONF_MMIO;
pci_write_config_byte(pdev, VIA_WDT_CONF, conf);
pci_read_config_dword(pdev, VIA_WDT_MMIO_BASE, &mmio);
if (mmio) {
dev_info(&pdev->dev, "VIA Chipset watchdog MMIO: %x\n", mmio);
} else {
dev_err(&pdev->dev, "MMIO setting failed. Check BIOS.\n");
goto err_out_resource;
}
if (!request_mem_region(mmio, VIA_WDT_MMIO_LEN, "via_wdt")) {
dev_err(&pdev->dev, "MMIO region busy\n");
goto err_out_resource;
}
wdt_mem = ioremap(mmio, VIA_WDT_MMIO_LEN);
if (wdt_mem == NULL) {
dev_err(&pdev->dev, "cannot remap VIA wdt MMIO registers\n");
goto err_out_release;
}
wdt_dev.timeout = timeout;
watchdog_set_nowayout(&wdt_dev, nowayout);
if (readl(wdt_mem) & VIA_WDT_FIRED)
wdt_dev.bootstatus |= WDIOF_CARDRESET;
ret = watchdog_register_device(&wdt_dev);
if (ret)
goto err_out_iounmap;
/* start triggering, in case of watchdog already enabled by BIOS */
mod_timer(&timer, jiffies + WDT_HEARTBEAT);
return 0;
err_out_iounmap:
iounmap(wdt_mem);
err_out_release:
release_mem_region(mmio, VIA_WDT_MMIO_LEN);
err_out_resource:
release_resource(&wdt_res);
err_out_disable_device:
pci_disable_device(pdev);
return ret;
}
static void __devexit wdt_remove(struct pci_dev *pdev)
{
watchdog_unregister_device(&wdt_dev);
del_timer(&timer);
iounmap(wdt_mem);
release_mem_region(mmio, VIA_WDT_MMIO_LEN);
release_resource(&wdt_res);
pci_disable_device(pdev);
}
DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700) },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800) },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
{ 0 }
};
static struct pci_driver wdt_driver = {
.name = "via_wdt",
.id_table = wdt_pci_table,
.probe = wdt_probe,
.remove = __devexit_p(wdt_remove),
};
static int __init wdt_init(void)
{
if (timeout < 1 || timeout > WDT_TIMEOUT_MAX)
timeout = WDT_TIMEOUT;
return pci_register_driver(&wdt_driver);
}
static void __exit wdt_exit(void)
{
pci_unregister_driver(&wdt_driver);
}
module_init(wdt_init);
module_exit(wdt_exit);
MODULE_AUTHOR("Marc Vertes");
MODULE_DESCRIPTION("Driver for watchdog timer on VIA chipset");
MODULE_LICENSE("GPL");

View File

@ -199,7 +199,8 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
if (reg & WM831X_WDOG_DEBUG) if (reg & WM831X_WDOG_DEBUG)
dev_warn(wm831x->dev, "Watchdog is paused\n"); dev_warn(wm831x->dev, "Watchdog is paused\n");
driver_data = kzalloc(sizeof(*driver_data), GFP_KERNEL); driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
GFP_KERNEL);
if (!driver_data) { if (!driver_data) {
dev_err(wm831x->dev, "Unable to alloacate watchdog device\n"); dev_err(wm831x->dev, "Unable to alloacate watchdog device\n");
ret = -ENOMEM; ret = -ENOMEM;
@ -213,11 +214,9 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
wm831x_wdt->info = &wm831x_wdt_info; wm831x_wdt->info = &wm831x_wdt_info;
wm831x_wdt->ops = &wm831x_wdt_ops; wm831x_wdt->ops = &wm831x_wdt_ops;
watchdog_set_nowayout(wm831x_wdt, nowayout);
watchdog_set_drvdata(wm831x_wdt, driver_data); watchdog_set_drvdata(wm831x_wdt, driver_data);
if (nowayout)
wm831x_wdt->status |= WDOG_NO_WAY_OUT;
reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG); reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
reg &= WM831X_WDOG_TO_MASK; reg &= WM831X_WDOG_TO_MASK;
for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++) for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++)
@ -252,7 +251,7 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
dev_err(wm831x->dev, dev_err(wm831x->dev,
"Failed to request update GPIO: %d\n", "Failed to request update GPIO: %d\n",
ret); ret);
goto err_alloc; goto err;
} }
ret = gpio_direction_output(pdata->update_gpio, 0); ret = gpio_direction_output(pdata->update_gpio, 0);
@ -294,8 +293,6 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
err_gpio: err_gpio:
if (driver_data->update_gpio) if (driver_data->update_gpio)
gpio_free(driver_data->update_gpio); gpio_free(driver_data->update_gpio);
err_alloc:
kfree(driver_data);
err: err:
return ret; return ret;
} }
@ -320,17 +317,7 @@ static struct platform_driver wm831x_wdt_driver = {
}, },
}; };
static int __init wm831x_wdt_init(void) module_platform_driver(wm831x_wdt_driver);
{
return platform_driver_register(&wm831x_wdt_driver);
}
module_init(wm831x_wdt_init);
static void __exit wm831x_wdt_exit(void)
{
platform_driver_unregister(&wm831x_wdt_driver);
}
module_exit(wm831x_wdt_exit);
MODULE_AUTHOR("Mark Brown"); MODULE_AUTHOR("Mark Brown");
MODULE_DESCRIPTION("WM831x Watchdog"); MODULE_DESCRIPTION("WM831x Watchdog");

View File

@ -311,17 +311,7 @@ static struct platform_driver wm8350_wdt_driver = {
}, },
}; };
static int __init wm8350_wdt_init(void) module_platform_driver(wm8350_wdt_driver);
{
return platform_driver_register(&wm8350_wdt_driver);
}
module_init(wm8350_wdt_init);
static void __exit wm8350_wdt_exit(void)
{
platform_driver_unregister(&wm8350_wdt_driver);
}
module_exit(wm8350_wdt_exit);
MODULE_AUTHOR("Mark Brown"); MODULE_AUTHOR("Mark Brown");
MODULE_DESCRIPTION("WM8350 Watchdog"); MODULE_DESCRIPTION("WM8350 Watchdog");

View File

@ -53,11 +53,7 @@ struct watchdog_info {
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifdef CONFIG_WATCHDOG_NOWAYOUT #include <linux/bitops.h>
#define WATCHDOG_NOWAYOUT 1
#else
#define WATCHDOG_NOWAYOUT 0
#endif
struct watchdog_ops; struct watchdog_ops;
struct watchdog_device; struct watchdog_device;
@ -122,6 +118,21 @@ struct watchdog_device {
#define WDOG_NO_WAY_OUT 3 /* Is 'nowayout' feature set ? */ #define WDOG_NO_WAY_OUT 3 /* Is 'nowayout' feature set ? */
}; };
#ifdef CONFIG_WATCHDOG_NOWAYOUT
#define WATCHDOG_NOWAYOUT 1
#define WATCHDOG_NOWAYOUT_INIT_STATUS (1 << WDOG_NO_WAY_OUT)
#else
#define WATCHDOG_NOWAYOUT 0
#define WATCHDOG_NOWAYOUT_INIT_STATUS 0
#endif
/* Use the following function to set the nowayout feature */
static inline void watchdog_set_nowayout(struct watchdog_device *wdd, int nowayout)
{
if (nowayout)
set_bit(WDOG_NO_WAY_OUT, &wdd->status);
}
/* Use the following functions to manipulate watchdog driver specific data */ /* Use the following functions to manipulate watchdog driver specific data */
static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
{ {