OMAP: PM counter infrastructure.
This patch provides the infrastructure to count how many times a powerdomain entered a given power state (on, inactive, retention, off). A number of functions are provided which will be called by the chip specific powerdomain and clockdomain code whenever a transition might have happened. Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
This commit is contained in:
parent
36d568ec05
commit
ba20bb1269
3 changed files with 108 additions and 2 deletions
|
@ -484,6 +484,8 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
|
||||||
v << __ffs(clkdm->clktrctrl_mask),
|
v << __ffs(clkdm->clktrctrl_mask),
|
||||||
clkdm->pwrdm.ptr->prcm_offs,
|
clkdm->pwrdm.ptr->prcm_offs,
|
||||||
CM_CLKSTCTRL);
|
CM_CLKSTCTRL);
|
||||||
|
|
||||||
|
pwrdm_clkdm_state_switch(clkdm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,6 +35,11 @@
|
||||||
#include <mach/powerdomain.h>
|
#include <mach/powerdomain.h>
|
||||||
#include <mach/clockdomain.h>
|
#include <mach/clockdomain.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PWRDM_STATE_NOW = 0,
|
||||||
|
PWRDM_STATE_PREV,
|
||||||
|
};
|
||||||
|
|
||||||
/* pwrdm_list contains all registered struct powerdomains */
|
/* pwrdm_list contains all registered struct powerdomains */
|
||||||
static LIST_HEAD(pwrdm_list);
|
static LIST_HEAD(pwrdm_list);
|
||||||
|
|
||||||
|
@ -102,6 +107,63 @@ static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
|
||||||
return pd->pwrdm;
|
return pd->pwrdm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
|
||||||
|
{
|
||||||
|
|
||||||
|
int prev;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
if (pwrdm == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
state = pwrdm_read_pwrst(pwrdm);
|
||||||
|
|
||||||
|
switch (flag) {
|
||||||
|
case PWRDM_STATE_NOW:
|
||||||
|
prev = pwrdm->state;
|
||||||
|
break;
|
||||||
|
case PWRDM_STATE_PREV:
|
||||||
|
prev = pwrdm_read_prev_pwrst(pwrdm);
|
||||||
|
if (pwrdm->state != prev)
|
||||||
|
pwrdm->state_counter[prev]++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state != prev)
|
||||||
|
pwrdm->state_counter[state]++;
|
||||||
|
|
||||||
|
pwrdm->state = state;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
pwrdm_clear_all_prev_pwrst(pwrdm);
|
||||||
|
_pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
_pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __init void _pwrdm_setup(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
pwrdm->state_counter[i] = 0;
|
||||||
|
|
||||||
|
pwrdm_wait_transition(pwrdm);
|
||||||
|
pwrdm->state = pwrdm_read_pwrst(pwrdm);
|
||||||
|
pwrdm->state_counter[pwrdm->state] = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Public functions */
|
/* Public functions */
|
||||||
|
|
||||||
|
@ -117,9 +179,12 @@ void pwrdm_init(struct powerdomain **pwrdm_list)
|
||||||
{
|
{
|
||||||
struct powerdomain **p = NULL;
|
struct powerdomain **p = NULL;
|
||||||
|
|
||||||
if (pwrdm_list)
|
if (pwrdm_list) {
|
||||||
for (p = pwrdm_list; *p; p++)
|
for (p = pwrdm_list; *p; p++) {
|
||||||
pwrdm_register(*p);
|
pwrdm_register(*p);
|
||||||
|
_pwrdm_setup(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1110,4 +1175,36 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pwrdm_state_switch(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
|
||||||
|
{
|
||||||
|
if (clkdm != NULL && clkdm->pwrdm.ptr != NULL) {
|
||||||
|
pwrdm_wait_transition(clkdm->pwrdm.ptr);
|
||||||
|
return pwrdm_state_switch(clkdm->pwrdm.ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
int pwrdm_clk_state_switch(struct clk *clk)
|
||||||
|
{
|
||||||
|
if (clk != NULL && clk->clkdm != NULL)
|
||||||
|
return pwrdm_clkdm_state_switch(clk->clkdm);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pwrdm_pre_transition(void)
|
||||||
|
{
|
||||||
|
pwrdm_for_each(_pwrdm_pre_transition_cb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pwrdm_post_transition(void)
|
||||||
|
{
|
||||||
|
pwrdm_for_each(_pwrdm_post_transition_cb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,8 @@ struct powerdomain {
|
||||||
|
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
|
|
||||||
|
int state;
|
||||||
|
unsigned state_counter[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -164,4 +166,9 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
|
||||||
|
|
||||||
int pwrdm_wait_transition(struct powerdomain *pwrdm);
|
int pwrdm_wait_transition(struct powerdomain *pwrdm);
|
||||||
|
|
||||||
|
int pwrdm_state_switch(struct powerdomain *pwrdm);
|
||||||
|
int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
|
||||||
|
int pwrdm_pre_transition(void);
|
||||||
|
int pwrdm_post_transition(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue