All of lore.kernel.org
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v1 2/2] net/axgbe: auto-negotiation support enabled for 1Gbps
@ 2020-01-10  8:36 ssardar
  0 siblings, 0 replies; only message in thread
From: ssardar @ 2020-01-10  8:36 UTC (permalink / raw)
  To: dev

From: Sardar Shamsher Singh <Shamshersingh.Sardar@amd.com>

Added CL37 Auto-neg support for 1Gbps interface
in axgbe driver

Signed-off-by: Sardar Shamsher Singh <Shamshersingh.Sardar@amd.com>
---
 drivers/net/axgbe/axgbe_common.h   |   1 +
 drivers/net/axgbe/axgbe_mdio.c     | 192 +++++++++++++++++++++++++++--
 drivers/net/axgbe/axgbe_phy_impl.c |  37 ++++++
 3 files changed, 219 insertions(+), 11 deletions(-)

diff --git a/drivers/net/axgbe/axgbe_common.h b/drivers/net/axgbe/axgbe_common.h
index 34f60f156..99fa92d5c 100644
--- a/drivers/net/axgbe/axgbe_common.h
+++ b/drivers/net/axgbe/axgbe_common.h
@@ -1296,6 +1296,7 @@
 #define AXGBE_AN_CL37_PCS_MODE_BASEX	0x00
 #define AXGBE_AN_CL37_PCS_MODE_SGMII	0x04
 #define AXGBE_AN_CL37_TX_CONFIG_MASK	0x08
+#define AXGBE_AN_CL37_MII_CTRL_8BIT     0x0100
 
 #define AXGBE_PMA_CDR_TRACK_EN_MASK	0x01
 #define AXGBE_PMA_CDR_TRACK_EN_OFF	0x00
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 2721e5cc9..3902b1ec3 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -29,6 +29,19 @@ static void axgbe_an37_disable_interrupts(struct axgbe_port *pdata)
 	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
 }
 
+static void axgbe_an37_enable_interrupts(struct axgbe_port *pdata)
+{
+	unsigned int reg;
+
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL);
+	reg |= AXGBE_PCS_CL37_BP;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
+
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
+	reg |= AXGBE_AN_CL37_INT_MASK;
+	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
+}
+
 static void axgbe_an73_clear_interrupts(struct axgbe_port *pdata)
 {
 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
@@ -54,7 +67,7 @@ static void axgbe_an_enable_interrupts(struct axgbe_port *pdata)
 		break;
 	case AXGBE_AN_MODE_CL37:
 	case AXGBE_AN_MODE_CL37_SGMII:
-		PMD_DRV_LOG(ERR, "Unsupported AN_MOD_37\n");
+		axgbe_an37_enable_interrupts(pdata);
 		break;
 	default:
 		break;
@@ -254,6 +267,12 @@ static void axgbe_an37_set(struct axgbe_port *pdata, bool enable,
 	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg);
 }
 
+static void axgbe_an37_restart(struct axgbe_port *pdata)
+{
+	axgbe_an37_enable_interrupts(pdata);
+	axgbe_an37_set(pdata, true, true);
+}
+
 static void axgbe_an37_disable(struct axgbe_port *pdata)
 {
 	axgbe_an37_set(pdata, false, false);
@@ -302,7 +321,7 @@ static void axgbe_an_restart(struct axgbe_port *pdata)
 		break;
 	case AXGBE_AN_MODE_CL37:
 	case AXGBE_AN_MODE_CL37_SGMII:
-		PMD_DRV_LOG(ERR, "Unsupported AN_MODE_CL37\n");
+		axgbe_an37_restart(pdata);
 		break;
 	default:
 		break;
@@ -321,7 +340,7 @@ static void axgbe_an_disable(struct axgbe_port *pdata)
 		break;
 	case AXGBE_AN_MODE_CL37:
 	case AXGBE_AN_MODE_CL37_SGMII:
-		PMD_DRV_LOG(ERR, "Unsupported AN_MODE_CL37\n");
+		axgbe_an37_disable(pdata);
 		break;
 	default:
 		break;
@@ -573,6 +592,53 @@ static void axgbe_an73_state_machine(struct axgbe_port *pdata)
 	axgbe_an73_enable_interrupts(pdata);
 }
 
+static void axgbe_an37_state_machine(struct axgbe_port *pdata)
+{
+	enum axgbe_an cur_state = pdata->an_state;
+
+	if (!pdata->an_int)
+		return;
+	if (pdata->an_int & AXGBE_AN_CL37_INT_CMPLT) {
+		pdata->an_state = AXGBE_AN_COMPLETE;
+		pdata->an_int &= ~AXGBE_AN_CL37_INT_CMPLT;
+
+	/* If SGMII is enabled, check the link status */
+		if (pdata->an_mode == AXGBE_AN_MODE_CL37_SGMII &&
+		    !(pdata->an_status & AXGBE_SGMII_AN_LINK_STATUS))
+			pdata->an_state = AXGBE_AN_NO_LINK;
+	}
+
+	cur_state = pdata->an_state;
+
+	switch (pdata->an_state) {
+	case AXGBE_AN_READY:
+		break;
+	case AXGBE_AN_COMPLETE:
+		break;
+	case AXGBE_AN_NO_LINK:
+		break;
+	default:
+		pdata->an_state = AXGBE_AN_ERROR;
+		break;
+	}
+
+	if (pdata->an_state == AXGBE_AN_ERROR) {
+		PMD_DRV_LOG(ERR, "error during auto-negotiation, state=%u\n",
+			    cur_state);
+		pdata->an_int = 0;
+		axgbe_an37_clear_interrupts(pdata);
+	}
+
+	if (pdata->an_state >= AXGBE_AN_COMPLETE) {
+		pdata->an_result = pdata->an_state;
+		pdata->an_state = AXGBE_AN_READY;
+		if (pdata->phy_if.phy_impl.an_post)
+			pdata->phy_if.phy_impl.an_post(pdata);
+	}
+
+	axgbe_an37_enable_interrupts(pdata);
+}
+
 static void axgbe_an73_isr(struct axgbe_port *pdata)
 {
 	/* Disable AN interrupts */
@@ -580,6 +646,7 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 
 	/* Save the interrupt(s) that fired */
 	pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
+	axgbe_an73_clear_interrupts(pdata);
 
 	if (pdata->an_int) {
 		/* Clear the interrupt(s) that fired and process them */
@@ -593,6 +660,29 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 	}
 }
 
+static void axgbe_an37_isr(struct axgbe_port *pdata)
+{
+	unsigned int reg = 0;
+	/* Disable AN interrupts */
+	axgbe_an37_disable_interrupts(pdata);
+
+	/* Save the interrupt(s) that fired */
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT);
+	pdata->an_int = reg & AXGBE_AN_CL37_INT_MASK;
+	pdata->an_status = reg & ~AXGBE_AN_CL37_INT_MASK;
+	axgbe_an37_clear_interrupts(pdata);
+
+	if (pdata->an_int & 0x01) {
+		/* Clear the interrupt(s) that fired and process them */
+		reg &= ~AXGBE_AN_CL37_INT_MASK;
+		XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg);
+		axgbe_an37_state_machine(pdata);
+	} else {
+		/* Enable AN interrupts */
+		axgbe_an37_enable_interrupts(pdata);
+	}
+}
+
 static void axgbe_an_isr(struct axgbe_port *pdata)
 {
 	switch (pdata->an_mode) {
@@ -602,7 +692,7 @@ static void axgbe_an_isr(struct axgbe_port *pdata)
 		break;
 	case AXGBE_AN_MODE_CL37:
 	case AXGBE_AN_MODE_CL37_SGMII:
-		PMD_DRV_LOG(ERR, "AN_MODE_37 not supported\n");
+		axgbe_an37_isr(pdata);
 		break;
 	default:
 		break;
@@ -614,6 +704,48 @@ static void axgbe_an_combined_isr(struct axgbe_port *pdata)
 	axgbe_an_isr(pdata);
 }
 
+static void axgbe_an37_init(struct axgbe_port *pdata)
+{
+	unsigned int advertising;
+	unsigned int reg = 0;
+
+	advertising = pdata->phy_if.phy_impl.an_advertising(pdata);
+
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
+	if (advertising & ADVERTISED_Pause)
+		reg |= 0x100;
+	else
+		reg &= ~0x100;
+	if (advertising & ADVERTISED_Asym_Pause)
+		reg |= 0x80;
+	else
+		reg &= ~0x80;
+
+	/* Full duplex, but not half */
+	reg |= AXGBE_AN_CL37_FD_MASK;
+	reg &= ~AXGBE_AN_CL37_HD_MASK;
+
+	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE, reg);
+
+	/* Set up the Control register */
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
+	reg &= ~AXGBE_AN_CL37_TX_CONFIG_MASK;
+	reg &= ~AXGBE_AN_CL37_PCS_MODE_MASK;
+
+	switch (pdata->an_mode) {
+	case AXGBE_AN_MODE_CL37:
+		reg |= AXGBE_AN_CL37_PCS_MODE_BASEX;
+		break;
+	case AXGBE_AN_MODE_CL37_SGMII:
+		reg |= AXGBE_AN_CL37_PCS_MODE_SGMII;
+		break;
+	default:
+		break;
+	}
+	reg |= AXGBE_AN_CL37_MII_CTRL_8BIT;
+	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
+}
+
 static void axgbe_an73_init(struct axgbe_port *pdata)
 {
 	unsigned int advertising, reg;
@@ -673,7 +805,7 @@ static void axgbe_an_init(struct axgbe_port *pdata)
 		break;
 	case AXGBE_AN_MODE_CL37:
 	case AXGBE_AN_MODE_CL37_SGMII:
-		PMD_DRV_LOG(ERR, "Unsupported AN_CL37\n");
+		axgbe_an37_init(pdata);
 		break;
 	default:
 		break;
@@ -782,9 +914,6 @@ static int __axgbe_phy_config_aneg(struct axgbe_port *pdata)
 	/* Disable and stop any in progress auto-negotiation */
 	axgbe_an_disable_all(pdata);
 
-	/* Clear any auto-negotitation interrupts */
-	axgbe_an_clear_interrupts_all(pdata);
-
 	pdata->an_result = AXGBE_AN_READY;
 	pdata->an_state = AXGBE_AN_READY;
 	pdata->kr_state = AXGBE_RX_BPA;
@@ -792,6 +921,7 @@ static int __axgbe_phy_config_aneg(struct axgbe_port *pdata)
 
 	/* Re-enable auto-negotiation interrupt */
 	rte_intr_enable(&pdata->pci_dev->intr_handle);
+	axgbe_an37_enable_interrupts(pdata);
 
 	axgbe_an_init(pdata);
 	axgbe_an_restart(pdata);
@@ -875,10 +1005,26 @@ static void axgbe_phy_status_result(struct axgbe_port *pdata)
 	axgbe_set_mode(pdata, mode);
 }
 
+static int autoneg_time_out(unsigned long autoneg_start_time)
+{
+	unsigned long autoneg_timeout;
+	unsigned long ticks;
+
+	autoneg_timeout = autoneg_start_time + (AXGBE_LINK_TIMEOUT *
+						2 *  rte_get_timer_hz());
+	ticks = rte_get_timer_cycles();
+	if (time_after(ticks, autoneg_timeout))
+		return 1;
+	else
+		return 0;
+}
+
 static void axgbe_phy_status(struct axgbe_port *pdata)
 {
 	unsigned int link_aneg;
-	int an_restart;
+	int an_restart, ret;
+	unsigned int reg = 0;
+	unsigned long autoneg_start_time;
 
 	if (axgbe_test_bit(AXGBE_LINK_ERR, &pdata->dev_state)) {
 		pdata->phy.link = 0;
@@ -896,8 +1042,32 @@ static void axgbe_phy_status(struct axgbe_port *pdata)
 
 	if (pdata->phy.link) {
 		if (link_aneg && !axgbe_phy_aneg_done(pdata)) {
-			axgbe_check_link_timeout(pdata);
-			return;
+			if (axgbe_cur_mode(pdata) == AXGBE_MODE_SGMII_1000) {
+				/*autoneg not complete, so re-intializing*/
+				/* and restarting it*/
+				axgbe_an_init(pdata);
+				axgbe_an_restart(pdata);
+				reg = XMDIO_READ(pdata, MDIO_MMD_VEND2,
+						 MDIO_VEND2_AN_STAT);
+				autoneg_start_time = rte_get_timer_cycles();
+				/*poll for autoneg to complete*/
+				while (!(reg & AXGBE_AN_CL37_INT_CMPLT)) {
+					ret =
+					autoneg_time_out(autoneg_start_time);
+					if (ret)
+						break;
+					reg = XMDIO_READ(pdata,
+							 MDIO_MMD_VEND2,
+							 MDIO_VEND2_AN_STAT);
+					if (reg & AXGBE_AN_CL37_INT_CMPLT) {
+						axgbe_an37_isr(pdata);
+						break;
+					}
+				}
+			} else {
+				axgbe_check_link_timeout(pdata);
+				return;
+			}
 		}
 		axgbe_phy_status_result(pdata);
 		if (axgbe_test_bit(AXGBE_LINK_INIT, &pdata->dev_state))
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index f0dc11695..a324a2bc9 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -957,6 +957,41 @@ static enum axgbe_mode axgbe_phy_an73_outcome(struct axgbe_port *pdata)
 	return mode;
 }
 
+static enum axgbe_mode axgbe_phy_an37_sgmii_outcome(struct axgbe_port *pdata)
+{
+	enum axgbe_mode mode;
+
+	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+	pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
+
+	if (pdata->phy.pause_autoneg)
+		axgbe_phy_phydev_flowctrl(pdata);
+
+	switch (pdata->an_status & AXGBE_SGMII_AN_LINK_SPEED) {
+	case AXGBE_SGMII_AN_LINK_SPEED_100:
+		if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
+			pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full;
+			mode = AXGBE_MODE_SGMII_100;
+		} else {
+			mode = AXGBE_MODE_UNKNOWN;
+		}
+		break;
+	case AXGBE_SGMII_AN_LINK_SPEED_1000:
+		if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
+			pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
+			mode = AXGBE_MODE_SGMII_1000;
+		} else {
+			/* Half-duplex not supported */
+			mode = AXGBE_MODE_UNKNOWN;
+		}
+		break;
+	default:
+		mode = AXGBE_MODE_UNKNOWN;
+		break;
+	}
+	return mode;
+}
+
 static enum axgbe_mode axgbe_phy_an_outcome(struct axgbe_port *pdata)
 {
 	switch (pdata->an_mode) {
@@ -966,6 +1001,7 @@ static enum axgbe_mode axgbe_phy_an_outcome(struct axgbe_port *pdata)
 		return axgbe_phy_an73_redrv_outcome(pdata);
 	case AXGBE_AN_MODE_CL37:
 	case AXGBE_AN_MODE_CL37_SGMII:
+		return axgbe_phy_an37_sgmii_outcome(pdata);
 	default:
 		return AXGBE_MODE_UNKNOWN;
 	}
@@ -1957,6 +1993,7 @@ static int axgbe_phy_start(struct axgbe_port *pdata)
 	default:
 		break;
 	}
+	pdata->phy.advertising &= axgbe_phy_an_advertising(pdata);
 
 	return ret;
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-01-10  8:36 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-10  8:36 [dpdk-dev] [PATCH v1 2/2] net/axgbe: auto-negotiation support enabled for 1Gbps ssardar

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.