aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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",