[PATCH] clk: mediatek: mt8188: Set clock parent for TOP_EDP and TOP_DP

yu-chang.lee yu-chang.lee at mediatek.com
Mon Oct 30 03:56:56 PDT 2023


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 at mediatek.com>
Signed-off-by: Garmin.Chang <Garmin.Chang at 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




More information about the linux-arm-kernel mailing list