Blame view
drivers/watchdog/sa1100_wdt.c
4.46 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * Watchdog driver for the SA11x0/PXA2xx * |
143a2e54b [WATCHDOG] More c... |
4 5 |
* (c) Copyright 2000 Oleg Drokin <green@crimea.edu> * Based on SoftDog driver by Alan Cox <alan@lxorguk.ukuu.org.uk> |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 11 12 13 14 15 16 17 |
* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide * warranty for any of this software. This material is provided * "AS-IS" and at no charge. * * (c) Copyright 2000 Oleg Drokin <green@crimea.edu> * |
143a2e54b [WATCHDOG] More c... |
18 |
* 27/11/2000 Initial release |
1da177e4c Linux-2.6.12-rc2 |
19 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
20 21 22 23 24 25 26 27 |
#include <linux/module.h> #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/init.h> |
1977f0327 remove asm/bitops... |
28 |
#include <linux/bitops.h> |
f19e03126 [WATCHDOG 36/57] ... |
29 |
#include <linux/uaccess.h> |
87c52578b [ARM] Remove linu... |
30 |
#include <linux/timex.h> |
1da177e4c Linux-2.6.12-rc2 |
31 32 |
#ifdef CONFIG_ARCH_PXA |
5bf3df3f0 [ARM] pxa: separa... |
33 |
#include <mach/regs-ost.h> |
1da177e4c Linux-2.6.12-rc2 |
34 |
#endif |
afd2fc02a Merge branch 'for... |
35 |
#include <mach/reset.h> |
a09e64fbc [ARM] Move includ... |
36 |
#include <mach/hardware.h> |
1da177e4c Linux-2.6.12-rc2 |
37 |
|
28a623855 [ARM] sa1100_wdt:... |
38 |
static unsigned long oscr_freq; |
1da177e4c Linux-2.6.12-rc2 |
39 |
static unsigned long sa1100wdt_users; |
a6f052e39 [WATCHDOG] SA1100... |
40 |
static unsigned int pre_margin; |
1da177e4c Linux-2.6.12-rc2 |
41 |
static int boot_status; |
1da177e4c Linux-2.6.12-rc2 |
42 43 44 45 46 47 |
/* * Allow only one person to hold it open */ static int sa1100dog_open(struct inode *inode, struct file *file) { |
f19e03126 [WATCHDOG 36/57] ... |
48 |
if (test_and_set_bit(1, &sa1100wdt_users)) |
1da177e4c Linux-2.6.12-rc2 |
49 50 51 52 53 54 55 |
return -EBUSY; /* Activate SA1100 Watchdog timer */ OSMR3 = OSCR + pre_margin; OSSR = OSSR_M3; OWER = OWER_WME; OIER |= OIER_E3; |
6abe78bf1 [WATCHDOG] Return... |
56 |
return nonseekable_open(inode, file); |
1da177e4c Linux-2.6.12-rc2 |
57 58 59 |
} /* |
9bbd03758 [PATCH] ARM: 2833... |
60 61 62 63 64 |
* The watchdog cannot be disabled. * * Previous comments suggested that turning off the interrupt by * clearing OIER[E3] would prevent the watchdog timing out but this * does not appear to be true (at least on the PXA255). |
1da177e4c Linux-2.6.12-rc2 |
65 66 67 |
*/ static int sa1100dog_release(struct inode *inode, struct file *file) { |
9bbd03758 [PATCH] ARM: 2833... |
68 69 |
printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop "); |
1da177e4c Linux-2.6.12-rc2 |
70 |
clear_bit(1, &sa1100wdt_users); |
1da177e4c Linux-2.6.12-rc2 |
71 72 |
return 0; } |
f19e03126 [WATCHDOG 36/57] ... |
73 74 |
static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) |
1da177e4c Linux-2.6.12-rc2 |
75 |
{ |
9bbd03758 [PATCH] ARM: 2833... |
76 |
if (len) |
1da177e4c Linux-2.6.12-rc2 |
77 78 |
/* Refresh OSMR3 timer. */ OSMR3 = OSCR + pre_margin; |
1da177e4c Linux-2.6.12-rc2 |
79 80 |
return len; } |
f19e03126 [WATCHDOG 36/57] ... |
81 82 83 |
static const struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
9bbd03758 [PATCH] ARM: 2833... |
84 |
.identity = "SA1100/PXA255 Watchdog", |
a6f052e39 [WATCHDOG] SA1100... |
85 |
.firmware_version = 1, |
1da177e4c Linux-2.6.12-rc2 |
86 |
}; |
f19e03126 [WATCHDOG 36/57] ... |
87 88 |
static long sa1100dog_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
89 |
{ |
795b89d20 [WATCHDOG] use EN... |
90 |
int ret = -ENOTTY; |
1da177e4c Linux-2.6.12-rc2 |
91 |
int time; |
3a69e5791 [WATCHDOG] sa1100... |
92 93 |
void __user *argp = (void __user *)arg; int __user *p = argp; |
1da177e4c Linux-2.6.12-rc2 |
94 95 96 |
switch (cmd) { case WDIOC_GETSUPPORT: |
3a69e5791 [WATCHDOG] sa1100... |
97 |
ret = copy_to_user(argp, &ident, |
1da177e4c Linux-2.6.12-rc2 |
98 99 100 101 |
sizeof(ident)) ? -EFAULT : 0; break; case WDIOC_GETSTATUS: |
3a69e5791 [WATCHDOG] sa1100... |
102 |
ret = put_user(0, p); |
1da177e4c Linux-2.6.12-rc2 |
103 104 105 |
break; case WDIOC_GETBOOTSTATUS: |
3a69e5791 [WATCHDOG] sa1100... |
106 |
ret = put_user(boot_status, p); |
1da177e4c Linux-2.6.12-rc2 |
107 |
break; |
0c06090c9 [WATCHDOG] Coding... |
108 109 110 111 |
case WDIOC_KEEPALIVE: OSMR3 = OSCR + pre_margin; ret = 0; break; |
1da177e4c Linux-2.6.12-rc2 |
112 |
case WDIOC_SETTIMEOUT: |
3a69e5791 [WATCHDOG] sa1100... |
113 |
ret = get_user(time, p); |
1da177e4c Linux-2.6.12-rc2 |
114 115 |
if (ret) break; |
a6f052e39 [WATCHDOG] SA1100... |
116 |
if (time <= 0 || (oscr_freq * (long long)time >= 0xffffffff)) { |
1da177e4c Linux-2.6.12-rc2 |
117 118 119 |
ret = -EINVAL; break; } |
28a623855 [ARM] sa1100_wdt:... |
120 |
pre_margin = oscr_freq * time; |
1da177e4c Linux-2.6.12-rc2 |
121 122 123 124 |
OSMR3 = OSCR + pre_margin; /*fall through*/ case WDIOC_GETTIMEOUT: |
28a623855 [ARM] sa1100_wdt:... |
125 |
ret = put_user(pre_margin / oscr_freq, p); |
1da177e4c Linux-2.6.12-rc2 |
126 |
break; |
1da177e4c Linux-2.6.12-rc2 |
127 128 129 |
} return ret; } |
f19e03126 [WATCHDOG 36/57] ... |
130 |
static const struct file_operations sa1100dog_fops = { |
1da177e4c Linux-2.6.12-rc2 |
131 132 133 |
.owner = THIS_MODULE, .llseek = no_llseek, .write = sa1100dog_write, |
f19e03126 [WATCHDOG 36/57] ... |
134 |
.unlocked_ioctl = sa1100dog_ioctl, |
1da177e4c Linux-2.6.12-rc2 |
135 136 137 |
.open = sa1100dog_open, .release = sa1100dog_release, }; |
f19e03126 [WATCHDOG 36/57] ... |
138 |
static struct miscdevice sa1100dog_miscdev = { |
1da177e4c Linux-2.6.12-rc2 |
139 |
.minor = WATCHDOG_MINOR, |
9bbd03758 [PATCH] ARM: 2833... |
140 |
.name = "watchdog", |
1da177e4c Linux-2.6.12-rc2 |
141 142 143 144 145 146 147 148 |
.fops = &sa1100dog_fops, }; static int margin __initdata = 60; /* (secs) Default is 1 minute */ static int __init sa1100dog_init(void) { int ret; |
28a623855 [ARM] sa1100_wdt:... |
149 |
oscr_freq = get_clock_tick_rate(); |
1da177e4c Linux-2.6.12-rc2 |
150 151 152 153 154 |
/* * Read the reset status, and save it for later. If * we suspend, RCSR will be cleared, and the watchdog * reset reason will be lost. */ |
214c6a7ed [ARM] sa1100_wdt:... |
155 156 |
boot_status = (reset_status & RESET_STATUS_WATCHDOG) ? WDIOF_CARDRESET : 0; |
28a623855 [ARM] sa1100_wdt:... |
157 |
pre_margin = oscr_freq * margin; |
1da177e4c Linux-2.6.12-rc2 |
158 159 160 |
ret = misc_register(&sa1100dog_miscdev); if (ret == 0) |
f19e03126 [WATCHDOG 36/57] ... |
161 162 163 164 |
printk(KERN_INFO "SA1100/PXA2xx Watchdog Timer: timer margin %d sec ", margin); |
1da177e4c Linux-2.6.12-rc2 |
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
return ret; } static void __exit sa1100dog_exit(void) { misc_deregister(&sa1100dog_miscdev); } module_init(sa1100dog_init); module_exit(sa1100dog_exit); MODULE_AUTHOR("Oleg Drokin <green@crimea.edu>"); MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog"); module_param(margin, int, 0); MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); |
1da177e4c Linux-2.6.12-rc2 |
181 182 |
MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |