From 87d805f9ab551d6d9c5bec94c633ac0d30343f85 Mon Sep 17 00:00:00 2001
From: Grygorii Strashko <grygorii.strashko@ti.com>
Date: Fri, 18 Jun 2021 20:51:47 +0300
Subject: [PATCH] net: ethernet: icssg-prueth: fix rgmii tx delay configuration

The driver enables RGMII TX delay without checking specified
phy-connection-type value, which may break TX data path.

Hence, fix it by checking phy-connection-type and enable RGMII TX delay for
"rgmii" and "rgmii-rxid" modes only.

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
---
 drivers/net/ethernet/ti/icssg_prueth.c | 70 +++++++++++++-------------
 1 file changed, 34 insertions(+), 36 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg_prueth.c b/drivers/net/ethernet/ti/icssg_prueth.c
index 38d151dca81c..d19a05fd8b06 100644
--- a/drivers/net/ethernet/ti/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg_prueth.c
@@ -2021,6 +2021,36 @@ static int prueth_node_mac(struct device_node *eth_node)
 		return -EINVAL;
 }
 
+static int prueth_config_rgmiidelay(struct prueth *prueth,
+				    struct device_node *eth_np,
+				    phy_interface_t phy_if)
+{
+	struct device *dev = prueth->dev;
+	struct regmap *ctrl_mmr;
+	u32 rgmii_tx_id = 0;
+	u32 icssgctrl_reg;
+
+	ctrl_mmr = syscon_regmap_lookup_by_phandle(eth_np, "syscon-rgmii-delay");
+	if (IS_ERR(ctrl_mmr)) {
+		dev_err(dev, "couldn't get syscon-rgmii-delay\n");
+		return -ENODEV;
+	}
+
+	if (of_property_read_u32_index(eth_np, "syscon-rgmii-delay", 1,
+				       &icssgctrl_reg)) {
+		dev_err(dev, "couldn't get rgmii-delay reg. offset\n");
+		return -ENODEV;
+	}
+
+	if (phy_if == PHY_INTERFACE_MODE_RGMII_ID ||
+	    phy_if == PHY_INTERFACE_MODE_RGMII_TXID)
+		rgmii_tx_id |= ICSSG_CTRL_RGMII_ID_MODE;
+
+	regmap_update_bits(ctrl_mmr, icssgctrl_reg, ICSSG_CTRL_RGMII_ID_MODE, rgmii_tx_id);
+
+	return 0;
+}
+
 extern const struct ethtool_ops icssg_ethtool_ops;
 
 static int prueth_netdev_init(struct prueth *prueth,
@@ -2116,6 +2146,10 @@ static int prueth_netdev_init(struct prueth *prueth,
 		goto free;
 	}
 
+	ret = prueth_config_rgmiidelay(prueth, eth_node, emac->phy_if);
+	if (ret)
+		goto free;
+
 	/* connect PHY */
 	emac->phydev = of_phy_connect(ndev, emac->phy_node,
 				      &emac_adjust_link, 0, emac->phy_if);
@@ -2261,34 +2295,6 @@ static void prueth_put_cores(struct prueth *prueth, int slice)
 		pru_rproc_put(prueth->pru[slice]);
 }
 
-static int prueth_config_rgmiidelay(struct prueth *prueth,
-				    struct device_node *eth_np)
-{
-	struct device *dev = prueth->dev;
-	struct regmap *ctrl_mmr;
-	u32 icssgctrl;
-	struct device_node *np = dev->of_node;
-
-	if (!of_device_is_compatible(np, "ti,am654-icssg-prueth"))
-		return 0;
-
-	ctrl_mmr = syscon_regmap_lookup_by_phandle(eth_np, "syscon-rgmii-delay");
-	if (IS_ERR(ctrl_mmr)) {
-		dev_err(dev, "couldn't get syscon-rgmii-delay\n");
-		return -ENODEV;
-	}
-
-	if (of_property_read_u32_index(eth_np, "syscon-rgmii-delay", 1,
-				       &icssgctrl)) {
-		dev_err(dev, "couldn't get rgmii-delay reg. offset\n");
-		return -ENODEV;
-	}
-
-	regmap_update_bits(ctrl_mmr, icssgctrl, ICSSG_CTRL_RGMII_ID_MODE, 0);
-
-	return 0;
-}
-
 static const struct of_device_id prueth_dt_match[];
 
 static int prueth_probe(struct platform_device *pdev)
@@ -2355,20 +2361,12 @@ static int prueth_probe(struct platform_device *pdev)
 	}
 
 	if (eth0_node) {
-		ret = prueth_config_rgmiidelay(prueth, eth0_node);
-		if (ret)
-			goto put_cores;
-
 		ret = prueth_get_cores(prueth, ICSS_SLICE0);
 		if (ret)
 			goto put_cores;
 	}
 
 	if (eth1_node) {
-		ret = prueth_config_rgmiidelay(prueth, eth1_node);
-		if (ret)
-			goto put_cores;
-
 		ret = prueth_get_cores(prueth, ICSS_SLICE1);
 		if (ret)
 			goto put_cores;
