aboutsummaryrefslogtreecommitdiff
path: root/drivers/watchdog/bfin_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/bfin_wdt.c')
-rw-r--r--drivers/watchdog/bfin_wdt.c132
1 files changed, 46 insertions, 86 deletions
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 067a57cb3f8..a3b6a5b30f9 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -1,9 +1,8 @@
/*
* Blackfin On-Chip Watchdog Driver
- * Supports BF53[123]/BF53[467]/BF54[2489]/BF561
*
* Originally based on softdog.c
- * Copyright 2006-2007 Analog Devices Inc.
+ * Copyright 2006-2010 Analog Devices Inc.
* Copyright 2006-2007 Michele d'Amico
* Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>
*
@@ -12,6 +11,8 @@
* Licensed under the GPL-2 or later.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -20,20 +21,17 @@
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/fs.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>
#include <asm/blackfin.h>
+#include <asm/bfin_watchdog.h>
-#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
+#define stamp(fmt, args...) \
+ pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
#define stampit() stamp("here i am")
-#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
-#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
#define WATCHDOG_NAME "bfin-wdt"
-#define PFX WATCHDOG_NAME ": "
/* The BF561 has two watchdogs (one per core), but since Linux
* only runs on core A, we'll just work with that one.
@@ -47,30 +45,12 @@
# define bfin_write_WDOG_STAT(x) bfin_write_WDOGA_STAT(x)
#endif
-/* Bit in SWRST that indicates boot caused by watchdog */
-#define SWRST_RESET_WDOG 0x4000
-
-/* Bit in WDOG_CTL that indicates watchdog has expired (WDR0) */
-#define WDOG_EXPIRED 0x8000
-
-/* Masks for WDEV field in WDOG_CTL register */
-#define ICTL_RESET 0x0
-#define ICTL_NMI 0x2
-#define ICTL_GPI 0x4
-#define ICTL_NONE 0x6
-#define ICTL_MASK 0x6
-
-/* Masks for WDEN field in WDOG_CTL register */
-#define WDEN_MASK 0x0FF0
-#define WDEN_ENABLE 0x0000
-#define WDEN_DISABLE 0x0AD0
-
/* some defaults */
#define WATCHDOG_TIMEOUT 20
static unsigned int timeout = WATCHDOG_TIMEOUT;
-static int nowayout = WATCHDOG_NOWAYOUT;
-static struct watchdog_info bfin_wdt_info;
+static bool nowayout = WATCHDOG_NOWAYOUT;
+static const struct watchdog_info bfin_wdt_info;
static unsigned long open_check;
static char expect_close;
static DEFINE_SPINLOCK(bfin_wdt_spinlock);
@@ -78,7 +58,7 @@ static DEFINE_SPINLOCK(bfin_wdt_spinlock);
/**
* bfin_wdt_keepalive - Keep the Userspace Watchdog Alive
*
- * The Userspace watchdog got a KeepAlive: schedule the next timeout.
+ * The Userspace watchdog got a KeepAlive: schedule the next timeout.
*/
static int bfin_wdt_keepalive(void)
{
@@ -132,14 +112,16 @@ static int bfin_wdt_running(void)
*/
static int bfin_wdt_set_timeout(unsigned long t)
{
- u32 cnt;
+ u32 cnt, max_t, sclk;
unsigned long flags;
- stampit();
+ sclk = get_sclk();
+ max_t = -1 / sclk;
+ cnt = t * sclk;
+ stamp("maxtimeout=%us newtimeout=%lus (cnt=%#x)", max_t, t, cnt);
- cnt = t * get_sclk();
- if (cnt < get_sclk()) {
- printk(KERN_WARNING PFX "timeout value is too large\n");
+ if (t > max_t) {
+ pr_warn("timeout value is too large\n");
return -EINVAL;
}
@@ -195,8 +177,7 @@ static int bfin_wdt_release(struct inode *inode, struct file *file)
if (expect_close == 42)
bfin_wdt_stop();
else {
- printk(KERN_CRIT PFX
- "Unexpected close, not stopping watchdog!\n");
+ pr_crit("Unexpected close, not stopping watchdog!\n");
bfin_wdt_keepalive();
}
expect_close = 0;
@@ -303,26 +284,6 @@ static long bfin_wdt_ioctl(struct file *file,
}
}
-/**
- * bfin_wdt_notify_sys - Notifier Handler
- * @this: notifier block
- * @code: notifier event
- * @unused: unused
- *
- * Handles specific events, such as turning off the watchdog during a
- * shutdown event.
- */
-static int bfin_wdt_notify_sys(struct notifier_block *this,
- unsigned long code, void *unused)
-{
- stampit();
-
- if (code == SYS_DOWN || code == SYS_HALT)
- bfin_wdt_stop();
-
- return NOTIFY_DONE;
-}
-
#ifdef CONFIG_PM
static int state_before_suspend;
@@ -370,7 +331,7 @@ static int bfin_wdt_resume(struct platform_device *pdev)
static const struct file_operations bfin_wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
- .write = bfin_wdt_write,
+ .write = bfin_wdt_write,
.unlocked_ioctl = bfin_wdt_ioctl,
.open = bfin_wdt_open,
.release = bfin_wdt_release,
@@ -382,45 +343,32 @@ static struct miscdevice bfin_wdt_miscdev = {
.fops = &bfin_wdt_fops,
};
-static struct watchdog_info bfin_wdt_info = {
+static const struct watchdog_info bfin_wdt_info = {
.identity = "Blackfin Watchdog",
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
};
-static struct notifier_block bfin_wdt_notifier = {
- .notifier_call = bfin_wdt_notify_sys,
-};
-
/**
* bfin_wdt_probe - Initialize module
*
- * Registers the misc device and notifier handler. Actual device
+ * Registers the misc device. Actual device
* initialization is handled by bfin_wdt_open().
*/
-static int __devinit bfin_wdt_probe(struct platform_device *pdev)
+static int bfin_wdt_probe(struct platform_device *pdev)
{
int ret;
- ret = register_reboot_notifier(&bfin_wdt_notifier);
- if (ret) {
- pr_devinit(KERN_ERR PFX
- "cannot register reboot notifier (err=%d)\n", ret);
- return ret;
- }
-
ret = misc_register(&bfin_wdt_miscdev);
if (ret) {
- pr_devinit(KERN_ERR PFX
- "cannot register miscdev on minor=%d (err=%d)\n",
- WATCHDOG_MINOR, ret);
- unregister_reboot_notifier(&bfin_wdt_notifier);
+ pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
return ret;
}
- pr_devinit(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
- timeout, nowayout);
+ pr_info("initialized: timeout=%d sec (nowayout=%d)\n",
+ timeout, nowayout);
return 0;
}
@@ -428,21 +376,33 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev)
/**
* bfin_wdt_remove - Initialize module
*
- * Unregisters the misc device and notifier handler. Actual device
+ * Unregisters the misc device. Actual device
* deinitialization is handled by bfin_wdt_close().
*/
-static int __devexit bfin_wdt_remove(struct platform_device *pdev)
+static int bfin_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&bfin_wdt_miscdev);
- unregister_reboot_notifier(&bfin_wdt_notifier);
return 0;
}
+/**
+ * bfin_wdt_shutdown - Soft Shutdown Handler
+ *
+ * Handles the soft shutdown event.
+ */
+static void bfin_wdt_shutdown(struct platform_device *pdev)
+{
+ stampit();
+
+ bfin_wdt_stop();
+}
+
static struct platform_device *bfin_wdt_device;
static struct platform_driver bfin_wdt_driver = {
.probe = bfin_wdt_probe,
- .remove = __devexit_p(bfin_wdt_remove),
+ .remove = bfin_wdt_remove,
+ .shutdown = bfin_wdt_shutdown,
.suspend = bfin_wdt_suspend,
.resume = bfin_wdt_resume,
.driver = {
@@ -472,13 +432,14 @@ static int __init bfin_wdt_init(void)
*/
ret = platform_driver_register(&bfin_wdt_driver);
if (ret) {
- pr_init(KERN_ERR PFX "unable to register driver\n");
+ pr_err("unable to register driver\n");
return ret;
}
- bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0);
+ bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME,
+ -1, NULL, 0);
if (IS_ERR(bfin_wdt_device)) {
- pr_init(KERN_ERR PFX "unable to register device\n");
+ pr_err("unable to register device\n");
platform_driver_unregister(&bfin_wdt_driver);
return PTR_ERR(bfin_wdt_device);
}
@@ -504,14 +465,13 @@ module_exit(bfin_wdt_exit);
MODULE_AUTHOR("Michele d'Amico, Mike Frysinger <vapier@gentoo.org>");
MODULE_DESCRIPTION("Blackfin Watchdog Device Driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
module_param(timeout, uint, 0);
MODULE_PARM_DESC(timeout,
"Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
__MODULE_STRING(WATCHDOG_TIMEOUT) ")");
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");