mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
cpufreq: qcom-hw: Add cycle_counter support
Add support for qcom_cpufreq_get_cpu_cycle_counter(), which provides the
total accumulated CPU cycle counts for use by the scheduler.
This code is a modified snapshot from msm-5.10 commit 83dbc79da4b1
("qcom-cpufreq: remove references to WALT").
Change-Id: Id3ea9a4113cbe2581d159c780ab5d4b71e4d0edb
Signed-off-by: Sai Harshini Nimmala <quic_snimmala@quicinc.com>
Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com>
This commit is contained in:
parent
cc321fbbae
commit
cb0c7a7d3a
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/pm_opp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/qcom-cpufreq-hw.h>
|
||||
|
||||
#define LUT_MAX_ENTRIES 40U
|
||||
#define LUT_SRC GENMASK(31, 30)
|
||||
|
|
@ -28,6 +29,17 @@
|
|||
|
||||
#define HZ_PER_KHZ 1000
|
||||
|
||||
#define CYCLE_CNTR_OFFSET(c, m, acc_count) \
|
||||
(acc_count ? ((c - cpumask_first(m) + 1) * 4) : 0)
|
||||
|
||||
struct cpufreq_counter {
|
||||
u64 total_cycle_counter;
|
||||
u32 prev_cycle_counter;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static struct cpufreq_counter qcom_cpufreq_counter[NR_CPUS];
|
||||
|
||||
struct qcom_cpufreq_soc_data {
|
||||
u32 reg_enable;
|
||||
u32 reg_domain_state;
|
||||
|
|
@ -37,7 +49,9 @@ struct qcom_cpufreq_soc_data {
|
|||
u32 reg_intr_clr;
|
||||
u32 reg_current_vote;
|
||||
u32 reg_perf_state;
|
||||
u32 reg_cycle_cntr;
|
||||
u8 lut_row_size;
|
||||
bool accumulative_counter;
|
||||
};
|
||||
|
||||
struct qcom_cpufreq_data {
|
||||
|
|
@ -103,6 +117,49 @@ static int qcom_cpufreq_update_opp(struct device *cpu_dev,
|
|||
return dev_pm_opp_enable(cpu_dev, freq_hz);
|
||||
}
|
||||
|
||||
u64 qcom_cpufreq_get_cpu_cycle_counter(int cpu)
|
||||
{
|
||||
const struct qcom_cpufreq_soc_data *soc_data;
|
||||
struct cpufreq_counter *cpu_counter;
|
||||
struct qcom_cpufreq_data *data;
|
||||
struct cpufreq_policy *policy;
|
||||
u64 cycle_counter_ret;
|
||||
unsigned long flags;
|
||||
u16 offset;
|
||||
u32 val;
|
||||
|
||||
policy = cpufreq_cpu_get_raw(cpu);
|
||||
if (!policy)
|
||||
return 0;
|
||||
|
||||
data = policy->driver_data;
|
||||
soc_data = data->soc_data;
|
||||
|
||||
cpu_counter = &qcom_cpufreq_counter[cpu];
|
||||
spin_lock_irqsave(&cpu_counter->lock, flags);
|
||||
|
||||
offset = CYCLE_CNTR_OFFSET(cpu, policy->related_cpus,
|
||||
soc_data->accumulative_counter);
|
||||
val = readl_relaxed(data->base +
|
||||
soc_data->reg_cycle_cntr + offset);
|
||||
|
||||
if (val < cpu_counter->prev_cycle_counter) {
|
||||
/* Handle counter overflow */
|
||||
cpu_counter->total_cycle_counter += UINT_MAX -
|
||||
cpu_counter->prev_cycle_counter + val;
|
||||
cpu_counter->prev_cycle_counter = val;
|
||||
} else {
|
||||
cpu_counter->total_cycle_counter += val -
|
||||
cpu_counter->prev_cycle_counter;
|
||||
cpu_counter->prev_cycle_counter = val;
|
||||
}
|
||||
cycle_counter_ret = cpu_counter->total_cycle_counter;
|
||||
spin_unlock_irqrestore(&cpu_counter->lock, flags);
|
||||
|
||||
return cycle_counter_ret;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_cpufreq_get_cpu_cycle_counter);
|
||||
|
||||
static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy,
|
||||
unsigned int index)
|
||||
{
|
||||
|
|
@ -377,7 +434,9 @@ static const struct qcom_cpufreq_soc_data qcom_soc_data = {
|
|||
.reg_volt_lut = 0x114,
|
||||
.reg_current_vote = 0x704,
|
||||
.reg_perf_state = 0x920,
|
||||
.reg_cycle_cntr = 0x9c0,
|
||||
.lut_row_size = 32,
|
||||
.accumulative_counter = true,
|
||||
};
|
||||
|
||||
static const struct qcom_cpufreq_soc_data epss_soc_data = {
|
||||
|
|
@ -388,7 +447,9 @@ static const struct qcom_cpufreq_soc_data epss_soc_data = {
|
|||
.reg_volt_lut = 0x200,
|
||||
.reg_intr_clr = 0x308,
|
||||
.reg_perf_state = 0x320,
|
||||
.reg_cycle_cntr = 0x3c4,
|
||||
.lut_row_size = 4,
|
||||
.accumulative_counter = false,
|
||||
};
|
||||
|
||||
static const struct of_device_id qcom_cpufreq_hw_match[] = {
|
||||
|
|
|
|||
20
include/linux/qcom-cpufreq-hw.h
Normal file
20
include/linux/qcom-cpufreq-hw.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef _LINUX_QCOM_CPUFREQ_HW_H
|
||||
#define _LINUX_QCOM_CPUFREQ_HW_H
|
||||
|
||||
/*
|
||||
* We can take this out if we could move the OSM cycle
|
||||
* counter to WALT scheduler?
|
||||
*/
|
||||
#if IS_ENABLED(CONFIG_ARM_QCOM_CPUFREQ_HW)
|
||||
extern u64 qcom_cpufreq_get_cpu_cycle_counter(int cpu);
|
||||
#else
|
||||
static inline u64 qcom_cpufreq_get_cpu_cycle_counter(int cpu)
|
||||
{
|
||||
return U64_MAX;
|
||||
}
|
||||
#endif /*CONFIG_ARM_QCOM_CPUFREQ_HW*/
|
||||
#endif /* _LINUX_QCOM_CPUFREQ_HW_H */
|
||||
Loading…
Reference in New Issue
Block a user