aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/powerdomain.c
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2010-01-26 22:12:59 -0500
committerPaul Walmsley <paul@pwsan.com>2010-01-26 22:12:59 -0500
commit55ed96945b1f3d0f4ad21a27b32ce4bd99d8c268 (patch)
tree0bec60498742922a9c00f39ff63eb48549d391fc /arch/arm/mach-omap2/powerdomain.c
parent6b04e0d99d4113ede24e263e3df246a17f490339 (diff)
OMAP2/3 clkdm/pwrdm: move wkdep/sleepdep handling from pwrdm to clkdm
Move clockdomain wakeup dependency and sleep dependency data structures from the powerdomain layer to the clockdomain layer, where they belong. These dependencies were originally placed in the powerdomain layer due to unclear documentation; however, it is clear now that these dependencies are between clockdomains. For OMAP2/3, this is not such a big problem, but for OMAP4 this needs to be fixed. Thanks to Benoît Cousson <b-cousson@ti.com> for his advice on this patch. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Benoît Cousson <b-cousson@ti.com>
Diffstat (limited to 'arch/arm/mach-omap2/powerdomain.c')
-rw-r--r--arch/arm/mach-omap2/powerdomain.c259
1 files changed, 2 insertions, 257 deletions
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index c0de05097b5d..e8e8d8872a0e 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -2,7 +2,7 @@
2 * OMAP powerdomain control 2 * OMAP powerdomain control
3 * 3 *
4 * Copyright (C) 2007-2008 Texas Instruments, Inc. 4 * Copyright (C) 2007-2008 Texas Instruments, Inc.
5 * Copyright (C) 2007-2008 Nokia Corporation 5 * Copyright (C) 2007-2009 Nokia Corporation
6 * 6 *
7 * Written by Paul Walmsley 7 * Written by Paul Walmsley
8 * 8 *
@@ -36,6 +36,7 @@
36#include <plat/cpu.h> 36#include <plat/cpu.h>
37#include <plat/powerdomain.h> 37#include <plat/powerdomain.h>
38#include <plat/clockdomain.h> 38#include <plat/clockdomain.h>
39#include <plat/prcm.h>
39 40
40#include "pm.h" 41#include "pm.h"
41 42
@@ -88,17 +89,6 @@ static DEFINE_RWLOCK(pwrdm_rwlock);
88 89
89/* Private functions */ 90/* Private functions */
90 91
91static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
92{
93 u32 v;
94
95 v = prm_read_mod_reg(domain, idx);
96 v &= mask;
97 v >>= __ffs(mask);
98
99 return v;
100}
101
102static struct powerdomain *_pwrdm_lookup(const char *name) 92static struct powerdomain *_pwrdm_lookup(const char *name)
103{ 93{
104 struct powerdomain *pwrdm, *temp_pwrdm; 94 struct powerdomain *pwrdm, *temp_pwrdm;
@@ -115,34 +105,6 @@ static struct powerdomain *_pwrdm_lookup(const char *name)
115 return pwrdm; 105 return pwrdm;
116} 106}
117 107
118/* _pwrdm_deps_lookup - look up the specified powerdomain in a pwrdm list */
119static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
120 struct pwrdm_dep *deps)
121{
122 struct pwrdm_dep *pd;
123
124 if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip))
125 return ERR_PTR(-EINVAL);
126
127 for (pd = deps; pd->pwrdm_name; pd++) {
128
129 if (!omap_chip_is(pd->omap_chip))
130 continue;
131
132 if (!pd->pwrdm && pd->pwrdm_name)
133 pd->pwrdm = pwrdm_lookup(pd->pwrdm_name);
134
135 if (pd->pwrdm == pwrdm)
136 break;
137
138 }
139
140 if (!pd->pwrdm_name)
141 return ERR_PTR(-ENOENT);
142
143 return pd->pwrdm;
144}
145
146static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) 108static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
147{ 109{
148 110
@@ -502,223 +464,6 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
502 return ret; 464 return ret;
503} 465}
504 466
505
506/**
507 * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1
508 * @pwrdm1: wake this struct powerdomain * up (dependent)
509 * @pwrdm2: when this struct powerdomain * wakes up (source)
510 *
511 * When the powerdomain represented by pwrdm2 wakes up (due to an
512 * interrupt), wake up pwrdm1. Implemented in hardware on the OMAP,
513 * this feature is designed to reduce wakeup latency of the dependent
514 * powerdomain. Returns -EINVAL if presented with invalid powerdomain
515 * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
516 * 0 upon success.
517 */
518int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
519{
520 struct powerdomain *p;
521
522 if (!pwrdm1)
523 return -EINVAL;
524
525 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
526 if (IS_ERR(p)) {
527 pr_debug("powerdomain: hardware cannot set/clear wake up of "
528 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
529 return PTR_ERR(p);
530 }
531
532 pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n",
533 pwrdm1->name, pwrdm2->name);
534
535 prm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
536 pwrdm1->prcm_offs, PM_WKDEP);
537
538 return 0;
539}
540
541/**
542 * pwrdm_del_wkdep - remove a wakeup dependency from pwrdm2 to pwrdm1
543 * @pwrdm1: wake this struct powerdomain * up (dependent)
544 * @pwrdm2: when this struct powerdomain * wakes up (source)
545 *
546 * Remove a wakeup dependency that causes pwrdm1 to wake up when pwrdm2
547 * wakes up. Returns -EINVAL if presented with invalid powerdomain
548 * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
549 * 0 upon success.
550 */
551int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
552{
553 struct powerdomain *p;
554
555 if (!pwrdm1)
556 return -EINVAL;
557
558 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
559 if (IS_ERR(p)) {
560 pr_debug("powerdomain: hardware cannot set/clear wake up of "
561 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
562 return PTR_ERR(p);
563 }
564
565 pr_debug("powerdomain: hardware will no longer wake up %s after %s "
566 "wakes up\n", pwrdm1->name, pwrdm2->name);
567
568 prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
569 pwrdm1->prcm_offs, PM_WKDEP);
570
571 return 0;
572}
573
574/**
575 * pwrdm_read_wkdep - read wakeup dependency state from pwrdm2 to pwrdm1
576 * @pwrdm1: wake this struct powerdomain * up (dependent)
577 * @pwrdm2: when this struct powerdomain * wakes up (source)
578 *
579 * Return 1 if a hardware wakeup dependency exists wherein pwrdm1 will be
580 * awoken when pwrdm2 wakes up; 0 if dependency is not set; -EINVAL
581 * if either powerdomain pointer is invalid; or -ENOENT if the hardware
582 * is incapable.
583 *
584 * REVISIT: Currently this function only represents software-controllable
585 * wakeup dependencies. Wakeup dependencies fixed in hardware are not
586 * yet handled here.
587 */
588int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
589{
590 struct powerdomain *p;
591
592 if (!pwrdm1)
593 return -EINVAL;
594
595 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
596 if (IS_ERR(p)) {
597 pr_debug("powerdomain: hardware cannot set/clear wake up of "
598 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
599 return PTR_ERR(p);
600 }
601
602 return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP,
603 (1 << pwrdm2->dep_bit));
604}
605
606/**
607 * pwrdm_add_sleepdep - add a sleep dependency from pwrdm2 to pwrdm1
608 * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
609 * @pwrdm2: when this struct powerdomain * is active (source)
610 *
611 * Prevent pwrdm1 from automatically going inactive (and then to
612 * retention or off) if pwrdm2 is still active. Returns -EINVAL if
613 * presented with invalid powerdomain pointers or called on a machine
614 * that does not support software-configurable hardware sleep dependencies,
615 * -ENOENT if the specified dependency cannot be set in hardware, or
616 * 0 upon success.
617 */
618int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
619{
620 struct powerdomain *p;
621
622 if (!cpu_is_omap34xx())
623 return -EINVAL;
624
625 if (!pwrdm1)
626 return -EINVAL;
627
628 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
629 if (IS_ERR(p)) {
630 pr_debug("powerdomain: hardware cannot set/clear sleep "
631 "dependency affecting %s from %s\n", pwrdm1->name,
632 pwrdm2->name);
633 return PTR_ERR(p);
634 }
635
636 pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n",
637 pwrdm1->name, pwrdm2->name);
638
639 cm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
640 pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
641
642 return 0;
643}
644
645/**
646 * pwrdm_del_sleepdep - remove a sleep dependency from pwrdm2 to pwrdm1
647 * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
648 * @pwrdm2: when this struct powerdomain * is active (source)
649 *
650 * Allow pwrdm1 to automatically go inactive (and then to retention or
651 * off), independent of the activity state of pwrdm2. Returns -EINVAL
652 * if presented with invalid powerdomain pointers or called on a machine
653 * that does not support software-configurable hardware sleep dependencies,
654 * -ENOENT if the specified dependency cannot be cleared in hardware, or
655 * 0 upon success.
656 */
657int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
658{
659 struct powerdomain *p;
660
661 if (!cpu_is_omap34xx())
662 return -EINVAL;
663
664 if (!pwrdm1)
665 return -EINVAL;
666
667 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
668 if (IS_ERR(p)) {
669 pr_debug("powerdomain: hardware cannot set/clear sleep "
670 "dependency affecting %s from %s\n", pwrdm1->name,
671 pwrdm2->name);
672 return PTR_ERR(p);
673 }
674
675 pr_debug("powerdomain: will no longer prevent %s from sleeping if "
676 "%s is active\n", pwrdm1->name, pwrdm2->name);
677
678 cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
679 pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
680
681 return 0;
682}
683
684/**
685 * pwrdm_read_sleepdep - read sleep dependency state from pwrdm2 to pwrdm1
686 * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
687 * @pwrdm2: when this struct powerdomain * is active (source)
688 *
689 * Return 1 if a hardware sleep dependency exists wherein pwrdm1 will
690 * not be allowed to automatically go inactive if pwrdm2 is active;
691 * 0 if pwrdm1's automatic power state inactivity transition is independent
692 * of pwrdm2's; -EINVAL if either powerdomain pointer is invalid or called
693 * on a machine that does not support software-configurable hardware sleep
694 * dependencies; or -ENOENT if the hardware is incapable.
695 *
696 * REVISIT: Currently this function only represents software-controllable
697 * sleep dependencies. Sleep dependencies fixed in hardware are not
698 * yet handled here.
699 */
700int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
701{
702 struct powerdomain *p;
703
704 if (!cpu_is_omap34xx())
705 return -EINVAL;
706
707 if (!pwrdm1)
708 return -EINVAL;
709
710 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
711 if (IS_ERR(p)) {
712 pr_debug("powerdomain: hardware cannot set/clear sleep "
713 "dependency affecting %s from %s\n", pwrdm1->name,
714 pwrdm2->name);
715 return PTR_ERR(p);
716 }
717
718 return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP,
719 (1 << pwrdm2->dep_bit));
720}
721
722/** 467/**
723 * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain 468 * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
724 * @pwrdm: struct powerdomain * 469 * @pwrdm: struct powerdomain *