diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/Kconfig | 8 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 5 | ||||
-rw-r--r-- | drivers/watchdog/acquirewdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/bcm63xx_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/davinci_wdt.c | 22 | ||||
-rw-r--r-- | drivers/watchdog/iTCO_wdt.c | 97 | ||||
-rw-r--r-- | drivers/watchdog/lantiq_wdt.c | 261 | ||||
-rw-r--r-- | drivers/watchdog/max63xx_wdt.c | 20 | ||||
-rw-r--r-- | drivers/watchdog/mpc8xxx_wdt.c | 5 | ||||
-rw-r--r-- | drivers/watchdog/mtx-1_wdt.c | 21 | ||||
-rw-r--r-- | drivers/watchdog/nv_tco.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/pc87413_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/pnx4008_wdt.c | 28 | ||||
-rw-r--r-- | drivers/watchdog/s3c2410_wdt.c | 19 | ||||
-rw-r--r-- | drivers/watchdog/sbc7240_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/sch311x_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/shwdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/smsc37b787_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/softdog.c | 16 | ||||
-rw-r--r-- | drivers/watchdog/sp5100_tco.c | 16 | ||||
-rw-r--r-- | drivers/watchdog/sp805_wdt.c | 2 |
21 files changed, 459 insertions, 77 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b69d7148255..022f9eb0b7b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -933,7 +933,7 @@ config PNX833X_WDT depends on SOC_PNX8335 help Hardware driver for the PNX833x's watchdog. This is a - watchdog timer that will reboot the machine after a programable + watchdog timer that will reboot the machine after a programmable timer has expired and no process has written to /dev/watchdog during that time. @@ -990,6 +990,12 @@ config BCM63XX_WDT To compile this driver as a loadable module, choose M here. The module will be called bcm63xx_wdt. +config LANTIQ_WDT + tristate "Lantiq SoC watchdog" + depends on LANTIQ + help + Hardware driver for the Lantiq SoC Watchdog Timer. + # PARISC Architecture # POWERPC Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index d520bf9c335..ed26f7094e4 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -4,7 +4,7 @@ # Only one watchdog can succeed. We probe the ISA/PCI/USB based # watchdog-cards first, then the architecture specific watchdog -# drivers and then the architecture independant "softdog" driver. +# drivers and then the architecture independent "softdog" driver. # This means that if your ISA/PCI/USB card isn't detected that # you can fall back to an architecture specific driver and if # that also fails then you can fall back to the software watchdog @@ -123,6 +123,7 @@ obj-$(CONFIG_AR7_WDT) += ar7_wdt.o obj-$(CONFIG_TXX9_WDT) += txx9wdt.o obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o +obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o # PARISC Architecture @@ -153,7 +154,7 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o # Xen obj-$(CONFIG_XEN_WDT) += xen_wdt.o -# Architecture Independant +# Architecture Independent obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c index 2ffce4d7544..b6a2b58cbe6 100644 --- a/drivers/watchdog/acquirewdt.c +++ b/drivers/watchdog/acquirewdt.c @@ -26,7 +26,7 @@ * Theory of Operation: * The Watch-Dog Timer is provided to ensure that standalone * Systems can always recover from catastrophic conditions that - * caused the CPU to crash. This condition may have occured by + * caused the CPU to crash. This condition may have occurred by * external EMI or a software bug. When the CPU stops working * correctly, hardware on the board will either perform a hardware * reset (cold boot) or a non-maskable interrupt (NMI) to bring the diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c index 3c5045a206d..5064e831752 100644 --- a/drivers/watchdog/bcm63xx_wdt.c +++ b/drivers/watchdog/bcm63xx_wdt.c @@ -248,7 +248,7 @@ static int __devinit bcm63xx_wdt_probe(struct platform_device *pdev) return -ENODEV; } - bcm63xx_wdt_device.regs = ioremap_nocache(r->start, r->end - r->start); + bcm63xx_wdt_device.regs = ioremap_nocache(r->start, resource_size(r)); if (!bcm63xx_wdt_device.regs) { dev_err(&pdev->dev, "failed to remap I/O resources\n"); return -ENXIO; diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 596ba604e78..51b5551b4e3 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c @@ -202,7 +202,6 @@ static struct miscdevice davinci_wdt_miscdev = { static int __devinit davinci_wdt_probe(struct platform_device *pdev) { int ret = 0, size; - struct resource *res; struct device *dev = &pdev->dev; wdt_clk = clk_get(dev, NULL); @@ -216,31 +215,31 @@ static int __devinit davinci_wdt_probe(struct platform_device *pdev) dev_info(dev, "heartbeat %d sec\n", heartbeat); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { + wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (wdt_mem == NULL) { dev_err(dev, "failed to get memory region resource\n"); return -ENOENT; } - size = resource_size(res); - wdt_mem = request_mem_region(res->start, size, pdev->name); - - if (wdt_mem == NULL) { + size = resource_size(wdt_mem); + if (!request_mem_region(wdt_mem->start, size, pdev->name)) { dev_err(dev, "failed to get memory region\n"); return -ENOENT; } - wdt_base = ioremap(res->start, size); + wdt_base = ioremap(wdt_mem->start, size); if (!wdt_base) { dev_err(dev, "failed to map memory region\n"); + release_mem_region(wdt_mem->start, size); + wdt_mem = NULL; return -ENOMEM; } ret = misc_register(&davinci_wdt_miscdev); if (ret < 0) { dev_err(dev, "cannot register misc device\n"); - release_resource(wdt_mem); - kfree(wdt_mem); + release_mem_region(wdt_mem->start, size); + wdt_mem = NULL; } else { set_bit(WDT_DEVICE_INITED, &wdt_status); } @@ -253,8 +252,7 @@ static int __devexit davinci_wdt_remove(struct platform_device *pdev) { misc_deregister(&davinci_wdt_miscdev); if (wdt_mem) { - release_resource(wdt_mem); - kfree(wdt_mem); + release_mem_region(wdt_mem->start, resource_size(wdt_mem)); wdt_mem = NULL; } diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 35a0d12dad7..5fd020da7c5 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -35,6 +35,7 @@ * document number 324645-001, 324646-001: Cougar Point (CPT) * document number TBD : Patsburg (PBG) * document number TBD : DH89xxCC + * document number TBD : Panther Point */ /* @@ -153,6 +154,38 @@ enum iTCO_chipsets { TCO_PBG1, /* Patsburg */ TCO_PBG2, /* Patsburg */ TCO_DH89XXCC, /* DH89xxCC */ + TCO_PPT0, /* Panther Point */ + TCO_PPT1, /* Panther Point */ + TCO_PPT2, /* Panther Point */ + TCO_PPT3, /* Panther Point */ + TCO_PPT4, /* Panther Point */ + TCO_PPT5, /* Panther Point */ + TCO_PPT6, /* Panther Point */ + TCO_PPT7, /* Panther Point */ + TCO_PPT8, /* Panther Point */ + TCO_PPT9, /* Panther Point */ + TCO_PPT10, /* Panther Point */ + TCO_PPT11, /* Panther Point */ + TCO_PPT12, /* Panther Point */ + TCO_PPT13, /* Panther Point */ + TCO_PPT14, /* Panther Point */ + TCO_PPT15, /* Panther Point */ + TCO_PPT16, /* Panther Point */ + TCO_PPT17, /* Panther Point */ + TCO_PPT18, /* Panther Point */ + TCO_PPT19, /* Panther Point */ + TCO_PPT20, /* Panther Point */ + TCO_PPT21, /* Panther Point */ + TCO_PPT22, /* Panther Point */ + TCO_PPT23, /* Panther Point */ + TCO_PPT24, /* Panther Point */ + TCO_PPT25, /* Panther Point */ + TCO_PPT26, /* Panther Point */ + TCO_PPT27, /* Panther Point */ + TCO_PPT28, /* Panther Point */ + TCO_PPT29, /* Panther Point */ + TCO_PPT30, /* Panther Point */ + TCO_PPT31, /* Panther Point */ }; static struct { @@ -244,6 +277,38 @@ static struct { {"Patsburg", 2}, {"Patsburg", 2}, {"DH89xxCC", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, + {"Panther Point", 2}, {NULL, 0} }; @@ -363,6 +428,38 @@ static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = { { ITCO_PCI_DEVICE(0x1d40, TCO_PBG1)}, { ITCO_PCI_DEVICE(0x1d41, TCO_PBG2)}, { ITCO_PCI_DEVICE(0x2310, TCO_DH89XXCC)}, + { ITCO_PCI_DEVICE(0x1e40, TCO_PPT0)}, + { ITCO_PCI_DEVICE(0x1e41, TCO_PPT1)}, + { ITCO_PCI_DEVICE(0x1e42, TCO_PPT2)}, + { ITCO_PCI_DEVICE(0x1e43, TCO_PPT3)}, + { ITCO_PCI_DEVICE(0x1e44, TCO_PPT4)}, + { ITCO_PCI_DEVICE(0x1e45, TCO_PPT5)}, + { ITCO_PCI_DEVICE(0x1e46, TCO_PPT6)}, + { ITCO_PCI_DEVICE(0x1e47, TCO_PPT7)}, + { ITCO_PCI_DEVICE(0x1e48, TCO_PPT8)}, + { ITCO_PCI_DEVICE(0x1e49, TCO_PPT9)}, + { ITCO_PCI_DEVICE(0x1e4a, TCO_PPT10)}, + { ITCO_PCI_DEVICE(0x1e4b, TCO_PPT11)}, + { ITCO_PCI_DEVICE(0x1e4c, TCO_PPT12)}, + { ITCO_PCI_DEVICE(0x1e4d, TCO_PPT13)}, + { ITCO_PCI_DEVICE(0x1e4e, TCO_PPT14)}, + { ITCO_PCI_DEVICE(0x1e4f, TCO_PPT15)}, + { ITCO_PCI_DEVICE(0x1e50, TCO_PPT16)}, + { ITCO_PCI_DEVICE(0x1e51, TCO_PPT17)}, + { ITCO_PCI_DEVICE(0x1e52, TCO_PPT18)}, + { ITCO_PCI_DEVICE(0x1e53, TCO_PPT19)}, + { ITCO_PCI_DEVICE(0x1e54, TCO_PPT20)}, + { ITCO_PCI_DEVICE(0x1e55, TCO_PPT21)}, + { ITCO_PCI_DEVICE(0x1e56, TCO_PPT22)}, + { ITCO_PCI_DEVICE(0x1e57, TCO_PPT23)}, + { ITCO_PCI_DEVICE(0x1e58, TCO_PPT24)}, + { ITCO_PCI_DEVICE(0x1e59, TCO_PPT25)}, + { ITCO_PCI_DEVICE(0x1e5a, TCO_PPT26)}, + { ITCO_PCI_DEVICE(0x1e5b, TCO_PPT27)}, + { ITCO_PCI_DEVICE(0x1e5c, TCO_PPT28)}, + { ITCO_PCI_DEVICE(0x1e5d, TCO_PPT29)}, + { ITCO_PCI_DEVICE(0x1e5e, TCO_PPT30)}, + { ITCO_PCI_DEVICE(0x1e5f, TCO_PPT31)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c new file mode 100644 index 00000000000..7d82adac1cb --- /dev/null +++ b/drivers/watchdog/lantiq_wdt.c @@ -0,0 +1,261 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2010 John Crispin <blogic@openwrt.org> + * Based on EP93xx wdt driver + */ + +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <linux/watchdog.h> +#include <linux/platform_device.h> +#include <linux/uaccess.h> +#include <linux/clk.h> +#include <linux/io.h> + +#include <lantiq.h> + +/* Section 3.4 of the datasheet + * The password sequence protects the WDT control register from unintended + * write actions, which might cause malfunction of the WDT. + * + * essentially the following two magic passwords need to be written to allow + * IO access to the WDT core + */ +#define LTQ_WDT_PW1 0x00BE0000 +#define LTQ_WDT_PW2 0x00DC0000 + +#define LTQ_WDT_CR 0x0 /* watchdog control register */ +#define LTQ_WDT_SR 0x8 /* watchdog status register */ + +#define LTQ_WDT_SR_EN (0x1 << 31) /* enable bit */ +#define LTQ_WDT_SR_PWD (0x3 << 26) /* turn on power */ +#define LTQ_WDT_SR_CLKDIV (0x3 << 24) /* turn on clock and set */ + /* divider to 0x40000 */ +#define LTQ_WDT_DIVIDER 0x40000 +#define LTQ_MAX_TIMEOUT ((1 << 16) - 1) /* the reload field is 16 bit */ + +static int nowayout = WATCHDOG_NOWAYOUT; + +static void __iomem *ltq_wdt_membase; +static unsigned long ltq_io_region_clk_rate; + +static unsigned long ltq_wdt_bootstatus; +static unsigned long ltq_wdt_in_use; +static int ltq_wdt_timeout = 30; +static int ltq_wdt_ok_to_close; + +static void +ltq_wdt_enable(void) +{ + ltq_wdt_timeout = ltq_wdt_timeout * + (ltq_io_region_clk_rate / LTQ_WDT_DIVIDER) + 0x1000; + if (ltq_wdt_timeout > LTQ_MAX_TIMEOUT) + ltq_wdt_timeout = LTQ_MAX_TIMEOUT; + + /* write the first password magic */ + ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR); + /* write the second magic plus the configuration and new timeout */ + ltq_w32(LTQ_WDT_SR_EN | LTQ_WDT_SR_PWD | LTQ_WDT_SR_CLKDIV | + LTQ_WDT_PW2 | ltq_wdt_timeout, ltq_wdt_membase + LTQ_WDT_CR); +} + +static void +ltq_wdt_disable(void) +{ + /* write the first password magic */ + ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR); + /* write the second password magic with no config + * this turns the watchdog off + */ + ltq_w32(LTQ_WDT_PW2, ltq_wdt_membase + LTQ_WDT_CR); +} + +static ssize_t +ltq_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + if (len) { + if (!nowayout) { + size_t i; + + ltq_wdt_ok_to_close = 0; + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + ltq_wdt_ok_to_close = 1; + else + ltq_wdt_ok_to_close = 0; + } + } + ltq_wdt_enable(); + } + + return len; +} + +static struct watchdog_info ident = { + .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | + WDIOF_CARDRESET, + .identity = "ltq_wdt", +}; + +static long +ltq_wdt_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret = -ENOTTY; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user((struct watchdog_info __user *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETBOOTSTATUS: + ret = put_user(ltq_wdt_bootstatus, (int __user *)arg); + break; + + case WDIOC_GETSTATUS: + ret = put_user(0, (int __user *)arg); + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(ltq_wdt_timeout, (int __user *)arg); + if (!ret) + ltq_wdt_enable(); + /* intentional drop through */ + case WDIOC_GETTIMEOUT: + ret = put_user(ltq_wdt_timeout, (int __user *)arg); + break; + + case WDIOC_KEEPALIVE: + ltq_wdt_enable(); + ret = 0; + break; + } + return ret; +} + +static int +ltq_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, <q_wdt_in_use)) + return -EBUSY; + ltq_wdt_in_use = 1; + ltq_wdt_enable(); + + return nonseekable_open(inode, file); +} + +static int +ltq_wdt_release(struct inode *inode, struct file *file) +{ + if (ltq_wdt_ok_to_close) + ltq_wdt_disable(); + else + pr_err("ltq_wdt: watchdog closed without warning\n"); + ltq_wdt_ok_to_close = 0; + clear_bit(0, <q_wdt_in_use); + + return 0; +} + +static const struct file_operations ltq_wdt_fops = { + .owner = THIS_MODULE, + .write = ltq_wdt_write, + .unlocked_ioctl = ltq_wdt_ioctl, + .open = ltq_wdt_open, + .release = ltq_wdt_release, + .llseek = no_llseek, +}; + +static struct miscdevice ltq_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = <q_wdt_fops, +}; + +static int __init +ltq_wdt_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct clk *clk; + + if (!res) { + dev_err(&pdev->dev, "cannot obtain I/O memory region"); + return -ENOENT; + } + res = devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), dev_name(&pdev->dev)); + if (!res) { + dev_err(&pdev->dev, "cannot request I/O memory region"); + return -EBUSY; + } + ltq_wdt_membase = devm_ioremap_nocache(&pdev->dev, res->start, + resource_size(res)); + if (!ltq_wdt_membase) { + dev_err(&pdev->dev, "cannot remap I/O memory region\n"); + return -ENOMEM; + } + + /* we do not need to enable the clock as it is always running */ + clk = clk_get(&pdev->dev, "io"); + WARN_ON(!clk); + ltq_io_region_clk_rate = clk_get_rate(clk); + clk_put(clk); + + if (ltq_reset_cause() == LTQ_RST_CAUSE_WDTRST) + ltq_wdt_bootstatus = WDIOF_CARDRESET; + + return misc_register(<q_wdt_miscdev); +} + +static int __devexit +ltq_wdt_remove(struct platform_device *pdev) +{ + misc_deregister(<q_wdt_miscdev); + + if (ltq_wdt_membase) + iounmap(ltq_wdt_membase); + + return 0; +} + + +static struct platform_driver ltq_wdt_driver = { + .remove = __devexit_p(ltq_wdt_remove), + .driver = { + .name = "ltq_wdt", + .owner = THIS_MODULE, + }, +}; + +static int __init +init_ltq_wdt(void) +{ + return platform_driver_probe(<q_wdt_driver, ltq_wdt_probe); +} + +static void __exit +exit_ltq_wdt(void) +{ + return platform_driver_unregister(<q_wdt_driver); +} + +module_init(init_ltq_wdt); +module_exit(exit_ltq_wdt); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); + +MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); +MODULE_DESCRIPTION("Lantiq SoC Watchdog"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c index 7a82ce5a633..73ba2fd8e59 100644 --- a/drivers/watchdog/max63xx_wdt.c +++ b/drivers/watchdog/max63xx_wdt.c @@ -270,7 +270,6 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev) { int ret = 0; int size; - struct resource *res; struct device *dev = &pdev->dev; struct max63xx_timeout *table; @@ -294,21 +293,19 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev) max63xx_pdev = pdev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { + wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (wdt_mem == NULL) { dev_err(dev, "failed to get memory region resource\n"); return -ENOENT; } - size = resource_size(res); - wdt_mem = request_mem_region(res->start, size, pdev->name); - - if (wdt_mem == NULL) { + size = resource_size(wdt_mem); + if (!request_mem_region(wdt_mem->start, size, pdev->name)) { dev_err(dev, "failed to get memory region\n"); return -ENOENT; } - wdt_base = ioremap(res->start, size); + wdt_base = ioremap(wdt_mem->start, size); if (!wdt_base) { dev_err(dev, "failed to map memory region\n"); ret = -ENOMEM; @@ -326,8 +323,8 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev) out_unmap: iounmap(wdt_base); out_request: - release_resource(wdt_mem); - kfree(wdt_mem); + release_mem_region(wdt_mem->start, size); + wdt_mem = NULL; return ret; } @@ -336,8 +333,7 @@ static int __devexit max63xx_wdt_remove(struct platform_device *pdev) { misc_deregister(&max63xx_wdt_miscdev); if (wdt_mem) { - release_resource(wdt_mem); - kfree(wdt_mem); + release_mem_region(wdt_mem->start, resource_size(wdt_mem)); wdt_mem = NULL; } diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 6709d723e01..eed5436ffb5 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -185,15 +185,18 @@ static struct miscdevice mpc8xxx_wdt_miscdev = { .fops = &mpc8xxx_wdt_fops, }; +static const struct of_device_id mpc8xxx_wdt_match[]; static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev) { int ret; + const struct of_device_id *match; struct device_node *np = ofdev->dev.of_node; struct mpc8xxx_wdt_type *wdt_type; u32 freq = fsl_get_sys_freq(); bool enabled; - if (!ofdev->dev.of_match) + match = of_match_device(mpc8xxx_wdt_match, &ofdev->dev); + if (!match) return -EINVAL; wdt_type = match->data; diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 5ec5ac1f787..1479dc4d612 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -66,6 +66,7 @@ static struct { int default_ticks; unsigned long inuse; unsigned gpio; + int gstate; } mtx1_wdt_device; static void mtx1_wdt_trigger(unsigned long unused) @@ -75,13 +76,13 @@ static void mtx1_wdt_trigger(unsigned long unused) spin_lock(&mtx1_wdt_device.lock); if (mtx1_wdt_device.running) ticks--; - /* - * toggle GPIO2_15 - */ - tmp = au_readl(GPIO2_DIR); - tmp = (tmp & ~(1 << mtx1_wdt_device.gpio)) | - ((~tmp) & (1 << mtx1_wdt_device.gpio)); - au_writel(tmp, GPIO2_DIR); + + /* toggle wdt gpio */ + mtx1_wdt_device.gstate = ~mtx1_wdt_device.gstate; + if (mtx1_wdt_device.gstate) + gpio_direction_output(mtx1_wdt_device.gpio, 1); + else + gpio_direction_input(mtx1_wdt_device.gpio); if (mtx1_wdt_device.queue && ticks) mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); @@ -103,7 +104,8 @@ static void mtx1_wdt_start(void) spin_lock_irqsave(&mtx1_wdt_device.lock, flags); if (!mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 1; - gpio_set_value(mtx1_wdt_device.gpio, 1); + mtx1_wdt_device.gstate = 1; + gpio_direction_output(mtx1_wdt_device.gpio, 1); mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); } mtx1_wdt_device.running++; @@ -117,7 +119,8 @@ static int mtx1_wdt_stop(void) spin_lock_irqsave(&mtx1_wdt_device.lock, flags); if (mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 0; - gpio_set_value(mtx1_wdt_device.gpio, 0); + mtx1_wdt_device.gstate = 0; + gpio_direction_output(mtx1_wdt_device.gpio, 0); } ticks = mtx1_wdt_device.default_ticks; spin_unlock_irqrestore(&mtx1_wdt_device.lock, flags); diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c index 267377a5a83..afa78a54711 100644 --- a/drivers/watchdog/nv_tco.c +++ b/drivers/watchdog/nv_tco.c @@ -302,7 +302,7 @@ MODULE_DEVICE_TABLE(pci, tco_pci_tbl); * Init & exit routines */ -static unsigned char __init nv_tco_getdevice(void) +static unsigned char __devinit nv_tco_getdevice(void) { struct pci_dev *dev = NULL; u32 val; diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 139d773300c..b7c13905157 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -49,7 +49,7 @@ #define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1) #define SWC_LDN 0x04 #define SIOCFG2 0x22 /* Serial IO register */ -#define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */ +#define WDCTL 0x10 /* Watchdog-Timer-Control-Register */ #define WDTO 0x11 /* Watchdog timeout register */ #define WDCFG 0x12 /* Watchdog config register */ diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index c7cf4cbf8ab..61493322556 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -254,7 +254,6 @@ static struct miscdevice pnx4008_wdt_miscdev = { static int __devinit pnx4008_wdt_probe(struct platform_device *pdev) { int ret = 0, size; - struct resource *res; if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) heartbeat = DEFAULT_HEARTBEAT; @@ -262,42 +261,42 @@ static int __devinit pnx4008_wdt_probe(struct platform_device *pdev) printk(KERN_INFO MODULE_NAME "PNX4008 Watchdog Timer: heartbeat %d sec\n", heartbeat); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { + wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (wdt_mem == NULL) { printk(KERN_INFO MODULE_NAME "failed to get memory region resouce\n"); return -ENOENT; } - size = resource_size(res); - wdt_mem = request_mem_region(res->start, size, pdev->name); + size = resource_size(wdt_mem); - if (wdt_mem == NULL) { + if (!request_mem_region(wdt_mem->start, size, pdev->name)) { printk(KERN_INFO MODULE_NAME "failed to get memory region\n"); return -ENOENT; } - wdt_base = (void __iomem *)IO_ADDRESS(res->start); + wdt_base = (void __iomem *)IO_ADDRESS(wdt_mem->start); wdt_clk = clk_get(&pdev->dev, NULL); if (IS_ERR(wdt_clk)) { ret = PTR_ERR(wdt_clk); - release_resource(wdt_mem); - kfree(wdt_mem); + release_mem_region(wdt_mem->start, size); + wdt_mem = NULL; goto out; } ret = clk_enable(wdt_clk); if (ret) { - release_resource(wdt_mem); - kfree(wdt_mem); + release_mem_region(wdt_mem->start, size); + wdt_mem = NULL; + clk_put(wdt_clk); goto out; } ret = misc_register(&pnx4008_wdt_miscdev); if (ret < 0) { printk(KERN_ERR MODULE_NAME "cannot register misc device\n"); - release_resource(wdt_mem); - kfree(wdt_mem); + release_mem_region(wdt_mem->start, size); + wdt_mem = NULL; clk_disable(wdt_clk); clk_put(wdt_clk); } else { @@ -320,8 +319,7 @@ static int __devexit pnx4008_wdt_remove(struct platform_device *pdev) clk_put(wdt_clk); if (wdt_mem) { - release_resource(wdt_mem); - kfree(wdt_mem); + release_mem_region(wdt_mem->start, resource_size(wdt_mem)); wdt_mem = NULL; } return 0; diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 25b39bf3592..f7f5aa00df6 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -402,7 +402,6 @@ static inline void s3c2410wdt_cpufreq_deregister(void) static int __devinit s3c2410wdt_probe(struct platform_device *pdev) { - struct resource *res; struct device *dev; unsigned int wtcon; int started = 0; @@ -416,20 +415,19 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev) /* get the memory region for the watchdog timer */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { + wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (wdt_mem == NULL) { dev_err(dev, "no memory resource specified\n"); return -ENOENT; } - size = resource_size(res); - wdt_mem = request_mem_region(res->start, size, pdev->name); - if (wdt_mem == NULL) { + size = resource_size(wdt_mem); + if (!request_mem_region(wdt_mem->start, size, pdev->name)) { dev_err(dev, "failed to get memory region\n"); return -EBUSY; } - wdt_base = ioremap(res->start, size); + wdt_base = ioremap(wdt_mem->start, size); if (wdt_base == NULL) { dev_err(dev, "failed to ioremap() region\n"); ret = -EINVAL; @@ -524,8 +522,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev) iounmap(wdt_base); err_req: - release_resource(wdt_mem); - kfree(wdt_mem); + release_mem_region(wdt_mem->start, size); + wdt_mem = NULL; return ret; } @@ -545,8 +543,7 @@ static int __devexit s3c2410wdt_remove(struct platform_device *dev) iounmap(wdt_base); - release_resource(wdt_mem); - kfree(wdt_mem); + release_mem_region(wdt_mem->start, resource_size(wdt_mem)); wdt_mem = NULL; return 0; } diff --git a/drivers/watchdog/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c index 67ddeb1c830..ff11504c376 100644 --- a/drivers/watchdog/sbc7240_wdt.c +++ b/drivers/watchdog/sbc7240_wdt.c @@ -273,7 +273,7 @@ static int __init sbc7240_wdt_init(void) /* The IO port 0x043 used to disable the watchdog * is already claimed by the system timer, so we - * cant request_region() it ...*/ + * can't request_region() it ...*/ if (timeout < 1 || timeout > SBC7240_MAX_TIMEOUT) { timeout = SBC7240_TIMEOUT; diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index b61ab1c5429..c7cf4b01f58 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c @@ -201,7 +201,7 @@ static void sch311x_wdt_get_status(int *status) spin_lock(&sch311x_wdt_data.io_lock); /* -- Watchdog timer control -- - * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured + * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occurred * Bit 1 Reserved * Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) * Bit 3 P20 Force Timeout enabled: diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index 4e3e7eb5919..db84f2322d1 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -50,7 +50,7 @@ * necssary. * * As a result of this timing problem, the only modes that are particularly - * feasible are the 4096 and the 2048 divisors, which yeild 5.25 and 2.62ms + * feasible are the 4096 and the 2048 divisors, which yield 5.25 and 2.62ms * overflow periods respectively. * * Also, since we can't really expect userspace to be responsive enough diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c index df88cfa05f3..e97b0499bd0 100644 --- a/drivers/watchdog/smsc37b787_wdt.c +++ b/drivers/watchdog/smsc37b787_wdt.c @@ -191,7 +191,7 @@ static inline void wdt_timer_conf(unsigned char conf) static inline void wdt_timer_ctrl(unsigned char reg) { /* -- Watchdog timer control -- - * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured + * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occurred * Bit 1 Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz * Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) * Bit 3 P20 Force Timeout enabled: diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index 100b114e3c3..bf16ffb4d21 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -48,6 +48,7 @@ #include <linux/init.h> #include <linux/jiffies.h> #include <linux/uaccess.h> +#include <linux/kernel.h> #define PFX "SoftDog: " @@ -75,6 +76,11 @@ MODULE_PARM_DESC(soft_noboot, "Softdog action, set to 1 to ignore reboots, 0 to reboot " "(default depends on ONLY_TESTING)"); +static int soft_panic; +module_param(soft_panic, int, 0); +MODULE_PARM_DESC(soft_panic, + "Softdog action, set to 1 to panic, 0 to reboot (default=0)"); + /* * Our timer */ @@ -98,7 +104,10 @@ static void watchdog_fire(unsigned long data) if (soft_noboot) printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n"); - else { + else if (soft_panic) { + printk(KERN_CRIT PFX "Initiating panic.\n"); + panic("Software Watchdog Timer expired."); + } else { printk(KERN_CRIT PFX "Initiating system reboot.\n"); emergency_restart(); printk(KERN_CRIT PFX "Reboot didn't ?????\n"); @@ -267,7 +276,8 @@ static struct notifier_block softdog_notifier = { }; static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 " - "initialized. soft_noboot=%d soft_margin=%d sec (nowayout= %d)\n"; + "initialized. soft_noboot=%d soft_margin=%d sec soft_panic=%d " + "(nowayout= %d)\n"; static int __init watchdog_init(void) { @@ -298,7 +308,7 @@ static int __init watchdog_init(void) return ret; } - printk(banner, soft_noboot, soft_margin, nowayout); + printk(banner, soft_noboot, soft_margin, soft_panic, nowayout); return 0; } diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c index 1bc493848ed..87e0527669d 100644 --- a/drivers/watchdog/sp5100_tco.c +++ b/drivers/watchdog/sp5100_tco.c @@ -42,6 +42,7 @@ #define PFX TCO_MODULE_NAME ": " /* internal variables */ +static u32 tcobase_phys; static void __iomem *tcobase; static unsigned int pm_iobase; static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */ @@ -305,10 +306,18 @@ static unsigned char __devinit sp5100_tco_setupdevice(void) /* Low three bits of BASE0 are reserved. */ val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8); + if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE, + "SP5100 TCO")) { + printk(KERN_ERR PFX "mmio address 0x%04x already in use\n", + val); + goto unreg_region; + } + tcobase_phys = val; + tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE); if (tcobase == 0) { printk(KERN_ERR PFX "failed to get tcobase address\n"); - goto unreg_region; + goto unreg_mem_region; } /* Enable watchdog decode bit */ @@ -346,7 +355,8 @@ static unsigned char __devinit sp5100_tco_setupdevice(void) /* Done */ return 1; - iounmap(tcobase); +unreg_mem_region: + release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); unreg_region: release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); exit: @@ -401,6 +411,7 @@ static int __devinit sp5100_tco_init(struct platform_device *dev) exit: iounmap(tcobase); + release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); return ret; } @@ -414,6 +425,7 @@ static void __devexit sp5100_tco_cleanup(void) /* Deregister */ misc_deregister(&sp5100_tco_miscdev); iounmap(tcobase); + release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); } diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 0a0efe713bc..0d80e08b643 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -90,7 +90,7 @@ static void wdt_setload(unsigned int timeout) /* * sp805 runs counter with given value twice, after the end of first * counter it gives an interrupt and then starts counter again. If - * interrupt already occured then it resets the system. This is why + * interrupt already occurred then it resets the system. This is why * load is half of what should be required. */ load = div_u64(rate, 2) * timeout - 1; |