diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 15:42:42 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 15:42:42 -0700 |
commit | 0b87da68a0f0a7bf7f7446cf64f92e672bd68ef8 (patch) | |
tree | cc5ddfd411bc9c5d6fb828b86eba92f50294805e | |
parent | 59d0952b43552570e0f1c3ff91ebb16d4caec171 (diff) | |
parent | cad19fa66469d2a745fae0c168833d5d33d64489 (diff) |
Merge git://www.linux-watchdog.org/linux-watchdog
Pull first set of watchdog updates from Wim Van Sebroeck:
"This pull contains:
- The removal of ixp2000_wdt
- The addition of ie6xx_wdt
- Some documentation fixes
- Small fixes and improvements
(Note: Part 2 will contain generic watchdog core changes + conversion
of some more drivers)"
* git://www.linux-watchdog.org/linux-watchdog:
Documentation/watchdog: Fix the file descriptor leak when no cmdline arg given
Documentation/watchdog: close the fd when cmdline arg given
Documentation/watchdog: Fix a small typo
watchdog: s3c2410_wdt: Set timeout to actually achieved timeout
watchdog: wm831x: Convert to gpio_request_one()
watchdog: via_wdt: depends on PCI
watchdog: ie6xx_wdt needs io.h
watchdog: ie6xx_wdt.c: fix printk format warning
watchdog: Add watchdog driver for Intel Atom E6XX
watchdog: it87_wdt: Add support for IT8728F watchdog.
watchdog: i6300esb: don't depend on X86
watchdog: Use module_pci_driver
watchdog: sch311x_wdt.c: Remove RESGEN
watchdog: s3c2410-wdt: Use of_match_ptr().
watchdog: Device tree support for pnx4008-wdt
watchdog: ar7_wdt.c: use devm_request_and_ioremap
watchdog: remove ixp2000 driver
watchdog: sp5100_tco.c: quiet sparse noise about using plain integer was NULL pointer
-rw-r--r-- | Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt | 13 | ||||
-rw-r--r-- | Documentation/watchdog/src/watchdog-test.c | 20 | ||||
-rw-r--r-- | Documentation/watchdog/watchdog-kernel-api.txt | 2 | ||||
-rw-r--r-- | drivers/watchdog/Kconfig | 35 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 2 | ||||
-rw-r--r-- | drivers/watchdog/ar7_wdt.c | 33 | ||||
-rw-r--r-- | drivers/watchdog/hpwdt.c | 13 | ||||
-rw-r--r-- | drivers/watchdog/i6300esb.c | 14 | ||||
-rw-r--r-- | drivers/watchdog/ie6xx_wdt.c | 348 | ||||
-rw-r--r-- | drivers/watchdog/it87_wdt.c | 7 | ||||
-rw-r--r-- | drivers/watchdog/ixp2000_wdt.c | 215 | ||||
-rw-r--r-- | drivers/watchdog/pcwd_pci.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/pnx4008_wdt.c | 10 | ||||
-rw-r--r-- | drivers/watchdog/s3c2410_wdt.c | 7 | ||||
-rw-r--r-- | drivers/watchdog/sch311x_wdt.c | 39 | ||||
-rw-r--r-- | drivers/watchdog/sp5100_tco.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/via_wdt.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/wdt_pci.c | 34 | ||||
-rw-r--r-- | drivers/watchdog/wm831x_wdt.c | 13 |
19 files changed, 447 insertions, 396 deletions
diff --git a/Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt b/Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt new file mode 100644 index 00000000000..7c7f6887c79 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt @@ -0,0 +1,13 @@ +* NXP PNX watchdog timer + +Required properties: +- compatible: must be "nxp,pnx4008-wdt" +- reg: physical base address of the controller and length of memory mapped + region. + +Example: + + watchdog@4003C000 { + compatible = "nxp,pnx4008-wdt"; + reg = <0x4003C000 0x1000>; + }; diff --git a/Documentation/watchdog/src/watchdog-test.c b/Documentation/watchdog/src/watchdog-test.c index 63fdc34ceb9..73ff5cc93e0 100644 --- a/Documentation/watchdog/src/watchdog-test.c +++ b/Documentation/watchdog/src/watchdog-test.c @@ -7,6 +7,7 @@ #include <string.h> #include <unistd.h> #include <fcntl.h> +#include <signal.h> #include <sys/ioctl.h> #include <linux/types.h> #include <linux/watchdog.h> @@ -29,6 +30,14 @@ static void keep_alive(void) * The main program. Run the program with "-d" to disable the card, * or "-e" to enable the card. */ + +void term(int sig) +{ + close(fd); + fprintf(stderr, "Stopping watchdog ticks...\n"); + exit(0); +} + int main(int argc, char *argv[]) { int flags; @@ -47,26 +56,31 @@ int main(int argc, char *argv[]) ioctl(fd, WDIOC_SETOPTIONS, &flags); fprintf(stderr, "Watchdog card disabled.\n"); fflush(stderr); - exit(0); + goto end; } else if (!strncasecmp(argv[1], "-e", 2)) { flags = WDIOS_ENABLECARD; ioctl(fd, WDIOC_SETOPTIONS, &flags); fprintf(stderr, "Watchdog card enabled.\n"); fflush(stderr); - exit(0); + goto end; } else { fprintf(stderr, "-d to disable, -e to enable.\n"); fprintf(stderr, "run by itself to tick the card.\n"); fflush(stderr); - exit(0); + goto end; } } else { fprintf(stderr, "Watchdog Ticking Away!\n"); fflush(stderr); } + signal(SIGINT, term); + while(1) { keep_alive(); sleep(1); } +end: + close(fd); + return 0; } diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt index 227f6cd0e5f..25fe4304f2f 100644 --- a/Documentation/watchdog/watchdog-kernel-api.txt +++ b/Documentation/watchdog/watchdog-kernel-api.txt @@ -59,7 +59,7 @@ It contains following fields: * bootstatus: status of the device after booting (reported with watchdog WDIOF_* status bits). * driver_data: a pointer to the drivers private data of a watchdog device. - This data should only be accessed via the watchdog_set_drvadata and + This data should only be accessed via the watchdog_set_drvdata and watchdog_get_drvdata routines. * status: this field contains a number of status bits that give extra information about the status of the device (Like: is the watchdog timer diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index edebaf771f5..a18bf6358eb 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -129,17 +129,6 @@ config 977_WATCHDOG Not sure? It's safe to say N. -config IXP2000_WATCHDOG - tristate "IXP2000 Watchdog" - depends on ARCH_IXP2000 - help - Say Y here if to include support for the watchdog timer - in the Intel IXP2000(2400, 2800, 2850) network processors. - This driver can be built as a module by choosing M. The module - will be called ixp2000_wdt. - - Say N if you are unsure. - config IXP4XX_WATCHDOG tristate "IXP4xx Watchdog" depends on ARCH_IXP4XX @@ -543,7 +532,7 @@ config WAFER_WDT config I6300ESB_WDT tristate "Intel 6300ESB Timer/Watchdog" - depends on X86 && PCI + depends on PCI ---help--- Hardware driver for the watchdog timer built into the Intel 6300ESB controller hub. @@ -551,6 +540,19 @@ config I6300ESB_WDT To compile this driver as a module, choose M here: the module will be called i6300esb. +config IE6XX_WDT + tristate "Intel Atom E6xx Watchdog" + depends on X86 && PCI + select WATCHDOG_CORE + select MFD_CORE + select LPC_SCH + ---help--- + Hardware driver for the watchdog timer built into the Intel + Atom E6XX (TunnelCreek) processor. + + To compile this driver as a module, choose M here: the + module will be called ie6xx_wdt. + config INTEL_SCU_WATCHDOG bool "Intel SCU Watchdog for Mobile Platforms" depends on X86_MRST @@ -607,7 +609,12 @@ config IT87_WDT depends on X86 && EXPERIMENTAL ---help--- This is the driver for the hardware watchdog on the ITE IT8702, - IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 Super I/O chips. + IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 and IT8728 + Super I/O chips. + + If the driver does not work, then make sure that the game port in + the BIOS is enabled. + This watchdog simply watches your kernel to make sure it doesn't freeze, and if it does, it reboots your computer after a certain amount of time. @@ -780,7 +787,7 @@ config SMSC37B787_WDT config VIA_WDT tristate "VIA Watchdog Timer" - depends on X86 + depends on X86 && PCI select WATCHDOG_CORE ---help--- This is the driver for the hardware watchdog timer on VIA diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index e8f479a1640..442bfbe0882 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -36,7 +36,6 @@ obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o obj-$(CONFIG_TWL4030_WATCHDOG) += twl4030_wdt.o obj-$(CONFIG_21285_WATCHDOG) += wdt285.o obj-$(CONFIG_977_WATCHDOG) += wdt977.o -obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o @@ -81,6 +80,7 @@ obj-$(CONFIG_IB700_WDT) += ib700wdt.o obj-$(CONFIG_IBMASR) += ibmasr.o obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o +obj-$(CONFIG_IE6XX_WDT) += ie6xx_wdt.o obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y) obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 639ae9a23fb..dc30dbd21cf 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c @@ -282,29 +282,19 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev) platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); if (!ar7_regs_wdt) { pr_err("could not get registers resource\n"); - rc = -ENODEV; - goto out; - } - - if (!request_mem_region(ar7_regs_wdt->start, - resource_size(ar7_regs_wdt), LONGNAME)) { - pr_warn("watchdog I/O region busy\n"); - rc = -EBUSY; - goto out; + return -ENODEV; } - ar7_wdt = ioremap(ar7_regs_wdt->start, resource_size(ar7_regs_wdt)); + ar7_wdt = devm_request_and_ioremap(&pdev->dev, ar7_regs_wdt); if (!ar7_wdt) { pr_err("could not ioremap registers\n"); - rc = -ENXIO; - goto out_mem_region; + return -ENXIO; } vbus_clk = clk_get(NULL, "vbus"); if (IS_ERR(vbus_clk)) { pr_err("could not get vbus clock\n"); - rc = PTR_ERR(vbus_clk); - goto out_mem_region; + return PTR_ERR(vbus_clk); } ar7_wdt_disable_wdt(); @@ -314,24 +304,21 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev) rc = misc_register(&ar7_wdt_miscdev); if (rc) { pr_err("unable to register misc device\n"); - goto out_alloc; + goto out; } - goto out; + return 0; -out_alloc: - iounmap(ar7_wdt); -out_mem_region: - release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt)); out: + clk_put(vbus_clk); + vbus_clk = NULL; return rc; } static int __devexit ar7_wdt_remove(struct platform_device *pdev) { misc_deregister(&ar7_wdt_miscdev); - iounmap(ar7_wdt); - release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt)); - + clk_put(vbus_clk); + vbus_clk = NULL; return 0; } diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 23885f2d56a..2b763815aee 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -861,16 +861,6 @@ static struct pci_driver hpwdt_driver = { .remove = __devexit_p(hpwdt_exit), }; -static void __exit hpwdt_cleanup(void) -{ - pci_unregister_driver(&hpwdt_driver); -} - -static int __init hpwdt_init(void) -{ - return pci_register_driver(&hpwdt_driver); -} - MODULE_AUTHOR("Tom Mingarelli"); MODULE_DESCRIPTION("hp watchdog driver"); MODULE_LICENSE("GPL"); @@ -889,5 +879,4 @@ module_param(allow_kdump, int, 0); MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs"); #endif /* !CONFIG_HPWDT_NMI_DECODING */ -module_init(hpwdt_init); -module_exit(hpwdt_cleanup); +module_pci_driver(hpwdt_driver); diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 738032a36bc..276877d5b6a 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -492,19 +492,7 @@ static struct pci_driver esb_driver = { .shutdown = esb_shutdown, }; -static int __init watchdog_init(void) -{ - return pci_register_driver(&esb_driver); -} - -static void __exit watchdog_cleanup(void) -{ - pci_unregister_driver(&esb_driver); - pr_info("Watchdog Module Unloaded\n"); -} - -module_init(watchdog_init); -module_exit(watchdog_cleanup); +module_pci_driver(esb_driver); MODULE_AUTHOR("Ross Biro and David Härdeman"); MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets"); diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c new file mode 100644 index 00000000000..5f0d776f902 --- /dev/null +++ b/drivers/watchdog/ie6xx_wdt.c @@ -0,0 +1,348 @@ +/* + * Intel Atom E6xx Watchdog driver + * + * Copyright (C) 2011 Alexander Stein + * <alexander.stein@systec-electronic.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General + * Public License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * The full GNU General Public License is included in this + * distribution in the file called COPYING. + * + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/watchdog.h> +#include <linux/miscdevice.h> +#include <linux/seq_file.h> +#include <linux/debugfs.h> +#include <linux/uaccess.h> +#include <linux/spinlock.h> + +#define DRIVER_NAME "ie6xx_wdt" + +#define PV1 0x00 +#define PV2 0x04 + +#define RR0 0x0c +#define RR1 0x0d +#define WDT_RELOAD 0x01 +#define WDT_TOUT 0x02 + +#define WDTCR 0x10 +#define WDT_PRE_SEL 0x04 +#define WDT_RESET_SEL 0x08 +#define WDT_RESET_EN 0x10 +#define WDT_TOUT_EN 0x20 + +#define DCR 0x14 + +#define WDTLR 0x18 +#define WDT_LOCK 0x01 +#define WDT_ENABLE 0x02 +#define WDT_TOUT_CNF 0x03 + +#define MIN_TIME 1 +#define MAX_TIME (10 * 60) /* 10 minutes */ +#define DEFAULT_TIME 60 + +static unsigned int timeout = DEFAULT_TIME; +module_param(timeout, uint, 0); +MODULE_PARM_DESC(timeout, + "Default Watchdog timer setting (" + __MODULE_STRING(DEFAULT_TIME) "s)." + "The range is from 1 to 600"); + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static u8 resetmode = 0x10; +module_param(resetmode, byte, 0); +MODULE_PARM_DESC(resetmode, + "Resetmode bits: 0x08 warm reset (cold reset otherwise), " + "0x10 reset enable, 0x20 disable toggle GPIO[4] (default=0x10)"); + +static struct { + unsigned short sch_wdtba; + struct spinlock unlock_sequence; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs; +#endif +} ie6xx_wdt_data; + +/* + * This is needed to write to preload and reload registers + * struct ie6xx_wdt_data.unlock_sequence must be used + * to prevent sequence interrupts + */ +static void ie6xx_wdt_unlock_registers(void) +{ + outb(0x80, ie6xx_wdt_data.sch_wdtba + RR0); + outb(0x86, ie6xx_wdt_data.sch_wdtba + RR0); +} + +static int ie6xx_wdt_ping(struct watchdog_device *wdd) +{ + spin_lock(&ie6xx_wdt_data.unlock_sequence); + ie6xx_wdt_unlock_registers(); + outb(WDT_RELOAD, ie6xx_wdt_data.sch_wdtba + RR1); + spin_unlock(&ie6xx_wdt_data.unlock_sequence); + return 0; +} + +static int ie6xx_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) +{ + u32 preload; + u64 clock; + u8 wdtcr; + + /* Watchdog clock is PCI Clock (33MHz) */ + clock = 33000000; + /* and the preload value is loaded into [34:15] of the down counter */ + preload = (t * clock) >> 15; + /* + * Manual states preload must be one less. + * Does not wrap as t is at least 1 + */ + preload -= 1; + + spin_lock(&ie6xx_wdt_data.unlock_sequence); + + /* Set ResetMode & Enable prescaler for range 10ms to 10 min */ + wdtcr = resetmode & 0x38; + outb(wdtcr, ie6xx_wdt_data.sch_wdtba + WDTCR); + + ie6xx_wdt_unlock_registers(); + outl(0, ie6xx_wdt_data.sch_wdtba + PV1); + + ie6xx_wdt_unlock_registers(); + outl(preload, ie6xx_wdt_data.sch_wdtba + PV2); + + ie6xx_wdt_unlock_registers(); + outb(WDT_RELOAD | WDT_TOUT, ie6xx_wdt_data.sch_wdtba + RR1); + + spin_unlock(&ie6xx_wdt_data.unlock_sequence); + + wdd->timeout = t; + return 0; +} + +static int ie6xx_wdt_start(struct watchdog_device *wdd) +{ + ie6xx_wdt_set_timeout(wdd, wdd->timeout); + + /* Enable the watchdog timer */ + spin_lock(&ie6xx_wdt_data.unlock_sequence); + outb(WDT_ENABLE, ie6xx_wdt_data.sch_wdtba + WDTLR); + spin_unlock(&ie6xx_wdt_data.unlock_sequence); + + return 0; +} + +static int ie6xx_wdt_stop(struct watchdog_device *wdd) +{ + if (inb(ie6xx_wdt_data.sch_wdtba + WDTLR) & WDT_LOCK) + return -1; + + /* Disable the watchdog timer */ + spin_lock(&ie6xx_wdt_data.unlock_sequence); + outb(0, ie6xx_wdt_data.sch_wdtba + WDTLR); + spin_unlock(&ie6xx_wdt_data.unlock_sequence); + + return 0; +} + +static const struct watchdog_info ie6xx_wdt_info = { + .identity = "Intel Atom E6xx Watchdog", + .options = WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE | + WDIOF_KEEPALIVEPING, +}; + +static const struct watchdog_ops ie6xx_wdt_ops = { + .owner = THIS_MODULE, + .start = ie6xx_wdt_start, + .stop = ie6xx_wdt_stop, + .ping = ie6xx_wdt_ping, + .set_timeout = ie6xx_wdt_set_timeout, +}; + +static struct watchdog_device ie6xx_wdt_dev = { + .info = &ie6xx_wdt_info, + .ops = &ie6xx_wdt_ops, + .min_timeout = MIN_TIME, + .max_timeout = MAX_TIME, +}; + +#ifdef CONFIG_DEBUG_FS + +static int ie6xx_wdt_dbg_show(struct seq_file *s, void *unused) +{ + seq_printf(s, "PV1 = 0x%08x\n", + inl(ie6xx_wdt_data.sch_wdtba + PV1)); + seq_printf(s, "PV2 = 0x%08x\n", + inl(ie6xx_wdt_data.sch_wdtba + PV2)); + seq_printf(s, "RR = 0x%08x\n", + inw(ie6xx_wdt_data.sch_wdtba + RR0)); + seq_printf(s, "WDTCR = 0x%08x\n", + inw(ie6xx_wdt_data.sch_wdtba + WDTCR)); + seq_printf(s, "DCR = 0x%08x\n", + inl(ie6xx_wdt_data.sch_wdtba + DCR)); + seq_printf(s, "WDTLR = 0x%08x\n", + inw(ie6xx_wdt_data.sch_wdtba + WDTLR)); + + seq_printf(s, "\n"); + return 0; +} + +static int ie6xx_wdt_dbg_open(struct inode *inode, struct file *file) +{ + return single_open(file, ie6xx_wdt_dbg_show, NULL); +} + +static const struct file_operations ie6xx_wdt_dbg_operations = { + .open = ie6xx_wdt_dbg_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void __devinit ie6xx_wdt_debugfs_init(void) +{ + /* /sys/kernel/debug/ie6xx_wdt */ + ie6xx_wdt_data.debugfs = debugfs_create_file("ie6xx_wdt", + S_IFREG | S_IRUGO, NULL, NULL, &ie6xx_wdt_dbg_operations); +} + +static void __devexit ie6xx_wdt_debugfs_exit(void) +{ + debugfs_remove(ie6xx_wdt_data.debugfs); +} + +#else +static void __devinit ie6xx_wdt_debugfs_init(void) +{ +} + +static void __devexit ie6xx_wdt_debugfs_exit(void) +{ +} +#endif + +static int __devinit ie6xx_wdt_probe(struct platform_device *pdev) +{ + struct resource *res; + u8 wdtlr; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!res) + return -ENODEV; + + if (!request_region(res->start, resource_size(res), pdev->name)) { + dev_err(&pdev->dev, "Watchdog region 0x%llx already in use!\n", + (u64)res->start); + return -EBUSY; + } + + ie6xx_wdt_data.sch_wdtba = res->start; + dev_dbg(&pdev->dev, "WDT = 0x%X\n", ie6xx_wdt_data.sch_wdtba); + + ie6xx_wdt_dev.timeout = timeout; + watchdog_set_nowayout(&ie6xx_wdt_dev, nowayout); + + spin_lock_init(&ie6xx_wdt_data.unlock_sequence); + + wdtlr = inb(ie6xx_wdt_data.sch_wdtba + WDTLR); + if (wdtlr & WDT_LOCK) + dev_warn(&pdev->dev, + "Watchdog Timer is Locked (Reg=0x%x)\n", wdtlr); + + ie6xx_wdt_debugfs_init(); + + ret = watchdog_register_device(&ie6xx_wdt_dev); + if (ret) { + dev_err(&pdev->dev, + "Watchdog timer: cannot register device (err =%d)\n", + ret); + goto misc_register_error; + } + + return 0; + +misc_register_error: + ie6xx_wdt_debugfs_exit(); + release_region(res->start, resource_size(res)); + ie6xx_wdt_data.sch_wdtba = 0; + return ret; +} + +static int __devexit ie6xx_wdt_remove(struct platform_device *pdev) +{ + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + ie6xx_wdt_stop(NULL); + watchdog_unregister_device(&ie6xx_wdt_dev); + ie6xx_wdt_debugfs_exit(); + release_region(res->start, resource_size(res)); + ie6xx_wdt_data.sch_wdtba = 0; + + return 0; +} + +static struct platform_driver ie6xx_wdt_driver = { + .probe = ie6xx_wdt_probe, + .remove = __devexit_p(ie6xx_wdt_remove), + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init ie6xx_wdt_init(void) +{ + /* Check boot parameters to verify that their initial values */ + /* are in range. */ + if ((timeout < MIN_TIME) || + (timeout > MAX_TIME)) { + pr_err("Watchdog timer: value of timeout %d (dec) " + "is out of range from %d to %d (dec)\n", + timeout, MIN_TIME, MAX_TIME); + return -EINVAL; + } + + return platform_driver_register(&ie6xx_wdt_driver); +} + +static void __exit ie6xx_wdt_exit(void) +{ + platform_driver_unregister(&ie6xx_wdt_driver); +} + +late_initcall(ie6xx_wdt_init); +module_exit(ie6xx_wdt_exit); + +MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>"); +MODULE_DESCRIPTION("Intel Atom E6xx Watchdog Device Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index 8a741bcb512..d3dcc6988b5 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -12,7 +12,8 @@ * http://www.ite.com.tw/ * * Support of the watchdog timers, which are available on - * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721 and IT8726. + * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 + * and IT8728. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -84,6 +85,7 @@ #define IT8720_ID 0x8720 #define IT8721_ID 0x8721 #define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ +#define IT8728_ID 0x8728 /* GPIO Configuration Registers LDN=0x07 */ #define WDTCTRL 0x71 @@ -95,7 +97,7 @@ #define WDT_CIRINT 0x80 #define WDT_MOUSEINT 0x40 #define WDT_KYBINT 0x20 -#define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721 */ +#define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721, it8728 */ #define WDT_FORCE 0x02 #define WDT_ZERO 0x01 @@ -616,6 +618,7 @@ static int __init it87_wdt_init(void) case IT8718_ID: case IT8720_ID: case IT8721_ID: + case IT8728_ID: max_units = 65535; try_gameport = 0; break; diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c deleted file mode 100644 index 3f047a58d3a..00000000000 --- a/drivers/watchdog/ixp2000_wdt.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * drivers/char/watchdog/ixp2000_wdt.c - * - * Watchdog driver for Intel IXP2000 network processors - * - * Adapted from the IXP4xx watchdog driver by Lennert Buytenhek. - * The original version carries these notices: - * - * Author: Deepak Saxena <dsaxena@plexity.net> - * - * Copyright 2004 (c) MontaVista, Software, Inc. - * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/timer.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/watchdog.h> -#include <linux/init.h> -#include <linux/bitops.h> -#include <linux/uaccess.h> -#include <mach/hardware.h> - -static bool nowayout = WATCHDOG_NOWAYOUT; -static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */ -static unsigned long wdt_status; -static DEFINE_SPINLOCK(wdt_lock); - -#define WDT_IN_USE 0 -#define WDT_OK_TO_CLOSE 1 - -static unsigned long wdt_tick_rate; - -static void wdt_enable(void) -{ - spin_lock(&wdt_lock); - ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE); - ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE); - ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); - ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE); - spin_unlock(&wdt_lock); -} - -static void wdt_disable(void) -{ - spin_lock(&wdt_lock); - ixp2000_reg_write(IXP2000_T4_CTL, 0); - spin_unlock(&wdt_lock); -} - -static void wdt_keepalive(void) -{ - spin_lock(&wdt_lock); - ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); - spin_unlock(&wdt_lock); -} - -static int ixp2000_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(WDT_IN_USE, &wdt_status)) - return -EBUSY; - - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - - wdt_enable(); - - return nonseekable_open(inode, file); -} - -static ssize_t ixp2000_wdt_write(struct file *file, const char *data, - size_t len, loff_t *ppos) -{ - if (len) { - if (!nowayout) { - size_t i; - - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - - for (i = 0; i != len; i++) { - char c; - - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - set_bit(WDT_OK_TO_CLOSE, &wdt_status); - } - } - wdt_keepalive(); - } - - return len; -} - - -static const struct watchdog_info ident = { - .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | - WDIOF_KEEPALIVEPING, - .identity = "IXP2000 Watchdog", -}; - -static long ixp2000_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - int ret = -ENOTTY; - int time; - - switch (cmd) { - case WDIOC_GETSUPPORT: - ret = copy_to_user((struct watchdog_info *)arg, &ident, - sizeof(ident)) ? -EFAULT : 0; - break; - - case WDIOC_GETSTATUS: - ret = put_user(0, (int *)arg); - break; - - case WDIOC_GETBOOTSTATUS: - ret = put_user(0, (int *)arg); - break; - - case WDIOC_KEEPALIVE: - wdt_enable(); - ret = 0; - break; - - case WDIOC_SETTIMEOUT: - ret = get_user(time, (int *)arg); - if (ret) - break; - - if (time <= 0 || time > 60) { - ret = -EINVAL; - break; - } - - heartbeat = time; - wdt_keepalive(); - /* Fall through */ - - case WDIOC_GETTIMEOUT: - ret = put_user(heartbeat, (int *)arg); - break; - } - - return ret; -} - -static int ixp2000_wdt_release(struct inode *inode, struct file *file) -{ - if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) - wdt_disable(); - else - pr_crit("Device closed unexpectedly - timer will not stop\n"); - clear_bit(WDT_IN_USE, &wdt_status); - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - - return 0; -} - - -static const struct file_operations ixp2000_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = ixp2000_wdt_write, - .unlocked_ioctl = ixp2000_wdt_ioctl, - .open = ixp2000_wdt_open, - .release = ixp2000_wdt_release, -}; - -static struct miscdevice ixp2000_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &ixp2000_wdt_fops, -}; - -static int __init ixp2000_wdt_init(void) -{ - if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) { - pr_info("Unable to use IXP2000 watchdog due to IXP2800 erratum #25\n"); - return -EIO; - } - wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256; - return misc_register(&ixp2000_wdt_miscdev); -} - -static void __exit ixp2000_wdt_exit(void) -{ - misc_deregister(&ixp2000_wdt_miscdev); -} - -module_init(ixp2000_wdt_init); -module_exit(ixp2000_wdt_exit); - -MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); -MODULE_DESCRIPTION("IXP2000 Network Processor Watchdog"); - -module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)"); - -module_param(nowayout, bool, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); - diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c index c891399bed6..ee6900da867 100644 --- a/drivers/watchdog/pcwd_pci.c +++ b/drivers/watchdog/pcwd_pci.c @@ -707,6 +707,7 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev, goto err_out_disable_device; } + spin_lock_init(&pcipcwd_private.io_lock); pcipcwd_private.pdev = pdev; pcipcwd_private.io_addr = pci_resource_start(pdev, 0); @@ -814,22 +815,7 @@ static struct pci_driver pcipcwd_driver = { .remove = __devexit_p(pcipcwd_card_exit), }; -static int __init pcipcwd_init_module(void) -{ - spin_lock_init(&pcipcwd_private.io_lock); - - return pci_register_driver(&pcipcwd_driver); -} - -static void __exit pcipcwd_cleanup_module(void) -{ - pci_unregister_driver(&pcipcwd_driver); - - pr_info("Watchdog Module Unloaded\n"); -} - -module_init(pcipcwd_init_module); -module_exit(pcipcwd_cleanup_module); +module_pci_driver(pcipcwd_driver); MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>"); MODULE_DESCRIPTION("Berkshire PCI-PC Watchdog driver"); diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 6b8432f61d0..87722e12605 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -32,6 +32,7 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/err.h> +#include <linux/of.h> #include <mach/hardware.h> /* WatchDog Timer - Chapter 23 Page 207 */ @@ -201,10 +202,19 @@ static int __devexit pnx4008_wdt_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id pnx4008_wdt_match[] = { + { .compatible = "nxp,pnx4008-wdt" }, + { } +}; +MODULE_DEVICE_TABLE(of, pnx4008_wdt_match); +#endif + static struct platform_driver platform_wdt_driver = { .driver = { .name = "pnx4008-watchdog", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(pnx4008_wdt_match), }, .probe = pnx4008_wdt_probe, .remove = __devexit_p(pnx4008_wdt_remove), diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 04e5a6de47d..200ece5e2a2 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -40,6 +40,7 @@ #include <linux/cpufreq.h> #include <linux/slab.h> #include <linux/err.h> +#include <linux/of.h> #include <mach/map.h> @@ -201,7 +202,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeou writel(count, wdt_base + S3C2410_WTDAT); writel(wtcon, wdt_base + S3C2410_WTCON); - wdd->timeout = timeout; + wdd->timeout = (count * divisor) / freq; return 0; } @@ -503,8 +504,6 @@ static const struct of_device_id s3c2410_wdt_match[] = { {}, }; MODULE_DEVICE_TABLE(of, s3c2410_wdt_match); -#else -#define s3c2410_wdt_match NULL #endif static struct platform_driver s3c2410wdt_driver = { @@ -516,7 +515,7 @@ static struct platform_driver s3c2410wdt_driver = { .driver = { .owner = THIS_MODULE, .name = "s3c2410-wdt", - .of_match_table = s3c2410_wdt_match, + .of_match_table = of_match_ptr(s3c2410_wdt_match), }, }; diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index bd86f32d63a..f8477002b72 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c @@ -41,7 +41,6 @@ #define DRV_NAME "sch311x_wdt" /* Runtime registers */ -#define RESGEN 0x1d #define GP60 0x47 #define WDT_TIME_OUT 0x65 #define WDT_VAL 0x66 @@ -69,10 +68,6 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -static unsigned short therm_trip; -module_param(therm_trip, ushort, 0); -MODULE_PARM_DESC(therm_trip, "Should a ThermTrip trigger the reset generator"); - #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ module_param(timeout, int, 0); @@ -358,26 +353,16 @@ static struct miscdevice sch311x_wdt_miscdev = { static int __devinit sch311x_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - unsigned char val; int err; spin_lock_init(&sch311x_wdt_data.io_lock); - if (!request_region(sch311x_wdt_data.runtime_reg + RESGEN, 1, - DRV_NAME)) { - dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", - sch311x_wdt_data.runtime_reg + RESGEN, - sch311x_wdt_data.runtime_reg + RESGEN); - err = -EBUSY; - goto exit; - } - if (!request_region(sch311x_wdt_data.runtime_reg + GP60, 1, DRV_NAME)) { dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", sch311x_wdt_data.runtime_reg + GP60, sch311x_wdt_data.runtime_reg + GP60); err = -EBUSY; - goto exit_release_region; + goto exit; } if (!request_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4, @@ -386,7 +371,7 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev) sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, sch311x_wdt_data.runtime_reg + WDT_CTRL); err = -EBUSY; - goto exit_release_region2; + goto exit_release_region; } /* Make sure that the watchdog is not running */ @@ -414,24 +399,13 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev) /* Get status at boot */ sch311x_wdt_get_status(&sch311x_wdt_data.boot_status); - /* enable watchdog */ - /* -- Reset Generator -- - * Bit 0 Enable Watchdog Timer Generation: 0* = Enabled, 1 = Disabled - * Bit 1 Thermtrip Source Select: O* = No Source, 1 = Source - * Bit 2 WDT2_CTL: WDT input bit - * Bit 3-7 Reserved - */ - outb(0, sch311x_wdt_data.runtime_reg + RESGEN); - val = therm_trip ? 0x06 : 0x04; - outb(val, sch311x_wdt_data.runtime_reg + RESGEN); - sch311x_wdt_miscdev.parent = dev; err = misc_register(&sch311x_wdt_miscdev); if (err != 0) { dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, err); - goto exit_release_region3; + goto exit_release_region2; } dev_info(dev, @@ -440,12 +414,10 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev) return 0; -exit_release_region3: - release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4); exit_release_region2: - release_region(sch311x_wdt_data.runtime_reg + GP60, 1); + release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4); exit_release_region: - release_region(sch311x_wdt_data.runtime_reg + RESGEN, 1); + release_region(sch311x_wdt_data.runtime_reg + GP60, 1); sch311x_wdt_data.runtime_reg = 0; exit: return err; @@ -461,7 +433,6 @@ static int __devexit sch311x_wdt_remove(struct platform_device *pdev) misc_deregister(&sch311x_wdt_miscdev); release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4); release_region(sch311x_wdt_data.runtime_reg + GP60, 1); - release_region(sch311x_wdt_data.runtime_reg + RESGEN, 1); sch311x_wdt_data.runtime_reg = 0; return 0; } diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c index 59108e48ada..ae5e82cb83f 100644 --- a/drivers/watchdog/sp5100_tco.c +++ b/drivers/watchdog/sp5100_tco.c @@ -313,7 +313,7 @@ static unsigned char __devinit sp5100_tco_setupdevice(void) tcobase_phys = val; tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE); - if (tcobase == 0) { + if (!tcobase) { pr_err("failed to get tcobase address\n"); goto unreg_mem_region; } diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c index 465e08273c9..5603e31afda 100644 --- a/drivers/watchdog/via_wdt.c +++ b/drivers/watchdog/via_wdt.c @@ -202,6 +202,9 @@ static int __devinit wdt_probe(struct pci_dev *pdev, goto err_out_release; } + if (timeout < 1 || timeout > WDT_TIMEOUT_MAX) + timeout = WDT_TIMEOUT; + wdt_dev.timeout = timeout; watchdog_set_nowayout(&wdt_dev, nowayout); if (readl(wdt_mem) & VIA_WDT_FIRED) @@ -250,20 +253,7 @@ static struct pci_driver wdt_driver = { .remove = __devexit_p(wdt_remove), }; -static int __init wdt_init(void) -{ - if (timeout < 1 || timeout > WDT_TIMEOUT_MAX) - timeout = WDT_TIMEOUT; - return pci_register_driver(&wdt_driver); -} - -static void __exit wdt_exit(void) -{ - pci_unregister_driver(&wdt_driver); -} - -module_init(wdt_init); -module_exit(wdt_exit); +module_pci_driver(wdt_driver); MODULE_AUTHOR("Marc Vertes"); MODULE_DESCRIPTION("Driver for watchdog timer on VIA chipset"); diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 1c888c7d4cc..e32654efdbb 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -739,39 +739,7 @@ static struct pci_driver wdtpci_driver = { .remove = __devexit_p(wdtpci_remove_one), }; - -/** - * wdtpci_cleanup: - * - * Unload the watchdog. You cannot do this with any file handles open. - * If your watchdog is set to continue ticking on close and you unload - * it, well it keeps ticking. We won't get the interrupt but the board - * will not touch PC memory so all is fine. You just have to load a new - * module in xx seconds or reboot. - */ - -static void __exit wdtpci_cleanup(void) -{ - pci_unregister_driver(&wdtpci_driver); -} - - -/** - * wdtpci_init: - * - * Set up the WDT watchdog board. All we have to do is grab the - * resources we require and bitch if anyone beat us to them. - * The open() function will actually kick the board off. - */ - -static int __init wdtpci_init(void) -{ - return pci_register_driver(&wdtpci_driver); -} - - -module_init(wdtpci_init); -module_exit(wdtpci_cleanup); +module_pci_driver(wdtpci_driver); MODULE_AUTHOR("JP Nollmann, Alan Cox"); MODULE_DESCRIPTION("Driver for the ICS PCI-WDT500/501 watchdog cards"); diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index b1815c5ed7a..87d66d236c3 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c @@ -247,8 +247,9 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev) reg |= pdata->software << WM831X_WDOG_RST_SRC_SHIFT; if (pdata->update_gpio) { - ret = gpio_request(pdata->update_gpio, - "Watchdog update"); + ret = gpio_request_one(pdata->update_gpio, + GPIOF_DIR_OUT | GPIOF_INIT_LOW, + "Watchdog update"); if (ret < 0) { dev_err(wm831x->dev, "Failed to request update GPIO: %d\n", @@ -256,14 +257,6 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev) goto err; } - ret = gpio_direction_output(pdata->update_gpio, 0); - if (ret != 0) { - dev_err(wm831x->dev, - "gpio_direction_output returned: %d\n", - ret); - goto err_gpio; - } - driver_data->update_gpio = pdata->update_gpio; /* Make sure the watchdog takes hardware updates */ |