Commit 6e77b267 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk fixes from Stephen Boyd:
 "One more round of updates for problems seen this -rc series. Drivers
  fixes are:

   - Amlogic Meson audio divider fix and CPU clk critical marking

   - Qualcomm multimedia GDSC marked as 'always on' to keep display
     working

   - Aspeed fixes for critical clks, resets causing clks to stay
     disabled, and an incorrect HPLL frequency calculation

   - Marvell Armada 3700 cpu clks would undervolt when switching from
     low frequencies to high frequencies because the voltage didn't
     stabilize in time so now we switch to an intermediate frequency

  Plus we have a core framework thinko that messed up the debugfs flag
  printing logic to make it not very useful"

* tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux:
  clk: aspeed: Support HPLL strapping on ast2400
  clk: mvebu: armada-37xx-periph: Fix switching CPU rate from 300Mhz to 1.2GHz
  clk: aspeed: Mark bclk (PCIe) and dclk (VGA) as critical
  clk/mmcc-msm8996: Make mmagic_bimc_gdsc ALWAYS_ON
  clk: aspeed: Treat a gate in reset as disabled
  clk: Really show symbolic clock flags in debugfs
  clk: qcom: gcc-msm8996: Disable halt check on UFS tx clock
  clk: meson: audio-divider is one based
  clk: meson-gxbb: set fclk_div2 as CLK_IS_CRITICAL
parents 5c61ef1b 565b9937
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#define ASPEED_MPLL_PARAM 0x20 #define ASPEED_MPLL_PARAM 0x20
#define ASPEED_HPLL_PARAM 0x24 #define ASPEED_HPLL_PARAM 0x24
#define AST2500_HPLL_BYPASS_EN BIT(20) #define AST2500_HPLL_BYPASS_EN BIT(20)
#define AST2400_HPLL_STRAPPED BIT(18) #define AST2400_HPLL_PROGRAMMED BIT(18)
#define AST2400_HPLL_BYPASS_EN BIT(17) #define AST2400_HPLL_BYPASS_EN BIT(17)
#define ASPEED_MISC_CTRL 0x2c #define ASPEED_MISC_CTRL 0x2c
#define UART_DIV13_EN BIT(12) #define UART_DIV13_EN BIT(12)
...@@ -91,8 +91,8 @@ static const struct aspeed_gate_data aspeed_gates[] = { ...@@ -91,8 +91,8 @@ static const struct aspeed_gate_data aspeed_gates[] = {
[ASPEED_CLK_GATE_GCLK] = { 1, 7, "gclk-gate", NULL, 0 }, /* 2D engine */ [ASPEED_CLK_GATE_GCLK] = { 1, 7, "gclk-gate", NULL, 0 }, /* 2D engine */
[ASPEED_CLK_GATE_MCLK] = { 2, -1, "mclk-gate", "mpll", CLK_IS_CRITICAL }, /* SDRAM */ [ASPEED_CLK_GATE_MCLK] = { 2, -1, "mclk-gate", "mpll", CLK_IS_CRITICAL }, /* SDRAM */
[ASPEED_CLK_GATE_VCLK] = { 3, 6, "vclk-gate", NULL, 0 }, /* Video Capture */ [ASPEED_CLK_GATE_VCLK] = { 3, 6, "vclk-gate", NULL, 0 }, /* Video Capture */
[ASPEED_CLK_GATE_BCLK] = { 4, 8, "bclk-gate", "bclk", 0 }, /* PCIe/PCI */ [ASPEED_CLK_GATE_BCLK] = { 4, 8, "bclk-gate", "bclk", CLK_IS_CRITICAL }, /* PCIe/PCI */
[ASPEED_CLK_GATE_DCLK] = { 5, -1, "dclk-gate", NULL, 0 }, /* DAC */ [ASPEED_CLK_GATE_DCLK] = { 5, -1, "dclk-gate", NULL, CLK_IS_CRITICAL }, /* DAC */
[ASPEED_CLK_GATE_REFCLK] = { 6, -1, "refclk-gate", "clkin", CLK_IS_CRITICAL }, [ASPEED_CLK_GATE_REFCLK] = { 6, -1, "refclk-gate", "clkin", CLK_IS_CRITICAL },
[ASPEED_CLK_GATE_USBPORT2CLK] = { 7, 3, "usb-port2-gate", NULL, 0 }, /* USB2.0 Host port 2 */ [ASPEED_CLK_GATE_USBPORT2CLK] = { 7, 3, "usb-port2-gate", NULL, 0 }, /* USB2.0 Host port 2 */
[ASPEED_CLK_GATE_LCLK] = { 8, 5, "lclk-gate", NULL, 0 }, /* LPC */ [ASPEED_CLK_GATE_LCLK] = { 8, 5, "lclk-gate", NULL, 0 }, /* LPC */
...@@ -212,9 +212,22 @@ static int aspeed_clk_is_enabled(struct clk_hw *hw) ...@@ -212,9 +212,22 @@ static int aspeed_clk_is_enabled(struct clk_hw *hw)
{ {
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw); struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
u32 clk = BIT(gate->clock_idx); u32 clk = BIT(gate->clock_idx);
u32 rst = BIT(gate->reset_idx);
u32 enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk; u32 enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk;
u32 reg; u32 reg;
/*
* If the IP is in reset, treat the clock as not enabled,
* this happens with some clocks such as the USB one when
* coming from cold reset. Without this, aspeed_clk_enable()
* will fail to lift the reset.
*/
if (gate->reset_idx >= 0) {
regmap_read(gate->map, ASPEED_RESET_CTRL, &reg);
if (reg & rst)
return 0;
}
regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, &reg); regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, &reg);
return ((reg & clk) == enval) ? 1 : 0; return ((reg & clk) == enval) ? 1 : 0;
...@@ -565,29 +578,45 @@ builtin_platform_driver(aspeed_clk_driver); ...@@ -565,29 +578,45 @@ builtin_platform_driver(aspeed_clk_driver);
static void __init aspeed_ast2400_cc(struct regmap *map) static void __init aspeed_ast2400_cc(struct regmap *map)
{ {
struct clk_hw *hw; struct clk_hw *hw;
u32 val, freq, div; u32 val, div, clkin, hpll;
const u16 hpll_rates[][4] = {
{384, 360, 336, 408},
{400, 375, 350, 425},
};
int rate;
/* /*
* CLKIN is the crystal oscillator, 24, 48 or 25MHz selected by * CLKIN is the crystal oscillator, 24, 48 or 25MHz selected by
* strapping * strapping
*/ */
regmap_read(map, ASPEED_STRAP, &val); regmap_read(map, ASPEED_STRAP, &val);
if (val & CLKIN_25MHZ_EN) rate = (val >> 8) & 3;
freq = 25000000; if (val & CLKIN_25MHZ_EN) {
else if (val & AST2400_CLK_SOURCE_SEL) clkin = 25000000;
freq = 48000000; hpll = hpll_rates[1][rate];
else } else if (val & AST2400_CLK_SOURCE_SEL) {
freq = 24000000; clkin = 48000000;
hw = clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, freq); hpll = hpll_rates[0][rate];
pr_debug("clkin @%u MHz\n", freq / 1000000); } else {
clkin = 24000000;
hpll = hpll_rates[0][rate];
}
hw = clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, clkin);
pr_debug("clkin @%u MHz\n", clkin / 1000000);
/* /*
* High-speed PLL clock derived from the crystal. This the CPU clock, * High-speed PLL clock derived from the crystal. This the CPU clock,
* and we assume that it is enabled * and we assume that it is enabled. It can be configured through the
* HPLL_PARAM register, or set to a specified frequency by strapping.
*/ */
regmap_read(map, ASPEED_HPLL_PARAM, &val); regmap_read(map, ASPEED_HPLL_PARAM, &val);
WARN(val & AST2400_HPLL_STRAPPED, "hpll is strapped not configured"); if (val & AST2400_HPLL_PROGRAMMED)
aspeed_clk_data->hws[ASPEED_CLK_HPLL] = aspeed_ast2400_calc_pll("hpll", val); hw = aspeed_ast2400_calc_pll("hpll", val);
else
hw = clk_hw_register_fixed_rate(NULL, "hpll", "clkin", 0,
hpll * 1000000);
aspeed_clk_data->hws[ASPEED_CLK_HPLL] = hw;
/* /*
* Strap bits 11:10 define the CPU/AHB clock frequency ratio (aka HCLK) * Strap bits 11:10 define the CPU/AHB clock frequency ratio (aka HCLK)
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/stringify.h>
#include "clk.h" #include "clk.h"
...@@ -2559,7 +2558,7 @@ static const struct { ...@@ -2559,7 +2558,7 @@ static const struct {
unsigned long flag; unsigned long flag;
const char *name; const char *name;
} clk_flags[] = { } clk_flags[] = {
#define ENTRY(f) { f, __stringify(f) } #define ENTRY(f) { f, #f }
ENTRY(CLK_SET_RATE_GATE), ENTRY(CLK_SET_RATE_GATE),
ENTRY(CLK_SET_PARENT_GATE), ENTRY(CLK_SET_PARENT_GATE),
ENTRY(CLK_SET_RATE_PARENT), ENTRY(CLK_SET_RATE_PARENT),
......
...@@ -51,7 +51,7 @@ static unsigned long audio_divider_recalc_rate(struct clk_hw *hw, ...@@ -51,7 +51,7 @@ static unsigned long audio_divider_recalc_rate(struct clk_hw *hw,
struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk); struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk);
unsigned long divider; unsigned long divider;
divider = meson_parm_read(clk->map, &adiv->div); divider = meson_parm_read(clk->map, &adiv->div) + 1;
return DIV_ROUND_UP_ULL((u64)parent_rate, divider); return DIV_ROUND_UP_ULL((u64)parent_rate, divider);
} }
......
...@@ -498,6 +498,7 @@ static struct clk_regmap gxbb_fclk_div2 = { ...@@ -498,6 +498,7 @@ static struct clk_regmap gxbb_fclk_div2 = {
.ops = &clk_regmap_gate_ops, .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div2_div" }, .parent_names = (const char *[]){ "fclk_div2_div" },
.num_parents = 1, .num_parents = 1,
.flags = CLK_IS_CRITICAL,
}, },
}; };
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#define CLK_SEL 0x10 #define CLK_SEL 0x10
#define CLK_DIS 0x14 #define CLK_DIS 0x14
#define ARMADA_37XX_DVFS_LOAD_1 1
#define LOAD_LEVEL_NR 4 #define LOAD_LEVEL_NR 4
#define ARMADA_37XX_NB_L0L1 0x18 #define ARMADA_37XX_NB_L0L1 0x18
...@@ -507,6 +508,40 @@ static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate, ...@@ -507,6 +508,40 @@ static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
return -EINVAL; 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, static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate) unsigned long parent_rate)
{ {
...@@ -537,6 +572,9 @@ static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -537,6 +572,9 @@ static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
*/ */
reg = ARMADA_37XX_NB_CPU_LOAD; reg = ARMADA_37XX_NB_CPU_LOAD;
mask = ARMADA_37XX_NB_CPU_LOAD_MASK; mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
clk_pm_cpu_set_rate_wa(rate, base);
regmap_update_bits(base, reg, mask, load_level); regmap_update_bits(base, reg, mask, load_level);
return rate; return rate;
......
...@@ -2781,6 +2781,7 @@ static struct clk_branch gcc_ufs_rx_cfg_clk = { ...@@ -2781,6 +2781,7 @@ static struct clk_branch gcc_ufs_rx_cfg_clk = {
static struct clk_branch gcc_ufs_tx_symbol_0_clk = { static struct clk_branch gcc_ufs_tx_symbol_0_clk = {
.halt_reg = 0x75018, .halt_reg = 0x75018,
.halt_check = BRANCH_HALT_SKIP,
.clkr = { .clkr = {
.enable_reg = 0x75018, .enable_reg = 0x75018,
.enable_mask = BIT(0), .enable_mask = BIT(0),
......
...@@ -2910,6 +2910,7 @@ static struct gdsc mmagic_bimc_gdsc = { ...@@ -2910,6 +2910,7 @@ static struct gdsc mmagic_bimc_gdsc = {
.name = "mmagic_bimc", .name = "mmagic_bimc",
}, },
.pwrsts = PWRSTS_OFF_ON, .pwrsts = PWRSTS_OFF_ON,
.flags = ALWAYS_ON,
}; };
static struct gdsc mmagic_video_gdsc = { static struct gdsc mmagic_video_gdsc = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment