Commit cd3c1cde262b0f068d27d980648892b2843966d4

Authored by Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
  [WATCHDOG] orion5x_wdt.c: 'ORION5X_TCLK' undeclared
  [WATCHDOG] gef_wdt.c: fsl_get_sys_freq() failure not noticed
  [WATCHDOG] ks8695_wdt.c: 'CLOCK_TICK_RATE' undeclared
  [WATCHDOG] rc32434_wdt: fix sections
  [WATCHDOG] rc32434_wdt: fix watchdog driver

Showing 4 changed files Side-by-side Diff

drivers/watchdog/gef_wdt.c
... ... @@ -269,7 +269,7 @@
269 269 bus_clk = 133; /* in MHz */
270 270  
271 271 freq = fsl_get_sys_freq();
272   - if (freq > 0)
  272 + if (freq != -1)
273 273 bus_clk = freq;
274 274  
275 275 /* Map devices registers into memory */
drivers/watchdog/ks8695_wdt.c
... ... @@ -21,6 +21,7 @@
21 21 #include <linux/watchdog.h>
22 22 #include <linux/io.h>
23 23 #include <linux/uaccess.h>
  24 +#include <mach/timex.h>
24 25 #include <mach/regs-timer.h>
25 26  
26 27 #define WDT_DEFAULT_TIME 5 /* seconds */
drivers/watchdog/orion5x_wdt.c
... ... @@ -29,6 +29,7 @@
29 29 #define WDT_EN 0x0010
30 30 #define WDT_VAL (TIMER_VIRT_BASE + 0x0024)
31 31  
  32 +#define ORION5X_TCLK 166666667
32 33 #define WDT_MAX_DURATION (0xffffffff / ORION5X_TCLK)
33 34 #define WDT_IN_USE 0
34 35 #define WDT_OK_TO_CLOSE 1
drivers/watchdog/rc32434_wdt.c
... ... @@ -34,104 +34,89 @@
34 34 #include <asm/time.h>
35 35 #include <asm/mach-rc32434/integ.h>
36 36  
37   -#define MAX_TIMEOUT 20
38   -#define RC32434_WDT_INTERVAL (15 * HZ)
  37 +#define VERSION "0.4"
39 38  
40   -#define VERSION "0.2"
41   -
42 39 static struct {
43   - struct completion stop;
44   - int running;
45   - struct timer_list timer;
46   - int queue;
47   - int default_ticks;
48 40 unsigned long inuse;
49 41 } rc32434_wdt_device;
50 42  
51 43 static struct integ __iomem *wdt_reg;
52   -static int ticks = 100 * HZ;
53 44  
54 45 static int expect_close;
55   -static int timeout;
56 46  
  47 +/* Board internal clock speed in Hz,
  48 + * the watchdog timer ticks at. */
  49 +extern unsigned int idt_cpu_freq;
  50 +
  51 +/* translate wtcompare value to seconds and vice versa */
  52 +#define WTCOMP2SEC(x) (x / idt_cpu_freq)
  53 +#define SEC2WTCOMP(x) (x * idt_cpu_freq)
  54 +
  55 +/* Use a default timeout of 20s. This should be
  56 + * safe for CPU clock speeds up to 400MHz, as
  57 + * ((2 ^ 32) - 1) / (400MHz / 2) = 21s. */
  58 +#define WATCHDOG_TIMEOUT 20
  59 +
  60 +static int timeout = WATCHDOG_TIMEOUT;
  61 +
57 62 static int nowayout = WATCHDOG_NOWAYOUT;
58 63 module_param(nowayout, int, 0);
59 64 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
60 65 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
61 66  
  67 +/* apply or and nand masks to data read from addr and write back */
  68 +#define SET_BITS(addr, or, nand) \
  69 + writel((readl(&addr) | or) & ~nand, &addr)
62 70  
63 71 static void rc32434_wdt_start(void)
64 72 {
65   - u32 val;
  73 + u32 or, nand;
66 74  
67   - if (!rc32434_wdt_device.inuse) {
68   - writel(0, &wdt_reg->wtcount);
  75 + /* zero the counter before enabling */
  76 + writel(0, &wdt_reg->wtcount);
69 77  
70   - val = RC32434_ERR_WRE;
71   - writel(readl(&wdt_reg->errcs) | val, &wdt_reg->errcs);
  78 + /* don't generate a non-maskable interrupt,
  79 + * do a warm reset instead */
  80 + nand = 1 << RC32434_ERR_WNE;
  81 + or = 1 << RC32434_ERR_WRE;
72 82  
73   - val = RC32434_WTC_EN;
74   - writel(readl(&wdt_reg->wtc) | val, &wdt_reg->wtc);
75   - }
76   - rc32434_wdt_device.running++;
77   -}
  83 + /* reset the ERRCS timeout bit in case it's set */
  84 + nand |= 1 << RC32434_ERR_WTO;
78 85  
79   -static void rc32434_wdt_stop(void)
80   -{
81   - u32 val;
  86 + SET_BITS(wdt_reg->errcs, or, nand);
82 87  
83   - if (rc32434_wdt_device.running) {
  88 + /* reset WTC timeout bit and enable WDT */
  89 + nand = 1 << RC32434_WTC_TO;
  90 + or = 1 << RC32434_WTC_EN;
84 91  
85   - val = ~RC32434_WTC_EN;
86   - writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc);
  92 + SET_BITS(wdt_reg->wtc, or, nand);
  93 +}
87 94  
88   - val = ~RC32434_ERR_WRE;
89   - writel(readl(&wdt_reg->errcs) & val, &wdt_reg->errcs);
90   -
91   - rc32434_wdt_device.running = 0;
92   - }
  95 +static void rc32434_wdt_stop(void)
  96 +{
  97 + /* Disable WDT */
  98 + SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN);
93 99 }
94 100  
95   -static void rc32434_wdt_set(int new_timeout)
  101 +static int rc32434_wdt_set(int new_timeout)
96 102 {
97   - u32 cmp = new_timeout * HZ;
98   - u32 state, val;
  103 + int max_to = WTCOMP2SEC((u32)-1);
99 104  
  105 + if (new_timeout < 0 || new_timeout > max_to) {
  106 + printk(KERN_ERR KBUILD_MODNAME
  107 + ": timeout value must be between 0 and %d",
  108 + max_to);
  109 + return -EINVAL;
  110 + }
100 111 timeout = new_timeout;
101   - /*
102   - * store and disable WTC
103   - */
104   - state = (u32)(readl(&wdt_reg->wtc) & RC32434_WTC_EN);
105   - val = ~RC32434_WTC_EN;
106   - writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc);
  112 + writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare);
107 113  
108   - writel(0, &wdt_reg->wtcount);
109   - writel(cmp, &wdt_reg->wtcompare);
110   -
111   - /*
112   - * restore WTC
113   - */
114   -
115   - writel(readl(&wdt_reg->wtc) | state, &wdt_reg);
  114 + return 0;
116 115 }
117 116  
118   -static void rc32434_wdt_reset(void)
  117 +static void rc32434_wdt_ping(void)
119 118 {
120   - ticks = rc32434_wdt_device.default_ticks;
121   -}
122   -
123   -static void rc32434_wdt_update(unsigned long unused)
124   -{
125   - if (rc32434_wdt_device.running)
126   - ticks--;
127   -
128 119 writel(0, &wdt_reg->wtcount);
129   -
130   - if (rc32434_wdt_device.queue && ticks)
131   - mod_timer(&rc32434_wdt_device.timer,
132   - jiffies + RC32434_WDT_INTERVAL);
133   - else
134   - complete(&rc32434_wdt_device.stop);
135 120 }
136 121  
137 122 static int rc32434_wdt_open(struct inode *inode, struct file *file)
138 123  
139 124  
140 125  
... ... @@ -142,19 +127,23 @@
142 127 if (nowayout)
143 128 __module_get(THIS_MODULE);
144 129  
  130 + rc32434_wdt_start();
  131 + rc32434_wdt_ping();
  132 +
145 133 return nonseekable_open(inode, file);
146 134 }
147 135  
148 136 static int rc32434_wdt_release(struct inode *inode, struct file *file)
149 137 {
150   - if (expect_close && nowayout == 0) {
  138 + if (expect_close == 42) {
151 139 rc32434_wdt_stop();
152 140 printk(KERN_INFO KBUILD_MODNAME ": disabling watchdog timer\n");
153 141 module_put(THIS_MODULE);
154   - } else
  142 + } else {
155 143 printk(KERN_CRIT KBUILD_MODNAME
156 144 ": device closed unexpectedly. WDT will not stop !\n");
157   -
  145 + rc32434_wdt_ping();
  146 + }
158 147 clear_bit(0, &rc32434_wdt_device.inuse);
159 148 return 0;
160 149 }
161 150  
... ... @@ -174,10 +163,10 @@
174 163 if (get_user(c, data + i))
175 164 return -EFAULT;
176 165 if (c == 'V')
177   - expect_close = 1;
  166 + expect_close = 42;
178 167 }
179 168 }
180   - rc32434_wdt_update(0);
  169 + rc32434_wdt_ping();
181 170 return len;
182 171 }
183 172 return 0;
184 173  
... ... @@ -197,11 +186,11 @@
197 186 };
198 187 switch (cmd) {
199 188 case WDIOC_KEEPALIVE:
200   - rc32434_wdt_reset();
  189 + rc32434_wdt_ping();
201 190 break;
202 191 case WDIOC_GETSTATUS:
203 192 case WDIOC_GETBOOTSTATUS:
204   - value = readl(&wdt_reg->wtcount);
  193 + value = 0;
205 194 if (copy_to_user(argp, &value, sizeof(int)))
206 195 return -EFAULT;
207 196 break;
... ... @@ -218,6 +207,7 @@
218 207 break;
219 208 case WDIOS_DISABLECARD:
220 209 rc32434_wdt_stop();
  210 + break;
221 211 default:
222 212 return -EINVAL;
223 213 }
224 214  
... ... @@ -225,11 +215,9 @@
225 215 case WDIOC_SETTIMEOUT:
226 216 if (copy_from_user(&new_timeout, argp, sizeof(int)))
227 217 return -EFAULT;
228   - if (new_timeout < 1)
  218 + if (rc32434_wdt_set(new_timeout))
229 219 return -EINVAL;
230   - if (new_timeout > MAX_TIMEOUT)
231   - return -EINVAL;
232   - rc32434_wdt_set(new_timeout);
  220 + /* Fall through */
233 221 case WDIOC_GETTIMEOUT:
234 222 return copy_to_user(argp, &timeout, sizeof(int));
235 223 default:
236 224  
237 225  
... ... @@ -254,15 +242,15 @@
254 242 .fops = &rc32434_wdt_fops,
255 243 };
256 244  
257   -static char banner[] = KERN_INFO KBUILD_MODNAME
  245 +static char banner[] __devinitdata = KERN_INFO KBUILD_MODNAME
258 246 ": Watchdog Timer version " VERSION ", timer margin: %d sec\n";
259 247  
260   -static int rc32434_wdt_probe(struct platform_device *pdev)
  248 +static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
261 249 {
262 250 int ret;
263 251 struct resource *r;
264 252  
265   - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb500_wdt_res");
  253 + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res");
266 254 if (!r) {
267 255 printk(KERN_ERR KBUILD_MODNAME
268 256 "failed to retrieve resources\n");
269 257  
... ... @@ -277,24 +265,12 @@
277 265 }
278 266  
279 267 ret = misc_register(&rc32434_wdt_miscdev);
280   -
281 268 if (ret < 0) {
282 269 printk(KERN_ERR KBUILD_MODNAME
283 270 "failed to register watchdog device\n");
284 271 goto unmap;
285 272 }
286 273  
287   - init_completion(&rc32434_wdt_device.stop);
288   - rc32434_wdt_device.queue = 0;
289   -
290   - clear_bit(0, &rc32434_wdt_device.inuse);
291   -
292   - setup_timer(&rc32434_wdt_device.timer, rc32434_wdt_update, 0L);
293   -
294   - rc32434_wdt_device.default_ticks = ticks;
295   -
296   - rc32434_wdt_start();
297   -
298 274 printk(banner, timeout);
299 275  
300 276 return 0;
301 277  
302 278  
303 279  
304 280  
... ... @@ -304,23 +280,17 @@
304 280 return ret;
305 281 }
306 282  
307   -static int rc32434_wdt_remove(struct platform_device *pdev)
  283 +static int __devexit rc32434_wdt_remove(struct platform_device *pdev)
308 284 {
309   - if (rc32434_wdt_device.queue) {
310   - rc32434_wdt_device.queue = 0;
311   - wait_for_completion(&rc32434_wdt_device.stop);
312   - }
313 285 misc_deregister(&rc32434_wdt_miscdev);
314   -
315 286 iounmap(wdt_reg);
316   -
317 287 return 0;
318 288 }
319 289  
320 290 static struct platform_driver rc32434_wdt = {
321 291 .probe = rc32434_wdt_probe,
322   - .remove = rc32434_wdt_remove,
323   - .driver = {
  292 + .remove = __devexit_p(rc32434_wdt_remove),
  293 + .driver = {
324 294 .name = "rc32434_wdt",
325 295 }
326 296 };