openwrt/target/linux/ipq806x/patches-4.19/0055-cpufreq-dt-Add-L2-frequency-scaling-support.patch

89 lines
2.8 KiB
Diff
Raw Normal View History

From 0759cdff49f1cf361bf503c13f7bcb33da43ab95 Mon Sep 17 00:00:00 2001
From: Georgi Djakov <georgi.djakov@linaro.org>
Date: Tue, 8 Sep 2015 11:24:41 +0300
Subject: [PATCH 55/69] cpufreq-dt: Add L2 frequency scaling support
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
drivers/cpufreq/cpufreq-dt.c | 41 ++++++++++++++++++++++++++++++++++++++++-
include/linux/cpufreq.h | 2 ++
2 files changed, 42 insertions(+), 1 deletion(-)
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
ipq806x: fix bug in L2 cache scaling It has been notice a buf in L2 cache scaling where the scaling is not done proprely if the frequency is set to the initial state before the new frequency. From: https://patchwork.kernel.org/patch/10565443/ * The clocks are set to aux clock rate first to make sure the * secondary mux is not sourcing off of QSB. The rate is then set to * two different rates to force a HFPLL reinit under all * circumstances. In the initial stage of boot to force a new frequency to apply, is needed to first set the frequency back to the lowest one (aux_rate) and then to the target one. This force and make sure the controller actually switch the frequency to the right one. Apply the same mechanism to L2 frequency scaling. Before scaling to the target frequency, first set the frequency to the aux_rate to force the transition, then scale it to the target frequency. Doing the wrong way can produce unexpected results and could lock the scaling mechanism until a full reboot is done (Causing a full reset by the krait-cc driver) From: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=77612720a2362230af726baa4149c40ec7a7fb05 When the Hfplls are reprogrammed during the rate change, the primary muxes which are sourced from the same hfpll for higher frequencies, needs to be switched to the 'safe secondary mux' as the parent for that small window. This is done by registering a clk notifier for the muxes and switching to the safe parent in the PRE_RATE_CHANGE notifier and back to the original parent in the POST_RATE_CHANGE notifier. This should apply also to L2 scaling... as we can't relly use the notifier, we manually do this on L2 scaling. Tested-by: Stefan Lippers-Hollmann <s.l-h@gmx.de> [nbg6817/ipq8065] Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
2019-12-15 01:25:04 +00:00
@@ -49,11 +49,40 @@ static int set_target(struct cpufreq_pol
struct private_data *priv = policy->driver_data;
unsigned long freq = policy->freq_table[index].frequency;
int ret;
+ struct clk *l2_clk = policy->l2_clk;
+ unsigned int l2_freq;
+ unsigned long new_l2_freq = 0;
mutex_lock(&priv->lock);
ret = dev_pm_opp_set_rate(priv->cpu_dev, freq * 1000);
if (!ret) {
+ if (!IS_ERR(l2_clk) && policy->l2_rate[0] && policy->l2_rate[1] &&
+ policy->l2_rate[2]) {
+ static unsigned long krait_l2[CONFIG_NR_CPUS] = { };
+ int cpu, ret = 0;
+ unsigned long target_freq = freq * 1000;
+
+ 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];
+
+ krait_l2[policy->cpu] = new_l2_freq;
+ for_each_present_cpu(cpu)
+ new_l2_freq = max(new_l2_freq, krait_l2[cpu]);
+
+ l2_freq = clk_get_rate(l2_clk);
+
+ if (l2_freq != new_l2_freq) {
ipq806x: fix bug in L2 cache scaling It has been notice a buf in L2 cache scaling where the scaling is not done proprely if the frequency is set to the initial state before the new frequency. From: https://patchwork.kernel.org/patch/10565443/ * The clocks are set to aux clock rate first to make sure the * secondary mux is not sourcing off of QSB. The rate is then set to * two different rates to force a HFPLL reinit under all * circumstances. In the initial stage of boot to force a new frequency to apply, is needed to first set the frequency back to the lowest one (aux_rate) and then to the target one. This force and make sure the controller actually switch the frequency to the right one. Apply the same mechanism to L2 frequency scaling. Before scaling to the target frequency, first set the frequency to the aux_rate to force the transition, then scale it to the target frequency. Doing the wrong way can produce unexpected results and could lock the scaling mechanism until a full reboot is done (Causing a full reset by the krait-cc driver) From: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=77612720a2362230af726baa4149c40ec7a7fb05 When the Hfplls are reprogrammed during the rate change, the primary muxes which are sourced from the same hfpll for higher frequencies, needs to be switched to the 'safe secondary mux' as the parent for that small window. This is done by registering a clk notifier for the muxes and switching to the safe parent in the PRE_RATE_CHANGE notifier and back to the original parent in the POST_RATE_CHANGE notifier. This should apply also to L2 scaling... as we can't relly use the notifier, we manually do this on L2 scaling. Tested-by: Stefan Lippers-Hollmann <s.l-h@gmx.de> [nbg6817/ipq8065] Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
2019-12-15 01:25:04 +00:00
+ ret = clk_set_rate(l2_clk, policy->l2_rate[0]);
+ /* scale l2 with the core */
+ ret = clk_set_rate(l2_clk, new_l2_freq);
+ }
+ }
+
priv->opp_freq = freq * 1000;
arch_set_freq_scale(policy->related_cpus, freq,
policy->cpuinfo.max_freq);
@@ -201,6 +230,8 @@ static int cpufreq_init(struct cpufreq_p
bool fallback = false;
const char *name;
int ret;
+ struct device_node *l2_np;
+ struct clk *l2_clk = NULL;
cpu_dev = get_cpu_device(policy->cpu);
if (!cpu_dev) {
@@ -307,6 +338,13 @@ static int cpufreq_init(struct cpufreq_p
policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000;
+ 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);
+
/* Support turbo/boost mode */
if (policy_has_boost_freq(policy)) {
/* This gets disabled by core on driver unregister */
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -73,6 +73,8 @@ struct cpufreq_policy {
unsigned int cpu; /* cpu managing this policy, must be online */
struct clk *clk;
+ struct clk *l2_clk; /* L2 clock */
+ unsigned int l2_rate[3]; /* L2 bus clock rate thresholds */
struct cpufreq_cpuinfo cpuinfo;/* see above */
unsigned int min; /* in kHz */