DPDK patches and discussions
 help / color / mirror / Atom feed
From: Jiawen Wu <jiawenwu@trustnetic.com>
To: dev@dpdk.org
Cc: Jiawen Wu <jiawenwu@trustnetic.com>
Subject: [PATCH v2 06/12] net/ngbe: add support to custom PHY interfaces
Date: Wed,  9 Feb 2022 18:42:07 +0800	[thread overview]
Message-ID: <20220209104213.602728-7-jiawenwu@trustnetic.com> (raw)
In-Reply-To: <20220209104213.602728-1-jiawenwu@trustnetic.com>

Support sub_device ID 61/62/64 for YT8521S SFP, and 51/52 for M88E1512
PHY.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 doc/guides/rel_notes/release_22_03.rst |   7 +
 drivers/net/ngbe/base/ngbe_devids.h    |  12 +-
 drivers/net/ngbe/base/ngbe_hw.c        |  50 +++++--
 drivers/net/ngbe/base/ngbe_phy.c       |  27 ++--
 drivers/net/ngbe/base/ngbe_phy.h       |   2 +-
 drivers/net/ngbe/base/ngbe_phy_mvl.c   |  55 +++++++-
 drivers/net/ngbe/base/ngbe_phy_mvl.h   |   5 +
 drivers/net/ngbe/base/ngbe_phy_yt.c    | 182 +++++++++++++++++++++----
 drivers/net/ngbe/base/ngbe_phy_yt.h    |  19 ++-
 drivers/net/ngbe/base/ngbe_type.h      |   8 ++
 drivers/net/ngbe/ngbe_ethdev.c         |   6 +-
 11 files changed, 314 insertions(+), 59 deletions(-)

diff --git a/doc/guides/rel_notes/release_22_03.rst b/doc/guides/rel_notes/release_22_03.rst
index 746f50e84f..233c34a2d0 100644
--- a/doc/guides/rel_notes/release_22_03.rst
+++ b/doc/guides/rel_notes/release_22_03.rst
@@ -69,6 +69,13 @@ New Features
   * Added AES-XCBC support in lookaside protocol (IPsec) for CN9K & CN10K.
   * Added AES-CMAC support in CN9K & CN10K.
 
+* **Updated Wangxun ngbe driver.**
+
+  * Added support for devices of custom PHY interfaces.
+    - M88E1512 PHY connects to RJ45
+    - M88E1512 PHY connects to RGMII combo
+    - YT8521S PHY connects to SFP
+
 * **Added an API to retrieve event port id of ethdev Rx adapter.**
 
   The new API ``rte_event_eth_rx_adapter_event_port_get()`` was added.
diff --git a/drivers/net/ngbe/base/ngbe_devids.h b/drivers/net/ngbe/base/ngbe_devids.h
index 6010cc050e..83eedf423e 100644
--- a/drivers/net/ngbe/base/ngbe_devids.h
+++ b/drivers/net/ngbe/base/ngbe_devids.h
@@ -19,9 +19,11 @@
 #define   NGBE_SUB_DEV_ID_EM_VF			0x0110
 #define NGBE_DEV_ID_EM				0x0100
 #define   NGBE_SUB_DEV_ID_EM_MVL_RGMII		0x0200
+#define   NGBE_SUB_DEV_ID_EM_MVL_MIX		0x0252
 #define   NGBE_SUB_DEV_ID_EM_MVL_SFP		0x0403
 #define   NGBE_SUB_DEV_ID_EM_RTL_SGMII		0x0410
 #define   NGBE_SUB_DEV_ID_EM_YT8521S_SFP	0x0460
+#define   NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP	0x0461
 
 #define NGBE_DEV_ID_EM_WX1860AL_W		0x0100
 #define NGBE_DEV_ID_EM_WX1860AL_W_VF		0x0110
@@ -67,15 +69,19 @@
 #define   NGBE_SUB_DEV_ID_EM_SF400_LY_YT	0x0470
 
 /* Assign excessive id with masks */
-#define NGBE_INTERNAL_MASK			0x000F
-#define NGBE_OEM_MASK				0x00F0
+#define NGBE_OEM_MASK				0x00FF
 #define NGBE_WOL_SUP_MASK			0x4000
 #define NGBE_NCSI_SUP_MASK			0x8000
 
-#define NGBE_INTERNAL_SFP			0x0003
+#define NGBE_M88E1512_SFP			0x0003
 #define NGBE_OCP_CARD				0x0040
 #define NGBE_LY_M88E1512_SFP			0x0050
+#define NGBE_M88E1512_RJ45			0x0051
+#define NGBE_M88E1512_MIX			0x0052
 #define NGBE_YT8521S_SFP			0x0060
+#define NGBE_INTERNAL_YT8521S_SFP		0x0061
+#define NGBE_YT8521S_SFP_GPIO			0x0062
+#define NGBE_INTERNAL_YT8521S_SFP_GPIO		0x0064
 #define NGBE_LY_YT8521S_SFP			0x0070
 #define NGBE_WOL_SUP				0x4000
 #define NGBE_NCSI_SUP				0x8000
diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c
index 72d475ccf9..67e4b4a6fd 100644
--- a/drivers/net/ngbe/base/ngbe_hw.c
+++ b/drivers/net/ngbe/base/ngbe_hw.c
@@ -124,8 +124,7 @@ ngbe_reset_misc_em(struct ngbe_hw *hw)
 
 	wr32m(hw, NGBE_GPIE, NGBE_GPIE_MSIX, NGBE_GPIE_MSIX);
 
-	if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP ||
-		(hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) {
+	if (hw->gpio_ctl) {
 		/* gpio0 is used to power on/off control*/
 		wr32(hw, NGBE_GPIODIR, NGBE_GPIODIR_DDR(1));
 		wr32(hw, NGBE_GPIODATA, NGBE_GPIOBIT_0);
@@ -1617,19 +1616,21 @@ s32 ngbe_get_link_capabilities_em(struct ngbe_hw *hw,
 				      bool *autoneg)
 {
 	s32 status = 0;
-
+	u16 value = 0;
 	DEBUGFUNC("\n");
 
 	hw->mac.autoneg = *autoneg;
 
-	switch (hw->sub_device_id) {
-	case NGBE_SUB_DEV_ID_EM_RTL_SGMII:
+	if (hw->phy.type == ngbe_phy_rtl) {
 		*speed = NGBE_LINK_SPEED_1GB_FULL |
 			NGBE_LINK_SPEED_100M_FULL |
 			NGBE_LINK_SPEED_10M_FULL;
-		break;
-	default:
-		break;
+	}
+
+	if (hw->phy.type == ngbe_phy_yt8521s_sfi) {
+		ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
+		if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1))
+			*speed = NGBE_LINK_SPEED_1GB_FULL;
 	}
 
 	return status;
@@ -1815,11 +1816,23 @@ s32 ngbe_set_mac_type(struct ngbe_hw *hw)
 	case NGBE_SUB_DEV_ID_EM_MVL_RGMII:
 		hw->phy.media_type = ngbe_media_type_copper;
 		hw->mac.type = ngbe_mac_em;
+		hw->mac.link_type = ngbe_link_copper;
+		break;
+	case NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP:
+		hw->phy.media_type = ngbe_media_type_copper;
+		hw->mac.type = ngbe_mac_em;
+		hw->mac.link_type = ngbe_link_fiber;
 		break;
 	case NGBE_SUB_DEV_ID_EM_MVL_SFP:
 	case NGBE_SUB_DEV_ID_EM_YT8521S_SFP:
 		hw->phy.media_type = ngbe_media_type_fiber;
 		hw->mac.type = ngbe_mac_em;
+		hw->mac.link_type = ngbe_link_fiber;
+		break;
+	case NGBE_SUB_DEV_ID_EM_MVL_MIX:
+		hw->phy.media_type = ngbe_media_type_unknown;
+		hw->mac.type = ngbe_mac_em;
+		hw->mac.link_type = ngbe_link_type_unknown;
 		break;
 	case NGBE_SUB_DEV_ID_EM_VF:
 		hw->phy.media_type = ngbe_media_type_virtual;
@@ -1871,7 +1884,7 @@ s32 ngbe_enable_rx_dma(struct ngbe_hw *hw, u32 regval)
 void ngbe_map_device_id(struct ngbe_hw *hw)
 {
 	u16 oem = hw->sub_system_id & NGBE_OEM_MASK;
-	u16 internal = hw->sub_system_id & NGBE_INTERNAL_MASK;
+
 	hw->is_pf = true;
 
 	/* move subsystem_device_id to device_id */
@@ -1905,20 +1918,31 @@ void ngbe_map_device_id(struct ngbe_hw *hw)
 	case NGBE_DEV_ID_EM_WX1860A1:
 	case NGBE_DEV_ID_EM_WX1860A1L:
 		hw->device_id = NGBE_DEV_ID_EM;
-		if (oem == NGBE_LY_M88E1512_SFP ||
-				internal == NGBE_INTERNAL_SFP)
+		if (oem == NGBE_M88E1512_SFP || oem == NGBE_LY_M88E1512_SFP)
 			hw->sub_device_id = NGBE_SUB_DEV_ID_EM_MVL_SFP;
-		else if (hw->sub_system_id == NGBE_SUB_DEV_ID_EM_M88E1512_RJ45)
+		else if (oem == NGBE_M88E1512_RJ45 ||
+			(hw->sub_system_id == NGBE_SUB_DEV_ID_EM_M88E1512_RJ45))
 			hw->sub_device_id = NGBE_SUB_DEV_ID_EM_MVL_RGMII;
+		else if (oem == NGBE_M88E1512_MIX)
+			hw->sub_device_id = NGBE_SUB_DEV_ID_EM_MVL_MIX;
 		else if (oem == NGBE_YT8521S_SFP ||
-				oem == NGBE_LY_YT8521S_SFP)
+			 oem == NGBE_YT8521S_SFP_GPIO ||
+			 oem == NGBE_LY_YT8521S_SFP)
 			hw->sub_device_id = NGBE_SUB_DEV_ID_EM_YT8521S_SFP;
+		else if (oem == NGBE_INTERNAL_YT8521S_SFP ||
+			 oem == NGBE_INTERNAL_YT8521S_SFP_GPIO)
+			hw->sub_device_id = NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP;
 		else
 			hw->sub_device_id = NGBE_SUB_DEV_ID_EM_RTL_SGMII;
 		break;
 	default:
 		break;
 	}
+
+	if (oem == NGBE_LY_M88E1512_SFP || oem == NGBE_YT8521S_SFP_GPIO ||
+			oem == NGBE_INTERNAL_YT8521S_SFP_GPIO ||
+			oem == NGBE_LY_YT8521S_SFP)
+		hw->gpio_ctl = true;
 }
 
 /**
diff --git a/drivers/net/ngbe/base/ngbe_phy.c b/drivers/net/ngbe/base/ngbe_phy.c
index 51b0a2ec60..93450b2977 100644
--- a/drivers/net/ngbe/base/ngbe_phy.c
+++ b/drivers/net/ngbe/base/ngbe_phy.c
@@ -54,8 +54,7 @@ static bool ngbe_probe_phy(struct ngbe_hw *hw, u16 phy_addr)
 	if (ngbe_get_phy_id(hw))
 		return false;
 
-	hw->phy.type = ngbe_get_phy_type_from_id(hw);
-	if (hw->phy.type == ngbe_phy_unknown)
+	if (ngbe_get_phy_type_from_id(hw))
 		return false;
 
 	return true;
@@ -174,37 +173,39 @@ s32 ngbe_get_phy_id(struct ngbe_hw *hw)
 
 /**
  *  ngbe_get_phy_type_from_id - Get the phy type
- *  @phy_id: PHY ID information
  *
  **/
-enum ngbe_phy_type ngbe_get_phy_type_from_id(struct ngbe_hw *hw)
+s32 ngbe_get_phy_type_from_id(struct ngbe_hw *hw)
 {
-	enum ngbe_phy_type phy_type;
+	s32 status = 0;
 
 	DEBUGFUNC("ngbe_get_phy_type_from_id");
 
 	switch (hw->phy.id) {
 	case NGBE_PHYID_RTL:
-		phy_type = ngbe_phy_rtl;
+		hw->phy.type = ngbe_phy_rtl;
 		break;
 	case NGBE_PHYID_MVL:
 		if (hw->phy.media_type == ngbe_media_type_fiber)
-			phy_type = ngbe_phy_mvl_sfi;
+			hw->phy.type = ngbe_phy_mvl_sfi;
+		else if (hw->phy.media_type == ngbe_media_type_copper)
+			hw->phy.type = ngbe_phy_mvl;
 		else
-			phy_type = ngbe_phy_mvl;
+			status = ngbe_check_phy_mode_mvl(hw);
 		break;
 	case NGBE_PHYID_YT:
 		if (hw->phy.media_type == ngbe_media_type_fiber)
-			phy_type = ngbe_phy_yt8521s_sfi;
+			hw->phy.type = ngbe_phy_yt8521s_sfi;
 		else
-			phy_type = ngbe_phy_yt8521s;
+			hw->phy.type = ngbe_phy_yt8521s;
 		break;
 	default:
-		phy_type = ngbe_phy_unknown;
+		hw->phy.type = ngbe_phy_unknown;
+		status = NGBE_ERR_DEVICE_NOT_SUPPORTED;
 		break;
 	}
 
-	return phy_type;
+	return status;
 }
 
 /**
@@ -400,11 +401,13 @@ s32 ngbe_init_phy(struct ngbe_hw *hw)
 
 	switch (hw->sub_device_id) {
 	case NGBE_SUB_DEV_ID_EM_RTL_SGMII:
+	case NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP:
 		hw->phy.read_reg_unlocked = ngbe_read_phy_reg_rtl;
 		hw->phy.write_reg_unlocked = ngbe_write_phy_reg_rtl;
 		break;
 	case NGBE_SUB_DEV_ID_EM_MVL_RGMII:
 	case NGBE_SUB_DEV_ID_EM_MVL_SFP:
+	case NGBE_SUB_DEV_ID_EM_MVL_MIX:
 		hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl;
 		hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl;
 		break;
diff --git a/drivers/net/ngbe/base/ngbe_phy.h b/drivers/net/ngbe/base/ngbe_phy.h
index f262ff3350..e93d6a4c4a 100644
--- a/drivers/net/ngbe/base/ngbe_phy.h
+++ b/drivers/net/ngbe/base/ngbe_phy.h
@@ -48,7 +48,7 @@ typedef struct mdi_reg mdi_reg_t;
 s32 ngbe_mdi_map_register(mdi_reg_t *reg, mdi_reg_22_t *reg22);
 
 bool ngbe_validate_phy_addr(struct ngbe_hw *hw, u32 phy_addr);
-enum ngbe_phy_type ngbe_get_phy_type_from_id(struct ngbe_hw *hw);
+s32 ngbe_get_phy_type_from_id(struct ngbe_hw *hw);
 s32 ngbe_get_phy_id(struct ngbe_hw *hw);
 s32 ngbe_identify_phy(struct ngbe_hw *hw);
 s32 ngbe_reset_phy(struct ngbe_hw *hw);
diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.c b/drivers/net/ngbe/base/ngbe_phy_mvl.c
index 2eb351d258..8a4df90a42 100644
--- a/drivers/net/ngbe/base/ngbe_phy_mvl.c
+++ b/drivers/net/ngbe/base/ngbe_phy_mvl.c
@@ -48,6 +48,31 @@ s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw,
 	return 0;
 }
 
+s32 ngbe_check_phy_mode_mvl(struct ngbe_hw *hw)
+{
+	u16 value = 0;
+
+	/* select page 18 reg 20 */
+	ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 18);
+	ngbe_read_phy_reg_mdi(hw, MVL_GEN_CTL, 0, &value);
+	if (MVL_GEN_CTL_MODE(value) == MVL_GEN_CTL_MODE_COPPER) {
+		/* mode select to RGMII-to-copper */
+		hw->phy.type = ngbe_phy_mvl;
+		hw->phy.media_type = ngbe_media_type_copper;
+		hw->mac.link_type = ngbe_link_copper;
+	} else if (MVL_GEN_CTL_MODE(value) == MVL_GEN_CTL_MODE_FIBER) {
+		/* mode select to RGMII-to-sfi */
+		hw->phy.type = ngbe_phy_mvl_sfi;
+		hw->phy.media_type = ngbe_media_type_fiber;
+		hw->mac.link_type = ngbe_link_fiber;
+	} else {
+		DEBUGOUT("marvell 88E1512 mode %x is not supported.\n", value);
+		return NGBE_ERR_DEVICE_NOT_SUPPORTED;
+	}
+
+	return 0;
+}
+
 s32 ngbe_init_phy_mvl(struct ngbe_hw *hw)
 {
 	s32 ret_val = 0;
@@ -125,6 +150,29 @@ s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, u32 speed,
 	hw->phy.autoneg_advertised = 0;
 
 	if (hw->phy.type == ngbe_phy_mvl) {
+		if (!hw->mac.autoneg) {
+			switch (speed) {
+			case NGBE_LINK_SPEED_1GB_FULL:
+				value = MVL_CTRL_SPEED_SELECT1;
+				break;
+			case NGBE_LINK_SPEED_100M_FULL:
+				value = MVL_CTRL_SPEED_SELECT0;
+				break;
+			case NGBE_LINK_SPEED_10M_FULL:
+				value = 0;
+				break;
+			default:
+				value = MVL_CTRL_SPEED_SELECT0 |
+					MVL_CTRL_SPEED_SELECT1;
+				DEBUGOUT("unknown speed = 0x%x.\n", speed);
+				break;
+			}
+			/* duplex full */
+			value |= MVL_CTRL_DUPLEX | MVL_CTRL_RESET;
+			ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value);
+
+			goto skip_an;
+		}
 		if (speed & NGBE_LINK_SPEED_1GB_FULL) {
 			value_r9 |= MVL_PHY_1000BASET_FULL;
 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
@@ -162,7 +210,12 @@ s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, u32 speed,
 		hw->phy.write_reg(hw, MVL_ANA, 0, value);
 	}
 
-	value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE;
+	value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE | MVL_CTRL_RESET;
+	ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value);
+
+skip_an:
+	ngbe_read_phy_reg_mdi(hw, MVL_CTRL, 0, &value);
+	value |= MVL_CTRL_PWDN;
 	ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value);
 
 	hw->phy.read_reg(hw, MVL_INTR, 0, &value);
diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.h b/drivers/net/ngbe/base/ngbe_phy_mvl.h
index a2b5202d4b..8aee236390 100644
--- a/drivers/net/ngbe/base/ngbe_phy_mvl.h
+++ b/drivers/net/ngbe/base/ngbe_phy_mvl.h
@@ -12,8 +12,12 @@
 /* Page 0 for Copper, Page 1 for Fiber */
 #define MVL_CTRL			0x0
 #define   MVL_CTRL_RESET		MS16(15, 0x1)
+#define	  MVL_CTRL_SPEED_SELECT0	MS16(13, 0x1)
 #define   MVL_CTRL_ANE			MS16(12, 0x1)
+#define   MVL_CTRL_PWDN			MS16(11, 0x1)
 #define   MVL_CTRL_RESTART_AN		MS16(9, 0x1)
+#define   MVL_CTRL_DUPLEX		MS16(8, 0x1)
+#define	  MVL_CTRL_SPEED_SELECT1	MS16(6, 0x1)
 #define MVL_ANA				0x4
 /* copper */
 #define   MVL_CANA_ASM_PAUSE		MS16(11, 0x1)
@@ -86,6 +90,7 @@ s32 ngbe_read_phy_reg_mvl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
 			u16 *phy_data);
 s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
 			u16 phy_data);
+s32 ngbe_check_phy_mode_mvl(struct ngbe_hw *hw);
 s32 ngbe_init_phy_mvl(struct ngbe_hw *hw);
 
 s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw);
diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c
index 8db0f9ce48..2d184a1c30 100644
--- a/drivers/net/ngbe/base/ngbe_phy_yt.c
+++ b/drivers/net/ngbe/base/ngbe_phy_yt.c
@@ -104,23 +104,22 @@ s32 ngbe_init_phy_yt(struct ngbe_hw *hw)
 
 	DEBUGFUNC("ngbe_init_phy_yt");
 
-	if (hw->phy.type != ngbe_phy_yt8521s_sfi)
-		return 0;
-
-	/* select sds area register */
+	/* close sds area register */
 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
 	/* enable interrupts */
-	ngbe_write_phy_reg_mdi(hw, YT_INTR, 0, YT_INTR_ENA_MASK);
-
-	/* select fiber_to_rgmii first in multiplex */
-	ngbe_read_phy_reg_ext_yt(hw, YT_MISC, 0, &value);
-	value |= YT_MISC_FIBER_PRIO;
-	ngbe_write_phy_reg_ext_yt(hw, YT_MISC, 0, value);
+	ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
+				YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
 
+	/* power down in fiber mode */
 	hw->phy.read_reg(hw, YT_BCR, 0, &value);
 	value |= YT_BCR_PWDN;
 	hw->phy.write_reg(hw, YT_BCR, 0, value);
 
+	/* power down in UTP mode */
+	ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
+	value |= YT_BCR_PWDN;
+	ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
+
 	return 0;
 }
 
@@ -136,15 +135,44 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
 
 	hw->phy.autoneg_advertised = 0;
 
-	if (hw->phy.type == ngbe_phy_yt8521s) {
+	/* check chip_mode first */
+	ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
+	if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(0)) {
+		/* UTP to rgmii */
+		if (!hw->mac.autoneg) {
+			switch (speed) {
+			case NGBE_LINK_SPEED_1GB_FULL:
+				value = YT_BCR_SPEED_SELECT1;
+				break;
+			case NGBE_LINK_SPEED_100M_FULL:
+				value = YT_BCR_SPEED_SELECT0;
+				break;
+			case NGBE_LINK_SPEED_10M_FULL:
+				value = 0;
+				break;
+			default:
+				value = YT_BCR_SPEED_SELECT0 |
+					YT_BCR_SPEED_SELECT1;
+				DEBUGOUT("unknown speed = 0x%x.\n",
+					speed);
+				break;
+			}
+			/* duplex full */
+			value |= YT_BCR_DUPLEX | YT_BCR_RESET;
+			hw->phy.write_reg(hw, YT_BCR, 0, value);
+
+			goto skip_an;
+		}
+
 		/*disable 100/10base-T Self-negotiation ability*/
 		hw->phy.read_reg(hw, YT_ANA, 0, &value);
-		value &= ~(YT_ANA_100BASET_FULL | YT_ANA_10BASET_FULL);
+		value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
+			YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
 		hw->phy.write_reg(hw, YT_ANA, 0, value);
 
 		/*disable 1000base-T Self-negotiation ability*/
 		hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
-		value &= ~YT_MS_1000BASET_FULL;
+		value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
 		hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
 
 		if (speed & NGBE_LINK_SPEED_1GB_FULL) {
@@ -172,9 +200,15 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
 
 		/* software reset to make the above configuration take effect*/
 		hw->phy.read_reg(hw, YT_BCR, 0, &value);
-		value |= YT_BCR_RESET;
+		value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
 		hw->phy.write_reg(hw, YT_BCR, 0, value);
-	} else {
+skip_an:
+		/* power on in UTP mode */
+		ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
+		value &= ~YT_BCR_PWDN;
+		ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
+	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1)) {
+		/* fiber to rgmii */
 		hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
 
 		/* RGMII_Config1 : Config rx and tx training delay */
@@ -190,6 +224,88 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
 		/* software reset */
 		ngbe_write_phy_reg_sds_ext_yt(hw, 0x0, 0, 0x9140);
 
+		/* power on phy */
+		hw->phy.read_reg(hw, YT_BCR, 0, &value);
+		value &= ~YT_BCR_PWDN;
+		hw->phy.write_reg(hw, YT_BCR, 0, value);
+	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(2)) {
+		/* power on in UTP mode */
+		ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
+		value &= ~YT_BCR_PWDN;
+		ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
+		/* power down in fiber mode */
+		hw->phy.read_reg(hw, YT_BCR, 0, &value);
+		value &= ~YT_BCR_PWDN;
+		hw->phy.write_reg(hw, YT_BCR, 0, value);
+
+		hw->phy.read_reg(hw, YT_SPST, 0, &value);
+		if (value & YT_SPST_LINK) {
+			/* fiber up */
+			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
+		} else {
+			/* utp up */
+			/*disable 100/10base-T Self-negotiation ability*/
+			hw->phy.read_reg(hw, YT_ANA, 0, &value);
+			value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
+				YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
+			hw->phy.write_reg(hw, YT_ANA, 0, value);
+
+			/*disable 1000base-T Self-negotiation ability*/
+			hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
+			value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
+			hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
+
+			if (speed & NGBE_LINK_SPEED_1GB_FULL) {
+				hw->phy.autoneg_advertised |=
+						NGBE_LINK_SPEED_1GB_FULL;
+				value_r9 |= YT_MS_1000BASET_FULL;
+			}
+			if (speed & NGBE_LINK_SPEED_100M_FULL) {
+				hw->phy.autoneg_advertised |=
+						NGBE_LINK_SPEED_100M_FULL;
+				value_r4 |= YT_ANA_100BASET_FULL;
+			}
+			if (speed & NGBE_LINK_SPEED_10M_FULL) {
+				hw->phy.autoneg_advertised |=
+						NGBE_LINK_SPEED_10M_FULL;
+				value_r4 |= YT_ANA_10BASET_FULL;
+			}
+
+			/* enable 1000base-T Self-negotiation ability */
+			hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
+			value |= value_r9;
+			hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
+
+			/* enable 100/10base-T Self-negotiation ability */
+			hw->phy.read_reg(hw, YT_ANA, 0, &value);
+			value |= value_r4;
+			hw->phy.write_reg(hw, YT_ANA, 0, value);
+
+			/* software reset to make the above configuration
+			 * take effect
+			 */
+			hw->phy.read_reg(hw, YT_BCR, 0, &value);
+			value |= YT_BCR_RESET;
+			hw->phy.write_reg(hw, YT_BCR, 0, value);
+		}
+	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(4)) {
+		hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
+
+		ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, &value);
+		value |= YT_RGMII_CONF1_MODE;
+		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
+
+		ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, &value);
+		value &= ~(YT_RGMII_CONF2_SPEED_MASK | YT_RGMII_CONF2_DUPLEX |
+			YT_RGMII_CONF2_LINKUP);
+		value |= YT_RGMII_CONF2_SPEED(2) | YT_RGMII_CONF2_DUPLEX |
+			YT_RGMII_CONF2_LINKUP;
+		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, value);
+
+		ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
+		value &= ~YT_SMI_PHY_SW_RST;
+		ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
+
 		/* power on phy */
 		hw->phy.read_reg(hw, YT_BCR, 0, &value);
 		value &= ~YT_BCR_PWDN;
@@ -214,16 +330,34 @@ s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
 		hw->phy.type != ngbe_phy_yt8521s_sfi)
 		return NGBE_ERR_PHY_TYPE;
 
-	status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
-	/* sds software reset */
-	ctrl |= YT_BCR_RESET;
-	status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
-
-	for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
+	/* check chip_mode first */
+	ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &ctrl);
+	if (ctrl & YT_CHIP_MODE_MASK) {
+		/* fiber to rgmii */
 		status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
-		if (!(ctrl & YT_BCR_RESET))
-			break;
-		msleep(1);
+		/* sds software reset */
+		ctrl |= YT_BCR_RESET;
+		status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
+
+		for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
+			status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
+			if (!(ctrl & YT_BCR_RESET))
+				break;
+			msleep(1);
+		}
+	} else {
+		/* UTP to rgmii */
+		status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
+		/* sds software reset */
+		ctrl |= YT_BCR_RESET;
+		status = ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, ctrl);
+
+		for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
+			status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
+			if (!(ctrl & YT_BCR_RESET))
+				break;
+			msleep(1);
+		}
 	}
 
 	if (i == YT_PHY_RST_WAIT_PERIOD) {
diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.h b/drivers/net/ngbe/base/ngbe_phy_yt.h
index e729e0c854..c8763a90df 100644
--- a/drivers/net/ngbe/base/ngbe_phy_yt.h
+++ b/drivers/net/ngbe/base/ngbe_phy_yt.h
@@ -11,26 +11,41 @@
 
 /* Common EXT */
 #define YT_SMI_PHY			0xA000
+#define   YT_SMI_PHY_SW_RST		MS16(15, 0x1)
 #define   YT_SMI_PHY_SDS		MS16(1, 0x1) /* 0 for UTP */
 #define YT_CHIP				0xA001
 #define   YT_CHIP_SW_RST		MS16(15, 0x1)
 #define   YT_CHIP_SW_LDO_EN		MS16(6, 0x1)
+#define   YT_CHIP_MODE_MASK		MS16(0, 0x7)
 #define   YT_CHIP_MODE_SEL(v)		LS16(v, 0, 0x7)
 #define YT_RGMII_CONF1			0xA003
+#define   YT_RGMII_CONF1_MODE		MS16(15, 0x1)
 #define   YT_RGMII_CONF1_RXDELAY	MS16(10, 0xF)
 #define   YT_RGMII_CONF1_TXDELAY_FE	MS16(4, 0xF)
 #define   YT_RGMII_CONF1_TXDELAY	MS16(0, 0x1)
+#define YT_RGMII_CONF2			0xA004
+#define   YT_RGMII_CONF2_SPEED_MASK	MS16(6, 0x3)
+#define   YT_RGMII_CONF2_SPEED(v)	LS16(v, 6, 0x3)
+#define   YT_RGMII_CONF2_DUPLEX		MS16(5, 0x1)
+#define   YT_RGMII_CONF2_LINKUP		MS16(4, 0x1)
 #define YT_MISC				0xA006
 #define   YT_MISC_FIBER_PRIO		MS16(8, 0x1) /* 0 for UTP */
 
 /* MII common registers in UTP and SDS */
 #define YT_BCR				0x0
 #define   YT_BCR_RESET			MS16(15, 0x1)
+#define	  YT_BCR_SPEED_SELECT0		MS16(13, 0x1)
+#define   YT_BCR_ANE			MS16(12, 0x1)
 #define   YT_BCR_PWDN			MS16(11, 0x1)
+#define   YT_BCR_RESTART_AN		MS16(9, 0x1)
+#define   YT_BCR_DUPLEX			MS16(8, 0x1)
+#define   YT_BCR_SPEED_SELECT1		MS16(6, 0x1)
 #define YT_ANA				0x4
 /* copper */
 #define   YT_ANA_100BASET_FULL		MS16(8, 0x1)
+#define   YT_ANA_100BASET_HALF		MS16(7, 0x1)
 #define   YT_ANA_10BASET_FULL		MS16(6, 0x1)
+#define   YT_ANA_10BASET_HALF		MS16(5, 0x1)
 /* fiber */
 #define   YT_FANA_PAUSE_MASK		MS16(7, 0x3)
 
@@ -41,6 +56,7 @@
 
 #define YT_MS_CTRL			0x9
 #define   YT_MS_1000BASET_FULL		MS16(9, 0x1)
+#define   YT_MS_1000BASET_HALF		MS16(8, 0x1)
 #define YT_SPST				0x11
 #define   YT_SPST_SPEED_MASK		MS16(14, 0x3)
 #define	    YT_SPST_SPEED_1000M		LS16(2, 14, 0x3)
@@ -50,7 +66,8 @@
 
 /* UTP only */
 #define YT_INTR				0x12
-#define   YT_INTR_ENA_MASK		MS16(2, 0x3)
+#define   YT_INTR_ENA_MASK		MS16(10, 0x3)
+#define   YT_SDS_INTR_ENA_MASK		MS16(2, 0x3)
 #define YT_INTR_STATUS			0x13
 
 s32 ngbe_read_phy_reg_yt(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h
index 4c995e7397..cb8d65ff27 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -44,6 +44,12 @@ enum ngbe_eeprom_type {
 	ngbe_eeprom_none /* No NVM support */
 };
 
+enum ngbe_link_type {
+	ngbe_link_type_unknown = 0,
+	ngbe_link_fiber,
+	ngbe_link_copper
+};
+
 enum ngbe_mac_type {
 	ngbe_mac_unknown = 0,
 	ngbe_mac_em,
@@ -312,6 +318,7 @@ struct ngbe_mac_info {
 	s32 (*check_overtemp)(struct ngbe_hw *hw);
 
 	enum ngbe_mac_type type;
+	enum ngbe_link_type link_type;
 	u8 addr[ETH_ADDR_LEN];
 	u8 perm_addr[ETH_ADDR_LEN];
 #define NGBE_MAX_MTA			128
@@ -422,6 +429,7 @@ struct ngbe_hw {
 	u32 q_tx_regs[8 * 4];
 	bool offset_loaded;
 	bool is_pf;
+	bool gpio_ctl;
 	struct {
 		u64 rx_qp_packets;
 		u64 tx_qp_packets;
diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c
index cc530fdced..9f42c26f9b 100644
--- a/drivers/net/ngbe/ngbe_ethdev.c
+++ b/drivers/net/ngbe/ngbe_ethdev.c
@@ -1097,8 +1097,7 @@ ngbe_dev_start(struct rte_eth_dev *dev)
 	/* resume enabled intr since HW reset */
 	ngbe_enable_intr(dev);
 
-	if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP ||
-		(hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) {
+	if (hw->gpio_ctl) {
 		/* gpio0 is used to power on/off control*/
 		wr32(hw, NGBE_GPIODATA, 0);
 	}
@@ -1141,8 +1140,7 @@ ngbe_dev_stop(struct rte_eth_dev *dev)
 
 	rte_eal_alarm_cancel(ngbe_dev_setup_link_alarm_handler, dev);
 
-	if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP ||
-		(hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) {
+	if (hw->gpio_ctl) {
 		/* gpio0 is used to power on/off control*/
 		wr32(hw, NGBE_GPIODATA, NGBE_GPIOBIT_0);
 	}
-- 
2.21.0.windows.1




  parent reply	other threads:[~2022-02-09 10:36 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-09 10:42 [PATCH v2 00/12] Wangxun fixes and supports Jiawen Wu
2022-02-09 10:42 ` [PATCH v2 01/12] net/ngbe: fix failed to receive packets Jiawen Wu
2022-02-09 10:42 ` [PATCH v2 02/12] net/ngbe: fix link interrupt sometimes lost Jiawen Wu
2022-02-09 10:42 ` [PATCH v2 03/12] net/ngbe: fix Tx pending Jiawen Wu
2022-02-09 19:07   ` Ferruh Yigit
2022-02-09 10:42 ` [PATCH v2 04/12] net/ngbe: fix RxTx packet statistics Jiawen Wu
2022-02-09 10:42 ` [PATCH v2 05/12] net/ngbe: optimize the PHY initialization process Jiawen Wu
2022-02-09 10:42 ` Jiawen Wu [this message]
2022-02-09 10:42 ` [PATCH v2 07/12] net/ngbe: add LED OEM support Jiawen Wu
2022-02-09 19:06   ` Ferruh Yigit
2022-02-09 10:42 ` [PATCH v2 08/12] net/ngbe: fix debug log Jiawen Wu
2022-02-09 19:07   ` Ferruh Yigit
2022-02-10  8:03     ` Jiawen Wu
2022-02-10  9:02       ` Ferruh Yigit
2022-02-10  9:49         ` Jiawen Wu
2022-02-10 10:16           ` Ferruh Yigit
2022-02-11  2:02             ` Jiawen Wu
2022-02-09 10:42 ` [PATCH v2 09/12] net/txgbe: add LED OEM support Jiawen Wu
2022-02-09 10:42 ` [PATCH v2 10/12] net/txgbe: fix debug log Jiawen Wu
2022-02-09 19:07   ` Ferruh Yigit
2022-02-09 10:42 ` [PATCH v2 11/12] net/txgbe: fix to set link up and down Jiawen Wu
2022-02-09 10:42 ` [PATCH v2 12/12] net/txgbe: fix KR auto-negotiation Jiawen Wu
2022-02-09 19:06 ` [PATCH v2 00/12] Wangxun fixes and supports Ferruh Yigit
2022-02-11 13:10 ` Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220209104213.602728-7-jiawenwu@trustnetic.com \
    --to=jiawenwu@trustnetic.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).