aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLokesh Vutla <lokeshvutla@ti.com>2012-06-18 01:23:16 -0400
committerWim Van Sebroeck <wim@iguana.be>2012-07-23 06:50:11 -0400
commit41814eed414ab3cef3d2b857ae3690a2b4888291 (patch)
treef027af4b049e2bcc366be42916b98c425fbce483
parent0402450f45673d3c03340cb1e679bf2a1fc0abee (diff)
Watchdog: OMAP: Fix the runtime pm code to avoid module getting stuck intransition state.
OMAP watchdog driver is adapted to runtime PM like a general device driver but it is not appropriate. It is causing couple of functional issues. 1. On OMAP4 SYSCLK can't be gated, because of issue with WDTIMER2 module, which constantly stays in "in transition" state. Value of register CM_WKUP_WDTIMER2_CLKCTRL is always 0x00010000 in this case. Issue occurs immediately after first idle, when hwmod framework tries to disable WDTIMER2 functional clock - "wd_timer2_fck". After this module falls to "in transition" state, and SYSCLK gating is blocked. 2. Due to runtime PM, watchdog timer may be completely disabled. In current code base watchdog timer is not disabled only because of issue 1. Otherwise state of WDTIMER2 module will be "Disabled", and there will be no interrupts from omap_wdt. In other words watchdog will not work at all. Watchdong is a special IP and it should not be disabled otherwise purpose of it itself is defeated. Watchdog functional clock should never be disabled. This patch updates the runtime PM handling in driver so that runtime PM is limited only during probe/shutdown and suspend/resume. The patch fixes issue 1 and 2 Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
-rw-r--r--drivers/watchdog/omap_wdt.c17
1 files changed, 0 insertions, 17 deletions
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 8285d65cd207..27ab8db67d14 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -126,8 +126,6 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev)
126 u32 pre_margin = GET_WLDR_VAL(timer_margin); 126 u32 pre_margin = GET_WLDR_VAL(timer_margin);
127 void __iomem *base = wdev->base; 127 void __iomem *base = wdev->base;
128 128
129 pm_runtime_get_sync(wdev->dev);
130
131 /* just count up at 32 KHz */ 129 /* just count up at 32 KHz */
132 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) 130 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
133 cpu_relax(); 131 cpu_relax();
@@ -135,8 +133,6 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev)
135 __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); 133 __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR);
136 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) 134 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
137 cpu_relax(); 135 cpu_relax();
138
139 pm_runtime_put_sync(wdev->dev);
140} 136}
141 137
142/* 138/*
@@ -166,8 +162,6 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
166 omap_wdt_ping(wdev); /* trigger loading of new timeout value */ 162 omap_wdt_ping(wdev); /* trigger loading of new timeout value */
167 omap_wdt_enable(wdev); 163 omap_wdt_enable(wdev);
168 164
169 pm_runtime_put_sync(wdev->dev);
170
171 return nonseekable_open(inode, file); 165 return nonseekable_open(inode, file);
172} 166}
173 167
@@ -179,8 +173,6 @@ static int omap_wdt_release(struct inode *inode, struct file *file)
179 * Shut off the timer unless NOWAYOUT is defined. 173 * Shut off the timer unless NOWAYOUT is defined.
180 */ 174 */
181#ifndef CONFIG_WATCHDOG_NOWAYOUT 175#ifndef CONFIG_WATCHDOG_NOWAYOUT
182 pm_runtime_get_sync(wdev->dev);
183
184 omap_wdt_disable(wdev); 176 omap_wdt_disable(wdev);
185 177
186 pm_runtime_put_sync(wdev->dev); 178 pm_runtime_put_sync(wdev->dev);
@@ -199,11 +191,9 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data,
199 191
200 /* Refresh LOAD_TIME. */ 192 /* Refresh LOAD_TIME. */
201 if (len) { 193 if (len) {
202 pm_runtime_get_sync(wdev->dev);
203 spin_lock(&wdt_lock); 194 spin_lock(&wdt_lock);
204 omap_wdt_ping(wdev); 195 omap_wdt_ping(wdev);
205 spin_unlock(&wdt_lock); 196 spin_unlock(&wdt_lock);
206 pm_runtime_put_sync(wdev->dev);
207 } 197 }
208 return len; 198 return len;
209} 199}
@@ -236,18 +226,15 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
236 (int __user *)arg); 226 (int __user *)arg);
237 return put_user(0, (int __user *)arg); 227 return put_user(0, (int __user *)arg);
238 case WDIOC_KEEPALIVE: 228 case WDIOC_KEEPALIVE:
239 pm_runtime_get_sync(wdev->dev);
240 spin_lock(&wdt_lock); 229 spin_lock(&wdt_lock);
241 omap_wdt_ping(wdev); 230 omap_wdt_ping(wdev);
242 spin_unlock(&wdt_lock); 231 spin_unlock(&wdt_lock);
243 pm_runtime_put_sync(wdev->dev);
244 return 0; 232 return 0;
245 case WDIOC_SETTIMEOUT: 233 case WDIOC_SETTIMEOUT:
246 if (get_user(new_margin, (int __user *)arg)) 234 if (get_user(new_margin, (int __user *)arg))
247 return -EFAULT; 235 return -EFAULT;
248 omap_wdt_adjust_timeout(new_margin); 236 omap_wdt_adjust_timeout(new_margin);
249 237
250 pm_runtime_get_sync(wdev->dev);
251 spin_lock(&wdt_lock); 238 spin_lock(&wdt_lock);
252 omap_wdt_disable(wdev); 239 omap_wdt_disable(wdev);
253 omap_wdt_set_timeout(wdev); 240 omap_wdt_set_timeout(wdev);
@@ -255,7 +242,6 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
255 242
256 omap_wdt_ping(wdev); 243 omap_wdt_ping(wdev);
257 spin_unlock(&wdt_lock); 244 spin_unlock(&wdt_lock);
258 pm_runtime_put_sync(wdev->dev);
259 /* Fall */ 245 /* Fall */
260 case WDIOC_GETTIMEOUT: 246 case WDIOC_GETTIMEOUT:
261 return put_user(timer_margin, (int __user *)arg); 247 return put_user(timer_margin, (int __user *)arg);
@@ -363,7 +349,6 @@ static void omap_wdt_shutdown(struct platform_device *pdev)
363 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 349 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
364 350
365 if (wdev->omap_wdt_users) { 351 if (wdev->omap_wdt_users) {
366 pm_runtime_get_sync(wdev->dev);
367 omap_wdt_disable(wdev); 352 omap_wdt_disable(wdev);
368 pm_runtime_put_sync(wdev->dev); 353 pm_runtime_put_sync(wdev->dev);
369 } 354 }
@@ -403,7 +388,6 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
403 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 388 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
404 389
405 if (wdev->omap_wdt_users) { 390 if (wdev->omap_wdt_users) {
406 pm_runtime_get_sync(wdev->dev);
407 omap_wdt_disable(wdev); 391 omap_wdt_disable(wdev);
408 pm_runtime_put_sync(wdev->dev); 392 pm_runtime_put_sync(wdev->dev);
409 } 393 }
@@ -419,7 +403,6 @@ static int omap_wdt_resume(struct platform_device *pdev)
419 pm_runtime_get_sync(wdev->dev); 403 pm_runtime_get_sync(wdev->dev);
420 omap_wdt_enable(wdev); 404 omap_wdt_enable(wdev);
421 omap_wdt_ping(wdev); 405 omap_wdt_ping(wdev);
422 pm_runtime_put_sync(wdev->dev);
423 } 406 }
424 407
425 return 0; 408 return 0;