diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-28 20:03:26 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-28 20:03:26 (GMT) |
commit | 750f77064a290beb162352077b52c61b04bcae0e (patch) | |
tree | 736a8dd043dc4cda298762a80e7c1fbf1bb87742 /drivers/watchdog/sp805_wdt.c | |
parent | 89e5d6f0d979f6e7dc2bbb1ebd9e239217e2e952 (diff) | |
parent | b92c803ec61de59e6e4ab9b2748d8e633cec3f08 (diff) | |
download | linux-750f77064a290beb162352077b52c61b04bcae0e.tar.xz |
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck:
- Removal of the Documentation/watchdog/00-INDEX file
- Fix boot status reporting for imx2_wdt
- clean-up sp805_wdt, pnx4008_wdt and mpcore_wdt
- convert printk in watchdog drivers to pr_ functions
- change nowayout module parameter to bool for every watchdog device
- conversion of jz4740_wdt, pnx4008_wdt, max63xx_wdt, softdog,
ep93xx_wdt, coh901327 and txx9wdt to new watchdog API
- Add support for the WDIOC_GETTIMELEFT ioctl call to the new watchdog
API
- Change the new watchdog API so that the driver updates the timeout
value
- two fixes for the xen_wdt driver
Fix up conflicts in ep93xx driver due to the same patches being merged
through separate branches.
* git://www.linux-watchdog.org/linux-watchdog: (33 commits)
watchdog: txx9wdt: fix timeout
watchdog: Convert txx9wdt driver to watchdog framework
watchdog: coh901327_wdt.c: fix timeout
watchdog: coh901327: convert to use watchdog core
watchdog: Add support for WDIOC_GETTIMELEFT IOCTL in watchdog core
watchdog: ep93xx_wdt: timeout is an unsigned int value.
watchdog: ep93xx_wdt: Fix timeout after conversion to watchdog core
watchdog: Convert ep93xx driver to watchdog core
watchdog: sp805: Use devm routines
watchdog: sp805: replace readl/writel with lighter _relaxed variants
watchdog: sp805: Fix documentation style comment
watchdog: mpcore_wdt: Allow platform_get_irq() to fail
watchdog: mpcore_wdt: Use devm routines
watchdog: mpcore_wdt: Rename dev to pdev for pointing to struct platform_device
watchdog: xen: don't clear is_active when xen_wdt_stop() failed
watchdog: xen: don't unconditionally enable the watchdog during resume
watchdog: fix compiler error for missing parenthesis
watchdog: ep93xx_wdt.c: fix platform probe
watchdog: ep93xx: Convert the watchdog driver into a platform device.
watchdog: fix set_timeout operations
...
Diffstat (limited to 'drivers/watchdog/sp805_wdt.c')
-rw-r--r-- | drivers/watchdog/sp805_wdt.c | 111 |
1 files changed, 67 insertions, 44 deletions
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 3ff9e47..bbb170e 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -25,6 +25,7 @@ #include <linux/miscdevice.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/pm.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/types.h> @@ -55,14 +56,13 @@ /** * struct sp805_wdt: sp805 wdt device structure - * - * lock: spin lock protecting dev structure and io access - * base: base address of wdt - * clk: clock structure of wdt - * dev: amba device structure of wdt - * status: current status of wdt - * load_val: load value to be set for current timeout - * timeout: current programmed timeout + * @lock: spin lock protecting dev structure and io access + * @base: base address of wdt + * @clk: clock structure of wdt + * @adev: amba device structure of wdt + * @status: current status of wdt + * @load_val: load value to be set for current timeout + * @timeout: current programmed timeout */ struct sp805_wdt { spinlock_t lock; @@ -78,7 +78,7 @@ struct sp805_wdt { /* local variables */ static struct sp805_wdt *wdt; -static int nowayout = WATCHDOG_NOWAYOUT; +static bool nowayout = WATCHDOG_NOWAYOUT; /* This routine finds load value that will reset system in required timout */ static void wdt_setload(unsigned int timeout) @@ -113,10 +113,10 @@ static u32 wdt_timeleft(void) rate = clk_get_rate(wdt->clk); spin_lock(&wdt->lock); - load = readl(wdt->base + WDTVALUE); + load = readl_relaxed(wdt->base + WDTVALUE); /*If the interrupt is inactive then time left is WDTValue + WDTLoad. */ - if (!(readl(wdt->base + WDTRIS) & INT_MASK)) + if (!(readl_relaxed(wdt->base + WDTRIS) & INT_MASK)) load += wdt->load_val + 1; spin_unlock(&wdt->lock); @@ -128,14 +128,14 @@ static void wdt_enable(void) { spin_lock(&wdt->lock); - writel(UNLOCK, wdt->base + WDTLOCK); - writel(wdt->load_val, wdt->base + WDTLOAD); - writel(INT_MASK, wdt->base + WDTINTCLR); - writel(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL); - writel(LOCK, wdt->base + WDTLOCK); + writel_relaxed(UNLOCK, wdt->base + WDTLOCK); + writel_relaxed(wdt->load_val, wdt->base + WDTLOAD); + writel_relaxed(INT_MASK, wdt->base + WDTINTCLR); + writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL); + writel_relaxed(LOCK, wdt->base + WDTLOCK); /* Flush posted writes. */ - readl(wdt->base + WDTLOCK); + readl_relaxed(wdt->base + WDTLOCK); spin_unlock(&wdt->lock); } @@ -144,12 +144,12 @@ static void wdt_disable(void) { spin_lock(&wdt->lock); - writel(UNLOCK, wdt->base + WDTLOCK); - writel(0, wdt->base + WDTCONTROL); - writel(LOCK, wdt->base + WDTLOCK); + writel_relaxed(UNLOCK, wdt->base + WDTLOCK); + writel_relaxed(0, wdt->base + WDTCONTROL); + writel_relaxed(LOCK, wdt->base + WDTLOCK); /* Flush posted writes. */ - readl(wdt->base + WDTLOCK); + readl_relaxed(wdt->base + WDTLOCK); spin_unlock(&wdt->lock); } @@ -285,32 +285,33 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; - if (!request_mem_region(adev->res.start, resource_size(&adev->res), - "sp805_wdt")) { + if (!devm_request_mem_region(&adev->dev, adev->res.start, + resource_size(&adev->res), "sp805_wdt")) { dev_warn(&adev->dev, "Failed to get memory region resource\n"); ret = -ENOENT; goto err; } - wdt = kzalloc(sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) { dev_warn(&adev->dev, "Kzalloc failed\n"); ret = -ENOMEM; - goto err_kzalloc; + goto err; + } + + wdt->base = devm_ioremap(&adev->dev, adev->res.start, + resource_size(&adev->res)); + if (!wdt->base) { + ret = -ENOMEM; + dev_warn(&adev->dev, "ioremap fail\n"); + goto err; } wdt->clk = clk_get(&adev->dev, NULL); if (IS_ERR(wdt->clk)) { dev_warn(&adev->dev, "Clock not found\n"); ret = PTR_ERR(wdt->clk); - goto err_clk_get; - } - - wdt->base = ioremap(adev->res.start, resource_size(&adev->res)); - if (!wdt->base) { - ret = -ENOMEM; - dev_warn(&adev->dev, "ioremap fail\n"); - goto err_ioremap; + goto err; } wdt->adev = adev; @@ -327,14 +328,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) return 0; err_misc_register: - iounmap(wdt->base); -err_ioremap: clk_put(wdt->clk); -err_clk_get: - kfree(wdt); - wdt = NULL; -err_kzalloc: - release_mem_region(adev->res.start, resource_size(&adev->res)); err: dev_err(&adev->dev, "Probe Failed!!!\n"); return ret; @@ -343,14 +337,42 @@ err: static int __devexit sp805_wdt_remove(struct amba_device *adev) { misc_deregister(&sp805_wdt_miscdev); - iounmap(wdt->base); clk_put(wdt->clk); - kfree(wdt); - release_mem_region(adev->res.start, resource_size(&adev->res)); return 0; } +#ifdef CONFIG_PM +static int sp805_wdt_suspend(struct device *dev) +{ + if (test_bit(WDT_BUSY, &wdt->status)) { + wdt_disable(); + clk_disable(wdt->clk); + } + + return 0; +} + +static int sp805_wdt_resume(struct device *dev) +{ + int ret = 0; + + if (test_bit(WDT_BUSY, &wdt->status)) { + ret = clk_enable(wdt->clk); + if (ret) { + dev_err(dev, "clock enable fail"); + return ret; + } + wdt_enable(); + } + + return ret; +} +#endif /* CONFIG_PM */ + +static SIMPLE_DEV_PM_OPS(sp805_wdt_dev_pm_ops, sp805_wdt_suspend, + sp805_wdt_resume); + static struct amba_id sp805_wdt_ids[] = { { .id = 0x00141805, @@ -364,6 +386,7 @@ MODULE_DEVICE_TABLE(amba, sp805_wdt_ids); static struct amba_driver sp805_wdt_driver = { .drv = { .name = MODULE_NAME, + .pm = &sp805_wdt_dev_pm_ops, }, .id_table = sp805_wdt_ids, .probe = sp805_wdt_probe, @@ -372,7 +395,7 @@ static struct amba_driver sp805_wdt_driver = { module_amba_driver(sp805_wdt_driver); -module_param(nowayout, int, 0); +module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Set to 1 to keep watchdog running after device release"); |