diff mbox series

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

Message ID 20220128081152.14901-24-a-govindraju@ti.com
State Accepted
Commit 68c6476146339bc0a8724e0f6314a3b71a329598
Delegated to: Tom Rini
Headers show
Series SIERRA: Add support for Mulitlink Configuration | expand

Commit Message

Aswath Govindraju Jan. 28, 2022, 8:11 a.m. UTC
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@ti.com>
---
 drivers/phy/cadence/phy-cadence-sierra.c | 58 +++++++++++++++++-------
 1 file changed, 42 insertions(+), 16 deletions(-)

Comments

Tom Rini Feb. 8, 2022, 5:36 p.m. UTC | #1
On Fri, Jan 28, 2022 at 01:41:50PM +0530, Aswath Govindraju wrote:

> 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@ti.com>

Applied to u-boot/master, thanks!
diff mbox series

Patch

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;
 }