From 7d188fb4dbdc5336cf7a802a9af9355fb69b0e97 Mon Sep 17 00:00:00 2001 From: Tomasz Maciej Nowak Date: Sun, 13 Jan 2019 21:30:26 +0100 Subject: [PATCH] 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 --- ...-37xx-periph-Fix-switching-CPU-rate-.patch | 92 +++++++++++++++++++ ...-37xx-periph-Fix-wrong-return-value-.patch | 33 +++++++ ...-37xx-periph-Remove-unused-var-num_p.patch | 33 +++++++ 3 files changed, 158 insertions(+) create mode 100644 target/linux/mvebu/patches-4.14/510-clk-mvebu-armada-37xx-periph-Fix-switching-CPU-rate-.patch create mode 100644 target/linux/mvebu/patches-4.14/511-clk-mvebu-armada-37xx-periph-Fix-wrong-return-value-.patch create mode 100644 target/linux/mvebu/patches-4.14/512-clk-mvebu-armada-37xx-periph-Remove-unused-var-num_p.patch diff --git a/target/linux/mvebu/patches-4.14/510-clk-mvebu-armada-37xx-periph-Fix-switching-CPU-rate-.patch b/target/linux/mvebu/patches-4.14/510-clk-mvebu-armada-37xx-periph-Fix-switching-CPU-rate-.patch new file mode 100644 index 0000000000..42bfef7b7e --- /dev/null +++ b/target/linux/mvebu/patches-4.14/510-clk-mvebu-armada-37xx-periph-Fix-switching-CPU-rate-.patch @@ -0,0 +1,92 @@ +From 61c40f35f5cd6f67ccbd7319a1722eb78c815989 Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +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 + +Cc: stable@vger.kernel.org +Fixes: 2089dc33ea0e ("clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks") +Signed-off-by: Gregory CLEMENT +Signed-off-by: Stephen Boyd +--- + 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; diff --git a/target/linux/mvebu/patches-4.14/511-clk-mvebu-armada-37xx-periph-Fix-wrong-return-value-.patch b/target/linux/mvebu/patches-4.14/511-clk-mvebu-armada-37xx-periph-Fix-wrong-return-value-.patch new file mode 100644 index 0000000000..389a13a2b4 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/511-clk-mvebu-armada-37xx-periph-Fix-wrong-return-value-.patch @@ -0,0 +1,33 @@ +From 616bf80d381da13fbb392ebff06f46f946e3ee84 Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +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 +Fixes: 9818a7a4fd10 ("clk: mvebu: armada-37xx-periph: prepare cpu clk to +be used with DVFS") +Signed-off-by: Gregory CLEMENT +Signed-off-by: Stephen Boyd +--- + 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; + } + diff --git a/target/linux/mvebu/patches-4.14/512-clk-mvebu-armada-37xx-periph-Remove-unused-var-num_p.patch b/target/linux/mvebu/patches-4.14/512-clk-mvebu-armada-37xx-periph-Remove-unused-var-num_p.patch new file mode 100644 index 0000000000..874f982bd7 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/512-clk-mvebu-armada-37xx-periph-Remove-unused-var-num_p.patch @@ -0,0 +1,33 @@ +From 8927c27b32703e28041ae19bf25ea53461be83a1 Mon Sep 17 00:00:00 2001 +From: Anders Roxell +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 +Signed-off-by: Stephen Boyd +--- + 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)) {