2020-03-30 22:12:10

by Martin Blumenstingl

[permalink] [raw]
Subject: [RFC v1 1/5] clk: meson: gxbb: Prepare the GPU clock tree to change at runtime

The "mali_0" or "mali_1" clock trees should not be updated while the
clock is running. Enforce this by setting CLK_SET_RATE_GATE on the
"mali_0" and "mali_1" gates. This makes the CCF switch to the "mali_1"
tree when "mali_0" is currently active and vice versa, which is exactly
what the vendor driver does when updating the frequency of the mali
clock.
Also populate set_rate requests from the divider to the mux so the GPU
clock frequency can be updated at runtime (which will be required for
GPU DVFS).

Signed-off-by: Martin Blumenstingl <[email protected]>
---
drivers/clk/meson/gxbb.c | 40 ++++++++++++++++++++++------------------
1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 5fd6a574f8c3..0a68af6eec3d 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -957,7 +957,9 @@ static struct clk_regmap gxbb_sar_adc_clk = {

/*
* The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
- * muxed by a glitch-free switch.
+ * muxed by a glitch-free switch. The CCF can 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.
*/

static const struct clk_parent_data gxbb_mali_0_1_parent_data[] = {
@@ -980,14 +982,15 @@ static struct clk_regmap gxbb_mali_0_sel = {
.hw.init = &(struct clk_init_data){
.name = "mali_0_sel",
.ops = &clk_regmap_mux_ops,
- /*
- * bits 10:9 selects from 8 possible parents:
- * xtal, gp0_pll, mpll2, mpll1, fclk_div7,
- * fclk_div4, fclk_div3, fclk_div5
- */
.parent_data = gxbb_mali_0_1_parent_data,
.num_parents = 8,
- .flags = CLK_SET_RATE_NO_REPARENT,
+ /*
+ * Don't request the parent to change the rate because
+ * all GPU frequencies can be derived from the fclk_*
+ * clocks and one special GP0_PLL setting. This is
+ * important because we need the MPLL clocks for audio.
+ */
+ .flags = 0,
},
};

@@ -1004,7 +1007,7 @@ static struct clk_regmap gxbb_mali_0_div = {
&gxbb_mali_0_sel.hw
},
.num_parents = 1,
- .flags = CLK_SET_RATE_NO_REPARENT,
+ .flags = CLK_SET_RATE_PARENT,
},
};

@@ -1020,7 +1023,7 @@ static struct clk_regmap gxbb_mali_0 = {
&gxbb_mali_0_div.hw
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
+ .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
},
};

@@ -1033,14 +1036,15 @@ static struct clk_regmap gxbb_mali_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "mali_1_sel",
.ops = &clk_regmap_mux_ops,
- /*
- * bits 10:9 selects from 8 possible parents:
- * xtal, gp0_pll, mpll2, mpll1, fclk_div7,
- * fclk_div4, fclk_div3, fclk_div5
- */
.parent_data = gxbb_mali_0_1_parent_data,
.num_parents = 8,
- .flags = CLK_SET_RATE_NO_REPARENT,
+ /*
+ * Don't request the parent to change the rate because
+ * all GPU frequencies can be derived from the fclk_*
+ * clocks and one special GP0_PLL setting. This is
+ * important because we need the MPLL clocks for audio.
+ */
+ .flags = 0,
},
};

@@ -1057,7 +1061,7 @@ static struct clk_regmap gxbb_mali_1_div = {
&gxbb_mali_1_sel.hw
},
.num_parents = 1,
- .flags = CLK_SET_RATE_NO_REPARENT,
+ .flags = CLK_SET_RATE_PARENT,
},
};

@@ -1073,7 +1077,7 @@ static struct clk_regmap gxbb_mali_1 = {
&gxbb_mali_1_div.hw
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
+ .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
},
};

@@ -1093,7 +1097,7 @@ static struct clk_regmap gxbb_mali = {
.ops = &clk_regmap_mux_ops,
.parent_hws = gxbb_mali_parent_hws,
.num_parents = 2,
- .flags = CLK_SET_RATE_NO_REPARENT,
+ .flags = CLK_SET_RATE_PARENT,
},
};

--
2.26.0