diff options
Diffstat (limited to 'arch/arm/mach-omap2/powerdomain.c')
-rw-r--r-- | arch/arm/mach-omap2/powerdomain.c | 69 |
1 files changed, 65 insertions, 4 deletions
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index eaed0df16699..49c6513e90d8 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-2009 Nokia Corporation | 5 | * Copyright (C) 2007-2011 Nokia Corporation |
6 | * | 6 | * |
7 | * Written by Paul Walmsley | 7 | * Written by Paul Walmsley |
8 | * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com> | 8 | * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com> |
@@ -19,12 +19,15 @@ | |||
19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
20 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <trace/events/power.h> | ||
23 | |||
22 | #include "cm2xxx_3xxx.h" | 24 | #include "cm2xxx_3xxx.h" |
23 | #include "prcm44xx.h" | 25 | #include "prcm44xx.h" |
24 | #include "cm44xx.h" | 26 | #include "cm44xx.h" |
25 | #include "prm2xxx_3xxx.h" | 27 | #include "prm2xxx_3xxx.h" |
26 | #include "prm44xx.h" | 28 | #include "prm44xx.h" |
27 | 29 | ||
30 | #include <asm/cpu.h> | ||
28 | #include <plat/cpu.h> | 31 | #include <plat/cpu.h> |
29 | #include "powerdomain.h" | 32 | #include "powerdomain.h" |
30 | #include "clockdomain.h" | 33 | #include "clockdomain.h" |
@@ -32,6 +35,8 @@ | |||
32 | 35 | ||
33 | #include "pm.h" | 36 | #include "pm.h" |
34 | 37 | ||
38 | #define PWRDM_TRACE_STATES_FLAG (1<<31) | ||
39 | |||
35 | enum { | 40 | enum { |
36 | PWRDM_STATE_NOW = 0, | 41 | PWRDM_STATE_NOW = 0, |
37 | PWRDM_STATE_PREV, | 42 | PWRDM_STATE_PREV, |
@@ -130,8 +135,7 @@ static void _update_logic_membank_counters(struct powerdomain *pwrdm) | |||
130 | static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) | 135 | static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) |
131 | { | 136 | { |
132 | 137 | ||
133 | int prev; | 138 | int prev, state, trace_state = 0; |
134 | int state; | ||
135 | 139 | ||
136 | if (pwrdm == NULL) | 140 | if (pwrdm == NULL) |
137 | return -EINVAL; | 141 | return -EINVAL; |
@@ -148,6 +152,17 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) | |||
148 | pwrdm->state_counter[prev]++; | 152 | pwrdm->state_counter[prev]++; |
149 | if (prev == PWRDM_POWER_RET) | 153 | if (prev == PWRDM_POWER_RET) |
150 | _update_logic_membank_counters(pwrdm); | 154 | _update_logic_membank_counters(pwrdm); |
155 | /* | ||
156 | * If the power domain did not hit the desired state, | ||
157 | * generate a trace event with both the desired and hit states | ||
158 | */ | ||
159 | if (state != prev) { | ||
160 | trace_state = (PWRDM_TRACE_STATES_FLAG | | ||
161 | ((state & OMAP_POWERSTATE_MASK) << 8) | | ||
162 | ((prev & OMAP_POWERSTATE_MASK) << 0)); | ||
163 | trace_power_domain_target(pwrdm->name, trace_state, | ||
164 | smp_processor_id()); | ||
165 | } | ||
151 | break; | 166 | break; |
152 | default: | 167 | default: |
153 | return -EINVAL; | 168 | return -EINVAL; |
@@ -406,8 +421,13 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | |||
406 | pr_debug("powerdomain: setting next powerstate for %s to %0x\n", | 421 | pr_debug("powerdomain: setting next powerstate for %s to %0x\n", |
407 | pwrdm->name, pwrst); | 422 | pwrdm->name, pwrst); |
408 | 423 | ||
409 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) | 424 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) { |
425 | /* Trace the pwrdm desired target state */ | ||
426 | trace_power_domain_target(pwrdm->name, pwrst, | ||
427 | smp_processor_id()); | ||
428 | /* Program the pwrdm desired target state */ | ||
410 | ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst); | 429 | ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst); |
430 | } | ||
411 | 431 | ||
412 | return ret; | 432 | return ret; |
413 | } | 433 | } |
@@ -938,3 +958,44 @@ u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm) | |||
938 | 958 | ||
939 | return count; | 959 | return count; |
940 | } | 960 | } |
961 | |||
962 | /** | ||
963 | * pwrdm_can_ever_lose_context - can this powerdomain ever lose context? | ||
964 | * @pwrdm: struct powerdomain * | ||
965 | * | ||
966 | * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain | ||
967 | * can lose either memory or logic context or if @pwrdm is invalid, or | ||
968 | * returns 0 otherwise. This function is not concerned with how the | ||
969 | * powerdomain registers are programmed (i.e., to go off or not); it's | ||
970 | * concerned with whether it's ever possible for this powerdomain to | ||
971 | * go off while some other part of the chip is active. This function | ||
972 | * assumes that every powerdomain can go to either ON or INACTIVE. | ||
973 | */ | ||
974 | bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm) | ||
975 | { | ||
976 | int i; | ||
977 | |||
978 | if (IS_ERR_OR_NULL(pwrdm)) { | ||
979 | pr_debug("powerdomain: %s: invalid powerdomain pointer\n", | ||
980 | __func__); | ||
981 | return 1; | ||
982 | } | ||
983 | |||
984 | if (pwrdm->pwrsts & PWRSTS_OFF) | ||
985 | return 1; | ||
986 | |||
987 | if (pwrdm->pwrsts & PWRSTS_RET) { | ||
988 | if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF) | ||
989 | return 1; | ||
990 | |||
991 | for (i = 0; i < pwrdm->banks; i++) | ||
992 | if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF) | ||
993 | return 1; | ||
994 | } | ||
995 | |||
996 | for (i = 0; i < pwrdm->banks; i++) | ||
997 | if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF) | ||
998 | return 1; | ||
999 | |||
1000 | return 0; | ||
1001 | } | ||