diff options
Diffstat (limited to 'drivers/watchdog/omap_wdt.c')
-rw-r--r-- | drivers/watchdog/omap_wdt.c | 68 |
1 files changed, 31 insertions, 37 deletions
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 76b58abf4451..2b4acb86c191 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c | |||
@@ -38,11 +38,11 @@ | |||
38 | #include <linux/err.h> | 38 | #include <linux/err.h> |
39 | #include <linux/platform_device.h> | 39 | #include <linux/platform_device.h> |
40 | #include <linux/moduleparam.h> | 40 | #include <linux/moduleparam.h> |
41 | #include <linux/clk.h> | ||
42 | #include <linux/bitops.h> | 41 | #include <linux/bitops.h> |
43 | #include <linux/io.h> | 42 | #include <linux/io.h> |
44 | #include <linux/uaccess.h> | 43 | #include <linux/uaccess.h> |
45 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/pm_runtime.h> | ||
46 | #include <mach/hardware.h> | 46 | #include <mach/hardware.h> |
47 | #include <plat/prcm.h> | 47 | #include <plat/prcm.h> |
48 | 48 | ||
@@ -61,8 +61,6 @@ struct omap_wdt_dev { | |||
61 | void __iomem *base; /* physical */ | 61 | void __iomem *base; /* physical */ |
62 | struct device *dev; | 62 | struct device *dev; |
63 | int omap_wdt_users; | 63 | int omap_wdt_users; |
64 | struct clk *ick; | ||
65 | struct clk *fck; | ||
66 | struct resource *mem; | 64 | struct resource *mem; |
67 | struct miscdevice omap_wdt_miscdev; | 65 | struct miscdevice omap_wdt_miscdev; |
68 | }; | 66 | }; |
@@ -126,6 +124,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) | |||
126 | u32 pre_margin = GET_WLDR_VAL(timer_margin); | 124 | u32 pre_margin = GET_WLDR_VAL(timer_margin); |
127 | void __iomem *base = wdev->base; | 125 | void __iomem *base = wdev->base; |
128 | 126 | ||
127 | pm_runtime_get_sync(wdev->dev); | ||
128 | |||
129 | /* just count up at 32 KHz */ | 129 | /* just count up at 32 KHz */ |
130 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) | 130 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) |
131 | cpu_relax(); | 131 | cpu_relax(); |
@@ -133,6 +133,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) | |||
133 | __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); | 133 | __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); |
134 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) | 134 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) |
135 | cpu_relax(); | 135 | cpu_relax(); |
136 | |||
137 | pm_runtime_put_sync(wdev->dev); | ||
136 | } | 138 | } |
137 | 139 | ||
138 | /* | 140 | /* |
@@ -146,8 +148,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file) | |||
146 | if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) | 148 | if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) |
147 | return -EBUSY; | 149 | return -EBUSY; |
148 | 150 | ||
149 | clk_enable(wdev->ick); /* Enable the interface clock */ | 151 | pm_runtime_get_sync(wdev->dev); |
150 | clk_enable(wdev->fck); /* Enable the functional clock */ | ||
151 | 152 | ||
152 | /* initialize prescaler */ | 153 | /* initialize prescaler */ |
153 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) | 154 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) |
@@ -163,6 +164,8 @@ static int omap_wdt_open(struct inode *inode, struct file *file) | |||
163 | omap_wdt_ping(wdev); /* trigger loading of new timeout value */ | 164 | omap_wdt_ping(wdev); /* trigger loading of new timeout value */ |
164 | omap_wdt_enable(wdev); | 165 | omap_wdt_enable(wdev); |
165 | 166 | ||
167 | pm_runtime_put_sync(wdev->dev); | ||
168 | |||
166 | return nonseekable_open(inode, file); | 169 | return nonseekable_open(inode, file); |
167 | } | 170 | } |
168 | 171 | ||
@@ -174,11 +177,11 @@ static int omap_wdt_release(struct inode *inode, struct file *file) | |||
174 | * Shut off the timer unless NOWAYOUT is defined. | 177 | * Shut off the timer unless NOWAYOUT is defined. |
175 | */ | 178 | */ |
176 | #ifndef CONFIG_WATCHDOG_NOWAYOUT | 179 | #ifndef CONFIG_WATCHDOG_NOWAYOUT |
180 | pm_runtime_get_sync(wdev->dev); | ||
177 | 181 | ||
178 | omap_wdt_disable(wdev); | 182 | omap_wdt_disable(wdev); |
179 | 183 | ||
180 | clk_disable(wdev->ick); | 184 | pm_runtime_put_sync(wdev->dev); |
181 | clk_disable(wdev->fck); | ||
182 | #else | 185 | #else |
183 | printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); | 186 | printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); |
184 | #endif | 187 | #endif |
@@ -194,9 +197,11 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data, | |||
194 | 197 | ||
195 | /* Refresh LOAD_TIME. */ | 198 | /* Refresh LOAD_TIME. */ |
196 | if (len) { | 199 | if (len) { |
200 | pm_runtime_get_sync(wdev->dev); | ||
197 | spin_lock(&wdt_lock); | 201 | spin_lock(&wdt_lock); |
198 | omap_wdt_ping(wdev); | 202 | omap_wdt_ping(wdev); |
199 | spin_unlock(&wdt_lock); | 203 | spin_unlock(&wdt_lock); |
204 | pm_runtime_put_sync(wdev->dev); | ||
200 | } | 205 | } |
201 | return len; | 206 | return len; |
202 | } | 207 | } |
@@ -228,15 +233,18 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | |||
228 | return put_user(omap_prcm_get_reset_sources(), | 233 | return put_user(omap_prcm_get_reset_sources(), |
229 | (int __user *)arg); | 234 | (int __user *)arg); |
230 | case WDIOC_KEEPALIVE: | 235 | case WDIOC_KEEPALIVE: |
236 | pm_runtime_get_sync(wdev->dev); | ||
231 | spin_lock(&wdt_lock); | 237 | spin_lock(&wdt_lock); |
232 | omap_wdt_ping(wdev); | 238 | omap_wdt_ping(wdev); |
233 | spin_unlock(&wdt_lock); | 239 | spin_unlock(&wdt_lock); |
240 | pm_runtime_put_sync(wdev->dev); | ||
234 | return 0; | 241 | return 0; |
235 | case WDIOC_SETTIMEOUT: | 242 | case WDIOC_SETTIMEOUT: |
236 | if (get_user(new_margin, (int __user *)arg)) | 243 | if (get_user(new_margin, (int __user *)arg)) |
237 | return -EFAULT; | 244 | return -EFAULT; |
238 | omap_wdt_adjust_timeout(new_margin); | 245 | omap_wdt_adjust_timeout(new_margin); |
239 | 246 | ||
247 | pm_runtime_get_sync(wdev->dev); | ||
240 | spin_lock(&wdt_lock); | 248 | spin_lock(&wdt_lock); |
241 | omap_wdt_disable(wdev); | 249 | omap_wdt_disable(wdev); |
242 | omap_wdt_set_timeout(wdev); | 250 | omap_wdt_set_timeout(wdev); |
@@ -244,6 +252,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | |||
244 | 252 | ||
245 | omap_wdt_ping(wdev); | 253 | omap_wdt_ping(wdev); |
246 | spin_unlock(&wdt_lock); | 254 | spin_unlock(&wdt_lock); |
255 | pm_runtime_put_sync(wdev->dev); | ||
247 | /* Fall */ | 256 | /* Fall */ |
248 | case WDIOC_GETTIMEOUT: | 257 | case WDIOC_GETTIMEOUT: |
249 | return put_user(timer_margin, (int __user *)arg); | 258 | return put_user(timer_margin, (int __user *)arg); |
@@ -258,6 +267,7 @@ static const struct file_operations omap_wdt_fops = { | |||
258 | .unlocked_ioctl = omap_wdt_ioctl, | 267 | .unlocked_ioctl = omap_wdt_ioctl, |
259 | .open = omap_wdt_open, | 268 | .open = omap_wdt_open, |
260 | .release = omap_wdt_release, | 269 | .release = omap_wdt_release, |
270 | .llseek = no_llseek, | ||
261 | }; | 271 | }; |
262 | 272 | ||
263 | static int __devinit omap_wdt_probe(struct platform_device *pdev) | 273 | static int __devinit omap_wdt_probe(struct platform_device *pdev) |
@@ -292,19 +302,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) | |||
292 | 302 | ||
293 | wdev->omap_wdt_users = 0; | 303 | wdev->omap_wdt_users = 0; |
294 | wdev->mem = mem; | 304 | wdev->mem = mem; |
295 | 305 | wdev->dev = &pdev->dev; | |
296 | wdev->ick = clk_get(&pdev->dev, "ick"); | ||
297 | if (IS_ERR(wdev->ick)) { | ||
298 | ret = PTR_ERR(wdev->ick); | ||
299 | wdev->ick = NULL; | ||
300 | goto err_clk; | ||
301 | } | ||
302 | wdev->fck = clk_get(&pdev->dev, "fck"); | ||
303 | if (IS_ERR(wdev->fck)) { | ||
304 | ret = PTR_ERR(wdev->fck); | ||
305 | wdev->fck = NULL; | ||
306 | goto err_clk; | ||
307 | } | ||
308 | 306 | ||
309 | wdev->base = ioremap(res->start, resource_size(res)); | 307 | wdev->base = ioremap(res->start, resource_size(res)); |
310 | if (!wdev->base) { | 308 | if (!wdev->base) { |
@@ -314,8 +312,8 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) | |||
314 | 312 | ||
315 | platform_set_drvdata(pdev, wdev); | 313 | platform_set_drvdata(pdev, wdev); |
316 | 314 | ||
317 | clk_enable(wdev->ick); | 315 | pm_runtime_enable(wdev->dev); |
318 | clk_enable(wdev->fck); | 316 | pm_runtime_get_sync(wdev->dev); |
319 | 317 | ||
320 | omap_wdt_disable(wdev); | 318 | omap_wdt_disable(wdev); |
321 | omap_wdt_adjust_timeout(timer_margin); | 319 | omap_wdt_adjust_timeout(timer_margin); |
@@ -333,11 +331,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) | |||
333 | __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, | 331 | __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, |
334 | timer_margin); | 332 | timer_margin); |
335 | 333 | ||
336 | /* autogate OCP interface clock */ | 334 | pm_runtime_put_sync(wdev->dev); |
337 | __raw_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG); | ||
338 | |||
339 | clk_disable(wdev->ick); | ||
340 | clk_disable(wdev->fck); | ||
341 | 335 | ||
342 | omap_wdt_dev = pdev; | 336 | omap_wdt_dev = pdev; |
343 | 337 | ||
@@ -349,12 +343,6 @@ err_misc: | |||
349 | 343 | ||
350 | err_ioremap: | 344 | err_ioremap: |
351 | wdev->base = NULL; | 345 | wdev->base = NULL; |
352 | |||
353 | err_clk: | ||
354 | if (wdev->ick) | ||
355 | clk_put(wdev->ick); | ||
356 | if (wdev->fck) | ||
357 | clk_put(wdev->fck); | ||
358 | kfree(wdev); | 346 | kfree(wdev); |
359 | 347 | ||
360 | err_kzalloc: | 348 | err_kzalloc: |
@@ -370,8 +358,11 @@ static void omap_wdt_shutdown(struct platform_device *pdev) | |||
370 | { | 358 | { |
371 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); | 359 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
372 | 360 | ||
373 | if (wdev->omap_wdt_users) | 361 | if (wdev->omap_wdt_users) { |
362 | pm_runtime_get_sync(wdev->dev); | ||
374 | omap_wdt_disable(wdev); | 363 | omap_wdt_disable(wdev); |
364 | pm_runtime_put_sync(wdev->dev); | ||
365 | } | ||
375 | } | 366 | } |
376 | 367 | ||
377 | static int __devexit omap_wdt_remove(struct platform_device *pdev) | 368 | static int __devexit omap_wdt_remove(struct platform_device *pdev) |
@@ -386,8 +377,6 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev) | |||
386 | release_mem_region(res->start, resource_size(res)); | 377 | release_mem_region(res->start, resource_size(res)); |
387 | platform_set_drvdata(pdev, NULL); | 378 | platform_set_drvdata(pdev, NULL); |
388 | 379 | ||
389 | clk_put(wdev->ick); | ||
390 | clk_put(wdev->fck); | ||
391 | iounmap(wdev->base); | 380 | iounmap(wdev->base); |
392 | 381 | ||
393 | kfree(wdev); | 382 | kfree(wdev); |
@@ -408,8 +397,11 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) | |||
408 | { | 397 | { |
409 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); | 398 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
410 | 399 | ||
411 | if (wdev->omap_wdt_users) | 400 | if (wdev->omap_wdt_users) { |
401 | pm_runtime_get_sync(wdev->dev); | ||
412 | omap_wdt_disable(wdev); | 402 | omap_wdt_disable(wdev); |
403 | pm_runtime_put_sync(wdev->dev); | ||
404 | } | ||
413 | 405 | ||
414 | return 0; | 406 | return 0; |
415 | } | 407 | } |
@@ -419,8 +411,10 @@ static int omap_wdt_resume(struct platform_device *pdev) | |||
419 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); | 411 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
420 | 412 | ||
421 | if (wdev->omap_wdt_users) { | 413 | if (wdev->omap_wdt_users) { |
414 | pm_runtime_get_sync(wdev->dev); | ||
422 | omap_wdt_enable(wdev); | 415 | omap_wdt_enable(wdev); |
423 | omap_wdt_ping(wdev); | 416 | omap_wdt_ping(wdev); |
417 | pm_runtime_put_sync(wdev->dev); | ||
424 | } | 418 | } |
425 | 419 | ||
426 | return 0; | 420 | return 0; |