aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/powerdomain.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/powerdomain.c')
-rw-r--r--arch/arm/mach-omap2/powerdomain.c114
1 files changed, 108 insertions, 6 deletions
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 983f1cb676be..2594cbff3947 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -35,6 +35,13 @@
35#include <mach/powerdomain.h> 35#include <mach/powerdomain.h>
36#include <mach/clockdomain.h> 36#include <mach/clockdomain.h>
37 37
38#include "pm.h"
39
40enum {
41 PWRDM_STATE_NOW = 0,
42 PWRDM_STATE_PREV,
43};
44
38/* pwrdm_list contains all registered struct powerdomains */ 45/* pwrdm_list contains all registered struct powerdomains */
39static LIST_HEAD(pwrdm_list); 46static LIST_HEAD(pwrdm_list);
40 47
@@ -83,7 +90,7 @@ static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
83 if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip)) 90 if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip))
84 return ERR_PTR(-EINVAL); 91 return ERR_PTR(-EINVAL);
85 92
86 for (pd = deps; pd; pd++) { 93 for (pd = deps; pd->pwrdm_name; pd++) {
87 94
88 if (!omap_chip_is(pd->omap_chip)) 95 if (!omap_chip_is(pd->omap_chip))
89 continue; 96 continue;
@@ -96,12 +103,71 @@ static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
96 103
97 } 104 }
98 105
99 if (!pd) 106 if (!pd->pwrdm_name)
100 return ERR_PTR(-ENOENT); 107 return ERR_PTR(-ENOENT);
101 108
102 return pd->pwrdm; 109 return pd->pwrdm;
103} 110}
104 111
112static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
113{
114
115 int prev;
116 int state;
117
118 if (pwrdm == NULL)
119 return -EINVAL;
120
121 state = pwrdm_read_pwrst(pwrdm);
122
123 switch (flag) {
124 case PWRDM_STATE_NOW:
125 prev = pwrdm->state;
126 break;
127 case PWRDM_STATE_PREV:
128 prev = pwrdm_read_prev_pwrst(pwrdm);
129 if (pwrdm->state != prev)
130 pwrdm->state_counter[prev]++;
131 break;
132 default:
133 return -EINVAL;
134 }
135
136 if (state != prev)
137 pwrdm->state_counter[state]++;
138
139 pm_dbg_update_time(pwrdm, prev);
140
141 pwrdm->state = state;
142
143 return 0;
144}
145
146static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
147{
148 pwrdm_clear_all_prev_pwrst(pwrdm);
149 _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
150 return 0;
151}
152
153static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
154{
155 _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV);
156 return 0;
157}
158
159static __init void _pwrdm_setup(struct powerdomain *pwrdm)
160{
161 int i;
162
163 for (i = 0; i < 4; i++)
164 pwrdm->state_counter[i] = 0;
165
166 pwrdm_wait_transition(pwrdm);
167 pwrdm->state = pwrdm_read_pwrst(pwrdm);
168 pwrdm->state_counter[pwrdm->state] = 1;
169
170}
105 171
106/* Public functions */ 172/* Public functions */
107 173
@@ -117,9 +183,12 @@ void pwrdm_init(struct powerdomain **pwrdm_list)
117{ 183{
118 struct powerdomain **p = NULL; 184 struct powerdomain **p = NULL;
119 185
120 if (pwrdm_list) 186 if (pwrdm_list) {
121 for (p = pwrdm_list; *p; p++) 187 for (p = pwrdm_list; *p; p++) {
122 pwrdm_register(*p); 188 pwrdm_register(*p);
189 _pwrdm_setup(*p);
190 }
191 }
123} 192}
124 193
125/** 194/**
@@ -217,7 +286,8 @@ struct powerdomain *pwrdm_lookup(const char *name)
217 * anything else to indicate failure; or -EINVAL if the function 286 * anything else to indicate failure; or -EINVAL if the function
218 * pointer is null. 287 * pointer is null.
219 */ 288 */
220int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) 289int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
290 void *user)
221{ 291{
222 struct powerdomain *temp_pwrdm; 292 struct powerdomain *temp_pwrdm;
223 unsigned long flags; 293 unsigned long flags;
@@ -228,7 +298,7 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))
228 298
229 read_lock_irqsave(&pwrdm_rwlock, flags); 299 read_lock_irqsave(&pwrdm_rwlock, flags);
230 list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { 300 list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
231 ret = (*fn)(temp_pwrdm); 301 ret = (*fn)(temp_pwrdm, user);
232 if (ret) 302 if (ret)
233 break; 303 break;
234 } 304 }
@@ -1110,4 +1180,36 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm)
1110 return 0; 1180 return 0;
1111} 1181}
1112 1182
1183int pwrdm_state_switch(struct powerdomain *pwrdm)
1184{
1185 return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
1186}
1187
1188int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
1189{
1190 if (clkdm != NULL && clkdm->pwrdm.ptr != NULL) {
1191 pwrdm_wait_transition(clkdm->pwrdm.ptr);
1192 return pwrdm_state_switch(clkdm->pwrdm.ptr);
1193 }
1194
1195 return -EINVAL;
1196}
1197int pwrdm_clk_state_switch(struct clk *clk)
1198{
1199 if (clk != NULL && clk->clkdm != NULL)
1200 return pwrdm_clkdm_state_switch(clk->clkdm);
1201 return -EINVAL;
1202}
1203
1204int pwrdm_pre_transition(void)
1205{
1206 pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
1207 return 0;
1208}
1209
1210int pwrdm_post_transition(void)
1211{
1212 pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
1213 return 0;
1214}
1113 1215