diff options
-rw-r--r-- | arch/arm/mach-omap2/clockdomain.c | 216 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm24xx.c | 49 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 3 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/clockdomain.h | 8 |
4 files changed, 237 insertions, 39 deletions
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 2af9996f010b..6eaa9314cd64 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c | |||
@@ -113,7 +113,6 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm, | |||
113 | return ERR_PTR(-EINVAL); | 113 | return ERR_PTR(-EINVAL); |
114 | 114 | ||
115 | for (cd = deps; cd->clkdm_name; cd++) { | 115 | for (cd = deps; cd->clkdm_name; cd++) { |
116 | |||
117 | if (!omap_chip_is(cd->omap_chip)) | 116 | if (!omap_chip_is(cd->omap_chip)) |
118 | continue; | 117 | continue; |
119 | 118 | ||
@@ -122,7 +121,6 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm, | |||
122 | 121 | ||
123 | if (cd->clkdm == clkdm) | 122 | if (cd->clkdm == clkdm) |
124 | break; | 123 | break; |
125 | |||
126 | } | 124 | } |
127 | 125 | ||
128 | if (!cd->clkdm_name) | 126 | if (!cd->clkdm_name) |
@@ -254,6 +252,96 @@ static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable) | |||
254 | 252 | ||
255 | } | 253 | } |
256 | 254 | ||
255 | /** | ||
256 | * _init_wkdep_usecount - initialize wkdep usecounts to match hardware | ||
257 | * @clkdm: clockdomain to initialize wkdep usecounts | ||
258 | * | ||
259 | * Initialize the wakeup dependency usecount variables for clockdomain @clkdm. | ||
260 | * If a wakeup dependency is present in the hardware, the usecount will be | ||
261 | * set to 1; otherwise, it will be set to 0. Software should clear all | ||
262 | * software wakeup dependencies prior to calling this function if it wishes | ||
263 | * to ensure that all usecounts start at 0. No return value. | ||
264 | */ | ||
265 | static void _init_wkdep_usecount(struct clockdomain *clkdm) | ||
266 | { | ||
267 | u32 v; | ||
268 | struct clkdm_dep *cd; | ||
269 | |||
270 | if (!clkdm->wkdep_srcs) | ||
271 | return; | ||
272 | |||
273 | for (cd = clkdm->wkdep_srcs; cd->clkdm_name; cd++) { | ||
274 | if (!omap_chip_is(cd->omap_chip)) | ||
275 | continue; | ||
276 | |||
277 | if (!cd->clkdm && cd->clkdm_name) | ||
278 | cd->clkdm = _clkdm_lookup(cd->clkdm_name); | ||
279 | |||
280 | if (!cd->clkdm) { | ||
281 | WARN(!cd->clkdm, "clockdomain: %s: wkdep clkdm %s not " | ||
282 | "found\n", clkdm->name, cd->clkdm_name); | ||
283 | continue; | ||
284 | } | ||
285 | |||
286 | v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs, | ||
287 | PM_WKDEP, | ||
288 | (1 << cd->clkdm->dep_bit)); | ||
289 | |||
290 | if (v) | ||
291 | pr_debug("clockdomain: %s: wakeup dependency already " | ||
292 | "set to wake up when %s wakes\n", | ||
293 | clkdm->name, cd->clkdm->name); | ||
294 | |||
295 | atomic_set(&cd->wkdep_usecount, (v) ? 1 : 0); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * _init_sleepdep_usecount - initialize sleepdep usecounts to match hardware | ||
301 | * @clkdm: clockdomain to initialize sleepdep usecounts | ||
302 | * | ||
303 | * Initialize the sleep dependency usecount variables for clockdomain @clkdm. | ||
304 | * If a sleep dependency is present in the hardware, the usecount will be | ||
305 | * set to 1; otherwise, it will be set to 0. Software should clear all | ||
306 | * software sleep dependencies prior to calling this function if it wishes | ||
307 | * to ensure that all usecounts start at 0. No return value. | ||
308 | */ | ||
309 | static void _init_sleepdep_usecount(struct clockdomain *clkdm) | ||
310 | { | ||
311 | u32 v; | ||
312 | struct clkdm_dep *cd; | ||
313 | |||
314 | if (!cpu_is_omap34xx()) | ||
315 | return; | ||
316 | |||
317 | if (!clkdm->sleepdep_srcs) | ||
318 | return; | ||
319 | |||
320 | for (cd = clkdm->sleepdep_srcs; cd->clkdm_name; cd++) { | ||
321 | if (!omap_chip_is(cd->omap_chip)) | ||
322 | continue; | ||
323 | |||
324 | if (!cd->clkdm && cd->clkdm_name) | ||
325 | cd->clkdm = _clkdm_lookup(cd->clkdm_name); | ||
326 | |||
327 | if (!cd->clkdm) { | ||
328 | WARN(!cd->clkdm, "clockdomain: %s: sleepdep clkdm %s " | ||
329 | "not found\n", clkdm->name, cd->clkdm_name); | ||
330 | continue; | ||
331 | } | ||
332 | |||
333 | v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs, | ||
334 | OMAP3430_CM_SLEEPDEP, | ||
335 | (1 << cd->clkdm->dep_bit)); | ||
336 | |||
337 | if (v) | ||
338 | pr_debug("clockdomain: %s: sleep dependency already " | ||
339 | "set to prevent from idling until %s " | ||
340 | "idles\n", clkdm->name, cd->clkdm->name); | ||
341 | |||
342 | atomic_set(&cd->sleepdep_usecount, (v) ? 1 : 0); | ||
343 | } | ||
344 | }; | ||
257 | 345 | ||
258 | /* Public functions */ | 346 | /* Public functions */ |
259 | 347 | ||
@@ -272,6 +360,7 @@ void clkdm_init(struct clockdomain **clkdms, | |||
272 | struct clkdm_autodep *init_autodeps) | 360 | struct clkdm_autodep *init_autodeps) |
273 | { | 361 | { |
274 | struct clockdomain **c = NULL; | 362 | struct clockdomain **c = NULL; |
363 | struct clockdomain *clkdm; | ||
275 | struct clkdm_autodep *autodep = NULL; | 364 | struct clkdm_autodep *autodep = NULL; |
276 | 365 | ||
277 | if (clkdms) | 366 | if (clkdms) |
@@ -282,6 +371,15 @@ void clkdm_init(struct clockdomain **clkdms, | |||
282 | if (autodeps) | 371 | if (autodeps) |
283 | for (autodep = autodeps; autodep->clkdm.ptr; autodep++) | 372 | for (autodep = autodeps; autodep->clkdm.ptr; autodep++) |
284 | _autodep_lookup(autodep); | 373 | _autodep_lookup(autodep); |
374 | |||
375 | /* | ||
376 | * Ensure that the *dep_usecount registers reflect the current | ||
377 | * state of the PRCM. | ||
378 | */ | ||
379 | list_for_each_entry(clkdm, &clkdm_list, node) { | ||
380 | _init_wkdep_usecount(clkdm); | ||
381 | _init_sleepdep_usecount(clkdm); | ||
382 | } | ||
285 | } | 383 | } |
286 | 384 | ||
287 | /** | 385 | /** |
@@ -387,11 +485,13 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
387 | return PTR_ERR(cd); | 485 | return PTR_ERR(cd); |
388 | } | 486 | } |
389 | 487 | ||
390 | pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n", | 488 | if (atomic_inc_return(&cd->wkdep_usecount) == 1) { |
391 | clkdm1->name, clkdm2->name); | 489 | pr_debug("clockdomain: hardware will wake up %s when %s wakes " |
490 | "up\n", clkdm1->name, clkdm2->name); | ||
392 | 491 | ||
393 | prm_set_mod_reg_bits((1 << clkdm2->dep_bit), | 492 | prm_set_mod_reg_bits((1 << clkdm2->dep_bit), |
394 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); | 493 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); |
494 | } | ||
395 | 495 | ||
396 | return 0; | 496 | return 0; |
397 | } | 497 | } |
@@ -420,11 +520,13 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
420 | return PTR_ERR(cd); | 520 | return PTR_ERR(cd); |
421 | } | 521 | } |
422 | 522 | ||
423 | pr_debug("clockdomain: hardware will no longer wake up %s after %s " | 523 | if (atomic_dec_return(&cd->wkdep_usecount) == 0) { |
424 | "wakes up\n", clkdm1->name, clkdm2->name); | 524 | pr_debug("clockdomain: hardware will no longer wake up %s " |
525 | "after %s wakes up\n", clkdm1->name, clkdm2->name); | ||
425 | 526 | ||
426 | prm_clear_mod_reg_bits((1 << clkdm2->dep_bit), | 527 | prm_clear_mod_reg_bits((1 << clkdm2->dep_bit), |
427 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); | 528 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); |
529 | } | ||
428 | 530 | ||
429 | return 0; | 531 | return 0; |
430 | } | 532 | } |
@@ -457,11 +559,44 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
457 | return PTR_ERR(cd); | 559 | return PTR_ERR(cd); |
458 | } | 560 | } |
459 | 561 | ||
562 | /* XXX It's faster to return the atomic wkdep_usecount */ | ||
460 | return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP, | 563 | return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP, |
461 | (1 << clkdm2->dep_bit)); | 564 | (1 << clkdm2->dep_bit)); |
462 | } | 565 | } |
463 | 566 | ||
464 | /** | 567 | /** |
568 | * clkdm_clear_all_wkdeps - remove all wakeup dependencies from target clkdm | ||
569 | * @clkdm: struct clockdomain * to remove all wakeup dependencies from | ||
570 | * | ||
571 | * Remove all inter-clockdomain wakeup dependencies that could cause | ||
572 | * @clkdm to wake. Intended to be used during boot to initialize the | ||
573 | * PRCM to a known state, after all clockdomains are put into swsup idle | ||
574 | * and woken up. Returns -EINVAL if @clkdm pointer is invalid, or | ||
575 | * 0 upon success. | ||
576 | */ | ||
577 | int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) | ||
578 | { | ||
579 | struct clkdm_dep *cd; | ||
580 | u32 mask = 0; | ||
581 | |||
582 | if (!clkdm) | ||
583 | return -EINVAL; | ||
584 | |||
585 | for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { | ||
586 | if (!omap_chip_is(cd->omap_chip)) | ||
587 | continue; | ||
588 | |||
589 | /* PRM accesses are slow, so minimize them */ | ||
590 | mask |= 1 << cd->clkdm->dep_bit; | ||
591 | atomic_set(&cd->wkdep_usecount, 0); | ||
592 | } | ||
593 | |||
594 | prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP); | ||
595 | |||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | /** | ||
465 | * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1 | 600 | * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1 |
466 | * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) | 601 | * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) |
467 | * @clkdm2: when this struct clockdomain * is active (source) | 602 | * @clkdm2: when this struct clockdomain * is active (source) |
@@ -491,12 +626,14 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
491 | return PTR_ERR(cd); | 626 | return PTR_ERR(cd); |
492 | } | 627 | } |
493 | 628 | ||
494 | pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n", | 629 | if (atomic_inc_return(&cd->sleepdep_usecount) == 1) { |
495 | clkdm1->name, clkdm2->name); | 630 | pr_debug("clockdomain: will prevent %s from sleeping if %s " |
631 | "is active\n", clkdm1->name, clkdm2->name); | ||
496 | 632 | ||
497 | cm_set_mod_reg_bits((1 << clkdm2->dep_bit), | 633 | cm_set_mod_reg_bits((1 << clkdm2->dep_bit), |
498 | clkdm1->pwrdm.ptr->prcm_offs, | 634 | clkdm1->pwrdm.ptr->prcm_offs, |
499 | OMAP3430_CM_SLEEPDEP); | 635 | OMAP3430_CM_SLEEPDEP); |
636 | } | ||
500 | 637 | ||
501 | return 0; | 638 | return 0; |
502 | } | 639 | } |
@@ -531,12 +668,15 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
531 | return PTR_ERR(cd); | 668 | return PTR_ERR(cd); |
532 | } | 669 | } |
533 | 670 | ||
534 | pr_debug("clockdomain: will no longer prevent %s from sleeping if " | 671 | if (atomic_dec_return(&cd->sleepdep_usecount) == 0) { |
535 | "%s is active\n", clkdm1->name, clkdm2->name); | 672 | pr_debug("clockdomain: will no longer prevent %s from " |
673 | "sleeping if %s is active\n", clkdm1->name, | ||
674 | clkdm2->name); | ||
536 | 675 | ||
537 | cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), | 676 | cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), |
538 | clkdm1->pwrdm.ptr->prcm_offs, | 677 | clkdm1->pwrdm.ptr->prcm_offs, |
539 | OMAP3430_CM_SLEEPDEP); | 678 | OMAP3430_CM_SLEEPDEP); |
679 | } | ||
540 | 680 | ||
541 | return 0; | 681 | return 0; |
542 | } | 682 | } |
@@ -575,11 +715,47 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
575 | return PTR_ERR(cd); | 715 | return PTR_ERR(cd); |
576 | } | 716 | } |
577 | 717 | ||
718 | /* XXX It's faster to return the atomic sleepdep_usecount */ | ||
578 | return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, | 719 | return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, |
579 | OMAP3430_CM_SLEEPDEP, | 720 | OMAP3430_CM_SLEEPDEP, |
580 | (1 << clkdm2->dep_bit)); | 721 | (1 << clkdm2->dep_bit)); |
581 | } | 722 | } |
582 | 723 | ||
724 | /** | ||
725 | * clkdm_clear_all_sleepdeps - remove all sleep dependencies from target clkdm | ||
726 | * @clkdm: struct clockdomain * to remove all sleep dependencies from | ||
727 | * | ||
728 | * Remove all inter-clockdomain sleep dependencies that could prevent | ||
729 | * @clkdm from idling. Intended to be used during boot to initialize the | ||
730 | * PRCM to a known state, after all clockdomains are put into swsup idle | ||
731 | * and woken up. Returns -EINVAL if @clkdm pointer is invalid, or | ||
732 | * 0 upon success. | ||
733 | */ | ||
734 | int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) | ||
735 | { | ||
736 | struct clkdm_dep *cd; | ||
737 | u32 mask = 0; | ||
738 | |||
739 | if (!cpu_is_omap34xx()) | ||
740 | return -EINVAL; | ||
741 | |||
742 | if (!clkdm) | ||
743 | return -EINVAL; | ||
744 | |||
745 | for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) { | ||
746 | if (!omap_chip_is(cd->omap_chip)) | ||
747 | continue; | ||
748 | |||
749 | /* PRM accesses are slow, so minimize them */ | ||
750 | mask |= 1 << cd->clkdm->dep_bit; | ||
751 | atomic_set(&cd->sleepdep_usecount, 0); | ||
752 | } | ||
753 | |||
754 | prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, | ||
755 | OMAP3430_CM_SLEEPDEP); | ||
756 | |||
757 | return 0; | ||
758 | } | ||
583 | 759 | ||
584 | /** | 760 | /** |
585 | * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode | 761 | * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode |
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 754381857cb6..374299ea7ade 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c | |||
@@ -57,11 +57,8 @@ static void (*omap2_sram_idle)(void); | |||
57 | static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl, | 57 | static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl, |
58 | void __iomem *sdrc_power); | 58 | void __iomem *sdrc_power); |
59 | 59 | ||
60 | static struct powerdomain *mpu_pwrdm; | 60 | static struct powerdomain *mpu_pwrdm, *core_pwrdm; |
61 | static struct powerdomain *core_pwrdm; | 61 | static struct clockdomain *dsp_clkdm, *mpu_clkdm, *wkup_clkdm, *gfx_clkdm; |
62 | |||
63 | static struct clockdomain *dsp_clkdm; | ||
64 | static struct clockdomain *gfx_clkdm; | ||
65 | 62 | ||
66 | static struct clk *osc_ck, *emul_ck; | 63 | static struct clk *osc_ck, *emul_ck; |
67 | 64 | ||
@@ -334,9 +331,17 @@ static struct platform_suspend_ops omap_pm_ops = { | |||
334 | .valid = suspend_valid_only_mem, | 331 | .valid = suspend_valid_only_mem, |
335 | }; | 332 | }; |
336 | 333 | ||
337 | static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm, void *unused) | 334 | /* XXX This function should be shareable between OMAP2xxx and OMAP3 */ |
335 | static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) | ||
338 | { | 336 | { |
339 | omap2_clkdm_allow_idle(clkdm); | 337 | clkdm_clear_all_wkdeps(clkdm); |
338 | clkdm_clear_all_sleepdeps(clkdm); | ||
339 | |||
340 | if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO) | ||
341 | omap2_clkdm_allow_idle(clkdm); | ||
342 | else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && | ||
343 | atomic_read(&clkdm->usecount) == 0) | ||
344 | omap2_clkdm_sleep(clkdm); | ||
340 | return 0; | 345 | return 0; |
341 | } | 346 | } |
342 | 347 | ||
@@ -349,14 +354,6 @@ static void __init prcm_setup_regs(void) | |||
349 | prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD, | 354 | prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD, |
350 | OMAP2_PRCM_SYSCONFIG_OFFSET); | 355 | OMAP2_PRCM_SYSCONFIG_OFFSET); |
351 | 356 | ||
352 | /* Set all domain wakeup dependencies */ | ||
353 | prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP); | ||
354 | prm_write_mod_reg(0, OMAP24XX_DSP_MOD, PM_WKDEP); | ||
355 | prm_write_mod_reg(0, GFX_MOD, PM_WKDEP); | ||
356 | prm_write_mod_reg(0, CORE_MOD, PM_WKDEP); | ||
357 | if (cpu_is_omap2430()) | ||
358 | prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP); | ||
359 | |||
360 | /* | 357 | /* |
361 | * Set CORE powerdomain memory banks to retain their contents | 358 | * Set CORE powerdomain memory banks to retain their contents |
362 | * during RETENTION | 359 | * during RETENTION |
@@ -385,8 +382,12 @@ static void __init prcm_setup_regs(void) | |||
385 | pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); | 382 | pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); |
386 | omap2_clkdm_sleep(gfx_clkdm); | 383 | omap2_clkdm_sleep(gfx_clkdm); |
387 | 384 | ||
388 | /* Enable clockdomain hardware-supervised control for all clkdms */ | 385 | /* |
389 | clkdm_for_each(_pm_clkdm_enable_hwsup, NULL); | 386 | * Clear clockdomain wakeup dependencies and enable |
387 | * hardware-supervised idle for all clkdms | ||
388 | */ | ||
389 | clkdm_for_each(clkdms_setup, NULL); | ||
390 | clkdm_add_wkdep(mpu_clkdm, wkup_clkdm); | ||
390 | 391 | ||
391 | /* Enable clock autoidle for all domains */ | 392 | /* Enable clock autoidle for all domains */ |
392 | cm_write_mod_reg(OMAP24XX_AUTO_CAM | | 393 | cm_write_mod_reg(OMAP24XX_AUTO_CAM | |
@@ -482,7 +483,7 @@ static int __init omap2_pm_init(void) | |||
482 | l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET); | 483 | l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET); |
483 | printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f); | 484 | printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f); |
484 | 485 | ||
485 | /* Look up important powerdomains, clockdomains */ | 486 | /* Look up important powerdomains */ |
486 | 487 | ||
487 | mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); | 488 | mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); |
488 | if (!mpu_pwrdm) | 489 | if (!mpu_pwrdm) |
@@ -492,9 +493,19 @@ static int __init omap2_pm_init(void) | |||
492 | if (!core_pwrdm) | 493 | if (!core_pwrdm) |
493 | pr_err("PM: core_pwrdm not found\n"); | 494 | pr_err("PM: core_pwrdm not found\n"); |
494 | 495 | ||
496 | /* Look up important clockdomains */ | ||
497 | |||
498 | mpu_clkdm = clkdm_lookup("mpu_clkdm"); | ||
499 | if (!mpu_clkdm) | ||
500 | pr_err("PM: mpu_clkdm not found\n"); | ||
501 | |||
502 | wkup_clkdm = clkdm_lookup("wkup_clkdm"); | ||
503 | if (!wkup_clkdm) | ||
504 | pr_err("PM: wkup_clkdm not found\n"); | ||
505 | |||
495 | dsp_clkdm = clkdm_lookup("dsp_clkdm"); | 506 | dsp_clkdm = clkdm_lookup("dsp_clkdm"); |
496 | if (!dsp_clkdm) | 507 | if (!dsp_clkdm) |
497 | pr_err("PM: mpu_clkdm not found\n"); | 508 | pr_err("PM: dsp_clkdm not found\n"); |
498 | 509 | ||
499 | gfx_clkdm = clkdm_lookup("gfx_clkdm"); | 510 | gfx_clkdm = clkdm_lookup("gfx_clkdm"); |
500 | if (!gfx_clkdm) | 511 | if (!gfx_clkdm) |
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 5f59df87abf7..5087b153b093 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c | |||
@@ -998,6 +998,9 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) | |||
998 | */ | 998 | */ |
999 | static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) | 999 | static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) |
1000 | { | 1000 | { |
1001 | clkdm_clear_all_wkdeps(clkdm); | ||
1002 | clkdm_clear_all_sleepdeps(clkdm); | ||
1003 | |||
1001 | if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO) | 1004 | if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO) |
1002 | omap2_clkdm_allow_idle(clkdm); | 1005 | omap2_clkdm_allow_idle(clkdm); |
1003 | else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && | 1006 | else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && |
diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h index 22869713265f..45b5debc5d3f 100644 --- a/arch/arm/plat-omap/include/plat/clockdomain.h +++ b/arch/arm/plat-omap/include/plat/clockdomain.h | |||
@@ -70,6 +70,12 @@ struct clkdm_dep { | |||
70 | /* Clockdomain pointer - resolved by the clockdomain code */ | 70 | /* Clockdomain pointer - resolved by the clockdomain code */ |
71 | struct clockdomain *clkdm; | 71 | struct clockdomain *clkdm; |
72 | 72 | ||
73 | /* Number of wakeup dependencies causing this clkdm to wake */ | ||
74 | atomic_t wkdep_usecount; | ||
75 | |||
76 | /* Number of sleep dependencies that could prevent clkdm from idle */ | ||
77 | atomic_t sleepdep_usecount; | ||
78 | |||
73 | /* Flags to mark OMAP chip restrictions, etc. */ | 79 | /* Flags to mark OMAP chip restrictions, etc. */ |
74 | const struct omap_chip_id omap_chip; | 80 | const struct omap_chip_id omap_chip; |
75 | 81 | ||
@@ -126,9 +132,11 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm); | |||
126 | int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); | 132 | int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); |
127 | int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); | 133 | int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); |
128 | int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); | 134 | int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); |
135 | int clkdm_clear_all_wkdeps(struct clockdomain *clkdm); | ||
129 | int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); | 136 | int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); |
130 | int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); | 137 | int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); |
131 | int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); | 138 | int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); |
139 | int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); | ||
132 | 140 | ||
133 | void omap2_clkdm_allow_idle(struct clockdomain *clkdm); | 141 | void omap2_clkdm_allow_idle(struct clockdomain *clkdm); |
134 | void omap2_clkdm_deny_idle(struct clockdomain *clkdm); | 142 | void omap2_clkdm_deny_idle(struct clockdomain *clkdm); |