All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiawen Wu <jiawenwu@trustnetic.com>
To: dev@dpdk.org
Cc: Jiawen Wu <jiawenwu@trustnetic.com>
Subject: [dpdk-dev] [PATCH v7 11/19] net/ngbe: setup the check PHY link
Date: Tue,  6 Jul 2021 17:55:37 +0800	[thread overview]
Message-ID: <20210706095545.10776-12-jiawenwu@trustnetic.com> (raw)
In-Reply-To: <20210706095545.10776-1-jiawenwu@trustnetic.com>

Setup PHY, determine link and speed status from PHY.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ngbe/base/ngbe_dummy.h   |  18 +++
 drivers/net/ngbe/base/ngbe_hw.c      |  53 +++++++++
 drivers/net/ngbe/base/ngbe_hw.h      |   6 +
 drivers/net/ngbe/base/ngbe_phy.c     |  22 ++++
 drivers/net/ngbe/base/ngbe_phy.h     |   2 +
 drivers/net/ngbe/base/ngbe_phy_mvl.c |  98 ++++++++++++++++
 drivers/net/ngbe/base/ngbe_phy_mvl.h |   4 +
 drivers/net/ngbe/base/ngbe_phy_rtl.c | 166 +++++++++++++++++++++++++++
 drivers/net/ngbe/base/ngbe_phy_rtl.h |   4 +
 drivers/net/ngbe/base/ngbe_phy_yt.c  | 134 +++++++++++++++++++++
 drivers/net/ngbe/base/ngbe_phy_yt.h  |   8 ++
 drivers/net/ngbe/base/ngbe_type.h    |  11 ++
 12 files changed, 526 insertions(+)

diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h
index 634e9a69c1..1b74710b09 100644
--- a/drivers/net/ngbe/base/ngbe_dummy.h
+++ b/drivers/net/ngbe/base/ngbe_dummy.h
@@ -64,6 +64,11 @@ static inline void ngbe_mac_release_swfw_sync_dummy(struct ngbe_hw *TUP0,
 					u32 TUP1)
 {
 }
+static inline s32 ngbe_mac_setup_link_dummy(struct ngbe_hw *TUP0, u32 TUP1,
+					bool TUP2)
+{
+	return NGBE_ERR_OPS_DUMMY;
+}
 static inline s32 ngbe_mac_check_link_dummy(struct ngbe_hw *TUP0, u32 *TUP1,
 					bool *TUP3, bool TUP4)
 {
@@ -129,6 +134,16 @@ static inline s32 ngbe_phy_write_reg_unlocked_dummy(struct ngbe_hw *TUP0,
 {
 	return NGBE_ERR_OPS_DUMMY;
 }
+static inline s32 ngbe_phy_setup_link_dummy(struct ngbe_hw *TUP0,
+					u32 TUP1, bool TUP2)
+{
+	return NGBE_ERR_OPS_DUMMY;
+}
+static inline s32 ngbe_phy_check_link_dummy(struct ngbe_hw *TUP0, u32 *TUP1,
+					bool *TUP2)
+{
+	return NGBE_ERR_OPS_DUMMY;
+}
 static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw)
 {
 	hw->bus.set_lan_id = ngbe_bus_set_lan_id_dummy;
@@ -140,6 +155,7 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw)
 	hw->mac.get_mac_addr = ngbe_mac_get_mac_addr_dummy;
 	hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy;
 	hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy;
+	hw->mac.setup_link = ngbe_mac_setup_link_dummy;
 	hw->mac.check_link = ngbe_mac_check_link_dummy;
 	hw->mac.set_rar = ngbe_mac_set_rar_dummy;
 	hw->mac.clear_rar = ngbe_mac_clear_rar_dummy;
@@ -154,6 +170,8 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw)
 	hw->phy.write_reg = ngbe_phy_write_reg_dummy;
 	hw->phy.read_reg_unlocked = ngbe_phy_read_reg_unlocked_dummy;
 	hw->phy.write_reg_unlocked = ngbe_phy_write_reg_unlocked_dummy;
+	hw->phy.setup_link = ngbe_phy_setup_link_dummy;
+	hw->phy.check_link = ngbe_phy_check_link_dummy;
 }
 
 #endif /* _NGBE_TYPE_DUMMY_H_ */
diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c
index 2daddaaf05..3683475970 100644
--- a/drivers/net/ngbe/base/ngbe_hw.c
+++ b/drivers/net/ngbe/base/ngbe_hw.c
@@ -599,6 +599,54 @@ s32 ngbe_init_uta_tables(struct ngbe_hw *hw)
 	return 0;
 }
 
+/**
+ *  ngbe_check_mac_link_em - Determine link and speed status
+ *  @hw: pointer to hardware structure
+ *  @speed: pointer to link speed
+ *  @link_up: true when link is up
+ *  @link_up_wait_to_complete: bool used to wait for link up or not
+ *
+ *  Reads the links register to determine if link is up and the current speed
+ **/
+s32 ngbe_check_mac_link_em(struct ngbe_hw *hw, u32 *speed,
+			bool *link_up, bool link_up_wait_to_complete)
+{
+	u32 i, reg;
+	s32 status = 0;
+
+	DEBUGFUNC("ngbe_check_mac_link_em");
+
+	reg = rd32(hw, NGBE_GPIOINTSTAT);
+	wr32(hw, NGBE_GPIOEOI, reg);
+
+	if (link_up_wait_to_complete) {
+		for (i = 0; i < hw->mac.max_link_up_time; i++) {
+			status = hw->phy.check_link(hw, speed, link_up);
+			if (*link_up)
+				break;
+			msec_delay(100);
+		}
+	} else {
+		status = hw->phy.check_link(hw, speed, link_up);
+	}
+
+	return status;
+}
+
+s32 ngbe_setup_mac_link_em(struct ngbe_hw *hw,
+			       u32 speed,
+			       bool autoneg_wait_to_complete)
+{
+	s32 status;
+
+	DEBUGFUNC("\n");
+
+	/* Setup the PHY according to input speed */
+	status = hw->phy.setup_link(hw, speed, autoneg_wait_to_complete);
+
+	return status;
+}
+
 /**
  *  ngbe_init_thermal_sensor_thresh - Inits thermal sensor thresholds
  *  @hw: pointer to hardware structure
@@ -806,6 +854,10 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw)
 	mac->set_vmdq = ngbe_set_vmdq;
 	mac->clear_vmdq = ngbe_clear_vmdq;
 
+	/* Link */
+	mac->check_link = ngbe_check_mac_link_em;
+	mac->setup_link = ngbe_setup_mac_link_em;
+
 	/* Manageability interface */
 	mac->init_thermal_sensor_thresh = ngbe_init_thermal_sensor_thresh;
 	mac->check_overtemp = ngbe_mac_check_overtemp;
@@ -853,6 +905,7 @@ s32 ngbe_init_shared_code(struct ngbe_hw *hw)
 		status = NGBE_ERR_DEVICE_NOT_SUPPORTED;
 		break;
 	}
+	hw->mac.max_link_up_time = NGBE_LINK_UP_TIME;
 
 	hw->bus.set_lan_id(hw);
 
diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h
index 875bfa1add..9b71e4b0dd 100644
--- a/drivers/net/ngbe/base/ngbe_hw.h
+++ b/drivers/net/ngbe/base/ngbe_hw.h
@@ -20,6 +20,12 @@ s32 ngbe_get_mac_addr(struct ngbe_hw *hw, u8 *mac_addr);
 
 void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw);
 
+s32 ngbe_check_mac_link_em(struct ngbe_hw *hw, u32 *speed,
+			bool *link_up, bool link_up_wait_to_complete);
+s32 ngbe_setup_mac_link_em(struct ngbe_hw *hw,
+			       u32 speed,
+			       bool autoneg_wait_to_complete);
+
 s32 ngbe_set_rar(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
 			  u32 enable_addr);
 s32 ngbe_clear_rar(struct ngbe_hw *hw, u32 index);
diff --git a/drivers/net/ngbe/base/ngbe_phy.c b/drivers/net/ngbe/base/ngbe_phy.c
index 61bb953b6a..f0265d83b8 100644
--- a/drivers/net/ngbe/base/ngbe_phy.c
+++ b/drivers/net/ngbe/base/ngbe_phy.c
@@ -420,7 +420,29 @@ s32 ngbe_init_phy(struct ngbe_hw *hw)
 
 	/* Identify the PHY */
 	err = phy->identify(hw);
+	if (err == NGBE_ERR_PHY_ADDR_INVALID)
+		goto init_phy_ops_out;
 
+	/* Set necessary function pointers based on PHY type */
+	switch (hw->phy.type) {
+	case ngbe_phy_rtl:
+		hw->phy.check_link = ngbe_check_phy_link_rtl;
+		hw->phy.setup_link = ngbe_setup_phy_link_rtl;
+		break;
+	case ngbe_phy_mvl:
+	case ngbe_phy_mvl_sfi:
+		hw->phy.check_link = ngbe_check_phy_link_mvl;
+		hw->phy.setup_link = ngbe_setup_phy_link_mvl;
+		break;
+	case ngbe_phy_yt8521s:
+	case ngbe_phy_yt8521s_sfi:
+		hw->phy.check_link = ngbe_check_phy_link_yt;
+		hw->phy.setup_link = ngbe_setup_phy_link_yt;
+	default:
+		break;
+	}
+
+init_phy_ops_out:
 	return err;
 }
 
diff --git a/drivers/net/ngbe/base/ngbe_phy.h b/drivers/net/ngbe/base/ngbe_phy.h
index 226e0189ec..5d6ff1711c 100644
--- a/drivers/net/ngbe/base/ngbe_phy.h
+++ b/drivers/net/ngbe/base/ngbe_phy.h
@@ -22,6 +22,8 @@
 #define NGBE_MD_PHY_ID_LOW		0x3 /* PHY ID Low Reg*/
 #define   NGBE_PHY_REVISION_MASK	0xFFFFFFF0
 
+#define NGBE_MII_AUTONEG_REG			0x0
+
 /* IEEE 802.3 Clause 22 */
 struct mdi_reg_22 {
 	u16 page;
diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.c b/drivers/net/ngbe/base/ngbe_phy_mvl.c
index 1248478252..f8cb6cd38a 100644
--- a/drivers/net/ngbe/base/ngbe_phy_mvl.c
+++ b/drivers/net/ngbe/base/ngbe_phy_mvl.c
@@ -48,6 +48,64 @@ s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw,
 	return 0;
 }
 
+s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, u32 speed,
+				bool autoneg_wait_to_complete)
+{
+	u16 value_r4 = 0;
+	u16 value_r9 = 0;
+	u16 value;
+
+	DEBUGFUNC("ngbe_setup_phy_link_mvl");
+	UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
+
+	hw->phy.autoneg_advertised = 0;
+
+	if (hw->phy.type == ngbe_phy_mvl) {
+		if (speed & NGBE_LINK_SPEED_1GB_FULL) {
+			value_r9 |= MVL_PHY_1000BASET_FULL;
+			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
+		}
+
+		if (speed & NGBE_LINK_SPEED_100M_FULL) {
+			value_r4 |= MVL_PHY_100BASET_FULL;
+			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
+		}
+
+		if (speed & NGBE_LINK_SPEED_10M_FULL) {
+			value_r4 |= MVL_PHY_10BASET_FULL;
+			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
+		}
+
+		hw->phy.read_reg(hw, MVL_ANA, 0, &value);
+		value &= ~(MVL_PHY_100BASET_FULL |
+			   MVL_PHY_100BASET_HALF |
+			   MVL_PHY_10BASET_FULL |
+			   MVL_PHY_10BASET_HALF);
+		value_r4 |= value;
+		hw->phy.write_reg(hw, MVL_ANA, 0, value_r4);
+
+		hw->phy.read_reg(hw, MVL_PHY_1000BASET, 0, &value);
+		value &= ~(MVL_PHY_1000BASET_FULL |
+			   MVL_PHY_1000BASET_HALF);
+		value_r9 |= value;
+		hw->phy.write_reg(hw, MVL_PHY_1000BASET, 0, value_r9);
+	} else {
+		hw->phy.autoneg_advertised = 1;
+
+		hw->phy.read_reg(hw, MVL_ANA, 0, &value);
+		value &= ~(MVL_PHY_1000BASEX_HALF | MVL_PHY_1000BASEX_FULL);
+		value |= MVL_PHY_1000BASEX_FULL;
+		hw->phy.write_reg(hw, MVL_ANA, 0, value);
+	}
+
+	value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE;
+	ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value);
+
+	hw->phy.read_reg(hw, MVL_INTR, 0, &value);
+
+	return 0;
+}
+
 s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw)
 {
 	u32 i;
@@ -87,3 +145,43 @@ s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw)
 	return status;
 }
 
+s32 ngbe_check_phy_link_mvl(struct ngbe_hw *hw,
+		u32 *speed, bool *link_up)
+{
+	s32 status = 0;
+	u16 phy_link = 0;
+	u16 phy_speed = 0;
+	u16 phy_data = 0;
+	u16 insr = 0;
+
+	DEBUGFUNC("ngbe_check_phy_link_mvl");
+
+	/* Initialize speed and link to default case */
+	*link_up = false;
+	*speed = NGBE_LINK_SPEED_UNKNOWN;
+
+	hw->phy.read_reg(hw, MVL_INTR, 0, &insr);
+
+	/*
+	 * Check current speed and link status of the PHY register.
+	 * This is a vendor specific register and may have to
+	 * be changed for other copper PHYs.
+	 */
+	status = hw->phy.read_reg(hw, MVL_PHYSR, 0, &phy_data);
+	phy_link = phy_data & MVL_PHYSR_LINK;
+	phy_speed = phy_data & MVL_PHYSR_SPEED_MASK;
+
+	if (phy_link == MVL_PHYSR_LINK) {
+		*link_up = true;
+
+		if (phy_speed == MVL_PHYSR_SPEED_1000M)
+			*speed = NGBE_LINK_SPEED_1GB_FULL;
+		else if (phy_speed == MVL_PHYSR_SPEED_100M)
+			*speed = NGBE_LINK_SPEED_100M_FULL;
+		else if (phy_speed == MVL_PHYSR_SPEED_10M)
+			*speed = NGBE_LINK_SPEED_10M_FULL;
+	}
+
+	return status;
+}
+
diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.h b/drivers/net/ngbe/base/ngbe_phy_mvl.h
index ca39f3cd58..c8155c39a0 100644
--- a/drivers/net/ngbe/base/ngbe_phy_mvl.h
+++ b/drivers/net/ngbe/base/ngbe_phy_mvl.h
@@ -89,4 +89,8 @@ s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
 
 s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw);
 
+s32 ngbe_check_phy_link_mvl(struct ngbe_hw *hw,
+		u32 *speed, bool *link_up);
+s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw,
+			u32 speed, bool autoneg_wait_to_complete);
 #endif /* _NGBE_PHY_MVL_H_ */
diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.c b/drivers/net/ngbe/base/ngbe_phy_rtl.c
index 400fbe8c1f..a45b0f0a55 100644
--- a/drivers/net/ngbe/base/ngbe_phy_rtl.c
+++ b/drivers/net/ngbe/base/ngbe_phy_rtl.c
@@ -38,6 +38,134 @@ s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw,
 	return 0;
 }
 
+/**
+ *  ngbe_setup_phy_link_rtl - Set and restart auto-neg
+ *  @hw: pointer to hardware structure
+ *
+ *  Restart auto-negotiation and PHY and waits for completion.
+ **/
+s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
+		u32 speed, bool autoneg_wait_to_complete)
+{
+	u16 autoneg_reg = NGBE_MII_AUTONEG_REG;
+	u16 value = 0;
+
+	DEBUGFUNC("ngbe_setup_phy_link_rtl");
+
+	UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
+
+	hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg);
+
+	if (!hw->mac.autoneg) {
+		hw->phy.reset_hw(hw);
+
+		switch (speed) {
+		case NGBE_LINK_SPEED_1GB_FULL:
+			value = RTL_BMCR_SPEED_SELECT1;
+			break;
+		case NGBE_LINK_SPEED_100M_FULL:
+			value = RTL_BMCR_SPEED_SELECT0;
+			break;
+		case NGBE_LINK_SPEED_10M_FULL:
+			value = 0;
+			break;
+		default:
+			value = RTL_BMCR_SPEED_SELECT1 | RTL_BMCR_SPEED_SELECT0;
+			DEBUGOUT("unknown speed = 0x%x.\n", speed);
+			break;
+		}
+		/* duplex full */
+		value |= RTL_BMCR_DUPLEX;
+		hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
+
+		goto skip_an;
+	}
+
+	/*
+	 * Clear autoneg_advertised and set new values based on input link
+	 * speed.
+	 */
+	if (speed) {
+		hw->phy.autoneg_advertised = 0;
+
+		if (speed & NGBE_LINK_SPEED_1GB_FULL)
+			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
+
+		if (speed & NGBE_LINK_SPEED_100M_FULL)
+			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
+
+		if (speed & NGBE_LINK_SPEED_10M_FULL)
+			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
+	}
+
+	/* disable 10/100M Half Duplex */
+	hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &autoneg_reg);
+	autoneg_reg &= 0xFF5F;
+	hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, autoneg_reg);
+
+	/* set advertise enable according to input speed */
+	if (!(speed & NGBE_LINK_SPEED_1GB_FULL)) {
+		hw->phy.read_reg(hw, RTL_GBCR,
+			RTL_DEV_ZERO, &autoneg_reg);
+		autoneg_reg &= ~RTL_GBCR_1000F;
+		hw->phy.write_reg(hw, RTL_GBCR,
+			RTL_DEV_ZERO, autoneg_reg);
+	} else {
+		hw->phy.read_reg(hw, RTL_GBCR,
+			RTL_DEV_ZERO, &autoneg_reg);
+		autoneg_reg |= RTL_GBCR_1000F;
+		hw->phy.write_reg(hw, RTL_GBCR,
+			RTL_DEV_ZERO, autoneg_reg);
+	}
+
+	if (!(speed & NGBE_LINK_SPEED_100M_FULL)) {
+		hw->phy.read_reg(hw, RTL_ANAR,
+			RTL_DEV_ZERO, &autoneg_reg);
+		autoneg_reg &= ~RTL_ANAR_100F;
+		autoneg_reg &= ~RTL_ANAR_100H;
+		hw->phy.write_reg(hw, RTL_ANAR,
+			RTL_DEV_ZERO, autoneg_reg);
+	} else {
+		hw->phy.read_reg(hw, RTL_ANAR,
+			RTL_DEV_ZERO, &autoneg_reg);
+		autoneg_reg |= RTL_ANAR_100F;
+		hw->phy.write_reg(hw, RTL_ANAR,
+			RTL_DEV_ZERO, autoneg_reg);
+	}
+
+	if (!(speed & NGBE_LINK_SPEED_10M_FULL)) {
+		hw->phy.read_reg(hw, RTL_ANAR,
+			RTL_DEV_ZERO, &autoneg_reg);
+		autoneg_reg &= ~RTL_ANAR_10F;
+		autoneg_reg &= ~RTL_ANAR_10H;
+		hw->phy.write_reg(hw, RTL_ANAR,
+			RTL_DEV_ZERO, autoneg_reg);
+	} else {
+		hw->phy.read_reg(hw, RTL_ANAR,
+			RTL_DEV_ZERO, &autoneg_reg);
+		autoneg_reg |= RTL_ANAR_10F;
+		hw->phy.write_reg(hw, RTL_ANAR,
+			RTL_DEV_ZERO, autoneg_reg);
+	}
+
+	/* restart AN and wait AN done interrupt */
+	autoneg_reg = RTL_BMCR_RESTART_AN | RTL_BMCR_ANE;
+	hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, autoneg_reg);
+
+skip_an:
+	autoneg_reg = 0x205B;
+	hw->phy.write_reg(hw, RTL_LCR, 0xd04, autoneg_reg);
+	hw->phy.write_reg(hw, RTL_EEELCR, 0xd04, 0);
+
+	hw->phy.read_reg(hw, RTL_LPCR, 0xd04, &autoneg_reg);
+	autoneg_reg = autoneg_reg & 0xFFFC;
+	/* act led blinking mode set to 60ms */
+	autoneg_reg |= 0x2;
+	hw->phy.write_reg(hw, RTL_LPCR, 0xd04, autoneg_reg);
+
+	return 0;
+}
+
 s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw)
 {
 	u16 value = 0, i;
@@ -63,3 +191,41 @@ s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw)
 	return status;
 }
 
+s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up)
+{
+	s32 status = 0;
+	u16 phy_link = 0;
+	u16 phy_speed = 0;
+	u16 phy_data = 0;
+	u16 insr = 0;
+
+	DEBUGFUNC("ngbe_check_phy_link_rtl");
+
+	hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr);
+
+	/* Initialize speed and link to default case */
+	*link_up = false;
+	*speed = NGBE_LINK_SPEED_UNKNOWN;
+
+	/*
+	 * Check current speed and link status of the PHY register.
+	 * This is a vendor specific register and may have to
+	 * be changed for other copper PHYs.
+	 */
+	status = hw->phy.read_reg(hw, RTL_PHYSR, 0xa43, &phy_data);
+	phy_link = phy_data & RTL_PHYSR_RTLS;
+	phy_speed = phy_data & (RTL_PHYSR_SPEED_MASK | RTL_PHYSR_DP);
+	if (phy_link == RTL_PHYSR_RTLS) {
+		*link_up = true;
+
+		if (phy_speed == (RTL_PHYSR_SPEED_1000M | RTL_PHYSR_DP))
+			*speed = NGBE_LINK_SPEED_1GB_FULL;
+		else if (phy_speed == (RTL_PHYSR_SPEED_100M | RTL_PHYSR_DP))
+			*speed = NGBE_LINK_SPEED_100M_FULL;
+		else if (phy_speed == (RTL_PHYSR_SPEED_10M | RTL_PHYSR_DP))
+			*speed = NGBE_LINK_SPEED_10M_FULL;
+	}
+
+	return status;
+}
+
diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.h b/drivers/net/ngbe/base/ngbe_phy_rtl.h
index 2da5c7b626..ee5e03e9f3 100644
--- a/drivers/net/ngbe/base/ngbe_phy_rtl.h
+++ b/drivers/net/ngbe/base/ngbe_phy_rtl.h
@@ -78,6 +78,10 @@ s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
 s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
 			u16 phy_data);
 
+s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
+		u32 speed, bool autoneg_wait_to_complete);
 s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw);
+s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw,
+			u32 *speed, bool *link_up);
 
 #endif /* _NGBE_PHY_RTL_H_ */
diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c
index a5b032240c..4a44414c64 100644
--- a/drivers/net/ngbe/base/ngbe_phy_yt.c
+++ b/drivers/net/ngbe/base/ngbe_phy_yt.c
@@ -78,6 +78,104 @@ s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw,
 	return 0;
 }
 
+s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
+		u32 reg_addr, u32 device_type, u16 *phy_data)
+{
+	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
+	ngbe_read_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
+	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
+
+	return 0;
+}
+
+s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
+		u32 reg_addr, u32 device_type, u16 phy_data)
+{
+	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
+	ngbe_write_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
+	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
+
+	return 0;
+}
+
+s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
+				bool autoneg_wait_to_complete)
+{
+	u16 value_r4 = 0;
+	u16 value_r9 = 0;
+	u16 value;
+
+	DEBUGFUNC("ngbe_setup_phy_link_yt");
+	UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
+
+	hw->phy.autoneg_advertised = 0;
+
+	if (hw->phy.type == ngbe_phy_yt8521s) {
+		/*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);
+		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;
+		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 {
+		hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
+
+		/* RGMII_Config1 : Config rx and tx training delay */
+		value = YT_RGMII_CONF1_RXDELAY |
+			YT_RGMII_CONF1_TXDELAY_FE |
+			YT_RGMII_CONF1_TXDELAY;
+		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
+		value = YT_CHIP_MODE_SEL(1) |
+			YT_CHIP_SW_LDO_EN |
+			YT_CHIP_SW_RST;
+		ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
+
+		/* 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);
+	}
+
+	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
+	ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value);
+
+	return 0;
+}
+
 s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
 {
 	u32 i;
@@ -110,3 +208,39 @@ s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
 	return status;
 }
 
+s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
+		u32 *speed, bool *link_up)
+{
+	s32 status = 0;
+	u16 phy_link = 0;
+	u16 phy_speed = 0;
+	u16 phy_data = 0;
+	u16 insr = 0;
+
+	DEBUGFUNC("ngbe_check_phy_link_yt");
+
+	/* Initialize speed and link to default case */
+	*link_up = false;
+	*speed = NGBE_LINK_SPEED_UNKNOWN;
+
+	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
+	ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr);
+
+	status = hw->phy.read_reg(hw, YT_SPST, 0, &phy_data);
+	phy_link = phy_data & YT_SPST_LINK;
+	phy_speed = phy_data & YT_SPST_SPEED_MASK;
+
+	if (phy_link) {
+		*link_up = true;
+
+		if (phy_speed == YT_SPST_SPEED_1000M)
+			*speed = NGBE_LINK_SPEED_1GB_FULL;
+		else if (phy_speed == YT_SPST_SPEED_100M)
+			*speed = NGBE_LINK_SPEED_100M_FULL;
+		else if (phy_speed == YT_SPST_SPEED_10M)
+			*speed = NGBE_LINK_SPEED_10M_FULL;
+	}
+
+	return status;
+}
+
diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.h b/drivers/net/ngbe/base/ngbe_phy_yt.h
index 6d49464d6d..f7a0cb873c 100644
--- a/drivers/net/ngbe/base/ngbe_phy_yt.h
+++ b/drivers/net/ngbe/base/ngbe_phy_yt.h
@@ -61,7 +61,15 @@ s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw,
 		u32 reg_addr, u32 device_type, u16 *phy_data);
 s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw,
 		u32 reg_addr, u32 device_type, u16 phy_data);
+s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
+		u32 reg_addr, u32 device_type, u16 *phy_data);
+s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
+		u32 reg_addr, u32 device_type, u16 phy_data);
 
 s32 ngbe_reset_phy_yt(struct ngbe_hw *hw);
 
+s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
+		u32 *speed, bool *link_up);
+s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw,
+			u32 speed, bool autoneg_wait_to_complete);
 #endif /* _NGBE_PHY_YT_H_ */
diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h
index 554c57c845..472c0c1bea 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -6,6 +6,8 @@
 #ifndef _NGBE_TYPE_H_
 #define _NGBE_TYPE_H_
 
+#define NGBE_LINK_UP_TIME	90 /* 9.0 Seconds */
+
 #define NGBE_FRAME_SIZE_DFT       (1522) /* Default frame size, +FCS */
 
 #define NGBE_ALIGN		128 /* as intel did */
@@ -97,6 +99,8 @@ struct ngbe_mac_info {
 	s32 (*acquire_swfw_sync)(struct ngbe_hw *hw, u32 mask);
 	void (*release_swfw_sync)(struct ngbe_hw *hw, u32 mask);
 
+	s32 (*setup_link)(struct ngbe_hw *hw, u32 speed,
+			       bool autoneg_wait_to_complete);
 	s32 (*check_link)(struct ngbe_hw *hw, u32 *speed,
 			       bool *link_up, bool link_up_wait_to_complete);
 	/* RAR */
@@ -122,6 +126,9 @@ struct ngbe_mac_info {
 	bool get_link_status;
 	struct ngbe_thermal_sensor_data  thermal_sensor_data;
 	bool set_lben;
+	u32  max_link_up_time;
+
+	bool autoneg;
 };
 
 struct ngbe_phy_info {
@@ -135,6 +142,9 @@ struct ngbe_phy_info {
 				u32 device_type, u16 *phy_data);
 	s32 (*write_reg_unlocked)(struct ngbe_hw *hw, u32 reg_addr,
 				u32 device_type, u16 phy_data);
+	s32 (*setup_link)(struct ngbe_hw *hw, u32 speed,
+				bool autoneg_wait_to_complete);
+	s32 (*check_link)(struct ngbe_hw *hw, u32 *speed, bool *link_up);
 
 	enum ngbe_media_type media_type;
 	enum ngbe_phy_type type;
@@ -143,6 +153,7 @@ struct ngbe_phy_info {
 	u32 revision;
 	u32 phy_semaphore_mask;
 	bool reset_disable;
+	u32 autoneg_advertised;
 };
 
 enum ngbe_isb_idx {
-- 
2.21.0.windows.1




  parent reply	other threads:[~2021-07-06  9:58 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-06  9:55 [dpdk-dev] [PATCH v7 00/19] net: ngbe PMD Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 01/19] net/ngbe: add build and doc infrastructure Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 02/19] net/ngbe: support probe and remove Jiawen Wu
2021-07-07 13:48   ` Andrew Rybchenko
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 03/19] net/ngbe: add log type and error type Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 04/19] net/ngbe: define registers Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 05/19] net/ngbe: set MAC type and LAN ID with device initialization Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 06/19] net/ngbe: init and validate EEPROM Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 07/19] net/ngbe: add HW initialization Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 08/19] net/ngbe: identify PHY and reset PHY Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 09/19] net/ngbe: store MAC address Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 10/19] net/ngbe: support link update Jiawen Wu
2021-07-07 13:50   ` Andrew Rybchenko
2021-07-06  9:55 ` Jiawen Wu [this message]
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 12/19] net/ngbe: add Rx queue setup and release Jiawen Wu
2021-07-07 13:56   ` Andrew Rybchenko
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 13/19] net/ngbe: add Tx " Jiawen Wu
2021-07-07 14:00   ` Andrew Rybchenko
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 14/19] net/ngbe: add device start and stop operations Jiawen Wu
2021-07-07 14:04   ` Andrew Rybchenko
2021-07-08  6:09     ` Jiawen Wu
2021-07-08  7:36       ` Andrew Rybchenko
2021-07-08  7:50         ` Jiawen Wu
2021-07-08  8:07           ` Andrew Rybchenko
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 15/19] net/ngbe: add Tx queue start and stop Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 16/19] net/ngbe: add Rx " Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 17/19] net/ngbe: add simple Rx flow Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 18/19] net/ngbe: add simple Tx flow Jiawen Wu
2021-07-06  9:55 ` [dpdk-dev] [PATCH v7 19/19] net/ngbe: support to close and reset device Jiawen Wu
2021-07-07 14:12   ` Andrew Rybchenko
2021-07-08  8:56     ` Jiawen Wu
2021-07-07 14:13 ` [dpdk-dev] [PATCH v7 00/19] net: ngbe PMD Andrew Rybchenko

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=20210706095545.10776-12-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 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.