summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c')
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index b8d467ba6d72..4d207f41a43b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -525,6 +525,32 @@ static int intel_set_reg_access(const struct pmc_serdes_regs *regs, int max_regs
return ret;
}
+/*
+ * Return true if the SerDes lane rate must change to serve @interface.
+ * If the current rate cannot be determined, reconfigure as before.
+ */
+static bool intel_serdes_needs_reconfig(struct stmmac_priv *priv,
+ struct intel_priv_data *intel_priv,
+ phy_interface_t interface)
+{
+ u32 cur_rate, want_rate;
+ int data;
+
+ if (!intel_priv->mdio_adhoc_addr)
+ return true;
+
+ data = mdiobus_read(priv->mii, intel_priv->mdio_adhoc_addr,
+ SERDES_GCR0);
+ if (data < 0)
+ return true;
+
+ cur_rate = (data & SERDES_RATE_MASK) >> SERDES_RATE_PCIE_SHIFT;
+ want_rate = interface == PHY_INTERFACE_MODE_2500BASEX ?
+ SERDES_RATE_PCIE_GEN2 : SERDES_RATE_PCIE_GEN1;
+
+ return cur_rate != want_rate;
+}
+
static int intel_mac_finish(struct net_device *ndev,
void *intel_data,
unsigned int mode,
@@ -536,6 +562,11 @@ static int intel_mac_finish(struct net_device *ndev,
int max_regs = 0;
int ret = 0;
+ if (!intel_serdes_needs_reconfig(priv, intel_priv, interface)) {
+ priv->plat->phy_interface = interface;
+ return 0;
+ }
+
ret = intel_tsn_lane_is_available(ndev, intel_priv);
if (ret < 0) {
netdev_info(priv->dev, "No TSN lane available to set the registers.\n");