diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-24 04:43:53 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-24 04:43:53 +0400 |
commit | a5ebba6b54bc8038a38d3eacac3a79bbeaf3ee24 (patch) | |
tree | d36eb26a7efd4e00381bc9f6474ea3ec31340585 /arch/arm/mach-omap2/cpuidle34xx.c | |
parent | e81218f5f0fd219bd75768d845159ba4810bdd48 (diff) | |
parent | 6b21a9ce0402e0c5fd2adfa3d41328fdd8f55a9a (diff) | |
download | linux-a5ebba6b54bc8038a38d3eacac3a79bbeaf3ee24.tar.xz |
Merge tag 'pm' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull arm-soc power management changes from Arnd Bergmann:
"These are various power management related changes, mainly concerning
cpuidle on i.MX and OMAP, as well as a the move of the omap
smartreflex driver to live in the power subsystem."
Fix up conflicts in arch/arm/mach-{imx/mach-imx6q.c,omap2/prm2xxx_3xxx.h}
* tag 'pm' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (37 commits)
ARM: OMAP2+: PM: fix IRQ_NOAUTOEN removal by mis-merge
ARM: OMAP2+: do not allow SmartReflex to be built as a module
ARM: OMAP2: Use hwmod to initialize mmc for 2420
ARM: OMAP3: PM: cpuidle: optimize the clkdm idle latency in C1 state
ARM: OMAP3: PM: cpuidle: optimize the PER latency in C1 state
ARM: OMAP3: PM: cpuidle: default to C1 in next_valid_state
ARM: OMAP3: PM: cleanup cam_pwrdm leftovers
ARM: OMAP3: PM: call pre/post transition per powerdomain
ARM: OMAP2+: powerdomain: allow pre/post transtion to be per pwrdm
ARM: OMAP3: PM: Remove IO Daisychain control from cpuidle
ARM: OMAP3PLUS: hwmod: reconfigure IO Daisychain during hwmod mux
ARM: OMAP3+: PRM: Enable IO wake up
ARM: OMAP4: PRM: Add IO Daisychain support
ARM: OMAP3: PM: Move IO Daisychain function to omap3 prm file
ARM: OMAP3: PM: correct enable/disable of daisy io chain
ARM: OMAP2+: PRM: fix compile for OMAP4-only build
W1: OMAP HDQ1W: use runtime PM
ARM: OMAP2+: HDQ1W: use omap_device
W1: OMAP HDQ1W: use 32-bit register accesses
W1: OMAP HDQ1W: allow driver to be built on all OMAP2+
...
Diffstat (limited to 'arch/arm/mach-omap2/cpuidle34xx.c')
-rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 71 |
1 files changed, 27 insertions, 44 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 31344528eb54..f2a49a48ef59 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -75,20 +75,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = { static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; -static int _cpuidle_allow_idle(struct powerdomain *pwrdm, - struct clockdomain *clkdm) -{ - clkdm_allow_idle(clkdm); - return 0; -} - -static int _cpuidle_deny_idle(struct powerdomain *pwrdm, - struct clockdomain *clkdm) -{ - clkdm_deny_idle(clkdm); - return 0; -} - static int __omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -106,8 +92,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, /* Deny idle for C1 */ if (index == 0) { - pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); - pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); + clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]); + clkdm_deny_idle(core_pd->pwrdm_clkdms[0]); } /* @@ -129,8 +115,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, /* Re-allow idle for C1 */ if (index == 0) { - pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); - pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); + clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]); + clkdm_allow_idle(core_pd->pwrdm_clkdms[0]); } return_sleep_time: @@ -176,7 +162,7 @@ static int next_valid_state(struct cpuidle_device *dev, u32 mpu_deepest_state = PWRDM_POWER_RET; u32 core_deepest_state = PWRDM_POWER_RET; int idx; - int next_index = -1; + int next_index = 0; /* C1 is the default value */ if (enable_off_mode) { mpu_deepest_state = PWRDM_POWER_OFF; @@ -207,12 +193,6 @@ static int next_valid_state(struct cpuidle_device *dev, } } - /* - * C1 is always valid. - * So, no need to check for 'next_index == -1' outside - * this loop. - */ - return next_index; } @@ -226,23 +206,22 @@ static int next_valid_state(struct cpuidle_device *dev, * the device to the specified or a safer state. */ static int omap3_enter_idle_bm(struct cpuidle_device *dev, - struct cpuidle_driver *drv, + struct cpuidle_driver *drv, int index) { int new_state_idx; - u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; + u32 core_next_state, per_next_state = 0, per_saved_state = 0; struct omap3_idle_statedata *cx; int ret; /* - * Prevent idle completely if CAM is active. + * Use only C1 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) { + if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON) new_state_idx = drv->safe_state_index; - goto select_state; - } + else + new_state_idx = next_valid_state(dev, drv, index); /* * FIXME: we currently manage device-specific idle states @@ -252,24 +231,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, * its own code. */ - /* - * Prevent PER off if CORE is not in retention or off as this - * would disable PER wakeups completely. - */ - cx = &omap3_idle_data[index]; + /* Program PER state */ + cx = &omap3_idle_data[new_state_idx]; core_next_state = cx->core_state; 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; + if (new_state_idx == 0) { + /* In C1 do not allow PER state lower than CORE state */ + if (per_next_state < core_next_state) + per_next_state = core_next_state; + } else { + /* + * Prevent PER OFF if CORE is not in RETention or OFF as this + * would disable PER wakeups completely. + */ + if ((per_next_state == PWRDM_POWER_OFF) && + (core_next_state > PWRDM_POWER_RET)) + per_next_state = PWRDM_POWER_RET; + } /* Are we changing PER target state? */ if (per_next_state != per_saved_state) pwrdm_set_next_pwrst(per_pd, per_next_state); - new_state_idx = next_valid_state(dev, drv, index); - -select_state: ret = omap3_enter_idle(dev, drv, new_state_idx); /* Restore original PER state if it was modified */ @@ -286,7 +269,7 @@ struct cpuidle_driver omap3_idle_driver = { .owner = THIS_MODULE, .states = { { - .enter = omap3_enter_idle, + .enter = omap3_enter_idle_bm, .exit_latency = 2 + 2, .target_residency = 5, .flags = CPUIDLE_FLAG_TIME_VALID, |