diff options
Diffstat (limited to 'drivers/watchdog/mpc8xxx_wdt.c')
| -rw-r--r-- | drivers/watchdog/mpc8xxx_wdt.c | 168 |
1 files changed, 70 insertions, 98 deletions
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 38c588ee694..7831955cd9e 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -2,9 +2,9 @@ * mpc8xxx_wdt.c - MPC8xx/MPC83xx/MPC86xx watchdog userspace interface * * Authors: Dave Updegraff <dave@cray.org> - * Kumar Gala <galak@kernel.crashing.org> - * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org> - * ..and from sc520_wdt + * Kumar Gala <galak@kernel.crashing.org> + * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org> + * ..and from sc520_wdt * Copyright (c) 2008 MontaVista Software, Inc. * Anton Vorontsov <avorontsov@ru.mvista.com> * @@ -17,11 +17,14 @@ * option) any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/fs.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/timer.h> #include <linux/miscdevice.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/module.h> #include <linux/watchdog.h> @@ -53,15 +56,15 @@ static int mpc8xxx_wdt_init_late(void); static u16 timeout = 0xffff; module_param(timeout, ushort, 0); MODULE_PARM_DESC(timeout, - "Watchdog timeout in ticks. (0<timeout<65536, default=65535"); + "Watchdog timeout in ticks. (0<timeout<65536, default=65535)"); -static int reset = 1; +static bool reset = 1; module_param(reset, bool, 0); MODULE_PARM_DESC(reset, "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset"); -static int nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, int, 0); +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) ")"); @@ -70,9 +73,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " * to 0 */ static int prescale = 1; -static unsigned int timeout_sec; -static unsigned long wdt_is_open; static DEFINE_SPINLOCK(wdt_spinlock); static void mpc8xxx_wdt_keepalive(void) @@ -84,39 +85,23 @@ static void mpc8xxx_wdt_keepalive(void) spin_unlock(&wdt_spinlock); } +static struct watchdog_device mpc8xxx_wdt_dev; static void mpc8xxx_wdt_timer_ping(unsigned long arg); -static DEFINE_TIMER(wdt_timer, mpc8xxx_wdt_timer_ping, 0, 0); +static DEFINE_TIMER(wdt_timer, mpc8xxx_wdt_timer_ping, 0, + (unsigned long)&mpc8xxx_wdt_dev); static void mpc8xxx_wdt_timer_ping(unsigned long arg) { + struct watchdog_device *w = (struct watchdog_device *)arg; + mpc8xxx_wdt_keepalive(); /* We're pinging it twice faster than needed, just to be sure. */ - mod_timer(&wdt_timer, jiffies + HZ * timeout_sec / 2); -} - -static void mpc8xxx_wdt_pr_warn(const char *msg) -{ - pr_crit("mpc8xxx_wdt: %s, expect the %s soon!\n", msg, - reset ? "reset" : "machine check exception"); + mod_timer(&wdt_timer, jiffies + HZ * w->timeout / 2); } -static ssize_t mpc8xxx_wdt_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - if (count) - mpc8xxx_wdt_keepalive(); - return count; -} - -static int mpc8xxx_wdt_open(struct inode *inode, struct file *file) +static int mpc8xxx_wdt_start(struct watchdog_device *w) { u32 tmp = SWCRR_SWEN; - if (test_and_set_bit(0, &wdt_is_open)) - return -EBUSY; - - /* Once we start the watchdog we can't stop it */ - if (nowayout) - __module_get(THIS_MODULE); /* Good, fire up the show */ if (prescale) @@ -130,69 +115,54 @@ static int mpc8xxx_wdt_open(struct inode *inode, struct file *file) del_timer_sync(&wdt_timer); - return nonseekable_open(inode, file); + return 0; } -static int mpc8xxx_wdt_release(struct inode *inode, struct file *file) +static int mpc8xxx_wdt_ping(struct watchdog_device *w) { - if (!nowayout) - mpc8xxx_wdt_timer_ping(0); - else - mpc8xxx_wdt_pr_warn("watchdog closed"); - clear_bit(0, &wdt_is_open); + mpc8xxx_wdt_keepalive(); return 0; } -static long mpc8xxx_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +static int mpc8xxx_wdt_stop(struct watchdog_device *w) { - void __user *argp = (void __user *)arg; - int __user *p = argp; - static struct watchdog_info ident = { - .options = WDIOF_KEEPALIVEPING, - .firmware_version = 1, - .identity = "MPC8xxx", - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0, p); - case WDIOC_KEEPALIVE: - mpc8xxx_wdt_keepalive(); - return 0; - case WDIOC_GETTIMEOUT: - return put_user(timeout_sec, p); - default: - return -ENOTTY; - } + mod_timer(&wdt_timer, jiffies); + return 0; } -static const struct file_operations mpc8xxx_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = mpc8xxx_wdt_write, - .unlocked_ioctl = mpc8xxx_wdt_ioctl, - .open = mpc8xxx_wdt_open, - .release = mpc8xxx_wdt_release, +static struct watchdog_info mpc8xxx_wdt_info = { + .options = WDIOF_KEEPALIVEPING, + .firmware_version = 1, + .identity = "MPC8xxx", +}; + +static struct watchdog_ops mpc8xxx_wdt_ops = { + .owner = THIS_MODULE, + .start = mpc8xxx_wdt_start, + .ping = mpc8xxx_wdt_ping, + .stop = mpc8xxx_wdt_stop, }; -static struct miscdevice mpc8xxx_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &mpc8xxx_wdt_fops, +static struct watchdog_device mpc8xxx_wdt_dev = { + .info = &mpc8xxx_wdt_info, + .ops = &mpc8xxx_wdt_ops, }; -static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, - const struct of_device_id *match) +static const struct of_device_id mpc8xxx_wdt_match[]; +static int mpc8xxx_wdt_probe(struct platform_device *ofdev) { int ret; - struct device_node *np = ofdev->node; - struct mpc8xxx_wdt_type *wdt_type = match->data; + const struct of_device_id *match; + struct device_node *np = ofdev->dev.of_node; + const struct mpc8xxx_wdt_type *wdt_type; u32 freq = fsl_get_sys_freq(); bool enabled; + unsigned int timeout_sec; + + match = of_match_device(mpc8xxx_wdt_match, &ofdev->dev); + if (!match) + return -EINVAL; + wdt_type = match->data; if (!freq || freq == -1) return -EINVAL; @@ -203,7 +173,7 @@ static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, enabled = in_be32(&wd_base->swcrr) & SWCRR_SWEN; if (!enabled && wdt_type->hw_enabled) { - pr_info("mpc8xxx_wdt: could not be enabled in software\n"); + pr_info("could not be enabled in software\n"); ret = -ENOSYS; goto err_unmap; } @@ -214,15 +184,15 @@ static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, else timeout_sec = timeout / freq; + mpc8xxx_wdt_dev.timeout = timeout_sec; #ifdef MODULE ret = mpc8xxx_wdt_init_late(); if (ret) goto err_unmap; #endif - pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d " - "(%d seconds)\n", reset ? "reset" : "interrupt", timeout, - timeout_sec); + pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d (%d seconds)\n", + reset ? "reset" : "interrupt", timeout, timeout_sec); /* * If the watchdog was previously enabled or we're running on @@ -230,7 +200,7 @@ static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, * userspace handles it. */ if (enabled) - mpc8xxx_wdt_timer_ping(0); + mod_timer(&wdt_timer, jiffies); return 0; err_unmap: iounmap(wd_base); @@ -238,11 +208,12 @@ err_unmap: return ret; } -static int __devexit mpc8xxx_wdt_remove(struct of_device *ofdev) +static int mpc8xxx_wdt_remove(struct platform_device *ofdev) { - mpc8xxx_wdt_pr_warn("watchdog removed"); + pr_crit("Watchdog removed, expect the %s soon!\n", + reset ? "reset" : "machine check exception"); del_timer_sync(&wdt_timer); - misc_deregister(&mpc8xxx_wdt_miscdev); + watchdog_unregister_device(&mpc8xxx_wdt_dev); iounmap(wd_base); return 0; @@ -266,19 +237,20 @@ static const struct of_device_id mpc8xxx_wdt_match[] = { .compatible = "fsl,mpc823-wdt", .data = &(struct mpc8xxx_wdt_type) { .prescaler = 0x800, + .hw_enabled = true, }, }, {}, }; MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match); -static struct of_platform_driver mpc8xxx_wdt_driver = { - .match_table = mpc8xxx_wdt_match, +static struct platform_driver mpc8xxx_wdt_driver = { .probe = mpc8xxx_wdt_probe, - .remove = __devexit_p(mpc8xxx_wdt_remove), - .driver = { - .name = "mpc8xxx_wdt", - .owner = THIS_MODULE, + .remove = mpc8xxx_wdt_remove, + .driver = { + .name = "mpc8xxx_wdt", + .owner = THIS_MODULE, + .of_match_table = mpc8xxx_wdt_match, }, }; @@ -294,10 +266,11 @@ static int mpc8xxx_wdt_init_late(void) if (!wd_base) return -ENODEV; - ret = misc_register(&mpc8xxx_wdt_miscdev); + watchdog_set_nowayout(&mpc8xxx_wdt_dev, nowayout); + + ret = watchdog_register_device(&mpc8xxx_wdt_dev); if (ret) { - pr_err("cannot register miscdev on minor=%d (err=%d)\n", - WATCHDOG_MINOR, ret); + pr_err("cannot register watchdog device (err=%d)\n", ret); return ret; } return 0; @@ -308,13 +281,13 @@ module_init(mpc8xxx_wdt_init_late); static int __init mpc8xxx_wdt_init(void) { - return of_register_platform_driver(&mpc8xxx_wdt_driver); + return platform_driver_register(&mpc8xxx_wdt_driver); } arch_initcall(mpc8xxx_wdt_init); static void __exit mpc8xxx_wdt_exit(void) { - of_unregister_platform_driver(&mpc8xxx_wdt_driver); + platform_driver_unregister(&mpc8xxx_wdt_driver); } module_exit(mpc8xxx_wdt_exit); @@ -322,4 +295,3 @@ MODULE_AUTHOR("Dave Updegraff, Kumar Gala"); MODULE_DESCRIPTION("Driver for watchdog timer in MPC8xx/MPC83xx/MPC86xx " "uProcessors"); MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
