diff options
Diffstat (limited to 'drivers/watchdog/sa1100_wdt.c')
| -rw-r--r-- | drivers/watchdog/sa1100_wdt.c | 91 |
1 files changed, 48 insertions, 43 deletions
diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index 34a2b3b8180..e1d39a1e962 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c @@ -1,8 +1,8 @@ /* * Watchdog driver for the SA11x0/PXA2xx * - * (c) Copyright 2000 Oleg Drokin <green@crimea.edu> - * Based on SoftDog driver by Alan Cox <alan@redhat.com> + * (c) Copyright 2000 Oleg Drokin <green@crimea.edu> + * Based on SoftDog driver by Alan Cox <alan@lxorguk.ukuu.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,8 +15,11 @@ * * (c) Copyright 2000 Oleg Drokin <green@crimea.edu> * - * 27/11/2000 Initial release + * 27/11/2000 Initial release */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/types.h> @@ -25,19 +28,21 @@ #include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/init.h> +#include <linux/io.h> #include <linux/bitops.h> +#include <linux/uaccess.h> +#include <linux/timex.h> #ifdef CONFIG_ARCH_PXA -#include <asm/arch/pxa-regs.h> +#include <mach/regs-ost.h> #endif -#include <asm/hardware.h> -#include <asm/uaccess.h> - -#define OSCR_FREQ CLOCK_TICK_RATE +#include <mach/reset.h> +#include <mach/hardware.h> +static unsigned long oscr_freq; static unsigned long sa1100wdt_users; -static int pre_margin; +static unsigned int pre_margin; static int boot_status; /* @@ -45,14 +50,14 @@ static int boot_status; */ static int sa1100dog_open(struct inode *inode, struct file *file) { - if (test_and_set_bit(1,&sa1100wdt_users)) + if (test_and_set_bit(1, &sa1100wdt_users)) return -EBUSY; /* Activate SA1100 Watchdog timer */ - OSMR3 = OSCR + pre_margin; - OSSR = OSSR_M3; - OWER = OWER_WME; - OIER |= OIER_E3; + writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); + writel_relaxed(OSSR_M3, OSSR); + writel_relaxed(OWER_WME, OWER); + writel_relaxed(readl_relaxed(OIER) | OIER_E3, OIER); return nonseekable_open(inode, file); } @@ -65,29 +70,29 @@ static int sa1100dog_open(struct inode *inode, struct file *file) */ static int sa1100dog_release(struct inode *inode, struct file *file) { - printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); - + pr_crit("Device closed - timer will not stop\n"); clear_bit(1, &sa1100wdt_users); - return 0; } -static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) +static ssize_t sa1100dog_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) { if (len) /* Refresh OSMR3 timer. */ - OSMR3 = OSCR + pre_margin; - + writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); return len; } -static struct watchdog_info ident = { - .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, +static const struct watchdog_info ident = { + .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT + | WDIOF_KEEPALIVEPING, .identity = "SA1100/PXA255 Watchdog", + .firmware_version = 1, }; -static int sa1100dog_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long sa1100dog_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { int ret = -ENOTTY; int time; @@ -108,44 +113,42 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, ret = put_user(boot_status, p); break; + case WDIOC_KEEPALIVE: + writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); + ret = 0; + break; + case WDIOC_SETTIMEOUT: ret = get_user(time, p); if (ret) break; - if (time <= 0 || time > 255) { + if (time <= 0 || (oscr_freq * (long long)time >= 0xffffffff)) { ret = -EINVAL; break; } - pre_margin = OSCR_FREQ * time; - OSMR3 = OSCR + pre_margin; + pre_margin = oscr_freq * time; + writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); /*fall through*/ case WDIOC_GETTIMEOUT: - ret = put_user(pre_margin / OSCR_FREQ, p); - break; - - case WDIOC_KEEPALIVE: - OSMR3 = OSCR + pre_margin; - ret = 0; + ret = put_user(pre_margin / oscr_freq, p); break; } return ret; } -static const struct file_operations sa1100dog_fops = -{ +static const struct file_operations sa1100dog_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = sa1100dog_write, - .ioctl = sa1100dog_ioctl, + .unlocked_ioctl = sa1100dog_ioctl, .open = sa1100dog_open, .release = sa1100dog_release, }; -static struct miscdevice sa1100dog_miscdev = -{ +static struct miscdevice sa1100dog_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &sa1100dog_fops, @@ -157,18 +160,21 @@ static int __init sa1100dog_init(void) { int ret; + oscr_freq = get_clock_tick_rate(); + /* * Read the reset status, and save it for later. If * we suspend, RCSR will be cleared, and the watchdog * reset reason will be lost. */ - boot_status = (RCSR & RCSR_WDR) ? WDIOF_CARDRESET : 0; - pre_margin = OSCR_FREQ * margin; + boot_status = (reset_status & RESET_STATUS_WATCHDOG) ? + WDIOF_CARDRESET : 0; + pre_margin = oscr_freq * margin; ret = misc_register(&sa1100dog_miscdev); if (ret == 0) - printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", - margin); + pr_info("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", + margin); return ret; } @@ -187,4 +193,3 @@ module_param(margin, int, 0); MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
