]> git.droids-corp.org - dpdk.git/commitdiff
net/ngbe: redesign internal PHY init flow
authorJiawen Wu <jiawenwu@trustnetic.com>
Mon, 30 May 2022 09:30:14 +0000 (17:30 +0800)
committerFerruh Yigit <ferruh.yigit@xilinx.com>
Tue, 31 May 2022 07:42:16 +0000 (09:42 +0200)
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
drivers/net/ngbe/base/ngbe_hw.h
drivers/net/ngbe/base/ngbe_phy.c
drivers/net/ngbe/base/ngbe_phy_rtl.c
drivers/net/ngbe/base/ngbe_type.h

index facc1d9e82922d386bf6f22fb9fc20675bc042f6..c1114ba3b1b9a7ccba69da41a92f64fe0a66c12f 100644 (file)
@@ -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;
index 2813e72d605ea892f32117d965f0f4e87f81595f..b92a691fa076808111e1d50e22d8c866fbe98858 100644 (file)
@@ -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);
 
index 84f2925e7e29313ff2ff284030e396e99e2c4ac7..06562b594fb2987d00efbfe99cd5c8afbc32b222 100644 (file)
@@ -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;
 }
 
index 3a2d624ddb29e404246348d539c16605ec651560..33c5e79e8784507cf8f2385ca76f484530a1f665 100644 (file)
@@ -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 */
index 666562bf22d3db34aedd97a901fec169f65ee5df..0ad4766d2a0912dc9b0ac7133edb1b534def311c 100644 (file)
@@ -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;