diff options
author | Phil Sutter <n0-1@freewrt.org> | 2009-02-08 10:44:42 -0500 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2009-03-25 05:00:05 -0400 |
commit | 08eb2e0c084778f30691e3f18540cdb754c56530 (patch) | |
tree | 3bf0dc94b35e4db2452944db4391874d7672b2f8 | |
parent | 9b655e07d77e3b1a00c1c8302e2ef3b7fb719de3 (diff) |
[WATCHDOG] rc32434_wdt: add timeout module parameter
The WDT timer ticks quite fast (half of the CPU clock speed, which may
be between 198MHz and 330MHz (or 400MHz on newer boards)). Given it's
size of 32Bit, the maximum timeout value ranges from about 21s to 43s,
depending on the configured CPU clock speed.
This patch add's the timeout module parameter and checks that it's not
bigger then the maximum timeout for the given clock speed.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
-rw-r--r-- | drivers/watchdog/rc32434_wdt.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index 68fb22625cdc..89f326a39b6b 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c | |||
@@ -34,7 +34,7 @@ | |||
34 | 34 | ||
35 | #define PFX KBUILD_MODNAME ": " | 35 | #define PFX KBUILD_MODNAME ": " |
36 | 36 | ||
37 | #define VERSION "0.4" | 37 | #define VERSION "0.5" |
38 | 38 | ||
39 | static struct { | 39 | static struct { |
40 | unsigned long inuse; | 40 | unsigned long inuse; |
@@ -58,6 +58,9 @@ extern unsigned int idt_cpu_freq; | |||
58 | #define WATCHDOG_TIMEOUT 20 | 58 | #define WATCHDOG_TIMEOUT 20 |
59 | 59 | ||
60 | static int timeout = WATCHDOG_TIMEOUT; | 60 | static int timeout = WATCHDOG_TIMEOUT; |
61 | module_param(timeout, int, 0); | ||
62 | MODULE_PARM_DESC(timeout, "Watchdog timeout value, in seconds (default=" | ||
63 | WATCHDOG_TIMEOUT ")"); | ||
61 | 64 | ||
62 | static int nowayout = WATCHDOG_NOWAYOUT; | 65 | static int nowayout = WATCHDOG_NOWAYOUT; |
63 | module_param(nowayout, int, 0); | 66 | module_param(nowayout, int, 0); |
@@ -68,6 +71,21 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | |||
68 | #define SET_BITS(addr, or, nand) \ | 71 | #define SET_BITS(addr, or, nand) \ |
69 | writel((readl(&addr) | or) & ~nand, &addr) | 72 | writel((readl(&addr) | or) & ~nand, &addr) |
70 | 73 | ||
74 | static int rc32434_wdt_set(int new_timeout) | ||
75 | { | ||
76 | int max_to = WTCOMP2SEC((u32)-1); | ||
77 | |||
78 | if (new_timeout < 0 || new_timeout > max_to) { | ||
79 | printk(KERN_ERR PFX "timeout value must be between 0 and %d", | ||
80 | max_to); | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | timeout = new_timeout; | ||
84 | writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
71 | static void rc32434_wdt_start(void) | 89 | static void rc32434_wdt_start(void) |
72 | { | 90 | { |
73 | u32 or, nand; | 91 | u32 or, nand; |
@@ -85,6 +103,9 @@ static void rc32434_wdt_start(void) | |||
85 | 103 | ||
86 | SET_BITS(wdt_reg->errcs, or, nand); | 104 | SET_BITS(wdt_reg->errcs, or, nand); |
87 | 105 | ||
106 | /* set the timeout (either default or based on module param) */ | ||
107 | rc32434_wdt_set(timeout); | ||
108 | |||
88 | /* reset WTC timeout bit and enable WDT */ | 109 | /* reset WTC timeout bit and enable WDT */ |
89 | nand = 1 << RC32434_WTC_TO; | 110 | nand = 1 << RC32434_WTC_TO; |
90 | or = 1 << RC32434_WTC_EN; | 111 | or = 1 << RC32434_WTC_EN; |
@@ -102,21 +123,6 @@ static void rc32434_wdt_stop(void) | |||
102 | printk(KERN_INFO PFX "Stopped watchdog timer.\n"); | 123 | printk(KERN_INFO PFX "Stopped watchdog timer.\n"); |
103 | } | 124 | } |
104 | 125 | ||
105 | static int rc32434_wdt_set(int new_timeout) | ||
106 | { | ||
107 | int max_to = WTCOMP2SEC((u32)-1); | ||
108 | |||
109 | if (new_timeout < 0 || new_timeout > max_to) { | ||
110 | printk(KERN_ERR PFX "timeout value must be between 0 and %d", | ||
111 | max_to); | ||
112 | return -EINVAL; | ||
113 | } | ||
114 | timeout = new_timeout; | ||
115 | writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static void rc32434_wdt_ping(void) | 126 | static void rc32434_wdt_ping(void) |
121 | { | 127 | { |
122 | writel(0, &wdt_reg->wtcount); | 128 | writel(0, &wdt_reg->wtcount); |
@@ -264,6 +270,15 @@ static int __devinit rc32434_wdt_probe(struct platform_device *pdev) | |||
264 | return -ENXIO; | 270 | return -ENXIO; |
265 | } | 271 | } |
266 | 272 | ||
273 | /* Check that the heartbeat value is within it's range; | ||
274 | * if not reset to the default */ | ||
275 | if (rc32434_wdt_set(timeout)) { | ||
276 | rc32434_wdt_set(WATCHDOG_TIMEOUT); | ||
277 | printk(KERN_INFO PFX | ||
278 | "timeout value must be between 0 and %d\n", | ||
279 | WTCOMP2SEC((u32)-1)); | ||
280 | } | ||
281 | |||
267 | ret = misc_register(&rc32434_wdt_miscdev); | 282 | ret = misc_register(&rc32434_wdt_miscdev); |
268 | if (ret < 0) { | 283 | if (ret < 0) { |
269 | printk(KERN_ERR PFX "failed to register watchdog device\n"); | 284 | printk(KERN_ERR PFX "failed to register watchdog device\n"); |