Blame view
drivers/watchdog/sa1100_wdt.c
4.64 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 |
*/ |
27c766aaa watchdog: Use pr_... |
20 21 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
1da177e4c Linux-2.6.12-rc2 |
22 23 24 25 26 27 28 29 |
#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> |
23019a733 ARM: pxa: use com... |
30 |
#include <linux/io.h> |
1977f0327 remove asm/bitops... |
31 |
#include <linux/bitops.h> |
f19e03126 [WATCHDOG 36/57] ... |
32 |
#include <linux/uaccess.h> |
87c52578b [ARM] Remove linu... |
33 |
#include <linux/timex.h> |
1da177e4c Linux-2.6.12-rc2 |
34 35 |
#ifdef CONFIG_ARCH_PXA |
5bf3df3f0 [ARM] pxa: separa... |
36 |
#include <mach/regs-ost.h> |
1da177e4c Linux-2.6.12-rc2 |
37 |
#endif |
afd2fc02a Merge branch 'for... |
38 |
#include <mach/reset.h> |
a09e64fbc [ARM] Move includ... |
39 |
#include <mach/hardware.h> |
1da177e4c Linux-2.6.12-rc2 |
40 |
|
28a623855 [ARM] sa1100_wdt:... |
41 |
static unsigned long oscr_freq; |
1da177e4c Linux-2.6.12-rc2 |
42 |
static unsigned long sa1100wdt_users; |
a6f052e39 [WATCHDOG] SA1100... |
43 |
static unsigned int pre_margin; |
1da177e4c Linux-2.6.12-rc2 |
44 |
static int boot_status; |
1da177e4c Linux-2.6.12-rc2 |
45 46 47 48 49 50 |
/* * Allow only one person to hold it open */ static int sa1100dog_open(struct inode *inode, struct file *file) { |
f19e03126 [WATCHDOG 36/57] ... |
51 |
if (test_and_set_bit(1, &sa1100wdt_users)) |
1da177e4c Linux-2.6.12-rc2 |
52 53 54 |
return -EBUSY; /* Activate SA1100 Watchdog timer */ |
3169663ac ARM: sa11x0/pxa: ... |
55 56 57 58 |
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); |
6abe78bf1 [WATCHDOG] Return... |
59 |
return nonseekable_open(inode, file); |
1da177e4c Linux-2.6.12-rc2 |
60 61 62 |
} /* |
9bbd03758 [PATCH] ARM: 2833... |
63 64 65 66 67 |
* 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 |
68 69 70 |
*/ static int sa1100dog_release(struct inode *inode, struct file *file) { |
27c766aaa watchdog: Use pr_... |
71 72 |
pr_crit("Device closed - timer will not stop "); |
1da177e4c Linux-2.6.12-rc2 |
73 |
clear_bit(1, &sa1100wdt_users); |
1da177e4c Linux-2.6.12-rc2 |
74 75 |
return 0; } |
f19e03126 [WATCHDOG 36/57] ... |
76 77 |
static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) |
1da177e4c Linux-2.6.12-rc2 |
78 |
{ |
9bbd03758 [PATCH] ARM: 2833... |
79 |
if (len) |
1da177e4c Linux-2.6.12-rc2 |
80 |
/* Refresh OSMR3 timer. */ |
3169663ac ARM: sa11x0/pxa: ... |
81 |
writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); |
1da177e4c Linux-2.6.12-rc2 |
82 83 |
return len; } |
f19e03126 [WATCHDOG 36/57] ... |
84 85 86 |
static const struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
9bbd03758 [PATCH] ARM: 2833... |
87 |
.identity = "SA1100/PXA255 Watchdog", |
a6f052e39 [WATCHDOG] SA1100... |
88 |
.firmware_version = 1, |
1da177e4c Linux-2.6.12-rc2 |
89 |
}; |
f19e03126 [WATCHDOG 36/57] ... |
90 91 |
static long sa1100dog_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
92 |
{ |
795b89d20 [WATCHDOG] use EN... |
93 |
int ret = -ENOTTY; |
1da177e4c Linux-2.6.12-rc2 |
94 |
int time; |
3a69e5791 [WATCHDOG] sa1100... |
95 96 |
void __user *argp = (void __user *)arg; int __user *p = argp; |
1da177e4c Linux-2.6.12-rc2 |
97 98 99 |
switch (cmd) { case WDIOC_GETSUPPORT: |
3a69e5791 [WATCHDOG] sa1100... |
100 |
ret = copy_to_user(argp, &ident, |
1da177e4c Linux-2.6.12-rc2 |
101 102 103 104 |
sizeof(ident)) ? -EFAULT : 0; break; case WDIOC_GETSTATUS: |
3a69e5791 [WATCHDOG] sa1100... |
105 |
ret = put_user(0, p); |
1da177e4c Linux-2.6.12-rc2 |
106 107 108 |
break; case WDIOC_GETBOOTSTATUS: |
3a69e5791 [WATCHDOG] sa1100... |
109 |
ret = put_user(boot_status, p); |
1da177e4c Linux-2.6.12-rc2 |
110 |
break; |
0c06090c9 [WATCHDOG] Coding... |
111 |
case WDIOC_KEEPALIVE: |
3169663ac ARM: sa11x0/pxa: ... |
112 |
writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); |
0c06090c9 [WATCHDOG] Coding... |
113 114 |
ret = 0; break; |
1da177e4c Linux-2.6.12-rc2 |
115 |
case WDIOC_SETTIMEOUT: |
3a69e5791 [WATCHDOG] sa1100... |
116 |
ret = get_user(time, p); |
1da177e4c Linux-2.6.12-rc2 |
117 118 |
if (ret) break; |
a6f052e39 [WATCHDOG] SA1100... |
119 |
if (time <= 0 || (oscr_freq * (long long)time >= 0xffffffff)) { |
1da177e4c Linux-2.6.12-rc2 |
120 121 122 |
ret = -EINVAL; break; } |
28a623855 [ARM] sa1100_wdt:... |
123 |
pre_margin = oscr_freq * time; |
3169663ac ARM: sa11x0/pxa: ... |
124 |
writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); |
1da177e4c Linux-2.6.12-rc2 |
125 126 127 |
/*fall through*/ case WDIOC_GETTIMEOUT: |
28a623855 [ARM] sa1100_wdt:... |
128 |
ret = put_user(pre_margin / oscr_freq, p); |
1da177e4c Linux-2.6.12-rc2 |
129 |
break; |
1da177e4c Linux-2.6.12-rc2 |
130 131 132 |
} return ret; } |
f19e03126 [WATCHDOG 36/57] ... |
133 |
static const struct file_operations sa1100dog_fops = { |
1da177e4c Linux-2.6.12-rc2 |
134 135 136 |
.owner = THIS_MODULE, .llseek = no_llseek, .write = sa1100dog_write, |
f19e03126 [WATCHDOG 36/57] ... |
137 |
.unlocked_ioctl = sa1100dog_ioctl, |
1da177e4c Linux-2.6.12-rc2 |
138 139 140 |
.open = sa1100dog_open, .release = sa1100dog_release, }; |
f19e03126 [WATCHDOG 36/57] ... |
141 |
static struct miscdevice sa1100dog_miscdev = { |
1da177e4c Linux-2.6.12-rc2 |
142 |
.minor = WATCHDOG_MINOR, |
9bbd03758 [PATCH] ARM: 2833... |
143 |
.name = "watchdog", |
1da177e4c Linux-2.6.12-rc2 |
144 145 146 147 148 149 150 151 |
.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:... |
152 |
oscr_freq = get_clock_tick_rate(); |
1da177e4c Linux-2.6.12-rc2 |
153 154 155 156 157 |
/* * 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:... |
158 159 |
boot_status = (reset_status & RESET_STATUS_WATCHDOG) ? WDIOF_CARDRESET : 0; |
28a623855 [ARM] sa1100_wdt:... |
160 |
pre_margin = oscr_freq * margin; |
1da177e4c Linux-2.6.12-rc2 |
161 162 163 |
ret = misc_register(&sa1100dog_miscdev); if (ret == 0) |
27c766aaa watchdog: Use pr_... |
164 165 166 |
pr_info("SA1100/PXA2xx Watchdog Timer: timer margin %d sec ", margin); |
1da177e4c Linux-2.6.12-rc2 |
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
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 |
183 |
MODULE_LICENSE("GPL"); |