Skip to content

Commit

Permalink
Merge branch 'pm-next' of ssh://master.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/khilman/linux-omap-pm into omap-for-linus
  • Loading branch information
Tony Lindgren committed Sep 24, 2010
2 parents 9af2ebb + 0aed043 commit 172c113
Show file tree
Hide file tree
Showing 15 changed files with 696 additions and 230 deletions.
1 change: 1 addition & 0 deletions arch/arm/mach-omap2/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ obj-$(CONFIG_ARCH_OMAP2430) += opp2430_data.o
obj-$(CONFIG_ARCH_OMAP2420) += omap_hwmod_2420_data.o
obj-$(CONFIG_ARCH_OMAP2430) += omap_hwmod_2430_data.o
obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_3xxx_data.o
obj-$(CONFIG_ARCH_OMAP4) += omap_hwmod_44xx_data.o

# EMU peripherals
obj-$(CONFIG_OMAP3_EMU) += emu.o
Expand Down
110 changes: 15 additions & 95 deletions arch/arm/mach-omap2/clockdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,97 +258,6 @@ static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable)

}

/**
* _init_wkdep_usecount - initialize wkdep usecounts to match hardware
* @clkdm: clockdomain to initialize wkdep usecounts
*
* Initialize the wakeup dependency usecount variables for clockdomain @clkdm.
* If a wakeup dependency is present in the hardware, the usecount will be
* set to 1; otherwise, it will be set to 0. Software should clear all
* software wakeup dependencies prior to calling this function if it wishes
* to ensure that all usecounts start at 0. No return value.
*/
static void _init_wkdep_usecount(struct clockdomain *clkdm)
{
u32 v;
struct clkdm_dep *cd;

if (!clkdm->wkdep_srcs)
return;

for (cd = clkdm->wkdep_srcs; cd->clkdm_name; cd++) {
if (!omap_chip_is(cd->omap_chip))
continue;

if (!cd->clkdm && cd->clkdm_name)
cd->clkdm = _clkdm_lookup(cd->clkdm_name);

if (!cd->clkdm) {
WARN(!cd->clkdm, "clockdomain: %s: wkdep clkdm %s not "
"found\n", clkdm->name, cd->clkdm_name);
continue;
}

v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
PM_WKDEP,
(1 << cd->clkdm->dep_bit));

if (v)
pr_debug("clockdomain: %s: wakeup dependency already "
"set to wake up when %s wakes\n",
clkdm->name, cd->clkdm->name);

atomic_set(&cd->wkdep_usecount, (v) ? 1 : 0);
}
}

/**
* _init_sleepdep_usecount - initialize sleepdep usecounts to match hardware
* @clkdm: clockdomain to initialize sleepdep usecounts
*
* Initialize the sleep dependency usecount variables for clockdomain @clkdm.
* If a sleep dependency is present in the hardware, the usecount will be
* set to 1; otherwise, it will be set to 0. Software should clear all
* software sleep dependencies prior to calling this function if it wishes
* to ensure that all usecounts start at 0. No return value.
*/
static void _init_sleepdep_usecount(struct clockdomain *clkdm)
{
u32 v;
struct clkdm_dep *cd;

if (!cpu_is_omap34xx())
return;

if (!clkdm->sleepdep_srcs)
return;

for (cd = clkdm->sleepdep_srcs; cd->clkdm_name; cd++) {
if (!omap_chip_is(cd->omap_chip))
continue;

if (!cd->clkdm && cd->clkdm_name)
cd->clkdm = _clkdm_lookup(cd->clkdm_name);

if (!cd->clkdm) {
WARN(!cd->clkdm, "clockdomain: %s: sleepdep clkdm %s "
"not found\n", clkdm->name, cd->clkdm_name);
continue;
}

v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
OMAP3430_CM_SLEEPDEP,
(1 << cd->clkdm->dep_bit));

if (v)
pr_debug("clockdomain: %s: sleep dependency already "
"set to prevent from idling until %s "
"idles\n", clkdm->name, cd->clkdm->name);

atomic_set(&cd->sleepdep_usecount, (v) ? 1 : 0);
}
};

/* Public functions */

/**
Expand Down Expand Up @@ -379,12 +288,17 @@ void clkdm_init(struct clockdomain **clkdms,
_autodep_lookup(autodep);

/*
* Ensure that the *dep_usecount registers reflect the current
* state of the PRCM.
* Put all clockdomains into software-supervised mode; PM code
* should later enable hardware-supervised mode as appropriate
*/
list_for_each_entry(clkdm, &clkdm_list, node) {
_init_wkdep_usecount(clkdm);
_init_sleepdep_usecount(clkdm);
if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
omap2_clkdm_wakeup(clkdm);
else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
omap2_clkdm_deny_idle(clkdm);

clkdm_clear_all_wkdeps(clkdm);
clkdm_clear_all_sleepdeps(clkdm);
}
}

Expand Down Expand Up @@ -592,6 +506,9 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
if (!omap_chip_is(cd->omap_chip))
continue;

if (!cd->clkdm && cd->clkdm_name)
cd->clkdm = _clkdm_lookup(cd->clkdm_name);

/* PRM accesses are slow, so minimize them */
mask |= 1 << cd->clkdm->dep_bit;
atomic_set(&cd->wkdep_usecount, 0);
Expand Down Expand Up @@ -752,6 +669,9 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
if (!omap_chip_is(cd->omap_chip))
continue;

if (!cd->clkdm && cd->clkdm_name)
cd->clkdm = _clkdm_lookup(cd->clkdm_name);

/* PRM accesses are slow, so minimize them */
mask |= 1 << cd->clkdm->dep_bit;
atomic_set(&cd->sleepdep_usecount, 0);
Expand Down
58 changes: 55 additions & 3 deletions arch/arm/mach-omap2/cpuidle34xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 4 additions & 3 deletions arch/arm/mach-omap2/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
omap2430_hwmod_init();
else if (cpu_is_omap34xx())
omap3xxx_hwmod_init();
else if (cpu_is_omap44xx())
omap44xx_hwmod_init();

/* The OPP tables have to be registered before a clk init */
omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);

Expand All @@ -342,9 +345,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
#ifndef CONFIG_PM_RUNTIME
skip_setup_idle = 1;
#endif
if (cpu_is_omap24xx() || cpu_is_omap34xx()) /* FIXME: OMAP4 */
omap_hwmod_late_init(skip_setup_idle);

omap_hwmod_late_init(skip_setup_idle);
if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
_omap2_init_reprogram_sdrc();
Expand Down
Loading

0 comments on commit 172c113

Please sign in to comment.