On Mon 25 Mar 2024 at 12:09, Neil Armstrong <neil.armstrong@xxxxxxxxxx> wrote: > In order to setup the DSI clock, let's make the unused VCLK2 clock path > configuration via CCF. > > The nocache option is removed from following clocks: > - vclk2_sel > - vclk2_input > - vclk2_div > - vclk2 > - vclk_div1 > - vclk2_div2_en > - vclk2_div4_en > - vclk2_div6_en > - vclk2_div12_en > - vclk2_div2 > - vclk2_div4 > - vclk2_div6 > - vclk2_div12 > - cts_encl_sel > > vclk2 and vclk2_div uses the newly introduced vclk regmap driver > to handle the enable and reset bits. > > In order to set a rate on cts_encl via the vclk2 clock path, > the NO_REPARENT flag is set on cts_encl_sel & vclk2_sel in order > to keep CCF from selection a parent. > The parents of cts_encl_sel & vclk2_sel are expected to be defined > in DT or manually set by the display driver at some point. > > The following clock scheme is to be used for DSI: > > xtal > \_ gp0_pll_dco > \_ gp0_pll > |- vclk2_sel > | \_ vclk2_input > | \_ vclk2_div > | \_ vclk2 > | \_ vclk2_div1 > | \_ cts_encl_sel > | \_ cts_encl -> to VPU LCD Encoder > |- mipi_dsi_pxclk_sel > \_ mipi_dsi_pxclk_div > \_ mipi_dsi_pxclk -> to DSI controller > > The mipi_dsi_pxclk_div is set as bypass with a single /1 entry in div_table > in order to use the same GP0 for mipi_dsi_pxclk and vclk2_input. > > The SET_RATE_PARENT is only set on the mipi_dsi_pxclk_sel clock so the > DSI bitclock is the reference base clock to calculate the vclk2_div value > when pixel clock is set on the cts_encl endpoint. > > Signed-off-by: Neil Armstrong <neil.armstrong@xxxxxxxxxx> > --- > drivers/clk/meson/Kconfig | 1 + > drivers/clk/meson/g12a.c | 72 ++++++++++++++++++++++++++++++++++------------- > 2 files changed, 53 insertions(+), 20 deletions(-) > > diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig > index 8a9823789fa3..59a40a49f8e1 100644 > --- a/drivers/clk/meson/Kconfig > +++ b/drivers/clk/meson/Kconfig > @@ -144,6 +144,7 @@ config COMMON_CLK_G12A > select COMMON_CLK_MESON_EE_CLKC > select COMMON_CLK_MESON_CPU_DYNDIV > select COMMON_CLK_MESON_VID_PLL_DIV > + select COMMON_CLK_MESON_VCLK > select MFD_SYSCON > help > Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2 > diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c > index 90f4c6103014..083882e53b65 100644 > --- a/drivers/clk/meson/g12a.c > +++ b/drivers/clk/meson/g12a.c > @@ -22,6 +22,7 @@ > #include "clk-regmap.h" > #include "clk-cpu-dyndiv.h" > #include "vid-pll-div.h" > +#include "vclk.h" > #include "meson-eeclk.h" > #include "g12a.h" > > @@ -3165,7 +3166,7 @@ static struct clk_regmap g12a_vclk2_sel = { > .ops = &clk_regmap_mux_ops, > .parent_hws = g12a_vclk_parent_hws, > .num_parents = ARRAY_SIZE(g12a_vclk_parent_hws), > - .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, > + .flags = CLK_SET_RATE_NO_REPARENT, > }, > }; > > @@ -3193,7 +3194,6 @@ static struct clk_regmap g12a_vclk2_input = { > .ops = &clk_regmap_gate_ops, > .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_sel.hw }, > .num_parents = 1, > - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, > }, > }; > > @@ -3215,19 +3215,32 @@ static struct clk_regmap g12a_vclk_div = { > }; > > static struct clk_regmap g12a_vclk2_div = { > - .data = &(struct clk_regmap_div_data){ > - .offset = HHI_VIID_CLK_DIV, > - .shift = 0, > - .width = 8, > + .data = &(struct meson_vclk_div_data){ > + .div = { > + .reg_off = HHI_VIID_CLK_DIV, > + .shift = 0, > + .width = 8, > + }, > + .enable = { > + .reg_off = HHI_VIID_CLK_DIV, > + .shift = 16, > + .width = 1, > + }, > + .reset = { > + .reg_off = HHI_VIID_CLK_DIV, > + .shift = 17, > + .width = 1, > + }, > + .flags = CLK_DIVIDER_ROUND_CLOSEST, > }, > .hw.init = &(struct clk_init_data){ > .name = "vclk2_div", > - .ops = &clk_regmap_divider_ops, > + .ops = &meson_vclk_div_ops, > .parent_hws = (const struct clk_hw *[]) { > &g12a_vclk2_input.hw > }, > .num_parents = 1, > - .flags = CLK_GET_RATE_NOCACHE, > + .flags = CLK_SET_RATE_GATE, > }, > }; > > @@ -3246,16 +3259,24 @@ static struct clk_regmap g12a_vclk = { > }; > > static struct clk_regmap g12a_vclk2 = { > - .data = &(struct clk_regmap_gate_data){ > - .offset = HHI_VIID_CLK_CNTL, > - .bit_idx = 19, > + .data = &(struct meson_vclk_gate_data){ > + .enable = { > + .reg_off = HHI_VIID_CLK_CNTL, > + .shift = 19, > + .width = 1, > + }, > + .reset = { > + .reg_off = HHI_VIID_CLK_CNTL, > + .shift = 15, > + .width = 1, > + }, > }, > .hw.init = &(struct clk_init_data) { > .name = "vclk2", > - .ops = &clk_regmap_gate_ops, > + .ops = &meson_vclk_gate_ops, > .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_div.hw }, > .num_parents = 1, > - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, > + .flags = CLK_SET_RATE_PARENT, > }, > }; > > @@ -3339,7 +3360,7 @@ static struct clk_regmap g12a_vclk2_div1 = { > .ops = &clk_regmap_gate_ops, > .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, > .num_parents = 1, > - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, > + .flags = CLK_SET_RATE_PARENT, > }, > }; > > @@ -3353,7 +3374,7 @@ static struct clk_regmap g12a_vclk2_div2_en = { > .ops = &clk_regmap_gate_ops, > .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, > .num_parents = 1, > - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, > + .flags = CLK_SET_RATE_PARENT, > }, > }; > > @@ -3367,7 +3388,7 @@ static struct clk_regmap g12a_vclk2_div4_en = { > .ops = &clk_regmap_gate_ops, > .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, > .num_parents = 1, > - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, > + .flags = CLK_SET_RATE_PARENT, > }, > }; > > @@ -3381,7 +3402,7 @@ static struct clk_regmap g12a_vclk2_div6_en = { > .ops = &clk_regmap_gate_ops, > .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, > .num_parents = 1, > - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, > + .flags = CLK_SET_RATE_PARENT, > }, > }; > > @@ -3395,7 +3416,7 @@ static struct clk_regmap g12a_vclk2_div12_en = { > .ops = &clk_regmap_gate_ops, > .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, > .num_parents = 1, > - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, > + .flags = CLK_SET_RATE_PARENT, > }, > }; > > @@ -3461,6 +3482,7 @@ static struct clk_fixed_factor g12a_vclk2_div2 = { > &g12a_vclk2_div2_en.hw > }, > .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > }, > }; > > @@ -3474,6 +3496,7 @@ static struct clk_fixed_factor g12a_vclk2_div4 = { > &g12a_vclk2_div4_en.hw > }, > .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > }, > }; > > @@ -3487,6 +3510,7 @@ static struct clk_fixed_factor g12a_vclk2_div6 = { > &g12a_vclk2_div6_en.hw > }, > .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > }, > }; > > @@ -3500,6 +3524,7 @@ static struct clk_fixed_factor g12a_vclk2_div12 = { > &g12a_vclk2_div12_en.hw > }, > .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > }, > }; > > @@ -3561,7 +3586,7 @@ static struct clk_regmap g12a_cts_encl_sel = { > .ops = &clk_regmap_mux_ops, > .parent_hws = g12a_cts_parent_hws, > .num_parents = ARRAY_SIZE(g12a_cts_parent_hws), > - .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, > + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, > }, > }; > > @@ -3717,15 +3742,22 @@ static struct clk_regmap g12a_mipi_dsi_pxclk_sel = { > .ops = &clk_regmap_mux_ops, > .parent_hws = g12a_mipi_dsi_pxclk_parent_hws, > .num_parents = ARRAY_SIZE(g12a_mipi_dsi_pxclk_parent_hws), > - .flags = CLK_SET_RATE_NO_REPARENT, > + .flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, > }, > }; > > +/* Force as bypass by forcing a single /1 table entry, and not rely of boot value */ The comment here is not entirely accurate. The table below will actually force to only use a 1 divider on .set_rate(), not on boot, AFAICT. The boot value will stay in the register until the first call to set_rate(). Considering this is quite fragile as it is, It would be nice to prefix the updated comment with "FIXME" > +static const struct clk_div_table g12a_mipi_dsi_pxclk_div_table[] = { > + { .val = 0, .div = 1 }, > + { /* sentinel */ }, > +}; > + > static struct clk_regmap g12a_mipi_dsi_pxclk_div = { > .data = &(struct clk_regmap_div_data){ > .offset = HHI_MIPIDSI_PHY_CLK_CNTL, > .shift = 0, > .width = 7, > + .table = g12a_mipi_dsi_pxclk_div_table, > }, > .hw.init = &(struct clk_init_data){ > .name = "mipi_dsi_pxclk_div", -- Jerome