diff mbox series

clk: mediatek: mt8188: Set clock parent for TOP_EDP and TOP_DP

Message ID 20231030105656.7288-1-yu-chang.lee@mediatek.com (mailing list archive)
State New, archived
Headers show
Series clk: mediatek: mt8188: Set clock parent for TOP_EDP and TOP_DP | expand

Commit Message

Yu-chang Lee (李禹璋) Oct. 30, 2023, 10:56 a.m. UTC
Modify MT8188 edp, dp clock and add .determine_rate() callback to
dynamically set parent for TOP_EDP and TOP_DP. By separating tvdpll
output into different interval, we can make sure VCO operate at optimal
condition.

Signed-off-by: yu-chang.lee <yu-chang.lee@mediatek.com>
Signed-off-by: Garmin.Chang <Garmin.Chang@mediatek.com>

---
 drivers/clk/mediatek/clk-mt8188-topckgen.c | 74 +++++++++++++++++++++-
 1 file changed, 72 insertions(+), 2 deletions(-)

Comments

Chen-Yu Tsai Nov. 1, 2023, 7:48 a.m. UTC | #1
On Mon, Oct 30, 2023 at 6:57 PM yu-chang.lee <yu-chang.lee@mediatek.com> wrote:
>
> Modify MT8188 edp, dp clock and add .determine_rate() callback to
> dynamically set parent for TOP_EDP and TOP_DP. By separating tvdpll
> output into different interval, we can make sure VCO operate at optimal
> condition.

This patch does two things: a) separate eDP and DP clocks onto two separate
PLLs, and b) customize how the parent (divider) is selected. They should
be separate patches.

(a) can be done like how Angelo proposed for MT8195 [1]. If PLL separation
is all you need, please post a patch like it.

It's unclear to me how (b) is an improvement over existing code. The MediaTek
clock driver library already specifies proper ranges for the PLLs, and the
mux code should go through all the clock parents and choose one that can
generate a clock rate closest to the requested one while using one of the
dividers and a PLL rate within spec. If that isn't working, it should be
fixed, not worked around.


Regards
ChenYu

[1] https://lore.kernel.org/linux-mediatek/20231018103546.48174-1-angelogioacchino.delregno@collabora.com/

>
> Signed-off-by: yu-chang.lee <yu-chang.lee@mediatek.com>
> Signed-off-by: Garmin.Chang <Garmin.Chang@mediatek.com>
>
> ---
>  drivers/clk/mediatek/clk-mt8188-topckgen.c | 74 +++++++++++++++++++++-
>  1 file changed, 72 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/mediatek/clk-mt8188-topckgen.c b/drivers/clk/mediatek/clk-mt8188-topckgen.c
> index e330a4f9a0c3..921fb31fe4b1 100644
> --- a/drivers/clk/mediatek/clk-mt8188-topckgen.c
> +++ b/drivers/clk/mediatek/clk-mt8188-topckgen.c
> @@ -487,6 +487,74 @@ static const char * const dp_parents[] = {
>         "tvdpll2_d16"
>  };
>
> +#define VCO_OPP_LOW    7000000
> +#define VCO_OPP_MEDIUM 200000000
> +
> +enum dp_edp_parent_index {
> +       PLL_D4 = 2,
> +       PLL_D8,
> +       PLL_D16
> +};
> +
> +static int dp_clk_determine_rate(struct clk_hw *hw,
> +                                  struct clk_rate_request *req)
> +{
> +       const char *clk_hw_name = clk_hw_get_name(hw);
> +       unsigned int pow, parent_id, is_edp = 0;
> +       struct clk_rate_request parent_req = *req;
> +       struct clk_hw *parent_hw = clk_hw_get_parent(hw);
> +       unsigned long parent_rate = clk_hw_get_rate(parent_hw);
> +       int ret = 0;
> +
> +       if (!strncmp(clk_hw_name, "top_edp", 7))
> +               is_edp = 1;
> +
> +       if (req->rate < VCO_OPP_LOW)
> +               pow = PLL_D16;
> +       else if (req->rate < VCO_OPP_MEDIUM)
> +               pow = PLL_D8;
> +       else
> +               pow = PLL_D4;
> +
> +       if (is_edp)
> +               parent_id = (pow << 1) - 1;
> +       else
> +               parent_id = pow << 1;
> +
> +       /* re-parenting and determine rate */
> +       if (clk_hw_can_set_rate_parent(hw)) {
> +               parent_hw = clk_hw_get_parent_by_index(hw, parent_id);
> +               ret = __clk_determine_rate(parent_hw, &parent_req);
> +               if (ret)
> +                       return ret;
> +
> +               req->best_parent_hw = parent_hw;
> +               req->rate = req->best_parent_rate = parent_req.rate;
> +       } else {
> +               req->best_parent_hw = parent_hw;
> +               req->rate = req->best_parent_rate = parent_rate;
> +       }
> +
> +       return ret;
> +}
> +
> +static struct clk_ops dp_clk_ops;
> +
> +static void dp_clk_ops_init(void)
> +{
> +       dp_clk_ops = mtk_mux_gate_clr_set_upd_ops;
> +       dp_clk_ops.determine_rate = dp_clk_determine_rate;
> +}
> +
> +#define DP_MUX(_id, _name, _parents, _mux_ofs, _mux_set_ofs,   \
> +                _mux_clr_ofs, _shift, _width, _gate, _upd_ofs, \
> +                _upd)  \
> +       GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,  \
> +               _mux_set_ofs, _mux_clr_ofs, _shift, _width,     \
> +               _gate, _upd_ofs, _upd, CLK_SET_RATE_PARENT,     \
> +               dp_clk_ops)
> +
> +
>  static const char * const edp_parents[] = {
>         "clk26m",
>         "tvdpll1_d2",
> @@ -1038,9 +1106,9 @@ static const struct mtk_mux top_mtk_muxes[] = {
>         MUX_GATE_CLR_SET_UPD(CLK_TOP_SSPM, "top_sspm",
>                              sspm_parents, 0x080, 0x084, 0x088, 24, 4, 31, 0x08, 3),
>         /* CLK_CFG_9 */
> -       MUX_GATE_CLR_SET_UPD(CLK_TOP_DP, "top_dp",
> +       DP_MUX(CLK_TOP_DP, "top_dp",
>                              dp_parents, 0x08C, 0x090, 0x094, 0, 4, 7, 0x08, 4),
> -       MUX_GATE_CLR_SET_UPD(CLK_TOP_EDP, "top_edp",
> +       DP_MUX(CLK_TOP_EDP, "top_edp",
>                              edp_parents, 0x08C, 0x090, 0x094, 8, 4, 15, 0x08, 5),
>         MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI, "top_dpi",
>                              dpi_parents, 0x08C, 0x090, 0x094, 16, 4, 23, 0x08, 6),
> @@ -1267,6 +1335,8 @@ static int clk_mt8188_topck_probe(struct platform_device *pdev)
>                 goto free_top_data;
>         }
>
> +       dp_clk_ops_init();
> +
>         r = mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
>                                         top_clk_data);
>         if (r)
> --
> 2.18.0
>
>
diff mbox series

Patch

diff --git a/drivers/clk/mediatek/clk-mt8188-topckgen.c b/drivers/clk/mediatek/clk-mt8188-topckgen.c
index e330a4f9a0c3..921fb31fe4b1 100644
--- a/drivers/clk/mediatek/clk-mt8188-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt8188-topckgen.c
@@ -487,6 +487,74 @@  static const char * const dp_parents[] = {
 	"tvdpll2_d16"
 };
 
+#define VCO_OPP_LOW	7000000
+#define VCO_OPP_MEDIUM	200000000
+
+enum dp_edp_parent_index {
+	PLL_D4 = 2,
+	PLL_D8,
+	PLL_D16
+};
+
+static int dp_clk_determine_rate(struct clk_hw *hw,
+				   struct clk_rate_request *req)
+{
+	const char *clk_hw_name = clk_hw_get_name(hw);
+	unsigned int pow, parent_id, is_edp = 0;
+	struct clk_rate_request parent_req = *req;
+	struct clk_hw *parent_hw = clk_hw_get_parent(hw);
+	unsigned long parent_rate = clk_hw_get_rate(parent_hw);
+	int ret = 0;
+
+	if (!strncmp(clk_hw_name, "top_edp", 7))
+		is_edp = 1;
+
+	if (req->rate < VCO_OPP_LOW)
+		pow = PLL_D16;
+	else if (req->rate < VCO_OPP_MEDIUM)
+		pow = PLL_D8;
+	else
+		pow = PLL_D4;
+
+	if (is_edp)
+		parent_id = (pow << 1) - 1;
+	else
+		parent_id = pow << 1;
+
+	/* re-parenting and determine rate */
+	if (clk_hw_can_set_rate_parent(hw)) {
+		parent_hw = clk_hw_get_parent_by_index(hw, parent_id);
+		ret = __clk_determine_rate(parent_hw, &parent_req);
+		if (ret)
+			return ret;
+
+		req->best_parent_hw = parent_hw;
+		req->rate = req->best_parent_rate = parent_req.rate;
+	} else {
+		req->best_parent_hw = parent_hw;
+		req->rate = req->best_parent_rate = parent_rate;
+	}
+
+	return ret;
+}
+
+static struct clk_ops dp_clk_ops;
+
+static void dp_clk_ops_init(void)
+{
+	dp_clk_ops = mtk_mux_gate_clr_set_upd_ops;
+	dp_clk_ops.determine_rate = dp_clk_determine_rate;
+}
+
+#define DP_MUX(_id, _name, _parents, _mux_ofs, _mux_set_ofs,	\
+		 _mux_clr_ofs, _shift, _width, _gate, _upd_ofs, \
+		 _upd)	\
+	GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,	\
+		_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
+		_gate, _upd_ofs, _upd, CLK_SET_RATE_PARENT,	\
+		dp_clk_ops)
+
+
 static const char * const edp_parents[] = {
 	"clk26m",
 	"tvdpll1_d2",
@@ -1038,9 +1106,9 @@  static const struct mtk_mux top_mtk_muxes[] = {
 	MUX_GATE_CLR_SET_UPD(CLK_TOP_SSPM, "top_sspm",
 			     sspm_parents, 0x080, 0x084, 0x088, 24, 4, 31, 0x08, 3),
 	/* CLK_CFG_9 */
-	MUX_GATE_CLR_SET_UPD(CLK_TOP_DP, "top_dp",
+	DP_MUX(CLK_TOP_DP, "top_dp",
 			     dp_parents, 0x08C, 0x090, 0x094, 0, 4, 7, 0x08, 4),
-	MUX_GATE_CLR_SET_UPD(CLK_TOP_EDP, "top_edp",
+	DP_MUX(CLK_TOP_EDP, "top_edp",
 			     edp_parents, 0x08C, 0x090, 0x094, 8, 4, 15, 0x08, 5),
 	MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI, "top_dpi",
 			     dpi_parents, 0x08C, 0x090, 0x094, 16, 4, 23, 0x08, 6),
@@ -1267,6 +1335,8 @@  static int clk_mt8188_topck_probe(struct platform_device *pdev)
 		goto free_top_data;
 	}
 
+	dp_clk_ops_init();
+
 	r = mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
 					top_clk_data);
 	if (r)