aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cppc_cpufreq.c
diff options
context:
space:
mode:
authorGeorge Cherian <george.cherian@cavium.com>2018-07-12 02:07:55 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-07-18 04:13:16 -0400
commit33477d84c26bbfa626da2c032e567a90dd70a528 (patch)
treeb17b51457b533e208635692735c45161d1e48ff4 /drivers/cpufreq/cppc_cpufreq.c
parent1c3528232f4ba608cc2c31c7a8a55e0dbd6cb200 (diff)
cpufreq / CPPC: Add cpuinfo_cur_freq support for CPPC
Per Section 8.4.7.1.3 of ACPI 6.2, the platform provides performance feedback via set of performance counters. To determine the actual performance level delivered over time, OSPM may read a set of performance counters from the Reference Performance Counter Register and the Delivered Performance Counter Register. OSPM calculates the delivered performance over a given time period by taking a beginning and ending snapshot of both the reference and delivered performance counters, and calculating: delivered_perf = reference_perf X (delta of delivered_perf counter / delta of reference_perf counter). Implement the above and hook this up to the cpufreq->get method. Signed-off-by: George Cherian <george.cherian@cavium.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Prashanth Prakash <pprakash@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/cppc_cpufreq.c')
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index a9d3eec32795..30f302149730 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -296,10 +296,62 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
296 return ret; 296 return ret;
297} 297}
298 298
299static inline u64 get_delta(u64 t1, u64 t0)
300{
301 if (t1 > t0 || t0 > ~(u32)0)
302 return t1 - t0;
303
304 return (u32)t1 - (u32)t0;
305}
306
307static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu,
308 struct cppc_perf_fb_ctrs fb_ctrs_t0,
309 struct cppc_perf_fb_ctrs fb_ctrs_t1)
310{
311 u64 delta_reference, delta_delivered;
312 u64 reference_perf, delivered_perf;
313
314 reference_perf = fb_ctrs_t0.reference_perf;
315
316 delta_reference = get_delta(fb_ctrs_t1.reference,
317 fb_ctrs_t0.reference);
318 delta_delivered = get_delta(fb_ctrs_t1.delivered,
319 fb_ctrs_t0.delivered);
320
321 /* Check to avoid divide-by zero */
322 if (delta_reference || delta_delivered)
323 delivered_perf = (reference_perf * delta_delivered) /
324 delta_reference;
325 else
326 delivered_perf = cpu->perf_ctrls.desired_perf;
327
328 return cppc_cpufreq_perf_to_khz(cpu, delivered_perf);
329}
330
331static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum)
332{
333 struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0};
334 struct cppc_cpudata *cpu = all_cpu_data[cpunum];
335 int ret;
336
337 ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t0);
338 if (ret)
339 return ret;
340
341 udelay(2); /* 2usec delay between sampling */
342
343 ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t1);
344 if (ret)
345 return ret;
346
347 return cppc_get_rate_from_fbctrs(cpu, fb_ctrs_t0, fb_ctrs_t1);
348}
349
299static struct cpufreq_driver cppc_cpufreq_driver = { 350static struct cpufreq_driver cppc_cpufreq_driver = {
300 .flags = CPUFREQ_CONST_LOOPS, 351 .flags = CPUFREQ_CONST_LOOPS,
301 .verify = cppc_verify_policy, 352 .verify = cppc_verify_policy,
302 .target = cppc_cpufreq_set_target, 353 .target = cppc_cpufreq_set_target,
354 .get = cppc_cpufreq_get_rate,
303 .init = cppc_cpufreq_cpu_init, 355 .init = cppc_cpufreq_cpu_init,
304 .stop_cpu = cppc_cpufreq_stop_cpu, 356 .stop_cpu = cppc_cpufreq_stop_cpu,
305 .name = "cppc_cpufreq", 357 .name = "cppc_cpufreq",