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.c110
1 files changed, 85 insertions, 25 deletions
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index ef71fdd40fc4..5164d587ef52 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * OMAP powerdomain control 2 * OMAP powerdomain control
3 * 3 *
4 * Copyright (C) 2007-2008 Texas Instruments, Inc. 4 * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
5 * Copyright (C) 2007-2011 Nokia Corporation 5 * Copyright (C) 2007-2011 Nokia Corporation
6 * 6 *
7 * Written by Paul Walmsley 7 * Written by Paul Walmsley
@@ -77,13 +77,11 @@ static struct powerdomain *_pwrdm_lookup(const char *name)
77static int _pwrdm_register(struct powerdomain *pwrdm) 77static int _pwrdm_register(struct powerdomain *pwrdm)
78{ 78{
79 int i; 79 int i;
80 struct voltagedomain *voltdm;
80 81
81 if (!pwrdm || !pwrdm->name) 82 if (!pwrdm || !pwrdm->name)
82 return -EINVAL; 83 return -EINVAL;
83 84
84 if (!omap_chip_is(pwrdm->omap_chip))
85 return -EINVAL;
86
87 if (cpu_is_omap44xx() && 85 if (cpu_is_omap44xx() &&
88 pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) { 86 pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) {
89 pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n", 87 pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n",
@@ -94,6 +92,16 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
94 if (_pwrdm_lookup(pwrdm->name)) 92 if (_pwrdm_lookup(pwrdm->name))
95 return -EEXIST; 93 return -EEXIST;
96 94
95 voltdm = voltdm_lookup(pwrdm->voltdm.name);
96 if (!voltdm) {
97 pr_err("powerdomain: %s: voltagedomain %s does not exist\n",
98 pwrdm->name, pwrdm->voltdm.name);
99 return -EINVAL;
100 }
101 pwrdm->voltdm.ptr = voltdm;
102 INIT_LIST_HEAD(&pwrdm->voltdm_node);
103 voltdm_add_pwrdm(voltdm, pwrdm);
104
97 list_add(&pwrdm->node, &pwrdm_list); 105 list_add(&pwrdm->node, &pwrdm_list);
98 106
99 /* Initialize the powerdomain's state counter */ 107 /* Initialize the powerdomain's state counter */
@@ -194,36 +202,76 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
194/* Public functions */ 202/* Public functions */
195 203
196/** 204/**
197 * pwrdm_init - set up the powerdomain layer 205 * pwrdm_register_platform_funcs - register powerdomain implementation fns
198 * @pwrdms: array of struct powerdomain pointers to register 206 * @po: func pointers for arch specific implementations
199 * @custom_funcs: func pointers for arch specific implementations
200 * 207 *
201 * Loop through the array of powerdomains @pwrdms, registering all 208 * Register the list of function pointers used to implement the
202 * that are available on the current CPU. Also, program all 209 * powerdomain functions on different OMAP SoCs. Should be called
203 * powerdomain target state as ON; this is to prevent domains from 210 * before any other pwrdm_register*() function. Returns -EINVAL if
204 * hitting low power states (if bootloader has target states set to 211 * @po is null, -EEXIST if platform functions have already been
205 * something other than ON) and potentially even losing context while 212 * registered, or 0 upon success.
206 * PM is not fully initialized. The PM late init code can then program
207 * the desired target state for all the power domains. No return
208 * value.
209 */ 213 */
210void pwrdm_init(struct powerdomain **pwrdms, struct pwrdm_ops *custom_funcs) 214int pwrdm_register_platform_funcs(struct pwrdm_ops *po)
215{
216 if (!po)
217 return -EINVAL;
218
219 if (arch_pwrdm)
220 return -EEXIST;
221
222 arch_pwrdm = po;
223
224 return 0;
225}
226
227/**
228 * pwrdm_register_pwrdms - register SoC powerdomains
229 * @ps: pointer to an array of struct powerdomain to register
230 *
231 * Register the powerdomains available on a particular OMAP SoC. Must
232 * be called after pwrdm_register_platform_funcs(). May be called
233 * multiple times. Returns -EACCES if called before
234 * pwrdm_register_platform_funcs(); -EINVAL if the argument @ps is
235 * null; or 0 upon success.
236 */
237int pwrdm_register_pwrdms(struct powerdomain **ps)
211{ 238{
212 struct powerdomain **p = NULL; 239 struct powerdomain **p = NULL;
213 struct powerdomain *temp_p;
214 240
215 if (!custom_funcs) 241 if (!arch_pwrdm)
216 WARN(1, "powerdomain: No custom pwrdm functions registered\n"); 242 return -EEXIST;
217 else
218 arch_pwrdm = custom_funcs;
219 243
220 if (pwrdms) { 244 if (!ps)
221 for (p = pwrdms; *p; p++) 245 return -EINVAL;
222 _pwrdm_register(*p); 246
223 } 247 for (p = ps; *p; p++)
248 _pwrdm_register(*p);
249
250 return 0;
251}
252
253/**
254 * pwrdm_complete_init - set up the powerdomain layer
255 *
256 * Do whatever is necessary to initialize registered powerdomains and
257 * powerdomain code. Currently, this programs the next power state
258 * for each powerdomain to ON. This prevents powerdomains from
259 * unexpectedly losing context or entering high wakeup latency modes
260 * with non-power-management-enabled kernels. Must be called after
261 * pwrdm_register_pwrdms(). Returns -EACCES if called before
262 * pwrdm_register_pwrdms(), or 0 upon success.
263 */
264int pwrdm_complete_init(void)
265{
266 struct powerdomain *temp_p;
267
268 if (list_empty(&pwrdm_list))
269 return -EACCES;
224 270
225 list_for_each_entry(temp_p, &pwrdm_list, node) 271 list_for_each_entry(temp_p, &pwrdm_list, node)
226 pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON); 272 pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
273
274 return 0;
227} 275}
228 276
229/** 277/**
@@ -390,6 +438,18 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
390} 438}
391 439
392/** 440/**
441 * pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in
442 * @pwrdm: struct powerdomain *
443 *
444 * Return a pointer to the struct voltageomain that the specified powerdomain
445 * @pwrdm exists in.
446 */
447struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm)
448{
449 return pwrdm->voltdm.ptr;
450}
451
452/**
393 * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain 453 * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
394 * @pwrdm: struct powerdomain * 454 * @pwrdm: struct powerdomain *
395 * 455 *