aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2012-03-23 18:15:35 +0200
committerTodd Poynor <toddpoynor@google.com>2012-05-10 14:24:54 -0700
commitfa09b1c1912ca021e48929038bb8c55885b4d03b (patch)
tree777704f45d663c8a7ed55570db29749ee7432745
parent2e11077e60e147615042b1481213998008d6bb8a (diff)
downloadkernel_samsung_tuna-fa09b1c1912ca021e48929038bb8c55885b4d03b.zip
kernel_samsung_tuna-fa09b1c1912ca021e48929038bb8c55885b4d03b.tar.gz
kernel_samsung_tuna-fa09b1c1912ca021e48929038bb8c55885b4d03b.tar.bz2
OMAP3+: LDO: ensure that right ABB type is selected
since target_volt converted by omap_voltage_get_voltdata to get to abb type for the OPP voltage level, we can have a scenario as follows: OPP100 Vnom=1.2V, Vcalib = 0V(not calibrated) ABB type - bypass OPPNitro Vnom=1.375, Vcalib = 1.2V ABB type = FBB in this case, voltdm_scale will first gets the operational_voltage of oppNitro and recieves 1.2V, sends it down to abb_prescale function which in turn converts it back into vdata using omap_voltage_get_voltdata however, omap_voltage_get_voltdata walks through the volt_data array and finds the first match of OPP100 where Vnom = 1.2V and returns the volt_data pointer for OPP100, this causes ABB logic to think that it is attempting to go to an OPP with bypass, which in effect crashes the device once frequency is set to OPPNitro, but ABB is in bypass mode. To solve this, we should pass the exact volt_data pointer down to the abb prescale and postscale handlers so that this back and forth conversion error does not take place. Change-Id: I49099caba069798d7bd8888c614fd5e2e27fab6f Signed-off-by: Nishanth Menon <nm@ti.com> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
-rw-r--r--arch/arm/mach-omap2/ldo.c23
-rw-r--r--arch/arm/mach-omap2/ldo.h4
-rw-r--r--arch/arm/mach-omap2/voltage.c7
3 files changed, 15 insertions, 19 deletions
diff --git a/arch/arm/mach-omap2/ldo.c b/arch/arm/mach-omap2/ldo.c
index e5f3ae9..13ee2a3 100644
--- a/arch/arm/mach-omap2/ldo.c
+++ b/arch/arm/mach-omap2/ldo.c
@@ -160,15 +160,12 @@ static int _abb_set_abb(struct voltagedomain *voltdm, int abb_type)
* of LDO functions
*/
static int _abb_scale(struct voltagedomain *voltdm,
- unsigned long target_volt, bool is_prescale)
+ struct omap_volt_data *target_vdata, bool is_prescale)
{
int ret = 0;
- struct omap_volt_data *target_vdata;
int curr_abb, target_abb;
struct omap_ldo_abb_instance *abb;
- /* get per-voltage ABB data */
- target_vdata = omap_voltage_get_voltdata(voltdm, target_volt);
if (IS_ERR_OR_NULL(target_vdata)) {
pr_err("%s:%s: Invalid volt data tv=%p!\n", __func__,
voltdm->name, target_vdata);
@@ -185,8 +182,8 @@ static int _abb_scale(struct voltagedomain *voltdm,
target_abb = target_vdata->abb_type;
pr_debug("%s: %s: Enter: t_v=%ld scale=%d c_abb=%d t_abb=%d ret=%d\n",
- __func__, voltdm->name, target_volt, is_prescale, curr_abb,
- target_abb, ret);
+ __func__, voltdm->name, omap_get_nominal_voltage(target_vdata),
+ is_prescale, curr_abb, target_abb, ret);
/* If we were'nt booting and there is no change, we get out */
if (target_abb == curr_abb && voltdm->curr_volt)
@@ -224,8 +221,8 @@ static int _abb_scale(struct voltagedomain *voltdm,
out:
pr_debug("%s: %s:Exit: t_v=%ld scale=%d c_abb=%d t_abb=%d ret=%d\n",
- __func__, voltdm->name, target_volt, is_prescale, curr_abb,
- target_abb, ret);
+ __func__, voltdm->name, omap_get_nominal_voltage(target_vdata),
+ is_prescale, curr_abb, target_abb, ret);
return ret;
}
@@ -233,12 +230,12 @@ out:
/**
* omap_ldo_abb_pre_scale() - Enable required ABB strategy before voltage scale
* @voltdm: voltage domain to operate on
- * @target_volt: target voltage we moved to.
+ * @target_volt: target voltage data we moved to.
*/
int omap_ldo_abb_pre_scale(struct voltagedomain *voltdm,
- unsigned long target_volt)
+ struct omap_volt_data *target_vdata)
{
- return _abb_scale(voltdm, target_volt, true);
+ return _abb_scale(voltdm, target_vdata, true);
}
/**
@@ -247,9 +244,9 @@ int omap_ldo_abb_pre_scale(struct voltagedomain *voltdm,
* @target_volt: target voltage we are going to
*/
int omap_ldo_abb_post_scale(struct voltagedomain *voltdm,
- unsigned long target_volt)
+ struct omap_volt_data *target_vdata)
{
- return _abb_scale(voltdm, target_volt, false);
+ return _abb_scale(voltdm, target_vdata, false);
}
/**
diff --git a/arch/arm/mach-omap2/ldo.h b/arch/arm/mach-omap2/ldo.h
index 0671b7e..44e66f4 100644
--- a/arch/arm/mach-omap2/ldo.h
+++ b/arch/arm/mach-omap2/ldo.h
@@ -105,9 +105,9 @@ extern struct omap_ldo_abb_instance omap4_ldo_abb_mpu_instance;
extern struct omap_ldo_abb_instance omap4_ldo_abb_iva_instance;
extern int omap_ldo_abb_pre_scale(struct voltagedomain *voltdm,
- unsigned long target_volt);
+ struct omap_volt_data *target_vdata);
extern int omap_ldo_abb_post_scale(struct voltagedomain *voltdm,
- unsigned long target_volt);
+ struct omap_volt_data *target_vdata);
extern void __init omap_ldo_abb_init(struct voltagedomain *voltdm);
#endif /* __ARCH_ARM_MACH_OMAP2_LDO_H */
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index bcc7593..78ed3ca 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -137,7 +137,7 @@ int voltdm_scale(struct voltagedomain *voltdm,
(void *)&notify);
if (voltdm->abb) {
- ret = omap_ldo_abb_pre_scale(voltdm, target_volt);
+ ret = omap_ldo_abb_pre_scale(voltdm, target_v);
if (ret)
pr_err("%s: ABB prescale failed for vdd%s: %d\n",
__func__, voltdm->name, ret);
@@ -151,9 +151,8 @@ int voltdm_scale(struct voltagedomain *voltdm,
__func__, voltdm->name, ret);
if (voltdm->abb) {
- unsigned long cv;
- cv = omap_get_operation_voltage(voltdm->curr_volt);
- ret = omap_ldo_abb_post_scale(voltdm, cv);
+ ret = omap_ldo_abb_post_scale(voltdm,
+ voltdm->curr_volt);
if (ret)
pr_err("%s: ABB postscale fail for vdd%s:%d\n",
__func__, voltdm->name, ret);