From b1fa888e0124763e5bafda074874fc7ac0f2f23f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 24 May 2010 10:55:59 +0900 Subject: watchdog: shwdt: Kill off mmap stub and superfluous comments. The wdt mmaping thing was a special-cased hack that nothing in the wild depends on, so just kill it off. While at it, sanitize the superfluous comments in preparation for a driver rewrite and overhauled interface. Signed-off-by: Paul Mundt --- drivers/watchdog/Kconfig | 8 --- drivers/watchdog/shwdt.c | 138 +---------------------------------------------- 2 files changed, 2 insertions(+), 144 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b87ba23442d2..8828d8ffd353 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -948,14 +948,6 @@ config SH_WDT To compile this driver as a module, choose M here: the module will be called shwdt. -config SH_WDT_MMAP - bool "Allow mmap of SH WDT" - default n - depends on SH_WDT - help - If you say Y here, user applications will be able to mmap the - WDT/CPG registers. - # SPARC Architecture # SPARC64 Architecture diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index a03f84e5ee1f..bee1f5865825 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -1,9 +1,9 @@ /* - * drivers/char/watchdog/shwdt.c + * drivers/watchdog/shwdt.c * * Watchdog driver for integrated watchdog in the SuperH processors. * - * Copyright (C) 2001, 2002, 2003 Paul Mundt + * Copyright (C) 2001 - 2010 Paul Mundt * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -76,14 +76,8 @@ static DEFINE_SPINLOCK(shwdt_lock); #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ - static int nowayout = WATCHDOG_NOWAYOUT; -/** - * sh_wdt_start - Start the Watchdog - * - * Starts the watchdog. - */ static void sh_wdt_start(void) { __u8 csr; @@ -114,15 +108,6 @@ static void sh_wdt_start(void) sh_wdt_write_csr(csr); #ifdef CONFIG_CPU_SH2 - /* - * Whoever came up with the RSTCSR semantics must've been smoking - * some of the good stuff, since in addition to the WTCSR/WTCNT write - * brain-damage, it's managed to fuck things up one step further.. - * - * If we need to clear the WOVF bit, the upper byte has to be 0xa5.. - * but if we want to touch RSTE or RSTS, the upper byte has to be - * 0x5a.. - */ csr = sh_wdt_read_rstcsr(); csr &= ~RSTCSR_RSTS; sh_wdt_write_rstcsr(csr); @@ -130,10 +115,6 @@ static void sh_wdt_start(void) spin_unlock_irqrestore(&shwdt_lock, flags); } -/** - * sh_wdt_stop - Stop the Watchdog - * Stops the watchdog. - */ static void sh_wdt_stop(void) { __u8 csr; @@ -149,10 +130,6 @@ static void sh_wdt_stop(void) spin_unlock_irqrestore(&shwdt_lock, flags); } -/** - * sh_wdt_keepalive - Keep the Userspace Watchdog Alive - * The Userspace watchdog got a KeepAlive: schedule the next heartbeat. - */ static inline void sh_wdt_keepalive(void) { unsigned long flags; @@ -162,10 +139,6 @@ static inline void sh_wdt_keepalive(void) spin_unlock_irqrestore(&shwdt_lock, flags); } -/** - * sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat - * Set the Userspace Watchdog heartbeat - */ static int sh_wdt_set_heartbeat(int t) { unsigned long flags; @@ -179,12 +152,6 @@ static int sh_wdt_set_heartbeat(int t) return 0; } -/** - * sh_wdt_ping - Ping the Watchdog - * @data: Unused - * - * Clears overflow bit, resets timer counter. - */ static void sh_wdt_ping(unsigned long data) { unsigned long flags; @@ -206,13 +173,6 @@ static void sh_wdt_ping(unsigned long data) spin_unlock_irqrestore(&shwdt_lock, flags); } -/** - * sh_wdt_open - Open the Device - * @inode: inode of device - * @file: file handle of device - * - * Watchdog device is opened and started. - */ static int sh_wdt_open(struct inode *inode, struct file *file) { if (test_and_set_bit(0, &shwdt_is_open)) @@ -225,13 +185,6 @@ static int sh_wdt_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); } -/** - * sh_wdt_close - Close the Device - * @inode: inode of device - * @file: file handle of device - * - * Watchdog device is closed and stopped. - */ static int sh_wdt_close(struct inode *inode, struct file *file) { if (shwdt_expect_close == 42) { @@ -248,15 +201,6 @@ static int sh_wdt_close(struct inode *inode, struct file *file) return 0; } -/** - * sh_wdt_write - Write to Device - * @file: file handle of device - * @buf: buffer to write - * @count: length of buffer - * @ppos: offset - * - * Pings the watchdog on write. - */ static ssize_t sh_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { @@ -280,64 +224,6 @@ static ssize_t sh_wdt_write(struct file *file, const char *buf, return count; } -/** - * sh_wdt_mmap - map WDT/CPG registers into userspace - * @file: file structure for the device - * @vma: VMA to map the registers into - * - * A simple mmap() implementation for the corner cases where the counter - * needs to be mapped in userspace directly. Due to the relatively small - * size of the area, neighbouring registers not necessarily tied to the - * CPG will also be accessible through the register page, so this remains - * configurable for users that really know what they're doing. - * - * Additionaly, the register page maps in the CPG register base relative - * to the nearest page-aligned boundary, which requires that userspace do - * the appropriate CPU subtype math for calculating the page offset for - * the counter value. - */ -static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma) -{ - int ret = -ENOSYS; - -#ifdef CONFIG_SH_WDT_MMAP - unsigned long addr; - - /* Only support the simple cases where we map in a register page. */ - if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff) - return -EINVAL; - - /* - * Pick WTCNT as the start, it's usually the first register after the - * FRQCR, and neither one are generally page-aligned out of the box. - */ - addr = WTCNT & ~(PAGE_SIZE - 1); - - vma->vm_flags |= VM_IO; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, - PAGE_SIZE, vma->vm_page_prot)) { - printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n", - __func__); - return -EAGAIN; - } - - ret = 0; -#endif - - return ret; -} - -/** - * sh_wdt_ioctl - Query Device - * @file: file handle of device - * @cmd: watchdog command - * @arg: argument - * - * Query basic information from the device or ping it, as outlined by the - * watchdog API. - */ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -386,15 +272,6 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, return 0; } -/** - * sh_wdt_notify_sys - Notifier Handler - * @this: notifier block - * @code: notifier event - * @unused: unused - * - * Handles specific events, such as turning off the watchdog during a - * shutdown event. - */ static int sh_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { @@ -411,7 +288,6 @@ static const struct file_operations sh_wdt_fops = { .unlocked_ioctl = sh_wdt_ioctl, .open = sh_wdt_open, .release = sh_wdt_close, - .mmap = sh_wdt_mmap, }; static const struct watchdog_info sh_wdt_info = { @@ -431,11 +307,6 @@ static struct miscdevice sh_wdt_miscdev = { .fops = &sh_wdt_fops, }; -/** - * sh_wdt_init - Initialize module - * Registers the device and notifier handler. Actual device - * initialization is handled by sh_wdt_open(). - */ static int __init sh_wdt_init(void) { int rc; @@ -477,11 +348,6 @@ static int __init sh_wdt_init(void) return 0; } -/** - * sh_wdt_exit - Deinitialize module - * Unregisters the device and notifier handler. Actual device - * deinitialization is handled by sh_wdt_close(). - */ static void __exit sh_wdt_exit(void) { misc_deregister(&sh_wdt_miscdev); -- cgit v1.2.2 From 8f5585ec3d173819dd7e751f661c33af39d7ec60 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 25 May 2010 18:31:12 +0900 Subject: watchdog: shwdt: driver model conversion. This is a long overdue driver model conversion for the shwdt watchdog driver. This is the initial conversion, more incremental changes to follow. Signed-off-by: Paul Mundt --- drivers/watchdog/shwdt.c | 227 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 168 insertions(+), 59 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index bee1f5865825..b7d2f8a0422b 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -19,6 +19,7 @@ */ #include #include +#include #include #include #include @@ -28,11 +29,12 @@ #include #include #include +#include #include #include #include -#define PFX "shwdt: " +#define DRV_NAME "sh-wdt" /* * Default clock division ratio is 5.25 msecs. For an additional table of @@ -62,31 +64,36 @@ * misses its deadline, the kernel timer will allow the WDT to overflow. */ static int clock_division_ratio = WTCSR_CKS_4096; - #define next_ping_period(cks) msecs_to_jiffies(cks - 4) -static void sh_wdt_ping(unsigned long data); - -static unsigned long shwdt_is_open; static const struct watchdog_info sh_wdt_info; -static char shwdt_expect_close; -static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0); -static unsigned long next_heartbeat; +static struct platform_device *sh_wdt_dev; static DEFINE_SPINLOCK(shwdt_lock); #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ static int nowayout = WATCHDOG_NOWAYOUT; +static unsigned long next_heartbeat; + +struct sh_wdt { + void __iomem *base; + struct device *dev; -static void sh_wdt_start(void) + struct timer_list timer; + + unsigned long enabled; + char expect_close; +}; + +static void sh_wdt_start(struct sh_wdt *wdt) { - __u8 csr; unsigned long flags; + u8 csr; spin_lock_irqsave(&shwdt_lock, flags); next_heartbeat = jiffies + (heartbeat * HZ); - mod_timer(&timer, next_ping_period(clock_division_ratio)); + mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); csr = sh_wdt_read_csr(); csr |= WTCSR_WT | clock_division_ratio; @@ -115,22 +122,23 @@ static void sh_wdt_start(void) spin_unlock_irqrestore(&shwdt_lock, flags); } -static void sh_wdt_stop(void) +static void sh_wdt_stop(struct sh_wdt *wdt) { - __u8 csr; unsigned long flags; + u8 csr; spin_lock_irqsave(&shwdt_lock, flags); - del_timer(&timer); + del_timer(&wdt->timer); csr = sh_wdt_read_csr(); csr &= ~WTCSR_TME; sh_wdt_write_csr(csr); + spin_unlock_irqrestore(&shwdt_lock, flags); } -static inline void sh_wdt_keepalive(void) +static inline void sh_wdt_keepalive(struct sh_wdt *wdt) { unsigned long flags; @@ -154,11 +162,12 @@ static int sh_wdt_set_heartbeat(int t) static void sh_wdt_ping(unsigned long data) { + struct sh_wdt *wdt = (struct sh_wdt *)data; unsigned long flags; spin_lock_irqsave(&shwdt_lock, flags); if (time_before(jiffies, next_heartbeat)) { - __u8 csr; + u8 csr; csr = sh_wdt_read_csr(); csr &= ~WTCSR_IOVF; @@ -166,37 +175,43 @@ static void sh_wdt_ping(unsigned long data) sh_wdt_write_cnt(0); - mod_timer(&timer, next_ping_period(clock_division_ratio)); + mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); } else - printk(KERN_WARNING PFX "Heartbeat lost! Will not ping " - "the watchdog\n"); + dev_warn(wdt->dev, "Heartbeat lost! Will not ping " + "the watchdog\n"); spin_unlock_irqrestore(&shwdt_lock, flags); } static int sh_wdt_open(struct inode *inode, struct file *file) { - if (test_and_set_bit(0, &shwdt_is_open)) + struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev); + + if (test_and_set_bit(0, &wdt->enabled)) return -EBUSY; if (nowayout) __module_get(THIS_MODULE); - sh_wdt_start(); + file->private_data = wdt; + + sh_wdt_start(wdt); return nonseekable_open(inode, file); } static int sh_wdt_close(struct inode *inode, struct file *file) { - if (shwdt_expect_close == 42) { - sh_wdt_stop(); + struct sh_wdt *wdt = file->private_data; + + if (wdt->expect_close == 42) { + sh_wdt_stop(wdt); } else { - printk(KERN_CRIT PFX "Unexpected close, not " - "stopping watchdog!\n"); - sh_wdt_keepalive(); + dev_crit(wdt->dev, "Unexpected close, not " + "stopping watchdog!\n"); + sh_wdt_keepalive(wdt); } - clear_bit(0, &shwdt_is_open); - shwdt_expect_close = 0; + clear_bit(0, &wdt->enabled); + wdt->expect_close = 0; return 0; } @@ -204,21 +219,23 @@ static int sh_wdt_close(struct inode *inode, struct file *file) static ssize_t sh_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { + struct sh_wdt *wdt = file->private_data; + if (count) { if (!nowayout) { size_t i; - shwdt_expect_close = 0; + wdt->expect_close = 0; for (i = 0; i != count; i++) { char c; if (get_user(c, buf + i)) return -EFAULT; if (c == 'V') - shwdt_expect_close = 42; + wdt->expect_close = 42; } } - sh_wdt_keepalive(); + sh_wdt_keepalive(wdt); } return count; @@ -227,6 +244,7 @@ static ssize_t sh_wdt_write(struct file *file, const char *buf, static long sh_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + struct sh_wdt *wdt = file->private_data; int new_heartbeat; int options, retval = -EINVAL; @@ -242,18 +260,18 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (options & WDIOS_DISABLECARD) { - sh_wdt_stop(); + sh_wdt_stop(wdt); retval = 0; } if (options & WDIOS_ENABLECARD) { - sh_wdt_start(); + sh_wdt_start(wdt); retval = 0; } return retval; case WDIOC_KEEPALIVE: - sh_wdt_keepalive(); + sh_wdt_keepalive(wdt); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_heartbeat, (int *)arg)) @@ -262,7 +280,7 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, if (sh_wdt_set_heartbeat(new_heartbeat)) return -EINVAL; - sh_wdt_keepalive(); + sh_wdt_keepalive(wdt); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(heartbeat, (int *)arg); @@ -275,8 +293,10 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, static int sh_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { + struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev); + if (code == SYS_DOWN || code == SYS_HALT) - sh_wdt_stop(); + sh_wdt_stop(wdt); return NOTIFY_DONE; } @@ -307,56 +327,148 @@ static struct miscdevice sh_wdt_miscdev = { .fops = &sh_wdt_fops, }; -static int __init sh_wdt_init(void) +static int __devinit sh_wdt_probe(struct platform_device *pdev) { + struct sh_wdt *wdt; + struct resource *res; int rc; - if (clock_division_ratio < 0x5 || clock_division_ratio > 0x7) { - clock_division_ratio = WTCSR_CKS_4096; - printk(KERN_INFO PFX - "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n", - clock_division_ratio); + /* + * As this driver only covers the global watchdog case, reject + * any attempts to register per-CPU watchdogs. + */ + if (pdev->id != -1) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!res)) + return -EINVAL; + + if (!devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), DRV_NAME)) + return -EBUSY; + + wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL); + if (unlikely(!wdt)) { + rc = -ENOMEM; + goto out_release; } - rc = sh_wdt_set_heartbeat(heartbeat); - if (unlikely(rc)) { - heartbeat = WATCHDOG_HEARTBEAT; - printk(KERN_INFO PFX - "heartbeat value must be 1<=x<=3600, using %d\n", - heartbeat); + wdt->dev = &pdev->dev; + + wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (unlikely(!wdt->base)) { + rc = -ENXIO; + goto out_err; } rc = register_reboot_notifier(&sh_wdt_notifier); if (unlikely(rc)) { - printk(KERN_ERR PFX + dev_err(&pdev->dev, "Can't register reboot notifier (err=%d)\n", rc); - return rc; + goto out_unmap; } + sh_wdt_miscdev.parent = wdt->dev; + rc = misc_register(&sh_wdt_miscdev); if (unlikely(rc)) { - printk(KERN_ERR PFX + dev_err(&pdev->dev, "Can't register miscdev on minor=%d (err=%d)\n", sh_wdt_miscdev.minor, rc); - unregister_reboot_notifier(&sh_wdt_notifier); - return rc; + goto out_unreg; } - printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", - heartbeat, nowayout); + init_timer(&wdt->timer); + wdt->timer.function = sh_wdt_ping; + wdt->timer.data = (unsigned long)wdt; + wdt->timer.expires = next_ping_period(clock_division_ratio); + + platform_set_drvdata(pdev, wdt); + sh_wdt_dev = pdev; + + dev_info(&pdev->dev, "initialized.\n"); return 0; + +out_unreg: + unregister_reboot_notifier(&sh_wdt_notifier); +out_unmap: + devm_iounmap(&pdev->dev, wdt->base); +out_err: + devm_kfree(&pdev->dev, wdt); +out_release: + devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); + + return rc; } -static void __exit sh_wdt_exit(void) +static int __devexit sh_wdt_remove(struct platform_device *pdev) { + struct sh_wdt *wdt = platform_get_drvdata(pdev); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + platform_set_drvdata(pdev, NULL); + misc_deregister(&sh_wdt_miscdev); + + sh_wdt_dev = NULL; + unregister_reboot_notifier(&sh_wdt_notifier); + devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); + devm_iounmap(&pdev->dev, wdt->base); + devm_kfree(&pdev->dev, wdt); + + return 0; +} + +static struct platform_driver sh_wdt_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + + .probe = sh_wdt_probe, + .remove = __devexit_p(sh_wdt_remove), +}; + +static int __init sh_wdt_init(void) +{ + int rc; + + if (unlikely(clock_division_ratio < 0x5 || + clock_division_ratio > 0x7)) { + clock_division_ratio = WTCSR_CKS_4096; + + pr_info("%s: divisor must be 0x5<=x<=0x7, using %d\n", + DRV_NAME, clock_division_ratio); + } + + rc = sh_wdt_set_heartbeat(heartbeat); + if (unlikely(rc)) { + heartbeat = WATCHDOG_HEARTBEAT; + + pr_info("%s: heartbeat value must be 1<=x<=3600, using %d\n", + DRV_NAME, heartbeat); + } + + pr_info("%s: configured with heartbeat=%d sec (nowayout=%d)\n", + DRV_NAME, heartbeat, nowayout); + + return platform_driver_register(&sh_wdt_driver); } +static void __exit sh_wdt_exit(void) +{ + platform_driver_unregister(&sh_wdt_driver); +} +module_init(sh_wdt_init); +module_exit(sh_wdt_exit); + MODULE_AUTHOR("Paul Mundt "); MODULE_DESCRIPTION("SuperH watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); module_param(clock_division_ratio, int, 0); @@ -373,6 +485,3 @@ module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - -module_init(sh_wdt_init); -module_exit(sh_wdt_exit); -- cgit v1.2.2 From 7ec5ad0f3c1e28b693185c35f768953c5db32291 Mon Sep 17 00:00:00 2001 From: "Varadarajan, Charulatha" Date: Thu, 23 Sep 2010 20:02:43 +0530 Subject: OMAP: WDT: Use PM runtime APIs instead of clk FW APIs Call runtime pm APIs pm_runtime_put_sync() and pm_runtime_get_sync() for enabling/disabling the clocks, sysconfig settings instead of using clock FW APIs. Signed-off-by: Charulatha V Acked-by: Cousson, Benoit Acked-by: Wim Van Sebroeck Signed-off-by: Kevin Hilman --- drivers/watchdog/omap_wdt.c | 42 +++++++----------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 76b58abf4451..dbbc5801a0c3 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -38,11 +38,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include @@ -61,8 +61,6 @@ struct omap_wdt_dev { void __iomem *base; /* physical */ struct device *dev; int omap_wdt_users; - struct clk *ick; - struct clk *fck; struct resource *mem; struct miscdevice omap_wdt_miscdev; }; @@ -146,8 +144,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file) if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) return -EBUSY; - clk_enable(wdev->ick); /* Enable the interface clock */ - clk_enable(wdev->fck); /* Enable the functional clock */ + pm_runtime_get_sync(wdev->dev); /* initialize prescaler */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) @@ -177,8 +174,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file) omap_wdt_disable(wdev); - clk_disable(wdev->ick); - clk_disable(wdev->fck); + pm_runtime_put_sync(wdev->dev); #else printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); #endif @@ -292,19 +288,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) wdev->omap_wdt_users = 0; wdev->mem = mem; - - wdev->ick = clk_get(&pdev->dev, "ick"); - if (IS_ERR(wdev->ick)) { - ret = PTR_ERR(wdev->ick); - wdev->ick = NULL; - goto err_clk; - } - wdev->fck = clk_get(&pdev->dev, "fck"); - if (IS_ERR(wdev->fck)) { - ret = PTR_ERR(wdev->fck); - wdev->fck = NULL; - goto err_clk; - } + wdev->dev = &pdev->dev; wdev->base = ioremap(res->start, resource_size(res)); if (!wdev->base) { @@ -314,8 +298,8 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, wdev); - clk_enable(wdev->ick); - clk_enable(wdev->fck); + pm_runtime_enable(wdev->dev); + pm_runtime_get_sync(wdev->dev); omap_wdt_disable(wdev); omap_wdt_adjust_timeout(timer_margin); @@ -333,11 +317,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, timer_margin); - /* autogate OCP interface clock */ - __raw_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG); - - clk_disable(wdev->ick); - clk_disable(wdev->fck); + pm_runtime_put_sync(wdev->dev); omap_wdt_dev = pdev; @@ -349,12 +329,6 @@ err_misc: err_ioremap: wdev->base = NULL; - -err_clk: - if (wdev->ick) - clk_put(wdev->ick); - if (wdev->fck) - clk_put(wdev->fck); kfree(wdev); err_kzalloc: @@ -386,8 +360,6 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev) release_mem_region(res->start, resource_size(res)); platform_set_drvdata(pdev, NULL); - clk_put(wdev->ick); - clk_put(wdev->fck); iounmap(wdev->base); kfree(wdev); -- cgit v1.2.2 From 613655fa39ff6957754fa8ceb8559980920eb8ee Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 2 Jun 2010 14:28:52 +0200 Subject: drivers: autoconvert trivial BKL users to private mutex All these files use the big kernel lock in a trivial way to serialize their private file operations, typically resulting from an earlier semi-automatic pushdown from VFS. None of these drivers appears to want to lock against other code, and they all use the BKL as the top-level lock in their file operations, meaning that there is no lock-order inversion problem. Consequently, we can remove the BKL completely, replacing it with a per-file mutex in every case. Using a scripted approach means we can avoid typos. These drivers do not seem to be under active maintainance from my brief investigation. Apologies to those maintainers that I have missed. file=$1 name=$2 if grep -q lock_kernel ${file} ; then if grep -q 'include.*linux.mutex.h' ${file} ; then sed -i '/include.*/d' ${file} else sed -i 's/include.*.*$/include /g' ${file} fi sed -i ${file} \ -e "/^#include.*linux.mutex.h/,$ { 1,/^\(static\|int\|long\)/ { /^\(static\|int\|long\)/istatic DEFINE_MUTEX(${name}_mutex); } }" \ -e "s/\(un\)*lock_kernel\>[ ]*()/mutex_\1lock(\&${name}_mutex)/g" \ -e '/[ ]*cycle_kernel_lock();/d' else sed -i -e '/include.*\/d' ${file} \ -e '/cycle_kernel_lock()/d' fi Signed-off-by: Arnd Bergmann --- drivers/watchdog/cpwd.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 566343b3c131..b7d96e6236a1 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -89,6 +89,7 @@ struct cpwd { } devs[WD_NUMDEVS]; }; +static DEFINE_MUTEX(cpwd_mutex); static struct cpwd *cpwd_device; /* Sun uses Altera PLD EPF8820ATC144-4 @@ -368,7 +369,7 @@ static int cpwd_open(struct inode *inode, struct file *f) { struct cpwd *p = cpwd_device; - lock_kernel(); + mutex_lock(&cpwd_mutex); switch (iminor(inode)) { case WD0_MINOR: case WD1_MINOR: @@ -376,7 +377,7 @@ static int cpwd_open(struct inode *inode, struct file *f) break; default: - unlock_kernel(); + mutex_unlock(&cpwd_mutex); return -ENODEV; } @@ -386,13 +387,13 @@ static int cpwd_open(struct inode *inode, struct file *f) IRQF_SHARED, DRIVER_NAME, p)) { printk(KERN_ERR PFX "Cannot register IRQ %d\n", p->irq); - unlock_kernel(); + mutex_unlock(&cpwd_mutex); return -EBUSY; } p->initialized = true; } - unlock_kernel(); + mutex_unlock(&cpwd_mutex); return nonseekable_open(inode, f); } @@ -482,9 +483,9 @@ static long cpwd_compat_ioctl(struct file *file, unsigned int cmd, case WIOCSTART: case WIOCSTOP: case WIOCGSTAT: - lock_kernel(); + mutex_lock(&cpwd_mutex); rval = cpwd_ioctl(file, cmd, arg); - unlock_kernel(); + mutex_unlock(&cpwd_mutex); break; /* everything else is handled by the generic compat layer */ -- cgit v1.2.2 From ca4d3e6746bdcfccb517349bce2d2c5b5614fb6f Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Oct 2010 14:08:54 +0100 Subject: MIPS: Add missing #inclusions of Add missing #inclusions of to a whole bunch of files that should really include it. Note that this can replace #inclusions of . This is required for the patch to sort out irqflags handling function naming to compile on MIPS. The problem is that these files require access to things like setup_irq() - which isn't available by #including Signed-off-by: David Howells Acked-by: Ralf Baechle --- drivers/watchdog/octeon-wdt-main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 2a410170eca6..909923800a02 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include -- cgit v1.2.2 From fbdd7144ceadd578bc2a875af1dabd67e80ba0d0 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 20 Sep 2010 11:23:42 -0500 Subject: powerpc/watchdog: Allow the Book-E driver to be compiled as a module Register the __init and __exit functions in the PowerPC Book-E Watchdog driver as module entry/exit functions, and modify the Kconfig entry. Add a .release method for the PowerPC Book-E Watchdog driver, so that the watchdog is disabled when the driver is closed. Loosely based on original code from Jiang Yutang . Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala --- drivers/watchdog/Kconfig | 5 ++++- drivers/watchdog/booke_wdt.c | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 24efd8ea41bb..a6812eb31fa1 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -957,9 +957,12 @@ config PIKA_WDT the Warp platform. config BOOKE_WDT - bool "PowerPC Book-E Watchdog Timer" + tristate "PowerPC Book-E Watchdog Timer" depends on BOOKE || 4xx ---help--- + Watchdog driver for PowerPC Book-E chips, such as the Freescale + MPC85xx SOCs and the IBM PowerPC 440. + Please see Documentation/watchdog/watchdog-api.txt for more information. diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index 3d49671cdf5a..a9899981fd97 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -4,7 +4,7 @@ * Author: Matthew McClintock * Maintainer: Kumar Gala * - * Copyright 2005, 2008 Freescale Semiconductor Inc. + * Copyright 2005, 2008, 2010 Freescale Semiconductor Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -114,6 +114,27 @@ static void __booke_wdt_enable(void *data) mtspr(SPRN_TCR, val); } +/** + * booke_wdt_disable - disable the watchdog on the given CPU + * + * This function is called on each CPU. It disables the watchdog on that CPU. + * + * TCR[WRC] cannot be changed once it has been set to non-zero, but we can + * effectively disable the watchdog by setting its period to the maximum value. + */ +static void __booke_wdt_disable(void *data) +{ + u32 val; + + val = mfspr(SPRN_TCR); + val &= ~(TCR_WIE | WDTP_MASK); + mtspr(SPRN_TCR, val); + + /* clear status to make sure nothing is pending */ + __booke_wdt_ping(NULL); + +} + static ssize_t booke_wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { @@ -193,12 +214,21 @@ static int booke_wdt_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); } +static int booke_wdt_release(struct inode *inode, struct file *file) +{ + on_each_cpu(__booke_wdt_disable, NULL, 0); + booke_wdt_enabled = 0; + + return 0; +} + static const struct file_operations booke_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = booke_wdt_write, .unlocked_ioctl = booke_wdt_ioctl, .open = booke_wdt_open, + .release = booke_wdt_release, }; static struct miscdevice booke_wdt_miscdev = { @@ -237,4 +267,9 @@ static int __init booke_wdt_init(void) return ret; } -device_initcall(booke_wdt_init); + +module_init(booke_wdt_init); +module_exit(booke_wdt_exit); + +MODULE_DESCRIPTION("PowerPC Book-E watchdog driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.2 From e0dc09ff9a28f37441c5e92a14de6abda8db49d6 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 13 Oct 2010 14:19:36 -0500 Subject: powerpc/watchdog: Make default timeout for Book-E watchdog a Kconfig option The PowerPC Book-E watchdog driver (booke_wdt.c) defines a default timeout value in the code based on whether it's a Freescale Book-E part of not. Instead of having hard-coded values in the driver, make it a Kconfig option. As newer chips gets faster, the current default values become less appropriate, since the timeout sometimes occurs before the kernel finishes booting. Making the value a Kconfig option allows BSPs to configure a new value without requiring the wdt_period command-line parameter to be set. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala --- drivers/watchdog/Kconfig | 17 +++++++++++++++++ drivers/watchdog/booke_wdt.c | 8 +------- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index a6812eb31fa1..c356146bd712 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -966,6 +966,23 @@ config BOOKE_WDT Please see Documentation/watchdog/watchdog-api.txt for more information. +config BOOKE_WDT_DEFAULT_TIMEOUT + int "PowerPC Book-E Watchdog Timer Default Timeout" + depends on BOOKE_WDT + default 38 if FSL_BOOKE + range 0 63 if FSL_BOOKE + default 3 if !FSL_BOOKE + range 0 3 if !FSL_BOOKE + help + Select the default watchdog timer period to be used by the PowerPC + Book-E watchdog driver. A watchdog "event" occurs when the bit + position represented by this number transitions from zero to one. + + For Freescale Book-E processors, this is a number between 0 and 63. + For other Book-E processors, this is a number between 0 and 3. + + The value can be overidden by the wdt_period command-line parameter. + # PPC64 Architecture config WATCHDOG_RTAS diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index a9899981fd97..d11ffb091b0d 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -33,14 +33,8 @@ * occur, and the final time the board will reset. */ -#ifdef CONFIG_FSL_BOOKE -#define WDT_PERIOD_DEFAULT 38 /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */ -#else -#define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ -#endif /* for timing information */ - u32 booke_wdt_enabled; -u32 booke_wdt_period = WDT_PERIOD_DEFAULT; +u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT; #ifdef CONFIG_FSL_BOOKE #define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15)) -- cgit v1.2.2 From 6038f373a3dc1f1c26496e60b6c40b164716f07e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sun, 15 Aug 2010 18:52:59 +0200 Subject: llseek: automatically add .llseek fop All file_operations should get a .llseek operation so we can make nonseekable_open the default for future file operations without a .llseek pointer. The three cases that we can automatically detect are no_llseek, seq_lseek and default_llseek. For cases where we can we can automatically prove that the file offset is always ignored, we use noop_llseek, which maintains the current behavior of not returning an error from a seek. New drivers should normally not use noop_llseek but instead use no_llseek and call nonseekable_open at open time. Existing drivers can be converted to do the same when the maintainer knows for certain that no user code relies on calling seek on the device file. The generated code is often incorrectly indented and right now contains comments that clarify for each added line why a specific variant was chosen. In the version that gets submitted upstream, the comments will be gone and I will manually fix the indentation, because there does not seem to be a way to do that using coccinelle. Some amount of new code is currently sitting in linux-next that should get the same modifications, which I will do at the end of the merge window. Many thanks to Julia Lawall for helping me learn to write a semantic patch that does all this. ===== begin semantic patch ===== // This adds an llseek= method to all file operations, // as a preparation for making no_llseek the default. // // The rules are // - use no_llseek explicitly if we do nonseekable_open // - use seq_lseek for sequential files // - use default_llseek if we know we access f_pos // - use noop_llseek if we know we don't access f_pos, // but we still want to allow users to call lseek // @ open1 exists @ identifier nested_open; @@ nested_open(...) { <+... nonseekable_open(...) ...+> } @ open exists@ identifier open_f; identifier i, f; identifier open1.nested_open; @@ int open_f(struct inode *i, struct file *f) { <+... ( nonseekable_open(...) | nested_open(...) ) ...+> } @ read disable optional_qualifier exists @ identifier read_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; expression E; identifier func; @@ ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off) { <+... ( *off = E | *off += E | func(..., off, ...) | E = *off ) ...+> } @ read_no_fpos disable optional_qualifier exists @ identifier read_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; @@ ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off) { ... when != off } @ write @ identifier write_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; expression E; identifier func; @@ ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off) { <+... ( *off = E | *off += E | func(..., off, ...) | E = *off ) ...+> } @ write_no_fpos @ identifier write_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; @@ ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off) { ... when != off } @ fops0 @ identifier fops; @@ struct file_operations fops = { ... }; @ has_llseek depends on fops0 @ identifier fops0.fops; identifier llseek_f; @@ struct file_operations fops = { ... .llseek = llseek_f, ... }; @ has_read depends on fops0 @ identifier fops0.fops; identifier read_f; @@ struct file_operations fops = { ... .read = read_f, ... }; @ has_write depends on fops0 @ identifier fops0.fops; identifier write_f; @@ struct file_operations fops = { ... .write = write_f, ... }; @ has_open depends on fops0 @ identifier fops0.fops; identifier open_f; @@ struct file_operations fops = { ... .open = open_f, ... }; // use no_llseek if we call nonseekable_open //////////////////////////////////////////// @ nonseekable1 depends on !has_llseek && has_open @ identifier fops0.fops; identifier nso ~= "nonseekable_open"; @@ struct file_operations fops = { ... .open = nso, ... +.llseek = no_llseek, /* nonseekable */ }; @ nonseekable2 depends on !has_llseek @ identifier fops0.fops; identifier open.open_f; @@ struct file_operations fops = { ... .open = open_f, ... +.llseek = no_llseek, /* open uses nonseekable */ }; // use seq_lseek for sequential files ///////////////////////////////////// @ seq depends on !has_llseek @ identifier fops0.fops; identifier sr ~= "seq_read"; @@ struct file_operations fops = { ... .read = sr, ... +.llseek = seq_lseek, /* we have seq_read */ }; // use default_llseek if there is a readdir /////////////////////////////////////////// @ fops1 depends on !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier readdir_e; @@ // any other fop is used that changes pos struct file_operations fops = { ... .readdir = readdir_e, ... +.llseek = default_llseek, /* readdir is present */ }; // use default_llseek if at least one of read/write touches f_pos ///////////////////////////////////////////////////////////////// @ fops2 depends on !fops1 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read.read_f; @@ // read fops use offset struct file_operations fops = { ... .read = read_f, ... +.llseek = default_llseek, /* read accesses f_pos */ }; @ fops3 depends on !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier write.write_f; @@ // write fops use offset struct file_operations fops = { ... .write = write_f, ... + .llseek = default_llseek, /* write accesses f_pos */ }; // Use noop_llseek if neither read nor write accesses f_pos /////////////////////////////////////////////////////////// @ fops4 depends on !fops1 && !fops2 && !fops3 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read_no_fpos.read_f; identifier write_no_fpos.write_f; @@ // write fops use offset struct file_operations fops = { ... .write = write_f, .read = read_f, ... +.llseek = noop_llseek, /* read and write both use no f_pos */ }; @ depends on has_write && !has_read && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier write_no_fpos.write_f; @@ struct file_operations fops = { ... .write = write_f, ... +.llseek = noop_llseek, /* write uses no f_pos */ }; @ depends on has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read_no_fpos.read_f; @@ struct file_operations fops = { ... .read = read_f, ... +.llseek = noop_llseek, /* read uses no f_pos */ }; @ depends on !has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; @@ struct file_operations fops = { ... +.llseek = noop_llseek, /* no read or write fn */ }; ===== End semantic patch ===== Signed-off-by: Arnd Bergmann Cc: Julia Lawall Cc: Christoph Hellwig --- drivers/watchdog/ar7_wdt.c | 1 + drivers/watchdog/cpwd.c | 1 + drivers/watchdog/ep93xx_wdt.c | 1 + drivers/watchdog/omap_wdt.c | 1 + 4 files changed, 4 insertions(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index c764c52412e4..b29221783598 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c @@ -267,6 +267,7 @@ static const struct file_operations ar7_wdt_fops = { .unlocked_ioctl = ar7_wdt_ioctl, .open = ar7_wdt_open, .release = ar7_wdt_release, + .llseek = no_llseek, }; static struct miscdevice ar7_wdt_miscdev = { diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 566343b3c131..51ae4e84f4f9 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -524,6 +524,7 @@ static const struct file_operations cpwd_fops = { .write = cpwd_write, .read = cpwd_read, .release = cpwd_release, + .llseek = no_llseek, }; static int __devinit cpwd_probe(struct platform_device *op, diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index 59359c9a5e01..726b7df61fd0 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c @@ -188,6 +188,7 @@ static const struct file_operations ep93xx_wdt_fops = { .unlocked_ioctl = ep93xx_wdt_ioctl, .open = ep93xx_wdt_open, .release = ep93xx_wdt_release, + .llseek = no_llseek, }; static struct miscdevice ep93xx_wdt_miscdev = { diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 76b58abf4451..81e3d6100894 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -258,6 +258,7 @@ static const struct file_operations omap_wdt_fops = { .unlocked_ioctl = omap_wdt_ioctl, .open = omap_wdt_open, .release = omap_wdt_release, + .llseek = no_llseek, }; static int __devinit omap_wdt_probe(struct platform_device *pdev) -- cgit v1.2.2 From cad0df370048f7980d4cbc9e88b74db0d87cfc56 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Thu, 9 Sep 2010 09:58:03 -0700 Subject: watchdog: iTCO_wdt: TCO Watchdog patch for Intel Patsburg DeviceIDs This patch adds the Intel Patsburg (PCH) DeviceIDs for iTCO Watchdog. Signed-off-by: Seth Heasley Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 69de8713b8e4..cdc79450538d 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -146,6 +146,7 @@ enum iTCO_chipsets { TCO_CPT29, /* Cougar Point */ TCO_CPT30, /* Cougar Point */ TCO_CPT31, /* Cougar Point */ + TCO_PBG, /* Patsburg */ }; static struct { @@ -233,6 +234,7 @@ static struct { {"Cougar Point", 2}, {"Cougar Point", 2}, {"Cougar Point", 2}, + {"Patsburg", 2}, {NULL, 0} }; @@ -348,6 +350,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x1c5d, TCO_CPT29)}, { ITCO_PCI_DEVICE(0x1c5e, TCO_CPT30)}, { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)}, + { ITCO_PCI_DEVICE(0x1d40, TCO_PBG)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); -- cgit v1.2.2 From 641912f479962e50b29573a8c0e8c514eb02e9b8 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Fri, 6 Aug 2010 11:41:24 -0400 Subject: watchdog: iTCO_wdt: Cleanup warning messages The current iTCO_wdt driver warnings are confusing. Currently when the device driver returns an error the console contains: iTCO_vendor_support: vendor-support=0 iTCO_wdt: Intel TCO WatchDog Timer Driver v1.05 iTCO_wdt: failed to reset NO_REBOOT flag, reboot disabled by hardware iTCO_wdt: No card detected After the patch, iTCO_vendor_support: vendor-support=0 iTCO_wdt: Intel TCO WatchDog Timer Driver v1.05 iTCO_wdt: failed to reset NO_REBOOT flag, device disabled by hardware/BIOS Clean this up and use the word "device" to describe the device. Signed-off-by: Prarit Bhargava Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index cdc79450538d..bc69731a5e6a 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -377,7 +377,7 @@ static char expect_release; static struct { /* this is private data for the iTCO_wdt device */ /* TCO version/generation */ unsigned int iTCO_version; - /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ + /* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ unsigned long ACPIBASE; /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ unsigned long __iomem *gcs; @@ -470,7 +470,7 @@ static int iTCO_wdt_start(void) if (iTCO_wdt_unset_NO_REBOOT_bit()) { spin_unlock(&iTCO_wdt_private.io_lock); printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " - "reboot disabled by hardware\n"); + "reboot disabled by hardware/BIOS\n"); return -EIO; } @@ -784,7 +784,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, base_address &= 0x0000ff80; if (base_address == 0x00000000) { /* Something's wrong here, ACPIBASE has to be set */ - printk(KERN_ERR PFX "failed to get TCOBASE address\n"); + printk(KERN_ERR PFX "failed to get TCOBASE address, " + "device disabled by hardware/BIOS\n"); pci_dev_put(pdev); return -ENODEV; } @@ -800,7 +801,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, if (iTCO_wdt_private.iTCO_version == 2) { pci_read_config_dword(pdev, 0xf0, &base_address); if ((base_address & 1) == 0) { - printk(KERN_ERR PFX "RCBA is disabled by hardware\n"); + printk(KERN_ERR PFX "RCBA is disabled by hardware" + "/BIOS, device disabled\n"); ret = -ENODEV; goto out; } @@ -811,7 +813,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, /* Check chipset's NO_REBOOT bit */ if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, " - "platform may have disabled it\n"); + "device disabled by hardware/BIOS\n"); ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ goto out_unmap; } @@ -822,7 +824,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ if (!request_region(SMI_EN, 4, "iTCO_wdt")) { printk(KERN_ERR PFX - "I/O address 0x%04lx already in use\n", SMI_EN); + "I/O address 0x%04lx already in use, " + "device disabled\n", SMI_EN); ret = -EIO; goto out_unmap; } @@ -834,8 +837,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, /* The TCO I/O registers reside in a 32-byte range pointed to by the TCOBASE value */ if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) { - printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n", - TCOBASE); + printk(KERN_ERR PFX "I/O address 0x%04lx already in use " + "device disabled\n", TCOBASE); ret = -EIO; goto unreg_smi_en; } @@ -924,7 +927,7 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev) } if (!found) - printk(KERN_INFO PFX "No card detected\n"); + printk(KERN_INFO PFX "No device detected.\n"); return ret; } -- cgit v1.2.2 From a2b89cd85ed55029400521a93dde868ac7150b31 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 13 Sep 2010 21:23:59 -0700 Subject: watchdog: Use static const char * const where possible Signed-off-by: Joe Perches Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/machzwd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index 2d118cf022fc..edffe68e3d2f 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c @@ -388,7 +388,7 @@ static struct notifier_block zf_notifier = { static void __init zf_show_action(int act) { - char *str[] = { "RESET", "SMI", "NMI", "SCI" }; + static const char * const str[] = { "RESET", "SMI", "NMI", "SCI" }; printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]); } -- cgit v1.2.2 From ee3e96583e42dcb4bd406ce4e5f824bd5bb80013 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Tue, 14 Sep 2010 02:47:28 +0200 Subject: watchdog: it87_wdt: Add support for IT8720F watchdog This simple patch adds support for a watchdog in IT8720F Super IO chip to it87_wdt driver. Signed-off-by: Ondrej Zajicek Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/watchdog/Kconfig | 9 +++++---- drivers/watchdog/it87_wdt.c | 17 +++++++++++------ 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c356146bd712..cc53136122f9 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -565,10 +565,11 @@ config IT87_WDT tristate "IT87 Watchdog Timer" depends on X86 && EXPERIMENTAL ---help--- - This is the driver for the hardware watchdog on the ITE IT8716, - IT8718, IT8726, IT8712(Version J,K) Super I/O chips. 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. + This is the driver for the hardware watchdog on the ITE + IT8716, IT8718, IT8720, IT8726, IT8712(Version J,K) Super I/O + chips. 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. To compile this driver as a module, choose M here: the module will be called it87_wdt. diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index b709b3b2d1ef..455de7714618 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -12,7 +12,7 @@ * http://www.ite.com.tw/ * * Support of the watchdog timers, which are available on - * IT8716, IT8718, IT8726 and IT8712 (J,K version). + * IT8716, IT8718, IT8720, IT8726 and IT8712 (J,K version). * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -45,7 +45,7 @@ #include -#define WATCHDOG_VERSION "1.12" +#define WATCHDOG_VERSION "1.13" #define WATCHDOG_NAME "IT87 WDT" #define PFX WATCHDOG_NAME ": " #define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" @@ -80,6 +80,7 @@ #define IT8712_ID 0x8712 #define IT8716_ID 0x8716 #define IT8718_ID 0x8718 +#define IT8720_ID 0x8720 #define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ /* GPIO Configuration Registers LDN=0x07 */ @@ -92,7 +93,7 @@ #define WDT_CIRINT 0x80 #define WDT_MOUSEINT 0x40 #define WDT_KYBINT 0x20 -#define WDT_GAMEPORT 0x10 /* not it8718 */ +#define WDT_GAMEPORT 0x10 /* not in it8718, it8720 */ #define WDT_FORCE 0x02 #define WDT_ZERO 0x01 @@ -529,6 +530,7 @@ static struct notifier_block wdt_notifier = { static int __init it87_wdt_init(void) { int rc = 0; + int try_gameport = !nogameport; u16 chip_type; u8 chip_rev; unsigned long flags; @@ -542,9 +544,12 @@ static int __init it87_wdt_init(void) switch (chip_type) { case IT8716_ID: - case IT8718_ID: case IT8726_ID: break; + case IT8718_ID: + case IT8720_ID: + try_gameport = 0; + break; case IT8712_ID: if (chip_rev > 7) break; @@ -571,7 +576,7 @@ static int __init it87_wdt_init(void) superio_outb(0x00, WDTCTRL); /* First try to get Gameport support */ - if (chip_type != IT8718_ID && !nogameport) { + if (try_gameport) { superio_select(GAMEPORT); base = superio_inw(BASEREG); if (!base) { @@ -676,7 +681,7 @@ err_out_region: spin_unlock_irqrestore(&spinlock, flags); } err_out: - if (chip_type != IT8718_ID && !nogameport) { + if (try_gameport) { spin_lock_irqsave(&spinlock, flags); superio_enter(); superio_select(GAMEPORT); -- cgit v1.2.2 From dfb0b8eae1f78c7d0cf7c8abe6c84ff8cefde50e Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Tue, 14 Sep 2010 02:54:16 +0200 Subject: watchdog: it87_wdt: Add support for watchdogs with 8b timers This patch adds support for watchdogs with 8b timers, like ones in IT8702F and older revisions of IT8712F Super IO chip, to it87_wdt driver. This patch should be used after the patch 'it87_wdt: Add support for IT8720F watchdog'. Signed-off-by: Ondrej Zajicek Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/watchdog/Kconfig | 10 +++--- drivers/watchdog/it87_wdt.c | 81 ++++++++++++++++++++++++++++++++------------- 2 files changed, 63 insertions(+), 28 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index cc53136122f9..5a5c024482fa 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -565,11 +565,11 @@ config IT87_WDT tristate "IT87 Watchdog Timer" depends on X86 && EXPERIMENTAL ---help--- - This is the driver for the hardware watchdog on the ITE - IT8716, IT8718, IT8720, IT8726, IT8712(Version J,K) Super I/O - chips. 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. + This is the driver for the hardware watchdog on the ITE IT8702, + IT8712, IT8716, IT8718, IT8720, IT8726, IT8712 Super I/O chips. + 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. To compile this driver as a module, choose M here: the module will be called it87_wdt. diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index 455de7714618..dad29245a6a7 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -12,7 +12,7 @@ * http://www.ite.com.tw/ * * Support of the watchdog timers, which are available on - * IT8716, IT8718, IT8720, IT8726 and IT8712 (J,K version). + * IT8702, IT8712, IT8716, IT8718, IT8720 and IT8726. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -76,6 +76,7 @@ /* Chip Id numbers */ #define NO_DEV_ID 0xffff +#define IT8702_ID 0x8702 #define IT8705_ID 0x8705 #define IT8712_ID 0x8712 #define IT8716_ID 0x8716 @@ -133,7 +134,7 @@ #define WDTS_USE_GP 4 #define WDTS_EXPECTED 5 -static unsigned int base, gpact, ciract; +static unsigned int base, gpact, ciract, max_units; static unsigned long wdt_status; static DEFINE_SPINLOCK(spinlock); @@ -211,6 +212,33 @@ static inline void superio_outw(int val, int reg) outb(val, VAL); } +/* Internal function, should be called after superio_select(GPIO) */ +static void wdt_update_timeout(void) +{ + unsigned char cfg = WDT_KRST | WDT_PWROK; + int tm = timeout; + + if (testmode) + cfg = 0; + + if (tm <= max_units) + cfg |= WDT_TOV1; + else + tm /= 60; + + superio_outb(cfg, WDTCFG); + superio_outb(tm, WDTVALLSB); + if (max_units > 255) + superio_outb(tm>>8, WDTVALMSB); +} + +static int wdt_round_time(int t) +{ + t += 59; + t -= t % 60; + return t; +} + /* watchdog timer handling */ static void wdt_keepalive(void) @@ -235,12 +263,7 @@ static void wdt_start(void) superio_outb(WDT_GAMEPORT, WDTCTRL); else superio_outb(WDT_CIRINT, WDTCTRL); - if (!testmode) - superio_outb(WDT_TOV1 | WDT_KRST | WDT_PWROK, WDTCFG); - else - superio_outb(WDT_TOV1, WDTCFG); - superio_outb(timeout>>8, WDTVALMSB); - superio_outb(timeout, WDTVALLSB); + wdt_update_timeout(); superio_exit(); spin_unlock_irqrestore(&spinlock, flags); @@ -256,8 +279,9 @@ static void wdt_stop(void) superio_select(GPIO); superio_outb(0x00, WDTCTRL); superio_outb(WDT_TOV1, WDTCFG); - superio_outb(0x00, WDTVALMSB); superio_outb(0x00, WDTVALLSB); + if (max_units > 255) + superio_outb(0x00, WDTVALMSB); superio_exit(); spin_unlock_irqrestore(&spinlock, flags); @@ -267,8 +291,8 @@ static void wdt_stop(void) * wdt_set_timeout - set a new timeout value with watchdog ioctl * @t: timeout value in seconds * - * The hardware device has a 16 bit watchdog timer, thus the - * timeout time ranges between 1 and 65535 seconds. + * The hardware device has a 8 or 16 bit watchdog timer (depends on + * chip version) that can be configured to count seconds or minutes. * * Used within WDIOC_SETTIMEOUT watchdog device ioctl. */ @@ -277,19 +301,19 @@ static int wdt_set_timeout(int t) { unsigned long flags; - if (t < 1 || t > 65535) + if (t < 1 || t > max_units * 60) return -EINVAL; - timeout = t; + if (t > max_units) + timeout = wdt_round_time(t); + else + timeout = t; spin_lock_irqsave(&spinlock, flags); if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { superio_enter(); - superio_select(GPIO); - superio_outb(t>>8, WDTVALMSB); - superio_outb(t, WDTVALLSB); - + wdt_update_timeout(); superio_exit(); } spin_unlock_irqrestore(&spinlock, flags); @@ -535,6 +559,8 @@ static int __init it87_wdt_init(void) u8 chip_rev; unsigned long flags; + wdt_status = 0; + spin_lock_irqsave(&spinlock, flags); superio_enter(); chip_type = superio_inw(CHIPID); @@ -543,16 +569,21 @@ static int __init it87_wdt_init(void) spin_unlock_irqrestore(&spinlock, flags); switch (chip_type) { + case IT8702_ID: + max_units = 255; + break; + case IT8712_ID: + max_units = (chip_rev < 8) ? 255 : 65535; + break; case IT8716_ID: case IT8726_ID: + max_units = 65535; break; case IT8718_ID: case IT8720_ID: + max_units = 65535; try_gameport = 0; break; - case IT8712_ID: - if (chip_rev > 7) - break; case IT8705_ID: printk(KERN_ERR PFX "Unsupported Chip found, Chip %04x Revision %02x\n", @@ -628,13 +659,16 @@ static int __init it87_wdt_init(void) spin_unlock_irqrestore(&spinlock, flags); } - if (timeout < 1 || timeout > 65535) { + if (timeout < 1 || timeout > max_units * 60) { timeout = DEFAULT_TIMEOUT; printk(KERN_WARNING PFX "Timeout value out of range, use default %d sec\n", DEFAULT_TIMEOUT); } + if (timeout > max_units) + timeout = wdt_round_time(timeout); + rc = register_reboot_notifier(&wdt_notifier); if (rc) { printk(KERN_ERR PFX @@ -661,7 +695,7 @@ static int __init it87_wdt_init(void) outb(0x09, CIR_IER(base)); } - printk(KERN_INFO PFX "Chip it%04x revision %d initialized. " + printk(KERN_INFO PFX "Chip IT%04x revision %d initialized. " "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d " "nogameport=%d)\n", chip_type, chip_rev, timeout, nowayout, testmode, exclusive, nogameport); @@ -703,8 +737,9 @@ static void __exit it87_wdt_exit(void) superio_select(GPIO); superio_outb(0x00, WDTCTRL); superio_outb(0x00, WDTCFG); - superio_outb(0x00, WDTVALMSB); superio_outb(0x00, WDTVALLSB); + if (max_units > 255) + superio_outb(0x00, WDTVALMSB); if (test_bit(WDTS_USE_GP, &wdt_status)) { superio_select(GAMEPORT); superio_outb(gpact, ACTREG); -- cgit v1.2.2 From f0fc10745a48c766ea5d6d83a6a371a223986bb0 Mon Sep 17 00:00:00 2001 From: Timo Juhani Lindfors Date: Thu, 30 Sep 2010 17:08:03 +0300 Subject: watchdog: it8712f_wdt: Add comments for config/control register names Signed-off-by: Timo Juhani Lindfors Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/it8712f_wdt.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index f52c162b1bea..b08fae65bb0e 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c @@ -75,15 +75,15 @@ static unsigned short address; #define WDT_CONFIG 0x72 /* WDT Register: Configuration */ #define WDT_TIMEOUT 0x73 /* WDT Register: Timeout Value */ -#define WDT_RESET_GAME 0x10 -#define WDT_RESET_KBD 0x20 -#define WDT_RESET_MOUSE 0x40 -#define WDT_RESET_CIR 0x80 +#define WDT_RESET_GAME 0x10 /* Reset timer on read or write to game port */ +#define WDT_RESET_KBD 0x20 /* Reset timer on keyboard interrupt */ +#define WDT_RESET_MOUSE 0x40 /* Reset timer on mouse interrupt */ +#define WDT_RESET_CIR 0x80 /* Reset timer on consumer IR interrupt */ #define WDT_UNIT_SEC 0x80 /* If 0 in MINUTES */ -#define WDT_OUT_PWROK 0x10 -#define WDT_OUT_KRST 0x40 +#define WDT_OUT_PWROK 0x10 /* Pulse PWROK on timeout */ +#define WDT_OUT_KRST 0x40 /* Pulse reset on timeout */ static int superio_inb(int reg) { -- cgit v1.2.2 From a422088db21333ba02a0f4fe4f5abfb08c802d35 Mon Sep 17 00:00:00 2001 From: Timo Juhani Lindfors Date: Thu, 30 Sep 2010 17:08:04 +0300 Subject: watchdog: it8712f_wdt: Add module parameter for alternative reset sources On iEi PCISA-9652-R10 (BIOS version 1.5) single board computer reads from the game port do not seem to reset the watchdog timer. This patch adds a module parameter wdt_config_reg to specify alternative reset sources. At least WDT_RESET_KBD has been tested, even just running while true; do setleds -L +scroll sleep 1 setleds -L -scroll sleep 1 done is enough to keep the watchdog happy. Signed-off-by: Timo Juhani Lindfors Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/it8712f_wdt.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index b08fae65bb0e..b32c6c045b1a 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c @@ -85,6 +85,14 @@ static unsigned short address; #define WDT_OUT_PWROK 0x10 /* Pulse PWROK on timeout */ #define WDT_OUT_KRST 0x40 /* Pulse reset on timeout */ +static int wdt_control_reg = WDT_RESET_GAME; +module_param(wdt_control_reg, int, 0); +MODULE_PARM_DESC(wdt_control_reg, "Value to write to watchdog control " + "register. The default WDT_RESET_GAME resets the timer on " + "game port reads that this driver generates. You can also " + "use KBD, MOUSE or CIR if you have some external way to " + "generate those interrupts."); + static int superio_inb(int reg) { outb(reg, REG); @@ -131,7 +139,8 @@ static inline void superio_exit(void) static inline void it8712f_wdt_ping(void) { - inb(address); + if (wdt_control_reg & WDT_RESET_GAME) + inb(address); } static void it8712f_wdt_update_margin(void) @@ -170,7 +179,7 @@ static void it8712f_wdt_enable(void) superio_enter(); superio_select(LDN_GPIO); - superio_outb(WDT_RESET_GAME, WDT_CONTROL); + superio_outb(wdt_control_reg, WDT_CONTROL); it8712f_wdt_update_margin(); -- cgit v1.2.2 From 29c3e8c8d16b74e91da9be445ff3e14136957753 Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Sat, 9 Oct 2010 14:19:46 +0200 Subject: watchdog: MachZ: fix debug macro Fix debug macro line wrapping. Signed-off-by: Nicolas Kaiser Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/machzwd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index edffe68e3d2f..928035069396 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c @@ -143,7 +143,7 @@ static unsigned long next_heartbeat; #ifndef ZF_DEBUG # define dprintk(format, args...) #else -# define dprintk(format, args...) printk(KERN_DEBUG PFX +# define dprintk(format, args...) printk(KERN_DEBUG PFX \ ":%s:%d: " format, __func__, __LINE__ , ## args) #endif -- cgit v1.2.2 From dee00abbbcab97b8ee3bbafb5e786dde83e26741 Mon Sep 17 00:00:00 2001 From: Giel van Schijndel Date: Mon, 4 Oct 2010 10:45:28 +0200 Subject: watchdog: f71808e_wdt: add support for the F71889FG Signed-off-by: Giel van Schijndel Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 4 ++-- drivers/watchdog/f71808e_wdt.c | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 5a5c024482fa..57b8a410697b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -409,11 +409,11 @@ config ALIM7101_WDT Most people will say N. config F71808E_WDT - tristate "Fintek F71808E and F71882FG Watchdog" + tristate "Fintek F71808E, F71882FG and F71889FG Watchdog" depends on X86 && EXPERIMENTAL help This is the driver for the hardware watchdog on the Fintek - F71808E and F71882FG Super I/O controllers. + F71808E, F71882FG and F71889FG Super I/O controllers. You can compile this driver directly into the kernel, or use it as a module. The module will be called f71808e_wdt. diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index 7e5c266cda48..65e579635dba 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c @@ -308,6 +308,12 @@ static int watchdog_start(void) superio_set_bit(watchdog.sioaddr, 0x29, 1); break; + case f71889fg: + /* set pin 40 to WDTRST# */ + superio_outb(watchdog.sioaddr, 0x2b, + superio_inb(watchdog.sioaddr, 0x2b) & 0xcf); + break; + default: /* * 'default' label to shut up the compiler and catch @@ -708,8 +714,10 @@ static int __init f71808e_find(int sioaddr) case SIO_F71882_ID: watchdog.type = f71882fg; break; - case SIO_F71862_ID: case SIO_F71889_ID: + watchdog.type = f71889fg; + break; + case SIO_F71862_ID: /* These have a watchdog, though it isn't implemented (yet). */ err = -ENOSYS; goto exit; -- cgit v1.2.2 From b63aa731cd9e3fed7694a99f9c233f5f4b244f03 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 28 Aug 2010 22:03:45 +0200 Subject: watchdog: add support for Broadcom BCM63xx built-in watchdog This patch adds support for the Broadcom BCM63xx SoC built-in watchdog, it uses one of the BCM63xx hardware timer id. Signed-off-by: Miguel Gaio Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 10 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/bcm63xx_wdt.c | 350 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 361 insertions(+) create mode 100644 drivers/watchdog/bcm63xx_wdt.c (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 57b8a410697b..4a291045ebac 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -917,6 +917,16 @@ config OCTEON_WDT from the first interrupt, it is then only poked when the device is written. +config BCM63XX_WDT + tristate "Broadcom BCM63xx hardware watchdog" + depends on BCM63XX + help + Watchdog driver for the built in watchdog hardware in Broadcom + BCM63xx SoC. + + To compile this driver as a loadable module, choose M here. + The module will be called bcm63xx_wdt. + # PARISC Architecture # POWERPC Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 8374503fcc6a..4b0ef386229d 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -109,6 +109,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o # MIPS Architecture obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o +obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o obj-$(CONFIG_INDYDOG) += indydog.o obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c new file mode 100644 index 000000000000..a1debc89356b --- /dev/null +++ b/drivers/watchdog/bcm63xx_wdt.c @@ -0,0 +1,350 @@ +/* + * Broadcom BCM63xx SoC watchdog driver + * + * Copyright (C) 2007, Miguel Gaio + * Copyright (C) 2008, Florian Fainelli + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define PFX KBUILD_MODNAME + +#define WDT_HZ 50000000 /* Fclk */ +#define WDT_DEFAULT_TIME 30 /* seconds */ +#define WDT_MAX_TIME 256 /* seconds */ + +static struct { + void __iomem *regs; + struct timer_list timer; + int default_ticks; + unsigned long inuse; + atomic_t ticks; +} bcm63xx_wdt_device; + +static int expect_close; + +static int wdt_time = WDT_DEFAULT_TIME; +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +/* HW functions */ +static void bcm63xx_wdt_hw_start(void) +{ + bcm_writel(0xfffffffe, bcm63xx_wdt_device.regs + WDT_DEFVAL_REG); + bcm_writel(WDT_START_1, bcm63xx_wdt_device.regs + WDT_CTL_REG); + bcm_writel(WDT_START_2, bcm63xx_wdt_device.regs + WDT_CTL_REG); +} + +static void bcm63xx_wdt_hw_stop(void) +{ + bcm_writel(WDT_STOP_1, bcm63xx_wdt_device.regs + WDT_CTL_REG); + bcm_writel(WDT_STOP_2, bcm63xx_wdt_device.regs + WDT_CTL_REG); +} + +static void bcm63xx_wdt_isr(void *data) +{ + struct pt_regs *regs = get_irq_regs(); + + die(PFX " fire", regs); +} + +static void bcm63xx_timer_tick(unsigned long unused) +{ + if (!atomic_dec_and_test(&bcm63xx_wdt_device.ticks)) { + bcm63xx_wdt_hw_start(); + mod_timer(&bcm63xx_wdt_device.timer, jiffies + HZ); + } else + printk(KERN_CRIT PFX ": watchdog will restart system\n"); +} + +static void bcm63xx_wdt_pet(void) +{ + atomic_set(&bcm63xx_wdt_device.ticks, wdt_time); +} + +static void bcm63xx_wdt_start(void) +{ + bcm63xx_wdt_pet(); + bcm63xx_timer_tick(0); +} + +static void bcm63xx_wdt_pause(void) +{ + del_timer_sync(&bcm63xx_wdt_device.timer); + bcm63xx_wdt_hw_stop(); +} + +static int bcm63xx_wdt_settimeout(int new_time) +{ + if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) + return -EINVAL; + + wdt_time = new_time; + + return 0; +} + +static int bcm63xx_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &bcm63xx_wdt_device.inuse)) + return -EBUSY; + + bcm63xx_wdt_start(); + return nonseekable_open(inode, file); +} + +static int bcm63xx_wdt_release(struct inode *inode, struct file *file) +{ + if (expect_close == 42) + bcm63xx_wdt_pause(); + else { + printk(KERN_CRIT PFX + ": Unexpected close, not stopping watchdog!\n"); + bcm63xx_wdt_start(); + } + clear_bit(0, &bcm63xx_wdt_device.inuse); + expect_close = 0; + return 0; +} + +static ssize_t bcm63xx_wdt_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + if (len) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + expect_close = 0; + + for (i = 0; i != len; i++) { + char c; + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + expect_close = 42; + } + } + bcm63xx_wdt_pet(); + } + return len; +} + +static struct watchdog_info bcm63xx_wdt_info = { + .identity = PFX, + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, +}; + + +static long bcm63xx_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int new_value, retval = -EINVAL; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &bcm63xx_wdt_info, + sizeof(bcm63xx_wdt_info)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_SETOPTIONS: + if (get_user(new_value, p)) + return -EFAULT; + + if (new_value & WDIOS_DISABLECARD) { + bcm63xx_wdt_pause(); + retval = 0; + } + if (new_value & WDIOS_ENABLECARD) { + bcm63xx_wdt_start(); + retval = 0; + } + + return retval; + + case WDIOC_KEEPALIVE: + bcm63xx_wdt_pet(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_value, p)) + return -EFAULT; + + if (bcm63xx_wdt_settimeout(new_value)) + return -EINVAL; + + bcm63xx_wdt_pet(); + + case WDIOC_GETTIMEOUT: + return put_user(wdt_time, p); + + default: + return -ENOTTY; + + } +} + +static int bcm63xx_wdt_notify_sys(struct notifier_block *this, + unsigned long code, void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + bcm63xx_wdt_pause(); + return NOTIFY_DONE; +} + +static const struct file_operations bcm63xx_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = bcm63xx_wdt_write, + .unlocked_ioctl = bcm63xx_wdt_ioctl, + .open = bcm63xx_wdt_open, + .release = bcm63xx_wdt_release, +}; + +static struct miscdevice bcm63xx_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &bcm63xx_wdt_fops, +}; + +static struct notifier_block bcm63xx_wdt_notifier = { + .notifier_call = bcm63xx_wdt_notify_sys, +}; + + +static int bcm63xx_wdt_probe(struct platform_device *pdev) +{ + int ret; + struct resource *r; + + setup_timer(&bcm63xx_wdt_device.timer, bcm63xx_timer_tick, 0L); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "failed to get resources\n"); + return -ENODEV; + } + + bcm63xx_wdt_device.regs = ioremap_nocache(r->start, r->end - r->start); + if (!bcm63xx_wdt_device.regs) { + dev_err(&pdev->dev, "failed to remap I/O resources\n"); + return -ENXIO; + } + + ret = bcm63xx_timer_register(TIMER_WDT_ID, bcm63xx_wdt_isr, NULL); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register wdt timer isr\n"); + goto unmap; + } + + if (bcm63xx_wdt_settimeout(wdt_time)) { + bcm63xx_wdt_settimeout(WDT_DEFAULT_TIME); + dev_info(&pdev->dev, + ": wdt_time value must be 1 <= wdt_time <= 256, using %d\n", + wdt_time); + } + + ret = register_reboot_notifier(&bcm63xx_wdt_notifier); + if (ret) { + dev_err(&pdev->dev, "failed to register reboot_notifier\n"); + goto unregister_timer; + } + + ret = misc_register(&bcm63xx_wdt_miscdev); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register watchdog device\n"); + goto unregister_reboot_notifier; + } + + dev_info(&pdev->dev, " started, timer margin: %d sec\n", + WDT_DEFAULT_TIME); + + return 0; + +unregister_reboot_notifier: + unregister_reboot_notifier(&bcm63xx_wdt_notifier); +unregister_timer: + bcm63xx_timer_unregister(TIMER_WDT_ID); +unmap: + iounmap(bcm63xx_wdt_device.regs); + return ret; +} + +static int bcm63xx_wdt_remove(struct platform_device *pdev) +{ + if (!nowayout) + bcm63xx_wdt_pause(); + + misc_deregister(&bcm63xx_wdt_miscdev); + + iounmap(bcm63xx_wdt_device.regs); + + unregister_reboot_notifier(&bcm63xx_wdt_notifier); + bcm63xx_timer_unregister(TIMER_WDT_ID); + + return 0; +} + +static struct platform_driver bcm63xx_wdt = { + .probe = bcm63xx_wdt_probe, + .remove = bcm63xx_wdt_remove, + .driver = { + .name = "bcm63xx-wdt", + } +}; + +static int __init bcm63xx_wdt_init(void) +{ + return platform_driver_register(&bcm63xx_wdt); +} + +static void __exit bcm63xx_wdt_exit(void) +{ + platform_driver_unregister(&bcm63xx_wdt); +} + +module_init(bcm63xx_wdt_init); +module_exit(bcm63xx_wdt_exit); + +MODULE_AUTHOR("Miguel Gaio "); +MODULE_AUTHOR("Florian Fainelli "); +MODULE_DESCRIPTION("Driver for the Broadcom BCM63xx SoC watchdog"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS("platform:bcm63xx-wdt"); -- cgit v1.2.2 From ad1d3a26cdb9a0eaa0bf8351a000df0f256b0baa Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Wed, 27 Oct 2010 09:50:22 -0400 Subject: watchdog: iTCO_wdt.c: remove extra pci_dev_put()'s from init code The iTCO_wdt driver erroneously releases the pci_dev, and causes PCI hotremove to fail because of an incorrect usage count. The probe for this driver does a for_each_pci_dev() which gets a reference for a pci_dev when iTCO_wdt_init() is successful. The for_each_pci_dev() loop puts a reference for a pci_dev when iTCO_wdt_init() fails, so the iTCO_wdt_init() does not need to do any pci_dev_put()'s. The only pci_dev_put() that is required is in the iTCO_wdt_cleanup() function. Signed-off-by: Prarit Bhargava Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index bc69731a5e6a..f7e90fe47b71 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -786,7 +786,6 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, /* Something's wrong here, ACPIBASE has to be set */ printk(KERN_ERR PFX "failed to get TCOBASE address, " "device disabled by hardware/BIOS\n"); - pci_dev_put(pdev); return -ENODEV; } iTCO_wdt_private.iTCO_version = @@ -886,7 +885,6 @@ out_unmap: if (iTCO_wdt_private.iTCO_version == 2) iounmap(iTCO_wdt_private.gcs); out: - pci_dev_put(iTCO_wdt_private.pdev); iTCO_wdt_private.ACPIBASE = 0; return ret; } -- cgit v1.2.2 From 468ffde46d429fbd291b0ef43a06afe9c837629f Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 7 Oct 2010 16:03:52 -0700 Subject: WATCHDOG: octeon-wdt: Use I/O clock rate for timing calculations. The creation of the I/O clock domain requires some adjustments. Since the watchdog counters are clocked by the I/O clock, use its rate for timing calculations. Signed-off-by: David Daney Cc: Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org Patchwork: http://patchwork.linux-mips.org/patch/1659/ Acked-by: Wim Van Sebroeck Signed-off-by: Ralf Baechle --- drivers/watchdog/octeon-wdt-main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 909923800a02..945ee8300306 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c @@ -478,7 +478,7 @@ static void octeon_wdt_calc_parameters(int t) countdown_reset = periods > 2 ? periods - 2 : 0; heartbeat = t; - timeout_cnt = ((octeon_get_clock_rate() >> 8) * timeout_sec) >> 8; + timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8; } static int octeon_wdt_set_heartbeat(int t) @@ -677,7 +677,7 @@ static int __init octeon_wdt_init(void) max_timeout_sec = 6; do { max_timeout_sec--; - timeout_cnt = ((octeon_get_clock_rate() >> 8) * max_timeout_sec) >> 8; + timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * max_timeout_sec) >> 8; } while (timeout_cnt > 65535); BUG_ON(timeout_cnt == 0); -- cgit v1.2.2 From 072b198a4ad48bd722ec6d203d65422a4698eae7 Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Fri, 12 Nov 2010 11:22:24 -0500 Subject: x86, nmi_watchdog: Remove all stub function calls from old nmi_watchdog Now that the bulk of the old nmi_watchdog is gone, remove all the stub variables and hooks associated with it. This touches lots of files mainly because of how the io_apic nmi_watchdog was implemented. Now that the io_apic nmi_watchdog is forever gone, remove all its fingers. Most of this code was not being exercised by virtue of nmi_watchdog != NMI_IO_APIC, so there shouldn't be anything to risky here. Signed-off-by: Don Zickus Cc: fweisbec@gmail.com Cc: gorcunov@openvz.org LKML-Reference: <1289578944-28564-3-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar --- drivers/watchdog/hpwdt.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 3d77116e4634..c19f4a20794a 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -649,12 +649,7 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) * If nmi_watchdog is turned off then we can turn on * our nmi decoding capability. */ - if (!nmi_watchdog_active()) - hpwdt_nmi_decoding = 1; - else - dev_warn(&dev->dev, "NMI decoding is disabled. To enable this " - "functionality you must reboot with nmi_watchdog=0 " - "and load the hpwdt driver with priority=1.\n"); + hpwdt_nmi_decoding = 1; } #else static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) -- cgit v1.2.2 From c54fb811745967732bc9e31d837e0c9925e12b4b Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Wed, 17 Nov 2010 12:15:08 -0700 Subject: watchdog: iTCO_wdt: TCO Watchdog patch for Intel Patsburg PCH This patch adds an additional LPC Controller DeviceID for the Intel Patsburg PCH for TCO Watchdog. Signed-off-by: Seth Heasley Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index f7e90fe47b71..b8838d2c67a6 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -32,6 +32,7 @@ * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) * document number 320066-003, 320257-008: EP80597 (IICH) * document number TBD : Cougar Point (CPT) + * document number TBD : Patsburg (PBG) */ /* @@ -146,7 +147,8 @@ enum iTCO_chipsets { TCO_CPT29, /* Cougar Point */ TCO_CPT30, /* Cougar Point */ TCO_CPT31, /* Cougar Point */ - TCO_PBG, /* Patsburg */ + TCO_PBG1, /* Patsburg */ + TCO_PBG2, /* Patsburg */ }; static struct { @@ -235,6 +237,7 @@ static struct { {"Cougar Point", 2}, {"Cougar Point", 2}, {"Patsburg", 2}, + {"Patsburg", 2}, {NULL, 0} }; @@ -350,7 +353,8 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x1c5d, TCO_CPT29)}, { ITCO_PCI_DEVICE(0x1c5e, TCO_CPT30)}, { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)}, - { ITCO_PCI_DEVICE(0x1d40, TCO_PBG)}, + { ITCO_PCI_DEVICE(0x1d40, TCO_PBG1)}, + { ITCO_PCI_DEVICE(0x1d41, TCO_PBG2)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); -- cgit v1.2.2 From e6c3b699b2f6fcba7036c079b6f16bf9556c7f0d Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 23 Oct 2010 20:59:42 +0000 Subject: watchdog: bcm63xx_wdt: improve platform part. * fix devinit and devexit sections * fix platform removal code so that the iounmap happens after the removal of the timer. * changes the reboot_notifier by a platform shutdown method. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/bcm63xx_wdt.c | 42 ++++++++++++------------------------------ 1 file changed, 12 insertions(+), 30 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c index a1debc89356b..3c5045a206dd 100644 --- a/drivers/watchdog/bcm63xx_wdt.c +++ b/drivers/watchdog/bcm63xx_wdt.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -220,14 +219,6 @@ static long bcm63xx_wdt_ioctl(struct file *file, unsigned int cmd, } } -static int bcm63xx_wdt_notify_sys(struct notifier_block *this, - unsigned long code, void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) - bcm63xx_wdt_pause(); - return NOTIFY_DONE; -} - static const struct file_operations bcm63xx_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -243,12 +234,8 @@ static struct miscdevice bcm63xx_wdt_miscdev = { .fops = &bcm63xx_wdt_fops, }; -static struct notifier_block bcm63xx_wdt_notifier = { - .notifier_call = bcm63xx_wdt_notify_sys, -}; - -static int bcm63xx_wdt_probe(struct platform_device *pdev) +static int __devinit bcm63xx_wdt_probe(struct platform_device *pdev) { int ret; struct resource *r; @@ -280,16 +267,10 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev) wdt_time); } - ret = register_reboot_notifier(&bcm63xx_wdt_notifier); - if (ret) { - dev_err(&pdev->dev, "failed to register reboot_notifier\n"); - goto unregister_timer; - } - ret = misc_register(&bcm63xx_wdt_miscdev); if (ret < 0) { dev_err(&pdev->dev, "failed to register watchdog device\n"); - goto unregister_reboot_notifier; + goto unregister_timer; } dev_info(&pdev->dev, " started, timer margin: %d sec\n", @@ -297,8 +278,6 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev) return 0; -unregister_reboot_notifier: - unregister_reboot_notifier(&bcm63xx_wdt_notifier); unregister_timer: bcm63xx_timer_unregister(TIMER_WDT_ID); unmap: @@ -306,25 +285,28 @@ unmap: return ret; } -static int bcm63xx_wdt_remove(struct platform_device *pdev) +static int __devexit bcm63xx_wdt_remove(struct platform_device *pdev) { if (!nowayout) bcm63xx_wdt_pause(); misc_deregister(&bcm63xx_wdt_miscdev); - - iounmap(bcm63xx_wdt_device.regs); - - unregister_reboot_notifier(&bcm63xx_wdt_notifier); bcm63xx_timer_unregister(TIMER_WDT_ID); - + iounmap(bcm63xx_wdt_device.regs); return 0; } +static void bcm63xx_wdt_shutdown(struct platform_device *pdev) +{ + bcm63xx_wdt_pause(); +} + static struct platform_driver bcm63xx_wdt = { .probe = bcm63xx_wdt_probe, - .remove = bcm63xx_wdt_remove, + .remove = __devexit_p(bcm63xx_wdt_remove), + .shutdown = bcm63xx_wdt_shutdown, .driver = { + .owner = THIS_MODULE, .name = "bcm63xx-wdt", } }; -- cgit v1.2.2 From f6e0722fc3a35ff818c86ffbc414f7592a8119cf Mon Sep 17 00:00:00 2001 From: Wolfram Sang & Martyn Welch Date: Thu, 2 Dec 2010 00:11:16 +0100 Subject: watchdog: gef_wdt: include fs.h Add missing include "linux/fs.h". This fixes compile failure. Signed-off-by: Wolfram Sang Signed-off-by: Martyn Welch Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/gef_wdt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 9c21d19043a6..f6bd6f10fcec 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.2 From 4fc3680894ff5739e7474b6633e962bfbdf0d3d8 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Thu, 2 Dec 2010 14:03:29 +0000 Subject: watchdog: it8712f_wdt: add note to Kconfig On some motherboards the it8712f watchdog does not work unless the game port was enabled. see Bug 13140. We therefor add a note to Kconfig. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 4a291045ebac..a5ad77ef4266 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -558,6 +558,9 @@ config IT8712F_WDT This is the driver for the built-in watchdog timer on the IT8712F Super I/0 chipset used on many motherboards. + If the driver does not work, then make sure that the game port in + the BIOS is enabled. + To compile this driver as a module, choose M here: the module will be called it8712f_wdt. -- cgit v1.2.2 From 2c1f4672f0711e7f23ae49cbb7541088126fe576 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 7 Dec 2010 14:16:04 -0200 Subject: watchdog: imx: use clk_get to acquire the watchdog clock Use clk_get to acquire the watchdog clock and also avoid hardcoding the clock name. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer --- drivers/watchdog/imx2_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index 2ee7dac55a3c..86f7cac1026c 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -270,7 +270,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) return -ENOMEM; } - imx2_wdt.clk = clk_get_sys("imx-wdt.0", NULL); + imx2_wdt.clk = clk_get(&pdev->dev, NULL); if (IS_ERR(imx2_wdt.clk)) { dev_err(&pdev->dev, "can't get Watchdog clock\n"); return PTR_ERR(imx2_wdt.clk); -- cgit v1.2.2 From 3b3c1f24e96c411a95daabb6af9e09c5381f713b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 26 Nov 2010 10:39:55 +0100 Subject: watchdog: Fix null pointer dereference while accessing rdc321x platform_data rdc321x-wdt currently fetches its driver specific data by using the platform_device->platform_data pointer, this is wrong because the mfd device which registers our platform_device has been added using mfd_add_device() which sets the platform_device->driver_data pointer instead. Signed-off-by: Florian Fainelli CC: stable@kernel.org Signed-off-by: Samuel Ortiz --- drivers/watchdog/rdc321x_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 428f8a1583e8..3939e53f5f98 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c @@ -231,7 +231,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) struct resource *r; struct rdc321x_wdt_pdata *pdata; - pdata = pdev->dev.platform_data; + pdata = platform_get_drvdata(pdev); if (!pdata) { dev_err(&pdev->dev, "no platform data supplied\n"); return -ENODEV; -- cgit v1.2.2 From 4a7863cc2eb5f9804f1c4e9156619a801cd7f14f Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Wed, 22 Dec 2010 14:00:03 -0500 Subject: x86, nmi_watchdog: Remove ARCH_HAS_NMI_WATCHDOG and rely on CONFIG_HARDLOCKUP_DETECTOR The x86 arch has shifted its use of the nmi_watchdog from a local implementation to the global one provide by kernel/watchdog.c. This shift has caused a whole bunch of compile problems under different config options. I attempt to simplify things with the patch below. In order to simplify things, I had to come to terms with the meaning of two terms ARCH_HAS_NMI_WATCHDOG and CONFIG_HARDLOCKUP_DETECTOR. Basically they mean the same thing, the former on a local level and the latter on a global level. With the old x86 nmi watchdog gone, there is no need to rely on defining the ARCH_HAS_NMI_WATCHDOG variable because it doesn't make sense any more. x86 will now use the global implementation. The changes below do a few things. First it changes the few places that relied on ARCH_HAS_NMI_WATCHDOG to use CONFIG_X86_LOCAL_APIC (the former was an alias for the latter anyway, so nothing unusual here). Those pieces of code were relying more on local apic functionality the nmi watchdog functionality, so the change should make sense. Second, I removed the x86 implementation of touch_nmi_watchdog(). It isn't need now, instead x86 will rely on kernel/watchdog.c's implementation. Third, I removed the #define ARCH_HAS_NMI_WATCHDOG itself from x86. And tweaked the include/linux/nmi.h file to tell users to look for an externally defined touch_nmi_watchdog in the case of ARCH_HAS_NMI_WATCHDOG _or_ CONFIG_HARDLOCKUP_DETECTOR. This changes removes some of the ugliness in that file. Finally, I added a Kconfig dependency for CONFIG_HARDLOCKUP_DETECTOR that said you can't have ARCH_HAS_NMI_WATCHDOG _and_ CONFIG_HARDLOCKUP_DETECTOR. You can only have one nmi_watchdog. Tested with ARCH=i386: allnoconfig, defconfig, allyesconfig, (various broken configs) ARCH=x86_64: allnoconfig, defconfig, allyesconfig, (various broken configs) Hopefully, after this patch I won't get any more compile broken emails. :-) v3: changed a couple of 'linux/nmi.h' -> 'asm/nmi.h' to pick-up correct function prototypes when CONFIG_HARDLOCKUP_DETECTOR is not set. Signed-off-by: Don Zickus Cc: Peter Zijlstra Cc: fweisbec@gmail.com LKML-Reference: <1293044403-14117-1-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar --- drivers/watchdog/hpwdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index c19f4a20794a..dea7b5bf6e2c 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -642,7 +642,7 @@ static struct notifier_block die_notifier = { */ #ifdef CONFIG_HPWDT_NMI_DECODING -#ifdef ARCH_HAS_NMI_WATCHDOG +#ifdef CONFIG_X86_LOCAL_APIC static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) { /* @@ -657,7 +657,7 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) dev_warn(&dev->dev, "NMI decoding is disabled. " "Your kernel does not support a NMI Watchdog.\n"); } -#endif /* ARCH_HAS_NMI_WATCHDOG */ +#endif /* CONFIG_X86_LOCAL_APIC */ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) { -- cgit v1.2.2 From 673a6092ce5f5bec45619b7a7f89cfcf8bcf3c41 Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Thu, 6 Jan 2011 16:18:48 -0500 Subject: x86: Convert some devices to use DIE_NMIUNKNOWN They are a handful of places in the code that register a die_notifier as a catch all in case no claims the NMI. Unfortunately, they trigger on events like DIE_NMI and DIE_NMI_IPI, which depending on when they registered may collide with other handlers that have the ability to determine if the NMI is theirs or not. The function unknown_nmi_error() makes one last effort to walk the die_chain when no one else has claimed the NMI before spitting out messages that the NMI is unknown. This is a better spot for these devices to execute any code without colliding with the other handlers. The two drivers modified are only compiled on x86 arches I believe, so they shouldn't be affected by other arches that may not have DIE_NMIUNKNOWN defined. Signed-off-by: Don Zickus Cc: Russ Anderson Cc: Corey Minyard Cc: openipmi-developer@lists.sourceforge.net Cc: dann frazier Signed-off-by: Peter Zijlstra LKML-Reference: <1294348732-15030-3-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar --- drivers/watchdog/hpwdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index dea7b5bf6e2c..24b966d5061a 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -469,7 +469,7 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, unsigned long rom_pl; static int die_nmi_called; - if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) + if (ulReason != DIE_NMIUNKNOWN) goto out; if (!hpwdt_nmi_decoding) -- cgit v1.2.2 From f9a9f096d25bbc54dc3147613ee1d86b35cce691 Mon Sep 17 00:00:00 2001 From: Lutz Ballaschke Date: Sun, 26 Sep 2010 16:38:20 +0200 Subject: watchdog: clean-up f71808e_wdt.c Cleaned up and replaced some magic numbers by constants. Signed-off-by: Lutz Ballaschke Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/f71808e_wdt.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index 65e579635dba..3c9142474d18 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c @@ -42,18 +42,19 @@ #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ #define SIO_REG_DEVREV 0x22 /* Device revision */ #define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ +#define SIO_REG_MFUNCT1 0x29 /* Multi function select 1 */ +#define SIO_REG_MFUNCT2 0x2a /* Multi function select 2 */ +#define SIO_REG_MFUNCT3 0x2b /* Multi function select 3 */ #define SIO_REG_ENABLE 0x30 /* Logical device enable */ #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ -#define SIO_F71808_ID 0x0901 /* Chipset ID */ -#define SIO_F71858_ID 0x0507 /* Chipset ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ +#define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ #define SIO_F71889_ID 0x0723 /* Chipset ID */ -#define F71882FG_REG_START 0x01 - #define F71808FG_REG_WDO_CONF 0xf0 #define F71808FG_REG_WDT_CONF 0xf5 #define F71808FG_REG_WD_TIME 0xf6 @@ -76,7 +77,7 @@ module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); static const int max_timeout = WATCHDOG_MAX_TIMEOUT; -static int timeout = 60; /* default timeout in seconds */ +static int timeout = WATCHDOG_TIMEOUT; /* default timeout in seconds */ module_param(timeout, int, 0); MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=" @@ -299,19 +300,19 @@ static int watchdog_start(void) switch (watchdog.type) { case f71808fg: /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */ - superio_clear_bit(watchdog.sioaddr, 0x2a, 3); - superio_clear_bit(watchdog.sioaddr, 0x2b, 3); + superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT2, 3); + superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 3); break; case f71882fg: /* Set pin 56 to WDTRST# */ - superio_set_bit(watchdog.sioaddr, 0x29, 1); + superio_set_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 1); break; case f71889fg: /* set pin 40 to WDTRST# */ - superio_outb(watchdog.sioaddr, 0x2b, - superio_inb(watchdog.sioaddr, 0x2b) & 0xcf); + superio_outb(watchdog.sioaddr, SIO_REG_MFUNCT3, + superio_inb(watchdog.sioaddr, SIO_REG_MFUNCT3) & 0xcf); break; default: -- cgit v1.2.2 From 7977ff6e3deb042b29370e52607df20d1ee33b9d Mon Sep 17 00:00:00 2001 From: Lutz Ballaschke Date: Sun, 26 Sep 2010 16:25:35 +0200 Subject: watchdog: add f71862fg support Watchdog support for Fintek F71862fg Super-I/O added. Two different hardware reset pins of the F71862fg chip can be configured by an additional module parameter. Signed-off-by: Lutz Ballaschke Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/f71808e_wdt.c | 45 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index 3c9142474d18..f573948998b0 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c @@ -42,6 +42,7 @@ #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ #define SIO_REG_DEVREV 0x22 /* Device revision */ #define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ +#define SIO_REG_ROM_ADDR_SEL 0x27 /* ROM address select */ #define SIO_REG_MFUNCT1 0x29 /* Multi function select 1 */ #define SIO_REG_MFUNCT2 0x2a /* Multi function select 2 */ #define SIO_REG_MFUNCT3 0x2b /* Multi function select 3 */ @@ -71,6 +72,8 @@ #define WATCHDOG_MAX_TIMEOUT (60 * 255) #define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for watchdog signal */ +#define WATCHDOG_F71862FG_PIN 63 /* default watchdog reset output + pin number 63 */ static unsigned short force_id; module_param(force_id, ushort, 0); @@ -90,6 +93,12 @@ MODULE_PARM_DESC(pulse_width, "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); +static unsigned int f71862fg_pin = WATCHDOG_F71862FG_PIN; +module_param(f71862fg_pin, uint, 0); +MODULE_PARM_DESC(f71862fg_pin, + "Watchdog f71862fg reset output pin configuration. Choose pin 56 or 63" + " (default=" __MODULE_STRING(WATCHDOG_F71862FG_PIN)")"); + static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, bool, 0444); MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); @@ -283,6 +292,28 @@ exit_unlock: return err; } +static int f71862fg_pin_configure(unsigned short ioaddr) +{ + /* When ioaddr is non-zero the calling function has to take care of + mutex handling and superio preparation! */ + + if (f71862fg_pin == 63) { + if (ioaddr) { + /* SPI must be disabled first to use this pin! */ + superio_clear_bit(ioaddr, SIO_REG_ROM_ADDR_SEL, 6); + superio_set_bit(ioaddr, SIO_REG_MFUNCT3, 4); + } + } else if (f71862fg_pin == 56) { + if (ioaddr) + superio_set_bit(ioaddr, SIO_REG_MFUNCT1, 1); + } else { + printk(KERN_ERR DRVNAME ": Invalid argument f71862fg_pin=%d\n", + f71862fg_pin); + return -EINVAL; + } + return 0; +} + static int watchdog_start(void) { /* Make sure we don't die as soon as the watchdog is enabled below */ @@ -304,6 +335,12 @@ static int watchdog_start(void) superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 3); break; + case f71862fg: + err = f71862fg_pin_configure(watchdog.sioaddr); + if (err) + goto exit_superio; + break; + case f71882fg: /* Set pin 56 to WDTRST# */ superio_set_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 1); @@ -712,16 +749,16 @@ static int __init f71808e_find(int sioaddr) case SIO_F71808_ID: watchdog.type = f71808fg; break; + case SIO_F71862_ID: + watchdog.type = f71862fg; + err = f71862fg_pin_configure(0); /* validate module parameter */ + break; case SIO_F71882_ID: watchdog.type = f71882fg; break; case SIO_F71889_ID: watchdog.type = f71889fg; break; - case SIO_F71862_ID: - /* These have a watchdog, though it isn't implemented (yet). */ - err = -ENOSYS; - goto exit; case SIO_F71858_ID: /* Confirmed (by datasheet) not to have a watchdog. */ err = -ENODEV; -- cgit v1.2.2 From df278dac2070e677cf22c30e1c78c5a753191375 Mon Sep 17 00:00:00 2001 From: Michel Arboi Date: Mon, 6 Dec 2010 20:53:45 +0100 Subject: watchdog: f71808e_wdt: Add Fintek F71869 watchdog Add Fintek f71869 as a supported watchdog device. Signed-off-by: Michel Arboi Acked-by: Giel van Schijndel Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/f71808e_wdt.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index f573948998b0..d4d8d1fdccc4 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c @@ -53,6 +53,7 @@ #define SIO_F71808_ID 0x0901 /* Chipset ID */ #define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ +#define SIO_F71869_ID 0x0814 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ #define SIO_F71889_ID 0x0723 /* Chipset ID */ @@ -108,12 +109,13 @@ module_param(start_withtimeout, uint, 0); MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" " given initial timeout. Zero (default) disables this feature."); -enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg }; +enum chips { f71808fg, f71858fg, f71862fg, f71869, f71882fg, f71889fg }; static const char *f71808e_names[] = { "f71808fg", "f71858fg", "f71862fg", + "f71869", "f71882fg", "f71889fg", }; @@ -341,6 +343,11 @@ static int watchdog_start(void) goto exit_superio; break; + case f71869: + /* GPIO14 --> WDTRST# */ + superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 4); + break; + case f71882fg: /* Set pin 56 to WDTRST# */ superio_set_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 1); @@ -753,6 +760,9 @@ static int __init f71808e_find(int sioaddr) watchdog.type = f71862fg; err = f71862fg_pin_configure(0); /* validate module parameter */ break; + case SIO_F71869_ID: + watchdog.type = f71869; + break; case SIO_F71882_ID: watchdog.type = f71882fg; break; -- cgit v1.2.2 From 9c67bea419c384561eeb84bdf251d521a3234e45 Mon Sep 17 00:00:00 2001 From: Benny Loenstrup Ammitzboell Date: Thu, 11 Nov 2010 16:08:41 +0100 Subject: watchdog: Add watchdog support for W83627DHG chip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following adds watchdog support for the Winbond W83627DHG chip. I have tested it on a PQ7-M102XL (Intel Atom) board. Signed-off-by: Benny Lønstrup Ammitzbøll Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 9 +++++---- drivers/watchdog/w83627hf_wdt.c | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index a5ad77ef4266..8a3aa2f050c8 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -722,14 +722,15 @@ config SMSC37B787_WDT Most people will say N. config W83627HF_WDT - tristate "W83627HF Watchdog Timer" + tristate "W83627HF/W83627DHG Watchdog Timer" depends on X86 ---help--- This is the driver for the hardware watchdog on the W83627HF chipset as used in Advantech PC-9578 and Tyan S2721-533 motherboards - (and likely others). 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. + (and likely others). The driver also supports the W83627DHG chip. + 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. To compile this driver as a module, choose M here: the module will be called w83627hf_wdt. diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index 0f5288df0091..48f2e0148bb4 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c @@ -42,7 +42,7 @@ #include -#define WATCHDOG_NAME "w83627hf/thf/hg WDT" +#define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT" #define PFX WATCHDOG_NAME ": " #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ @@ -89,7 +89,7 @@ static void w83627hf_select_wd_register(void) c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ outb_p(0x2b, WDT_EFER); outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */ - } else if (c == 0x88) { /* W83627EHF */ + } else if (c == 0x88 || c == 0xa0) { /* W83627EHF / W83627DHG */ outb_p(0x2d, WDT_EFER); /* select GPIO5 */ c = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */ outb_p(0x2d, WDT_EFER); @@ -321,7 +321,7 @@ static int __init wdt_init(void) { int ret; - printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG Super I/O chip initialising.\n"); + printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising.\n"); if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); -- cgit v1.2.2 From 6d106e0cac842bc17c87aadd5fa01730694c987a Mon Sep 17 00:00:00 2001 From: Herman Morsink Vollenbroek Date: Mon, 6 Dec 2010 21:24:56 +0100 Subject: watchdog: Fix reboot on W83627ehf chipset. The watchdog driver for the SUPERIO chip winbond w83627ehf does not work. If you open /dev/watchdog and write a character to /dev/watchdog then the watchdog will be triggered. However the watchdog will not trigger the hardware RESET after the timeout, because the watchdog has never been enabled. Signed-off-by: Herman Morsink Vollenbroek Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/w83627hf_wdt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index 48f2e0148bb4..e5c91d4404ed 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c @@ -129,6 +129,8 @@ static void w83627hf_init(void) t = inb_p(WDT_EFDR); /* read CRF5 */ t &= ~0x0C; /* set second mode & disable keyboard turning off watchdog */ + t |= 0x02; /* enable the WDTO# output low pulse + to the KBRST# pin (PIN60) */ outb_p(t, WDT_EFDR); /* Write back to CRF5 */ outb_p(0xF7, WDT_EFER); /* Select CRF7 */ -- cgit v1.2.2 From 202af5b307b0ccdad5e960a1f87fac322d8cdb02 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 8 Dec 2010 01:27:35 +0900 Subject: watchdog: alim1535_wdt: fix compiler warning on ali_pci_tbl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Annotate ali_pci_tbl as '__used' to fix following warning: CC drivers/watchdog/alim1535_wdt.o drivers/watchdog/alim1535_wdt.c:304: warning: ‘ali_pci_tbl’ defined but not used Signed-off-by: Namhyung Kim Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/alim1535_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index 1e9caea8ff8a..fa4d36033552 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c @@ -301,7 +301,7 @@ static int ali_notify_sys(struct notifier_block *this, * want to register another driver on the same PCI id. */ -static struct pci_device_id ali_pci_tbl[] = { +static struct pci_device_id ali_pci_tbl[] __used = { { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,}, { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,}, { 0, }, -- cgit v1.2.2 From a787e71068d7c2e438d8a5a38a7e1385389819f0 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 8 Dec 2010 01:27:36 +0900 Subject: watchdog: alim7101_wdt: fix compiler warning on alim7101_pci_tbl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Annotate alim7101_pci_tbl as '__used' to fix following warning: CC drivers/watchdog/alim7101_wdt.o drivers/watchdog/alim7101_wdt.c:433: warning: ‘alim7101_pci_tbl’ defined but not used Signed-off-by: Namhyung Kim Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/alim7101_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index d8d4da9a483d..4b7a2b4138ed 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c @@ -430,7 +430,7 @@ err_out: module_init(alim7101_wdt_init); module_exit(alim7101_wdt_unload); -static struct pci_device_id alim7101_pci_tbl[] __devinitdata = { +static struct pci_device_id alim7101_pci_tbl[] __devinitdata __used = { { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) }, { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, { } -- cgit v1.2.2 From 5d63c13415db2819590bba975dd023eaa593ddc3 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 3 Dec 2010 10:51:43 -0600 Subject: watchdog: add CONFIG_WATCHDOG_NOWAYOUT support to PowerPC Book-E watchdog driver Normally, the watchdog is disabled when dev/watchdog is closed, but if CONFIG_WATCHDOG_NOWAYOUT is defined, then it means that the watchdog should remain enabled. So we should disable it only if CONFIG_WATCHDOG_NOWAYOUT is not defined. Also ensure that /dev/watchdog is only opened by one process at a time. That way, a second process can't accidentally disable the watchdog while the first process has it open. There shouldn't be any need for more than one process to open /dev/watchdog anyway. Signed-off-by: Timur Tabi Acked-by: Josh Boyer Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/booke_wdt.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index d11ffb091b0d..636e013e221e 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -193,8 +193,15 @@ static long booke_wdt_ioctl(struct file *file, return 0; } +/* wdt_is_active stores wether or not the /dev/watchdog device is opened */ +static unsigned long wdt_is_active; + static int booke_wdt_open(struct inode *inode, struct file *file) { + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &wdt_is_active)) + return -EBUSY; + spin_lock(&booke_wdt_lock); if (booke_wdt_enabled == 0) { booke_wdt_enabled = 1; @@ -210,8 +217,17 @@ static int booke_wdt_open(struct inode *inode, struct file *file) static int booke_wdt_release(struct inode *inode, struct file *file) { +#ifndef CONFIG_WATCHDOG_NOWAYOUT + /* Normally, the watchdog is disabled when /dev/watchdog is closed, but + * if CONFIG_WATCHDOG_NOWAYOUT is defined, then it means that the + * watchdog should remain enabled. So we disable it only if + * CONFIG_WATCHDOG_NOWAYOUT is not defined. + */ on_each_cpu(__booke_wdt_disable, NULL, 0); booke_wdt_enabled = 0; +#endif + + clear_bit(0, &wdt_is_active); return 0; } -- cgit v1.2.2 From 6ae98ed186cbe6909105c536c24419e52af8fc66 Mon Sep 17 00:00:00 2001 From: Randy Vinson Date: Mon, 6 Dec 2010 14:02:23 -0700 Subject: watchdog: Propagate Book E WDT period changes to all cores When the watchdog period is changed, it needs to be propagated to all cores in addition to the core that performed the change. Signed-off-by: Randy Vinson Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/booke_wdt.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index 636e013e221e..7e7ec9c35b6a 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -85,6 +85,22 @@ static unsigned int sec_to_period(unsigned int secs) return 0; } +static void __booke_wdt_set(void *data) +{ + u32 val; + + val = mfspr(SPRN_TCR); + val &= ~WDTP_MASK; + val |= WDTP(booke_wdt_period); + + mtspr(SPRN_TCR, val); +} + +static void booke_wdt_set(void) +{ + on_each_cpu(__booke_wdt_set, NULL, 0); +} + static void __booke_wdt_ping(void *data) { mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); @@ -181,8 +197,7 @@ static long booke_wdt_ioctl(struct file *file, #else booke_wdt_period = tmp; #endif - mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP_MASK) | - WDTP(booke_wdt_period)); + booke_wdt_set(); return 0; case WDIOC_GETTIMEOUT: return put_user(booke_wdt_period, p); -- cgit v1.2.2 From 568dba66ac307532b6703331df71c17373c17a4a Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Tue, 14 Dec 2010 16:29:31 +0100 Subject: watchdog: ks8695_wdt: include mach/hardware.h instead of mach/timex.h. ks8695_wdt needs KS8695_CLOCK_RATE, which is defined in mach/hardware.h, which is pulled in by the include of mach/timex.h, but the latter is going away, so just include mach/hardware.h directly. Signed-off-by: Yegor Yefremov Signed-off-by: Lennert Buytenhek Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/ks8695_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c index 2852bb2e3fd9..811471903e8a 100644 --- a/drivers/watchdog/ks8695_wdt.c +++ b/drivers/watchdog/ks8695_wdt.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #define WDT_DEFAULT_TIME 5 /* seconds */ -- cgit v1.2.2 From d38bd479a10d1981816061da0a8ba27384dc3c35 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Fri, 31 Dec 2010 14:10:45 +0000 Subject: watchdog: iTCO_wdt: TCO Watchdog patch for Intel NM10 DeviceIDs This patch adds the Intel NM10 DeviceIDs for iTCO Watchdog. Reported-by: Dan Weinlader Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index b8838d2c67a6..db164153239e 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -1,7 +1,7 @@ /* * intel TCO Watchdog Driver * - * (c) Copyright 2006-2009 Wim Van Sebroeck . + * (c) Copyright 2006-2010 Wim Van Sebroeck . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,6 +26,7 @@ * document number 301473-002, 301474-026: 82801F (ICH6) * document number 313082-001, 313075-006: 631xESB, 632xESB * document number 307013-003, 307014-024: 82801G (ICH7) + * document number 322896-001, 322897-001: NM10 * document number 313056-003, 313057-017: 82801H (ICH8) * document number 316972-004, 316973-012: 82801I (ICH9) * document number 319973-002, 319974-002: 82801J (ICH10) @@ -85,6 +86,7 @@ enum iTCO_chipsets { TCO_ICH7DH, /* ICH7DH */ TCO_ICH7M, /* ICH7-M & ICH7-U */ TCO_ICH7MDH, /* ICH7-M DH */ + TCO_NM10, /* NM10 */ TCO_ICH8, /* ICH8 & ICH8R */ TCO_ICH8DH, /* ICH8DH */ TCO_ICH8DO, /* ICH8DO */ @@ -174,6 +176,7 @@ static struct { {"ICH7DH", 2}, {"ICH7-M or ICH7-U", 2}, {"ICH7-M DH", 2}, + {"NM10", 2}, {"ICH8 or ICH8R", 2}, {"ICH8DH", 2}, {"ICH8DO", 2}, @@ -291,6 +294,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, + { ITCO_PCI_DEVICE(0x27bc, TCO_NM10)}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)}, -- cgit v1.2.2 From 203f8d893ed772ec8589cfd3c7d1af312643b703 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Fri, 7 Jan 2011 17:11:08 -0800 Subject: watchdog: iTCO_wdt: TCO Watchdog patch for Intel DH89xxCC PCH This patch adds the DeviceIDs for TCO Watchdog on the Intel DH89xxCC PCH. Signed-off-by: Seth Heasley Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index db164153239e..2c6c2b4ad8bf 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -32,8 +32,9 @@ * document number 319973-002, 319974-002: 82801J (ICH10) * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) * document number 320066-003, 320257-008: EP80597 (IICH) - * document number TBD : Cougar Point (CPT) + * document number 324645-001, 324646-001: Cougar Point (CPT) * document number TBD : Patsburg (PBG) + * document number TBD : DH89xxCC */ /* @@ -151,6 +152,7 @@ enum iTCO_chipsets { TCO_CPT31, /* Cougar Point */ TCO_PBG1, /* Patsburg */ TCO_PBG2, /* Patsburg */ + TCO_DH89XXCC, /* DH89xxCC */ }; static struct { @@ -241,6 +243,7 @@ static struct { {"Cougar Point", 2}, {"Patsburg", 2}, {"Patsburg", 2}, + {"DH89xxCC", 2}, {NULL, 0} }; @@ -359,6 +362,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)}, { ITCO_PCI_DEVICE(0x1d40, TCO_PBG1)}, { ITCO_PCI_DEVICE(0x1d41, TCO_PBG2)}, + { ITCO_PCI_DEVICE(0x2310, TCO_DH89XXCC)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); -- cgit v1.2.2 From e13752a1de02044bfda352cbc834e3c9541f148b Mon Sep 17 00:00:00 2001 From: Lutz Ballaschke Date: Wed, 12 Jan 2011 01:09:02 +0100 Subject: watchdog: f71808e_wdt: add F71862FG, F71869 to Kconfig Update Kconfig with the additional Fintek hardware that we support. Signed-off-by: Lutz Ballaschke Acked-by: Giel van Schijndel Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 8a3aa2f050c8..3c6607ddcd20 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -409,11 +409,11 @@ config ALIM7101_WDT Most people will say N. config F71808E_WDT - tristate "Fintek F71808E, F71882FG and F71889FG Watchdog" + tristate "Fintek F71808E, F71862FG, F71869, F71882FG and F71889FG Watchdog" depends on X86 && EXPERIMENTAL help This is the driver for the hardware watchdog on the Fintek - F71808E, F71882FG and F71889FG Super I/O controllers. + F71808E, F71862FG, F71869, F71882FG and F71889FG Super I/O controllers. You can compile this driver directly into the kernel, or use it as a module. The module will be called f71808e_wdt. -- cgit v1.2.2 From 15e28bf130081a574192fb934b832ac7d07739f7 Mon Sep 17 00:00:00 2001 From: Priyanka Gupta Date: Mon, 25 Oct 2010 17:58:04 -0700 Subject: watchdog: Add support for sp5100 chipset TCO This driver adds /dev/watchdog support for the AMD sp5100 aka SB7x0 chipsets. It follows the same conventions found in other /dev/watchdog drivers. Signed-off-by: Priyanka Gupta Signed-off-by: Mike Waychison Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 11 + drivers/watchdog/Makefile | 1 + drivers/watchdog/sp5100_tco.c | 480 ++++++++++++++++++++++++++++++++++++++++++ drivers/watchdog/sp5100_tco.h | 41 ++++ 4 files changed, 533 insertions(+) create mode 100644 drivers/watchdog/sp5100_tco.c create mode 100644 drivers/watchdog/sp5100_tco.h (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 3c6607ddcd20..c48faa5ade73 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -418,6 +418,17 @@ config F71808E_WDT You can compile this driver directly into the kernel, or use it as a module. The module will be called f71808e_wdt. +config SP5100_TCO + tristate "AMD/ATI SP5100 TCO Timer/Watchdog" + depends on X86 && PCI + ---help--- + Hardware watchdog driver for the AMD/ATI SP5100 chipset. The TCO + (Total Cost of Ownership) timer is a watchdog timer that will reboot + the machine after its expiration. The expiration time can be + configured with the "heartbeat" parameter. + + To compile this driver as a module, choose M here: the + module will be called sp5100_tco. config GEODE_WDT tristate "AMD Geode CS5535/CS5536 Watchdog" diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 4b0ef386229d..12e6c1e32671 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o +obj-$(CONFIG_SP5100_TCO) += sp5100_tco.o obj-$(CONFIG_GEODE_WDT) += geodewdt.o obj-$(CONFIG_SC520_WDT) += sc520_wdt.o obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c new file mode 100644 index 000000000000..808372883e88 --- /dev/null +++ b/drivers/watchdog/sp5100_tco.c @@ -0,0 +1,480 @@ +/* + * sp5100_tco : TCO timer driver for sp5100 chipsets + * + * (c) Copyright 2009 Google Inc., All Rights Reserved. + * + * Based on i8xx_tco.c: + * (c) Copyright 2000 kernel concepts , All Rights + * Reserved. + * http://www.kernelconcepts.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * See AMD Publication 43009 "AMD SB700/710/750 Register Reference Guide" + */ + +/* + * Includes, defines, variables, module parameters, ... + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sp5100_tco.h" + +/* Module and version information */ +#define TCO_VERSION "0.01" +#define TCO_MODULE_NAME "SP5100 TCO timer" +#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION +#define PFX TCO_MODULE_NAME ": " + +/* internal variables */ +static void __iomem *tcobase; +static unsigned int pm_iobase; +static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */ +static unsigned long timer_alive; +static char tco_expect_close; +static struct pci_dev *sp5100_tco_pci; + +/* the watchdog platform device */ +static struct platform_device *sp5100_tco_platform_device; + +/* module parameters */ + +#define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat. */ +static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default=" + __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started" + " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +/* + * Some TCO specific functions + */ +static void tco_timer_start(void) +{ + u32 val; + unsigned long flags; + + spin_lock_irqsave(&tco_lock, flags); + val = readl(SP5100_WDT_CONTROL(tcobase)); + val |= SP5100_WDT_START_STOP_BIT; + writel(val, SP5100_WDT_CONTROL(tcobase)); + spin_unlock_irqrestore(&tco_lock, flags); +} + +static void tco_timer_stop(void) +{ + u32 val; + unsigned long flags; + + spin_lock_irqsave(&tco_lock, flags); + val = readl(SP5100_WDT_CONTROL(tcobase)); + val &= ~SP5100_WDT_START_STOP_BIT; + writel(val, SP5100_WDT_CONTROL(tcobase)); + spin_unlock_irqrestore(&tco_lock, flags); +} + +static void tco_timer_keepalive(void) +{ + u32 val; + unsigned long flags; + + spin_lock_irqsave(&tco_lock, flags); + val = readl(SP5100_WDT_CONTROL(tcobase)); + val |= SP5100_WDT_TRIGGER_BIT; + writel(val, SP5100_WDT_CONTROL(tcobase)); + spin_unlock_irqrestore(&tco_lock, flags); +} + +static int tco_timer_set_heartbeat(int t) +{ + unsigned long flags; + + if (t < 0 || t > 0xffff) + return -EINVAL; + + /* Write new heartbeat to watchdog */ + spin_lock_irqsave(&tco_lock, flags); + writel(t, SP5100_WDT_COUNT(tcobase)); + spin_unlock_irqrestore(&tco_lock, flags); + + heartbeat = t; + return 0; +} + +/* + * /dev/watchdog handling + */ + +static int sp5100_tco_open(struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &timer_alive)) + return -EBUSY; + + /* Reload and activate timer */ + tco_timer_start(); + tco_timer_keepalive(); + return nonseekable_open(inode, file); +} + +static int sp5100_tco_release(struct inode *inode, struct file *file) +{ + /* Shut off the timer. */ + if (tco_expect_close == 42) { + tco_timer_stop(); + } else { + printk(KERN_CRIT PFX + "Unexpected close, not stopping watchdog!\n"); + tco_timer_keepalive(); + } + clear_bit(0, &timer_alive); + tco_expect_close = 0; + return 0; +} + +static ssize_t sp5100_tco_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* note: just in case someone wrote the magic character + * five months ago... */ + tco_expect_close = 0; + + /* scan to see whether or not we got the magic character + */ + for (i = 0; i != len; i++) { + char c; + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + tco_expect_close = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + tco_timer_keepalive(); + } + return len; +} + +static long sp5100_tco_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int new_options, retval = -EINVAL; + int new_heartbeat; + void __user *argp = (void __user *)arg; + int __user *p = argp; + static const struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = TCO_MODULE_NAME, + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, + sizeof(ident)) ? -EFAULT : 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + case WDIOC_SETOPTIONS: + if (get_user(new_options, p)) + return -EFAULT; + if (new_options & WDIOS_DISABLECARD) { + tco_timer_stop(); + retval = 0; + } + if (new_options & WDIOS_ENABLECARD) { + tco_timer_start(); + tco_timer_keepalive(); + retval = 0; + } + return retval; + case WDIOC_KEEPALIVE: + tco_timer_keepalive(); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_heartbeat, p)) + return -EFAULT; + if (tco_timer_set_heartbeat(new_heartbeat)) + return -EINVAL; + tco_timer_keepalive(); + /* Fall through */ + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, p); + default: + return -ENOTTY; + } +} + +/* + * Kernel Interfaces + */ + +static const struct file_operations sp5100_tco_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = sp5100_tco_write, + .unlocked_ioctl = sp5100_tco_ioctl, + .open = sp5100_tco_open, + .release = sp5100_tco_release, +}; + +static struct miscdevice sp5100_tco_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &sp5100_tco_fops, +}; + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might + * want to register another driver on the same PCI id. + */ +static struct pci_device_id sp5100_tco_pci_tbl[] = { + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID, + PCI_ANY_ID, }, + { 0, }, /* End of list */ +}; +MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl); + +/* + * Init & exit routines + */ + +static unsigned char __devinit sp5100_tco_setupdevice(void) +{ + struct pci_dev *dev = NULL; + u32 val; + + /* Match the PCI device */ + for_each_pci_dev(dev) { + if (pci_match_id(sp5100_tco_pci_tbl, dev) != NULL) { + sp5100_tco_pci = dev; + break; + } + } + + if (!sp5100_tco_pci) + return 0; + + /* Request the IO ports used by this driver */ + pm_iobase = SP5100_IO_PM_INDEX_REG; + if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) { + printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", + pm_iobase); + goto exit; + } + + /* Find the watchdog base address. */ + outb(SP5100_PM_WATCHDOG_BASE3, SP5100_IO_PM_INDEX_REG); + val = inb(SP5100_IO_PM_DATA_REG); + outb(SP5100_PM_WATCHDOG_BASE2, SP5100_IO_PM_INDEX_REG); + val = val << 8 | inb(SP5100_IO_PM_DATA_REG); + outb(SP5100_PM_WATCHDOG_BASE1, SP5100_IO_PM_INDEX_REG); + val = val << 8 | inb(SP5100_IO_PM_DATA_REG); + outb(SP5100_PM_WATCHDOG_BASE0, SP5100_IO_PM_INDEX_REG); + /* Low three bits of BASE0 are reserved. */ + val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8); + + tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE); + if (tcobase == 0) { + printk(KERN_ERR PFX "failed to get tcobase address\n"); + goto unreg_region; + } + + /* Enable watchdog decode bit */ + pci_read_config_dword(sp5100_tco_pci, + SP5100_PCI_WATCHDOG_MISC_REG, + &val); + + val |= SP5100_PCI_WATCHDOG_DECODE_EN; + + pci_write_config_dword(sp5100_tco_pci, + SP5100_PCI_WATCHDOG_MISC_REG, + val); + + /* Enable Watchdog timer and set the resolution to 1 sec. */ + outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG); + val = inb(SP5100_IO_PM_DATA_REG); + val |= SP5100_PM_WATCHDOG_SECOND_RES; + val &= ~SP5100_PM_WATCHDOG_DISABLE; + outb(val, SP5100_IO_PM_DATA_REG); + + /* Check that the watchdog action is set to reset the system. */ + val = readl(SP5100_WDT_CONTROL(tcobase)); + val &= ~SP5100_PM_WATCHDOG_ACTION_RESET; + writel(val, SP5100_WDT_CONTROL(tcobase)); + + /* Set a reasonable heartbeat before we stop the timer */ + tco_timer_set_heartbeat(heartbeat); + + /* + * Stop the TCO before we change anything so we don't race with + * a zeroed timer. + */ + tco_timer_stop(); + + /* Done */ + return 1; + + iounmap(tcobase); +unreg_region: + release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); +exit: + return 0; +} + +static int __devinit sp5100_tco_init(struct platform_device *dev) +{ + int ret; + u32 val; + + /* Check whether or not the hardware watchdog is there. If found, then + * set it up. + */ + if (!sp5100_tco_setupdevice()) + return -ENODEV; + + /* Check to see if last reboot was due to watchdog timeout */ + printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n", + readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ? + "" : "not "); + + /* Clear out the old status */ + val = readl(SP5100_WDT_CONTROL(tcobase)); + val &= ~SP5100_PM_WATCHDOG_FIRED; + writel(val, SP5100_WDT_CONTROL(tcobase)); + + /* + * Check that the heartbeat value is within it's range. + * If not, reset to the default. + */ + if (tco_timer_set_heartbeat(heartbeat)) { + heartbeat = WATCHDOG_HEARTBEAT; + tco_timer_set_heartbeat(heartbeat); + } + + ret = misc_register(&sp5100_tco_miscdev); + if (ret != 0) { + printk(KERN_ERR PFX "cannot register miscdev on minor=" + "%d (err=%d)\n", + WATCHDOG_MINOR, ret); + goto exit; + } + + clear_bit(0, &timer_alive); + + printk(KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec" + " (nowayout=%d)\n", + tcobase, heartbeat, nowayout); + + return 0; + +exit: + iounmap(tcobase); + release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); + return ret; +} + +static void __devexit sp5100_tco_cleanup(void) +{ + /* Stop the timer before we leave */ + if (!nowayout) + tco_timer_stop(); + + /* Deregister */ + misc_deregister(&sp5100_tco_miscdev); + iounmap(tcobase); + release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); +} + +static int __devexit sp5100_tco_remove(struct platform_device *dev) +{ + if (tcobase) + sp5100_tco_cleanup(); + return 0; +} + +static void sp5100_tco_shutdown(struct platform_device *dev) +{ + tco_timer_stop(); +} + +static struct platform_driver sp5100_tco_driver = { + .probe = sp5100_tco_init, + .remove = __devexit_p(sp5100_tco_remove), + .shutdown = sp5100_tco_shutdown, + .driver = { + .owner = THIS_MODULE, + .name = TCO_MODULE_NAME, + }, +}; + +static int __init sp5100_tco_init_module(void) +{ + int err; + + printk(KERN_INFO PFX "SP5100 TCO WatchDog Timer Driver v%s\n", + TCO_VERSION); + + err = platform_driver_register(&sp5100_tco_driver); + if (err) + return err; + + sp5100_tco_platform_device = platform_device_register_simple( + TCO_MODULE_NAME, -1, NULL, 0); + if (IS_ERR(sp5100_tco_platform_device)) { + err = PTR_ERR(sp5100_tco_platform_device); + goto unreg_platform_driver; + } + + return 0; + +unreg_platform_driver: + platform_driver_unregister(&sp5100_tco_driver); + return err; +} + +static void __exit sp5100_tco_cleanup_module(void) +{ + platform_device_unregister(sp5100_tco_platform_device); + platform_driver_unregister(&sp5100_tco_driver); + printk(KERN_INFO PFX "SP5100 TCO Watchdog Module Unloaded.\n"); +} + +module_init(sp5100_tco_init_module); +module_exit(sp5100_tco_cleanup_module); + +MODULE_AUTHOR("Priyanka Gupta"); +MODULE_DESCRIPTION("TCO timer driver for SP5100 chipset"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/sp5100_tco.h b/drivers/watchdog/sp5100_tco.h new file mode 100644 index 000000000000..a5a16cc90a34 --- /dev/null +++ b/drivers/watchdog/sp5100_tco.h @@ -0,0 +1,41 @@ +/* + * sp5100_tco: TCO timer driver for sp5100 chipsets. + * + * (c) Copyright 2009 Google Inc., All Rights Reserved. + * + * TCO timer driver for sp5100 chipsets + */ + +/* + * Some address definitions for the Watchdog + */ + +#define SP5100_WDT_MEM_MAP_SIZE 0x08 +#define SP5100_WDT_CONTROL(base) ((base) + 0x00) /* Watchdog Control */ +#define SP5100_WDT_COUNT(base) ((base) + 0x04) /* Watchdog Count */ + +#define SP5100_WDT_START_STOP_BIT 1 +#define SP5100_WDT_TRIGGER_BIT (1 << 7) + +#define SP5100_PCI_WATCHDOG_MISC_REG 0x41 +#define SP5100_PCI_WATCHDOG_DECODE_EN (1 << 3) + +#define SP5100_PM_IOPORTS_SIZE 0x02 + +/* These two IO registers are hardcoded and there doesn't seem to be a way to + * read them from a register. + */ +#define SP5100_IO_PM_INDEX_REG 0xCD6 +#define SP5100_IO_PM_DATA_REG 0xCD7 + +#define SP5100_PM_WATCHDOG_CONTROL 0x69 +#define SP5100_PM_WATCHDOG_BASE0 0x6C +#define SP5100_PM_WATCHDOG_BASE1 0x6D +#define SP5100_PM_WATCHDOG_BASE2 0x6E +#define SP5100_PM_WATCHDOG_BASE3 0x6F + +#define SP5100_PM_WATCHDOG_FIRED (1 << 1) +#define SP5100_PM_WATCHDOG_ACTION_RESET (1 << 2) + +#define SP5100_PM_WATCHDOG_DISABLE 1 +#define SP5100_PM_WATCHDOG_SECOND_RES (3 << 1) -- cgit v1.2.2 From 456c730153fe33134fe93742510a96e46a9217c4 Mon Sep 17 00:00:00 2001 From: Mike Waychison Date: Mon, 25 Oct 2010 17:58:05 -0700 Subject: watchdog: Add TCO support for nVidia chipsets This driver adds support for /dev/watchdog for boards using either the MCP51 or MCP55 chipsets. These are also known as the nForce 430 and nForce 550. This driver is likely to work on other chipsets as well, though those are the only two that have been tested. Signed-off-by: Mike Waychison Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 18 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/nv_tco.c | 512 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/watchdog/nv_tco.h | 64 ++++++ 4 files changed, 595 insertions(+) create mode 100644 drivers/watchdog/nv_tco.c create mode 100644 drivers/watchdog/nv_tco.h (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c48faa5ade73..db00fa9f6979 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -642,6 +642,24 @@ config PC87413_WDT Most people will say N. +config NV_TCO + tristate "nVidia TCO Timer/Watchdog" + depends on X86 && PCI + ---help--- + Hardware driver for the TCO timer built into the nVidia Hub family + (such as the MCP51). The TCO (Total Cost of Ownership) timer is a + watchdog timer that will reboot the machine after its second + expiration. The expiration time can be configured with the + "heartbeat" parameter. + + On some motherboards the driver may fail to reset the chipset's + NO_REBOOT flag which prevents the watchdog from rebooting the + machine. If this is the case you will get a kernel message like + "failed to reset NO_REBOOT flag, reboot disabled by hardware". + + To compile this driver as a module, choose M here: the + module will be called nv_tco. + config RDC321X_WDT tristate "RDC R-321x SoC watchdog" depends on X86_RDC321X diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 12e6c1e32671..cd77f5492f95 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -87,6 +87,7 @@ obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o +obj-$(CONFIG_NV_TCO) += nv_tco.o obj-$(CONFIG_RDC321X_WDT) += rdc321x_wdt.o obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o obj-$(CONFIG_SBC8360_WDT) += sbc8360.o diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c new file mode 100644 index 000000000000..1a50aa7079bf --- /dev/null +++ b/drivers/watchdog/nv_tco.c @@ -0,0 +1,512 @@ +/* + * nv_tco 0.01: TCO timer driver for NV chipsets + * + * (c) Copyright 2005 Google Inc., All Rights Reserved. + * + * Based off i8xx_tco.c: + * (c) Copyright 2000 kernel concepts , All Rights + * Reserved. + * http://www.kernelconcepts.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * TCO timer driver for NV chipsets + * based on softdog.c by Alan Cox + */ + +/* + * Includes, defines, variables, module parameters, ... + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nv_tco.h" + +/* Module and version information */ +#define TCO_VERSION "0.01" +#define TCO_MODULE_NAME "NV_TCO" +#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION +#define PFX TCO_MODULE_NAME ": " + +/* internal variables */ +static unsigned int tcobase; +static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */ +static unsigned long timer_alive; +static char tco_expect_close; +static struct pci_dev *tco_pci; + +/* the watchdog platform device */ +static struct platform_device *nv_tco_platform_device; + +/* module parameters */ +#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (2 t, so if t > 0x3f, so is + * tmrval=seconds_to_ticks(t). Check that the count in seconds isn't + * out of range on it's own (to avoid overflow in tmrval). + */ + if (t < 0 || t > 0x3f) + return -EINVAL; + tmrval = seconds_to_ticks(t); + + /* "Values of 0h-3h are ignored and should not be attempted" */ + if (tmrval > 0x3f || tmrval < 0x04) + return -EINVAL; + + /* Write new heartbeat to watchdog */ + spin_lock_irqsave(&tco_lock, flags); + val = inb(TCO_TMR(tcobase)); + val &= 0xc0; + val |= tmrval; + outb(val, TCO_TMR(tcobase)); + val = inb(TCO_TMR(tcobase)); + + if ((val & 0x3f) != tmrval) + ret = -EINVAL; + spin_unlock_irqrestore(&tco_lock, flags); + + if (ret) + return ret; + + heartbeat = t; + return 0; +} + +/* + * /dev/watchdog handling + */ + +static int nv_tco_open(struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &timer_alive)) + return -EBUSY; + + /* Reload and activate timer */ + tco_timer_keepalive(); + tco_timer_start(); + return nonseekable_open(inode, file); +} + +static int nv_tco_release(struct inode *inode, struct file *file) +{ + /* Shut off the timer */ + if (tco_expect_close == 42) { + tco_timer_stop(); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping " + "watchdog!\n"); + tco_timer_keepalive(); + } + clear_bit(0, &timer_alive); + tco_expect_close = 0; + return 0; +} + +static ssize_t nv_tco_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* + * note: just in case someone wrote the magic character + * five months ago... + */ + tco_expect_close = 0; + + /* + * scan to see whether or not we got the magic + * character + */ + for (i = 0; i != len; i++) { + char c; + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + tco_expect_close = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + tco_timer_keepalive(); + } + return len; +} + +static long nv_tco_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int new_options, retval = -EINVAL; + int new_heartbeat; + void __user *argp = (void __user *)arg; + int __user *p = argp; + static const struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = TCO_MODULE_NAME, + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + case WDIOC_SETOPTIONS: + if (get_user(new_options, p)) + return -EFAULT; + if (new_options & WDIOS_DISABLECARD) { + tco_timer_stop(); + retval = 0; + } + if (new_options & WDIOS_ENABLECARD) { + tco_timer_keepalive(); + tco_timer_start(); + retval = 0; + } + return retval; + case WDIOC_KEEPALIVE: + tco_timer_keepalive(); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_heartbeat, p)) + return -EFAULT; + if (tco_timer_set_heartbeat(new_heartbeat)) + return -EINVAL; + tco_timer_keepalive(); + /* Fall through */ + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, p); + default: + return -ENOTTY; + } +} + +/* + * Kernel Interfaces + */ + +static const struct file_operations nv_tco_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = nv_tco_write, + .unlocked_ioctl = nv_tco_ioctl, + .open = nv_tco_open, + .release = nv_tco_release, +}; + +static struct miscdevice nv_tco_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &nv_tco_fops, +}; + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static struct pci_device_id tco_pci_tbl[] = { + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS, + PCI_ANY_ID, PCI_ANY_ID, }, + { 0, }, /* End of list */ +}; +MODULE_DEVICE_TABLE(pci, tco_pci_tbl); + +/* + * Init & exit routines + */ + +static unsigned char __init nv_tco_getdevice(void) +{ + struct pci_dev *dev = NULL; + u32 val; + + /* Find the PCI device */ + for_each_pci_dev(dev) { + if (pci_match_id(tco_pci_tbl, dev) != NULL) { + tco_pci = dev; + break; + } + } + + if (!tco_pci) + return 0; + + /* Find the base io port */ + pci_read_config_dword(tco_pci, 0x64, &val); + val &= 0xffff; + if (val == 0x0001 || val == 0x0000) { + /* Something is wrong here, bar isn't setup */ + printk(KERN_ERR PFX "failed to get tcobase address\n"); + return 0; + } + val &= 0xff00; + tcobase = val + 0x40; + + if (!request_region(tcobase, 0x10, "NV TCO")) { + printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", + tcobase); + return 0; + } + + /* Set a reasonable heartbeat before we stop the timer */ + tco_timer_set_heartbeat(30); + + /* + * Stop the TCO before we change anything so we don't race with + * a zeroed timer. + */ + tco_timer_keepalive(); + tco_timer_stop(); + + /* Disable SMI caused by TCO */ + if (!request_region(MCP51_SMI_EN(tcobase), 4, "NV TCO")) { + printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", + MCP51_SMI_EN(tcobase)); + goto out; + } + val = inl(MCP51_SMI_EN(tcobase)); + val &= ~MCP51_SMI_EN_TCO; + outl(val, MCP51_SMI_EN(tcobase)); + val = inl(MCP51_SMI_EN(tcobase)); + release_region(MCP51_SMI_EN(tcobase), 4); + if (val & MCP51_SMI_EN_TCO) { + printk(KERN_ERR PFX "Could not disable SMI caused by TCO\n"); + goto out; + } + + /* Check chipset's NO_REBOOT bit */ + pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val); + val |= MCP51_SMBUS_SETUP_B_TCO_REBOOT; + pci_write_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, val); + pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val); + if (!(val & MCP51_SMBUS_SETUP_B_TCO_REBOOT)) { + printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot " + "disabled by hardware\n"); + goto out; + } + + return 1; +out: + release_region(tcobase, 0x10); + return 0; +} + +static int __devinit nv_tco_init(struct platform_device *dev) +{ + int ret; + + /* Check whether or not the hardware watchdog is there */ + if (!nv_tco_getdevice()) + return -ENODEV; + + /* Check to see if last reboot was due to watchdog timeout */ + printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n", + inl(TCO_STS(tcobase)) & TCO_STS_TCO2TO_STS ? "" : "not "); + + /* Clear out the old status */ + outl(TCO_STS_RESET, TCO_STS(tcobase)); + + /* + * Check that the heartbeat value is within it's range. + * If not, reset to the default. + */ + if (tco_timer_set_heartbeat(heartbeat)) { + heartbeat = WATCHDOG_HEARTBEAT; + tco_timer_set_heartbeat(heartbeat); + printk(KERN_INFO PFX "heartbeat value must be 2, All Rights + * Reserved. + * http://www.kernelconcepts.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for NV chipsets + * based on softdog.c by Alan Cox + */ + +/* + * Some address definitions for the TCO + */ + +#define TCO_RLD(base) ((base) + 0x00) /* TCO Timer Reload and Current Value */ +#define TCO_TMR(base) ((base) + 0x01) /* TCO Timer Initial Value */ + +#define TCO_STS(base) ((base) + 0x04) /* TCO Status Register */ +/* + * TCO Boot Status bit: set on TCO reset, reset by software or standby + * power-good (survives reboots), unfortunately this bit is never + * set. + */ +# define TCO_STS_BOOT_STS (1 << 9) +/* + * first and 2nd timeout status bits, these also survive a warm boot, + * and they work, so we use them. + */ +# define TCO_STS_TCO_INT_STS (1 << 1) +# define TCO_STS_TCO2TO_STS (1 << 10) +# define TCO_STS_RESET (TCO_STS_BOOT_STS | TCO_STS_TCO2TO_STS | \ + TCO_STS_TCO_INT_STS) + +#define TCO_CNT(base) ((base) + 0x08) /* TCO Control Register */ +# define TCO_CNT_TCOHALT (1 << 12) + +#define MCP51_SMBUS_SETUP_B 0xe8 +# define MCP51_SMBUS_SETUP_B_TCO_REBOOT (1 << 25) + +/* + * The SMI_EN register is at the base io address + 0x04, + * while TCOBASE is + 0x40. + */ +#define MCP51_SMI_EN(base) ((base) - 0x40 + 0x04) +# define MCP51_SMI_EN_TCO ((1 << 4) | (1 << 5)) -- cgit v1.2.2 From f8394f61c66f48b1fe9d6964ddce492d7f9a4cd9 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jan 2011 21:28:19 +0100 Subject: watchdog: add driver for the Atheros AR71XX/AR724X/AR913X SoCs This patch adds a driver for the built-in hardware watchdog device of the Atheros AR71XX/AR724X/AR913X SoCs. Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 7 + drivers/watchdog/Makefile | 1 + drivers/watchdog/ath79_wdt.c | 305 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 drivers/watchdog/ath79_wdt.c (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index db00fa9f6979..68a9527f92d0 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -866,6 +866,13 @@ config SBC_EPX_C3_WATCHDOG # MIPS Architecture +config ATH79_WDT + tristate "Atheros AR71XX/AR724X/AR913X hardware watchdog" + depends on ATH79 + help + Hardware driver for the built-in watchdog timer on the Atheros + AR71XX/AR724X/AR913X SoCs. + config BCM47XX_WDT tristate "Broadcom BCM47xx Watchdog Timer" depends on BCM47XX diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index cd77f5492f95..9b6b33a02072 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -110,6 +110,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o # M68KNOMMU Architecture # MIPS Architecture +obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c new file mode 100644 index 000000000000..725c84bfdd76 --- /dev/null +++ b/drivers/watchdog/ath79_wdt.c @@ -0,0 +1,305 @@ +/* + * Atheros AR71XX/AR724X/AR913X built-in hardware watchdog timer. + * + * Copyright (C) 2008-2011 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * This driver was based on: drivers/watchdog/ixp4xx_wdt.c + * Author: Deepak Saxena + * Copyright 2004 (c) MontaVista, Software, Inc. + * + * which again was based on sa1100 driver, + * Copyright (C) 2000 Oleg Drokin + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DRIVER_NAME "ath79-wdt" + +#define WDT_TIMEOUT 15 /* seconds */ + +#define WDOG_CTRL_LAST_RESET BIT(31) +#define WDOG_CTRL_ACTION_MASK 3 +#define WDOG_CTRL_ACTION_NONE 0 /* no action */ +#define WDOG_CTRL_ACTION_GPI 1 /* general purpose interrupt */ +#define WDOG_CTRL_ACTION_NMI 2 /* NMI */ +#define WDOG_CTRL_ACTION_FCR 3 /* full chip reset */ + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " + "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static int timeout = WDT_TIMEOUT; +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds " + "(default=" __MODULE_STRING(WDT_TIMEOUT) "s)"); + +static unsigned long wdt_flags; + +#define WDT_FLAGS_BUSY 0 +#define WDT_FLAGS_EXPECT_CLOSE 1 + +static struct clk *wdt_clk; +static unsigned long wdt_freq; +static int boot_status; +static int max_timeout; + +static inline void ath79_wdt_keepalive(void) +{ + ath79_reset_wr(AR71XX_RESET_REG_WDOG, wdt_freq * timeout); +} + +static inline void ath79_wdt_enable(void) +{ + ath79_wdt_keepalive(); + ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR); +} + +static inline void ath79_wdt_disable(void) +{ + ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_NONE); +} + +static int ath79_wdt_set_timeout(int val) +{ + if (val < 1 || val > max_timeout) + return -EINVAL; + + timeout = val; + ath79_wdt_keepalive(); + + return 0; +} + +static int ath79_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_FLAGS_BUSY, &wdt_flags)) + return -EBUSY; + + clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags); + ath79_wdt_enable(); + + return nonseekable_open(inode, file); +} + +static int ath79_wdt_release(struct inode *inode, struct file *file) +{ + if (test_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags)) + ath79_wdt_disable(); + else { + pr_crit(DRIVER_NAME ": device closed unexpectedly, " + "watchdog timer will not stop!\n"); + ath79_wdt_keepalive(); + } + + clear_bit(WDT_FLAGS_BUSY, &wdt_flags); + clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags); + + return 0; +} + +static ssize_t ath79_wdt_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + if (len) { + if (!nowayout) { + size_t i; + + clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags); + + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + + if (c == 'V') + set_bit(WDT_FLAGS_EXPECT_CLOSE, + &wdt_flags); + } + } + + ath79_wdt_keepalive(); + } + + return len; +} + +static const struct watchdog_info ath79_wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE | WDIOF_CARDRESET, + .firmware_version = 0, + .identity = "ATH79 watchdog", +}; + +static long ath79_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int err; + int t; + + switch (cmd) { + case WDIOC_GETSUPPORT: + err = copy_to_user(argp, &ath79_wdt_info, + sizeof(ath79_wdt_info)) ? -EFAULT : 0; + break; + + case WDIOC_GETSTATUS: + err = put_user(0, p); + break; + + case WDIOC_GETBOOTSTATUS: + err = put_user(boot_status, p); + break; + + case WDIOC_KEEPALIVE: + ath79_wdt_keepalive(); + err = 0; + break; + + case WDIOC_SETTIMEOUT: + err = get_user(t, p); + if (err) + break; + + err = ath79_wdt_set_timeout(t); + if (err) + break; + + /* fallthrough */ + case WDIOC_GETTIMEOUT: + err = put_user(timeout, p); + break; + + default: + err = -ENOTTY; + break; + } + + return err; +} + +static const struct file_operations ath79_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = ath79_wdt_write, + .unlocked_ioctl = ath79_wdt_ioctl, + .open = ath79_wdt_open, + .release = ath79_wdt_release, +}; + +static struct miscdevice ath79_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &ath79_wdt_fops, +}; + +static int __devinit ath79_wdt_probe(struct platform_device *pdev) +{ + u32 ctrl; + int err; + + wdt_clk = clk_get(&pdev->dev, "wdt"); + if (IS_ERR(wdt_clk)) + return PTR_ERR(wdt_clk); + + err = clk_enable(wdt_clk); + if (err) + goto err_clk_put; + + wdt_freq = clk_get_rate(wdt_clk); + if (!wdt_freq) { + err = -EINVAL; + goto err_clk_disable; + } + + max_timeout = (0xfffffffful / wdt_freq); + if (timeout < 1 || timeout > max_timeout) { + timeout = max_timeout; + dev_info(&pdev->dev, + "timeout value must be 0 < timeout < %d, using %d\n", + max_timeout, timeout); + } + + ctrl = ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL); + boot_status = (ctrl & WDOG_CTRL_LAST_RESET) ? WDIOF_CARDRESET : 0; + + err = misc_register(&ath79_wdt_miscdev); + if (err) { + dev_err(&pdev->dev, + "unable to register misc device, err=%d\n", err); + goto err_clk_disable; + } + + return 0; + +err_clk_disable: + clk_disable(wdt_clk); +err_clk_put: + clk_put(wdt_clk); + return err; +} + +static int __devexit ath79_wdt_remove(struct platform_device *pdev) +{ + misc_deregister(&ath79_wdt_miscdev); + clk_disable(wdt_clk); + clk_put(wdt_clk); + return 0; +} + +static void ath97_wdt_shutdown(struct platform_device *pdev) +{ + ath79_wdt_disable(); +} + +static struct platform_driver ath79_wdt_driver = { + .remove = __devexit_p(ath79_wdt_remove), + .shutdown = ath97_wdt_shutdown, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init ath79_wdt_init(void) +{ + return platform_driver_probe(&ath79_wdt_driver, ath79_wdt_probe); +} +module_init(ath79_wdt_init); + +static void __exit ath79_wdt_exit(void) +{ + platform_driver_unregister(&ath79_wdt_driver); +} +module_exit(ath79_wdt_exit); + +MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X hardware watchdog driver"); +MODULE_AUTHOR("Gabor Juhos Date: Wed, 3 Nov 2010 15:07:28 +0100 Subject: watchdog: Add MCF548x watchdog driver. Add watchdog driver for MCF548x. Signed-off-by: Philippe De Muyter Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 7 +- drivers/watchdog/Makefile | 3 +- drivers/watchdog/m548x_wdt.c | 227 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 drivers/watchdog/m548x_wdt.c (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 68a9527f92d0..2e2400e7322e 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -862,7 +862,12 @@ config SBC_EPX_C3_WATCHDOG # M68K Architecture -# M68KNOMMU Architecture +config M548x_WATCHDOG + tristate "MCF548x watchdog support" + depends on M548x + help + To compile this driver as a module, choose M here: the + module will be called m548x_wdt. # MIPS Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 9b6b33a02072..dd776651917c 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -106,8 +106,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o # M32R Architecture # M68K Architecture - -# M68KNOMMU Architecture +obj-$(CONFIG_M548x_WATCHDOG) += m548x_wdt.o # MIPS Architecture obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o diff --git a/drivers/watchdog/m548x_wdt.c b/drivers/watchdog/m548x_wdt.c new file mode 100644 index 000000000000..cabbcfe1c847 --- /dev/null +++ b/drivers/watchdog/m548x_wdt.c @@ -0,0 +1,227 @@ +/* + * drivers/watchdog/m548x_wdt.c + * + * Watchdog driver for ColdFire MCF548x processors + * Copyright 2010 (c) Philippe De Muyter + * + * Adapted from the IXP4xx watchdog driver, which carries these notices: + * + * Author: Deepak Saxena + * + * Copyright 2004 (c) MontaVista, Software, Inc. + * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static int nowayout = WATCHDOG_NOWAYOUT; +static unsigned int heartbeat = 30; /* (secs) Default is 0.5 minute */ +static unsigned long wdt_status; + +#define WDT_IN_USE 0 +#define WDT_OK_TO_CLOSE 1 + +static void wdt_enable(void) +{ + unsigned int gms0; + + /* preserve GPIO usage, if any */ + gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); + if (gms0 & MCF_GPT_GMS_TMS_GPIO) + gms0 &= (MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_GPIO_MASK + | MCF_GPT_GMS_OD); + else + gms0 = MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_OD; + __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); + __raw_writel(MCF_GPT_GCIR_PRE(heartbeat*(MCF_BUSCLK/0xffff)) | + MCF_GPT_GCIR_CNT(0xffff), MCF_MBAR + MCF_GPT_GCIR0); + gms0 |= MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE; + __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); +} + +static void wdt_disable(void) +{ + unsigned int gms0; + + /* disable watchdog */ + gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); + gms0 &= ~(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE); + __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); +} + +static void wdt_keepalive(void) +{ + unsigned int gms0; + + gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); + gms0 |= MCF_GPT_GMS_OCPW(0xA5); + __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); +} + +static int m548x_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 m548x_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 = "Coldfire M548x Watchdog", +}; + +static long m548x_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_keepalive(); + ret = 0; + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(time, (int *)arg); + if (ret) + break; + + if (time <= 0 || time > 30) { + ret = -EINVAL; + break; + } + + heartbeat = time; + wdt_enable(); + /* Fall through */ + + case WDIOC_GETTIMEOUT: + ret = put_user(heartbeat, (int *)arg); + break; + } + return ret; +} + +static int m548x_wdt_release(struct inode *inode, struct file *file) +{ + if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) + wdt_disable(); + else { + printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " + "timer will not stop\n"); + wdt_keepalive(); + } + clear_bit(WDT_IN_USE, &wdt_status); + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + + return 0; +} + + +static const struct file_operations m548x_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = m548x_wdt_write, + .unlocked_ioctl = m548x_wdt_ioctl, + .open = m548x_wdt_open, + .release = m548x_wdt_release, +}; + +static struct miscdevice m548x_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &m548x_wdt_fops, +}; + +static int __init m548x_wdt_init(void) +{ + if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4, + "Coldfire M548x Watchdog")) { + printk(KERN_WARNING + "Coldfire M548x Watchdog : I/O region busy\n"); + return -EBUSY; + } + printk(KERN_INFO "ColdFire watchdog driver is loaded.\n"); + + return misc_register(&m548x_wdt_miscdev); +} + +static void __exit m548x_wdt_exit(void) +{ + misc_deregister(&m548x_wdt_miscdev); + release_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4); +} + +module_init(m548x_wdt_init); +module_exit(m548x_wdt_exit); + +MODULE_AUTHOR("Philippe De Muyter "); +MODULE_DESCRIPTION("Coldfire M548x Watchdog"); + +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)"); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.2 From 9b9c63ff1f3b09af8e0c66180a904bdbebe92634 Mon Sep 17 00:00:00 2001 From: Philippe De Muyter Date: Sat, 22 Jan 2011 00:21:24 +0100 Subject: m68knommu: fix m548x_wdt.c compilation after headers renaming m548x headers were renamed to m54xx, but m548x_wdt.c still uses the old names. Fix that. Signed-off-by: Philippe De Muyter Signed-off-by: Greg Ungerer --- drivers/watchdog/m548x_wdt.c | 50 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/m548x_wdt.c b/drivers/watchdog/m548x_wdt.c index cabbcfe1c847..4d43286074aa 100644 --- a/drivers/watchdog/m548x_wdt.c +++ b/drivers/watchdog/m548x_wdt.c @@ -1,7 +1,7 @@ /* - * drivers/watchdog/m548x_wdt.c + * drivers/watchdog/m54xx_wdt.c * - * Watchdog driver for ColdFire MCF548x processors + * Watchdog driver for ColdFire MCF547x & MCF548x processors * Copyright 2010 (c) Philippe De Muyter * * Adapted from the IXP4xx watchdog driver, which carries these notices: @@ -29,8 +29,8 @@ #include #include -#include -#include +#include +#include static int nowayout = WATCHDOG_NOWAYOUT; static unsigned int heartbeat = 30; /* (secs) Default is 0.5 minute */ @@ -76,7 +76,7 @@ static void wdt_keepalive(void) __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); } -static int m548x_wdt_open(struct inode *inode, struct file *file) +static int m54xx_wdt_open(struct inode *inode, struct file *file) { if (test_and_set_bit(WDT_IN_USE, &wdt_status)) return -EBUSY; @@ -86,7 +86,7 @@ static int m548x_wdt_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); } -static ssize_t m548x_wdt_write(struct file *file, const char *data, +static ssize_t m54xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) { if (len) { @@ -112,10 +112,10 @@ static ssize_t m548x_wdt_write(struct file *file, const char *data, static const struct watchdog_info ident = { .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, - .identity = "Coldfire M548x Watchdog", + .identity = "Coldfire M54xx Watchdog", }; -static long m548x_wdt_ioctl(struct file *file, unsigned int cmd, +static long m54xx_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = -ENOTTY; @@ -161,7 +161,7 @@ static long m548x_wdt_ioctl(struct file *file, unsigned int cmd, return ret; } -static int m548x_wdt_release(struct inode *inode, struct file *file) +static int m54xx_wdt_release(struct inode *inode, struct file *file) { if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) wdt_disable(); @@ -177,45 +177,45 @@ static int m548x_wdt_release(struct inode *inode, struct file *file) } -static const struct file_operations m548x_wdt_fops = { +static const struct file_operations m54xx_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .write = m548x_wdt_write, - .unlocked_ioctl = m548x_wdt_ioctl, - .open = m548x_wdt_open, - .release = m548x_wdt_release, + .write = m54xx_wdt_write, + .unlocked_ioctl = m54xx_wdt_ioctl, + .open = m54xx_wdt_open, + .release = m54xx_wdt_release, }; -static struct miscdevice m548x_wdt_miscdev = { +static struct miscdevice m54xx_wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", - .fops = &m548x_wdt_fops, + .fops = &m54xx_wdt_fops, }; -static int __init m548x_wdt_init(void) +static int __init m54xx_wdt_init(void) { if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4, - "Coldfire M548x Watchdog")) { + "Coldfire M54xx Watchdog")) { printk(KERN_WARNING - "Coldfire M548x Watchdog : I/O region busy\n"); + "Coldfire M54xx Watchdog : I/O region busy\n"); return -EBUSY; } printk(KERN_INFO "ColdFire watchdog driver is loaded.\n"); - return misc_register(&m548x_wdt_miscdev); + return misc_register(&m54xx_wdt_miscdev); } -static void __exit m548x_wdt_exit(void) +static void __exit m54xx_wdt_exit(void) { - misc_deregister(&m548x_wdt_miscdev); + misc_deregister(&m54xx_wdt_miscdev); release_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4); } -module_init(m548x_wdt_init); -module_exit(m548x_wdt_exit); +module_init(m54xx_wdt_init); +module_exit(m54xx_wdt_exit); MODULE_AUTHOR("Philippe De Muyter "); -MODULE_DESCRIPTION("Coldfire M548x Watchdog"); +MODULE_DESCRIPTION("Coldfire M54xx Watchdog"); module_param(heartbeat, int, 0); MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)"); -- cgit v1.2.2 From 4157a04d5d7def8661559cd98eb285a520d50075 Mon Sep 17 00:00:00 2001 From: Philippe De Muyter Date: Sat, 22 Jan 2011 00:21:25 +0100 Subject: m68knommu: Rename m548x_wdt.c to m54xx_wdt.c All m548x files were renamed to m54xx, except m548x_wdt.c. Fix that. Signed-off-by: Philippe De Muyter Signed-off-by: Greg Ungerer --- drivers/watchdog/Kconfig | 6 +- drivers/watchdog/Makefile | 2 +- drivers/watchdog/m548x_wdt.c | 227 ------------------------------------------- drivers/watchdog/m54xx_wdt.c | 227 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 231 insertions(+), 231 deletions(-) delete mode 100644 drivers/watchdog/m548x_wdt.c create mode 100644 drivers/watchdog/m54xx_wdt.c (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 2e2400e7322e..31649b7b672f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -862,12 +862,12 @@ config SBC_EPX_C3_WATCHDOG # M68K Architecture -config M548x_WATCHDOG - tristate "MCF548x watchdog support" +config M54xx_WATCHDOG + tristate "MCF54xx watchdog support" depends on M548x help To compile this driver as a module, choose M here: the - module will be called m548x_wdt. + module will be called m54xx_wdt. # MIPS Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index dd776651917c..20e44c4782b3 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -106,7 +106,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o # M32R Architecture # M68K Architecture -obj-$(CONFIG_M548x_WATCHDOG) += m548x_wdt.o +obj-$(CONFIG_M54xx_WATCHDOG) += m54xx_wdt.o # MIPS Architecture obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o diff --git a/drivers/watchdog/m548x_wdt.c b/drivers/watchdog/m548x_wdt.c deleted file mode 100644 index 4d43286074aa..000000000000 --- a/drivers/watchdog/m548x_wdt.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * drivers/watchdog/m54xx_wdt.c - * - * Watchdog driver for ColdFire MCF547x & MCF548x processors - * Copyright 2010 (c) Philippe De Muyter - * - * Adapted from the IXP4xx watchdog driver, which carries these notices: - * - * Author: Deepak Saxena - * - * Copyright 2004 (c) MontaVista, Software, Inc. - * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static int nowayout = WATCHDOG_NOWAYOUT; -static unsigned int heartbeat = 30; /* (secs) Default is 0.5 minute */ -static unsigned long wdt_status; - -#define WDT_IN_USE 0 -#define WDT_OK_TO_CLOSE 1 - -static void wdt_enable(void) -{ - unsigned int gms0; - - /* preserve GPIO usage, if any */ - gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); - if (gms0 & MCF_GPT_GMS_TMS_GPIO) - gms0 &= (MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_GPIO_MASK - | MCF_GPT_GMS_OD); - else - gms0 = MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_OD; - __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); - __raw_writel(MCF_GPT_GCIR_PRE(heartbeat*(MCF_BUSCLK/0xffff)) | - MCF_GPT_GCIR_CNT(0xffff), MCF_MBAR + MCF_GPT_GCIR0); - gms0 |= MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE; - __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); -} - -static void wdt_disable(void) -{ - unsigned int gms0; - - /* disable watchdog */ - gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); - gms0 &= ~(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE); - __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); -} - -static void wdt_keepalive(void) -{ - unsigned int gms0; - - gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); - gms0 |= MCF_GPT_GMS_OCPW(0xA5); - __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); -} - -static int m54xx_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 m54xx_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 = "Coldfire M54xx Watchdog", -}; - -static long m54xx_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_keepalive(); - ret = 0; - break; - - case WDIOC_SETTIMEOUT: - ret = get_user(time, (int *)arg); - if (ret) - break; - - if (time <= 0 || time > 30) { - ret = -EINVAL; - break; - } - - heartbeat = time; - wdt_enable(); - /* Fall through */ - - case WDIOC_GETTIMEOUT: - ret = put_user(heartbeat, (int *)arg); - break; - } - return ret; -} - -static int m54xx_wdt_release(struct inode *inode, struct file *file) -{ - if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) - wdt_disable(); - else { - printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " - "timer will not stop\n"); - wdt_keepalive(); - } - clear_bit(WDT_IN_USE, &wdt_status); - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - - return 0; -} - - -static const struct file_operations m54xx_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = m54xx_wdt_write, - .unlocked_ioctl = m54xx_wdt_ioctl, - .open = m54xx_wdt_open, - .release = m54xx_wdt_release, -}; - -static struct miscdevice m54xx_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &m54xx_wdt_fops, -}; - -static int __init m54xx_wdt_init(void) -{ - if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4, - "Coldfire M54xx Watchdog")) { - printk(KERN_WARNING - "Coldfire M54xx Watchdog : I/O region busy\n"); - return -EBUSY; - } - printk(KERN_INFO "ColdFire watchdog driver is loaded.\n"); - - return misc_register(&m54xx_wdt_miscdev); -} - -static void __exit m54xx_wdt_exit(void) -{ - misc_deregister(&m54xx_wdt_miscdev); - release_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4); -} - -module_init(m54xx_wdt_init); -module_exit(m54xx_wdt_exit); - -MODULE_AUTHOR("Philippe De Muyter "); -MODULE_DESCRIPTION("Coldfire M54xx Watchdog"); - -module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)"); - -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/m54xx_wdt.c b/drivers/watchdog/m54xx_wdt.c new file mode 100644 index 000000000000..4d43286074aa --- /dev/null +++ b/drivers/watchdog/m54xx_wdt.c @@ -0,0 +1,227 @@ +/* + * drivers/watchdog/m54xx_wdt.c + * + * Watchdog driver for ColdFire MCF547x & MCF548x processors + * Copyright 2010 (c) Philippe De Muyter + * + * Adapted from the IXP4xx watchdog driver, which carries these notices: + * + * Author: Deepak Saxena + * + * Copyright 2004 (c) MontaVista, Software, Inc. + * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static int nowayout = WATCHDOG_NOWAYOUT; +static unsigned int heartbeat = 30; /* (secs) Default is 0.5 minute */ +static unsigned long wdt_status; + +#define WDT_IN_USE 0 +#define WDT_OK_TO_CLOSE 1 + +static void wdt_enable(void) +{ + unsigned int gms0; + + /* preserve GPIO usage, if any */ + gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); + if (gms0 & MCF_GPT_GMS_TMS_GPIO) + gms0 &= (MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_GPIO_MASK + | MCF_GPT_GMS_OD); + else + gms0 = MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_OD; + __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); + __raw_writel(MCF_GPT_GCIR_PRE(heartbeat*(MCF_BUSCLK/0xffff)) | + MCF_GPT_GCIR_CNT(0xffff), MCF_MBAR + MCF_GPT_GCIR0); + gms0 |= MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE; + __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); +} + +static void wdt_disable(void) +{ + unsigned int gms0; + + /* disable watchdog */ + gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); + gms0 &= ~(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE); + __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); +} + +static void wdt_keepalive(void) +{ + unsigned int gms0; + + gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); + gms0 |= MCF_GPT_GMS_OCPW(0xA5); + __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); +} + +static int m54xx_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 m54xx_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 = "Coldfire M54xx Watchdog", +}; + +static long m54xx_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_keepalive(); + ret = 0; + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(time, (int *)arg); + if (ret) + break; + + if (time <= 0 || time > 30) { + ret = -EINVAL; + break; + } + + heartbeat = time; + wdt_enable(); + /* Fall through */ + + case WDIOC_GETTIMEOUT: + ret = put_user(heartbeat, (int *)arg); + break; + } + return ret; +} + +static int m54xx_wdt_release(struct inode *inode, struct file *file) +{ + if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) + wdt_disable(); + else { + printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " + "timer will not stop\n"); + wdt_keepalive(); + } + clear_bit(WDT_IN_USE, &wdt_status); + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + + return 0; +} + + +static const struct file_operations m54xx_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = m54xx_wdt_write, + .unlocked_ioctl = m54xx_wdt_ioctl, + .open = m54xx_wdt_open, + .release = m54xx_wdt_release, +}; + +static struct miscdevice m54xx_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &m54xx_wdt_fops, +}; + +static int __init m54xx_wdt_init(void) +{ + if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4, + "Coldfire M54xx Watchdog")) { + printk(KERN_WARNING + "Coldfire M54xx Watchdog : I/O region busy\n"); + return -EBUSY; + } + printk(KERN_INFO "ColdFire watchdog driver is loaded.\n"); + + return misc_register(&m54xx_wdt_miscdev); +} + +static void __exit m54xx_wdt_exit(void) +{ + misc_deregister(&m54xx_wdt_miscdev); + release_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4); +} + +module_init(m54xx_wdt_init); +module_exit(m54xx_wdt_exit); + +MODULE_AUTHOR("Philippe De Muyter "); +MODULE_DESCRIPTION("Coldfire M54xx Watchdog"); + +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)"); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.2 From aa25afad2ca60d19457849ea75e9c31236f4e174 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 19 Feb 2011 15:55:00 +0000 Subject: ARM: amba: make probe() functions take const id tables Make Primecell driver probe functions take a const pointer to their ID tables. Drivers should never modify their ID tables in their probe handler. Signed-off-by: Russell King --- drivers/watchdog/sp805_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 9127eda2145b..0a0efe713bc8 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -278,7 +278,7 @@ static struct miscdevice sp805_wdt_miscdev = { }; static int __devinit -sp805_wdt_probe(struct amba_device *adev, struct amba_id *id) +sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; -- cgit v1.2.2 From 1c48a5c93da63132b92c4bbcd18e690c51539df6 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 17 Feb 2011 02:43:24 -0700 Subject: dt: Eliminate of_platform_{,un}register_driver Final step to eliminate of_platform_bus_type. They're all just platform drivers now. v2: fix type in pasemi_nand.c (thanks to Stephen Rothwell) Signed-off-by: Grant Likely --- drivers/watchdog/cpwd.c | 9 ++++----- drivers/watchdog/gef_wdt.c | 9 ++++----- drivers/watchdog/mpc8xxx_wdt.c | 15 +++++++++------ drivers/watchdog/riowd.c | 9 ++++----- 4 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index eca855a55c0d..45db1d570df1 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -528,8 +528,7 @@ static const struct file_operations cpwd_fops = { .llseek = no_llseek, }; -static int __devinit cpwd_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit cpwd_probe(struct platform_device *op) { struct device_node *options; const char *str_prop; @@ -678,7 +677,7 @@ static const struct of_device_id cpwd_match[] = { }; MODULE_DEVICE_TABLE(of, cpwd_match); -static struct of_platform_driver cpwd_driver = { +static struct platform_driver cpwd_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -690,12 +689,12 @@ static struct of_platform_driver cpwd_driver = { static int __init cpwd_init(void) { - return of_register_platform_driver(&cpwd_driver); + return platform_driver_register(&cpwd_driver); } static void __exit cpwd_exit(void) { - of_unregister_platform_driver(&cpwd_driver); + platform_driver_unregister(&cpwd_driver); } module_init(cpwd_init); diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index f6bd6f10fcec..29a7cd4b90c8 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -261,8 +261,7 @@ static struct miscdevice gef_wdt_miscdev = { }; -static int __devinit gef_wdt_probe(struct platform_device *dev, - const struct of_device_id *match) +static int __devinit gef_wdt_probe(struct platform_device *dev) { int timeout = 10; u32 freq; @@ -303,7 +302,7 @@ static const struct of_device_id gef_wdt_ids[] = { {}, }; -static struct of_platform_driver gef_wdt_driver = { +static struct platform_driver gef_wdt_driver = { .driver = { .name = "gef_wdt", .owner = THIS_MODULE, @@ -315,12 +314,12 @@ static struct of_platform_driver gef_wdt_driver = { static int __init gef_wdt_init(void) { printk(KERN_INFO "GE watchdog driver\n"); - return of_register_platform_driver(&gef_wdt_driver); + return platform_driver_register(&gef_wdt_driver); } static void __exit gef_wdt_exit(void) { - of_unregister_platform_driver(&gef_wdt_driver); + platform_driver_unregister(&gef_wdt_driver); } module_init(gef_wdt_init); diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 8fa213cdb499..ea438ad53055 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 int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev) { int ret; struct device_node *np = ofdev->dev.of_node; - struct mpc8xxx_wdt_type *wdt_type = match->data; + struct mpc8xxx_wdt_type *wdt_type; u32 freq = fsl_get_sys_freq(); bool enabled; + if (!ofdev->dev.of_match) + return -EINVAL; + wdt_type = match->data; + if (!freq || freq == -1) return -EINVAL; @@ -272,7 +275,7 @@ static const struct of_device_id mpc8xxx_wdt_match[] = { }; MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match); -static struct of_platform_driver mpc8xxx_wdt_driver = { +static struct platform_driver mpc8xxx_wdt_driver = { .probe = mpc8xxx_wdt_probe, .remove = __devexit_p(mpc8xxx_wdt_remove), .driver = { @@ -308,13 +311,13 @@ module_init(mpc8xxx_wdt_init_late); static int __init mpc8xxx_wdt_init(void) { - return of_register_platform_driver(&mpc8xxx_wdt_driver); + return platform_driver_register(&mpc8xxx_wdt_driver); } arch_initcall(mpc8xxx_wdt_init); static void __exit mpc8xxx_wdt_exit(void) { - of_unregister_platform_driver(&mpc8xxx_wdt_driver); + platform_driver_unregister(&mpc8xxx_wdt_driver); } module_exit(mpc8xxx_wdt_exit); diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 3faee1ae64bd..109b533896b7 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -172,8 +172,7 @@ static struct miscdevice riowd_miscdev = { .fops = &riowd_fops }; -static int __devinit riowd_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit riowd_probe(struct platform_device *op) { struct riowd *p; int err = -EINVAL; @@ -238,7 +237,7 @@ static const struct of_device_id riowd_match[] = { }; MODULE_DEVICE_TABLE(of, riowd_match); -static struct of_platform_driver riowd_driver = { +static struct platform_driver riowd_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -250,12 +249,12 @@ static struct of_platform_driver riowd_driver = { static int __init riowd_init(void) { - return of_register_platform_driver(&riowd_driver); + return platform_driver_register(&riowd_driver); } static void __exit riowd_exit(void) { - of_unregister_platform_driver(&riowd_driver); + platform_driver_unregister(&riowd_driver); } module_init(riowd_init); -- cgit v1.2.2 From ae0e47f02aaedbfdd5e4bec73f79b714d758223d Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Tue, 1 Mar 2011 15:06:02 +0100 Subject: Remove one to many n's in a word Signed-off-by: Justin P. Mattock Signed-off-by: Jiri Kosina --- drivers/watchdog/sbc_epx_c3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c index 28f1214457bd..3066a5127ca8 100644 --- a/drivers/watchdog/sbc_epx_c3.c +++ b/drivers/watchdog/sbc_epx_c3.c @@ -220,7 +220,7 @@ module_exit(watchdog_exit); MODULE_AUTHOR("Calin A. Culianu "); MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. " "Note that there is no way to probe for this device -- " - "so only use it if you are *sure* you are runnning on this specific " + "so only use it if you are *sure* you are running on this specific " "SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.2 From d406577526a611e6be1f6b1cfeaf094dd95fa439 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 28 Feb 2011 10:16:29 +0100 Subject: watchdog: sbc_fitpc2_wdt, fix crash on systems without DMI_BOARD_NAME Some systems don't provide DMI_BOARD_NAME in their DMI tables. Avoid crash in such situations in fitpc2_wdt_init. The fix is to check if the dmi_get_system_info return value is NULL. The oops: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] strstr+0x26/0xa0 PGD 3966e067 PUD 39605067 PMD 0 Oops: 0000 [#1] SMP last sysfs file: /sys/devices/system/cpu/cpu1/cache/index2/shared_cpu_map CPU 1 Modules linked in: ... Pid: 1748, comm: modprobe Not tainted 2.6.37-22-default #1 /Bochs RIP: 0010:[] [] strstr+0x26/0xa0 RSP: 0018:ffff88003ad73f18 EFLAGS: 00010206 RAX: 0000000000000000 RBX: 00000000ffffffed RCX: 00000000ffffffff RDX: ffffffffa003f4cc RSI: ffffffffa003f4c2 RDI: 0000000000000000 ... CR2: 0000000000000000 CR3: 000000003b7ac000 CR4: 00000000000006e0 ... Process modprobe (pid: 1748, threadinfo ffff88003ad72000, task ffff88002e6365c0) Stack: ... Call Trace: [] fitpc2_wdt_init+0x1f/0x13c [sbc_fitpc2_wdt] [] do_one_initcall+0x3a/0x170 ... Code: f3 c3 0f 1f 00 80 3e 00 53 48 89 f8 74 1b 48 89 f2 0f 1f 40 00 48 83 c2 01 80 3a 00 75 f7 49 89 d0 48 89 f8 49 29 f0 75 02 5b c3 <80> 3f 00 74 0e 0f 1f 44 00 00 48 83 c0 01 80 38 00 75 f7 49 89 Signed-off-by: Jiri Slaby Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sbc_fitpc2_wdt.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c index c7d67e9a7465..79906255eeb6 100644 --- a/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/drivers/watchdog/sbc_fitpc2_wdt.c @@ -201,11 +201,14 @@ static struct miscdevice fitpc2_wdt_miscdev = { static int __init fitpc2_wdt_init(void) { int err; + const char *brd_name; - if (!strstr(dmi_get_system_info(DMI_BOARD_NAME), "SBC-FITPC2")) + brd_name = dmi_get_system_info(DMI_BOARD_NAME); + + if (!brd_name || !strstr(brd_name, "SBC-FITPC2")) return -ENODEV; - pr_info("%s found\n", dmi_get_system_info(DMI_BOARD_NAME)); + pr_info("%s found\n", brd_name); if (!request_region(COMMAND_PORT, 1, WATCHDOG_NAME)) { pr_err("I/O address 0x%04x already in use\n", COMMAND_PORT); -- cgit v1.2.2 From 0503add9d251db22ba2f610fb8d9b7743a9786da Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Thu, 10 Mar 2011 22:40:05 -0700 Subject: Watchdog: omap_wdt: add fine grain runtime-pm The omap_wdt should only be in full active state when the registers are being accessed. Otherwise the device can be on lower power mode. This patch is based on a patch created by Kalle Jokiniemi: https://patchwork.kernel.org/patch/618231/ which is itself based on a patch created by Atal Shargorodsky: http://lkml.org/lkml/2009/3/10/266. Signed-off-by: Paul Walmsley Signed-off-by: Kalle Jokiniemi Tested-by: Kalle Jokiniemi Cc: Wim Van Sebroeck Acked-by: Wim Van Sebroeck Acked-by: Kevin Hilman --- drivers/watchdog/omap_wdt.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 3dd4971160ef..2b4acb86c191 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -124,6 +124,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) u32 pre_margin = GET_WLDR_VAL(timer_margin); void __iomem *base = wdev->base; + pm_runtime_get_sync(wdev->dev); + /* just count up at 32 KHz */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) cpu_relax(); @@ -131,6 +133,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) cpu_relax(); + + pm_runtime_put_sync(wdev->dev); } /* @@ -160,6 +164,8 @@ static int omap_wdt_open(struct inode *inode, struct file *file) omap_wdt_ping(wdev); /* trigger loading of new timeout value */ omap_wdt_enable(wdev); + pm_runtime_put_sync(wdev->dev); + return nonseekable_open(inode, file); } @@ -171,6 +177,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file) * Shut off the timer unless NOWAYOUT is defined. */ #ifndef CONFIG_WATCHDOG_NOWAYOUT + pm_runtime_get_sync(wdev->dev); omap_wdt_disable(wdev); @@ -190,9 +197,11 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data, /* Refresh LOAD_TIME. */ if (len) { + pm_runtime_get_sync(wdev->dev); spin_lock(&wdt_lock); omap_wdt_ping(wdev); spin_unlock(&wdt_lock); + pm_runtime_put_sync(wdev->dev); } return len; } @@ -224,15 +233,18 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, return put_user(omap_prcm_get_reset_sources(), (int __user *)arg); case WDIOC_KEEPALIVE: + pm_runtime_get_sync(wdev->dev); spin_lock(&wdt_lock); omap_wdt_ping(wdev); spin_unlock(&wdt_lock); + pm_runtime_put_sync(wdev->dev); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_margin, (int __user *)arg)) return -EFAULT; omap_wdt_adjust_timeout(new_margin); + pm_runtime_get_sync(wdev->dev); spin_lock(&wdt_lock); omap_wdt_disable(wdev); omap_wdt_set_timeout(wdev); @@ -240,6 +252,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, omap_wdt_ping(wdev); spin_unlock(&wdt_lock); + pm_runtime_put_sync(wdev->dev); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(timer_margin, (int __user *)arg); @@ -345,8 +358,11 @@ static void omap_wdt_shutdown(struct platform_device *pdev) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); - if (wdev->omap_wdt_users) + if (wdev->omap_wdt_users) { + pm_runtime_get_sync(wdev->dev); omap_wdt_disable(wdev); + pm_runtime_put_sync(wdev->dev); + } } static int __devexit omap_wdt_remove(struct platform_device *pdev) @@ -381,8 +397,11 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); - if (wdev->omap_wdt_users) + if (wdev->omap_wdt_users) { + pm_runtime_get_sync(wdev->dev); omap_wdt_disable(wdev); + pm_runtime_put_sync(wdev->dev); + } return 0; } @@ -392,8 +411,10 @@ static int omap_wdt_resume(struct platform_device *pdev) struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); if (wdev->omap_wdt_users) { + pm_runtime_get_sync(wdev->dev); omap_wdt_enable(wdev); omap_wdt_ping(wdev); + pm_runtime_put_sync(wdev->dev); } return 0; -- cgit v1.2.2 From bbd562d717a84c6464211e8bd5efa0d9e25edc6d Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 21 Feb 2011 10:52:43 +0000 Subject: watchdog: cpwd: Fix buffer-overflow cppcheck-1.47 reports: [drivers/watchdog/cpwd.c:650]: (error) Buffer access out-of-bounds: p.devs The source code is for (i = 0; i < 4; i++) { misc_deregister(&p->devs[i].misc); where devs is defined as WD_NUMDEVS big and WD_NUMDEVS is equal to 3. So the 4 should be a 3 or WD_NUMDEVS. Reported-By: David Binderman Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/cpwd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index eca855a55c0d..3de4ba0260a5 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -646,7 +646,7 @@ static int __devexit cpwd_remove(struct platform_device *op) struct cpwd *p = dev_get_drvdata(&op->dev); int i; - for (i = 0; i < 4; i++) { + for (i = 0; i < WD_NUMDEVS; i++) { misc_deregister(&p->devs[i].misc); if (!p->enabled) { -- cgit v1.2.2 From a450c786a5769745cc8fa873a66ed3c377875ead Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 21 Feb 2011 19:09:40 +0000 Subject: watchdog: sch311x_wdt: Fix LDN active check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit if (sch311x_sio_inb(sio_config_port, 0x30) && 0x01 == 0) -> && should be & Reported-By: Toralf Förster Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sch311x_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index 0461858e07d0..7b687e9497f0 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c @@ -508,7 +508,7 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr) sch311x_sio_outb(sio_config_port, 0x07, 0x0a); /* Check if Logical Device Register is currently active */ - if (sch311x_sio_inb(sio_config_port, 0x30) && 0x01 == 0) + if (sch311x_sio_inb(sio_config_port, 0x30) & 0x01 == 0) printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n"); /* Get the base address of the runtime registers */ -- cgit v1.2.2 From 6899a8e13f76f37029084c891312e2cfad1305c8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 23 Feb 2011 23:26:01 +0300 Subject: watchdog: sch311x_wdt: fix printk condition "==" has higher precedence than "&". Since if (sch311x_sio_inb(sio_config_port, 0x30) & (0x01 == 0)) is always false the message is never printed. Signed-off-by: Dan Carpenter Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sch311x_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index 7b687e9497f0..b61ab1c54293 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c @@ -508,7 +508,7 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr) sch311x_sio_outb(sio_config_port, 0x07, 0x0a); /* Check if Logical Device Register is currently active */ - if (sch311x_sio_inb(sio_config_port, 0x30) & 0x01 == 0) + if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0) printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n"); /* Get the base address of the runtime registers */ -- cgit v1.2.2 From 943413c5b6e117a7eca029e3b07704d3b230d938 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 21 Feb 2011 19:28:58 +0000 Subject: watchdog: w83697ug_wdt: Fix set bit 0 to activate GPIO2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit outb_p(c || 0x01, WDT_EFDR); -> || should be | Reported-By: Toralf Förster Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/w83697ug_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c index a6c12dec91a1..df2a64dc9672 100644 --- a/drivers/watchdog/w83697ug_wdt.c +++ b/drivers/watchdog/w83697ug_wdt.c @@ -109,7 +109,7 @@ static int w83697ug_select_wd_register(void) outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ outb_p(0x30, WDT_EFER); /* select CR30 */ c = inb_p(WDT_EFDR); - outb_p(c || 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ + outb_p(c | 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ return 0; } -- cgit v1.2.2 From b77b708868c23737a4d25a474736cc924deb44f1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 2 Mar 2011 11:49:44 +0800 Subject: watchdog: hpwdt: eliminate section mismatch warning hpwdt_init_nmi_decoding() is called in hpwdt_init_one error handling, thus remove the __devexit annotation of hpwdt_exit_nmi_decoding(). This patch fixes below warning: WARNING: drivers/watchdog/hpwdt.o(.devinit.text+0x36f): Section mismatch in reference from the function hpwdt_init_one() to the function .devexit.text:hpwdt_exit_nmi_decoding() The function __devinit hpwdt_init_one() references a function __devexit hpwdt_exit_nmi_decoding(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of hpwdt_exit_nmi_decoding() so it may be used outside an exit section. Signed-off-by: Axel Lin Acked-by: Thomas Mingarelli Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/hpwdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 24b966d5061a..204a5603c4ae 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -710,7 +710,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) return 0; } -static void __devexit hpwdt_exit_nmi_decoding(void) +static void hpwdt_exit_nmi_decoding(void) { unregister_die_notifier(&die_notifier); if (cru_rom_addr) @@ -726,7 +726,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) return 0; } -static void __devexit hpwdt_exit_nmi_decoding(void) +static void hpwdt_exit_nmi_decoding(void) { } #endif /* CONFIG_HPWDT_NMI_DECODING */ -- cgit v1.2.2 From ea6649c721e0d8d2f79ae13ad9a21444f69dae70 Mon Sep 17 00:00:00 2001 From: Naga Chumbalkar Date: Fri, 4 Feb 2011 19:47:13 +0000 Subject: watchdog: hpwdt: Fix a couple of typos Fix some typos. Signed-off-by: Naga Chumbalkar Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 31649b7b672f..3dde7f0871a8 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -589,12 +589,12 @@ config IT87_WDT be called it87_wdt. config HP_WATCHDOG - tristate "HP Proliant iLO2+ Hardware Watchdog Timer" + tristate "HP ProLiant iLO2+ Hardware Watchdog Timer" depends on X86 help A software monitoring watchdog and NMI sourcing driver. This driver will detect lockups and provide a stack trace. This is a driver that - will only load on a HP ProLiant system with a minimum of iLO2 support. + will only load on an HP ProLiant system with a minimum of iLO2 support. To compile this driver as a module, choose M here: the module will be called hpwdt. -- cgit v1.2.2 From a4616153deae053b29a2b7dd9ec4b2a225accfc5 Mon Sep 17 00:00:00 2001 From: Tony Camuso Date: Fri, 4 Feb 2011 17:38:59 -0500 Subject: watchdog: hpwdt: build hpwdt as module by default with NMI_DECODING enabled Builds the hpwdt driver as a module by default. If the hardware is present, the module will be loaded. Also, if hpwdt is loaded, it will decode NMIs by default. This has been made possible by he patches to hpwdt made by Dann Frazier as well as related patches submitted by Don Zickus. hpwdt only loads on hp ProLiant x86 32-bit and 64-bit platforms. Signed-off-by: Tony Camuso Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 3dde7f0871a8..322b36a9c0e6 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -591,6 +591,7 @@ config IT87_WDT config HP_WATCHDOG tristate "HP ProLiant iLO2+ Hardware Watchdog Timer" depends on X86 + default m help A software monitoring watchdog and NMI sourcing driver. This driver will detect lockups and provide a stack trace. This is a driver that @@ -601,6 +602,7 @@ config HP_WATCHDOG config HPWDT_NMI_DECODING bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer" depends on HP_WATCHDOG + default y help When an NMI occurs this feature will make the necessary BIOS calls to log the cause of the NMI. -- cgit v1.2.2 From 4bc30272a15c58fc358bde093703d23bc0cf8e66 Mon Sep 17 00:00:00 2001 From: Huaro Tomita Date: Fri, 21 Jan 2011 07:37:51 +0900 Subject: watchdog: it87_wdt: Add support for IT8721F watchdog This patch adds support for a watchdog in IT8721F Super IO chip to it87_wdt driver. This new chips differ from the older IT87xxxF chips in the following ways: * WDT_GAMEPORT is not in IT8721F. * WDT_PWROK is not in IT8721F. Signed-off-by: Haruo Tomita Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 2 +- drivers/watchdog/it87_wdt.c | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 322b36a9c0e6..229a9c1506b6 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -580,7 +580,7 @@ config IT87_WDT depends on X86 && EXPERIMENTAL ---help--- This is the driver for the hardware watchdog on the ITE IT8702, - IT8712, IT8716, IT8718, IT8720, IT8726, IT8712 Super I/O chips. + IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 Super I/O chips. 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. diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index dad29245a6a7..e5c8b37bf739 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -12,7 +12,7 @@ * http://www.ite.com.tw/ * * Support of the watchdog timers, which are available on - * IT8702, IT8712, IT8716, IT8718, IT8720 and IT8726. + * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721 and IT8726. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -45,7 +45,7 @@ #include -#define WATCHDOG_VERSION "1.13" +#define WATCHDOG_VERSION "1.14" #define WATCHDOG_NAME "IT87 WDT" #define PFX WATCHDOG_NAME ": " #define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" @@ -82,6 +82,7 @@ #define IT8716_ID 0x8716 #define IT8718_ID 0x8718 #define IT8720_ID 0x8720 +#define IT8721_ID 0x8721 #define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ /* GPIO Configuration Registers LDN=0x07 */ @@ -94,7 +95,7 @@ #define WDT_CIRINT 0x80 #define WDT_MOUSEINT 0x40 #define WDT_KYBINT 0x20 -#define WDT_GAMEPORT 0x10 /* not in it8718, it8720 */ +#define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721 */ #define WDT_FORCE 0x02 #define WDT_ZERO 0x01 @@ -102,7 +103,7 @@ #define WDT_TOV1 0x80 #define WDT_KRST 0x40 #define WDT_TOVE 0x20 -#define WDT_PWROK 0x10 +#define WDT_PWROK 0x10 /* not in it8721 */ #define WDT_INT_MASK 0x0f /* CIR Configuration Register LDN=0x0a */ @@ -134,7 +135,7 @@ #define WDTS_USE_GP 4 #define WDTS_EXPECTED 5 -static unsigned int base, gpact, ciract, max_units; +static unsigned int base, gpact, ciract, max_units, chip_type; static unsigned long wdt_status; static DEFINE_SPINLOCK(spinlock); @@ -215,7 +216,7 @@ static inline void superio_outw(int val, int reg) /* Internal function, should be called after superio_select(GPIO) */ static void wdt_update_timeout(void) { - unsigned char cfg = WDT_KRST | WDT_PWROK; + unsigned char cfg = WDT_KRST; int tm = timeout; if (testmode) @@ -226,6 +227,9 @@ static void wdt_update_timeout(void) else tm /= 60; + if (chip_type != IT8721_ID) + cfg |= WDT_PWROK; + superio_outb(cfg, WDTCFG); superio_outb(tm, WDTVALLSB); if (max_units > 255) @@ -555,7 +559,6 @@ static int __init it87_wdt_init(void) { int rc = 0; int try_gameport = !nogameport; - u16 chip_type; u8 chip_rev; unsigned long flags; @@ -581,6 +584,7 @@ static int __init it87_wdt_init(void) break; case IT8718_ID: case IT8720_ID: + case IT8721_ID: max_units = 65535; try_gameport = 0; break; -- cgit v1.2.2 From f865c35224bb310a1b464062ae1e946d261708e3 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 5 Dec 2010 21:08:22 +0100 Subject: watchdog: add JZ4740 watchdog driver Adds support for the hardware watchdog found in Ingenic's jz4740 System-on-Chip. Signed-off-by: Paul Cercueil Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 6 + drivers/watchdog/Makefile | 1 + drivers/watchdog/jz4740_wdt.c | 315 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 322 insertions(+) create mode 100644 drivers/watchdog/jz4740_wdt.c (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 229a9c1506b6..6041692e2107 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -905,6 +905,12 @@ config INDYDOG timer expired and no process has written to /dev/watchdog during that time. +config JZ4740_WDT + tristate "Ingenic jz4740 SoC hardware watchdog" + depends on MACH_JZ4740 + help + Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs. + config WDT_MTX1 tristate "MTX-1 Hardware Watchdog" depends on MIPS_MTX1 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 20e44c4782b3..fd9c8c073a0a 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -114,6 +114,7 @@ obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o obj-$(CONFIG_INDYDOG) += indydog.o +obj-$(CONFIG_JZ4740_WDT) += jz4740_wdt.o obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c new file mode 100644 index 000000000000..935562322b38 --- /dev/null +++ b/drivers/watchdog/jz4740_wdt.c @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2010, Paul Cercueil + * JZ4740 Watchdog driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define JZ_REG_WDT_TIMER_DATA 0x0 +#define JZ_REG_WDT_COUNTER_ENABLE 0x4 +#define JZ_REG_WDT_TIMER_COUNTER 0x8 +#define JZ_REG_WDT_TIMER_CONTROL 0xC + +#define JZ_WDT_CLOCK_PCLK 0x1 +#define JZ_WDT_CLOCK_RTC 0x2 +#define JZ_WDT_CLOCK_EXT 0x4 + +#define WDT_IN_USE 0 +#define WDT_OK_TO_CLOSE 1 + +#define JZ_WDT_CLOCK_DIV_SHIFT 3 + +#define JZ_WDT_CLOCK_DIV_1 (0 << JZ_WDT_CLOCK_DIV_SHIFT) +#define JZ_WDT_CLOCK_DIV_4 (1 << JZ_WDT_CLOCK_DIV_SHIFT) +#define JZ_WDT_CLOCK_DIV_16 (2 << JZ_WDT_CLOCK_DIV_SHIFT) +#define JZ_WDT_CLOCK_DIV_64 (3 << JZ_WDT_CLOCK_DIV_SHIFT) +#define JZ_WDT_CLOCK_DIV_256 (4 << JZ_WDT_CLOCK_DIV_SHIFT) +#define JZ_WDT_CLOCK_DIV_1024 (5 << JZ_WDT_CLOCK_DIV_SHIFT) + +#define DEFAULT_HEARTBEAT 5 +#define MAX_HEARTBEAT 2048 + +static struct { + void __iomem *base; + struct resource *mem; + struct clk *rtc_clk; + unsigned long status; +} jz4740_wdt; + +static int heartbeat = DEFAULT_HEARTBEAT; + + +static void jz4740_wdt_service(void) +{ + writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER); +} + +static void jz4740_wdt_set_heartbeat(int new_heartbeat) +{ + unsigned int rtc_clk_rate; + unsigned int timeout_value; + unsigned short clock_div = JZ_WDT_CLOCK_DIV_1; + + heartbeat = new_heartbeat; + + rtc_clk_rate = clk_get_rate(jz4740_wdt.rtc_clk); + + timeout_value = rtc_clk_rate * heartbeat; + while (timeout_value > 0xffff) { + if (clock_div == JZ_WDT_CLOCK_DIV_1024) { + /* Requested timeout too high; + * use highest possible value. */ + timeout_value = 0xffff; + break; + } + timeout_value >>= 2; + clock_div += (1 << JZ_WDT_CLOCK_DIV_SHIFT); + } + + writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE); + writew(clock_div, jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL); + + writew((u16)timeout_value, jz4740_wdt.base + JZ_REG_WDT_TIMER_DATA); + writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER); + writew(clock_div | JZ_WDT_CLOCK_RTC, + jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL); + + writeb(0x1, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE); +} + +static void jz4740_wdt_enable(void) +{ + jz4740_timer_enable_watchdog(); + jz4740_wdt_set_heartbeat(heartbeat); +} + +static void jz4740_wdt_disable(void) +{ + jz4740_timer_disable_watchdog(); + writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE); +} + +static int jz4740_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_IN_USE, &jz4740_wdt.status)) + return -EBUSY; + + jz4740_wdt_enable(); + + return nonseekable_open(inode, file); +} + +static ssize_t jz4740_wdt_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + if (len) { + if (data[len-1] == 'V') + set_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status); + else + clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status); + + jz4740_wdt_service(); + } + + return len; +} + +static const struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING, + .identity = "jz4740 Watchdog", +}; + +static long jz4740_wdt_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret = -ENOTTY; + int heartbeat_seconds; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + ret = put_user(0, (int *)arg); + break; + + case WDIOC_KEEPALIVE: + jz4740_wdt_service(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(heartbeat_seconds, (int __user *)arg)) + return -EFAULT; + + jz4740_wdt_set_heartbeat(heartbeat_seconds); + return 0; + + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, (int *)arg); + + default: + break; + } + + return ret; +} + +static int jz4740_wdt_release(struct inode *inode, struct file *file) +{ + jz4740_wdt_service(); + + if (test_and_clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status)) + jz4740_wdt_disable(); + + clear_bit(WDT_IN_USE, &jz4740_wdt.status); + return 0; +} + +static const struct file_operations jz4740_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = jz4740_wdt_write, + .unlocked_ioctl = jz4740_wdt_ioctl, + .open = jz4740_wdt_open, + .release = jz4740_wdt_release, +}; + +static struct miscdevice jz4740_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &jz4740_wdt_fops, +}; + +static int __devinit jz4740_wdt_probe(struct platform_device *pdev) +{ + int ret = 0, size; + struct resource *res; + struct device *dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(dev, "failed to get memory region resource\n"); + return -ENXIO; + } + + size = resource_size(res); + jz4740_wdt.mem = request_mem_region(res->start, size, pdev->name); + if (jz4740_wdt.mem == NULL) { + dev_err(dev, "failed to get memory region\n"); + return -EBUSY; + } + + jz4740_wdt.base = ioremap_nocache(res->start, size); + if (jz4740_wdt.base == NULL) { + dev_err(dev, "failed to map memory region\n"); + ret = -EBUSY; + goto err_release_region; + } + + jz4740_wdt.rtc_clk = clk_get(NULL, "rtc"); + if (IS_ERR(jz4740_wdt.rtc_clk)) { + dev_err(dev, "cannot find RTC clock\n"); + ret = PTR_ERR(jz4740_wdt.rtc_clk); + goto err_iounmap; + } + + ret = misc_register(&jz4740_wdt_miscdev); + if (ret < 0) { + dev_err(dev, "cannot register misc device\n"); + goto err_disable_clk; + } + + return 0; + +err_disable_clk: + clk_put(jz4740_wdt.rtc_clk); +err_iounmap: + iounmap(jz4740_wdt.base); +err_release_region: + release_mem_region(jz4740_wdt.mem->start, + resource_size(jz4740_wdt.mem)); + return ret; +} + + +static int __devexit jz4740_wdt_remove(struct platform_device *pdev) +{ + jz4740_wdt_disable(); + misc_deregister(&jz4740_wdt_miscdev); + clk_put(jz4740_wdt.rtc_clk); + + iounmap(jz4740_wdt.base); + jz4740_wdt.base = NULL; + + release_mem_region(jz4740_wdt.mem->start, + resource_size(jz4740_wdt.mem)); + jz4740_wdt.mem = NULL; + + return 0; +} + + +static struct platform_driver jz4740_wdt_driver = { + .probe = jz4740_wdt_probe, + .remove = __devexit_p(jz4740_wdt_remove), + .driver = { + .name = "jz4740-wdt", + .owner = THIS_MODULE, + }, +}; + + +static int __init jz4740_wdt_init(void) +{ + return platform_driver_register(&jz4740_wdt_driver); +} +module_init(jz4740_wdt_init); + +static void __exit jz4740_wdt_exit(void) +{ + platform_driver_unregister(&jz4740_wdt_driver); +} +module_exit(jz4740_wdt_exit); + +MODULE_AUTHOR("Paul Cercueil "); +MODULE_DESCRIPTION("jz4740 Watchdog Driver"); + +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, + "Watchdog heartbeat period in seconds from 1 to " + __MODULE_STRING(MAX_HEARTBEAT) ", default " + __MODULE_STRING(DEFAULT_HEARTBEAT)); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS("platform:jz4740-wdt"); -- cgit v1.2.2 From 742e4b630895d751812b0682750db76c8072bf37 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sun, 16 Jan 2011 19:05:39 +0000 Subject: watchdog: jz4740_wdt - fix magic character checking When writing to /dev/watchdog all characters should be checked for the magic character 'V'. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/jz4740_wdt.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index 935562322b38..684ba01fb540 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -130,11 +130,18 @@ static ssize_t jz4740_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) { if (len) { - if (data[len-1] == 'V') - set_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status); - else - clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status); + size_t i; + clear_bit(WDT_OK_TO_CLOSE, &jz4740_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, &jz4740_wdt.status); + } jz4740_wdt_service(); } -- cgit v1.2.2 From 57539c1cf9f146ab9988a350dbc2d7e69a8a5c30 Mon Sep 17 00:00:00 2001 From: Donald Johnson Date: Wed, 2 Feb 2011 16:20:16 +0000 Subject: watchdog: Intel SCU Watchdog Timer Driver for Moorestown and Medfield platforms. This submission includes: - Fix to intel_scu_write() to start watchdog timer the on the first write, and refresh on subsequent writes. This enables Open, write, write, ... usage model. - Moves boot parameter checks from intel_scu_open() to intel_scu_watchdog_init(), so driver init will fail if these parameters are out of bounds. - Adds check for whether process waiting in wait_event_interruptible() received a signal while it was waiting. - Other small error handling changes. Removed the read() method for now as that wass a non-standard behaviour. Signed-off-by: Donald Johnson Signed-off-by: Shuduo Sang Signed-off-by: Alan Cox Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 10 + drivers/watchdog/Makefile | 1 + drivers/watchdog/intel_scu_watchdog.c | 572 ++++++++++++++++++++++++++++++++++ drivers/watchdog/intel_scu_watchdog.h | 66 ++++ 4 files changed, 649 insertions(+) create mode 100644 drivers/watchdog/intel_scu_watchdog.c create mode 100644 drivers/watchdog/intel_scu_watchdog.h (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 6041692e2107..28a9835f8256 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -533,6 +533,16 @@ config I6300ESB_WDT To compile this driver as a module, choose M here: the module will be called i6300esb. +config INTEL_SCU_WATCHDOG + bool "Intel SCU Watchdog for Mobile Platforms" + depends on WATCHDOG + depends on INTEL_SCU_IPC + ---help--- + Hardware driver for the watchdog time built into the Intel SCU + for Intel Mobile Platforms. + + To compile this driver as a module, choose M here. + config ITCO_WDT tristate "Intel TCO Timer/Watchdog" depends on (X86 || IA64) && PCI diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index fd9c8c073a0a..b037f3d0ec1a 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o +obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o # M32R Architecture diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c new file mode 100644 index 000000000000..919bdd16136f --- /dev/null +++ b/drivers/watchdog/intel_scu_watchdog.c @@ -0,0 +1,572 @@ +/* + * Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device + * for Intel part #(s): + * - AF82MP20 PCH + * + * Copyright (C) 2009-2010 Intel Corporation. All rights reserved. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "intel_scu_watchdog.h" + +/* Bounds number of times we will retry loading time count */ +/* This retry is a work around for a silicon bug. */ +#define MAX_RETRY 16 + +#define IPC_SET_WATCHDOG_TIMER 0xF8 + +static int timer_margin = DEFAULT_SOFT_TO_HARD_MARGIN; +module_param(timer_margin, int, 0); +MODULE_PARM_DESC(timer_margin, + "Watchdog timer margin" + "Time between interrupt and resetting the system" + "The range is from 1 to 160" + "This is the time for all keep alives to arrive"); + +static int timer_set = DEFAULT_TIME; +module_param(timer_set, int, 0); +MODULE_PARM_DESC(timer_set, + "Default Watchdog timer setting" + "Complete cycle time" + "The range is from 1 to 170" + "This is the time for all keep alives to arrive"); + +/* After watchdog device is closed, check force_boot. If: + * force_boot == 0, then force boot on next watchdog interrupt after close, + * force_boot == 1, then force boot immediately when device is closed. + */ +static int force_boot; +module_param(force_boot, int, 0); +MODULE_PARM_DESC(force_boot, + "A value of 1 means that the driver will reboot" + "the system immediately if the /dev/watchdog device is closed" + "A value of 0 means that when /dev/watchdog device is closed" + "the watchdog timer will be refreshed for one more interval" + "of length: timer_set. At the end of this interval, the" + "watchdog timer will reset the system." + ); + +/* there is only one device in the system now; this can be made into + * an array in the future if we have more than one device */ + +static struct intel_scu_watchdog_dev watchdog_device; + +/* Forces restart, if force_reboot is set */ +static void watchdog_fire(void) +{ + if (force_boot) { + printk(KERN_CRIT PFX "Initiating system reboot.\n"); + emergency_restart(); + printk(KERN_CRIT PFX "Reboot didn't ?????\n"); + } + + else { + printk(KERN_CRIT PFX "Immediate Reboot Disabled\n"); + printk(KERN_CRIT PFX + "System will reset when watchdog timer times out!\n"); + } +} + +static int check_timer_margin(int new_margin) +{ + if ((new_margin < MIN_TIME_CYCLE) || + (new_margin > MAX_TIME - timer_set)) { + pr_debug("Watchdog timer: value of new_margin %d is out of the range %d to %d\n", + new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set); + return -EINVAL; + } + return 0; +} + +/* + * IPC operations + */ +static int watchdog_set_ipc(int soft_threshold, int threshold) +{ + u32 *ipc_wbuf; + u8 cbuf[16] = { '\0' }; + int ipc_ret = 0; + + ipc_wbuf = (u32 *)&cbuf; + ipc_wbuf[0] = soft_threshold; + ipc_wbuf[1] = threshold; + + ipc_ret = intel_scu_ipc_command( + IPC_SET_WATCHDOG_TIMER, + 0, + ipc_wbuf, + 2, + NULL, + 0); + + if (ipc_ret != 0) + pr_err("Error setting SCU watchdog timer: %x\n", ipc_ret); + + return ipc_ret; +}; + +/* + * Intel_SCU operations + */ + +/* timer interrupt handler */ +static irqreturn_t watchdog_timer_interrupt(int irq, void *dev_id) +{ + int int_status; + int_status = ioread32(watchdog_device.timer_interrupt_status_addr); + + pr_debug("Watchdog timer: irq, int_status: %x\n", int_status); + + if (int_status != 0) + return IRQ_NONE; + + /* has the timer been started? If not, then this is spurious */ + if (watchdog_device.timer_started == 0) { + pr_debug("Watchdog timer: spurious interrupt received\n"); + return IRQ_HANDLED; + } + + /* temporarily disable the timer */ + iowrite32(0x00000002, watchdog_device.timer_control_addr); + + /* set the timer to the threshold */ + iowrite32(watchdog_device.threshold, + watchdog_device.timer_load_count_addr); + + /* allow the timer to run */ + iowrite32(0x00000003, watchdog_device.timer_control_addr); + + return IRQ_HANDLED; +} + +static int intel_scu_keepalive(void) +{ + + /* read eoi register - clears interrupt */ + ioread32(watchdog_device.timer_clear_interrupt_addr); + + /* temporarily disable the timer */ + iowrite32(0x00000002, watchdog_device.timer_control_addr); + + /* set the timer to the soft_threshold */ + iowrite32(watchdog_device.soft_threshold, + watchdog_device.timer_load_count_addr); + + /* allow the timer to run */ + iowrite32(0x00000003, watchdog_device.timer_control_addr); + + return 0; +} + +static int intel_scu_stop(void) +{ + iowrite32(0, watchdog_device.timer_control_addr); + return 0; +} + +static int intel_scu_set_heartbeat(u32 t) +{ + int ipc_ret; + int retry_count; + u32 soft_value; + u32 hw_pre_value; + u32 hw_value; + + watchdog_device.timer_set = t; + watchdog_device.threshold = + timer_margin * watchdog_device.timer_tbl_ptr->freq_hz; + watchdog_device.soft_threshold = + (watchdog_device.timer_set - timer_margin) + * watchdog_device.timer_tbl_ptr->freq_hz; + + pr_debug("Watchdog timer: set_heartbeat: timer freq is %d\n", + watchdog_device.timer_tbl_ptr->freq_hz); + pr_debug("Watchdog timer: set_heartbeat: timer_set is %x (hex)\n", + watchdog_device.timer_set); + pr_debug("Watchdog timer: set_hearbeat: timer_margin is %x (hex)\n", + timer_margin); + pr_debug("Watchdog timer: set_heartbeat: threshold is %x (hex)\n", + watchdog_device.threshold); + pr_debug("Watchdog timer: set_heartbeat: soft_threshold is %x (hex)\n", + watchdog_device.soft_threshold); + + /* Adjust thresholds by FREQ_ADJUSTMENT factor, to make the */ + /* watchdog timing come out right. */ + watchdog_device.threshold = + watchdog_device.threshold / FREQ_ADJUSTMENT; + watchdog_device.soft_threshold = + watchdog_device.soft_threshold / FREQ_ADJUSTMENT; + + /* temporarily disable the timer */ + iowrite32(0x00000002, watchdog_device.timer_control_addr); + + /* send the threshold and soft_threshold via IPC to the processor */ + ipc_ret = watchdog_set_ipc(watchdog_device.soft_threshold, + watchdog_device.threshold); + + if (ipc_ret != 0) { + /* Make sure the watchdog timer is stopped */ + intel_scu_stop(); + return ipc_ret; + } + + /* Soft Threshold set loop. Early versions of silicon did */ + /* not always set this count correctly. This loop checks */ + /* the value and retries if it was not set correctly. */ + + retry_count = 0; + soft_value = watchdog_device.soft_threshold & 0xFFFF0000; + do { + + /* Make sure timer is stopped */ + intel_scu_stop(); + + if (MAX_RETRY < retry_count++) { + /* Unable to set timer value */ + pr_err("Watchdog timer: Unable to set timer\n"); + return -ENODEV; + } + + /* set the timer to the soft threshold */ + iowrite32(watchdog_device.soft_threshold, + watchdog_device.timer_load_count_addr); + + /* read count value before starting timer */ + hw_pre_value = ioread32(watchdog_device.timer_load_count_addr); + hw_pre_value = hw_pre_value & 0xFFFF0000; + + /* Start the timer */ + iowrite32(0x00000003, watchdog_device.timer_control_addr); + + /* read the value the time loaded into its count reg */ + hw_value = ioread32(watchdog_device.timer_load_count_addr); + hw_value = hw_value & 0xFFFF0000; + + + } while (soft_value != hw_value); + + watchdog_device.timer_started = 1; + + return 0; +} + +/* + * /dev/watchdog handling + */ + +static int intel_scu_open(struct inode *inode, struct file *file) +{ + + /* Set flag to indicate that watchdog device is open */ + if (test_and_set_bit(0, &watchdog_device.driver_open)) + return -EBUSY; + + /* Check for reopen of driver. Reopens are not allowed */ + if (watchdog_device.driver_closed) + return -EPERM; + + return nonseekable_open(inode, file); +} + +static int intel_scu_release(struct inode *inode, struct file *file) +{ + /* + * This watchdog should not be closed, after the timer + * is started with the WDIPC_SETTIMEOUT ioctl + * If force_boot is set watchdog_fire() will cause an + * immediate reset. If force_boot is not set, the watchdog + * timer is refreshed for one more interval. At the end + * of that interval, the watchdog timer will reset the system. + */ + + if (!test_and_clear_bit(0, &watchdog_device.driver_open)) { + pr_debug("Watchdog timer: intel_scu_release, without open\n"); + return -ENOTTY; + } + + if (!watchdog_device.timer_started) { + /* Just close, since timer has not been started */ + pr_debug("Watchdog timer: closed, without starting timer\n"); + return 0; + } + + printk(KERN_CRIT PFX + "Unexpected close of /dev/watchdog!\n"); + + /* Since the timer was started, prevent future reopens */ + watchdog_device.driver_closed = 1; + + /* Refresh the timer for one more interval */ + intel_scu_keepalive(); + + /* Reboot system (if force_boot is set) */ + watchdog_fire(); + + /* We should only reach this point if force_boot is not set */ + return 0; +} + +static ssize_t intel_scu_write(struct file *file, + char const *data, + size_t len, + loff_t *ppos) +{ + + if (watchdog_device.timer_started) + /* Watchdog already started, keep it alive */ + intel_scu_keepalive(); + else + /* Start watchdog with timer value set by init */ + intel_scu_set_heartbeat(watchdog_device.timer_set); + + return len; +} + +static long intel_scu_ioctl(struct file *file, + unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + u32 __user *p = argp; + u32 new_margin; + + + static const struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT + | WDIOF_KEEPALIVEPING, + .firmware_version = 0, /* @todo Get from SCU via + ipc_get_scu_fw_version()? */ + .identity = "Intel_SCU IOH Watchdog" /* len < 32 */ + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, + &ident, + sizeof(ident)) ? -EFAULT : 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + case WDIOC_KEEPALIVE: + intel_scu_keepalive(); + + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, p)) + return -EFAULT; + + if (check_timer_margin(new_margin)) + return -EINVAL; + + if (intel_scu_set_heartbeat(new_margin)) + return -EINVAL; + return 0; + case WDIOC_GETTIMEOUT: + return put_user(watchdog_device.soft_threshold, p); + + default: + return -ENOTTY; + } +} + +/* + * Notifier for system down + */ +static int intel_scu_notify_sys(struct notifier_block *this, + unsigned long code, + void *another_unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + /* Turn off the watchdog timer. */ + intel_scu_stop(); + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ +static const struct file_operations intel_scu_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = intel_scu_write, + .unlocked_ioctl = intel_scu_ioctl, + .open = intel_scu_open, + .release = intel_scu_release, +}; + +static int __init intel_scu_watchdog_init(void) +{ + int ret; + u32 __iomem *tmp_addr; + + /* + * We don't really need to check this as the SFI timer get will fail + * but if we do so we can exit with a clearer reason and no noise. + * + * If it isn't an intel MID device then it doesn't have this watchdog + */ + if (!mrst_identify_cpu()) + return -ENODEV; + + /* Check boot parameters to verify that their initial values */ + /* are in range. */ + /* Check value of timer_set boot parameter */ + if ((timer_set < MIN_TIME_CYCLE) || + (timer_set > MAX_TIME - MIN_TIME_CYCLE)) { + pr_err("Watchdog timer: value of timer_set %x (hex) " + "is out of range from %x to %x (hex)\n", + timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE); + return -EINVAL; + } + + /* Check value of timer_margin boot parameter */ + if (check_timer_margin(timer_margin)) + return -EINVAL; + + watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1); + + if (watchdog_device.timer_tbl_ptr == NULL) { + pr_debug("Watchdog timer - Intel SCU watchdog: timer is not available\n"); + return -ENODEV; + } + /* make sure the timer exists */ + if (watchdog_device.timer_tbl_ptr->phys_addr == 0) { + pr_debug("Watchdog timer - Intel SCU watchdog - timer %d does not have valid physical memory\n", + sfi_mtimer_num); + return -ENODEV; + } + + if (watchdog_device.timer_tbl_ptr->irq == 0) { + pr_debug("Watchdog timer: timer %d invalid irq\n", + sfi_mtimer_num); + return -ENODEV; + } + + tmp_addr = ioremap_nocache(watchdog_device.timer_tbl_ptr->phys_addr, + 20); + + if (tmp_addr == NULL) { + pr_debug("Watchdog timer: timer unable to ioremap\n"); + return -ENOMEM; + } + + watchdog_device.timer_load_count_addr = tmp_addr++; + watchdog_device.timer_current_value_addr = tmp_addr++; + watchdog_device.timer_control_addr = tmp_addr++; + watchdog_device.timer_clear_interrupt_addr = tmp_addr++; + watchdog_device.timer_interrupt_status_addr = tmp_addr++; + + /* Set the default time values in device structure */ + + watchdog_device.timer_set = timer_set; + watchdog_device.threshold = + timer_margin * watchdog_device.timer_tbl_ptr->freq_hz; + watchdog_device.soft_threshold = + (watchdog_device.timer_set - timer_margin) + * watchdog_device.timer_tbl_ptr->freq_hz; + + + watchdog_device.intel_scu_notifier.notifier_call = + intel_scu_notify_sys; + + ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier); + if (ret) { + pr_err("Watchdog timer: cannot register notifier %d)\n", ret); + goto register_reboot_error; + } + + watchdog_device.miscdev.minor = WATCHDOG_MINOR; + watchdog_device.miscdev.name = "watchdog"; + watchdog_device.miscdev.fops = &intel_scu_fops; + + ret = misc_register(&watchdog_device.miscdev); + if (ret) { + pr_err("Watchdog timer: cannot register miscdev %d err =%d\n", + WATCHDOG_MINOR, ret); + goto misc_register_error; + } + + ret = request_irq((unsigned int)watchdog_device.timer_tbl_ptr->irq, + watchdog_timer_interrupt, + IRQF_SHARED, "watchdog", + &watchdog_device.timer_load_count_addr); + if (ret) { + pr_err("Watchdog timer: error requesting irq %d\n", ret); + goto request_irq_error; + } + /* Make sure timer is disabled before returning */ + intel_scu_stop(); + return 0; + +/* error cleanup */ + +request_irq_error: + misc_deregister(&watchdog_device.miscdev); +misc_register_error: + unregister_reboot_notifier(&watchdog_device.intel_scu_notifier); +register_reboot_error: + intel_scu_stop(); + iounmap(watchdog_device.timer_load_count_addr); + return ret; +} + +static void __exit intel_scu_watchdog_exit(void) +{ + + misc_deregister(&watchdog_device.miscdev); + unregister_reboot_notifier(&watchdog_device.intel_scu_notifier); + /* disable the timer */ + iowrite32(0x00000002, watchdog_device.timer_control_addr); + iounmap(watchdog_device.timer_load_count_addr); +} + +late_initcall(intel_scu_watchdog_init); +module_exit(intel_scu_watchdog_exit); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Intel SCU Watchdog Device Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_VERSION(WDT_VER); diff --git a/drivers/watchdog/intel_scu_watchdog.h b/drivers/watchdog/intel_scu_watchdog.h new file mode 100644 index 000000000000..d2b074a82db6 --- /dev/null +++ b/drivers/watchdog/intel_scu_watchdog.h @@ -0,0 +1,66 @@ +/* + * Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device + * for Intel part #(s): + * - AF82MP20 PCH + * + * Copyright (C) 2009-2010 Intel Corporation. All rights reserved. + * + * 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. + * + */ + +#ifndef __INTEL_SCU_WATCHDOG_H +#define __INTEL_SCU_WATCHDOG_H + +#define PFX "Intel_SCU: " +#define WDT_VER "0.3" + +/* minimum time between interrupts */ +#define MIN_TIME_CYCLE 1 + +/* Time from warning to reboot is 2 seconds */ +#define DEFAULT_SOFT_TO_HARD_MARGIN 2 + +#define MAX_TIME 170 + +#define DEFAULT_TIME 5 + +#define MAX_SOFT_TO_HARD_MARGIN (MAX_TIME-MIN_TIME_CYCLE) + +/* Ajustment to clock tick frequency to make timing come out right */ +#define FREQ_ADJUSTMENT 8 + +struct intel_scu_watchdog_dev { + ulong driver_open; + ulong driver_closed; + u32 timer_started; + u32 timer_set; + u32 threshold; + u32 soft_threshold; + u32 __iomem *timer_load_count_addr; + u32 __iomem *timer_current_value_addr; + u32 __iomem *timer_control_addr; + u32 __iomem *timer_clear_interrupt_addr; + u32 __iomem *timer_interrupt_status_addr; + struct sfi_timer_table_entry *timer_tbl_ptr; + struct notifier_block intel_scu_notifier; + struct miscdevice miscdev; +}; + +extern int sfi_mtimer_num; + +/* extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint); */ +#endif /* __INTEL_SCU_WATCHDOG_H */ -- cgit v1.2.2 From 066d6c7f4ec94d40d13061714489783916548cdb Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 4 Oct 2010 10:37:26 +0100 Subject: watchdog: Xen watchdog driver While the hypervisor change adding SCHEDOP_watchdog support included a daemon to make use of the new functionality, having a kernel driver for /dev/watchdog so that user space code doesn't need to distinguish non-Xen and Xen seems to be preferable. Signed-off-by: Jan Beulich Cc: Jeremy Fitzhardinge Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 10 ++ drivers/watchdog/Makefile | 3 + drivers/watchdog/xen_wdt.c | 359 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 372 insertions(+) create mode 100644 drivers/watchdog/xen_wdt.c (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 28a9835f8256..6c216f91b953 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1137,6 +1137,16 @@ config WATCHDOG_RIO # XTENSA Architecture +# Xen Architecture + +config XEN_WDT + tristate "Xen Watchdog support" + depends on XEN + help + Say Y here to support the hypervisor watchdog capability provided + by Xen 4.0 and newer. The watchdog timeout period is normally one + minute but can be changed with a boot-time parameter. + # # ISA-based Watchdog Cards # diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index b037f3d0ec1a..d520bf9c3355 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -150,6 +150,9 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o # XTENSA Architecture +# Xen +obj-$(CONFIG_XEN_WDT) += xen_wdt.o + # Architecture Independant obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o diff --git a/drivers/watchdog/xen_wdt.c b/drivers/watchdog/xen_wdt.c new file mode 100644 index 000000000000..49bd9d395562 --- /dev/null +++ b/drivers/watchdog/xen_wdt.c @@ -0,0 +1,359 @@ +/* + * Xen Watchdog Driver + * + * (c) Copyright 2010 Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define DRV_NAME "wdt" +#define DRV_VERSION "0.01" +#define PFX DRV_NAME ": " + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct platform_device *platform_device; +static DEFINE_SPINLOCK(wdt_lock); +static struct sched_watchdog wdt; +static __kernel_time_t wdt_expires; +static bool is_active, expect_release; + +#define WATCHDOG_TIMEOUT 60 /* in seconds */ +static unsigned int timeout = WATCHDOG_TIMEOUT; +module_param(timeout, uint, S_IRUGO); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds " + "(default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, S_IRUGO); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " + "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static inline __kernel_time_t set_timeout(void) +{ + wdt.timeout = timeout; + return ktime_to_timespec(ktime_get()).tv_sec + timeout; +} + +static int xen_wdt_start(void) +{ + __kernel_time_t expires; + int err; + + spin_lock(&wdt_lock); + + expires = set_timeout(); + if (!wdt.id) + err = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wdt); + else + err = -EBUSY; + if (err > 0) { + wdt.id = err; + wdt_expires = expires; + err = 0; + } else + BUG_ON(!err); + + spin_unlock(&wdt_lock); + + return err; +} + +static int xen_wdt_stop(void) +{ + int err = 0; + + spin_lock(&wdt_lock); + + wdt.timeout = 0; + if (wdt.id) + err = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wdt); + if (!err) + wdt.id = 0; + + spin_unlock(&wdt_lock); + + return err; +} + +static int xen_wdt_kick(void) +{ + __kernel_time_t expires; + int err; + + spin_lock(&wdt_lock); + + expires = set_timeout(); + if (wdt.id) + err = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wdt); + else + err = -ENXIO; + if (!err) + wdt_expires = expires; + + spin_unlock(&wdt_lock); + + return err; +} + +static int xen_wdt_open(struct inode *inode, struct file *file) +{ + int err; + + /* /dev/watchdog can only be opened once */ + if (xchg(&is_active, true)) + return -EBUSY; + + err = xen_wdt_start(); + if (err == -EBUSY) + err = xen_wdt_kick(); + return err ?: nonseekable_open(inode, file); +} + +static int xen_wdt_release(struct inode *inode, struct file *file) +{ + if (expect_release) + xen_wdt_stop(); + else { + printk(KERN_CRIT PFX + "unexpected close, not stopping watchdog!\n"); + xen_wdt_kick(); + } + is_active = false; + expect_release = false; + return 0; +} + +static ssize_t xen_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* in case it was set long ago */ + expect_release = false; + + /* scan to see whether or not we got the magic + character */ + for (i = 0; i != len; i++) { + char c; + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + expect_release = true; + } + } + + /* someone wrote to us, we should reload the timer */ + xen_wdt_kick(); + } + return len; +} + +static long xen_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int new_options, retval = -EINVAL; + int new_timeout; + int __user *argp = (void __user *)arg; + static const struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = DRV_NAME, + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, argp); + + case WDIOC_SETOPTIONS: + if (get_user(new_options, argp)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) + retval = xen_wdt_stop(); + if (new_options & WDIOS_ENABLECARD) { + retval = xen_wdt_start(); + if (retval == -EBUSY) + retval = xen_wdt_kick(); + } + return retval; + + case WDIOC_KEEPALIVE: + xen_wdt_kick(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, argp)) + return -EFAULT; + if (!new_timeout) + return -EINVAL; + timeout = new_timeout; + xen_wdt_kick(); + /* fall through */ + case WDIOC_GETTIMEOUT: + return put_user(timeout, argp); + + case WDIOC_GETTIMELEFT: + retval = wdt_expires - ktime_to_timespec(ktime_get()).tv_sec; + return put_user(retval, argp); + } + + return -ENOTTY; +} + +static const struct file_operations xen_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = xen_wdt_write, + .unlocked_ioctl = xen_wdt_ioctl, + .open = xen_wdt_open, + .release = xen_wdt_release, +}; + +static struct miscdevice xen_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &xen_wdt_fops, +}; + +static int __devinit xen_wdt_probe(struct platform_device *dev) +{ + struct sched_watchdog wd = { .id = ~0 }; + int ret = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wd); + + switch (ret) { + case -EINVAL: + if (!timeout) { + timeout = WATCHDOG_TIMEOUT; + printk(KERN_INFO PFX + "timeout value invalid, using %d\n", timeout); + } + + ret = misc_register(&xen_wdt_miscdev); + if (ret) { + printk(KERN_ERR PFX + "cannot register miscdev on minor=%d (%d)\n", + WATCHDOG_MINOR, ret); + break; + } + + printk(KERN_INFO PFX + "initialized (timeout=%ds, nowayout=%d)\n", + timeout, nowayout); + break; + + case -ENOSYS: + printk(KERN_INFO PFX "not supported\n"); + ret = -ENODEV; + break; + + default: + printk(KERN_INFO PFX "bogus return value %d\n", ret); + break; + } + + return ret; +} + +static int __devexit xen_wdt_remove(struct platform_device *dev) +{ + /* Stop the timer before we leave */ + if (!nowayout) + xen_wdt_stop(); + + misc_deregister(&xen_wdt_miscdev); + + return 0; +} + +static void xen_wdt_shutdown(struct platform_device *dev) +{ + xen_wdt_stop(); +} + +static int xen_wdt_suspend(struct platform_device *dev, pm_message_t state) +{ + return xen_wdt_stop(); +} + +static int xen_wdt_resume(struct platform_device *dev) +{ + return xen_wdt_start(); +} + +static struct platform_driver xen_wdt_driver = { + .probe = xen_wdt_probe, + .remove = __devexit_p(xen_wdt_remove), + .shutdown = xen_wdt_shutdown, + .suspend = xen_wdt_suspend, + .resume = xen_wdt_resume, + .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + }, +}; + +static int __init xen_wdt_init_module(void) +{ + int err; + + if (!xen_domain()) + return -ENODEV; + + printk(KERN_INFO PFX "Xen WatchDog Timer Driver v%s\n", DRV_VERSION); + + err = platform_driver_register(&xen_wdt_driver); + if (err) + return err; + + platform_device = platform_device_register_simple(DRV_NAME, + -1, NULL, 0); + if (IS_ERR(platform_device)) { + err = PTR_ERR(platform_device); + platform_driver_unregister(&xen_wdt_driver); + } + + return err; +} + +static void __exit xen_wdt_cleanup_module(void) +{ + platform_device_unregister(platform_device); + platform_driver_unregister(&xen_wdt_driver); + printk(KERN_INFO PFX "module unloaded\n"); +} + +module_init(xen_wdt_init_module); +module_exit(xen_wdt_cleanup_module); + +MODULE_AUTHOR("Jan Beulich "); +MODULE_DESCRIPTION("Xen WatchDog Timer Driver"); +MODULE_VERSION(DRV_VERSION); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.2 From 4562f53940432369df88e195ef8f9b642bdf7cd6 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 21 Feb 2011 12:16:44 +0000 Subject: watchdog: convert to DEFINE_PCI_DEVICE_TABLE Convert static struct pci_device_id *[] to static DEFINE_PCI_DEVICE_TABLE tables. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/alim1535_wdt.c | 2 +- drivers/watchdog/alim7101_wdt.c | 2 +- drivers/watchdog/hpwdt.c | 2 +- drivers/watchdog/i6300esb.c | 2 +- drivers/watchdog/iTCO_wdt.c | 2 +- drivers/watchdog/nv_tco.c | 2 +- drivers/watchdog/pcwd_pci.c | 2 +- drivers/watchdog/sp5100_tco.c | 2 +- drivers/watchdog/wdt_pci.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index fa4d36033552..f9e1b7eb6c49 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c @@ -301,7 +301,7 @@ static int ali_notify_sys(struct notifier_block *this, * want to register another driver on the same PCI id. */ -static struct pci_device_id ali_pci_tbl[] __used = { +static DEFINE_PCI_DEVICE_TABLE(ali_pci_tbl) __used = { { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,}, { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,}, { 0, }, diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index 4b7a2b4138ed..46f4b85b46de 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c @@ -430,7 +430,7 @@ err_out: module_init(alim7101_wdt_init); module_exit(alim7101_wdt_unload); -static struct pci_device_id alim7101_pci_tbl[] __devinitdata __used = { +static DEFINE_PCI_DEVICE_TABLE(alim7101_pci_tbl) __used = { { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) }, { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, { } diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 204a5603c4ae..8cb26855bfed 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -52,7 +52,7 @@ static void __iomem *pci_mem_addr; /* the PCI-memory address */ static unsigned long __iomem *hpwdt_timer_reg; static unsigned long __iomem *hpwdt_timer_con; -static struct pci_device_id hpwdt_devices[] = { +static DEFINE_PCI_DEVICE_TABLE(hpwdt_devices) = { { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, /* iLO2 */ { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, /* iLO3 */ {0}, /* terminate list */ diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index bb9750a03942..db45091ef434 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -334,7 +334,7 @@ static struct miscdevice esb_miscdev = { /* * Data for PCI driver interface */ -static struct pci_device_id esb_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(esb_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, { 0, }, /* End of list */ }; diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 2c6c2b4ad8bf..db0f5b85ba5f 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -262,7 +262,7 @@ static struct { * pci_driver, because the I/O Controller Hub has also other * functions that probably will be registered by other drivers. */ -static struct pci_device_id iTCO_wdt_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = { { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH)}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0)}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2)}, diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c index 1a50aa7079bf..267377a5a83e 100644 --- a/drivers/watchdog/nv_tco.c +++ b/drivers/watchdog/nv_tco.c @@ -289,7 +289,7 @@ static struct miscdevice nv_tco_miscdev = { * register a pci_driver, because someone else might one day * want to register another driver on the same PCI id. */ -static struct pci_device_id tco_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(tco_pci_tbl) = { { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS, diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c index 64374d636f09..b8d14f88f0b5 100644 --- a/drivers/watchdog/pcwd_pci.c +++ b/drivers/watchdog/pcwd_pci.c @@ -817,7 +817,7 @@ static void __devexit pcipcwd_card_exit(struct pci_dev *pdev) cards_found--; } -static struct pci_device_id pcipcwd_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(pcipcwd_pci_tbl) = { { PCI_VENDOR_ID_QUICKLOGIC, PCI_DEVICE_ID_WATCHDOG_PCIPCWD, PCI_ANY_ID, PCI_ANY_ID, }, { 0 }, /* End of list */ diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c index 808372883e88..1bc493848ed4 100644 --- a/drivers/watchdog/sp5100_tco.c +++ b/drivers/watchdog/sp5100_tco.c @@ -259,7 +259,7 @@ static struct miscdevice sp5100_tco_miscdev = { * register a pci_driver, because someone else might * want to register another driver on the same PCI id. */ -static struct pci_device_id sp5100_tco_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(sp5100_tco_pci_tbl) = { { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID, PCI_ANY_ID, }, { 0, }, /* End of list */ diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 6130c88fa5ac..97bb6fbdcf56 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -727,7 +727,7 @@ static void __devexit wdtpci_remove_one(struct pci_dev *pdev) } -static struct pci_device_id wdtpci_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(wdtpci_pci_tbl) = { { .vendor = PCI_VENDOR_ID_ACCESSIO, .device = PCI_DEVICE_ID_ACCESSIO_WDG_CSM, -- cgit v1.2.2 From 5f3b27569fc0286a51f8d0655c7fb4f5b36aea65 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 23 Feb 2011 20:04:38 +0000 Subject: watchdog: cleanup spaces before tabs cleanup spaces before tabs in drivers/watchdog/ Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/alim1535_wdt.c | 8 ++++---- drivers/watchdog/bcm47xx_wdt.c | 4 ++-- drivers/watchdog/bfin_wdt.c | 4 ++-- drivers/watchdog/cpwd.c | 36 ++++++++++++++++++------------------ drivers/watchdog/eurotechwdt.c | 2 +- drivers/watchdog/iTCO_wdt.c | 2 +- drivers/watchdog/it8712f_wdt.c | 2 +- drivers/watchdog/it87_wdt.c | 10 +++++----- drivers/watchdog/machzwd.c | 2 +- drivers/watchdog/max63xx_wdt.c | 2 +- drivers/watchdog/mpc8xxx_wdt.c | 6 +++--- drivers/watchdog/mpcore_wdt.c | 2 +- drivers/watchdog/mtx-1_wdt.c | 14 +++++++------- drivers/watchdog/omap_wdt.h | 2 +- drivers/watchdog/pc87413_wdt.c | 2 +- drivers/watchdog/pnx4008_wdt.c | 2 +- drivers/watchdog/s3c2410_wdt.c | 2 +- drivers/watchdog/sbc8360.c | 2 +- drivers/watchdog/sbc_fitpc2_wdt.c | 2 +- drivers/watchdog/smsc37b787_wdt.c | 4 ++-- drivers/watchdog/softdog.c | 2 +- drivers/watchdog/ts72xx_wdt.c | 2 +- drivers/watchdog/w83697ug_wdt.c | 4 ++-- drivers/watchdog/wdt.c | 2 +- drivers/watchdog/wdt977.c | 2 +- drivers/watchdog/wdt_pci.c | 4 ++-- 26 files changed, 63 insertions(+), 63 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index f9e1b7eb6c49..f16dcbd475fb 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c @@ -362,12 +362,12 @@ static int __init ali_find_watchdog(void) */ static const struct file_operations ali_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, + .owner = THIS_MODULE, + .llseek = no_llseek, .write = ali_write, .unlocked_ioctl = ali_ioctl, - .open = ali_open, - .release = ali_release, + .open = ali_open, + .release = ali_release, }; static struct miscdevice ali_miscdev = { diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c index 5f245522397b..bd44417c84d4 100644 --- a/drivers/watchdog/bcm47xx_wdt.c +++ b/drivers/watchdog/bcm47xx_wdt.c @@ -150,8 +150,8 @@ static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data, } static const struct watchdog_info bcm47xx_wdt_info = { - .identity = DRV_NAME, - .options = WDIOF_SETTIMEOUT | + .identity = DRV_NAME, + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, }; diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index 9042a95fc98c..b9fa9b71583a 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c @@ -63,7 +63,7 @@ static DEFINE_SPINLOCK(bfin_wdt_spinlock); /** * bfin_wdt_keepalive - Keep the Userspace Watchdog Alive * - * The Userspace watchdog got a KeepAlive: schedule the next timeout. + * The Userspace watchdog got a KeepAlive: schedule the next timeout. */ static int bfin_wdt_keepalive(void) { @@ -337,7 +337,7 @@ static int bfin_wdt_resume(struct platform_device *pdev) static const struct file_operations bfin_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .write = bfin_wdt_write, + .write = bfin_wdt_write, .unlocked_ioctl = bfin_wdt_ioctl, .open = bfin_wdt_open, .release = bfin_wdt_release, diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 3de4ba0260a5..1e60ff331b90 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -5,10 +5,10 @@ * interface and Solaris-compatible ioctls as best it is * able. * - * NOTE: CP1400 systems appear to have a defective intr_mask - * register on the PLD, preventing the disabling of - * timer interrupts. We use a timer to periodically - * reset 'stopped' watchdogs on affected platforms. + * NOTE: CP1400 systems appear to have a defective intr_mask + * register on the PLD, preventing the disabling of + * timer interrupts. We use a timer to periodically + * reset 'stopped' watchdogs on affected platforms. * * Copyright (c) 2000 Eric Brower (ebrower@usa.net) * Copyright (C) 2008 David S. Miller @@ -107,13 +107,13 @@ static struct cpwd *cpwd_device; * ------------------- * |- counter val -| * ------------------- - * dcntr - Current 16-bit downcounter value. - * When downcounter reaches '0' watchdog expires. - * Reading this register resets downcounter with - * 'limit' value. - * limit - 16-bit countdown value in 1/10th second increments. - * Writing this register begins countdown with input value. - * Reading from this register does not affect counter. + * dcntr - Current 16-bit downcounter value. + * When downcounter reaches '0' watchdog expires. + * Reading this register resets downcounter with + * 'limit' value. + * limit - 16-bit countdown value in 1/10th second increments. + * Writing this register begins countdown with input value. + * Reading from this register does not affect counter. * NOTES: After watchdog reset, dcntr and limit contain '1' * * status register (byte access): @@ -123,7 +123,7 @@ static struct cpwd *cpwd_device; * |- UNUSED -| EXP | RUN | * --------------------------- * status- Bit 0 - Watchdog is running - * Bit 1 - Watchdog has expired + * Bit 1 - Watchdog has expired * *** PLD register block definition (struct wd_pld_regblk) * @@ -197,7 +197,7 @@ static u8 cpwd_readb(void __iomem *addr) * Because of the CP1400 defect this should only be * called during initialzation or by wd_[start|stop]timer() * - * index - sub-device index, or -1 for 'all' + * index - sub-device index, or -1 for 'all' * enable - non-zero to enable interrupts, zero to disable */ static void cpwd_toggleintr(struct cpwd *p, int index, int enable) @@ -317,13 +317,13 @@ static int cpwd_getstatus(struct cpwd *p, int index) } else { /* Fudge WD_EXPIRED status for defective CP1400-- * IF timer is running - * AND brokenstop is set - * AND an interrupt has been serviced + * AND brokenstop is set + * AND an interrupt has been serviced * we are WD_EXPIRED. * * IF timer is running - * AND brokenstop is set - * AND no interrupt has been serviced + * AND brokenstop is set + * AND no interrupt has been serviced * we are WD_FREERUN. */ if (p->broken && @@ -614,7 +614,7 @@ static int __devinit cpwd_probe(struct platform_device *op, if (p->broken) { init_timer(&cpwd_timer); - cpwd_timer.function = cpwd_brokentimer; + cpwd_timer.function = cpwd_brokentimer; cpwd_timer.data = (unsigned long) p; cpwd_timer.expires = WD_BTIMEOUT; diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index 3f3dc093ad68..f1d1da662fbe 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c @@ -201,7 +201,7 @@ static void eurwdt_ping(void) static ssize_t eurwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - if (count) { + if (count) { if (!nowayout) { size_t i; diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index db0f5b85ba5f..35a0d12dad73 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -247,7 +247,7 @@ static struct { {NULL, 0} }; -#define ITCO_PCI_DEVICE(dev, data) \ +#define ITCO_PCI_DEVICE(dev, data) \ .vendor = PCI_VENDOR_ID_INTEL, \ .device = dev, \ .subvendor = PCI_ANY_ID, \ diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index b32c6c045b1a..6143f52ba6b8 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c @@ -69,7 +69,7 @@ static unsigned short address; #define IT8712F_DEVID 0x8712 #define LDN_GPIO 0x07 /* GPIO and Watch Dog Timer */ -#define LDN_GAME 0x09 /* Game Port */ +#define LDN_GAME 0x09 /* Game Port */ #define WDT_CONTROL 0x71 /* WDT Register: Control */ #define WDT_CONFIG 0x72 /* WDT Register: Configuration */ diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index e5c8b37bf739..b1bc72f9a209 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -54,7 +54,7 @@ /* Defaults for Module Parameter */ #define DEFAULT_NOGAMEPORT 0 #define DEFAULT_EXCLUSIVE 1 -#define DEFAULT_TIMEOUT 60 +#define DEFAULT_TIMEOUT 60 #define DEFAULT_TESTMODE 0 #define DEFAULT_NOWAYOUT WATCHDOG_NOWAYOUT @@ -70,9 +70,9 @@ /* Configuration Registers and Functions */ #define LDNREG 0x07 #define CHIPID 0x20 -#define CHIPREV 0x22 +#define CHIPREV 0x22 #define ACTREG 0x30 -#define BASEREG 0x60 +#define BASEREG 0x60 /* Chip Id numbers */ #define NO_DEV_ID 0xffff @@ -86,7 +86,7 @@ #define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ /* GPIO Configuration Registers LDN=0x07 */ -#define WDTCTRL 0x71 +#define WDTCTRL 0x71 #define WDTCFG 0x72 #define WDTVALLSB 0x73 #define WDTVALMSB 0x74 @@ -107,7 +107,7 @@ #define WDT_INT_MASK 0x0f /* CIR Configuration Register LDN=0x0a */ -#define CIR_ILS 0x70 +#define CIR_ILS 0x70 /* The default Base address is not always available, we use this */ #define CIR_BASE 0x0208 diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index 928035069396..1332b838cc58 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c @@ -54,7 +54,7 @@ /* indexes */ /* size */ #define ZFL_VERSION 0x02 /* 16 */ -#define CONTROL 0x10 /* 16 */ +#define CONTROL 0x10 /* 16 */ #define STATUS 0x12 /* 8 */ #define COUNTER_1 0x0C /* 16 */ #define COUNTER_2 0x0E /* 8 */ diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c index 3053ff05ca41..7a82ce5a6337 100644 --- a/drivers/watchdog/max63xx_wdt.c +++ b/drivers/watchdog/max63xx_wdt.c @@ -41,7 +41,7 @@ static int nowayout = WATCHDOG_NOWAYOUT; * to ping the watchdog. */ #define MAX6369_WDSET (7 << 0) -#define MAX6369_WDI (1 << 3) +#define MAX6369_WDI (1 << 3) static DEFINE_SPINLOCK(io_lock); diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 8fa213cdb499..3dee837190ea 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -2,9 +2,9 @@ * mpc8xxx_wdt.c - MPC8xx/MPC83xx/MPC86xx watchdog userspace interface * * Authors: Dave Updegraff - * Kumar Gala - * Attribution: from 83xx_wst: Florian Schirmer - * ..and from sc520_wdt + * Kumar Gala + * Attribution: from 83xx_wst: Florian Schirmer + * ..and from sc520_wdt * Copyright (c) 2008 MontaVista Software, Inc. * Anton Vorontsov * diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index b8ec7aca3c8e..2b4af222b5f2 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -172,7 +172,7 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file) /* * Shut off the timer. - * Lock it in if it's a module and we set nowayout + * Lock it in if it's a module and we set nowayout */ if (wdt->expect_close == 42) mpcore_wdt_stop(wdt); diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 08e8a6ab74e1..5ec5ac1f7878 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -190,19 +190,19 @@ static ssize_t mtx1_wdt_write(struct file *file, const char *buf, } static const struct file_operations mtx1_wdt_fops = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = mtx1_wdt_ioctl, - .open = mtx1_wdt_open, - .write = mtx1_wdt_write, - .release = mtx1_wdt_release, + .open = mtx1_wdt_open, + .write = mtx1_wdt_write, + .release = mtx1_wdt_release, }; static struct miscdevice mtx1_wdt_misc = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &mtx1_wdt_fops, + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &mtx1_wdt_fops, }; diff --git a/drivers/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h index fc02ec6a0386..09b774cf75b9 100644 --- a/drivers/watchdog/omap_wdt.h +++ b/drivers/watchdog/omap_wdt.h @@ -44,7 +44,7 @@ * months before firing. These limits work without scaling, * with the 60 second default assumed by most tools and docs. */ -#define TIMER_MARGIN_MAX (24 * 60 * 60) /* 1 day */ +#define TIMER_MARGIN_MAX (24 * 60 * 60) /* 1 day */ #define TIMER_MARGIN_DEFAULT 60 /* 60 secs */ #define TIMER_MARGIN_MIN 1 diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 3a56bc360924..139d773300c6 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -514,7 +514,7 @@ static struct miscdevice pc87413_miscdev = { /* -- Module init functions -------------------------------------*/ /** - * pc87413_init: module's "constructor" + * pc87413_init: module's "constructor" * * 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. diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index bf5b97c546eb..c7cf4cbf8ab3 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -4,7 +4,7 @@ * Watchdog driver for PNX4008 board * * Authors: Dmitry Chigirev , - * Vitaly Wool + * Vitaly Wool * Based on sa1100 driver, * Copyright (C) 2000 Oleg Drokin * diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index ae53662c29bc..25b39bf35925 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -224,7 +224,7 @@ static int s3c2410wdt_release(struct inode *inode, struct file *file) { /* * Shut off the timer. - * Lock it in if it's a module and we set nowayout + * Lock it in if it's a module and we set nowayout */ if (expect_close == 42) diff --git a/drivers/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c index 68e2e2d6f73d..514ec23050f7 100644 --- a/drivers/watchdog/sbc8360.c +++ b/drivers/watchdog/sbc8360.c @@ -114,7 +114,7 @@ static char expect_close; * C | 6.5s 65s 650s 1300s * D | 7s 70s 700s 1400s * E | 7.5s 75s 750s 1500s - * F | 8s 80s 800s 1600s + * F | 8s 80s 800s 1600s * * Another way to say the same things is: * For N=1, Timeout = (M+1) * 0.5s diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c index 79906255eeb6..d5d399464599 100644 --- a/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/drivers/watchdog/sbc_fitpc2_wdt.c @@ -41,7 +41,7 @@ static DEFINE_MUTEX(wdt_lock); #define IFACE_ON_COMMAND 1 #define REBOOT_COMMAND 2 -#define WATCHDOG_NAME "SBC-FITPC2 Watchdog" +#define WATCHDOG_NAME "SBC-FITPC2 Watchdog" static void wdt_send_data(unsigned char command, unsigned char data) { diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c index 8a1f0bc3e271..df88cfa05f35 100644 --- a/drivers/watchdog/smsc37b787_wdt.c +++ b/drivers/watchdog/smsc37b787_wdt.c @@ -434,11 +434,11 @@ static long wb_smsc_wdt_ioctl(struct file *file, } uarg; static const struct watchdog_info ident = { - .options = WDIOF_KEEPALIVEPING | + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 0, - .identity = "SMsC 37B787 Watchdog", + .identity = "SMsC 37B787 Watchdog", }; uarg.i = (int __user *)arg; diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index 833f49f43d43..100b114e3c3c 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -151,7 +151,7 @@ static int softdog_release(struct inode *inode, struct file *file) { /* * Shut off the timer. - * Lock it in if it's a module and we set nowayout + * Lock it in if it's a module and we set nowayout */ if (expect_close == 42) { softdog_stop(); diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 18cdeb4c4258..5a90a4a871dd 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c @@ -68,7 +68,7 @@ struct platform_device *ts72xx_wdt_pdev; * to control register): * value description * ------------------------- - * 0x00 watchdog disabled + * 0x00 watchdog disabled * 0x01 250ms * 0x02 500ms * 0x03 1s diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c index df2a64dc9672..be9c4d839e15 100644 --- a/drivers/watchdog/w83697ug_wdt.c +++ b/drivers/watchdog/w83697ug_wdt.c @@ -87,10 +87,10 @@ static int w83697ug_select_wd_register(void) outb_p(0x87, WDT_EFER); /* Enter extended function mode */ outb_p(0x87, WDT_EFER); /* Again according to manual */ - outb(0x20, WDT_EFER); /* check chip version */ + outb(0x20, WDT_EFER); /* check chip version */ version = inb(WDT_EFDR); - if (version == 0x68) { /* W83697UG */ + if (version == 0x68) { /* W83697UG */ printk(KERN_INFO PFX "Watchdog chip version 0x%02x = " "W83697UG/UF found at 0x%04x\n", version, wdt_io); diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index 552a4381e78f..bb03e151a1d0 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c @@ -581,7 +581,7 @@ static void __exit wdt_exit(void) } /** - * wdt_init: + * wdt_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. diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c index 5c2521fc836c..a2f01c9f5c34 100644 --- a/drivers/watchdog/wdt977.c +++ b/drivers/watchdog/wdt977.c @@ -281,7 +281,7 @@ static int wdt977_release(struct inode *inode, struct file *file) { /* * Shut off the timer. - * Lock it in if it's a module and we set nowayout + * Lock it in if it's a module and we set nowayout */ if (expect_close == 42) { wdt977_stop(); diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 97bb6fbdcf56..172dad6c7693 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -31,7 +31,7 @@ * Jeff Garzik : PCI cleanups * Tigran Aivazian : Restructured wdtpci_init_one() to handle * failures - * Joel Becker : Added WDIOC_GET/SETTIMEOUT + * Joel Becker : Added WDIOC_GET/SETTIMEOUT * Zwane Mwaikambo : Magic char closing, locking changes, * cleanups * Matt Domsch : nowayout module option @@ -764,7 +764,7 @@ static void __exit wdtpci_cleanup(void) /** - * wdtpci_init: + * 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. -- cgit v1.2.2 From 112e75466f63997d0f4c3c13ecf999e36aea692f Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 8 Feb 2011 17:39:46 -0600 Subject: watchdog: booke_wdt: clean up status messages Improve the status messages that are displayed during some operations of the PowerPC watchdog timer driver. When the watchdog is enabled, the timeout is displayed as a number of seconds, instead of an obscure "period". The "period" is the position of a bit in a 64-bit timer register. The higher the value, the quicker the watchdog timeout occurs. Some people chose a high "period" value for the timer and get confused as to why the board resets within a few seconds. Messages displayed during open and close are now debug messages, so that they don't clutter the console by default. Finally, printk() is replaced with the pr_xxx() equivalent. Signed-off-by: Timur Tabi Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/booke_wdt.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index 7e7ec9c35b6a..337265b47305 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -4,7 +4,7 @@ * Author: Matthew McClintock * Maintainer: Kumar Gala * - * Copyright 2005, 2008, 2010 Freescale Semiconductor Inc. + * Copyright 2005, 2008, 2010-2011 Freescale Semiconductor Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -221,9 +221,8 @@ static int booke_wdt_open(struct inode *inode, struct file *file) if (booke_wdt_enabled == 0) { booke_wdt_enabled = 1; on_each_cpu(__booke_wdt_enable, NULL, 0); - printk(KERN_INFO - "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", - booke_wdt_period); + pr_debug("booke_wdt: watchdog enabled (timeout = %llu sec)\n", + period_to_sec(booke_wdt_period)); } spin_unlock(&booke_wdt_lock); @@ -240,6 +239,7 @@ static int booke_wdt_release(struct inode *inode, struct file *file) */ on_each_cpu(__booke_wdt_disable, NULL, 0); booke_wdt_enabled = 0; + pr_debug("booke_wdt: watchdog disabled\n"); #endif clear_bit(0, &wdt_is_active); @@ -271,21 +271,20 @@ static int __init booke_wdt_init(void) { int ret = 0; - printk(KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n"); + pr_info("booke_wdt: powerpc book-e watchdog driver loaded\n"); ident.firmware_version = cur_cpu_spec->pvr_value; ret = misc_register(&booke_wdt_miscdev); if (ret) { - printk(KERN_CRIT "Cannot register miscdev on minor=%d: %d\n", - WATCHDOG_MINOR, ret); + pr_err("booke_wdt: cannot register device (minor=%u, ret=%i)\n", + WATCHDOG_MINOR, ret); return ret; } spin_lock(&booke_wdt_lock); if (booke_wdt_enabled == 1) { - printk(KERN_INFO - "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", - booke_wdt_period); + pr_info("booke_wdt: watchdog enabled (timeout = %llu sec)\n", + period_to_sec(booke_wdt_period)); on_each_cpu(__booke_wdt_enable, NULL, 0); } spin_unlock(&booke_wdt_lock); -- cgit v1.2.2 From 46673ed2cdca85afa7c69d126e3778bba2dbd2d5 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Thu, 17 Feb 2011 19:07:32 -0800 Subject: rdc321x-southbridge: Use mfd_data instead of driver_data Use mfd_data for passing information from mfd drivers to soc clients. The mfd_cell's driver_data field is being phased out. Clients that were using driver_data now access .mfd_data via mfd_get_data(). Signed-off-by: Andres Salomon Signed-off-by: Samuel Ortiz --- drivers/watchdog/rdc321x_wdt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 3939e53f5f98..d8e725082fdc 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c @@ -37,6 +37,7 @@ #include #include #include +#include #define RDC_WDT_MASK 0x80000000 /* Mask */ #define RDC_WDT_EN 0x00800000 /* Enable bit */ @@ -231,7 +232,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) struct resource *r; struct rdc321x_wdt_pdata *pdata; - pdata = platform_get_drvdata(pdev); + pdata = mfd_get_data(pdev); if (!pdata) { dev_err(&pdev->dev, "no platform data supplied\n"); return -ENODEV; -- cgit v1.2.2 From f72401e94d159bc4b2beab51d74e956da2c32e0a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 26 Feb 2011 17:34:38 +0100 Subject: watchdog: s3c2410_wdt.c: Convert release_resource to release_region/release_mem_region Request_mem_region should be used with release_mem_region, not release_resource. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,E; @@ *x = request_mem_region(...) ... when != release_mem_region(x) when != x = E * release_resource(x); // Signed-off-by: Julia Lawall Signed-off-by: Wim Van Sebroeck Cc: stable --- drivers/watchdog/s3c2410_wdt.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 25b39bf35925..f7f5aa00df60 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; } -- cgit v1.2.2 From f712eacf02ecfbf4f1686addb8c569841549b0b7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 26 Feb 2011 17:34:39 +0100 Subject: watchdog: Convert release_resource to release_region/release_mem_region Request_mem_region should be used with release_mem_region, not release_resource. In pnx4008_wdt.c, a missing clk_put is added as well. The semantic match that finds the first problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,E; @@ *x = request_mem_region(...) ... when != release_mem_region(x) when != x = E * release_resource(x); // Signed-off-by: Julia Lawall Signed-off-by: Wim Van Sebroeck Cc: stable --- drivers/watchdog/davinci_wdt.c | 22 ++++++++++------------ drivers/watchdog/max63xx_wdt.c | 20 ++++++++------------ drivers/watchdog/pnx4008_wdt.c | 28 +++++++++++++--------------- 3 files changed, 31 insertions(+), 39 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 596ba604e78d..51b5551b4e3f 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/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c index 7a82ce5a6337..73ba2fd8e591 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/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index c7cf4cbf8ab3..614933225560 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; -- cgit v1.2.2 From 90d241edd13bdeef70f264b569f7e150bf23621e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 16 Mar 2011 20:01:07 -0700 Subject: watchdog: sp5100_tco.c: Check if firmware has set correct value in tcobase. Stefano found SP5100 TCO watchdog driver using wrong address. [ 9.148536] SP5100 TCO timer: SP5100 TCO WatchDog Timer Driver v0.01 [ 9.148628] DEBUG __ioremap_caller WARNING address=b8fe00 size=8 valid=1 reserved=1 and e820 said that range is RAM. We should check if we can use that reading out. BIOS could just program wrong address there. Reported-by: Stefano Stabellini Signed-off-by:Yinghai Lu Acked-by: Mike Waychison Tested-by: Konrad Rzeszutek Wilk Signed-off-by: Wim Van Sebroeck Cc: stable --- drivers/watchdog/sp5100_tco.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c index 1bc493848ed4..87e0527669d8 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); } -- cgit v1.2.2 From 708d42472fba9a661a85ce12006c87ba3172a37e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 24 Mar 2011 13:32:44 -0700 Subject: watchdog: fix nv_tco section mismatch Fix section mismatch warning: Mark the called nv_tco_getdevice() as __devinit, just like its caller. WARNING: drivers/watchdog/nv_tco.o(.devinit.text+0x16): Section mismatch in reference from the function nv_tco_init() to the function .init.text:nv_tco_getdevice() The function __devinit nv_tco_init() references a function __init nv_tco_getdevice(). If nv_tco_getdevice is only used by nv_tco_init then annotate nv_tco_getdevice with a matching annotation. Signed-off-by: Randy Dunlap Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/nv_tco.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c index 267377a5a83e..afa78a54711e 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; -- cgit v1.2.2 From 7fff4beb311dfab4f18ff2cd64f78ec89296a39a Mon Sep 17 00:00:00 2001 From: Anithra P Janakiraman Date: Mon, 28 Mar 2011 14:29:19 -0700 Subject: watchdog: softdog.c: enhancement to optionally invoke panic instead of reboot on timer expiry This is needed for determining the reason for failure when a softdog timeout occurs. We use softdog to watch for critical application failures and at the minimum a snapshot of the system would help to determine the cause. In such a scenario the application could fail but there isn't a softlockup as such, hence the detect softlockup feature does not help. The patch adds a module parameter soft_panic which when set to 1 causes softdog to invoke panic instead of reboot when the softdog timer expires. By invoking panic we execute kdump if it is configured and the vmcore generated by kdump should provide atleast a minimal idea of the reason for failure. Based on an original patch by Ken Sugawara Signed-off-by: Anithra P J Reviewed-by: WANG Cong Acked-by: Alan Cox Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/watchdog/softdog.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index 100b114e3c3c..bf16ffb4d21e 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -48,6 +48,7 @@ #include #include #include +#include #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; } -- cgit v1.2.2 From 25985edcedea6396277003854657b5f3cb31a628 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 30 Mar 2011 22:57:33 -0300 Subject: Fix common misspellings Fixes generated by 'codespell' and manually reviewed. Signed-off-by: Lucas De Marchi --- drivers/watchdog/Kconfig | 2 +- drivers/watchdog/Makefile | 4 ++-- drivers/watchdog/acquirewdt.c | 2 +- drivers/watchdog/pc87413_wdt.c | 2 +- drivers/watchdog/sbc7240_wdt.c | 2 +- drivers/watchdog/sch311x_wdt.c | 2 +- drivers/watchdog/shwdt.c | 2 +- drivers/watchdog/smsc37b787_wdt.c | 2 +- drivers/watchdog/sp805_wdt.c | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b69d71482554..1b0f98bc51b5 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. diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index d520bf9c3355..3f8608b922a7 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 @@ -153,7 +153,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 2ffce4d75443..b6a2b58cbe64 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/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 139d773300c6..b7c139051575 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/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c index 67ddeb1c830a..ff11504c376e 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 b61ab1c54293..c7cf4b01f58d 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 4e3e7eb5919c..db84f2322d1a 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 df88cfa05f35..e97b0499bd0d 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/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 0a0efe713bc8..0d80e08b6439 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; -- cgit v1.2.2 From d856b418464024dba4c7e901bab74dfb9a030d2e Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Wed, 30 Mar 2011 15:48:22 +0200 Subject: watchdog: mpc8xxx_wdt: fix build Since 1c48a5c93da6313 (dt: Eliminate of_platform_{,un}register_driver) mpc8xxx_wdt no longer builds as it tries to refer to a 'match' variable rather than ofdev->dev.of_match that it checks just before. Signed-off-by: Peter Korsgaard Acked-by: Grant Likely Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mpc8xxx_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 6709d723e017..528bceb220fd 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -195,7 +195,7 @@ static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev) if (!ofdev->dev.of_match) return -EINVAL; - wdt_type = match->data; + wdt_type = ofdev->dev.of_match->data; if (!freq || freq == -1) return -EINVAL; -- cgit v1.2.2 From 06794eaeb766989e450c1b459ae28da76e1f8719 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 23 Mar 2011 12:55:36 -0700 Subject: treewide: Fix iomap resource size miscalculations Convert off-by-1 r->end - r->start to resource_size(r) Signed-off-by: Joe Perches Acked-by: David Brown Acked-by: Linus Walleij Acked-by: Florian Fainelli Acked-by: Wim Van Sebroeck Acked-by: Ralf Baechle Signed-off-by: Jiri Kosina --- drivers/watchdog/bcm63xx_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c index 3c5045a206dd..5064e8317521 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; -- cgit v1.2.2 From aa1f465225384b276e150238472a5452c4f92a84 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Wed, 20 Apr 2011 10:56:20 -0700 Subject: watchdog: iTCO_wdt: TCO Watchdog patch for Intel Panther Point PCH This patch adds the TCO Watchdog DeviceIDs for the Intel Panther Point PCH. Signed-off-by: Seth Heasley Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 97 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 35a0d12dad73..5fd020da7c55 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); -- cgit v1.2.2 From b1608d69cb804e414d0887140ba08a9398e4e638 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 18 May 2011 11:19:24 -0600 Subject: drivercore: revert addition of of_match to struct device Commit b826291c, "drivercore/dt: add a match table pointer to struct device" added an of_match pointer to struct device to cache the of_match_table entry discovered at driver match time. This was unsafe because matching is not an atomic operation with probing a driver. If two or more drivers are attempted to be matched to a driver at the same time, then the cached matching entry pointer could get overwritten. This patch reverts the of_match cache pointer and reworks all users to call of_match_device() directly instead. Signed-off-by: Grant Likely --- drivers/watchdog/mpc8xxx_wdt.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 528bceb220fd..eed5436ffb51 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -185,17 +185,20 @@ 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 = ofdev->dev.of_match->data; + wdt_type = match->data; if (!freq || freq == -1) return -EINVAL; -- cgit v1.2.2 From 2f58b8d04e680ec13157ba6eee44455438c56d5f Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 5 May 2011 23:00:23 +0200 Subject: MIPS: Lantiq: Add watchdog support This patch adds the driver for the watchdog found inside the Lantiq SoC family. Signed-off-by: John Crispin Signed-off-by: Ralph Hempel Cc: Wim Van Sebroeck Cc: linux-mips@linux-mips.org Cc: linux-watchdog@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/2327/ Signed-off-by: Ralf Baechle --- drivers/watchdog/Kconfig | 6 + drivers/watchdog/Makefile | 1 + drivers/watchdog/lantiq_wdt.c | 261 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 268 insertions(+) create mode 100644 drivers/watchdog/lantiq_wdt.c (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 1b0f98bc51b5..022f9eb0b7bf 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -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 3f8608b922a7..ed26f7094e47 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -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 diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c new file mode 100644 index 000000000000..7d82adac1cb2 --- /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 + * Based on EP93xx wdt driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* 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 "); +MODULE_DESCRIPTION("Lantiq SoC Watchdog"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.2 From b7f720d68c0042cc8ce496e31a61df79a77f1b48 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Sun, 8 May 2011 10:42:20 +0200 Subject: MIPS: Alchemy: Clean up GPIO registers and accessors remove au_readl/au_writel, remove the predefined GPIO1/2 KSEG1 register addresses and fix the fallout in all boards and drivers. This also fixes a bug in the mtx-1_wdt driver which was introduced by commit 6ea8115bb6f359df4f45152f2b40e1d4d1891392 ("Convert mtx1 wdt to be a platform device and use generic GPIO API") before this patch mtx-1_wdt only modified GPIO215, the patch then used the gpio resource information as bit index into the GPIO2 register but the conversion to the GPIO API didn't realize that. With this patch the drivers original behaviour is restored and GPIO15 is left alone. Signed-off-by: Manuel Lauss Cc: Florian Fainelli To: Linux-MIPS Cc: linux-watchdog@vger.kernel.org Cc: Wim Van Sebroeck Patchwork: https://patchwork.linux-mips.org/patch/2381/ Signed-off-by: Ralf Baechle Date: Wed, 6 Apr 2011 13:21:01 +0200 Subject: mfd: Use mfd cell platform_data for rdc321x cells platform bits With the addition of a platform device mfd_cell pointer, MFD drivers can go back to passing platform data back to their sub drivers. This allows for an mfd_cell->mfd_data removal and thus keep the sub drivers MFD agnostic. This is mostly needed for non MFD aware sub drivers. Cc: Grant Likely Cc: Wim Van Sebroeck Cc: Florian Fainelli Signed-off-by: Samuel Ortiz --- drivers/watchdog/rdc321x_wdt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index d8e725082fdc..428f8a1583e8 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c @@ -37,7 +37,6 @@ #include #include #include -#include #define RDC_WDT_MASK 0x80000000 /* Mask */ #define RDC_WDT_EN 0x00800000 /* Enable bit */ @@ -232,7 +231,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) struct resource *r; struct rdc321x_wdt_pdata *pdata; - pdata = mfd_get_data(pdev); + pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data supplied\n"); return -ENODEV; -- cgit v1.2.2 From 076bad7c4d2c51d9484f0ac60d68838139d2bf72 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 May 2011 14:46:55 +0100 Subject: watchdog: Handle multiple wm831x watchdogs being registered Due to the whole single instance based watchdog API we use static data for the wm831x watchdog which means that if the system tries to register a second one we end up trying to register the same miscdevice again, corrupting the miscdevice list. Work around this by checking for duplicate registrations until we get a watchdog core. Signed-off-by: Mark Brown Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wm831x_wdt.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index 8c4b2d5bb7da..871caea4e1c6 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c @@ -320,6 +320,11 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev) struct wm831x_watchdog_pdata *pdata; int reg, ret; + if (wm831x) { + dev_err(&pdev->dev, "wm831x watchdog already registered\n"); + return -EBUSY; + } + wm831x = dev_get_drvdata(pdev->dev.parent); ret = wm831x_reg_read(wm831x, WM831X_WATCHDOG); -- cgit v1.2.2 From 9b19d40aa3ebaf1078779da10555da2ab8512422 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 15 Jun 2011 19:15:23 +0200 Subject: watchdog: mtx1-wdt: request gpio before using it Otherwise, the gpiolib autorequest feature will produce a WARN_ON(): WARNING: at drivers/gpio/gpiolib.c:101 0x8020ec6c() autorequest GPIO-215 [...] Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck Cc: stable --- drivers/watchdog/mtx-1_wdt.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 1479dc4d6129..aa011da1d5fb 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -214,6 +214,12 @@ static int __devinit mtx1_wdt_probe(struct platform_device *pdev) int ret; mtx1_wdt_device.gpio = pdev->resource[0].start; + ret = gpio_request_one(mtx1_wdt_device.gpio, + GPIOF_OUT_INIT_HIGH, "mtx1-wdt"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request gpio"); + return ret; + } spin_lock_init(&mtx1_wdt_device.lock); init_completion(&mtx1_wdt_device.stop); @@ -239,6 +245,8 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev) mtx1_wdt_device.queue = 0; wait_for_completion(&mtx1_wdt_device.stop); } + + gpio_free(mtx1_wdt_device.gpio); misc_deregister(&mtx1_wdt_misc); return 0; } -- cgit v1.2.2 From 2ea4e76e997019ae25ac3417aa46e31ddf7ecb17 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 15 Jun 2011 19:15:41 +0200 Subject: watchdog: mtx1-wdt: fix GPIO toggling Commit e391be76 (MIPS: Alchemy: Clean up GPIO registers and accessors) changed the way the GPIO was toggled. Prior to this patch, we would always actively drive the GPIO output to either 0 or 1, this patch drove the GPIO active to 0, and put the GPIO in tristate to drive it to 1, unfortunately this does not work, revert back to active driving. Using a signed variable (gstate) to hold the gpio state and using a bit- wise operation on it also resulted in toggling value from 1 to -2 since the variable is signed. This value was then passed on to gpio_direction_ output, which always perform a if (value) ... to set the value to the gpio, so we were always writing a 1 to this GPIO instead of 1 -> 0 -> 1 ... Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck Cc: stable --- drivers/watchdog/mtx-1_wdt.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index aa011da1d5fb..54aa90042484 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -66,7 +66,7 @@ static struct { int default_ticks; unsigned long inuse; unsigned gpio; - int gstate; + unsigned int gstate; } mtx1_wdt_device; static void mtx1_wdt_trigger(unsigned long unused) @@ -78,11 +78,8 @@ static void mtx1_wdt_trigger(unsigned long unused) ticks--; /* 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); + mtx1_wdt_device.gstate = !mtx1_wdt_device.gstate; + gpio_set_value(mtx1_wdt_device.gpio, mtx1_wdt_device.gstate); if (mtx1_wdt_device.queue && ticks) mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); @@ -105,7 +102,7 @@ static void mtx1_wdt_start(void) if (!mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 1; mtx1_wdt_device.gstate = 1; - gpio_direction_output(mtx1_wdt_device.gpio, 1); + gpio_set_value(mtx1_wdt_device.gpio, 1); mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); } mtx1_wdt_device.running++; @@ -120,7 +117,7 @@ static int mtx1_wdt_stop(void) if (mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 0; mtx1_wdt_device.gstate = 0; - gpio_direction_output(mtx1_wdt_device.gpio, 0); + gpio_set_value(mtx1_wdt_device.gpio, 0); } ticks = mtx1_wdt_device.default_ticks; spin_unlock_irqrestore(&mtx1_wdt_device.lock, flags); -- cgit v1.2.2 From db98f89a2807966c6e82601f5c57e1a9c214c91a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 15 Jun 2011 19:15:52 +0200 Subject: watchdog: mtx1-wdt: fix section mismatch Fix section mismatch and remove unused variable 'tmp'. Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mtx-1_wdt.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 54aa90042484..0430e093b1a0 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -71,8 +71,6 @@ static struct { static void mtx1_wdt_trigger(unsigned long unused) { - u32 tmp; - spin_lock(&mtx1_wdt_device.lock); if (mtx1_wdt_device.running) ticks--; @@ -248,7 +246,7 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev) return 0; } -static struct platform_driver mtx1_wdt = { +static struct platform_driver mtx1_wdt_driver = { .probe = mtx1_wdt_probe, .remove = __devexit_p(mtx1_wdt_remove), .driver.name = "mtx1-wdt", @@ -257,12 +255,12 @@ static struct platform_driver mtx1_wdt = { static int __init mtx1_wdt_init(void) { - return platform_driver_register(&mtx1_wdt); + return platform_driver_register(&mtx1_wdt_driver); } static void __exit mtx1_wdt_exit(void) { - platform_driver_unregister(&mtx1_wdt); + platform_driver_unregister(&mtx1_wdt_driver); } module_init(mtx1_wdt_init); -- cgit v1.2.2 From e376fd664b1547e29e264e3cfb97553a1be9054b Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 26 May 2011 11:12:53 +0200 Subject: watchdog: Intel SCU Watchdog: Fix build and remove duplicate code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trying to build the Intel SCU Watchdog fails for me with gcc 4.6.0 - $ gcc --version | head -n 1 gcc (GCC) 4.6.0 20110513 (prerelease) like this : CC drivers/watchdog/intel_scu_watchdog.o In file included from drivers/watchdog/intel_scu_watchdog.c:49:0: /home/jj/src/linux-2.6/arch/x86/include/asm/apb_timer.h: In function ‘apbt_time_init’: /home/jj/src/linux-2.6/arch/x86/include/asm/apb_timer.h:65:42: warning: ‘return’ with a value, in function returning void [enabled by default] drivers/watchdog/intel_scu_watchdog.c: In function ‘intel_scu_watchdog_init’: drivers/watchdog/intel_scu_watchdog.c:468:2: error: implicit declaration of function ‘sfi_get_mtmr’ [-Werror=implicit-function-declaration] drivers/watchdog/intel_scu_watchdog.c:468:32: warning: assignment makes pointer from integer without a cast [enabled by default] cc1: some warnings being treated as errors make[1]: *** [drivers/watchdog/intel_scu_watchdog.o] Error 1 make: *** [drivers/watchdog/intel_scu_watchdog.o] Error 2 Additionally, linux/types.h is needlessly being included twice in drivers/watchdog/intel_scu_watchdog.c Signed-off-by: Jesper Juhl Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 3 +-- drivers/watchdog/intel_scu_watchdog.c | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 022f9eb0b7bf..9536d386bb38 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -535,8 +535,7 @@ config I6300ESB_WDT config INTEL_SCU_WATCHDOG bool "Intel SCU Watchdog for Mobile Platforms" - depends on WATCHDOG - depends on INTEL_SCU_IPC + depends on X86_MRST ---help--- Hardware driver for the watchdog time built into the Intel SCU for Intel Mobile Platforms. diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c index 919bdd16136f..ba4386066a42 100644 --- a/drivers/watchdog/intel_scu_watchdog.c +++ b/drivers/watchdog/intel_scu_watchdog.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.2 From ae2a00607463ceb647ada550d7f34ba33177ef38 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 27 Jun 2011 22:37:16 +0800 Subject: watchdog: gef_wdt: fix MODULE_ALIAS Remove the space between "platform:" prefix and the driver name. Signed-off-by: Axel Lin Acked-by: Martyn Welch Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/gef_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 29a7cd4b90c8..b146082bd85a 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -329,4 +329,4 @@ MODULE_AUTHOR("Martyn Welch "); MODULE_DESCRIPTION("GE watchdog driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -MODULE_ALIAS("platform: gef_wdt"); +MODULE_ALIAS("platform:gef_wdt"); -- cgit v1.2.2 From aeb0aea143e958d5218162d73b1ed4d6ff0ed7c4 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Tue, 28 Jun 2011 17:01:14 +0200 Subject: watchdog: update author email for at32ap700x_wdt This patch updates the email address of the at32ap700x_wdt driver supported by me to an email account I will use on a more regular basis in the future. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/at32ap700x_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index 750bc5281d79..4ca5d40304b2 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -448,7 +448,7 @@ static void __exit at32_wdt_exit(void) } module_exit(at32_wdt_exit); -MODULE_AUTHOR("Hans-Christian Egtvedt "); +MODULE_AUTHOR("Hans-Christian Egtvedt "); MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.2 From 2a75ca4a43e4276e6da2c75bea672a03e8e900fb Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 15 Jul 2011 23:23:33 +0200 Subject: watchdog: fix hpwdt Kconfig regression in 3.0-rc Remove Kconfig regression caused by commit a4616153deae053b29a2b7dd9ec4b2a225accfc5 "watchdog: hpwdt: build hpwdt as module by default with NMI_DECODING enabled" With the above change applied, hpwdt will be enabled unconditionally by just entering the Watchdog subscreen in menuconfig. Since this driver is not essential to boot any box it should remain disabled until it gets manually enabled, just like all other drivers. Signed-off-by: Olaf Hering Cc: Tony Camuso Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/watchdog/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 9536d386bb38..c57419bf08f1 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -600,7 +600,6 @@ config IT87_WDT config HP_WATCHDOG tristate "HP ProLiant iLO2+ Hardware Watchdog Timer" depends on X86 - default m help A software monitoring watchdog and NMI sourcing driver. This driver will detect lockups and provide a stack trace. This is a driver that -- cgit v1.2.2 From f71d26bb6503e9b11b91444819b2f96872baaab8 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 16 Jul 2011 12:25:49 -0700 Subject: watchdog: hpwdt depends on PCI hpwdt is a PCI driver so it should depend on PCI. Fixes these build errors: drivers/watchdog/hpwdt.c:762: error: implicit declaration of function 'pci_iomap' drivers/watchdog/hpwdt.c:762: warning: assignment makes pointer from integer without a cast drivers/watchdog/hpwdt.c:797: error: implicit declaration of function 'pci_iounmap' Signed-off-by: Randy Dunlap Signed-off-by: Wim Van Sebroeck Cc: Thomas Mingarelli --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c57419bf08f1..21d816e9dfa5 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -599,7 +599,7 @@ config IT87_WDT config HP_WATCHDOG tristate "HP ProLiant iLO2+ Hardware Watchdog Timer" - depends on X86 + depends on X86 && PCI help A software monitoring watchdog and NMI sourcing driver. This driver will detect lockups and provide a stack trace. This is a driver that -- cgit v1.2.2