@@ -48,8 +48,11 @@ struct mtk_cpu_dvfs_info {
struct clk *cpu_clk;
struct clk *inter_clk;
struct thermal_cooling_device *cdev;
+ struct mutex lock;
+ struct notifier_block opp_nb;
struct list_head list_head;
int intermediate_voltage;
+ unsigned long opp_freq;
bool need_voltage_tracking;
};
@@ -211,6 +214,33 @@ static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc)
vproc + VOLT_TOL);
}
+static int mtk_cpufreq_opp_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct dev_pm_opp *opp = data;
+ struct mtk_cpu_dvfs_info *info = container_of(nb,
+ struct mtk_cpu_dvfs_info,
+ opp_nb);
+ unsigned long freq, volt;
+ int ret = 0;
+
+ if (event == OPP_EVENT_ADJUST_VOLTAGE) {
+ freq = dev_pm_opp_get_freq(opp);
+
+ if (info->opp_freq == freq) {
+ volt = dev_pm_opp_get_voltage(opp);
+ mutex_lock(&info->lock);
+ ret = mtk_cpufreq_set_voltage(info, volt);
+ mutex_unlock(&info->lock);
+ if (ret)
+ dev_err(info->cpu_dev,
+ "failed to scale voltage: %d\n", ret);
+ }
+ }
+
+ return notifier_from_errno(ret);
+}
+
static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
unsigned int index)
{
@@ -245,6 +275,8 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
vproc = dev_pm_opp_get_voltage(opp);
rcu_read_unlock();
+ mutex_lock(&info->lock);
+
/*
* If the new voltage or the intermediate voltage is higher than the
* current voltage, scale up voltage first.
@@ -256,6 +288,7 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
pr_err("cpu%d: failed to scale up voltage!\n",
policy->cpu);
mtk_cpufreq_set_voltage(info, old_vproc);
+ mutex_unlock(&info->lock);
return ret;
}
}
@@ -267,6 +300,7 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
policy->cpu);
mtk_cpufreq_set_voltage(info, old_vproc);
WARN_ON(1);
+ mutex_unlock(&info->lock);
return ret;
}
@@ -277,6 +311,7 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
policy->cpu);
clk_set_parent(cpu_clk, armpll);
mtk_cpufreq_set_voltage(info, old_vproc);
+ mutex_unlock(&info->lock);
return ret;
}
@@ -287,6 +322,7 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
policy->cpu);
mtk_cpufreq_set_voltage(info, inter_vproc);
WARN_ON(1);
+ mutex_unlock(&info->lock);
return ret;
}
@@ -302,10 +338,14 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
clk_set_parent(cpu_clk, info->inter_clk);
clk_set_rate(armpll, old_freq_hz);
clk_set_parent(cpu_clk, armpll);
+ mutex_unlock(&info->lock);
return ret;
}
}
+ info->opp_freq = freq_hz;
+ mutex_unlock(&info->lock);
+
return 0;
}
@@ -343,6 +383,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
struct dev_pm_opp *opp;
unsigned long rate;
int ret;
+ struct srcu_notifier_head *opp_srcu_head;
cpu_dev = get_cpu_device(cpu);
if (!cpu_dev) {
@@ -417,11 +458,25 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
rcu_read_unlock();
+ opp_srcu_head = dev_pm_opp_get_notifier(cpu_dev);
+ if (IS_ERR(opp_srcu_head)) {
+ ret = PTR_ERR(opp_srcu_head);
+ goto out_free_opp_table;
+ }
+
+ info->opp_nb.notifier_call = mtk_cpufreq_opp_notifier;
+ ret = srcu_notifier_chain_register(opp_srcu_head, &info->opp_nb);
+ if (ret)
+ goto out_free_opp_table;
+
info->cpu_dev = cpu_dev;
info->proc_reg = proc_reg;
info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg;
info->cpu_clk = cpu_clk;
info->inter_clk = inter_clk;
+ info->opp_freq = clk_get_rate(cpu_clk);
+
+ mutex_init(&info->lock);
/*
* If SRAM regulator is present, software "voltage tracking" is needed
Add a notifier to receive OPP voltage adjustment event which is triggered by voltage change of OPP entries done by Mediatek SVS (Smart Voltage Scaling) engine. CC: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org> --- This patch is modify from the patch which adds[1] a notifier in cpufreq-dt to handle OPP voltage adjust event. This patch relies on the on the runtime voltage adjustment mechanism of OPP introduced in the same patchset. [1] https://lkml.org/lkml/2015/9/18/833 --- drivers/cpufreq/mt8173-cpufreq.c | 55 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html