[PATCH 1/2] cpufreq: qcom-cpufreq-hw: Register config_clks helper
From: Viresh Kumar
Date: Mon Nov 21 2022 - 01:58:31 EST
In qcom-cpufreq-hw driver, we want to skip clk configuration that
happens via dev_pm_opp_set_opp(), but still want the OPP core to parse
the "opp-hz" property so we can use the freq based OPP helpers.
The OPP core provides support for the platforms to provide config_clks
helpers now, lets use that to provide an empty callback to skip clock
configuration.
Signed-off-by: Viresh Kumar <viresh.kumar@xxxxxxxxxx>
---
drivers/cpufreq/qcom-cpufreq-hw.c | 34 ++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index 1bd1e9ae5308..5f8079898940 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -51,6 +51,7 @@ struct qcom_cpufreq_data {
*/
struct mutex throttle_lock;
int throttle_irq;
+ int opp_token;
char irq_name[15];
bool cancel_throttle;
struct delayed_work throttle_work;
@@ -58,7 +59,6 @@ struct qcom_cpufreq_data {
struct clk_hw cpu_clk;
bool per_core_dcvs;
-
struct freq_qos_request throttle_freq_req;
};
@@ -197,6 +197,15 @@ static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy,
return policy->freq_table[index].frequency;
}
+static int qcom_cpufreq_hw_config_clks(struct device *dev,
+ struct opp_table *opp_table,
+ struct dev_pm_opp *opp, void *data,
+ bool scaling_down)
+{
+ /* We want to skip clk configuration via dev_pm_opp_set_opp() */
+ return 0;
+}
+
static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
struct cpufreq_policy *policy)
{
@@ -208,11 +217,23 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
int ret;
struct qcom_cpufreq_data *drv_data = policy->driver_data;
const struct qcom_cpufreq_soc_data *soc_data = qcom_cpufreq.soc_data;
+ const char * const clk_names[] = { NULL, NULL };
+ struct dev_pm_opp_config config = {
+ .clk_names = clk_names,
+ .config_clks = qcom_cpufreq_hw_config_clks,
+ };
table = kcalloc(LUT_MAX_ENTRIES + 1, sizeof(*table), GFP_KERNEL);
if (!table)
return -ENOMEM;
+ ret = dev_pm_opp_set_config(cpu_dev, &config);
+ if (ret < 0) {
+ dev_err(cpu_dev, "Failed to set OPP config: %d\n", ret);
+ goto free_table;
+ }
+ drv_data->opp_token = ret;
+
ret = dev_pm_opp_of_add_table(cpu_dev);
if (!ret) {
/* Disable all opps and cross-validate against LUT later */
@@ -227,8 +248,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
}
} else if (ret != -ENODEV) {
dev_err(cpu_dev, "Invalid opp table in device tree\n");
- kfree(table);
- return ret;
+ goto clear_config;
} else {
policy->fast_switch_possible = true;
icc_scaling_enabled = false;
@@ -296,6 +316,13 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus);
return 0;
+
+clear_config:
+ dev_pm_opp_clear_config(drv_data->opp_token);
+
+free_table:
+ kfree(table);
+ return ret;
}
static void qcom_get_related_cpus(int index, struct cpumask *m)
@@ -594,6 +621,7 @@ static int qcom_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy)
dev_pm_opp_remove_all_dynamic(cpu_dev);
dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
qcom_cpufreq_hw_lmh_exit(data);
+ dev_pm_opp_clear_config(data->opp_token);
kfree(policy->freq_table);
kfree(data);
iounmap(base);
--
2.31.1.272.g89b43f80a514