From: Jia-Wei Chang <jia-wei.chang@xxxxxxxxxxxx> - Remove VOLT_TOL because CCI may share the same sram and vproc regulators with CPU. Therefore, set the max voltage in regulator_set_voltage() to the proc{sram}_max_volt. - Move comparison of new and old voltages to mtk_cpufreq_voltage_tracking(). Signed-off-by: Jia-Wei Chang <jia-wei.chang@xxxxxxxxxxxx> --- drivers/cpufreq/mediatek-cpufreq.c | 130 ++++++++--------------------- 1 file changed, 34 insertions(+), 96 deletions(-) diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index 8f688d47e64b..e69b16a6541e 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -8,6 +8,7 @@ #include <linux/cpu.h> #include <linux/cpufreq.h> #include <linux/cpumask.h> +#include <linux/minmax.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> @@ -15,8 +16,6 @@ #include <linux/pm_opp.h> #include <linux/regulator/consumer.h> -#define VOLT_TOL (10000) - struct mtk_cpufreq_platform_data { int min_volt_shift; int max_volt_shift; @@ -93,91 +92,44 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc); return old_vproc; } - /* Vsram should not exceed the maximum allowed voltage of SoC. */ - new_vsram = min(new_vproc + soc_data->min_volt_shift, - soc_data->sram_max_volt); - - if (old_vproc < new_vproc) { - /* - * When scaling up voltages, Vsram and Vproc scale up step - * by step. At each step, set Vsram to (Vproc + 200mV) first, - * then set Vproc to (Vsram - 100mV). - * Keep doing it until Vsram and Vproc hit target voltages. - */ - do { - old_vsram = regulator_get_voltage(sram_reg); - if (old_vsram < 0) { - pr_err("%s: invalid Vsram value: %d\n", - __func__, old_vsram); - return old_vsram; - } - old_vproc = regulator_get_voltage(proc_reg); - if (old_vproc < 0) { - pr_err("%s: invalid Vproc value: %d\n", - __func__, old_vproc); - return old_vproc; - } - vsram = min(new_vsram, - old_vproc + soc_data->min_volt_shift); - - if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { - vsram = soc_data->sram_max_volt; + old_vsram = regulator_get_voltage(sram_reg); + if (old_vsram < 0) { + pr_err("%s: invalid Vsram value: %d\n", __func__, old_vsram); + return old_vsram; + } - /* - * If the target Vsram hits the maximum voltage, - * try to set the exact voltage value first. - */ - ret = regulator_set_voltage(sram_reg, vsram, - vsram); - if (ret) - ret = regulator_set_voltage(sram_reg, - vsram - VOLT_TOL, - vsram); + new_vsram = clamp(new_vproc + soc_data->min_volt_shift, + soc_data->sram_min_volt, soc_data->sram_max_volt); - vproc = new_vproc; - } else { - ret = regulator_set_voltage(sram_reg, vsram, - vsram + VOLT_TOL); + do { + if (old_vproc <= new_vproc) { + vsram = clamp(old_vproc + soc_data->max_volt_shift, + soc_data->sram_min_volt, new_vsram); + ret = regulator_set_voltage(sram_reg, vsram, + soc_data->sram_max_volt); - vproc = vsram - soc_data->min_volt_shift; - } if (ret) return ret; + if (vsram == soc_data->sram_max_volt || + new_vsram == soc_data->sram_min_volt) + vproc = new_vproc; + else + vproc = vsram - soc_data->min_volt_shift; + ret = regulator_set_voltage(proc_reg, vproc, - vproc + VOLT_TOL); + soc_data->proc_max_volt); if (ret) { regulator_set_voltage(sram_reg, old_vsram, - old_vsram); + soc_data->sram_max_volt); return ret; } - } while (vproc < new_vproc || vsram < new_vsram); - } else if (old_vproc > new_vproc) { - /* - * When scaling down voltages, Vsram and Vproc scale down step - * by step. At each step, set Vproc to (Vsram - 200mV) first, - * then set Vproc to (Vproc + 100mV). - * Keep doing it until Vsram and Vproc hit target voltages. - */ - do { - old_vproc = regulator_get_voltage(proc_reg); - if (old_vproc < 0) { - pr_err("%s: invalid Vproc value: %d\n", - __func__, old_vproc); - return old_vproc; - } - old_vsram = regulator_get_voltage(sram_reg); - if (old_vsram < 0) { - pr_err("%s: invalid Vsram value: %d\n", - __func__, old_vsram); - return old_vsram; - } - + } else if (old_vproc > new_vproc) { vproc = max(new_vproc, old_vsram - soc_data->max_volt_shift); ret = regulator_set_voltage(proc_reg, vproc, - vproc + VOLT_TOL); + soc_data->proc_max_volt); if (ret) return ret; @@ -187,32 +139,18 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, vsram = max(new_vsram, vproc + soc_data->min_volt_shift); - if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { - vsram = soc_data->sram_max_volt; - - /* - * If the target Vsram hits the maximum voltage, - * try to set the exact voltage value first. - */ - ret = regulator_set_voltage(sram_reg, vsram, - vsram); - if (ret) - ret = regulator_set_voltage(sram_reg, - vsram - VOLT_TOL, - vsram); - } else { - ret = regulator_set_voltage(sram_reg, vsram, - vsram + VOLT_TOL); - } - + ret = regulator_set_voltage(sram_reg, vsram, + soc_data->sram_max_volt); if (ret) { regulator_set_voltage(proc_reg, old_vproc, - old_vproc); + soc_data->proc_max_volt); return ret; } - } while (vproc > new_vproc + VOLT_TOL || - vsram > new_vsram + VOLT_TOL); - } + } + + old_vproc = vproc; + old_vsram = vsram; + } while (vproc != new_vproc || vsram != new_vsram); return 0; } @@ -272,8 +210,8 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, * If the new voltage or the intermediate voltage is higher than the * current voltage, scale up voltage first. */ - target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc; - if (old_vproc < target_vproc) { + target_vproc = max(inter_vproc, vproc); + if (old_vproc <= target_vproc) { ret = mtk_cpufreq_set_voltage(info, target_vproc); if (ret) { pr_err("cpu%d: failed to scale up voltage!\n", -- 2.18.0