diff options
author | Tomasz Maciej Nowak <tomek_n@o2.pl> | 2019-01-13 21:30:26 +0100 |
---|---|---|
committer | Hauke Mehrtens <hauke@hauke-m.de> | 2019-01-27 00:16:14 +0100 |
commit | 7d188fb4dbdc5336cf7a802a9af9355fb69b0e97 (patch) | |
tree | 99fa66d8ef3d3c1db7c9a4fe31342349b72d9e9f /target/linux/mvebu/patches-4.14/510-clk-mvebu-armada-37xx-periph-Fix-switching-CPU-rate-.patch | |
parent | 9b1102416fff7257626fa0bcdfe2fead9f0b2aeb (diff) | |
download | upstream-7d188fb4dbdc5336cf7a802a9af9355fb69b0e97.tar.gz upstream-7d188fb4dbdc5336cf7a802a9af9355fb69b0e97.tar.bz2 upstream-7d188fb4dbdc5336cf7a802a9af9355fb69b0e97.zip |
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>
Diffstat (limited to 'target/linux/mvebu/patches-4.14/510-clk-mvebu-armada-37xx-periph-Fix-switching-CPU-rate-.patch')
-rw-r--r-- | target/linux/mvebu/patches-4.14/510-clk-mvebu-armada-37xx-periph-Fix-switching-CPU-rate-.patch | 92 |
1 files changed, 92 insertions, 0 deletions
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 <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; |