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

Commit e7410cf7 authored by Kevin Hilman's avatar Kevin Hilman
Browse files

OMAP3: PM: move device-specific special cases from PM core into CPUidle



In an effort to simplify the core idle path, move any device-specific
special case handling from the core PM idle path into the CPUidle
pre-idle checking path.

This keeps the core, interrupts-disabled idle path streamlined and
independent of any device-specific handling, and also allows CPUidle
to do the checking only for certain C-states as needed.  This patch
has the device checks in place for all states with the CHECK_BM flag,
namely all states >= C2.

This patch was inspired by a similar patch written by Tero Kristo as
part of a larger series to add INACTIVE state support.

NOTE: This is a baby-step towards decoupling device idle (or system
idle) from CPU idle.  Eventually, CPUidle should only manage the CPU,
and device/system idle should be managed elsewhere.

Cc: Tero Kristo <tero.kristo@nokia.com>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 6cdee912
Loading
Loading
Loading
Loading
+55 −3
Original line number Diff line number Diff line
@@ -60,7 +60,8 @@ struct omap3_processor_cx {

struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
struct omap3_processor_cx current_cx_state;
struct powerdomain *mpu_pd, *core_pd;
struct powerdomain *mpu_pd, *core_pd, *per_pd;
struct powerdomain *cam_pd;

/*
 * The latencies/thresholds for various C states have
@@ -233,14 +234,62 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
			       struct cpuidle_state *state)
{
	struct cpuidle_state *new_state = next_valid_state(dev, state);
	u32 core_next_state, per_next_state = 0, per_saved_state = 0;
	u32 cam_state;
	struct omap3_processor_cx *cx;
	int ret;

	if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) {
		BUG_ON(!dev->safe_state);
		new_state = dev->safe_state;
		goto select_state;
	}

	cx = cpuidle_get_statedata(state);
	core_next_state = cx->core_state;

	/*
	 * FIXME: we currently manage device-specific idle states
	 *        for PER and CORE in combination with CPU-specific
	 *        idle states.  This is wrong, and device-specific
	 *        idle managment needs to be separated out into 
	 *        its own code.
	 */

	/*
	 * Prevent idle completely if CAM is active.
	 * CAM does not have wakeup capability in OMAP3.
	 */
	cam_state = pwrdm_read_pwrst(cam_pd);
	if (cam_state == PWRDM_POWER_ON) {
		new_state = dev->safe_state;
		goto select_state;
	}

	/*
	 * Prevent PER off if CORE is not in retention or off as this
	 * would disable PER wakeups completely.
	 */
	per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
	if ((per_next_state == PWRDM_POWER_OFF) &&
	    (core_next_state > PWRDM_POWER_RET)) {
		per_next_state = PWRDM_POWER_RET;
		pwrdm_set_next_pwrst(per_pd, per_next_state);
	}

	/* Are we changing PER target state? */
	if (per_next_state != per_saved_state)
		pwrdm_set_next_pwrst(per_pd, per_next_state);

select_state:
	dev->last_state = new_state;
	return omap3_enter_idle(dev, new_state);
	ret = omap3_enter_idle(dev, new_state);

	/* Restore original PER state if it was modified */
	if (per_next_state != per_saved_state)
		pwrdm_set_next_pwrst(per_pd, per_saved_state);

	return ret;
}

DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
@@ -328,7 +377,8 @@ void omap_init_power_states(void)
			cpuidle_params_table[OMAP3_STATE_C2].threshold;
	omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
	omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
	omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
	omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
				CPUIDLE_FLAG_CHECK_BM;

	/* C3 . MPU CSWR + Core inactive */
	omap3_power_states[OMAP3_STATE_C3].valid =
@@ -426,6 +476,8 @@ int __init omap3_idle_init(void)

	mpu_pd = pwrdm_lookup("mpu_pwrdm");
	core_pd = pwrdm_lookup("core_pwrdm");
	per_pd = pwrdm_lookup("per_pwrdm");
	cam_pd = pwrdm_lookup("cam_pwrdm");

	omap_init_power_states();
	cpuidle_register_driver(&omap3_idle_driver);
+1 −13
Original line number Diff line number Diff line
@@ -346,7 +346,6 @@ void omap_sram_idle(void)
	int core_next_state = PWRDM_POWER_ON;
	int core_prev_state, per_prev_state;
	u32 sdrc_pwr = 0;
	int per_state_modified = 0;

	if (!_omap_sram_idle)
		return;
@@ -391,18 +390,9 @@ void omap_sram_idle(void)
	if (per_next_state < PWRDM_POWER_ON) {
		omap_uart_prepare_idle(2);
		omap2_gpio_prepare_for_idle(per_next_state);
		if (per_next_state == PWRDM_POWER_OFF) {
			if (core_next_state == PWRDM_POWER_ON) {
				per_next_state = PWRDM_POWER_RET;
				pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
				per_state_modified = 1;
			} else
		if (per_next_state == PWRDM_POWER_OFF)
				omap3_per_save_context();
	}
	}

	if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
		omap2_clkdm_deny_idle(mpu_pwrdm->pwrdm_clkdms[0]);

	/* CORE */
	if (core_next_state < PWRDM_POWER_ON) {
@@ -470,8 +460,6 @@ void omap_sram_idle(void)
		if (per_prev_state == PWRDM_POWER_OFF)
			omap3_per_restore_context();
		omap_uart_resume_idle(2);
		if (per_state_modified)
			pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
	}

	/* Disable IO-PAD and IO-CHAIN wakeup */