aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/dvfs.c
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2012-03-09 17:24:52 -0600
committerTodd Poynor <toddpoynor@google.com>2012-05-10 14:24:28 -0700
commit4d26f9303c4b4243e2dccc1ac8e0fba219d716d4 (patch)
treebd4a3ff300bef4e90cf4527cba86f80fbf3cc721 /arch/arm/mach-omap2/dvfs.c
parent2590ab9bbb3ce030daff208d6c8f0e196ac5c9d5 (diff)
downloadkernel_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.c19
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);
}