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.c69
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
35enum { 40enum {
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)
130static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) 135static 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 */
974bool 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}