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>v19.07.3_mercusys_ac12_duma
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue