diff options
author | Wim Van Sebroeck <wim@iguana.be> | 2006-11-17 17:15:48 -0500 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2006-11-17 17:15:48 -0500 |
commit | 97846e3ccbcbcc966e23a91b0d190efd1f889c9b (patch) | |
tree | 9d60f17dc7fb6e17b4e25ea9e4feeec444d1e642 /drivers/char/watchdog/rm9k_wdt.c | |
parent | cd57eeab7c4c108ce6e84545bdf37ae91b930781 (diff) |
[WATCHDOG] MIPS RM9000 on-chip watchdog device - patch 2
Reorganize source code so that it is structured as follows:
- Function prototypes
- Local variables
- Module arguments
- Interrupt handler
- Watchdog functions
- /dev/watchdog operations
- Shutdown notifier
- Kernel interfaces
- Init & exit procedures
- Device driver init & exit
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/char/watchdog/rm9k_wdt.c')
-rw-r--r-- | drivers/char/watchdog/rm9k_wdt.c | 216 |
1 files changed, 101 insertions, 115 deletions
diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index da3fc63bca61..1aad9138f714 100644 --- a/drivers/char/watchdog/rm9k_wdt.c +++ b/drivers/char/watchdog/rm9k_wdt.c | |||
@@ -46,8 +46,7 @@ | |||
46 | 46 | ||
47 | 47 | ||
48 | /* Function prototypes */ | 48 | /* Function prototypes */ |
49 | static int __init wdt_gpi_probe(struct device *); | 49 | static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *); |
50 | static int __exit wdt_gpi_remove(struct device *); | ||
51 | static void wdt_gpi_set_timeout(unsigned int); | 50 | static void wdt_gpi_set_timeout(unsigned int); |
52 | static int wdt_gpi_open(struct inode *, struct file *); | 51 | static int wdt_gpi_open(struct inode *, struct file *); |
53 | static int wdt_gpi_release(struct inode *, struct file *); | 52 | static int wdt_gpi_release(struct inode *, struct file *); |
@@ -55,7 +54,8 @@ static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t | |||
55 | static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); | 54 | static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); |
56 | static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); | 55 | static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); |
57 | static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); | 56 | static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); |
58 | static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *); | 57 | static int __init wdt_gpi_probe(struct device *); |
58 | static int __exit wdt_gpi_remove(struct device *); | ||
59 | 59 | ||
60 | 60 | ||
61 | static const char wdt_gpi_name[] = "wdt_gpi"; | 61 | static const char wdt_gpi_name[] = "wdt_gpi"; |
@@ -91,93 +91,26 @@ module_param(nowayout, bool, 0444); | |||
91 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started"); | 91 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started"); |
92 | 92 | ||
93 | 93 | ||
94 | 94 | /* Interrupt handler */ | |
95 | static struct file_operations fops = { | 95 | static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs) |
96 | .owner = THIS_MODULE, | ||
97 | .open = wdt_gpi_open, | ||
98 | .release = wdt_gpi_release, | ||
99 | .write = wdt_gpi_write, | ||
100 | .unlocked_ioctl = wdt_gpi_ioctl, | ||
101 | }; | ||
102 | |||
103 | static struct miscdevice miscdev = { | ||
104 | .minor = WATCHDOG_MINOR, | ||
105 | .name = wdt_gpi_name, | ||
106 | .fops = &fops, | ||
107 | }; | ||
108 | |||
109 | static struct device_driver wdt_gpi_driver = { | ||
110 | .name = (char *) wdt_gpi_name, | ||
111 | .bus = &platform_bus_type, | ||
112 | .owner = THIS_MODULE, | ||
113 | .probe = wdt_gpi_probe, | ||
114 | .remove = __exit_p(wdt_gpi_remove), | ||
115 | .shutdown = NULL, | ||
116 | .suspend = NULL, | ||
117 | .resume = NULL, | ||
118 | }; | ||
119 | |||
120 | static struct notifier_block wdt_gpi_shutdown = { | ||
121 | .notifier_call = wdt_gpi_notify, | ||
122 | }; | ||
123 | |||
124 | |||
125 | |||
126 | static const struct resource * | ||
127 | wdt_gpi_get_resource(struct platform_device *pdv, const char *name, | ||
128 | unsigned int type) | ||
129 | { | ||
130 | char buf[80]; | ||
131 | if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) | ||
132 | return NULL; | ||
133 | return platform_get_resource_byname(pdv, type, buf); | ||
134 | } | ||
135 | |||
136 | |||
137 | |||
138 | /* No hotplugging on the platform bus - use __init */ | ||
139 | static int __init wdt_gpi_probe(struct device *dev) | ||
140 | { | 96 | { |
141 | int res; | 97 | if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1)) |
142 | struct platform_device * const pdv = to_platform_device(dev); | 98 | return IRQ_NONE; |
143 | const struct resource | 99 | __raw_writel(0x1, wd_regs + 0x0008); |
144 | * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS, | ||
145 | IORESOURCE_MEM), | ||
146 | * const ri = wdt_gpi_get_resource(pdv, WDT_RESOURCE_IRQ, | ||
147 | IORESOURCE_IRQ), | ||
148 | * const rc = wdt_gpi_get_resource(pdv, WDT_RESOURCE_COUNTER, | ||
149 | 0); | ||
150 | |||
151 | if (unlikely(!rr || !ri || !rc)) | ||
152 | return -ENXIO; | ||
153 | |||
154 | wd_regs = ioremap_nocache(rr->start, rr->end + 1 - rr->start); | ||
155 | if (unlikely(!wd_regs)) | ||
156 | return -ENOMEM; | ||
157 | wd_irq = ri->start; | ||
158 | wd_ctr = rc->start; | ||
159 | res = misc_register(&miscdev); | ||
160 | if (res) | ||
161 | iounmap(wd_regs); | ||
162 | else | ||
163 | register_reboot_notifier(&wdt_gpi_shutdown); | ||
164 | return res; | ||
165 | } | ||
166 | |||
167 | 100 | ||
168 | 101 | ||
169 | static int __exit wdt_gpi_remove(struct device *dev) | 102 | printk(KERN_WARNING "%s: watchdog expired - resetting system\n", |
170 | { | 103 | wdt_gpi_name); |
171 | int res; | ||
172 | 104 | ||
173 | unregister_reboot_notifier(&wdt_gpi_shutdown); | 105 | *(volatile char *) flagaddr |= 0x01; |
174 | res = misc_deregister(&miscdev); | 106 | *(volatile char *) resetaddr = powercycle ? 0x01 : 0x2; |
175 | iounmap(wd_regs); | 107 | iob(); |
176 | wd_regs = NULL; | 108 | while (1) |
177 | return res; | 109 | cpu_relax(); |
178 | } | 110 | } |
179 | 111 | ||
180 | 112 | ||
113 | /* Watchdog functions */ | ||
181 | static void wdt_gpi_set_timeout(unsigned int to) | 114 | static void wdt_gpi_set_timeout(unsigned int to) |
182 | { | 115 | { |
183 | u32 reg; | 116 | u32 reg; |
@@ -197,7 +130,7 @@ static void wdt_gpi_set_timeout(unsigned int to) | |||
197 | } | 130 | } |
198 | 131 | ||
199 | 132 | ||
200 | 133 | /* /dev/watchdog operations */ | |
201 | static int wdt_gpi_open(struct inode *i, struct file *f) | 134 | static int wdt_gpi_open(struct inode *i, struct file *f) |
202 | { | 135 | { |
203 | int res; | 136 | int res; |
@@ -231,8 +164,6 @@ static int wdt_gpi_open(struct inode *i, struct file *f) | |||
231 | return 0; | 164 | return 0; |
232 | } | 165 | } |
233 | 166 | ||
234 | |||
235 | |||
236 | static int wdt_gpi_release(struct inode *i, struct file *f) | 167 | static int wdt_gpi_release(struct inode *i, struct file *f) |
237 | { | 168 | { |
238 | if (nowayout) { | 169 | if (nowayout) { |
@@ -267,8 +198,6 @@ static int wdt_gpi_release(struct inode *i, struct file *f) | |||
267 | return 0; | 198 | return 0; |
268 | } | 199 | } |
269 | 200 | ||
270 | |||
271 | |||
272 | static ssize_t | 201 | static ssize_t |
273 | wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o) | 202 | wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o) |
274 | { | 203 | { |
@@ -279,8 +208,6 @@ wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o) | |||
279 | return s ? 1 : 0; | 208 | return s ? 1 : 0; |
280 | } | 209 | } |
281 | 210 | ||
282 | |||
283 | |||
284 | static long | 211 | static long |
285 | wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | 212 | wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) |
286 | { | 213 | { |
@@ -362,27 +289,7 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
362 | } | 289 | } |
363 | 290 | ||
364 | 291 | ||
365 | 292 | /* Shutdown notifier*/ | |
366 | |||
367 | static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs) | ||
368 | { | ||
369 | if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1)) | ||
370 | return IRQ_NONE; | ||
371 | __raw_writel(0x1, wd_regs + 0x0008); | ||
372 | |||
373 | |||
374 | printk(KERN_WARNING "%s: watchdog expired - resetting system\n", | ||
375 | wdt_gpi_name); | ||
376 | |||
377 | *(volatile char *) flagaddr |= 0x01; | ||
378 | *(volatile char *) resetaddr = powercycle ? 0x01 : 0x2; | ||
379 | iob(); | ||
380 | while (1) | ||
381 | cpu_relax(); | ||
382 | } | ||
383 | |||
384 | |||
385 | |||
386 | static int | 293 | static int |
387 | wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) | 294 | wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) |
388 | { | 295 | { |
@@ -401,6 +308,89 @@ wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) | |||
401 | } | 308 | } |
402 | 309 | ||
403 | 310 | ||
311 | /* Kernel interfaces */ | ||
312 | static struct file_operations fops = { | ||
313 | .owner = THIS_MODULE, | ||
314 | .open = wdt_gpi_open, | ||
315 | .release = wdt_gpi_release, | ||
316 | .write = wdt_gpi_write, | ||
317 | .unlocked_ioctl = wdt_gpi_ioctl, | ||
318 | }; | ||
319 | |||
320 | static struct miscdevice miscdev = { | ||
321 | .minor = WATCHDOG_MINOR, | ||
322 | .name = wdt_gpi_name, | ||
323 | .fops = &fops, | ||
324 | }; | ||
325 | |||
326 | static struct notifier_block wdt_gpi_shutdown = { | ||
327 | .notifier_call = wdt_gpi_notify, | ||
328 | }; | ||
329 | |||
330 | |||
331 | /* Init & exit procedures */ | ||
332 | static const struct resource * | ||
333 | wdt_gpi_get_resource(struct platform_device *pdv, const char *name, | ||
334 | unsigned int type) | ||
335 | { | ||
336 | char buf[80]; | ||
337 | if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) | ||
338 | return NULL; | ||
339 | return platform_get_resource_byname(pdv, type, buf); | ||
340 | } | ||
341 | |||
342 | /* No hotplugging on the platform bus - use __init */ | ||
343 | static int __init wdt_gpi_probe(struct device *dev) | ||
344 | { | ||
345 | int res; | ||
346 | struct platform_device * const pdv = to_platform_device(dev); | ||
347 | const struct resource | ||
348 | * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS, | ||
349 | IORESOURCE_MEM), | ||
350 | * const ri = wdt_gpi_get_resource(pdv, WDT_RESOURCE_IRQ, | ||
351 | IORESOURCE_IRQ), | ||
352 | * const rc = wdt_gpi_get_resource(pdv, WDT_RESOURCE_COUNTER, | ||
353 | 0); | ||
354 | |||
355 | if (unlikely(!rr || !ri || !rc)) | ||
356 | return -ENXIO; | ||
357 | |||
358 | wd_regs = ioremap_nocache(rr->start, rr->end + 1 - rr->start); | ||
359 | if (unlikely(!wd_regs)) | ||
360 | return -ENOMEM; | ||
361 | wd_irq = ri->start; | ||
362 | wd_ctr = rc->start; | ||
363 | res = misc_register(&miscdev); | ||
364 | if (res) | ||
365 | iounmap(wd_regs); | ||
366 | else | ||
367 | register_reboot_notifier(&wdt_gpi_shutdown); | ||
368 | return res; | ||
369 | } | ||
370 | |||
371 | static int __exit wdt_gpi_remove(struct device *dev) | ||
372 | { | ||
373 | int res; | ||
374 | |||
375 | unregister_reboot_notifier(&wdt_gpi_shutdown); | ||
376 | res = misc_deregister(&miscdev); | ||
377 | iounmap(wd_regs); | ||
378 | wd_regs = NULL; | ||
379 | return res; | ||
380 | } | ||
381 | |||
382 | |||
383 | /* Device driver init & exit */ | ||
384 | static struct device_driver wdt_gpi_driver = { | ||
385 | .name = (char *) wdt_gpi_name, | ||
386 | .bus = &platform_bus_type, | ||
387 | .owner = THIS_MODULE, | ||
388 | .probe = wdt_gpi_probe, | ||
389 | .remove = __exit_p(wdt_gpi_remove), | ||
390 | .shutdown = NULL, | ||
391 | .suspend = NULL, | ||
392 | .resume = NULL, | ||
393 | }; | ||
404 | 394 | ||
405 | static int __init wdt_gpi_init_module(void) | 395 | static int __init wdt_gpi_init_module(void) |
406 | { | 396 | { |
@@ -410,8 +400,6 @@ static int __init wdt_gpi_init_module(void) | |||
410 | return driver_register(&wdt_gpi_driver); | 400 | return driver_register(&wdt_gpi_driver); |
411 | } | 401 | } |
412 | 402 | ||
413 | |||
414 | |||
415 | static void __exit wdt_gpi_cleanup_module(void) | 403 | static void __exit wdt_gpi_cleanup_module(void) |
416 | { | 404 | { |
417 | driver_unregister(&wdt_gpi_driver); | 405 | driver_unregister(&wdt_gpi_driver); |
@@ -420,8 +408,6 @@ static void __exit wdt_gpi_cleanup_module(void) | |||
420 | module_init(wdt_gpi_init_module); | 408 | module_init(wdt_gpi_init_module); |
421 | module_exit(wdt_gpi_cleanup_module); | 409 | module_exit(wdt_gpi_cleanup_module); |
422 | 410 | ||
423 | |||
424 | |||
425 | MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>"); | 411 | MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>"); |
426 | MODULE_DESCRIPTION("Basler eXcite watchdog driver for gpi devices"); | 412 | MODULE_DESCRIPTION("Basler eXcite watchdog driver for gpi devices"); |
427 | MODULE_VERSION("0.1"); | 413 | MODULE_VERSION("0.1"); |