[7/9] net/ngbe: redesign internal PHY init flow

Message ID 20220530093016.16326-8-jiawenwu@trustnetic.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series Wangxun fixes and new supports |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Jiawen Wu May 30, 2022, 9:30 a.m. UTC
  Add to read efuse values from flash, and disable EEE to improve signal
quality. Remove PHY semaphore to access PHY registers faster. And remove
unnecessary page selection where quick access is required.

When rte_eth_link_get_nowait() is called frequently with LSC disabled by
self-developed applications, eventually the PHY status register will be
accessed frequently. It will cause internal PHY init failure, if they are
done simultaneously. So there is a protection added for internal PHY init.

Fixes: 3518df5774c7 ("net/ngbe: support device start/stop")
Fixes: 91bc12c5227c ("net/ngbe: optimize PHY initialization process")
Cc: stable@dpdk.org

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ngbe/base/ngbe_hw.c      |  16 ++++
 drivers/net/ngbe/base/ngbe_hw.h      |   1 +
 drivers/net/ngbe/base/ngbe_phy.c     |  12 ---
 drivers/net/ngbe/base/ngbe_phy_rtl.c | 106 ++++++++++++++++++++-------
 drivers/net/ngbe/base/ngbe_type.h    |   2 +
 5 files changed, 100 insertions(+), 37 deletions(-)
  

Patch

diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c
index facc1d9e82..c1114ba3b1 100644
--- a/drivers/net/ngbe/base/ngbe_hw.c
+++ b/drivers/net/ngbe/base/ngbe_hw.c
@@ -53,6 +53,7 @@  s32 ngbe_init_hw(struct ngbe_hw *hw)
 {
 	s32 status;
 
+	ngbe_read_efuse(hw);
 	ngbe_save_eeprom_version(hw);
 
 	/* Reset the hardware */
@@ -1855,6 +1856,21 @@  u32 ngbe_flash_read_dword(struct ngbe_hw *hw, u32 addr)
 	return rd32(hw, NGBE_SPIDAT);
 }
 
+void ngbe_read_efuse(struct ngbe_hw *hw)
+{
+	u32 efuse[2];
+	u8 lan_id = hw->bus.lan_id;
+
+	efuse[0] = ngbe_flash_read_dword(hw, 0xfe010 + lan_id * 8);
+	efuse[1] = ngbe_flash_read_dword(hw, 0xfe010 + lan_id * 8 + 4);
+
+	DEBUGOUT("port %d efuse[0] = %08x, efuse[1] = %08x\n",
+		lan_id, efuse[0], efuse[1]);
+
+	hw->gphy_efuse[0] = efuse[0];
+	hw->gphy_efuse[1] = efuse[1];
+}
+
 void ngbe_map_device_id(struct ngbe_hw *hw)
 {
 	u16 oem = hw->sub_system_id & NGBE_OEM_MASK;
diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h
index 2813e72d60..b92a691fa0 100644
--- a/drivers/net/ngbe/base/ngbe_hw.h
+++ b/drivers/net/ngbe/base/ngbe_hw.h
@@ -83,6 +83,7 @@  s32 ngbe_init_phy(struct ngbe_hw *hw);
 s32 ngbe_enable_rx_dma(struct ngbe_hw *hw, u32 regval);
 void ngbe_map_device_id(struct ngbe_hw *hw);
 
+void ngbe_read_efuse(struct ngbe_hw *hw);
 u32 ngbe_fmgr_cmd_op(struct ngbe_hw *hw, u32 cmd, u32 cmd_addr);
 u32 ngbe_flash_read_dword(struct ngbe_hw *hw, u32 addr);
 
diff --git a/drivers/net/ngbe/base/ngbe_phy.c b/drivers/net/ngbe/base/ngbe_phy.c
index 84f2925e7e..06562b594f 100644
--- a/drivers/net/ngbe/base/ngbe_phy.c
+++ b/drivers/net/ngbe/base/ngbe_phy.c
@@ -290,16 +290,10 @@  s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr,
 			       u32 device_type, u16 *phy_data)
 {
 	s32 err;
-	u32 gssr = hw->phy.phy_semaphore_mask;
-
-	if (hw->mac.acquire_swfw_sync(hw, gssr))
-		return NGBE_ERR_SWFW_SYNC;
 
 	err = hw->phy.read_reg_unlocked(hw, reg_addr, device_type,
 					phy_data);
 
-	hw->mac.release_swfw_sync(hw, gssr);
-
 	return err;
 }
 
@@ -350,16 +344,10 @@  s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr,
 				u32 device_type, u16 phy_data)
 {
 	s32 err;
-	u32 gssr = hw->phy.phy_semaphore_mask;
-
-	if (hw->mac.acquire_swfw_sync(hw, gssr))
-		err = NGBE_ERR_SWFW_SYNC;
 
 	err = hw->phy.write_reg_unlocked(hw, reg_addr, device_type,
 					 phy_data);
 
-	hw->mac.release_swfw_sync(hw, gssr);
-
 	return err;
 }
 
diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.c b/drivers/net/ngbe/base/ngbe_phy_rtl.c
index 3a2d624ddb..33c5e79e87 100644
--- a/drivers/net/ngbe/base/ngbe_phy_rtl.c
+++ b/drivers/net/ngbe/base/ngbe_phy_rtl.c
@@ -14,7 +14,9 @@  s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw,
 	reg.addr = reg_addr;
 	ngbe_mdi_map_register(&reg, &reg22);
 
-	wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
+	if (!(reg22.page == 0xa43 &&
+			(reg22.addr == 0x1a || reg22.addr == 0x1d)))
+		wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
 	*phy_data = 0xFFFF & rd32(hw, NGBE_PHY_CONFIG(reg22.addr));
 
 	return 0;
@@ -30,7 +32,9 @@  s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw,
 	reg.addr = reg_addr;
 	ngbe_mdi_map_register(&reg, &reg22);
 
-	wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
+	if (!(reg22.page == 0xa43 &&
+			(reg22.addr == 0x1a || reg22.addr == 0x1d)))
+		wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
 	wr32(hw, NGBE_PHY_CONFIG(reg22.addr), phy_data);
 
 	return 0;
@@ -60,16 +64,61 @@  static void ngbe_phy_led_ctrl_rtl(struct ngbe_hw *hw)
 	hw->phy.write_reg(hw, RTL_LPCR, 0xd04, value);
 }
 
+static s32 ngbe_wait_mdio_access_on(struct ngbe_hw *hw)
+{
+	int i;
+	u16 val = 0;
+
+	for (i = 0; i < 100; i++) {
+		/* irq status */
+		hw->phy.read_reg(hw, RTL_INSR, 0xa43, &val);
+		if (val & RTL_INSR_ACCESS)
+			break;
+		msec_delay(1);
+	}
+
+	if (i == 100) {
+		DEBUGOUT("wait_mdio_access_on timeout");
+		return NGBE_ERR_PHY_TIMEOUT;
+	}
+
+	return 0;
+}
+
+static void ngbe_efuse_calibration(struct ngbe_hw *hw)
+{
+	u32 efuse[2];
+
+	ngbe_wait_mdio_access_on(hw);
+
+	efuse[0] = hw->gphy_efuse[0];
+	efuse[1] = hw->gphy_efuse[1];
+
+	if (!efuse[0] && !efuse[1]) {
+		efuse[0] = 0xFFFFFFFF;
+		efuse[1] = 0xFFFFFFFF;
+	}
+
+	/* calibration */
+	efuse[0] |= 0xF0000100;
+	efuse[1] |= 0xFF807FFF;
+	DEBUGOUT("port %d efuse[0] = %08x, efuse[1] = %08x",
+		hw->bus.lan_id, efuse[0], efuse[1]);
+
+	/* EODR, Efuse Output Data Register */
+	hw->phy.write_reg(hw, 16, 0xa46, (efuse[0] >>  0) & 0xFFFF);
+	hw->phy.write_reg(hw, 17, 0xa46, (efuse[0] >> 16) & 0xFFFF);
+	hw->phy.write_reg(hw, 18, 0xa46, (efuse[1] >>  0) & 0xFFFF);
+	hw->phy.write_reg(hw, 19, 0xa46, (efuse[1] >> 16) & 0xFFFF);
+}
+
 s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
 {
 	int i;
 	u16 value = 0;
 
-	/* enable interrupts, only link status change and an done is allowed */
-	value = RTL_INER_LSC | RTL_INER_ANC;
-	hw->phy.write_reg(hw, RTL_INER, 0xa42, value);
-
-	hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
+	hw->init_phy = true;
+	msec_delay(1);
 
 	for (i = 0; i < 15; i++) {
 		if (!rd32m(hw, NGBE_STAT,
@@ -83,6 +132,8 @@  s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
 		return NGBE_ERR_PHY_TIMEOUT;
 	}
 
+	ngbe_efuse_calibration(hw);
+
 	hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EFUSE);
 	hw->phy.read_reg(hw, RTL_SCR, 0xa46, &value);
 	if (!(value & RTL_SCR_EFUSE)) {
@@ -90,15 +141,10 @@  s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
 		return NGBE_ERR_PHY_TIMEOUT;
 	}
 
-	for (i = 0; i < 1000; i++) {
-		hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
-		if (value & RTL_INSR_ACCESS)
-			break;
-		msec_delay(1);
-	}
-	if (i == 1000)
-		DEBUGOUT("PHY wait mdio 1 access timeout.");
+	ngbe_wait_mdio_access_on(hw);
 
+	hw->phy.write_reg(hw, 27, 0xa42, 0x8011);
+	hw->phy.write_reg(hw, 28, 0xa42, 0x5737);
 
 	hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EXTINI);
 	hw->phy.read_reg(hw, RTL_SCR, 0xa46, &value);
@@ -107,24 +153,26 @@  s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
 		return NGBE_ERR_PHY_TIMEOUT;
 	}
 
-	for (i = 0; i < 1000; i++) {
-		hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
-		if (value & RTL_INSR_ACCESS)
-			break;
-		msec_delay(1);
-	}
-	if (i == 1000)
-		DEBUGOUT("PHY wait mdio 2 access timeout.");
+	ngbe_wait_mdio_access_on(hw);
 
-	for (i = 0; i < 1000; i++) {
+	for (i = 0; i < 100; i++) {
 		hw->phy.read_reg(hw, RTL_GSR, 0xa42, &value);
 		if ((value & RTL_GSR_ST) == RTL_GSR_ST_LANON)
 			break;
 		msec_delay(1);
 	}
-	if (i == 1000)
+	if (i == 100)
 		return NGBE_ERR_PHY_TIMEOUT;
 
+	/* Disable EEE */
+	hw->phy.write_reg(hw, 0x11, 0xa4b, 0x1110);
+	hw->phy.write_reg(hw, 0xd, 0x0, 0x0007);
+	hw->phy.write_reg(hw, 0xe, 0x0, 0x003c);
+	hw->phy.write_reg(hw, 0xd, 0x0, 0x4007);
+	hw->phy.write_reg(hw, 0xe, 0x0, 0x0000);
+
+	hw->init_phy = false;
+
 	return 0;
 }
 
@@ -142,6 +190,9 @@  s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
 
 	UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
 
+	hw->init_phy = true;
+	msec_delay(1);
+
 	hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg);
 
 	if (!hw->mac.autoneg) {
@@ -243,6 +294,8 @@  s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
 skip_an:
 	ngbe_phy_led_ctrl_rtl(hw);
 
+	hw->init_phy = false;
+
 	return 0;
 }
 
@@ -309,6 +362,9 @@  s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up)
 	u16 phy_data = 0;
 	u16 insr = 0;
 
+	if (hw->init_phy)
+		return -1;
+
 	hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr);
 
 	/* Initialize speed and link to default case */
diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h
index 666562bf22..0ad4766d2a 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -428,10 +428,12 @@  struct ngbe_hw {
 
 	u32 q_rx_regs[8 * 4];
 	u32 q_tx_regs[8 * 4];
+	u32 gphy_efuse[2];
 	bool offset_loaded;
 	bool is_pf;
 	bool gpio_ctl;
 	u32 led_conf;
+	bool init_phy;
 	struct {
 		u64 rx_qp_packets;
 		u64 tx_qp_packets;