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 | |
| 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>
| -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"); |
