diff options
author | Nishanth Menon <nm@ti.com> | 2012-03-23 18:15:35 +0200 |
---|---|---|
committer | Todd Poynor <toddpoynor@google.com> | 2012-05-10 14:24:54 -0700 |
commit | fa09b1c1912ca021e48929038bb8c55885b4d03b (patch) | |
tree | 777704f45d663c8a7ed55570db29749ee7432745 | |
parent | 2e11077e60e147615042b1481213998008d6bb8a (diff) | |
download | kernel_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.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-omap2/ldo.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/voltage.c | 7 |
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 *)¬ify); 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); |