[PATCH v2 23/25] phy: cadence: Sierra: Add support for skipping configuration

Aswath Govindraju a-govindraju at ti.com
Fri Jan 28 09:11:50 CET 2022


In some cases, a single SerDes instance can be shared between two different
processors, each using a separate link. In these cases, the SerDes
configuration is done in an earlier boot stage. Therefore, add support to
skip reconfiguring, if it is was already configured beforehand.

Signed-off-by: Aswath Govindraju <a-govindraju at ti.com>
---
 drivers/phy/cadence/phy-cadence-sierra.c | 58 +++++++++++++++++-------
 1 file changed, 42 insertions(+), 16 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
index 95cdd39cb367..d95d4b432a98 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -13,6 +13,7 @@
  */
 #include <common.h>
 #include <clk.h>
+#include <linux/delay.h>
 #include <linux/clk-provider.h>
 #include <generic-phy.h>
 #include <reset.h>
@@ -28,6 +29,8 @@
 #include <dt-bindings/phy/phy-cadence.h>
 #include <regmap.h>
 
+#define usleep_range(a, b) udelay((b))
+
 #define NUM_SSC_MODE		3
 #define NUM_PHY_TYPE		4
 
@@ -336,6 +339,7 @@ struct cdns_sierra_phy {
 	int nsubnodes;
 	u32 num_lanes;
 	bool autoconf;
+	unsigned int already_configured;
 };
 
 static inline int cdns_reset_assert(struct reset_control *rst)
@@ -386,7 +390,7 @@ static int cdns_sierra_phy_init(struct phy *gphy)
 	int i, j;
 
 	/* Initialise the PHY registers, unless auto configured */
-	if (phy->autoconf || phy->nsubnodes > 1)
+	if (phy->autoconf || phy->already_configured || phy->nsubnodes > 1)
 		return 0;
 
 	clk_set_rate(phy->input_clks[CMN_REFCLK_DIG_DIV], 25000000);
@@ -447,6 +451,11 @@ static int cdns_sierra_phy_on(struct phy *gphy)
 	u32 val;
 	int ret;
 
+	if (sp->already_configured) {
+		usleep_range(5000, 10000);
+		return 0;
+	}
+
 	if (sp->nsubnodes == 1) {
 		/* Take the PHY out of reset */
 		ret = reset_control_deassert(sp->phy_rst);
@@ -934,13 +943,6 @@ static int cdns_sierra_phy_get_clocks(struct cdns_sierra_phy *sp,
 	struct clk *clk;
 	int ret;
 
-	clk = devm_clk_get_optional(dev, "phy_clk");
-	if (IS_ERR(clk)) {
-		dev_err(dev, "failed to get clock phy_clk\n");
-		return PTR_ERR(clk);
-	}
-	sp->input_clks[PHY_CLK] = clk;
-
 	clk = devm_clk_get_optional(dev, "cmn_refclk_dig_div");
 	if (IS_ERR(clk)) {
 		dev_err(dev, "cmn_refclk_dig_div clock not found\n");
@@ -976,6 +978,25 @@ static int cdns_sierra_phy_get_clocks(struct cdns_sierra_phy *sp,
 	return 0;
 }
 
+static int cdns_sierra_phy_clk(struct cdns_sierra_phy *sp)
+{
+	struct udevice *dev = sp->dev;
+	struct clk *clk;
+	int ret;
+
+	clk = devm_clk_get_optional(dev, "phy_clk");
+	if (IS_ERR(clk)) {
+		dev_err(dev, "failed to get clock phy_clk\n");
+		return PTR_ERR(clk);
+	}
+	sp->input_clks[PHY_CLK] = clk;
+
+	ret = clk_prepare_enable(sp->input_clks[PHY_CLK]);
+	if (ret)
+		return ret;
+
+	return 0;
+}
 static int cdns_sierra_phy_get_resets(struct cdns_sierra_phy *sp,
 				      struct udevice *dev)
 {
@@ -1045,7 +1066,7 @@ static int cdns_sierra_link_probe(struct udevice *dev)
 	sp->num_lanes += inst->num_lanes;
 
 	/* If more than one subnode, configure the PHY as multilink */
-	if (!sp->autoconf && sp->nsubnodes > 1) {
+	if (!sp->autoconf && !sp->already_configured && sp->nsubnodes > 1) {
 		ret = cdns_sierra_phy_configure_multilink(sp);
 		if (ret)
 			return ret;
@@ -1098,13 +1119,17 @@ static int cdns_sierra_phy_probe(struct udevice *dev)
 	if (ret)
 		return ret;
 
-	ret = cdns_sierra_phy_get_resets(sp, dev);
-	if (ret)
-		return ret;
+	regmap_field_read(sp->pma_cmn_ready, &sp->already_configured);
 
-	ret = clk_prepare_enable(sp->input_clks[PHY_CLK]);
-	if (ret)
-		return ret;
+	if (!sp->already_configured) {
+		ret = cdns_sierra_phy_clk(sp);
+		if (ret)
+			return ret;
+
+		ret = cdns_sierra_phy_get_resets(sp, dev);
+		if (ret)
+			return ret;
+	}
 
 	/* Check that PHY is present */
 	regmap_field_read(sp->macro_id_type, &id_value);
@@ -1125,7 +1150,8 @@ static int cdns_sierra_phy_probe(struct udevice *dev)
 	return 0;
 
 clk_disable:
-	clk_disable_unprepare(sp->input_clks[PHY_CLK]);
+	if (!sp->already_configured)
+		clk_disable_unprepare(sp->input_clks[PHY_CLK]);
 	return ret;
 }
 
-- 
2.17.1



More information about the U-Boot mailing list