aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/shwdt.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2012-05-10 02:46:48 -0400
committerPaul Mundt <lethal@linux-sh.org>2012-05-10 02:46:48 -0400
commit9ea6404691a520f734b819cbbd4757b0ea5f99c6 (patch)
treecce41707ecec4c4556a264978eea52d9fbd96b8c /drivers/watchdog/shwdt.c
parentf9e2eae6c66437a414988b44e1d2b8c025134883 (diff)
watchdog: shwdt: Basic clock framework support.
This plugs in basic clock framework support for the watchdog. As it's an optional MSTP bit, we don't particularly care if a platform has provided it or not, though a valid clock will need to be available for the more complex overflow period calculations found on newer parts -- this will be addressed later. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/watchdog/shwdt.c')
-rw-r--r--drivers/watchdog/shwdt.c50
1 files changed, 26 insertions, 24 deletions
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index de3630d6bd4d..380ada4e5d66 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -32,6 +32,7 @@
32#include <linux/mm.h> 32#include <linux/mm.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/io.h> 34#include <linux/io.h>
35#include <linux/clk.h>
35#include <asm/watchdog.h> 36#include <asm/watchdog.h>
36 37
37#define DRV_NAME "sh-wdt" 38#define DRV_NAME "sh-wdt"
@@ -74,6 +75,7 @@ static unsigned long next_heartbeat;
74struct sh_wdt { 75struct sh_wdt {
75 void __iomem *base; 76 void __iomem *base;
76 struct device *dev; 77 struct device *dev;
78 struct clk *clk;
77 spinlock_t lock; 79 spinlock_t lock;
78 80
79 struct timer_list timer; 81 struct timer_list timer;
@@ -225,27 +227,32 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev)
225 if (unlikely(!res)) 227 if (unlikely(!res))
226 return -EINVAL; 228 return -EINVAL;
227 229
228 if (!devm_request_mem_region(&pdev->dev, res->start,
229 resource_size(res), DRV_NAME))
230 return -EBUSY;
231
232 wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL); 230 wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL);
233 if (unlikely(!wdt)) { 231 if (unlikely(!wdt))
234 rc = -ENOMEM; 232 return -ENOMEM;
235 goto out_release;
236 }
237 233
238 wdt->dev = &pdev->dev; 234 wdt->dev = &pdev->dev;
239 235
240 watchdog_set_nowayout(&sh_wdt_dev, nowayout); 236 wdt->clk = clk_get(&pdev->dev, NULL);
241 watchdog_set_drvdata(&sh_wdt_dev, wdt); 237 if (IS_ERR(wdt->clk)) {
238 /*
239 * Clock framework support is optional, continue on
240 * anyways if we don't find a matching clock.
241 */
242 wdt->clk = NULL;
243 }
242 244
243 wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 245 clk_enable(wdt->clk);
246
247 wdt->base = devm_request_and_ioremap(wdt->dev, res);
244 if (unlikely(!wdt->base)) { 248 if (unlikely(!wdt->base)) {
245 rc = -ENXIO; 249 rc = -EADDRNOTAVAIL;
246 goto out_err; 250 goto out_disable;
247 } 251 }
248 252
253 watchdog_set_nowayout(&sh_wdt_dev, nowayout);
254 watchdog_set_drvdata(&sh_wdt_dev, wdt);
255
249 spin_lock_init(&wdt->lock); 256 spin_lock_init(&wdt->lock);
250 257
251 rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat); 258 rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat);
@@ -264,7 +271,7 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev)
264 rc = watchdog_register_device(&sh_wdt_dev); 271 rc = watchdog_register_device(&sh_wdt_dev);
265 if (unlikely(rc)) { 272 if (unlikely(rc)) {
266 dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc); 273 dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc);
267 goto out_unmap; 274 goto out_disable;
268 } 275 }
269 276
270 init_timer(&wdt->timer); 277 init_timer(&wdt->timer);
@@ -278,12 +285,9 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev)
278 285
279 return 0; 286 return 0;
280 287
281out_unmap: 288out_disable:
282 devm_iounmap(&pdev->dev, wdt->base); 289 clk_disable(wdt->clk);
283out_err: 290 clk_put(wdt->clk);
284 devm_kfree(&pdev->dev, wdt);
285out_release:
286 devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
287 291
288 return rc; 292 return rc;
289} 293}
@@ -291,15 +295,13 @@ out_release:
291static int __devexit sh_wdt_remove(struct platform_device *pdev) 295static int __devexit sh_wdt_remove(struct platform_device *pdev)
292{ 296{
293 struct sh_wdt *wdt = platform_get_drvdata(pdev); 297 struct sh_wdt *wdt = platform_get_drvdata(pdev);
294 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
295 298
296 platform_set_drvdata(pdev, NULL); 299 platform_set_drvdata(pdev, NULL);
297 300
298 watchdog_unregister_device(&sh_wdt_dev); 301 watchdog_unregister_device(&sh_wdt_dev);
299 302
300 devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); 303 clk_disable(wdt->clk);
301 devm_iounmap(&pdev->dev, wdt->base); 304 clk_put(wdt->clk);
302 devm_kfree(&pdev->dev, wdt);
303 305
304 return 0; 306 return 0;
305} 307}