forked from lede-project/source
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ipq806x: cpufreq-dt: enhance l2 cache scaling
Allow to set target cpu frequency to take decision on scaling l2 cache up or down and corresponding voltages to be supplied per frequency. Add correct L2 cpu frequency targets and voltages according to GPL tarballs. Signed-off-by: Pavel Kubelun <be.dissent@gmail.com>
- Loading branch information
Showing
4 changed files
with
155 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
145 changes: 145 additions & 0 deletions
145
target/linux/ipq806x/patches-4.9/0055-2-cpufreq-dt-enhance-L2-cache-freq-scaling.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
From 9061c8a0799e27059e5fdf9b049ab8c7b83d58cf Mon Sep 17 00:00:00 2001 | ||
From: Pavel Kubelun <be.dissent@gmail.com> | ||
Date: Tue, 26 Dec 2017 23:25:41 +0300 | ||
Subject: [PATCH] cpufreq-dt: enhance L2 cache freq scaling | ||
|
||
Allow to set target cpu frequency to take decision on scaling l2 cache | ||
up or down and corresponding voltages to be supplied per frequency. | ||
|
||
Signed-off-by: Pavel Kubelun <be.dissent@gmail.com> | ||
--- | ||
drivers/cpufreq/cpufreq-dt.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- | ||
include/linux/cpufreq.h | 2 ++ | ||
2 files changed, 55 insertions(+), 16 deletions(-) | ||
|
||
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c | ||
index ac5d348..ec67a4b 100644 | ||
--- a/drivers/cpufreq/cpufreq-dt.c | ||
+++ b/drivers/cpufreq/cpufreq-dt.c | ||
@@ -37,6 +37,9 @@ struct private_data { | ||
unsigned long opp_freq; | ||
}; | ||
|
||
+static unsigned int voltage_tolerance; /* in percentage */ | ||
+static struct regulator *l2_regulator; | ||
+ | ||
static struct freq_attr *cpufreq_dt_attr[] = { | ||
&cpufreq_freq_attr_scaling_available_freqs, | ||
NULL, /* Extra space for boost-attr if required */ | ||
@@ -50,23 +53,27 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index) | ||
unsigned long target_freq = policy->freq_table[index].frequency * 1000; | ||
struct clk *l2_clk = policy->l2_clk; | ||
unsigned int l2_freq; | ||
- unsigned long new_l2_freq = 0; | ||
+ unsigned long new_l2_freq = 0, new_l2_volt = 0; | ||
|
||
mutex_lock(&priv->lock); | ||
ret = dev_pm_opp_set_rate(priv->cpu_dev, target_freq); | ||
|
||
if (!ret) { | ||
- if (!IS_ERR(l2_clk) && policy->l2_rate[0] && policy->l2_rate[1] && | ||
- policy->l2_rate[2]) { | ||
+ if (!IS_ERR(l2_clk) && !IS_ERR(l2_regulator) && policy->l2_rate[0] && | ||
+ policy->l2_rate[1] && policy->l2_rate[2] && policy->l2_cpufreq[0] && | ||
+ policy->l2_cpufreq[1] && policy->l2_cpufreq[2] && policy->l2_volt[2] && | ||
+ policy->l2_volt[1] && policy->l2_volt[0]) { | ||
static unsigned long krait_l2[CONFIG_NR_CPUS] = { }; | ||
- int cpu, ret = 0; | ||
- | ||
- if (target_freq >= policy->l2_rate[2]) | ||
- new_l2_freq = policy->l2_rate[2]; | ||
- else if (target_freq >= policy->l2_rate[1]) | ||
- new_l2_freq = policy->l2_rate[1]; | ||
- else | ||
- new_l2_freq = policy->l2_rate[0]; | ||
+ int cpu, i, tol = 0, ret = 0; | ||
+ | ||
+ for (i = 2; i >= 0; i--) { | ||
+ if (target_freq >= policy->l2_cpufreq[i]) { | ||
+ new_l2_freq = policy->l2_rate[i]; | ||
+ new_l2_volt = policy->l2_volt[i]; | ||
+ tol = policy->l2_volt[i] * voltage_tolerance / 100; | ||
+ break; | ||
+ } | ||
+ } | ||
|
||
krait_l2[policy->cpu] = new_l2_freq; | ||
for_each_present_cpu(cpu) | ||
@@ -74,9 +81,17 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index) | ||
|
||
l2_freq = clk_get_rate(l2_clk); | ||
|
||
- if (l2_freq != new_l2_freq) { | ||
- /* scale l2 with the core */ | ||
+ if (l2_freq > new_l2_freq) { | ||
+ /* scale l2 with the core, lower the frequency first */ | ||
ret = clk_set_rate(l2_clk, new_l2_freq); | ||
+ if (!ret) | ||
+ ret = regulator_set_voltage_tol(l2_regulator,new_l2_volt,tol); | ||
+ } | ||
+ if (l2_freq < new_l2_freq) { | ||
+ /* scale l2 with the core, rise the voltage first */ | ||
+ ret = regulator_set_voltage_tol(l2_regulator,new_l2_volt,tol); | ||
+ if (!ret) | ||
+ ret = clk_set_rate(l2_clk, new_l2_freq); | ||
} | ||
} | ||
|
||
@@ -231,6 +246,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) | ||
struct srcu_notifier_head *opp_srcu_head; | ||
struct device_node *l2_np; | ||
struct clk *l2_clk = NULL; | ||
+ struct device_node *np, *cache; | ||
|
||
cpu_dev = get_cpu_device(policy->cpu); | ||
if (!cpu_dev) { | ||
@@ -358,9 +374,30 @@ static int cpufreq_init(struct cpufreq_policy *policy) | ||
l2_clk = clk_get(cpu_dev, "l2"); | ||
if (!IS_ERR(l2_clk)) | ||
policy->l2_clk = l2_clk; | ||
- l2_np = of_find_node_by_name(NULL, "qcom,l2"); | ||
- if (l2_np) | ||
- of_property_read_u32_array(l2_np, "qcom,l2-rates", policy->l2_rate, 3); | ||
+ | ||
+ np = of_node_get(priv->cpu_dev->of_node); | ||
+ if (np) { | ||
+ of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance); | ||
+ cache = of_find_next_cache_node(np); | ||
+ } | ||
+ | ||
+ if (cache) { | ||
+ struct device_node *vdd; | ||
+ | ||
+ of_property_read_u32_array(cache, "l2-rates", policy->l2_rate, 3); | ||
+ of_property_read_u32_array(cache, "l2-cpufreq", policy->l2_cpufreq, 3); | ||
+ of_property_read_u32_array(cache, "l2-volt", policy->l2_volt, 3); | ||
+ | ||
+ vdd = of_parse_phandle(cache, "l2-supply", 0); | ||
+ if (vdd) { | ||
+ l2_regulator = regulator_get(NULL, vdd->name); | ||
+ if (IS_ERR(l2_regulator)) { | ||
+ pr_warn("failed to get l2 supply\n"); | ||
+ l2_regulator = NULL; | ||
+ } | ||
+ of_node_put(vdd); | ||
+ } | ||
+ } | ||
|
||
ret = cpufreq_table_validate_and_show(policy, freq_table); | ||
if (ret) { | ||
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h | ||
index 9c0a4b5..ffa6942 100644 | ||
--- a/include/linux/cpufreq.h | ||
+++ b/include/linux/cpufreq.h | ||
@@ -75,6 +75,8 @@ struct cpufreq_policy { | ||
struct clk *clk; | ||
struct clk *l2_clk; /* L2 clock */ | ||
unsigned int l2_rate[3]; /* L2 bus clock rate thresholds */ | ||
+ unsigned int l2_cpufreq[3]; /* L2 target CPU frequency */ | ||
+ unsigned int l2_volt[3]; /* L2 voltage array */ | ||
struct cpufreq_cpuinfo cpuinfo;/* see above */ | ||
|
||
unsigned int min; /* in kHz */ | ||
-- | ||
Working Copy 3.0.6 | ||
|