clk: qcom: Allow clk_set_parent() to work on display clocks
Subsystems (3)
PATCH 1/1 clk: qcom: Allow clk_set_parent() to work on display clocks
Sometimes the display driver may want to change the parent PLL of the display clocks (byte and pixel clocks) depending on the use-case. Currently the parent is fixed by means of having a frequency table with one entry that chooses a particular parent. Remove this restriction and use the parent the clock is configured for in the hardware during clk_set_rate(). This requires consumers to rely on the default parent or to configure the parent with clk_set_parent()/assigned-clock-parents on the clocks before calling clk_set_rate().
--- drivers/clk/qcom/clk-rcg.h | 1 + drivers/clk/qcom/clk-rcg2.c | 91 +++++++++++++++++++++++++++++++++++++---- drivers/clk/qcom/gcc-msm8916.c | 14 +------ drivers/clk/qcom/mmcc-apq8084.c | 18 +------- drivers/clk/qcom/mmcc-msm8974.c | 11 +---- 5 files changed, 89 insertions(+), 46 deletions(-)
drivers/clk/qcom/clk-rcg.h +1 -0
@@ -171,6 +171,7 @@ struct clk_rcg2 {extern const struct clk_ops clk_rcg2_ops;extern const struct clk_ops clk_edp_pixel_ops;extern const struct clk_ops clk_byte_ops; +extern const struct clk_ops clk_byte2_ops;extern const struct clk_ops clk_pixel_ops;#endif
drivers/clk/qcom/clk-rcg2.c +83 -8
122 lines not on this page · raw message
drivers/clk/qcom/gcc-msm8916.c +1 -13
@@ -906,21 +906,15 @@ static struct clk_rcg2 gp3_clk_src = { }, }; -static struct freq_tbl ftbl_gcc_mdss_byte0_clk[] = { - { .src =P_DSI0_PHYPLL_BYTE }, - { } -}; -static struct clk_rcg2 byte0_clk_src = { .cmd_rcgr =0x4d044 , .hid_width =5 , .parent_map = gcc_xo_gpll0a_dsibyte_map, - .freq_tbl = ftbl_gcc_mdss_byte0_clk, .clkr.hw.init = &(struct clk_init_data ){ .name ="byte0_clk_src" , .parent_names = gcc_xo_gpll0a_dsibyte, .num_parents =3 , - .ops = &clk_byte_ops, + .ops = &clk_byte2_ops, .flags =CLK_SET_RATE_PARENT , }, };
@@ -968,17 +962,11 @@ static struct clk_rcg2 mdp_clk_src = { }, }; -static struct freq_tbl ftbl_gcc_mdss_pclk[] = { - { .src =P_DSI0_PHYPLL_DSI }, - { } -}; -static struct clk_rcg2 pclk0_clk_src = { .cmd_rcgr =0x4d000 , .mnd_width =8 , .hid_width =5 , .parent_map = gcc_xo_gpll0a_dsiphy_map, - .freq_tbl = ftbl_gcc_mdss_pclk, .clkr.hw.init = &(struct clk_init_data ){ .name ="pclk0_clk_src" , .parent_names = gcc_xo_gpll0a_dsiphy,
drivers/clk/qcom/mmcc-apq8084.c +2 -16
@@ -571,17 +571,11 @@ static struct clk_rcg2 jpeg2_clk_src = { }, }; -static struct freq_tbl pixel_freq_tbl[] = { - { .src =P_DSI0PLL }, - { } -}; -static struct clk_rcg2 pclk0_clk_src = { .cmd_rcgr =0x2000 , .mnd_width =8 , .hid_width =5 , .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, - .freq_tbl = pixel_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="pclk0_clk_src" , .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
@@ -596,7 +590,6 @@ static struct clk_rcg2 pclk1_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, - .freq_tbl = pixel_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="pclk1_clk_src" , .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
@@ -844,21 +837,15 @@ static struct clk_rcg2 cpp_clk_src = { }, }; -static struct freq_tbl byte_freq_tbl[] = { - { .src =P_DSI0PLL_BYTE }, - { } -}; -static struct clk_rcg2 byte0_clk_src = { .cmd_rcgr =0x2120 , .hid_width =5 , .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map, - .freq_tbl = byte_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="byte0_clk_src" , .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, .num_parents =6 , - .ops = &clk_byte_ops, + .ops = &clk_byte2_ops, .flags =CLK_SET_RATE_PARENT , }, };
@@ -867,12 +854,11 @@ static struct clk_rcg2 byte1_clk_src = { .cmd_rcgr = 0x2140, .hid_width = 5, .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map, - .freq_tbl = byte_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="byte1_clk_src" , .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, .num_parents =6 , - .ops = &clk_byte_ops, + .ops = &clk_byte2_ops, .flags =CLK_SET_RATE_PARENT , }, };
drivers/clk/qcom/mmcc-msm8974.c +2 -9
@@ -522,17 +522,11 @@ static struct clk_rcg2 jpeg2_clk_src = { }, }; -static struct freq_tbl pixel_freq_tbl[] = { - { .src =P_DSI0PLL }, - { } -}; -static struct clk_rcg2 pclk0_clk_src = { .cmd_rcgr =0x2000 , .mnd_width =8 , .hid_width =5 , .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, - .freq_tbl = pixel_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="pclk0_clk_src" , .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
@@ -547,7 +541,6 @@ static struct clk_rcg2 pclk1_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, - .freq_tbl = pixel_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="pclk1_clk_src" , .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
@@ -785,7 +778,7 @@ static struct clk_rcg2 byte0_clk_src = { .name = "byte0_clk_src", .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, .num_parents = 6, - .ops = &clk_byte_ops, + .ops = &clk_byte2_ops, .flags = CLK_SET_RATE_PARENT, }, };
@@ -799,7 +792,7 @@ static struct clk_rcg2 byte1_clk_src = { .name = "byte1_clk_src", .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, .num_parents = 6, - .ops = &clk_byte_ops, + .ops = &clk_byte2_ops, .flags = CLK_SET_RATE_PARENT, }, };
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Quoted 9 lines · Stephen Boyd
Sometimes the display driver may want to change the parent PLL of the display clocks (byte and pixel clocks) depending on the use-case. Currently the parent is fixed by means of having a frequency table with one entry that chooses a particular parent. Remove this restriction and use the parent the clock is configured for in the hardware during
clk_set_rate(). This requires consumers to rely on the default parent or to configure the parent with clk_set_parent()/assigned-clock-parents on the clocks before callingclk_set_rate().
Quoted 315 lines
Cc Archit Taneja <[email protected]>Cc Hai Li <[email protected]>Signed-off-by Stephen Boyd <[email protected]>--- drivers/clk/qcom/clk-rcg.h | 1 + drivers/clk/qcom/clk-rcg2.c | 91 +++++++++++++++++++++++++++++++++++++---- drivers/clk/qcom/gcc-msm8916.c | 14 +------ drivers/clk/qcom/mmcc-apq8084.c | 18 +------- drivers/clk/qcom/mmcc-msm8974.c | 11 +---- 5 files changed, 89 insertions(+), 46 deletions(-)drivers/clk/qcom/clk-rcg.h +1
-0@@ -171,6 +171,7 @@ struct clk_rcg2 {extern const struct clk_ops clk_rcg2_ops;extern const struct clk_ops clk_edp_pixel_ops;extern const struct clk_ops clk_byte_ops; +extern const struct clk_ops clk_byte2_ops;extern const struct clk_ops clk_pixel_ops;#endif drivers/clk/qcom/clk-rcg2.c +83
-8@@ -485,6 +485,76 @@ const struct clk_ops clk_byte_ops = { };EXPORT_SYMBOL_GPL (clk_byte_ops); +static int clk_byte2_determine_rate (struct clk_hw *hw, +struct clk_rate_request *req) +{ +struct clk_rcg2 *rcg =to_clk_rcg2 (hw); +unsigned long parent_rate, div; +u32 mask =BIT (rcg->hid_width) -1 ; +struct clk_hw *p; +unsigned long rate = req->rate; + +if (rate ==0 ) +return -EINVAL ; + + p = req->best_parent_hw; + req->best_parent_rate = parent_rate =clk_hw_round_rate (p, rate); + + div =DIV_ROUND_UP ((2 * parent_rate), rate) -1 ; + div =min_t (u32, div, mask); + + req->rate =calc_rate (parent_rate,0 ,0 ,0 , div); + +return 0 ; +} + +static int clk_byte2_set_rate (struct clk_hw *hw,unsigned long rate, +unsigned long parent_rate) +{ +struct clk_rcg2 *rcg =to_clk_rcg2 (hw); +struct freq_tbl f = {0 }; +unsigned long div; +int i, num_parents =clk_hw_get_num_parents (hw); +u32 mask =BIT (rcg->hid_width) -1 ; +u32 cfg; + + div =DIV_ROUND_UP ((2 * parent_rate), rate) -1 ; + div =min_t (u32, div, mask); + + f.pre_div = div; + +regmap_read (rcg->clkr.regmap, rcg->cmd_rcgr +CFG_REG , &cfg); + cfg &=CFG_SRC_SEL_MASK ; + cfg >>=CFG_SRC_SEL_SHIFT ; + +for (i =0 ; i < num_parents; i++) { +if (cfg == rcg->parent_map[i].cfg) { + f.src = rcg->parent_map[i].src; +return clk_rcg2_configure (rcg, &f); + } + } + +return -EINVAL ; +} + +static int clk_byte2_set_rate_and_parent (struct clk_hw *hw, +unsigned long rate,unsigned long parent_rate,u8 index) +{ +/* Read the hardware to determine parent during set_rate */ +return clk_byte2_set_rate (hw, rate, parent_rate); +} + +const struct clk_ops clk_byte2_ops = { + .is_enabled = clk_rcg2_is_enabled, + .get_parent = clk_rcg2_get_parent, + .set_parent = clk_rcg2_set_parent, + .recalc_rate = clk_rcg2_recalc_rate, + .set_rate = clk_byte2_set_rate, + .set_rate_and_parent = clk_byte2_set_rate_and_parent, + .determine_rate = clk_byte2_determine_rate, +}; +EXPORT_SYMBOL_GPL (clk_byte2_ops); +static const struct frac_entry frac_table_pixel[] = { {3 ,8 }, {2 ,9 },@@ -496,14 +566,9 @@ static const struct frac_entry frac_table_pixel[] = {static int clk_pixel_determine_rate (struct clk_hw *hw,struct clk_rate_request *req) { -struct clk_rcg2 *rcg =to_clk_rcg2 (hw);unsigned long request, src_rate;int delta =100000 ; -const struct freq_tbl *f = rcg->freq_tbl;const struct frac_entry *frac = frac_table_pixel; -int index =qcom_find_src_index (hw, rcg->parent_map, f->src); - - req->best_parent_hw =clk_hw_get_parent_by_index (hw, index);for (; frac->num; frac++) { request = (req->rate * frac->den) / frac->num;@@ -525,12 +590,23 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) {struct clk_rcg2 *rcg =to_clk_rcg2 (hw); -struct freq_tbl f = *rcg->freq_tbl; +struct freq_tbl f = {0 };const struct frac_entry *frac = frac_table_pixel;unsigned long request;int delta =100000 ;u32 mask =BIT (rcg->hid_width) -1 ; -u32 hid_div; +u32 hid_div, cfg; +int i, num_parents =clk_hw_get_num_parents (hw); + +regmap_read (rcg->clkr.regmap, rcg->cmd_rcgr +CFG_REG , &cfg); + cfg &=CFG_SRC_SEL_MASK ; + cfg >>=CFG_SRC_SEL_SHIFT ; + +for (i =0 ; i < num_parents; i++) +if (cfg == rcg->parent_map[i].cfg) { + f.src = rcg->parent_map[i].src; +break ; + }for (; frac->num; frac++) { request = (rate * frac->den) / frac->num;@@ -555,7 +631,6 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,static int clk_pixel_set_rate_and_parent (struct clk_hw *hw,unsigned long rate,unsigned long parent_rate,u8 index) { -/* Parent index is set statically in frequency table */ return clk_pixel_set_rate (hw, rate, parent_rate); }drivers/clk/qcom/gcc-msm8916.c +1
-13@@ -906,21 +906,15 @@ static struct clk_rcg2 gp3_clk_src = { }, }; -static struct freq_tbl ftbl_gcc_mdss_byte0_clk[] = { - { .src =P_DSI0_PHYPLL_BYTE }, - { } -}; -static struct clk_rcg2 byte0_clk_src = { .cmd_rcgr =0x4d044 , .hid_width =5 , .parent_map = gcc_xo_gpll0a_dsibyte_map, - .freq_tbl = ftbl_gcc_mdss_byte0_clk, .clkr.hw.init = &(struct clk_init_data ){ .name ="byte0_clk_src" , .parent_names = gcc_xo_gpll0a_dsibyte, .num_parents =3 , - .ops = &clk_byte_ops, + .ops = &clk_byte2_ops, .flags =CLK_SET_RATE_PARENT , }, };@@ -968,17 +962,11 @@ static struct clk_rcg2 mdp_clk_src = { }, }; -static struct freq_tbl ftbl_gcc_mdss_pclk[] = { - { .src =P_DSI0_PHYPLL_DSI }, - { } -}; -static struct clk_rcg2 pclk0_clk_src = { .cmd_rcgr =0x4d000 , .mnd_width =8 , .hid_width =5 , .parent_map = gcc_xo_gpll0a_dsiphy_map, - .freq_tbl = ftbl_gcc_mdss_pclk, .clkr.hw.init = &(struct clk_init_data ){ .name ="pclk0_clk_src" , .parent_names = gcc_xo_gpll0a_dsiphy,drivers/clk/qcom/mmcc-apq8084.c +2
-16@@ -571,17 +571,11 @@ static struct clk_rcg2 jpeg2_clk_src = { }, }; -static struct freq_tbl pixel_freq_tbl[] = { - { .src =P_DSI0PLL }, - { } -}; -static struct clk_rcg2 pclk0_clk_src = { .cmd_rcgr =0x2000 , .mnd_width =8 , .hid_width =5 , .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, - .freq_tbl = pixel_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="pclk0_clk_src" , .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,@@ -596,7 +590,6 @@ static struct clk_rcg2 pclk1_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, - .freq_tbl = pixel_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="pclk1_clk_src" , .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,@@ -844,21 +837,15 @@ static struct clk_rcg2 cpp_clk_src = { }, }; -static struct freq_tbl byte_freq_tbl[] = { - { .src =P_DSI0PLL_BYTE }, - { } -}; -static struct clk_rcg2 byte0_clk_src = { .cmd_rcgr =0x2120 , .hid_width =5 , .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map, - .freq_tbl = byte_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="byte0_clk_src" , .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, .num_parents =6 , - .ops = &clk_byte_ops, + .ops = &clk_byte2_ops, .flags =CLK_SET_RATE_PARENT , }, };@@ -867,12 +854,11 @@ static struct clk_rcg2 byte1_clk_src = { .cmd_rcgr = 0x2140, .hid_width = 5, .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map, - .freq_tbl = byte_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="byte1_clk_src" , .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, .num_parents =6 , - .ops = &clk_byte_ops, + .ops = &clk_byte2_ops, .flags =CLK_SET_RATE_PARENT , }, };drivers/clk/qcom/mmcc-msm8974.c +2
-9@@ -522,17 +522,11 @@ static struct clk_rcg2 jpeg2_clk_src = { }, }; -static struct freq_tbl pixel_freq_tbl[] = { - { .src =P_DSI0PLL }, - { } -}; -static struct clk_rcg2 pclk0_clk_src = { .cmd_rcgr =0x2000 , .mnd_width =8 , .hid_width =5 , .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, - .freq_tbl = pixel_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="pclk0_clk_src" , .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,@@ -547,7 +541,6 @@ static struct clk_rcg2 pclk1_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, - .freq_tbl = pixel_freq_tbl, .clkr.hw.init = &(struct clk_init_data ){ .name ="pclk1_clk_src" , .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,@@ -785,7 +778,7 @@ static struct clk_rcg2 byte0_clk_src = { .name = "byte0_clk_src", .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, .num_parents = 6, - .ops = &clk_byte_ops, + .ops = &clk_byte2_ops, .flags = CLK_SET_RATE_PARENT, }, };@@ -799,7 +792,7 @@ static struct clk_rcg2 byte1_clk_src = { .name = "byte1_clk_src", .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, .num_parents = 6, - .ops = &clk_byte_ops, + .ops = &clk_byte2_ops, .flags = CLK_SET_RATE_PARENT, }, };
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Stephen Boyd
AppliedQuoted 10 lines · Stephen Boyd
Sometimes the display driver may want to change the parent PLL of the display clocks (byte and pixel clocks) depending on the use-case. Currently the parent is fixed by means of having a frequency table with one entry that chooses a particular parent. Remove this restriction and use the parent the clock is configured for in the hardware during
clk_set_rate(). This requires consumers to rely on the default parent or to configure the parent with clk_set_parent()/assigned-clock-parents on the clocks before callingclk_set_rate().
Quoted 4 lines
Cc Archit Taneja <[email protected]>Cc Hai Li <[email protected]>Signed-off-by Stephen Boyd <[email protected]>---
Applied to clk-next
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project