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] removed unused #include <version.h>
[WATCHDOG] at91rm9200_wdt.c: fix misleading indentation
[WATCHDOG] mpc8xxx_wdt: fix modular build
[WATCHDOG] hpwdt.c kdebug support
[WATCHDOG] Add support for the IDT RC32434 watchdog
[WATCHDOG] Add support for the built-int RDC R-321x SoC watchdog
[WATHDOG] delete unused driver mpc8xx_wdt.c
[WATCHDOG] Fix s3c2410_wdt driver coding style issues
[WATCHDOG] Clean out header of s3c2410_wdt driver.
[WATCHDOG] Fix NULL usage in s3c2410_wdt driver.

+714 -235
+20 -4
drivers/watchdog/Kconfig
··· 465 465 466 466 Most people will say N. 467 467 468 + config RDC321X_WDT 469 + tristate "RDC R-321x SoC watchdog" 470 + depends on X86_RDC321X 471 + help 472 + This is the driver for the built in hardware watchdog 473 + in the RDC R-321x SoC. 474 + 475 + To compile this driver as a module, choose M here: the 476 + module will be called rdc321x_wdt. 477 + 468 478 config 60XX_WDT 469 479 tristate "SBC-60XX Watchdog Timer" 470 480 depends on X86 ··· 643 633 644 634 # MIPS Architecture 645 635 636 + config RC32434_WDT 637 + tristate "IDT RC32434 SoC Watchdog Timer" 638 + depends on MIKROTIK_RB532 639 + help 640 + Hardware driver for the IDT RC32434 SoC built-in 641 + watchdog timer. 642 + 643 + To compile this driver as a module, choose M here: the 644 + module will be called rc32434_wdt. 645 + 646 646 config INDYDOG 647 647 tristate "Indy/I2 Hardware Watchdog" 648 648 depends on SGI_HAS_INDYDOG ··· 711 691 config MPC5200_WDT 712 692 tristate "MPC5200 Watchdog Timer" 713 693 depends on PPC_MPC52xx 714 - 715 - config 8xx_WDT 716 - tristate "MPC8xx Watchdog Timer" 717 - depends on 8xx 718 694 719 695 config 8xxx_WDT 720 696 tristate "MPC8xxx Platform Watchdog Timer"
+2 -1
drivers/watchdog/Makefile
··· 75 75 obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o 76 76 obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o 77 77 obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o 78 + obj-$(CONFIG_RDC321X_WDT) += rdc321x_wdt.o 78 79 obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o 79 80 obj-$(CONFIG_SBC8360_WDT) += sbc8360.o 80 81 obj-$(CONFIG_SBC7240_WDT) += sbc7240_wdt.o ··· 95 94 # M68KNOMMU Architecture 96 95 97 96 # MIPS Architecture 97 + obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o 98 98 obj-$(CONFIG_INDYDOG) += indydog.o 99 99 obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o 100 100 obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o ··· 106 104 # PARISC Architecture 107 105 108 106 # POWERPC Architecture 109 - obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o 110 107 obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o 111 108 obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o 112 109 obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
+1 -1
drivers/watchdog/at91rm9200_wdt.c
··· 241 241 { 242 242 if (at91wdt_busy) 243 243 at91_wdt_start(); 244 - return 0; 244 + return 0; 245 245 } 246 246 247 247 #else
+50 -43
drivers/watchdog/hpwdt.c
··· 116 116 static int nowayout = WATCHDOG_NOWAYOUT; 117 117 static char expect_release; 118 118 static unsigned long hpwdt_is_open; 119 + static unsigned int allow_kdump; 119 120 120 121 static void __iomem *pci_mem_addr; /* the PCI-memory address */ 121 122 static unsigned long __iomem *hpwdt_timer_reg; ··· 222 221 223 222 if (cmn_regs.u1.ral != 0) { 224 223 printk(KERN_WARNING 225 - "hpwdt: Call succeeded but with an error: 0x%x\n", 226 - cmn_regs.u1.ral); 224 + "hpwdt: Call succeeded but with an error: 0x%x\n", 225 + cmn_regs.u1.ral); 227 226 } else { 228 227 physical_bios_base = cmn_regs.u2.rebx; 229 228 physical_bios_offset = cmn_regs.u4.redx; 230 229 cru_length = cmn_regs.u3.recx; 231 230 cru_physical_address = 232 - physical_bios_base + physical_bios_offset; 231 + physical_bios_base + physical_bios_offset; 233 232 234 233 /* If the values look OK, then map it in. */ 235 234 if ((physical_bios_base + physical_bios_offset)) { 236 235 cru_rom_addr = 237 - ioremap(cru_physical_address, cru_length); 236 + ioremap(cru_physical_address, cru_length); 238 237 if (cru_rom_addr) 239 238 retval = 0; 240 239 } ··· 357 356 "call *%r12 \n\t" 358 357 "pushfq \n\t" 359 358 "popq %r12 \n\t" 360 - "popfq \n\t" 361 359 "movl %eax, (%r9) \n\t" 362 360 "movl %ebx, 4(%r9) \n\t" 363 361 "movl %ecx, 8(%r9) \n\t" ··· 390 390 smbios_cru64_ptr = (struct smbios_cru64_info *) dm; 391 391 if (smbios_cru64_ptr->signature == CRU_BIOS_SIGNATURE_VALUE) { 392 392 cru_physical_address = 393 - smbios_cru64_ptr->physical_address + 394 - smbios_cru64_ptr->double_offset; 393 + smbios_cru64_ptr->physical_address + 394 + smbios_cru64_ptr->double_offset; 395 395 cru_rom_addr = ioremap(cru_physical_address, 396 - smbios_cru64_ptr->double_length); 396 + smbios_cru64_ptr->double_length); 397 397 } 398 398 } 399 399 } ··· 405 405 dmi_walk(dmi_find_cru); 406 406 407 407 /* if cru_rom_addr has been set then we found a CRU service */ 408 - return ((cru_rom_addr != NULL) ? 0: -ENODEV); 408 + return ((cru_rom_addr != NULL) ? 0 : -ENODEV); 409 409 } 410 410 411 411 /* ------------------------------------------------------------------------- */ 412 412 413 413 #endif 414 - 415 - /* 416 - * NMI Handler 417 - */ 418 - static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, 419 - void *data) 420 - { 421 - unsigned long rom_pl; 422 - static int die_nmi_called; 423 - 424 - if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) 425 - return NOTIFY_OK; 426 - 427 - spin_lock_irqsave(&rom_lock, rom_pl); 428 - if (!die_nmi_called) 429 - asminline_call(&cmn_regs, cru_rom_addr); 430 - die_nmi_called = 1; 431 - spin_unlock_irqrestore(&rom_lock, rom_pl); 432 - if (cmn_regs.u1.ral == 0) { 433 - printk(KERN_WARNING "hpwdt: An NMI occurred, " 434 - "but unable to determine source.\n"); 435 - } else { 436 - panic("An NMI occurred, please see the Integrated " 437 - "Management Log for details.\n"); 438 - } 439 - 440 - return NOTIFY_STOP; 441 - } 442 414 443 415 /* 444 416 * Watchdog operations ··· 453 481 reload = (soft_margin * 1000) / 128; 454 482 455 483 return 0; 484 + } 485 + 486 + /* 487 + * NMI Handler 488 + */ 489 + static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, 490 + void *data) 491 + { 492 + unsigned long rom_pl; 493 + static int die_nmi_called; 494 + 495 + if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) 496 + return NOTIFY_OK; 497 + 498 + spin_lock_irqsave(&rom_lock, rom_pl); 499 + if (!die_nmi_called) 500 + asminline_call(&cmn_regs, cru_rom_addr); 501 + die_nmi_called = 1; 502 + spin_unlock_irqrestore(&rom_lock, rom_pl); 503 + if (cmn_regs.u1.ral == 0) { 504 + printk(KERN_WARNING "hpwdt: An NMI occurred, " 505 + "but unable to determine source.\n"); 506 + } else { 507 + if (allow_kdump) 508 + hpwdt_stop(); 509 + panic("An NMI occurred, please see the Integrated " 510 + "Management Log for details.\n"); 511 + } 512 + 513 + return NOTIFY_STOP; 456 514 } 457 515 458 516 /* ··· 627 625 */ 628 626 629 627 static int __devinit hpwdt_init_one(struct pci_dev *dev, 630 - const struct pci_device_id *ent) 628 + const struct pci_device_id *ent) 631 629 { 632 630 int retval; 633 631 634 632 /* 635 633 * First let's find out if we are on an iLO2 server. We will 636 634 * not run on a legacy ASM box. 635 + * So we only support the G5 ProLiant servers and higher. 637 636 */ 638 637 if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) { 639 638 dev_warn(&dev->dev, 640 - "This server does not have an iLO2 ASIC.\n"); 639 + "This server does not have an iLO2 ASIC.\n"); 641 640 return -ENODEV; 642 641 } 643 642 ··· 672 669 retval = detect_cru_service(); 673 670 if (retval < 0) { 674 671 dev_warn(&dev->dev, 675 - "Unable to detect the %d Bit CRU Service.\n", 672 + "Unable to detect the %d Bit CRU Service.\n", 676 673 HPWDT_ARCH); 677 674 goto error_get_cru; 678 675 } ··· 687 684 retval = register_die_notifier(&die_notifier); 688 685 if (retval != 0) { 689 686 dev_warn(&dev->dev, 690 - "Unable to register a die notifier (err=%d).\n", 687 + "Unable to register a die notifier (err=%d).\n", 691 688 retval); 692 689 goto error_die_notifier; 693 690 } ··· 702 699 703 700 printk(KERN_INFO 704 701 "hp Watchdog Timer Driver: 1.00" 705 - ", timer margin: %d seconds( nowayout=%d).\n", 706 - soft_margin, nowayout); 702 + ", timer margin: %d seconds (nowayout=%d)" 703 + ", allow kernel dump: %s (default = 0/OFF).\n", 704 + soft_margin, nowayout, (allow_kdump == 0) ? "OFF" : "ON"); 707 705 708 706 return 0; 709 707 ··· 758 754 759 755 module_param(soft_margin, int, 0); 760 756 MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds"); 757 + 758 + module_param(allow_kdump, int, 0); 759 + MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs"); 761 760 762 761 module_param(nowayout, int, 0); 763 762 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
-170
drivers/watchdog/mpc8xx_wdt.c
··· 1 - /* 2 - * mpc8xx_wdt.c - MPC8xx watchdog userspace interface 3 - * 4 - * Author: Florian Schirmer <jolt@tuxbox.org> 5 - * 6 - * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under 7 - * the terms of the GNU General Public License version 2. This program 8 - * is licensed "as is" without any warranty of any kind, whether express 9 - * or implied. 10 - */ 11 - 12 - #include <linux/fs.h> 13 - #include <linux/init.h> 14 - #include <linux/kernel.h> 15 - #include <linux/miscdevice.h> 16 - #include <linux/module.h> 17 - #include <linux/watchdog.h> 18 - #include <asm/8xx_immap.h> 19 - #include <linux/uaccess.h> 20 - #include <linux/io.h> 21 - #include <syslib/m8xx_wdt.h> 22 - 23 - static unsigned long wdt_opened; 24 - static int wdt_status; 25 - static spinlock_t wdt_lock; 26 - 27 - static void mpc8xx_wdt_handler_disable(void) 28 - { 29 - volatile uint __iomem *piscr; 30 - piscr = (uint *)&((immap_t *)IMAP_ADDR)->im_sit.sit_piscr; 31 - 32 - if (!m8xx_has_internal_rtc) 33 - m8xx_wdt_stop_timer(); 34 - else 35 - out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE)); 36 - printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); 37 - } 38 - 39 - static void mpc8xx_wdt_handler_enable(void) 40 - { 41 - volatile uint __iomem *piscr; 42 - piscr = (uint *)&((immap_t *)IMAP_ADDR)->im_sit.sit_piscr; 43 - 44 - if (!m8xx_has_internal_rtc) 45 - m8xx_wdt_install_timer(); 46 - else 47 - out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE); 48 - printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n"); 49 - } 50 - 51 - static int mpc8xx_wdt_open(struct inode *inode, struct file *file) 52 - { 53 - if (test_and_set_bit(0, &wdt_opened)) 54 - return -EBUSY; 55 - m8xx_wdt_reset(); 56 - mpc8xx_wdt_handler_disable(); 57 - return nonseekable_open(inode, file); 58 - } 59 - 60 - static int mpc8xx_wdt_release(struct inode *inode, struct file *file) 61 - { 62 - m8xx_wdt_reset(); 63 - #if !defined(CONFIG_WATCHDOG_NOWAYOUT) 64 - mpc8xx_wdt_handler_enable(); 65 - #endif 66 - clear_bit(0, &wdt_opened); 67 - return 0; 68 - } 69 - 70 - static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, 71 - size_t len, loff_t *ppos) 72 - { 73 - if (len) { 74 - spin_lock(&wdt_lock); 75 - m8xx_wdt_reset(); 76 - spin_unlock(&wdt_lock); 77 - } 78 - return len; 79 - } 80 - 81 - static long mpc8xx_wdt_ioctl(struct file *file, 82 - unsigned int cmd, unsigned long arg) 83 - { 84 - int timeout; 85 - static struct watchdog_info info = { 86 - .options = WDIOF_KEEPALIVEPING, 87 - .firmware_version = 0, 88 - .identity = "MPC8xx watchdog", 89 - }; 90 - 91 - switch (cmd) { 92 - case WDIOC_GETSUPPORT: 93 - if (copy_to_user((void *)arg, &info, sizeof(info))) 94 - return -EFAULT; 95 - break; 96 - 97 - case WDIOC_GETSTATUS: 98 - case WDIOC_GETBOOTSTATUS: 99 - if (put_user(wdt_status, (int *)arg)) 100 - return -EFAULT; 101 - wdt_status &= ~WDIOF_KEEPALIVEPING; 102 - break; 103 - 104 - case WDIOC_GETTEMP: 105 - return -EOPNOTSUPP; 106 - 107 - case WDIOC_SETOPTIONS: 108 - return -EOPNOTSUPP; 109 - 110 - case WDIOC_KEEPALIVE: 111 - spin_lock(&wdt_lock); 112 - m8xx_wdt_reset(); 113 - wdt_status |= WDIOF_KEEPALIVEPING; 114 - spin_unlock(&wdt_lock); 115 - break; 116 - 117 - case WDIOC_SETTIMEOUT: 118 - return -EOPNOTSUPP; 119 - 120 - case WDIOC_GETTIMEOUT: 121 - spin_lock(&wdt_lock); 122 - timeout = m8xx_wdt_get_timeout(); 123 - spin_unlock(&wdt_lock); 124 - if (put_user(timeout, (int *)arg)) 125 - return -EFAULT; 126 - break; 127 - 128 - default: 129 - return -ENOTTY; 130 - } 131 - 132 - return 0; 133 - } 134 - 135 - static const struct file_operations mpc8xx_wdt_fops = { 136 - .owner = THIS_MODULE, 137 - .llseek = no_llseek, 138 - .write = mpc8xx_wdt_write, 139 - .unlocked_ioctl = mpc8xx_wdt_ioctl, 140 - .open = mpc8xx_wdt_open, 141 - .release = mpc8xx_wdt_release, 142 - }; 143 - 144 - static struct miscdevice mpc8xx_wdt_miscdev = { 145 - .minor = WATCHDOG_MINOR, 146 - .name = "watchdog", 147 - .fops = &mpc8xx_wdt_fops, 148 - }; 149 - 150 - static int __init mpc8xx_wdt_init(void) 151 - { 152 - spin_lock_init(&wdt_lock); 153 - return misc_register(&mpc8xx_wdt_miscdev); 154 - } 155 - 156 - static void __exit mpc8xx_wdt_exit(void) 157 - { 158 - misc_deregister(&mpc8xx_wdt_miscdev); 159 - 160 - m8xx_wdt_reset(); 161 - mpc8xx_wdt_handler_enable(); 162 - } 163 - 164 - module_init(mpc8xx_wdt_init); 165 - module_exit(mpc8xx_wdt_exit); 166 - 167 - MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>"); 168 - MODULE_DESCRIPTION("MPC8xx watchdog driver"); 169 - MODULE_LICENSE("GPL"); 170 - MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+10 -1
drivers/watchdog/mpc8xxx_wdt.c
··· 48 48 }; 49 49 50 50 static struct mpc8xxx_wdt __iomem *wd_base; 51 + static int mpc8xxx_wdt_init_late(void); 51 52 52 53 static u16 timeout = 0xffff; 53 54 module_param(timeout, ushort, 0); ··· 214 213 else 215 214 timeout_sec = timeout / freq; 216 215 216 + #ifdef MODULE 217 + ret = mpc8xxx_wdt_init_late(); 218 + if (ret) 219 + goto err_unmap; 220 + #endif 221 + 217 222 pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d " 218 223 "(%d seconds)\n", reset ? "reset" : "interrupt", timeout, 219 224 timeout_sec); ··· 287 280 * very early to start pinging the watchdog (misc devices are not yet 288 281 * available), and later module_init() just registers the misc device. 289 282 */ 290 - static int __init mpc8xxx_wdt_init_late(void) 283 + static int mpc8xxx_wdt_init_late(void) 291 284 { 292 285 int ret; 293 286 ··· 302 295 } 303 296 return 0; 304 297 } 298 + #ifndef MODULE 305 299 module_init(mpc8xxx_wdt_init_late); 300 + #endif 306 301 307 302 static int __init mpc8xxx_wdt_init(void) 308 303 {
-1
drivers/watchdog/pc87413_wdt.c
··· 30 30 #include <linux/init.h> 31 31 #include <linux/spinlock.h> 32 32 #include <linux/moduleparam.h> 33 - #include <linux/version.h> 34 33 #include <linux/io.h> 35 34 #include <linux/uaccess.h> 36 35
+344
drivers/watchdog/rc32434_wdt.c
··· 1 + /* 2 + * IDT Interprise 79RC32434 watchdog driver 3 + * 4 + * Copyright (C) 2006, Ondrej Zajicek <santiago@crfreenet.org> 5 + * Copyright (C) 2008, Florian Fainelli <florian@openwrt.org> 6 + * 7 + * based on 8 + * SoftDog 0.05: A Software Watchdog Device 9 + * 10 + * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved. 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 15 + * 2 of the License, or (at your option) any later version. 16 + * 17 + */ 18 + 19 + #include <linux/module.h> 20 + #include <linux/types.h> 21 + #include <linux/kernel.h> 22 + #include <linux/fs.h> 23 + #include <linux/mm.h> 24 + #include <linux/miscdevice.h> 25 + #include <linux/watchdog.h> 26 + #include <linux/reboot.h> 27 + #include <linux/smp_lock.h> 28 + #include <linux/init.h> 29 + #include <linux/platform_device.h> 30 + #include <linux/uaccess.h> 31 + 32 + #include <asm/bootinfo.h> 33 + #include <asm/time.h> 34 + #include <asm/mach-rc32434/integ.h> 35 + 36 + #define MAX_TIMEOUT 20 37 + #define RC32434_WDT_INTERVAL (15 * HZ) 38 + 39 + #define VERSION "0.2" 40 + 41 + static struct { 42 + struct completion stop; 43 + int running; 44 + struct timer_list timer; 45 + int queue; 46 + int default_ticks; 47 + unsigned long inuse; 48 + } rc32434_wdt_device; 49 + 50 + static struct integ __iomem *wdt_reg; 51 + static int ticks = 100 * HZ; 52 + 53 + static int expect_close; 54 + static int timeout; 55 + 56 + static int nowayout = WATCHDOG_NOWAYOUT; 57 + module_param(nowayout, int, 0); 58 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 59 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 60 + 61 + 62 + static void rc32434_wdt_start(void) 63 + { 64 + u32 val; 65 + 66 + if (!rc32434_wdt_device.inuse) { 67 + writel(0, &wdt_reg->wtcount); 68 + 69 + val = RC32434_ERR_WRE; 70 + writel(readl(&wdt_reg->errcs) | val, &wdt_reg->errcs); 71 + 72 + val = RC32434_WTC_EN; 73 + writel(readl(&wdt_reg->wtc) | val, &wdt_reg->wtc); 74 + } 75 + rc32434_wdt_device.running++; 76 + } 77 + 78 + static void rc32434_wdt_stop(void) 79 + { 80 + u32 val; 81 + 82 + if (rc32434_wdt_device.running) { 83 + 84 + val = ~RC32434_WTC_EN; 85 + writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc); 86 + 87 + val = ~RC32434_ERR_WRE; 88 + writel(readl(&wdt_reg->errcs) & val, &wdt_reg->errcs); 89 + 90 + rc32434_wdt_device.running = 0; 91 + } 92 + } 93 + 94 + static void rc32434_wdt_set(int new_timeout) 95 + { 96 + u32 cmp = new_timeout * HZ; 97 + u32 state, val; 98 + 99 + timeout = new_timeout; 100 + /* 101 + * store and disable WTC 102 + */ 103 + state = (u32)(readl(&wdt_reg->wtc) & RC32434_WTC_EN); 104 + val = ~RC32434_WTC_EN; 105 + writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc); 106 + 107 + writel(0, &wdt_reg->wtcount); 108 + writel(cmp, &wdt_reg->wtcompare); 109 + 110 + /* 111 + * restore WTC 112 + */ 113 + 114 + writel(readl(&wdt_reg->wtc) | state, &wdt_reg); 115 + } 116 + 117 + static void rc32434_wdt_reset(void) 118 + { 119 + ticks = rc32434_wdt_device.default_ticks; 120 + } 121 + 122 + static void rc32434_wdt_update(unsigned long unused) 123 + { 124 + if (rc32434_wdt_device.running) 125 + ticks--; 126 + 127 + writel(0, &wdt_reg->wtcount); 128 + 129 + if (rc32434_wdt_device.queue && ticks) 130 + mod_timer(&rc32434_wdt_device.timer, 131 + jiffies + RC32434_WDT_INTERVAL); 132 + else 133 + complete(&rc32434_wdt_device.stop); 134 + } 135 + 136 + static int rc32434_wdt_open(struct inode *inode, struct file *file) 137 + { 138 + if (test_and_set_bit(0, &rc32434_wdt_device.inuse)) 139 + return -EBUSY; 140 + 141 + if (nowayout) 142 + __module_get(THIS_MODULE); 143 + 144 + return nonseekable_open(inode, file); 145 + } 146 + 147 + static int rc32434_wdt_release(struct inode *inode, struct file *file) 148 + { 149 + if (expect_close && nowayout == 0) { 150 + rc32434_wdt_stop(); 151 + printk(KERN_INFO KBUILD_MODNAME ": disabling watchdog timer\n"); 152 + module_put(THIS_MODULE); 153 + } else 154 + printk(KERN_CRIT KBUILD_MODNAME 155 + ": device closed unexpectedly. WDT will not stop !\n"); 156 + 157 + clear_bit(0, &rc32434_wdt_device.inuse); 158 + return 0; 159 + } 160 + 161 + static ssize_t rc32434_wdt_write(struct file *file, const char *data, 162 + size_t len, loff_t *ppos) 163 + { 164 + if (len) { 165 + if (!nowayout) { 166 + size_t i; 167 + 168 + /* In case it was set long ago */ 169 + expect_close = 0; 170 + 171 + for (i = 0; i != len; i++) { 172 + char c; 173 + if (get_user(c, data + i)) 174 + return -EFAULT; 175 + if (c == 'V') 176 + expect_close = 1; 177 + } 178 + } 179 + rc32434_wdt_update(0); 180 + return len; 181 + } 182 + return 0; 183 + } 184 + 185 + static int rc32434_wdt_ioctl(struct inode *inode, struct file *file, 186 + unsigned int cmd, unsigned long arg) 187 + { 188 + void __user *argp = (void __user *)arg; 189 + int new_timeout; 190 + unsigned int value; 191 + static struct watchdog_info ident = { 192 + .options = WDIOF_SETTIMEOUT | 193 + WDIOF_KEEPALIVEPING | 194 + WDIOF_MAGICCLOSE, 195 + .identity = "RC32434_WDT Watchdog", 196 + }; 197 + switch (cmd) { 198 + case WDIOC_KEEPALIVE: 199 + rc32434_wdt_reset(); 200 + break; 201 + case WDIOC_GETSTATUS: 202 + case WDIOC_GETBOOTSTATUS: 203 + value = readl(&wdt_reg->wtcount); 204 + if (copy_to_user(argp, &value, sizeof(int))) 205 + return -EFAULT; 206 + break; 207 + case WDIOC_GETSUPPORT: 208 + if (copy_to_user(argp, &ident, sizeof(ident))) 209 + return -EFAULT; 210 + break; 211 + case WDIOC_SETOPTIONS: 212 + if (copy_from_user(&value, argp, sizeof(int))) 213 + return -EFAULT; 214 + switch (value) { 215 + case WDIOS_ENABLECARD: 216 + rc32434_wdt_start(); 217 + break; 218 + case WDIOS_DISABLECARD: 219 + rc32434_wdt_stop(); 220 + default: 221 + return -EINVAL; 222 + } 223 + break; 224 + case WDIOC_SETTIMEOUT: 225 + if (copy_from_user(&new_timeout, argp, sizeof(int))) 226 + return -EFAULT; 227 + if (new_timeout < 1) 228 + return -EINVAL; 229 + if (new_timeout > MAX_TIMEOUT) 230 + return -EINVAL; 231 + rc32434_wdt_set(new_timeout); 232 + case WDIOC_GETTIMEOUT: 233 + return copy_to_user(argp, &timeout, sizeof(int)); 234 + default: 235 + return -ENOTTY; 236 + } 237 + 238 + return 0; 239 + } 240 + 241 + static struct file_operations rc32434_wdt_fops = { 242 + .owner = THIS_MODULE, 243 + .llseek = no_llseek, 244 + .write = rc32434_wdt_write, 245 + .ioctl = rc32434_wdt_ioctl, 246 + .open = rc32434_wdt_open, 247 + .release = rc32434_wdt_release, 248 + }; 249 + 250 + static struct miscdevice rc32434_wdt_miscdev = { 251 + .minor = WATCHDOG_MINOR, 252 + .name = "watchdog", 253 + .fops = &rc32434_wdt_fops, 254 + }; 255 + 256 + static char banner[] = KERN_INFO KBUILD_MODNAME 257 + ": Watchdog Timer version " VERSION ", timer margin: %d sec\n"; 258 + 259 + static int rc32434_wdt_probe(struct platform_device *pdev) 260 + { 261 + int ret; 262 + struct resource *r; 263 + 264 + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb500_wdt_res"); 265 + if (!r) { 266 + printk(KERN_ERR KBUILD_MODNAME 267 + "failed to retrieve resources\n"); 268 + return -ENODEV; 269 + } 270 + 271 + wdt_reg = ioremap_nocache(r->start, r->end - r->start); 272 + if (!wdt_reg) { 273 + printk(KERN_ERR KBUILD_MODNAME 274 + "failed to remap I/O resources\n"); 275 + return -ENXIO; 276 + } 277 + 278 + ret = misc_register(&rc32434_wdt_miscdev); 279 + 280 + if (ret < 0) { 281 + printk(KERN_ERR KBUILD_MODNAME 282 + "failed to register watchdog device\n"); 283 + goto unmap; 284 + } 285 + 286 + init_completion(&rc32434_wdt_device.stop); 287 + rc32434_wdt_device.queue = 0; 288 + 289 + clear_bit(0, &rc32434_wdt_device.inuse); 290 + 291 + setup_timer(&rc32434_wdt_device.timer, rc32434_wdt_update, 0L); 292 + 293 + rc32434_wdt_device.default_ticks = ticks; 294 + 295 + rc32434_wdt_start(); 296 + 297 + printk(banner, timeout); 298 + 299 + return 0; 300 + 301 + unmap: 302 + iounmap(wdt_reg); 303 + return ret; 304 + } 305 + 306 + static int rc32434_wdt_remove(struct platform_device *pdev) 307 + { 308 + if (rc32434_wdt_device.queue) { 309 + rc32434_wdt_device.queue = 0; 310 + wait_for_completion(&rc32434_wdt_device.stop); 311 + } 312 + misc_deregister(&rc32434_wdt_miscdev); 313 + 314 + iounmap(wdt_reg); 315 + 316 + return 0; 317 + } 318 + 319 + static struct platform_driver rc32434_wdt = { 320 + .probe = rc32434_wdt_probe, 321 + .remove = rc32434_wdt_remove, 322 + .driver = { 323 + .name = "rc32434_wdt", 324 + } 325 + }; 326 + 327 + static int __init rc32434_wdt_init(void) 328 + { 329 + return platform_driver_register(&rc32434_wdt); 330 + } 331 + 332 + static void __exit rc32434_wdt_exit(void) 333 + { 334 + platform_driver_unregister(&rc32434_wdt); 335 + } 336 + 337 + module_init(rc32434_wdt_init); 338 + module_exit(rc32434_wdt_exit); 339 + 340 + MODULE_AUTHOR("Ondrej Zajicek <santiago@crfreenet.org>," 341 + "Florian Fainelli <florian@openwrt.org>"); 342 + MODULE_DESCRIPTION("Driver for the IDT RC32434 SoC watchdog"); 343 + MODULE_LICENSE("GPL"); 344 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+285
drivers/watchdog/rdc321x_wdt.c
··· 1 + /* 2 + * RDC321x watchdog driver 3 + * 4 + * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org> 5 + * 6 + * This driver is highly inspired from the cpu5_wdt driver 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, write to the Free Software 20 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 + * 22 + */ 23 + 24 + #include <linux/module.h> 25 + #include <linux/moduleparam.h> 26 + #include <linux/types.h> 27 + #include <linux/errno.h> 28 + #include <linux/miscdevice.h> 29 + #include <linux/fs.h> 30 + #include <linux/init.h> 31 + #include <linux/ioport.h> 32 + #include <linux/timer.h> 33 + #include <linux/completion.h> 34 + #include <linux/jiffies.h> 35 + #include <linux/platform_device.h> 36 + #include <linux/watchdog.h> 37 + #include <linux/io.h> 38 + #include <linux/uaccess.h> 39 + 40 + #include <asm/mach-rdc321x/rdc321x_defs.h> 41 + 42 + #define RDC_WDT_MASK 0x80000000 /* Mask */ 43 + #define RDC_WDT_EN 0x00800000 /* Enable bit */ 44 + #define RDC_WDT_WTI 0x00200000 /* Generate CPU reset/NMI/WDT on timeout */ 45 + #define RDC_WDT_RST 0x00100000 /* Reset bit */ 46 + #define RDC_WDT_WIF 0x00040000 /* WDT IRQ Flag */ 47 + #define RDC_WDT_IRT 0x00000100 /* IRQ Routing table */ 48 + #define RDC_WDT_CNT 0x00000001 /* WDT count */ 49 + 50 + #define RDC_CLS_TMR 0x80003844 /* Clear timer */ 51 + 52 + #define RDC_WDT_INTERVAL (HZ/10+1) 53 + 54 + static int ticks = 1000; 55 + 56 + /* some device data */ 57 + 58 + static struct { 59 + struct completion stop; 60 + int running; 61 + struct timer_list timer; 62 + int queue; 63 + int default_ticks; 64 + unsigned long inuse; 65 + spinlock_t lock; 66 + } rdc321x_wdt_device; 67 + 68 + /* generic helper functions */ 69 + 70 + static void rdc321x_wdt_trigger(unsigned long unused) 71 + { 72 + unsigned long flags; 73 + 74 + if (rdc321x_wdt_device.running) 75 + ticks--; 76 + 77 + /* keep watchdog alive */ 78 + spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); 79 + outl(RDC_WDT_EN | inl(RDC3210_CFGREG_DATA), 80 + RDC3210_CFGREG_DATA); 81 + spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); 82 + 83 + /* requeue?? */ 84 + if (rdc321x_wdt_device.queue && ticks) 85 + mod_timer(&rdc321x_wdt_device.timer, 86 + jiffies + RDC_WDT_INTERVAL); 87 + else { 88 + /* ticks doesn't matter anyway */ 89 + complete(&rdc321x_wdt_device.stop); 90 + } 91 + 92 + } 93 + 94 + static void rdc321x_wdt_reset(void) 95 + { 96 + ticks = rdc321x_wdt_device.default_ticks; 97 + } 98 + 99 + static void rdc321x_wdt_start(void) 100 + { 101 + unsigned long flags; 102 + 103 + if (!rdc321x_wdt_device.queue) { 104 + rdc321x_wdt_device.queue = 1; 105 + 106 + /* Clear the timer */ 107 + spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); 108 + outl(RDC_CLS_TMR, RDC3210_CFGREG_ADDR); 109 + 110 + /* Enable watchdog and set the timeout to 81.92 us */ 111 + outl(RDC_WDT_EN | RDC_WDT_CNT, RDC3210_CFGREG_DATA); 112 + spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); 113 + 114 + mod_timer(&rdc321x_wdt_device.timer, 115 + jiffies + RDC_WDT_INTERVAL); 116 + } 117 + 118 + /* if process dies, counter is not decremented */ 119 + rdc321x_wdt_device.running++; 120 + } 121 + 122 + static int rdc321x_wdt_stop(void) 123 + { 124 + if (rdc321x_wdt_device.running) 125 + rdc321x_wdt_device.running = 0; 126 + 127 + ticks = rdc321x_wdt_device.default_ticks; 128 + 129 + return -EIO; 130 + } 131 + 132 + /* filesystem operations */ 133 + static int rdc321x_wdt_open(struct inode *inode, struct file *file) 134 + { 135 + if (test_and_set_bit(0, &rdc321x_wdt_device.inuse)) 136 + return -EBUSY; 137 + 138 + return nonseekable_open(inode, file); 139 + } 140 + 141 + static int rdc321x_wdt_release(struct inode *inode, struct file *file) 142 + { 143 + clear_bit(0, &rdc321x_wdt_device.inuse); 144 + return 0; 145 + } 146 + 147 + static int rdc321x_wdt_ioctl(struct inode *inode, struct file *file, 148 + unsigned int cmd, unsigned long arg) 149 + { 150 + void __user *argp = (void __user *)arg; 151 + unsigned int value; 152 + static struct watchdog_info ident = { 153 + .options = WDIOF_CARDRESET, 154 + .identity = "RDC321x WDT", 155 + }; 156 + unsigned long flags; 157 + 158 + switch (cmd) { 159 + case WDIOC_KEEPALIVE: 160 + rdc321x_wdt_reset(); 161 + break; 162 + case WDIOC_GETSTATUS: 163 + /* Read the value from the DATA register */ 164 + spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); 165 + value = inl(RDC3210_CFGREG_DATA); 166 + spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); 167 + if (copy_to_user(argp, &value, sizeof(int))) 168 + return -EFAULT; 169 + break; 170 + case WDIOC_GETSUPPORT: 171 + if (copy_to_user(argp, &ident, sizeof(ident))) 172 + return -EFAULT; 173 + break; 174 + case WDIOC_SETOPTIONS: 175 + if (copy_from_user(&value, argp, sizeof(int))) 176 + return -EFAULT; 177 + switch (value) { 178 + case WDIOS_ENABLECARD: 179 + rdc321x_wdt_start(); 180 + break; 181 + case WDIOS_DISABLECARD: 182 + return rdc321x_wdt_stop(); 183 + default: 184 + return -EINVAL; 185 + } 186 + break; 187 + default: 188 + return -ENOTTY; 189 + } 190 + return 0; 191 + } 192 + 193 + static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf, 194 + size_t count, loff_t *ppos) 195 + { 196 + if (!count) 197 + return -EIO; 198 + 199 + rdc321x_wdt_reset(); 200 + 201 + return count; 202 + } 203 + 204 + static const struct file_operations rdc321x_wdt_fops = { 205 + .owner = THIS_MODULE, 206 + .llseek = no_llseek, 207 + .ioctl = rdc321x_wdt_ioctl, 208 + .open = rdc321x_wdt_open, 209 + .write = rdc321x_wdt_write, 210 + .release = rdc321x_wdt_release, 211 + }; 212 + 213 + static struct miscdevice rdc321x_wdt_misc = { 214 + .minor = WATCHDOG_MINOR, 215 + .name = "watchdog", 216 + .fops = &rdc321x_wdt_fops, 217 + }; 218 + 219 + static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) 220 + { 221 + int err; 222 + 223 + err = misc_register(&rdc321x_wdt_misc); 224 + if (err < 0) { 225 + printk(KERN_ERR PFX "watchdog misc_register failed\n"); 226 + return err; 227 + } 228 + 229 + spin_lock_init(&rdc321x_wdt_device.lock); 230 + 231 + /* Reset the watchdog */ 232 + outl(RDC_WDT_RST, RDC3210_CFGREG_DATA); 233 + 234 + init_completion(&rdc321x_wdt_device.stop); 235 + rdc321x_wdt_device.queue = 0; 236 + 237 + clear_bit(0, &rdc321x_wdt_device.inuse); 238 + 239 + setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0); 240 + 241 + rdc321x_wdt_device.default_ticks = ticks; 242 + 243 + printk(KERN_INFO PFX "watchdog init success\n"); 244 + 245 + return 0; 246 + } 247 + 248 + static int rdc321x_wdt_remove(struct platform_device *pdev) 249 + { 250 + if (rdc321x_wdt_device.queue) { 251 + rdc321x_wdt_device.queue = 0; 252 + wait_for_completion(&rdc321x_wdt_device.stop); 253 + } 254 + 255 + misc_deregister(&rdc321x_wdt_misc); 256 + 257 + return 0; 258 + } 259 + 260 + static struct platform_driver rdc321x_wdt_driver = { 261 + .probe = rdc321x_wdt_probe, 262 + .remove = rdc321x_wdt_remove, 263 + .driver = { 264 + .owner = THIS_MODULE, 265 + .name = "rdc321x-wdt", 266 + }, 267 + }; 268 + 269 + static int __init rdc321x_wdt_init(void) 270 + { 271 + return platform_driver_register(&rdc321x_wdt_driver); 272 + } 273 + 274 + static void __exit rdc321x_wdt_exit(void) 275 + { 276 + platform_driver_unregister(&rdc321x_wdt_driver); 277 + } 278 + 279 + module_init(rdc321x_wdt_init); 280 + module_exit(rdc321x_wdt_exit); 281 + 282 + MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); 283 + MODULE_DESCRIPTION("RDC321x watchdog driver"); 284 + MODULE_LICENSE("GPL"); 285 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+2 -14
drivers/watchdog/s3c2410_wdt.c
··· 21 21 * You should have received a copy of the GNU General Public License 22 22 * along with this program; if not, write to the Free Software 23 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 - * 25 - * Changelog: 26 - * 05-Oct-2004 BJD Added semaphore init to stop crashes on open 27 - * Fixed tmr_count / wdt_count confusion 28 - * Added configurable debug 29 - * 30 - * 11-Jan-2005 BJD Fixed divide-by-2 in timeout code 31 - * 32 - * 25-Jan-2005 DA Added suspend/resume support 33 - * Replaced reboot notifier with .shutdown method 34 - * 35 - * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA 36 24 */ 37 25 38 26 #include <linux/module.h> ··· 353 365 return -ENOENT; 354 366 } 355 367 356 - size = (res->end-res->start)+1; 368 + size = (res->end - res->start) + 1; 357 369 wdt_mem = request_mem_region(res->start, size, pdev->name); 358 370 if (wdt_mem == NULL) { 359 371 dev_err(dev, "failed to get memory region\n"); ··· 362 374 } 363 375 364 376 wdt_base = ioremap(res->start, size); 365 - if (wdt_base == 0) { 377 + if (wdt_base == NULL) { 366 378 dev_err(dev, "failed to ioremap() region\n"); 367 379 ret = -EINVAL; 368 380 goto err_req;