diff options
Diffstat (limited to 'arch/arm/mach-omap2/powerdomain.c')
-rw-r--r-- | arch/arm/mach-omap2/powerdomain.c | 114 |
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 | |||
40 | enum { | ||
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 */ |
39 | static LIST_HEAD(pwrdm_list); | 46 | static 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 | ||
112 | static 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 | |||
146 | static 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 | |||
153 | static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) | ||
154 | { | ||
155 | _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static __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 | */ |
220 | int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) | 289 | int 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 | ||
1183 | int pwrdm_state_switch(struct powerdomain *pwrdm) | ||
1184 | { | ||
1185 | return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW); | ||
1186 | } | ||
1187 | |||
1188 | int 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 | } | ||
1197 | int 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 | |||
1204 | int pwrdm_pre_transition(void) | ||
1205 | { | ||
1206 | pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); | ||
1207 | return 0; | ||
1208 | } | ||
1209 | |||
1210 | int pwrdm_post_transition(void) | ||
1211 | { | ||
1212 | pwrdm_for_each(_pwrdm_post_transition_cb, NULL); | ||
1213 | return 0; | ||
1214 | } | ||
1113 | 1215 | ||