diff options
author | Nishanth Menon <nm@ti.com> | 2012-03-09 17:24:52 -0600 |
---|---|---|
committer | Todd Poynor <toddpoynor@google.com> | 2012-05-10 14:24:28 -0700 |
commit | 4d26f9303c4b4243e2dccc1ac8e0fba219d716d4 (patch) | |
tree | bd4a3ff300bef4e90cf4527cba86f80fbf3cc721 /arch/arm/mach-omap2/dvfs.c | |
parent | 2590ab9bbb3ce030daff208d6c8f0e196ac5c9d5 (diff) | |
download | kernel_samsung_tuna-4d26f9303c4b4243e2dccc1ac8e0fba219d716d4.zip kernel_samsung_tuna-4d26f9303c4b4243e2dccc1ac8e0fba219d716d4.tar.gz kernel_samsung_tuna-4d26f9303c4b4243e2dccc1ac8e0fba219d716d4.tar.bz2 |
OMAP3+: PM: DVFS: decide to scale dependent domains based on nominal voltage
Current DVFS scale decision assumes voltage dependency - hence the scale
decision is implemented based on voltage transition decision. This is
wrong as the dependency between domains is at OPP tuple level, so
no matter what the voltage level is, if we transition from a lower
frequency to a higher frequency, we should scale dependent domain
ahead of transitioning voltage/frequency for the current domain,
and viceversa when switching to lower OPP.
With Smartreflex AVS Class3 or Smartreflex AVS Class1.5, consider
the following Scenario:
The current OPP might be in
Vnom (Vn) - if SR is disabled OR if SR has not yet made the first
adjustment
Vcurrent(Vc) - which can either be:
Vsr_intermdiate(Vi) - if SR was interrupted in the middle
of convergence
Vsr(Vs) - if SR has completed adjustment.
For all purposes Current OPP's Vn > Vc.
However, when we consider the new OPP we are entering (assume for
SR1.5, new OPP is not a calibrated opp in this discussion):
Going down, we have the following cases:
Case a) current_Vn > current_Vc > new_Vn
Case b) current_Vn > new_Vn > current_Vc
Going up, we could have:
Case c) new_Vn > current_Vn > current_Vc
OR we might even have a scenario
case d) current_Vn > (current_Vc == new_Vn)
Today's code compares current_Vc against new_Vn, and makes a decision
when to scale dependent domain. This will work find in case (a) and
case (c).
However, in case (b), we scale dependent domain at the wrong time,
in case of case (d), we dont even attempt to scale dependent domains!!
This is wrong. since the comparable factor which closely represents
the order of OPP is Vnom, the right thing to check for scaling dependent
domains is Vnom. Hence use it instead.
Change-Id: I93868743301e115fab8e33ff14317b07b81ef5d8
Signed-off-by: Nishanth Menon <nm@ti.com>
Diffstat (limited to 'arch/arm/mach-omap2/dvfs.c')
-rw-r--r-- | arch/arm/mach-omap2/dvfs.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/arch/arm/mach-omap2/dvfs.c b/arch/arm/mach-omap2/dvfs.c index 0101a9e..afd6fa1 100644 --- a/arch/arm/mach-omap2/dvfs.c +++ b/arch/arm/mach-omap2/dvfs.c @@ -765,10 +765,9 @@ static int _dvfs_scale(struct device *req_dev, struct device *target_dev, if (!curr_volt) curr_volt = omap_get_operation_voltage(curr_vdata); - if (curr_volt == new_volt) { - volt_scale_dir = DVFS_VOLT_SCALE_NONE; - } else if (curr_volt < new_volt) { - + /* Make a decision to scale dependent domain based on nominal voltage */ + if (omap_get_nominal_voltage(new_vdata) > + omap_get_nominal_voltage(curr_vdata)) { ret = _dep_scale_domains(target_dev, vdd); if (ret) { dev_err(target_dev, @@ -776,7 +775,13 @@ static int _dvfs_scale(struct device *req_dev, struct device *target_dev, __func__, ret, new_volt); goto fail; } + } + /* Now decide on switching OPP */ + + if (curr_volt == new_volt) { + volt_scale_dir = DVFS_VOLT_SCALE_NONE; + } else if (curr_volt < new_volt) { ret = voltdm_scale(voltdm, new_vdata); if (ret) { dev_err(target_dev, @@ -833,8 +838,12 @@ static int _dvfs_scale(struct device *req_dev, struct device *target_dev, if (ret) goto fail; - if (DVFS_VOLT_SCALE_DOWN == volt_scale_dir) { + if (DVFS_VOLT_SCALE_DOWN == volt_scale_dir) voltdm_scale(voltdm, new_vdata); + + /* Make a decision to scale dependent domain based on nominal voltage */ + if (omap_get_nominal_voltage(new_vdata) < + omap_get_nominal_voltage(curr_vdata)) { _dep_scale_domains(target_dev, vdd); } |