@@ -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",