Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Watchdog: omap_wdt: add fine grain runtime-pm

The omap_wdt should only be in full active state when the
registers are being accessed. Otherwise the device can be
on lower power mode.

This patch is based on a patch created by Kalle Jokiniemi:
https://patchwork.kernel.org/patch/618231/
which is itself based on a patch created by Atal
Shargorodsky: http://lkml.org/lkml/2009/3/10/266.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Kalle Jokiniemi <kalle.jokiniemi@nokia.com>
Tested-by: Kalle Jokiniemi <kalle.jokiniemi@nokia.com>
Cc: Wim Van Sebroeck <wim@iguana.be>
Acked-by: Wim Van Sebroeck <wim@iguana.be>
Acked-by: Kevin Hilman <khilman@ti.com>

+23 -2
+23 -2
drivers/watchdog/omap_wdt.c
··· 124 124 u32 pre_margin = GET_WLDR_VAL(timer_margin); 125 125 void __iomem *base = wdev->base; 126 126 127 + pm_runtime_get_sync(wdev->dev); 128 + 127 129 /* just count up at 32 KHz */ 128 130 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) 129 131 cpu_relax(); ··· 133 131 __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); 134 132 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) 135 133 cpu_relax(); 134 + 135 + pm_runtime_put_sync(wdev->dev); 136 136 } 137 137 138 138 /* ··· 164 160 omap_wdt_ping(wdev); /* trigger loading of new timeout value */ 165 161 omap_wdt_enable(wdev); 166 162 163 + pm_runtime_put_sync(wdev->dev); 164 + 167 165 return nonseekable_open(inode, file); 168 166 } 169 167 ··· 177 171 * Shut off the timer unless NOWAYOUT is defined. 178 172 */ 179 173 #ifndef CONFIG_WATCHDOG_NOWAYOUT 174 + pm_runtime_get_sync(wdev->dev); 180 175 181 176 omap_wdt_disable(wdev); 182 177 ··· 197 190 198 191 /* Refresh LOAD_TIME. */ 199 192 if (len) { 193 + pm_runtime_get_sync(wdev->dev); 200 194 spin_lock(&wdt_lock); 201 195 omap_wdt_ping(wdev); 202 196 spin_unlock(&wdt_lock); 197 + pm_runtime_put_sync(wdev->dev); 203 198 } 204 199 return len; 205 200 } ··· 233 224 return put_user(omap_prcm_get_reset_sources(), 234 225 (int __user *)arg); 235 226 case WDIOC_KEEPALIVE: 227 + pm_runtime_get_sync(wdev->dev); 236 228 spin_lock(&wdt_lock); 237 229 omap_wdt_ping(wdev); 238 230 spin_unlock(&wdt_lock); 231 + pm_runtime_put_sync(wdev->dev); 239 232 return 0; 240 233 case WDIOC_SETTIMEOUT: 241 234 if (get_user(new_margin, (int __user *)arg)) 242 235 return -EFAULT; 243 236 omap_wdt_adjust_timeout(new_margin); 244 237 238 + pm_runtime_get_sync(wdev->dev); 245 239 spin_lock(&wdt_lock); 246 240 omap_wdt_disable(wdev); 247 241 omap_wdt_set_timeout(wdev); ··· 252 240 253 241 omap_wdt_ping(wdev); 254 242 spin_unlock(&wdt_lock); 243 + pm_runtime_put_sync(wdev->dev); 255 244 /* Fall */ 256 245 case WDIOC_GETTIMEOUT: 257 246 return put_user(timer_margin, (int __user *)arg); ··· 358 345 { 359 346 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 360 347 361 - if (wdev->omap_wdt_users) 348 + if (wdev->omap_wdt_users) { 349 + pm_runtime_get_sync(wdev->dev); 362 350 omap_wdt_disable(wdev); 351 + pm_runtime_put_sync(wdev->dev); 352 + } 363 353 } 364 354 365 355 static int __devexit omap_wdt_remove(struct platform_device *pdev) ··· 397 381 { 398 382 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 399 383 400 - if (wdev->omap_wdt_users) 384 + if (wdev->omap_wdt_users) { 385 + pm_runtime_get_sync(wdev->dev); 401 386 omap_wdt_disable(wdev); 387 + pm_runtime_put_sync(wdev->dev); 388 + } 402 389 403 390 return 0; 404 391 } ··· 411 392 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 412 393 413 394 if (wdev->omap_wdt_users) { 395 + pm_runtime_get_sync(wdev->dev); 414 396 omap_wdt_enable(wdev); 415 397 omap_wdt_ping(wdev); 398 + pm_runtime_put_sync(wdev->dev); 416 399 } 417 400 418 401 return 0;