Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0912a31 authored by Quentin Perret's avatar Quentin Perret
Browse files

ANDROID: cpufreq: scmi: Register an Energy Model



The Energy Model framework provides an API to register the active power
of CPUs. This commit calls this API from the scmi-cpufreq driver which uses
the power costs provided by the firmware.

Change-Id: I2e6036acbf004d41f921e1396983b07e022a5399
Signed-off-by: default avatarQuentin Perret <quentin.perret@arm.com>
parent b085f79a
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
#include <linux/cpu_cooling.h>
#include <linux/energy_model.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/pm_opp.h>
@@ -103,13 +104,42 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
	return 0;
}

static int __maybe_unused
scmi_get_cpu_power(unsigned long *power, unsigned long *KHz, int cpu)
{
	struct device *cpu_dev = get_cpu_device(cpu);
	unsigned long Hz;
	int ret, domain;

	if (!cpu_dev) {
		pr_err("failed to get cpu%d device\n", cpu);
		return -ENODEV;
	}

	domain = handle->perf_ops->device_domain_id(cpu_dev);
	if (domain < 0)
		return domain;

	/* Get the power cost of the performance domain. */
	Hz = *KHz * 1000;
	ret = handle->perf_ops->est_power_get(handle, domain, &Hz, power);
	if (ret)
		return ret;

	/* The EM framework specifies the frequency in KHz. */
	*KHz = Hz / 1000;

	return 0;
}

static int scmi_cpufreq_init(struct cpufreq_policy *policy)
{
	int ret;
	int ret, nr_opp;
	unsigned int latency;
	struct device *cpu_dev;
	struct scmi_data *priv;
	struct cpufreq_frequency_table *freq_table;
	struct em_data_callback em_cb = EM_DATA_CB(scmi_get_cpu_power);

	cpu_dev = get_cpu_device(policy->cpu);
	if (!cpu_dev) {
@@ -142,6 +172,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
		ret = -EPROBE_DEFER;
		goto out_free_opp;
	}
	nr_opp = ret;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
@@ -171,6 +202,9 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
	policy->cpuinfo.transition_latency = latency;

	policy->fast_switch_possible = true;

	em_register_perf_domain(policy->cpus, nr_opp, &em_cb);

	return 0;

out_free_priv: