2020-04-17 18:43:06

by Martin Blumenstingl

[permalink] [raw]
Subject: [PATCH v2 0/4] clk: meson8b: updates for video clocks / resets

This is the first batch of fixes and updates for the Meson8/8b/8m2
clock controller driver.

The first patch fixes the video clock hierarchy. Special thanks to
Neil for providing a lot of details about the video clock tree!

The second and third came up while testing video output on my EC-100
(Endless Mini). This board is special because u-boot does not enable
the video outputs like most other u-boot versions do. However, this
is very useful for development because it shows (the hard way ;))
where the existing code is buggy.

The last patch is a small improvement for the VPU clock so we
utilize the glitch-free mux (on SoCs which support it) and avoid
problems by changing the "live" clock tree at runtime (with the mali
clock this resulted in system hangs/freezes).

In my opinion all of these patches - including the fixes - can go to
"next" because the relevant clock trees are still read-only.


Changes since v1 at [0]:
- updated the description in patch #1 to clarify that (it seems that)
there is no fixed pre-multiplier for the HDMI PLL (like on GXL for
example). Spotted by Jerome - thanks!
- simplified the logic for the active_low resets in patch #2 by
shortening the if ... else. Thanks to Jerome for the suggestion.


[0] https://patchwork.kernel.org/cover/11489079/


Martin Blumenstingl (4):
clk: meson: meson8b: Fix the first parent of vid_pll_in_sel
clk: meson: meson8b: Fix the polarity of the RESET_N lines
clk: meson: meson8b: Fix the vclk_div{1,2,4,6,12}_en gate bits
clk: meson: meson8b: Make the CCF use the glitch-free VPU mux

drivers/clk/meson/meson8b.c | 105 +++++++++++++++++++++++++-----------
1 file changed, 73 insertions(+), 32 deletions(-)

--
2.26.1


2020-04-17 18:43:09

by Martin Blumenstingl

[permalink] [raw]
Subject: [PATCH v2 3/4] clk: meson: meson8b: Fix the vclk_div{1,2,4,6,12}_en gate bits

The DIV{1,2,4,6,12}_EN bits are actually located in HHI_VID_CLK_CNTL
register:
- HHI_VID_CLK_CNTL[0] = DIV1_EN
- HHI_VID_CLK_CNTL[1] = DIV2_EN
- HHI_VID_CLK_CNTL[2] = DIV4_EN
- HHI_VID_CLK_CNTL[3] = DIV6_EN
- HHI_VID_CLK_CNTL[4] = DIV12_EN

Update the bits accordingly so we will enable the bits in the correct
register once we switch these clocks to be mutable.

Fixes: 6cb57c678bb70e ("clk: meson: meson8b: add the read-only video clock trees")
Signed-off-by: Martin Blumenstingl <[email protected]>
---
drivers/clk/meson/meson8b.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 1dec8d5404a1..6d1727e62b55 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -1213,7 +1213,7 @@ static struct clk_regmap meson8b_vclk_in_en = {

static struct clk_regmap meson8b_vclk_div1_gate = {
.data = &(struct clk_regmap_gate_data){
- .offset = HHI_VID_CLK_DIV,
+ .offset = HHI_VID_CLK_CNTL,
.bit_idx = 0,
},
.hw.init = &(struct clk_init_data){
@@ -1243,7 +1243,7 @@ static struct clk_fixed_factor meson8b_vclk_div2_div = {

static struct clk_regmap meson8b_vclk_div2_div_gate = {
.data = &(struct clk_regmap_gate_data){
- .offset = HHI_VID_CLK_DIV,
+ .offset = HHI_VID_CLK_CNTL,
.bit_idx = 1,
},
.hw.init = &(struct clk_init_data){
@@ -1273,7 +1273,7 @@ static struct clk_fixed_factor meson8b_vclk_div4_div = {

static struct clk_regmap meson8b_vclk_div4_div_gate = {
.data = &(struct clk_regmap_gate_data){
- .offset = HHI_VID_CLK_DIV,
+ .offset = HHI_VID_CLK_CNTL,
.bit_idx = 2,
},
.hw.init = &(struct clk_init_data){
@@ -1303,7 +1303,7 @@ static struct clk_fixed_factor meson8b_vclk_div6_div = {

static struct clk_regmap meson8b_vclk_div6_div_gate = {
.data = &(struct clk_regmap_gate_data){
- .offset = HHI_VID_CLK_DIV,
+ .offset = HHI_VID_CLK_CNTL,
.bit_idx = 3,
},
.hw.init = &(struct clk_init_data){
@@ -1333,7 +1333,7 @@ static struct clk_fixed_factor meson8b_vclk_div12_div = {

static struct clk_regmap meson8b_vclk_div12_div_gate = {
.data = &(struct clk_regmap_gate_data){
- .offset = HHI_VID_CLK_DIV,
+ .offset = HHI_VID_CLK_CNTL,
.bit_idx = 4,
},
.hw.init = &(struct clk_init_data){
--
2.26.1

2020-04-17 18:43:15

by Martin Blumenstingl

[permalink] [raw]
Subject: [PATCH v2 4/4] clk: meson: meson8b: Make the CCF use the glitch-free VPU mux

The "vpu_0" or "vpu_1" clock trees should not be updated while the
clock is running. Enforce this by setting CLK_SET_RATE_GATE on the
"vpu_0" and "vpu_1" gates. This makes the CCF switch to the "vpu_1"
tree when "vpu_0" is currently active and vice versa, which is exactly
what the vendor driver does when updating the frequency of the VPU
clock.

Signed-off-by: Martin Blumenstingl <[email protected]>
---
drivers/clk/meson/meson8b.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 6d1727e62b55..811af1c11456 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -2063,7 +2063,7 @@ static struct clk_regmap meson8b_vpu_0 = {
&meson8b_vpu_0_div.hw
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
+ .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
},
};

@@ -2134,10 +2134,18 @@ static struct clk_regmap meson8b_vpu_1 = {
&meson8b_vpu_1_div.hw
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
+ .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
},
};

+/*
+ * The VPU clock has two two identical clock trees (vpu_0 and vpu_1)
+ * muxed by a glitch-free switch on Meson8b and Meson8m2. The CCF can
+ * actually manage this glitch-free mux because it does top-to-bottom
+ * updates the each clock tree and switches to the "inactive" one when
+ * CLK_SET_RATE_GATE is set.
+ * Meson8 only has vpu_0 and no glitch-free mux.
+ */
static struct clk_regmap meson8b_vpu = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VPU_CLK_CNTL,
@@ -2152,7 +2160,7 @@ static struct clk_regmap meson8b_vpu = {
&meson8b_vpu_1.hw,
},
.num_parents = 2,
- .flags = CLK_SET_RATE_NO_REPARENT,
+ .flags = CLK_SET_RATE_PARENT,
},
};

--
2.26.1

2020-04-17 18:44:05

by Martin Blumenstingl

[permalink] [raw]
Subject: [PATCH v2 2/4] clk: meson: meson8b: Fix the polarity of the RESET_N lines

CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_POST and
CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_PRE are active low. This means:
- asserting them requires setting the register value to 0
- de-asserting them requires setting the register value to 1

Set the register value accordingly for these two reset lines by setting
the inverted the register value compared to all other reset lines.

Fixes: 189621726bc2f6 ("clk: meson: meson8b: register the built-in reset controller")
Signed-off-by: Martin Blumenstingl <[email protected]>
---
drivers/clk/meson/meson8b.c | 79 ++++++++++++++++++++++++++-----------
1 file changed, 56 insertions(+), 23 deletions(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 90d284ffc780..1dec8d5404a1 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -3506,54 +3506,87 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
static const struct meson8b_clk_reset_line {
u32 reg;
u8 bit_idx;
+ bool active_low;
} meson8b_clk_reset_bits[] = {
[CLKC_RESET_L2_CACHE_SOFT_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 30
+ .reg = HHI_SYS_CPU_CLK_CNTL0,
+ .bit_idx = 30,
+ .active_low = false,
},
[CLKC_RESET_AXI_64_TO_128_BRIDGE_A5_SOFT_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 29
+ .reg = HHI_SYS_CPU_CLK_CNTL0,
+ .bit_idx = 29,
+ .active_low = false,
},
[CLKC_RESET_SCU_SOFT_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 28
+ .reg = HHI_SYS_CPU_CLK_CNTL0,
+ .bit_idx = 28,
+ .active_low = false,
},
[CLKC_RESET_CPU3_SOFT_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 27
+ .reg = HHI_SYS_CPU_CLK_CNTL0,
+ .bit_idx = 27,
+ .active_low = false,
},
[CLKC_RESET_CPU2_SOFT_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 26
+ .reg = HHI_SYS_CPU_CLK_CNTL0,
+ .bit_idx = 26,
+ .active_low = false,
},
[CLKC_RESET_CPU1_SOFT_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 25
+ .reg = HHI_SYS_CPU_CLK_CNTL0,
+ .bit_idx = 25,
+ .active_low = false,
},
[CLKC_RESET_CPU0_SOFT_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 24
+ .reg = HHI_SYS_CPU_CLK_CNTL0,
+ .bit_idx = 24,
+ .active_low = false,
},
[CLKC_RESET_A5_GLOBAL_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 18
+ .reg = HHI_SYS_CPU_CLK_CNTL0,
+ .bit_idx = 18,
+ .active_low = false,
},
[CLKC_RESET_A5_AXI_SOFT_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 17
+ .reg = HHI_SYS_CPU_CLK_CNTL0,
+ .bit_idx = 17,
+ .active_low = false,
},
[CLKC_RESET_A5_ABP_SOFT_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 16
+ .reg = HHI_SYS_CPU_CLK_CNTL0,
+ .bit_idx = 16,
+ .active_low = false,
},
[CLKC_RESET_AXI_64_TO_128_BRIDGE_MMC_SOFT_RESET] = {
- .reg = HHI_SYS_CPU_CLK_CNTL1, .bit_idx = 30
+ .reg = HHI_SYS_CPU_CLK_CNTL1,
+ .bit_idx = 30,
+ .active_low = false,
},
[CLKC_RESET_VID_CLK_CNTL_SOFT_RESET] = {
- .reg = HHI_VID_CLK_CNTL, .bit_idx = 15
+ .reg = HHI_VID_CLK_CNTL,
+ .bit_idx = 15,
+ .active_low = false,
},
[CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_POST] = {
- .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 7
+ .reg = HHI_VID_DIVIDER_CNTL,
+ .bit_idx = 7,
+ .active_low = false,
},
[CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_PRE] = {
- .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 3
+ .reg = HHI_VID_DIVIDER_CNTL,
+ .bit_idx = 3,
+ .active_low = false,
},
[CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_POST] = {
- .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 1
+ .reg = HHI_VID_DIVIDER_CNTL,
+ .bit_idx = 1,
+ .active_low = true,
},
[CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_PRE] = {
- .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 0
+ .reg = HHI_VID_DIVIDER_CNTL,
+ .bit_idx = 0,
+ .active_low = true,
},
};

@@ -3562,22 +3595,22 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
{
struct meson8b_clk_reset *meson8b_clk_reset =
container_of(rcdev, struct meson8b_clk_reset, reset);
- unsigned long flags;
const struct meson8b_clk_reset_line *reset;
+ unsigned int value = 0;
+ unsigned long flags;

if (id >= ARRAY_SIZE(meson8b_clk_reset_bits))
return -EINVAL;

reset = &meson8b_clk_reset_bits[id];

+ if (assert != reset->active_low)
+ value = BIT(reset->bit_idx);
+
spin_lock_irqsave(&meson_clk_lock, flags);

- if (assert)
- regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
- BIT(reset->bit_idx), BIT(reset->bit_idx));
- else
- regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
- BIT(reset->bit_idx), 0);
+ regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
+ BIT(reset->bit_idx), value);

spin_unlock_irqrestore(&meson_clk_lock, flags);

--
2.26.1

2020-04-17 18:45:24

by Martin Blumenstingl

[permalink] [raw]
Subject: [PATCH v2 1/4] clk: meson: meson8b: Fix the first parent of vid_pll_in_sel

Use hdmi_pll_lvds_out as parent of the vid_pll_in_sel clock. It's not
easy to see that the vendor kernel does the same, but it actually does.
meson_clk_pll_ops in mainline still cannot fully recalculate all rates
from the HDMI PLL registers because some register bits (at the time of
writing it's unknown which bits are used for this) double the HDMI PLL
output rate (compared to simply considering M, N and FRAC) for some (but
not all) PLL settings.

Update the vid_pll_in_sel parent so our clock calculation works for
simple clock settings like the CVBS output (where no rate doubling is
going on). The PLL ops need to be fixed later on for more complex clock
settings (all HDMI rates).

Fixes: 6cb57c678bb70 ("clk: meson: meson8b: add the read-only video clock trees")
Suggested-by: Neil Armstrong <[email protected]>
Signed-off-by: Martin Blumenstingl <[email protected]>
---
drivers/clk/meson/meson8b.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 7c55c695cbae..90d284ffc780 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -1077,7 +1077,7 @@ static struct clk_regmap meson8b_vid_pll_in_sel = {
* Meson8m2: vid2_pll
*/
.parent_hws = (const struct clk_hw *[]) {
- &meson8b_hdmi_pll_dco.hw
+ &meson8b_hdmi_pll_lvds_out.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
--
2.26.1

2020-04-29 11:46:56

by Jerome Brunet

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] clk: meson8b: updates for video clocks / resets


On Fri 17 Apr 2020 at 20:41, Martin Blumenstingl <[email protected]> wrote:

> This is the first batch of fixes and updates for the Meson8/8b/8m2
> clock controller driver.
>
> The first patch fixes the video clock hierarchy. Special thanks to
> Neil for providing a lot of details about the video clock tree!
>
> The second and third came up while testing video output on my EC-100
> (Endless Mini). This board is special because u-boot does not enable
> the video outputs like most other u-boot versions do. However, this
> is very useful for development because it shows (the hard way ;))
> where the existing code is buggy.
>
> The last patch is a small improvement for the VPU clock so we
> utilize the glitch-free mux (on SoCs which support it) and avoid
> problems by changing the "live" clock tree at runtime (with the mali
> clock this resulted in system hangs/freezes).
>
> In my opinion all of these patches - including the fixes - can go to
> "next" because the relevant clock trees are still read-only.
>
>
> Changes since v1 at [0]:
> - updated the description in patch #1 to clarify that (it seems that)
> there is no fixed pre-multiplier for the HDMI PLL (like on GXL for
> example). Spotted by Jerome - thanks!
> - simplified the logic for the active_low resets in patch #2 by
> shortening the if ... else. Thanks to Jerome for the suggestion.
>
>
> [0] https://patchwork.kernel.org/cover/11489079/
>
>
> Martin Blumenstingl (4):
> clk: meson: meson8b: Fix the first parent of vid_pll_in_sel
> clk: meson: meson8b: Fix the polarity of the RESET_N lines
> clk: meson: meson8b: Fix the vclk_div{1,2,4,6,12}_en gate bits
> clk: meson: meson8b: Make the CCF use the glitch-free VPU mux

Applied, Thx

>
> drivers/clk/meson/meson8b.c | 105 +++++++++++++++++++++++++-----------
> 1 file changed, 73 insertions(+), 32 deletions(-)