Browse Source

disp: msm: dp: update pll driver to fix clock names per target

With the change in the clock names for newer targets, this fix
updates the driver to support different clock names per target.

Change-Id: I58c35fce34356f8c79adb0ac8a907e2fb60813ae
Signed-off-by: Sudarsan Ramesh <[email protected]>
Sudarsan Ramesh 4 years ago
parent
commit
e66a2089f4
6 changed files with 86 additions and 28 deletions
  1. 17 1
      msm/dp/dp_catalog.c
  2. 2 1
      msm/dp/dp_catalog.h
  3. 1 0
      msm/dp/dp_display.c
  4. 30 1
      msm/dp/dp_pll.c
  5. 3 0
      msm/dp/dp_pll.h
  6. 33 25
      msm/dp/dp_pll_5nm.c

+ 17 - 1
msm/dp/dp_catalog.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 
@@ -1938,6 +1938,22 @@ static void dp_catalog_ctrl_fec_config(struct dp_catalog_ctrl *ctrl,
 	wmb();
 }
 
+u32 dp_catalog_get_dp_core_version(struct dp_catalog *dp_catalog)
+{
+	struct dp_catalog_private *catalog;
+	struct dp_io_data *io_data;
+
+	if (!dp_catalog) {
+		DP_ERR("invalid input\n");
+		return 0;
+	}
+
+	catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
+	io_data = catalog->io.dp_ahb;
+
+	return dp_read(DP_HW_VERSION);
+}
+
 static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog,
 		char *name, u8 **out_buf, u32 *out_buf_len)
 {

+ 2 - 1
msm/dp/dp_catalog.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _DP_CATALOG_H_
@@ -336,4 +336,5 @@ struct dp_catalog_sub *dp_catalog_get_v420(struct device *dev,
 struct dp_catalog_sub *dp_catalog_get_v200(struct device *dev,
 			struct dp_catalog *catalog, struct dp_catalog_io *io);
 
+u32 dp_catalog_get_dp_core_version(struct dp_catalog *dp_catalog);
 #endif /* _DP_CATALOG_H_ */

+ 1 - 0
msm/dp/dp_display.c

@@ -1919,6 +1919,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
 
 	pll_in.aux = dp->aux;
 	pll_in.parser = dp->parser;
+	pll_in.dp_core_revision = dp_catalog_get_dp_core_version(dp->catalog);
 
 	dp->pll = dp_pll_get(&pll_in);
 	if (IS_ERR(dp->pll)) {

+ 30 - 1
msm/dp/dp_pll.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/err.h>
@@ -74,6 +74,34 @@ static void dp_pll_clock_unregister(struct dp_pll *pll)
 	}
 }
 
+int dp_pll_clock_register_helper(struct dp_pll *pll, struct dp_pll_vco_clk *clks, int num_clks)
+{
+	int rc = 0, i = 0;
+	struct platform_device *pdev;
+	struct clk *clk;
+
+	if (!pll || !clks) {
+		DP_ERR("input not initialized\n");
+		return -EINVAL;
+	}
+
+	pdev = pll->pdev;
+
+	for (i = 0; i < num_clks; i++) {
+		clks[i].priv = pll;
+
+		clk = clk_register(&pdev->dev, &clks[i].hw);
+		if (IS_ERR(clk)) {
+			DP_ERR("%s registration failed for DP: %d\n",
+			clk_hw_get_name(&clks[i].hw), pll->index);
+			return -EINVAL;
+		}
+		pll->clk_data->clks[i] = clk;
+	}
+
+	return rc;
+}
+
 struct dp_pll *dp_pll_get(struct dp_pll_in *in)
 {
 	int rc = 0;
@@ -93,6 +121,7 @@ struct dp_pll *dp_pll_get(struct dp_pll_in *in)
 	pll->pdev = in->pdev;
 	pll->parser = in->parser;
 	pll->aux = in->aux;
+	pll->dp_core_revision = in->dp_core_revision;
 	parser = pll->parser;
 	pdev = pll->pdev;
 

+ 3 - 0
msm/dp/dp_pll.h

@@ -80,6 +80,7 @@ struct dp_pll {
 	struct dp_aux *aux;
 	struct dp_pll_io io;
 	struct clk_onecell_data *clk_data;
+	u32 dp_core_revision;
 
 	int (*pll_cfg)(struct dp_pll *pll, unsigned long rate);
 	int (*pll_prepare)(struct dp_pll *pll);
@@ -128,8 +129,10 @@ struct dp_pll_in {
 	struct platform_device *pdev;
 	struct dp_aux *aux;
 	struct dp_parser *parser;
+	u32 dp_core_revision;
 };
 
+int dp_pll_clock_register_helper(struct dp_pll *pll, struct dp_pll_vco_clk *clks, int num_clks);
 struct dp_pll *dp_pll_get(struct dp_pll_in *in);
 void dp_pll_put(struct dp_pll *pll);
 #endif /* __DP_PLL_H */

+ 33 - 25
msm/dp/dp_pll_5nm.c

@@ -121,6 +121,8 @@
 #define DP_VCO_RATE_9720MHZDIV1000		9720000UL
 #define DP_VCO_RATE_10800MHZDIV1000		10800000UL
 
+#define DP_PLL_NUM_CLKS				2
+
 #define DP_5NM_C_READY		BIT(0)
 #define DP_5NM_FREQ_DONE	BIT(0)
 #define DP_5NM_PLL_LOCKED	BIT(1)
@@ -826,17 +828,33 @@ static const struct clk_ops pll_vco_div_clk_ops = {
 	.set_rate = dp_pll_vco_div_clk_set_rate,
 };
 
-static struct dp_pll_vco_clk dp_phy_pll_link_clk = {
+static struct dp_pll_vco_clk dp0_phy_pll_clks[DP_PLL_NUM_CLKS] = {
+	{
 	.hw.init = &(struct clk_init_data) {
-		.name = "dp_phy_pll_link_clk",
+		.name = "dp0_phy_pll_link_clk",
 		.ops = &pll_link_clk_ops,
+		},
+	},
+	{
+	.hw.init = &(struct clk_init_data) {
+		.name = "dp0_phy_pll_vco_div_clk",
+		.ops = &pll_vco_div_clk_ops,
+		},
 	},
 };
 
-static struct dp_pll_vco_clk dp_phy_pll_vco_div_clk = {
+static struct dp_pll_vco_clk dp_phy_pll_clks[DP_PLL_NUM_CLKS] = {
+	{
+	.hw.init = &(struct clk_init_data) {
+		.name = "dp_phy_pll_link_clk",
+		.ops = &pll_link_clk_ops,
+		},
+	},
+	{
 	.hw.init = &(struct clk_init_data) {
 		.name = "dp_phy_pll_vco_div_clk",
 		.ops = &pll_vco_div_clk_ops,
+		},
 	},
 };
 
@@ -844,9 +862,9 @@ static struct dp_pll_db dp_pdb;
 
 int dp_pll_clock_register_5nm(struct dp_pll *pll)
 {
-	int rc = 0, num_clks = 2;
+	int rc = 0;
 	struct platform_device *pdev;
-	struct clk *clk;
+	struct dp_pll_vco_clk *pll_clks;
 
 	if (!pll) {
 		DP_ERR("pll data not initialized\n");
@@ -858,46 +876,36 @@ int dp_pll_clock_register_5nm(struct dp_pll *pll)
 	if (!pll->clk_data)
 		return -ENOMEM;
 
-	pll->clk_data->clks = kcalloc(num_clks, sizeof(struct clk *),
+	pll->clk_data->clks = kcalloc(DP_PLL_NUM_CLKS, sizeof(struct clk *),
 			GFP_KERNEL);
 	if (!pll->clk_data->clks) {
 		kfree(pll->clk_data);
 		return -ENOMEM;
 	}
 
-	pll->clk_data->clk_num = num_clks;
+	pll->clk_data->clk_num = DP_PLL_NUM_CLKS;
 	pll->priv = &dp_pdb;
 	dp_pdb.pll = pll;
 
-	dp_phy_pll_link_clk.priv = pll;
-	dp_phy_pll_vco_div_clk.priv = pll;
-
 	pll->pll_cfg = dp_pll_configure;
 	pll->pll_prepare = dp_pll_prepare;
 	pll->pll_unprepare = dp_pll_unprepare;
 
-	clk = clk_register(&pdev->dev, &dp_phy_pll_link_clk.hw);
-	if (IS_ERR(clk)) {
-		DP_ERR("%s registration failed for DP: %d\n",
-		       clk_hw_get_name(&dp_phy_pll_link_clk.hw), pll->index);
-		rc = -EINVAL;
-		goto clk_reg_fail;
-	}
-	pll->clk_data->clks[0] = clk;
+	if (pll->dp_core_revision >= 0x10040000)
+		pll_clks = dp0_phy_pll_clks;
+	else
+		pll_clks = dp_phy_pll_clks;
 
-	clk = clk_register(&pdev->dev, &dp_phy_pll_vco_div_clk.hw);
-	if (IS_ERR(clk)) {
-		DP_ERR("%s registration failed for DP: %d\n",
-		       clk_hw_get_name(&dp_phy_pll_vco_div_clk.hw), pll->index);
-		rc = -EINVAL;
+	rc = dp_pll_clock_register_helper(pll, pll_clks, DP_PLL_NUM_CLKS);
+	if (rc) {
+		DP_ERR("Clock register failed rc=%d\n", rc);
 		goto clk_reg_fail;
 	}
-	pll->clk_data->clks[1] = clk;
 
 	rc = of_clk_add_provider(pdev->dev.of_node,
 			of_clk_src_onecell_get, pll->clk_data);
 	if (rc) {
-		DP_ERR("Clock register failed rc=%d\n", rc);
+		DP_ERR("Clock add provider failed rc=%d\n", rc);
 		goto clk_reg_fail;
 	}