From: Dietmar Eggemann Date: Fri, 1 Jun 2018 13:27:24 +0000 (+0100) Subject: cpufreq: arm_big_little: Register an Energy Model X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=64fa469e280c9aaa7cc29bffcb78e471ae62ca63;p=platform%2Fkernel%2Flinux-exynos.git cpufreq: arm_big_little: 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 scpi-cpufreq driver which can rely on the power estimation helper provided by PM_OPP. Todo: Check if driver can handle -EPROBE_DEFER and if the call to dev_pm_opp_get_opp_count() id realy necessary. Change-Id: Ia808262ef6c9f2cc7819a83e8eb2f602454edfa3 Signed-off-by: Dietmar Eggemann [ Removed the dependency on dev_pm_opp_of_estimate_power() ] Signed-off-by: Quentin Perret --- diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index cf62a1f64dd7..e53cc0da7150 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -453,9 +454,48 @@ put_clusters: return ret; } +static int of_est_power(unsigned long *mW, unsigned long *KHz, int cpu) +{ + unsigned long mV, Hz, MHz; + struct device *cpu_dev; + struct dev_pm_opp *opp; + struct device_node *np; + u32 cap; + u64 tmp; + + cpu_dev = get_cpu_device(cpu); + if (!cpu_dev) + return -ENODEV; + + np = of_node_get(cpu_dev->of_node); + if (!np) + return -EINVAL; + + if (of_property_read_u32(np, "dynamic-power-coefficient", &cap)) + return -EINVAL; + + Hz = *KHz * 1000; + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &Hz); + if (IS_ERR(opp)) + return -EINVAL; + + mV = dev_pm_opp_get_voltage(opp) / 1000; + dev_pm_opp_put(opp); + + MHz = Hz / 1000000; + tmp = (u64)cap * mV * mV * MHz; + do_div(tmp, 1000000000); + + *mW = (unsigned long)tmp; + *KHz = Hz / 1000; + + return 0; +} + /* Per-CPU initialization */ static int bL_cpufreq_init(struct cpufreq_policy *policy) { + struct em_data_callback em_cb = EM_DATA_CB(of_est_power); u32 cur_cluster = cpu_to_cluster(policy->cpu); struct device *cpu_dev; int ret; @@ -487,6 +527,14 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = arm_bL_ops->get_transition_latency(cpu_dev); + ret = dev_pm_opp_get_opp_count(cpu_dev); + if (ret <= 0) { + dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n"); + return -EPROBE_DEFER; + } + + em_register_freq_domain(policy->cpus, ret, &em_cb); + if (is_bL_switching_enabled()) per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu);