diff mbox series

[v3,1/2] cpufreq: dt: permit defining custom .get and .target_index

Message ID 20241125150200.714-1-ansuelsmth@gmail.com (mailing list archive)
State New
Headers show
Series [v3,1/2] cpufreq: dt: permit defining custom .get and .target_index | expand

Commit Message

Christian Marangi Nov. 25, 2024, 3:01 p.m. UTC
Some modern device might have CPU frequency control totally detached
from the system and entirely handled by ATF or Secure World. Such device
also tune the CPU frequency indirectly with special call, like SMCCC
calls.

In such condition, creating a special clock for the task might introduce
lots of unneeded overhead to permit usage of the generic "cpufreq-dt"
driver.

To handle this scenario, expand the "cpufreq-dt" driver to also permit
defining custom .get and .target_index function. This is already
supported for the .suspend, .resume and the .get_intermediate OPs.

With this, custom CPU Freq driver can now define custom .get and
.target_index and directly make SMCCC calls to tune the CPU frequency
while keeping full support of all the property and initialization of
"cpufreq-dt".

It's also needed to introduce a bool to permit skipping CPU clock
parsing (no_cpu_clk). This bool is applied only if a custom .get is
defined and is needed to handle case when the CPU node doesn't have a
clock defined as it's entirely handled indirectly and not exposed to the
system. This permits full init of cpufreq-dt with custom .get() and
.target_index().

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
Changes v3:
- Add this patch

 drivers/cpufreq/cpufreq-dt.c | 19 +++++++++++++++++--
 drivers/cpufreq/cpufreq-dt.h |  4 ++++
 2 files changed, 21 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 983443396f8f..ecbac6502b57 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -31,6 +31,7 @@  struct private_data {
 	struct device *cpu_dev;
 	struct cpufreq_frequency_table *freq_table;
 	bool have_static_opps;
+	bool no_cpu_clk;
 	int opp_token;
 };
 
@@ -90,7 +91,7 @@  static int cpufreq_init(struct cpufreq_policy *policy)
 {
 	struct private_data *priv;
 	struct device *cpu_dev;
-	struct clk *cpu_clk;
+	struct clk *cpu_clk = NULL;
 	unsigned int transition_latency;
 	int ret;
 
@@ -101,7 +102,13 @@  static int cpufreq_init(struct cpufreq_policy *policy)
 	}
 	cpu_dev = priv->cpu_dev;
 
-	cpu_clk = clk_get(cpu_dev, NULL);
+	/*
+	 * CPU might have special clock handling (example handled by ATF with
+	 * SMCCC calls). If instructed, skip checking for a CPU clock as it's
+	 * handled by custom .get.
+	 */
+	if (!priv->no_cpu_clk)
+		cpu_clk = clk_get(cpu_dev, NULL);
 	if (IS_ERR(cpu_clk)) {
 		ret = PTR_ERR(cpu_clk);
 		dev_err(cpu_dev, "%s: failed to get clk: %d\n", __func__, ret);
@@ -175,6 +182,7 @@  static struct cpufreq_driver dt_cpufreq_driver = {
 
 static int dt_cpufreq_early_init(struct device *dev, int cpu)
 {
+	struct cpufreq_dt_platform_data *data = dev_get_platdata(dev);
 	struct private_data *priv;
 	struct device *cpu_dev;
 	bool fallback = false;
@@ -198,6 +206,9 @@  static int dt_cpufreq_early_init(struct device *dev, int cpu)
 
 	cpumask_set_cpu(cpu, priv->cpus);
 	priv->cpu_dev = cpu_dev;
+	/* Permit CPU with no clock, if custom .get is defined */
+	if (data->get)
+		priv->no_cpu_clk = data->no_cpu_clk;
 
 	/*
 	 * OPP layer will be taking care of regulators now, but it needs to know
@@ -313,6 +324,10 @@  static int dt_cpufreq_probe(struct platform_device *pdev)
 		if (data->have_governor_per_policy)
 			dt_cpufreq_driver.flags |= CPUFREQ_HAVE_GOVERNOR_PER_POLICY;
 
+		if (data->get)
+			dt_cpufreq_driver.get = data->get;
+		if (data->target_index)
+			dt_cpufreq_driver.target_index = data->target_index;
 		dt_cpufreq_driver.resume = data->resume;
 		if (data->suspend)
 			dt_cpufreq_driver.suspend = data->suspend;
diff --git a/drivers/cpufreq/cpufreq-dt.h b/drivers/cpufreq/cpufreq-dt.h
index 28c8af7ec5ef..ba0385d75bdb 100644
--- a/drivers/cpufreq/cpufreq-dt.h
+++ b/drivers/cpufreq/cpufreq-dt.h
@@ -13,7 +13,11 @@  struct cpufreq_policy;
 
 struct cpufreq_dt_platform_data {
 	bool have_governor_per_policy;
+	bool no_cpu_clk;
 
+	unsigned int	(*get)(unsigned int cpu);
+	int		(*target_index)(struct cpufreq_policy *policy,
+					unsigned int index);
 	unsigned int	(*get_intermediate)(struct cpufreq_policy *policy,
 					    unsigned int index);
 	int		(*target_intermediate)(struct cpufreq_policy *policy,