[16/24] net/axgbe: add support for 10 Mbps speed

Message ID 20240412125249.10625-16-VenkatKumar.Ande@amd.com (mailing list archive)
State Changes Requested
Delegated to: Ferruh Yigit
Headers
Series [01/24] net/axgbe: remove use of comm_owned field |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Venkat Kumar Ande April 12, 2024, 12:52 p.m. UTC
  Add the necessary changes to support 10 Mbps speed for BaseT and SFP
port modes. This is supported in MAC ver >= 30H.

Signed-off-by: Venkat Kumar Ande <VenkatKumar.Ande@amd.com>
---
 drivers/net/axgbe/axgbe_dev.c      |  3 ++
 drivers/net/axgbe/axgbe_ethdev.h   |  2 +
 drivers/net/axgbe/axgbe_mdio.c     | 22 +++++++++
 drivers/net/axgbe/axgbe_phy.h      |  2 +
 drivers/net/axgbe/axgbe_phy_impl.c | 75 ++++++++++++++++++++++++++++--
 5 files changed, 100 insertions(+), 4 deletions(-)
  

Patch

diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 9b0073eea6..b4afcf20ab 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -250,6 +250,9 @@  static int axgbe_set_speed(struct axgbe_port *pdata, int speed)
 	unsigned int ss;
 
 	switch (speed) {
+	case SPEED_10:
+		ss = 0x07;
+		break;
 	case SPEED_1000:
 		ss = 0x03;
 		break;
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index 20b36ced55..127427c736 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -114,6 +114,7 @@ 
 
 #define AXGBE_SGMII_AN_LINK_STATUS	BIT(1)
 #define AXGBE_SGMII_AN_LINK_SPEED	(BIT(2) | BIT(3))
+#define AXGBE_SGMII_AN_LINK_SPEED_10	0x00
 #define AXGBE_SGMII_AN_LINK_SPEED_100	0x04
 #define AXGBE_SGMII_AN_LINK_SPEED_1000	0x08
 #define AXGBE_SGMII_AN_LINK_DUPLEX	BIT(4)
@@ -213,6 +214,7 @@  enum axgbe_mode {
 	AXGBE_MODE_KX_2500,
 	AXGBE_MODE_KR,
 	AXGBE_MODE_X,
+	AXGBE_MODE_SGMII_10,
 	AXGBE_MODE_SGMII_100,
 	AXGBE_MODE_SGMII_1000,
 	AXGBE_MODE_SFI,
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 151b30e2ab..4307a7560a 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -143,6 +143,15 @@  static void axgbe_sgmii_1000_mode(struct axgbe_port *pdata)
 	pdata->phy_if.phy_impl.set_mode(pdata, AXGBE_MODE_SGMII_1000);
 }
 
+static void axgbe_sgmii_10_mode(struct axgbe_port *pdata)
+{
+	/* Set MAC to 10M speed */
+	pdata->hw_if.set_speed(pdata, SPEED_10);
+
+	/* Call PHY implementation support to complete rate change */
+	pdata->phy_if.phy_impl.set_mode(pdata, AXGBE_MODE_SGMII_10);
+}
+
 static void axgbe_sgmii_100_mode(struct axgbe_port *pdata)
 {
 
@@ -176,6 +185,9 @@  static void axgbe_change_mode(struct axgbe_port *pdata,
 	case AXGBE_MODE_KR:
 		axgbe_kr_mode(pdata);
 		break;
+	case AXGBE_MODE_SGMII_10:
+		axgbe_sgmii_10_mode(pdata);
+		break;
 	case AXGBE_MODE_SGMII_100:
 		axgbe_sgmii_100_mode(pdata);
 		break;
@@ -862,6 +874,7 @@  static int axgbe_phy_config_fixed(struct axgbe_port *pdata)
 	case AXGBE_MODE_KX_1000:
 	case AXGBE_MODE_KX_2500:
 	case AXGBE_MODE_KR:
+	case AXGBE_MODE_SGMII_10:
 	case AXGBE_MODE_SGMII_100:
 	case AXGBE_MODE_SGMII_1000:
 	case AXGBE_MODE_X:
@@ -921,6 +934,8 @@  static int __axgbe_phy_config_aneg(struct axgbe_port *pdata, bool set_mode)
 			axgbe_set_mode(pdata, AXGBE_MODE_SGMII_1000);
 		} else if (axgbe_use_mode(pdata, AXGBE_MODE_SGMII_100)) {
 			axgbe_set_mode(pdata, AXGBE_MODE_SGMII_100);
+		} else if (axgbe_use_mode(pdata, AXGBE_MODE_SGMII_10)) {
+			axgbe_set_mode(pdata, AXGBE_MODE_SGMII_10);
 		} else {
 			rte_intr_enable(pdata->pci_dev->intr_handle);
 			ret = -EINVAL;
@@ -1000,6 +1015,9 @@  static void axgbe_phy_status_result(struct axgbe_port *pdata)
 		mode = axgbe_phy_status_aneg(pdata);
 
 	switch (mode) {
+	case AXGBE_MODE_SGMII_10:
+		pdata->phy.speed = SPEED_10;
+		break;
 	case AXGBE_MODE_SGMII_100:
 		pdata->phy.speed = SPEED_100;
 		break;
@@ -1148,6 +1166,8 @@  static int axgbe_phy_start(struct axgbe_port *pdata)
 		axgbe_sgmii_1000_mode(pdata);
 	} else if (axgbe_use_mode(pdata, AXGBE_MODE_SGMII_100)) {
 		axgbe_sgmii_100_mode(pdata);
+	} else if (axgbe_use_mode(pdata, AXGBE_MODE_SGMII_10)) {
+		axgbe_sgmii_10_mode(pdata);
 	} else {
 		ret = -EINVAL;
 		goto err_stop;
@@ -1195,6 +1215,8 @@  static int axgbe_phy_best_advertised_speed(struct axgbe_port *pdata)
 		return SPEED_1000;
 	else if (pdata->phy.advertising & ADVERTISED_100baseT_Full)
 		return SPEED_100;
+	else if (pdata->phy.advertising & ADVERTISED_10baseT_Full)
+		return SPEED_10;
 
 	return SPEED_UNKNOWN;
 }
diff --git a/drivers/net/axgbe/axgbe_phy.h b/drivers/net/axgbe/axgbe_phy.h
index 77ee20a31a..5b844e81cd 100644
--- a/drivers/net/axgbe/axgbe_phy.h
+++ b/drivers/net/axgbe/axgbe_phy.h
@@ -168,6 +168,7 @@ 
 #define ADVERTISED_1000baseKX_Full	(1 << 17)
 #define ADVERTISED_1000baseT_Full	(1 << 5)
 #define ADVERTISED_100baseT_Full	(1 << 3)
+#define ADVERTISED_10baseT_Full		(1 << 2)
 #define ADVERTISED_TP			(1 << 7)
 #define ADVERTISED_FIBRE		(1 << 10)
 #define ADVERTISED_Backplane            (1 << 16)
@@ -175,6 +176,7 @@ 
 #define SUPPORTED_1000baseKX_Full       (1 << 17)
 #define SUPPORTED_10000baseKR_Full      (1 << 19)
 #define SUPPORTED_2500baseX_Full	(1 << 15)
+#define SUPPORTED_10baseT_Full		(1 << 3)
 #define SUPPORTED_100baseT_Full         (1 << 2)
 #define SUPPORTED_1000baseT_Full        (1 << 5)
 #define SUPPORTED_10000baseT_Full       (1 << 12)
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 67a18e7c55..9c2c411b4f 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -7,6 +7,7 @@ 
 #include "axgbe_common.h"
 #include "axgbe_phy.h"
 
+#define AXGBE_PHY_PORT_SPEED_10		BIT(0)
 #define AXGBE_PHY_PORT_SPEED_100	BIT(1)
 #define AXGBE_PHY_PORT_SPEED_1000	BIT(2)
 #define AXGBE_PHY_PORT_SPEED_2500	BIT(3)
@@ -490,6 +491,8 @@  static void axgbe_phy_sfp_phy_settings(struct axgbe_port *pdata)
 
 	switch (phy_data->sfp_speed) {
 	case AXGBE_SFP_SPEED_100_1000:
+		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)
+			pdata->phy.advertising |= ADVERTISED_10baseT_Full;
 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100)
 			pdata->phy.advertising |= ADVERTISED_100baseT_Full;
 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)
@@ -511,6 +514,8 @@  static void axgbe_phy_sfp_phy_settings(struct axgbe_port *pdata)
 			pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
 		else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100)
 			pdata->phy.advertising |= ADVERTISED_100baseT_Full;
+		else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)
+			pdata->phy.advertising |= ADVERTISED_10baseT_Full;
 	}
 }
 
@@ -980,6 +985,14 @@  static enum axgbe_mode axgbe_phy_an37_sgmii_outcome(struct axgbe_port *pdata)
 		axgbe_phy_phydev_flowctrl(pdata);
 
 	switch (pdata->an_status & AXGBE_SGMII_AN_LINK_SPEED) {
+	case AXGBE_SGMII_AN_LINK_SPEED_10:
+		if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
+			pdata->phy.lp_advertising |= ADVERTISED_10baseT_Full;
+			mode = AXGBE_MODE_SGMII_10;
+		} else {
+			mode = AXGBE_MODE_UNKNOWN;
+		}
+		break;
 	case AXGBE_SGMII_AN_LINK_SPEED_100:
 		if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
 			pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full;
@@ -1347,6 +1360,18 @@  static void axgbe_phy_sgmii_1000_mode(struct axgbe_port *pdata)
 	phy_data->cur_mode = AXGBE_MODE_SGMII_1000;
 }
 
+static void axgbe_phy_sgmii_10_mode(struct axgbe_port *pdata)
+{
+	struct axgbe_phy_data *phy_data = pdata->phy_data;
+
+	axgbe_phy_set_redrv_mode(pdata);
+
+	/* 10M/SGMII */
+	axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_1G, AXGBE_MB_SUBCMD_10MBITS);
+
+	phy_data->cur_mode = AXGBE_MODE_SGMII_10;
+}
+
 static enum axgbe_mode axgbe_phy_cur_mode(struct axgbe_port *pdata)
 {
 	struct axgbe_phy_data *phy_data = pdata->phy_data;
@@ -1363,6 +1388,7 @@  static enum axgbe_mode axgbe_phy_switch_baset_mode(struct axgbe_port *pdata)
 		return axgbe_phy_cur_mode(pdata);
 
 	switch (axgbe_phy_cur_mode(pdata)) {
+	case AXGBE_MODE_SGMII_10:
 	case AXGBE_MODE_SGMII_100:
 	case AXGBE_MODE_SGMII_1000:
 		return AXGBE_MODE_KR;
@@ -1433,6 +1459,8 @@  static enum axgbe_mode axgbe_phy_get_baset_mode(struct axgbe_phy_data *phy_data
 						int speed)
 {
 	switch (speed) {
+	case SPEED_10:
+		return AXGBE_MODE_SGMII_10;
 	case SPEED_100:
 		return AXGBE_MODE_SGMII_100;
 	case SPEED_1000:
@@ -1448,6 +1476,8 @@  static enum axgbe_mode axgbe_phy_get_sfp_mode(struct axgbe_phy_data *phy_data,
 					      int speed)
 {
 	switch (speed) {
+	case SPEED_10:
+		return AXGBE_MODE_SGMII_10;
 	case SPEED_100:
 		return AXGBE_MODE_SGMII_100;
 	case SPEED_1000:
@@ -1525,6 +1555,9 @@  static void axgbe_phy_set_mode(struct axgbe_port *pdata, enum axgbe_mode mode)
 	case AXGBE_MODE_SGMII_1000:
 		axgbe_phy_sgmii_1000_mode(pdata);
 		break;
+	case AXGBE_MODE_SGMII_10:
+		axgbe_phy_sgmii_10_mode(pdata);
+		break;
 	default:
 		break;
 	}
@@ -1566,6 +1599,9 @@  static bool axgbe_phy_use_baset_mode(struct axgbe_port *pdata,
 				     enum axgbe_mode mode)
 {
 	switch (mode) {
+	case AXGBE_MODE_SGMII_10:
+		return axgbe_phy_check_mode(pdata, mode,
+					    ADVERTISED_10baseT_Full);
 	case AXGBE_MODE_SGMII_100:
 		return axgbe_phy_check_mode(pdata, mode,
 					    ADVERTISED_100baseT_Full);
@@ -1591,6 +1627,11 @@  static bool axgbe_phy_use_sfp_mode(struct axgbe_port *pdata,
 			return false;
 		return axgbe_phy_check_mode(pdata, mode,
 					    ADVERTISED_1000baseT_Full);
+	case AXGBE_MODE_SGMII_10:
+		if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T)
+			return false;
+		return axgbe_phy_check_mode(pdata, mode,
+					    ADVERTISED_10baseT_Full);
 	case AXGBE_MODE_SGMII_100:
 		if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T)
 			return false;
@@ -1803,6 +1844,12 @@  static int axgbe_phy_mdio_reset_setup(struct axgbe_port *pdata)
 static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata)
 {
 	struct axgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int ver;
+
+	/* 10 Mbps speed is not supported in ver < 30H */
+	ver = AXGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
+	if (ver < 0x30 && phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)
+		return true;
 
 	switch (phy_data->port_mode) {
 	case AXGBE_PORT_MODE_BACKPLANE:
@@ -1816,7 +1863,8 @@  static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata)
 			return false;
 		break;
 	case AXGBE_PORT_MODE_1000BASE_T:
-		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
+		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)  ||
+			(phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000))
 			return false;
 		break;
@@ -1825,13 +1873,15 @@  static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata)
 			return false;
 		break;
 	case AXGBE_PORT_MODE_NBASE_T:
-		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
+		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)  ||
+			(phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500))
 			return false;
 		break;
 	case AXGBE_PORT_MODE_10GBASE_T:
-		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
+		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)  ||
+		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000))
 			return false;
@@ -1841,7 +1891,8 @@  static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata)
 			return false;
 		break;
 	case AXGBE_PORT_MODE_SFP:
-		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
+		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)  ||
+			(phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000))
 			return false;
@@ -2150,6 +2201,10 @@  static int axgbe_phy_init(struct axgbe_port *pdata)
 		pdata->phy.supported |= SUPPORTED_Autoneg;
 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
 		pdata->phy.supported |= SUPPORTED_TP;
+		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) {
+			pdata->phy.supported |= SUPPORTED_10baseT_Full;
+			phy_data->start_mode = AXGBE_MODE_SGMII_10;
+		}
 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
@@ -2178,6 +2233,10 @@  static int axgbe_phy_init(struct axgbe_port *pdata)
 		pdata->phy.supported |= SUPPORTED_Autoneg;
 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
 		pdata->phy.supported |= SUPPORTED_TP;
+		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) {
+			pdata->phy.supported |= SUPPORTED_10baseT_Full;
+			phy_data->start_mode = AXGBE_MODE_SGMII_10;
+		}
 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
@@ -2199,6 +2258,10 @@  static int axgbe_phy_init(struct axgbe_port *pdata)
 		pdata->phy.supported |= SUPPORTED_Autoneg;
 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
 		pdata->phy.supported |= SUPPORTED_TP;
+		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) {
+			pdata->phy.supported |= SUPPORTED_10baseT_Full;
+			phy_data->start_mode = AXGBE_MODE_SGMII_10;
+		}
 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
@@ -2234,6 +2297,10 @@  static int axgbe_phy_init(struct axgbe_port *pdata)
 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
 		pdata->phy.supported |= SUPPORTED_TP;
 		pdata->phy.supported |= SUPPORTED_FIBRE;
+		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) {
+			pdata->phy.supported |= SUPPORTED_10baseT_Full;
+			phy_data->start_mode = AXGBE_MODE_SGMII_10;
+		}
 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
 			phy_data->start_mode = AXGBE_MODE_SGMII_100;