mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-19 13:48:06 +00:00
mvebu: backport upstream fixes for armada 37xx
Upstream patches for processor frequency scaling, which fix possible system hard lockups. Signed-off-by: Tomasz Maciej Nowak <tomek_n@o2.pl>
This commit is contained in:
parent
9b1102416f
commit
7d188fb4db
@ -0,0 +1,92 @@
|
||||
From 61c40f35f5cd6f67ccbd7319a1722eb78c815989 Mon Sep 17 00:00:00 2001
|
||||
From: Gregory CLEMENT <gregory.clement@bootlin.com>
|
||||
Date: Tue, 19 Jun 2018 14:34:45 +0200
|
||||
Subject: [PATCH] clk: mvebu: armada-37xx-periph: Fix switching CPU rate from
|
||||
300Mhz to 1.2GHz
|
||||
|
||||
Switching the CPU from the L2 or L3 frequencies (300 and 200 Mhz
|
||||
respectively) to L0 frequency (1.2 Ghz) requires a significant amount
|
||||
of time to let VDD stabilize to the appropriate voltage. This amount of
|
||||
time is large enough that it cannot be covered by the hardware
|
||||
countdown register. Due to this, the CPU might start operating at L0
|
||||
before the voltage is stabilized, leading to CPU stalls.
|
||||
|
||||
To work around this problem, we prevent switching directly from the
|
||||
L2/L3 frequencies to the L0 frequency, and instead switch to the L1
|
||||
frequency in-between. The sequence therefore becomes:
|
||||
|
||||
1. First switch from L2/L3(200/300MHz) to L1(600MHZ)
|
||||
2. Sleep 20ms for stabling VDD voltage
|
||||
3. Then switch from L1(600MHZ) to L0(1200Mhz).
|
||||
|
||||
It is based on the work done by Ken Ma <make@marvell.com>
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 2089dc33ea0e ("clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks")
|
||||
Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/mvebu/armada-37xx-periph.c | 38 ++++++++++++++++++++++++++
|
||||
1 file changed, 38 insertions(+)
|
||||
|
||||
--- a/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#define CLK_SEL 0x10
|
||||
#define CLK_DIS 0x14
|
||||
|
||||
+#define ARMADA_37XX_DVFS_LOAD_1 1
|
||||
#define LOAD_LEVEL_NR 4
|
||||
|
||||
#define ARMADA_37XX_NB_L0L1 0x18
|
||||
@@ -507,6 +508,40 @@ static long clk_pm_cpu_round_rate(struct
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Switching the CPU from the L2 or L3 frequencies (300 and 200 Mhz
|
||||
+ * respectively) to L0 frequency (1.2 Ghz) requires a significant
|
||||
+ * amount of time to let VDD stabilize to the appropriate
|
||||
+ * voltage. This amount of time is large enough that it cannot be
|
||||
+ * covered by the hardware countdown register. Due to this, the CPU
|
||||
+ * might start operating at L0 before the voltage is stabilized,
|
||||
+ * leading to CPU stalls.
|
||||
+ *
|
||||
+ * To work around this problem, we prevent switching directly from the
|
||||
+ * L2/L3 frequencies to the L0 frequency, and instead switch to the L1
|
||||
+ * frequency in-between. The sequence therefore becomes:
|
||||
+ * 1. First switch from L2/L3(200/300MHz) to L1(600MHZ)
|
||||
+ * 2. Sleep 20ms for stabling VDD voltage
|
||||
+ * 3. Then switch from L1(600MHZ) to L0(1200Mhz).
|
||||
+ */
|
||||
+static void clk_pm_cpu_set_rate_wa(unsigned long rate, struct regmap *base)
|
||||
+{
|
||||
+ unsigned int cur_level;
|
||||
+
|
||||
+ if (rate != 1200 * 1000 * 1000)
|
||||
+ return;
|
||||
+
|
||||
+ regmap_read(base, ARMADA_37XX_NB_CPU_LOAD, &cur_level);
|
||||
+ cur_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
|
||||
+ if (cur_level <= ARMADA_37XX_DVFS_LOAD_1)
|
||||
+ return;
|
||||
+
|
||||
+ regmap_update_bits(base, ARMADA_37XX_NB_CPU_LOAD,
|
||||
+ ARMADA_37XX_NB_CPU_LOAD_MASK,
|
||||
+ ARMADA_37XX_DVFS_LOAD_1);
|
||||
+ msleep(20);
|
||||
+}
|
||||
+
|
||||
static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
@@ -537,6 +572,9 @@ static int clk_pm_cpu_set_rate(struct cl
|
||||
*/
|
||||
reg = ARMADA_37XX_NB_CPU_LOAD;
|
||||
mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
|
||||
+
|
||||
+ clk_pm_cpu_set_rate_wa(rate, base);
|
||||
+
|
||||
regmap_update_bits(base, reg, mask, load_level);
|
||||
|
||||
return rate;
|
@ -0,0 +1,33 @@
|
||||
From 616bf80d381da13fbb392ebff06f46f946e3ee84 Mon Sep 17 00:00:00 2001
|
||||
From: Gregory CLEMENT <gregory.clement@bootlin.com>
|
||||
Date: Fri, 13 Jul 2018 12:27:26 +0200
|
||||
Subject: [PATCH] clk: mvebu: armada-37xx-periph: Fix wrong return value in
|
||||
get_parent
|
||||
|
||||
The return value of the get_parent operation is a u8, whereas a -EINVAL
|
||||
was returned. This wrong value was return if the value was bigger that
|
||||
the number of parent but this case was already handled by the core.
|
||||
|
||||
So we can just remove this chunk of code to fix the issue.
|
||||
|
||||
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Fixes: 9818a7a4fd10 ("clk: mvebu: armada-37xx-periph: prepare cpu clk to
|
||||
be used with DVFS")
|
||||
Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/mvebu/armada-37xx-periph.c | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
--- a/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
@@ -429,9 +429,6 @@ static u8 clk_pm_cpu_get_parent(struct c
|
||||
val &= pm_cpu->mask_mux;
|
||||
}
|
||||
|
||||
- if (val >= num_parents)
|
||||
- return -EINVAL;
|
||||
-
|
||||
return val;
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
From 8927c27b32703e28041ae19bf25ea53461be83a1 Mon Sep 17 00:00:00 2001
|
||||
From: Anders Roxell <anders.roxell@linaro.org>
|
||||
Date: Fri, 27 Jul 2018 00:27:21 +0200
|
||||
Subject: [PATCH] clk: mvebu: armada-37xx-periph: Remove unused var num_parents
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When building armada-37xx-periph, num_parents isn't used in function
|
||||
clk_pm_cpu_get_parent:
|
||||
drivers/clk/mvebu/armada-37xx-periph.c: In function ‘clk_pm_cpu_get_parent’:
|
||||
drivers/clk/mvebu/armada-37xx-periph.c:419:6: warning: unused variable ‘num_parents’ [-Wunused-variable]
|
||||
int num_parents = clk_hw_get_num_parents(hw);
|
||||
^~~~~~~~~~~
|
||||
Remove the declaration of num_parents to dispose the warning.
|
||||
|
||||
Fixes: 616bf80d381d ("clk: mvebu: armada-37xx-periph: Fix wrong return value in get_parent")
|
||||
Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/mvebu/armada-37xx-periph.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
@@ -419,7 +419,6 @@ static unsigned int armada_3700_pm_dvfs_
|
||||
static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
|
||||
- int num_parents = clk_hw_get_num_parents(hw);
|
||||
u32 val;
|
||||
|
||||
if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) {
|
Loading…
Reference in New Issue
Block a user