diff options
author | Nishanth Menon <nm@ti.com> | 2012-02-23 16:30:50 +0800 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2012-06-20 10:27:01 +0800 |
commit | 9b26c994968f22d9e035dda73d8559875fd21d93 (patch) | |
tree | 7bf21d419612d31fa975a914e6a490c3eb4796ba | |
parent | 07390a6eb00c719fed062007eb14427e85d18379 (diff) |
OMAP4: PM: skip going through the LP sleep sequence if conflict with DVFS
Currently we consider Core and MPU dvfs transitions independently.
In the case of core PD:
With frequency dependency on core domain, we have almost all devices
depending to scale core domain frequency scaling. Currently, we restrict
ourselves to checking just core or IVA domain before deciding the domains
should remain ON, instead we should be checking for all devices scaling.
In the case of MPU PD:
If we interrupt dvfs scaling executing on MPU for a different domain(e.g IVA),
we should let it complete rather than go through the motions of programming
and exiting the transition, and leaving the dvfs transition which had started
half done and mpu hitting idle state. In cases such as IVA dvfs, this might
tend to become even fatal as clk configurations need to go through syslink
on A9 when requested from Ducati - So even if A9 is not really busy, Ducati
could be waiting for the action to complete.
Currently we can create all kind of weird cases with DVFS Vs LP
use cases such as MPUSS successfully in OSWR but CORE in ON because
we interrupted SGX dvfs scale or something similar. Instead,
simplify sequencing by denying transition to LP if DVFS was caught
when we dont want to be interrupted.
We do this after clearing the previous states to allow the callers
to detect a failed transition.
Also suspend is prevented if there is an ongoing DVFS.
If we interrupt an device scale operation, it is possible that
we might have caught the operation off-guard such as in the middle
of voltage scale or even frequency change operation. we might be
unable to guarentee that all cross domain dependencies are taken
care as well. Instead, we will abort suspend and priortize device
scale operation and allow the system to re-attempt suspend when
the conditions are right for the operation to proceed.
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com>
-rw-r--r-- | arch/arm/mach-omap2/pm44xx.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 5c69e3bf4ee..6edfe976465 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -40,6 +40,9 @@ #include "prm44xx.h" #include "prm-regbits-44xx.h" #include "cm2_54xx.h" +#include "cm44xx.h" +#include "prm54xx.h" +#include "dvfs.h" static const char * const autoidle_hwmods[] = { "gpio2", @@ -181,6 +184,13 @@ void omap_pm_idle(u32 cpu_id, int state) pwrdm_clear_all_prev_pwrst(per_pwrdm); omap4_device_clear_prev_off_state(); + /* + * Just return if we detect a scenario where we conflict + * with DVFS + */ + if (omap_dvfs_is_any_dev_scaling()) + return; + if (omap4_device_next_state_off()) { /* Save the device context to SAR RAM */ if (omap_sar_save()) @@ -208,6 +218,17 @@ static int omap4_pm_suspend(void) int state, ret = 0, logic_state; u32 cpu_id = smp_processor_id(); + /* + * If any device was in the middle of a scale operation + * then abort, as we cannot predict which part of the scale + * operation we interrupted. + */ + if (omap_dvfs_is_any_dev_scaling()) { + pr_err("%s: oops.. middle of scale op.. aborting suspend\n", + __func__); + return -EBUSY; + } + /* Save current powerdomain state */ list_for_each_entry(pwrst, &pwrst_list, node) { pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm); |