Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba20bb12 authored by Peter 'p2' De Schrijver's avatar Peter 'p2' De Schrijver Committed by Kevin Hilman
Browse files

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: default avatarPeter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 36d568ec
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -484,6 +484,8 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
			    v << __ffs(clkdm->clktrctrl_mask),
			    clkdm->pwrdm.ptr->prcm_offs,
			    CM_CLKSTCTRL);

	pwrdm_clkdm_state_switch(clkdm);
}

/**
+99 −2
Original line number Diff line number Diff line
@@ -35,6 +35,11 @@
#include <mach/powerdomain.h>
#include <mach/clockdomain.h>

enum {
	PWRDM_STATE_NOW = 0,
	PWRDM_STATE_PREV,
};

/* pwrdm_list contains all registered struct powerdomains */
static LIST_HEAD(pwrdm_list);

@@ -102,6 +107,63 @@ static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *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 */

@@ -117,9 +179,12 @@ void pwrdm_init(struct powerdomain **pwrdm_list)
{
	struct powerdomain **p = NULL;

	if (pwrdm_list)
		for (p = pwrdm_list; *p; p++)
	if (pwrdm_list) {
		for (p = pwrdm_list; *p; p++) {
			pwrdm_register(*p);
			_pwrdm_setup(*p);
		}
	}
}

/**
@@ -1110,4 +1175,36 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm)
	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;
}
+7 −0
Original line number Diff line number Diff line
@@ -117,6 +117,8 @@ struct powerdomain {

	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_state_switch(struct powerdomain *pwrdm);
int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
int pwrdm_pre_transition(void);
int pwrdm_post_transition(void);

#endif