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
next prev 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 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).