diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/ar7_wdt.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/bfin_wdt.c | 13 | ||||
-rw-r--r-- | drivers/watchdog/pnx4008_wdt.c | 39 |
3 files changed, 47 insertions, 23 deletions
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 2e94b71b20d..2bb95cd308c 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c @@ -34,6 +34,7 @@ #include <linux/ioport.h> #include <linux/io.h> #include <linux/uaccess.h> +#include <linux/clk.h> #include <asm/addrspace.h> #include <asm/mach-ar7/ar7.h> @@ -80,6 +81,8 @@ static struct resource *ar7_regs_wdt; /* Pointer to the remapped WDT IO space */ static struct ar7_wdt *ar7_wdt; +static struct clk *vbus_clk; + static void ar7_wdt_kick(u32 value) { WRITE_REG(ar7_wdt->kick_lock, 0x5555); @@ -138,17 +141,19 @@ static void ar7_wdt_disable(u32 value) static void ar7_wdt_update_margin(int new_margin) { u32 change; + u32 vbus_rate; - change = new_margin * (ar7_vbus_freq() / prescale_value); + vbus_rate = clk_get_rate(vbus_clk); + change = new_margin * (vbus_rate / prescale_value); if (change < 1) change = 1; if (change > 0xffff) change = 0xffff; ar7_wdt_change(change); - margin = change * prescale_value / ar7_vbus_freq(); + margin = change * prescale_value / vbus_rate; printk(KERN_INFO DRVNAME ": timer margin %d seconds (prescale %d, change %d, freq %d)\n", - margin, prescale_value, change, ar7_vbus_freq()); + margin, prescale_value, change, vbus_rate); } static void ar7_wdt_enable_wdt(void) @@ -298,6 +303,13 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev) goto out_mem_region; } + vbus_clk = clk_get(NULL, "vbus"); + if (IS_ERR(vbus_clk)) { + printk(KERN_ERR DRVNAME ": could not get vbus clock\n"); + rc = PTR_ERR(vbus_clk); + goto out_mem_region; + } + ar7_wdt_disable_wdt(); ar7_wdt_prescale(prescale_value); ar7_wdt_update_margin(margin); diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index c7b3f9df231..2159e668751 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c @@ -1,9 +1,8 @@ /* * Blackfin On-Chip Watchdog Driver - * Supports BF53[123]/BF53[467]/BF54[2489]/BF561 * * Originally based on softdog.c - * Copyright 2006-2007 Analog Devices Inc. + * Copyright 2006-2010 Analog Devices Inc. * Copyright 2006-2007 Michele d'Amico * Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk> * @@ -137,13 +136,15 @@ static int bfin_wdt_running(void) */ static int bfin_wdt_set_timeout(unsigned long t) { - u32 cnt; + u32 cnt, max_t, sclk; unsigned long flags; - stampit(); + sclk = get_sclk(); + max_t = -1 / sclk; + cnt = t * sclk; + stamp("maxtimeout=%us newtimeout=%lus (cnt=%#x)", max_t, t, cnt); - cnt = t * get_sclk(); - if (cnt < get_sclk()) { + if (t > max_t) { printk(KERN_WARNING PFX "timeout value is too large\n"); return -EINVAL; } diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 430a5848a9a..c7a9479934a 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -96,9 +96,6 @@ static void wdt_enable(void) { spin_lock(&io_lock); - if (wdt_clk) - clk_set_rate(wdt_clk, 1); - /* stop counter, initiate counter reset */ __raw_writel(RESET_COUNT, WDTIM_CTRL(wdt_base)); /*wait for reset to complete. 100% guarantee event */ @@ -125,19 +122,25 @@ static void wdt_disable(void) spin_lock(&io_lock); __raw_writel(0, WDTIM_CTRL(wdt_base)); /*stop counter */ - if (wdt_clk) - clk_set_rate(wdt_clk, 0); spin_unlock(&io_lock); } static int pnx4008_wdt_open(struct inode *inode, struct file *file) { + int ret; + if (test_and_set_bit(WDT_IN_USE, &wdt_status)) return -EBUSY; clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + ret = clk_enable(wdt_clk); + if (ret) { + clear_bit(WDT_IN_USE, &wdt_status); + return ret; + } + wdt_enable(); return nonseekable_open(inode, file); @@ -225,6 +228,7 @@ static int pnx4008_wdt_release(struct inode *inode, struct file *file) printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n"); wdt_disable(); + clk_disable(wdt_clk); clear_bit(WDT_IN_USE, &wdt_status); clear_bit(WDT_OK_TO_CLOSE, &wdt_status); @@ -273,25 +277,33 @@ static int __devinit pnx4008_wdt_probe(struct platform_device *pdev) } wdt_base = (void __iomem *)IO_ADDRESS(res->start); - wdt_clk = clk_get(&pdev->dev, "wdt_ck"); + wdt_clk = clk_get(&pdev->dev, NULL); if (IS_ERR(wdt_clk)) { ret = PTR_ERR(wdt_clk); release_resource(wdt_mem); kfree(wdt_mem); goto out; - } else - clk_set_rate(wdt_clk, 1); + } + + ret = clk_enable(wdt_clk); + if (ret) { + release_resource(wdt_mem); + kfree(wdt_mem); + 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); - clk_set_rate(wdt_clk, 0); + clk_disable(wdt_clk); + clk_put(wdt_clk); } else { boot_status = (__raw_readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ? WDIOF_CARDRESET : 0; wdt_disable(); /*disable for now */ + clk_disable(wdt_clk); set_bit(WDT_DEVICE_INITED, &wdt_status); } @@ -302,11 +314,10 @@ out: static int __devexit pnx4008_wdt_remove(struct platform_device *pdev) { misc_deregister(&pnx4008_wdt_miscdev); - if (wdt_clk) { - clk_set_rate(wdt_clk, 0); - clk_put(wdt_clk); - wdt_clk = NULL; - } + + clk_disable(wdt_clk); + clk_put(wdt_clk); + if (wdt_mem) { release_resource(wdt_mem); kfree(wdt_mem); |