aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/arm/mach-omap2/dvfs.c19
-rw-r--r--arch/arm/mach-omap2/voltage.h7
2 files changed, 21 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);
}
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index 34202dc..c454129 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -355,6 +355,13 @@ static inline unsigned long omap_get_dyn_nominal(struct omap_volt_data *vdata)
}
return vdata->volt_nominal;
}
+static inline unsigned long omap_get_nominal_voltage(
+ struct omap_volt_data *vdata)
+{
+ if (IS_ERR_OR_NULL(vdata))
+ return 0;
+ return vdata->volt_nominal;
+}
int omap_voltage_calib_reset(struct voltagedomain *voltdm);