Skip to content

Commit

Permalink
cpufreq: qcom-hw: Fix the frequency returned by cpufreq_driver->get()
Browse files Browse the repository at this point in the history
[ Upstream commit c72cf0c ]

The cpufreq_driver->get() callback is supposed to return the current
frequency of the CPU and not the one requested by the CPUFreq core.
Fix it by returning the frequency that gets supplied to the CPU after
the DCVS operation of EPSS/OSM.

Fixes: 2849dd8 ("cpufreq: qcom-hw: Add support for QCOM cpufreq HW driver")
Reported-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Mani-Sadhasivam authored and gregkh committed Dec 31, 2022
1 parent a753ee5 commit 205f5e9
Showing 1 changed file with 29 additions and 13 deletions.
42 changes: 29 additions & 13 deletions drivers/cpufreq/qcom-cpufreq-hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,35 @@ static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy,
return 0;
}

static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data)
{
unsigned int lval;

if (data->soc_data->reg_current_vote)
lval = readl_relaxed(data->base + data->soc_data->reg_current_vote) & 0x3ff;
else
lval = readl_relaxed(data->base + data->soc_data->reg_domain_state) & 0xff;

return lval * xo_rate;
}

/* Get the current frequency of the CPU (after throttling) */
static unsigned int qcom_cpufreq_hw_get(unsigned int cpu)
{
struct qcom_cpufreq_data *data;
struct cpufreq_policy *policy;

policy = cpufreq_cpu_get_raw(cpu);
if (!policy)
return 0;

data = policy->driver_data;

return qcom_lmh_get_throttle_freq(data) / HZ_PER_KHZ;
}

/* Get the frequency requested by the cpufreq core for the CPU */
static unsigned int qcom_cpufreq_get_freq(unsigned int cpu)
{
struct qcom_cpufreq_data *data;
const struct qcom_cpufreq_soc_data *soc_data;
Expand Down Expand Up @@ -287,18 +315,6 @@ static void qcom_get_related_cpus(int index, struct cpumask *m)
}
}

static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data)
{
unsigned int lval;

if (data->soc_data->reg_current_vote)
lval = readl_relaxed(data->base + data->soc_data->reg_current_vote) & 0x3ff;
else
lval = readl_relaxed(data->base + data->soc_data->reg_domain_state) & 0xff;

return lval * xo_rate;
}

static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
{
struct cpufreq_policy *policy = data->policy;
Expand Down Expand Up @@ -342,7 +358,7 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
* If h/w throttled frequency is higher than what cpufreq has requested
* for, then stop polling and switch back to interrupt mechanism.
*/
if (throttled_freq >= qcom_cpufreq_hw_get(cpu))
if (throttled_freq >= qcom_cpufreq_get_freq(cpu))
enable_irq(data->throttle_irq);
else
mod_delayed_work(system_highpri_wq, &data->throttle_work,
Expand Down

0 comments on commit 205f5e9

Please sign in to comment.