Skip to content

Commit c377d4b

Browse files
anderssonvireshk
authored andcommitted
cpufreq: qcom-hw: Add support for per-core-dcvs
The OSM and EPSS hardware controls the frequency of each cluster in the system based on requests from the OS and various limiting factors, such as input from LMH. In most systems the vote from the OS is done using a single register per cluster, but some systems are configured to instead take one request per core. In this configuration a set of consecutive registers are used for the OS to request the frequency of each of the cores within the cluster. The information is then aggregated in the hardware and the frequency for the cluster is determined. As the current implementation ends up only requesting a frequency for the first core in each cluster and only the vote of non-idle cores are considered it's often the case that the cluster will be clocked (much) lower than expected. It's possible that there are benefits of performing the per-core requests from the OS, but more investigation of the outcome is needed before introducing such support. As such this patch extends the request for the cluster to be written to all the cores. The weight of the policy's related_cpus is used to determine how many cores, and hence consecutive registers, each cluster has. The OS is not permitted to disable the per-core dcvs feature. Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
1 parent ec1c7ad commit c377d4b

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

drivers/cpufreq/qcom-cpufreq-hw.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
struct qcom_cpufreq_soc_data {
3030
u32 reg_enable;
31+
u32 reg_dcvs_ctrl;
3132
u32 reg_freq_lut;
3233
u32 reg_volt_lut;
3334
u32 reg_current_vote;
@@ -50,6 +51,8 @@ struct qcom_cpufreq_data {
5051
bool cancel_throttle;
5152
struct delayed_work throttle_work;
5253
struct cpufreq_policy *policy;
54+
55+
bool per_core_dcvs;
5356
};
5457

5558
static unsigned long cpu_hw_rate, xo_rate;
@@ -102,9 +105,14 @@ static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy,
102105
struct qcom_cpufreq_data *data = policy->driver_data;
103106
const struct qcom_cpufreq_soc_data *soc_data = data->soc_data;
104107
unsigned long freq = policy->freq_table[index].frequency;
108+
unsigned int i;
105109

106110
writel_relaxed(index, data->base + soc_data->reg_perf_state);
107111

112+
if (data->per_core_dcvs)
113+
for (i = 1; i < cpumask_weight(policy->related_cpus); i++)
114+
writel_relaxed(index, data->base + soc_data->reg_perf_state + i * 4);
115+
108116
if (icc_scaling_enabled)
109117
qcom_cpufreq_set_bw(policy, freq);
110118

@@ -137,10 +145,15 @@ static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy,
137145
struct qcom_cpufreq_data *data = policy->driver_data;
138146
const struct qcom_cpufreq_soc_data *soc_data = data->soc_data;
139147
unsigned int index;
148+
unsigned int i;
140149

141150
index = policy->cached_resolved_idx;
142151
writel_relaxed(index, data->base + soc_data->reg_perf_state);
143152

153+
if (data->per_core_dcvs)
154+
for (i = 1; i < cpumask_weight(policy->related_cpus); i++)
155+
writel_relaxed(index, data->base + soc_data->reg_perf_state + i * 4);
156+
144157
return policy->freq_table[index].frequency;
145158
}
146159

@@ -342,6 +355,7 @@ static irqreturn_t qcom_lmh_dcvs_handle_irq(int irq, void *data)
342355

343356
static const struct qcom_cpufreq_soc_data qcom_soc_data = {
344357
.reg_enable = 0x0,
358+
.reg_dcvs_ctrl = 0xbc,
345359
.reg_freq_lut = 0x110,
346360
.reg_volt_lut = 0x114,
347361
.reg_current_vote = 0x704,
@@ -351,6 +365,7 @@ static const struct qcom_cpufreq_soc_data qcom_soc_data = {
351365

352366
static const struct qcom_cpufreq_soc_data epss_soc_data = {
353367
.reg_enable = 0x0,
368+
.reg_dcvs_ctrl = 0xb0,
354369
.reg_freq_lut = 0x100,
355370
.reg_volt_lut = 0x200,
356371
.reg_perf_state = 0x320,
@@ -481,6 +496,9 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
481496
goto error;
482497
}
483498

499+
if (readl_relaxed(base + data->soc_data->reg_dcvs_ctrl) & 0x1)
500+
data->per_core_dcvs = true;
501+
484502
qcom_get_related_cpus(index, policy->cpus);
485503
if (cpumask_empty(policy->cpus)) {
486504
dev_err(dev, "Domain-%d failed to get related CPUs\n", index);

0 commit comments

Comments
 (0)