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 v6 11/19] net/ngbe: setup the check PHY link
Date: Thu, 17 Jun 2021 18:59:57 +0800	[thread overview]
Message-ID: <20210617110005.4132926-12-jiawenwu@trustnetic.com> (raw)
In-Reply-To: <20210617110005.4132926-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 4273e5af36..709e01659c 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 7f20d6c807..331fc752ff 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 0b3d60ae29..1689223168 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 0467e1e66e..471656cc51 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 59d9efe025..96e47b5bb9 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 40419a61f6..a1c055e238 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 a88ace9ec1..a663a429dd 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 0703ad9396..3401fc7e92 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 ecb60b0ddd..e8bc4a1bd7 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 84b20de45c..f518dc0af6 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 80fd420a63..26820ecb92 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 04c1cac422..626c6e2eec 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-06-17 10:59 UTC|newest]

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

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=20210617110005.4132926-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.