summaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/scmi-cpufreq.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-03-04 11:19:14 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-03-04 11:19:14 +0100
commit1271d6d576b7e7c80519de211f250cfd4eebca1a (patch)
treebe1edc3b8d6a2633af2b5552daefac7603176283 /drivers/cpufreq/scmi-cpufreq.c
parent6a558c723ed17c588dd951cf158e4adf2c85bcee (diff)
parent78317ed93a5865889cc1471df2afc9d7bc59f6e2 (diff)
downloadlinux-1271d6d576b7e7c80519de211f250cfd4eebca1a.tar.gz
linux-1271d6d576b7e7c80519de211f250cfd4eebca1a.tar.bz2
linux-1271d6d576b7e7c80519de211f250cfd4eebca1a.zip
Merge branch 'pm-opp'
* pm-opp: cpufreq: OMAP: Register an Energy Model cpufreq: imx6q: Register an Energy Model opp: no need to check return value of debugfs_create functions cpufreq: mediatek: Register an Energy Model cpufreq: scmi: Register an Energy Model cpufreq: arm_big_little: Register an Energy Model cpufreq: scpi: Register an Energy Model cpufreq: dt: Register an Energy Model
Diffstat (limited to 'drivers/cpufreq/scmi-cpufreq.c')
-rw-r--r--drivers/cpufreq/scmi-cpufreq.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index c47182fc64ea..e6182c89df79 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -11,6 +11,7 @@
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
+#include <linux/energy_model.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/pm_opp.h>
@@ -101,13 +102,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) {
@@ -134,8 +164,8 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
return ret;
}
- ret = dev_pm_opp_get_opp_count(cpu_dev);
- if (ret <= 0) {
+ nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
+ if (nr_opp <= 0) {
dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
ret = -EPROBE_DEFER;
goto out_free_opp;
@@ -169,6 +199,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: