@@ -137,6 +137,10 @@
#undef RTE_TXGBE_KR_POLL
#define RTE_TXGBE_KR_PRESENT 1
#undef RTE_TXGBE_KX_SGMII
+#undef RTE_TXGBE_FFE_SET
+#define RTE_TXGBE_FFE_MAIN 0x1B1B
+#define RTE_TXGBE_FFE_PRE 0x0808
+#define RTE_TXGBE_FFE_POST 0x2C2C
/* Ring net PMD settings */
#define RTE_PMD_RING_MAX_RX_RINGS 16
@@ -77,7 +77,7 @@ Please note that enabling debugging options may affect system performance.
- ``RTE_TXGBE_KR_POLL`` (undefined by default)
- Enable or disable polling mode to receive AN interrupt for backplane NICs.
+ Enable polling mode to receive AN interrupt for backplane NICs.
- ``RTE_TXGBE_KR_PRESENT`` (defined by default)
@@ -87,6 +87,22 @@ Please note that enabling debugging options may affect system performance.
Special treatment for KX SGMII cards.
+- ``RTE_TXGBE_FFE_SET`` (undefined by default)
+
+ Use to set PHY link mode and enable FFE parameters for user debugging.
+
+- ``RTE_TXGBE_FFE_MAIN`` (defined to 0x1B1B by default)
+
+ PHY parameter used for user debugging.
+
+- ``RTE_TXGBE_FFE_PRE`` (defined to 0x0808 by default)
+
+ PHY parameter used for user debugging.
+
+- ``RTE_TXGBE_FFE_POST`` (defined to 0x2C2C by default)
+
+ PHY parameter used for user debugging.
+
Dynamic Logging Parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2947,6 +2947,10 @@ u32 txgbe_get_media_type_raptor(struct txgbe_hw *hw)
DEBUGFUNC("txgbe_get_media_type_raptor");
+#ifdef RTE_TXGBE_FFE_SET
+ txgbe_bp_mode_set(hw);
+#endif
+
/* Detect if there is a copper PHY attached. */
switch (hw->phy.type) {
case txgbe_phy_cu_unknown:
@@ -3540,6 +3544,14 @@ s32 txgbe_reset_hw(struct txgbe_hw *hw)
hw->mac.orig_autoc = autoc;
}
+#ifdef RTE_TXGBE_FFE_SET
+ /* Make sure phy power is up */
+ msec_delay(50);
+
+ /* A temporary solution to set phy */
+ txgbe_set_phy_temp(hw);
+#endif
+
/* Store the permanent mac address */
hw->mac.get_mac_addr(hw, hw->mac.perm_addr);
@@ -1501,6 +1501,17 @@ txgbe_set_link_to_kr(struct txgbe_hw *hw, bool autoneg)
} else {
wr32_epcs(hw, VR_AN_KR_MODE_CL, 0x1);
}
+
+ if (hw->phy.ffe_set == TXGBE_BP_M_KR) {
+ BP_LOG("Set KR TX_EQ MAIN:%d PRE:%d POST:%d\n",
+ hw->phy.ffe_main, hw->phy.ffe_pre, hw->phy.ffe_post);
+ value = (0x1804 & ~0x3F3F);
+ value |= hw->phy.ffe_main << 8 | hw->phy.ffe_pre;
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
+
+ value = (0x50 & ~0x7F) | (1 << 6) | hw->phy.ffe_post;
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+ }
out:
return err;
}
@@ -1698,7 +1709,16 @@ txgbe_set_link_to_kx4(struct txgbe_hw *hw, bool autoneg)
goto out;
}
- if ((u32)(*hw->fw_version) <= TXGBE_FW_N_TXEQ) {
+ if (hw->phy.ffe_set == TXGBE_BP_M_KX4) {
+ BP_LOG("Set KX4 TX_EQ MAIN:%d PRE:%d POST:%d\n",
+ hw->phy.ffe_main, hw->phy.ffe_pre, hw->phy.ffe_post);
+ value = (0x1804 & ~0x3F3F);
+ value |= hw->phy.ffe_main << 8 | hw->phy.ffe_pre;
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
+
+ value = (0x50 & ~0x7F) | (1 << 6) | hw->phy.ffe_post;
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+ } else if ((u32)(*hw->fw_version) <= TXGBE_FW_N_TXEQ) {
value = (0x1804 & ~0x3F3F);
wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
@@ -1905,7 +1925,17 @@ txgbe_set_link_to_kx(struct txgbe_hw *hw,
goto out;
}
- if ((u32)(*hw->fw_version) <= TXGBE_FW_N_TXEQ) {
+ if (hw->phy.ffe_set == TXGBE_BP_M_KX) {
+ BP_LOG("Set KX TX_EQ MAIN:%d PRE:%d POST:%d\n",
+ hw->phy.ffe_main, hw->phy.ffe_pre, hw->phy.ffe_post);
+ value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0) & ~0x3F3F;
+ value |= hw->phy.ffe_main << 8 | hw->phy.ffe_pre;
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
+
+ value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0) & ~0x7F;
+ value |= hw->phy.ffe_post | (1 << 6);
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+ } else if ((u32)(*hw->fw_version) <= TXGBE_FW_N_TXEQ) {
value = (0x1804 & ~0x3F3F) | (24 << 8) | 4;
wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
@@ -2132,7 +2162,17 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw,
goto out;
}
- if ((u32)(*hw->fw_version) <= TXGBE_FW_N_TXEQ) {
+ if (hw->phy.ffe_set == TXGBE_BP_M_SFI) {
+ BP_LOG("Set SFI TX_EQ MAIN:%d PRE:%d POST:%d\n",
+ hw->phy.ffe_main, hw->phy.ffe_pre, hw->phy.ffe_post);
+ value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0) & ~0x3F3F;
+ value |= hw->phy.ffe_main << 8 | hw->phy.ffe_pre;
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
+
+ value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0) & ~0x7F;
+ value |= hw->phy.ffe_post | (1 << 6);
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+ } else if ((u32)(*hw->fw_version) <= TXGBE_FW_N_TXEQ) {
value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0);
value = (value & ~0x3F3F) | (24 << 8) | 4;
wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
@@ -2304,6 +2344,76 @@ void txgbe_bp_down_event(struct txgbe_hw *hw)
txgbe_set_link_to_kr(hw, 0);
}
+void txgbe_bp_mode_set(struct txgbe_hw *hw)
+{
+ u32 shift = hw->port_id * 8;
+
+ hw->phy.ffe_set = (u8)(TXGBE_FFE_SET >> shift);
+
+ if (hw->phy.ffe_set == TXGBE_BP_M_SFI)
+ hw->subsystem_device_id = TXGBE_DEV_ID_WX1820_SFP;
+ else if (hw->phy.ffe_set == TXGBE_BP_M_KR)
+ hw->subsystem_device_id = TXGBE_DEV_ID_WX1820_KR_KX_KX4;
+ else if (hw->phy.ffe_set == TXGBE_BP_M_KX4)
+ hw->subsystem_device_id = TXGBE_DEV_ID_WX1820_MAC_XAUI;
+ else if (hw->phy.ffe_set == TXGBE_BP_M_KX)
+ hw->subsystem_device_id = TXGBE_DEV_ID_WX1820_MAC_SGMII;
+}
+
+void txgbe_set_phy_temp(struct txgbe_hw *hw)
+{
+ u32 value, shift;
+
+ shift = hw->port_id * 8;
+
+ hw->phy.ffe_main = (u8)(TXGBE_FFE_MAIN >> shift);
+ hw->phy.ffe_pre = (u8)(TXGBE_FFE_PRE >> shift);
+ hw->phy.ffe_post = (u8)(TXGBE_FFE_POST >> shift);
+
+ if (hw->phy.ffe_set == TXGBE_BP_M_SFI) {
+ BP_LOG("Set SFI TX_EQ MAIN:%d PRE:%d POST:%d\n",
+ hw->phy.ffe_main, hw->phy.ffe_pre, hw->phy.ffe_post);
+
+ value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0);
+ value = (value & ~0x3F3F) | (hw->phy.ffe_main << 8) |
+ hw->phy.ffe_pre;
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
+
+ value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1);
+ value = (value & ~0x7F) | hw->phy.ffe_post | (1 << 6);
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+ }
+
+ if (hw->phy.ffe_set == TXGBE_BP_M_KR) {
+ BP_LOG("Set KR TX_EQ MAIN:%d PRE:%d POST:%d\n",
+ hw->phy.ffe_main, hw->phy.ffe_pre, hw->phy.ffe_post);
+ value = (0x1804 & ~0x3F3F);
+ value |= hw->phy.ffe_main << 8 | hw->phy.ffe_pre;
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
+
+ value = (0x50 & ~0x7F) | (1 << 6) | hw->phy.ffe_post;
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+ wr32_epcs(hw, 0x18035, 0x00FF);
+ wr32_epcs(hw, 0x18055, 0x00FF);
+ }
+
+ if (hw->phy.ffe_set == TXGBE_BP_M_KX) {
+ BP_LOG("Set KX TX_EQ MAIN:%d PRE:%d POST:%d\n",
+ hw->phy.ffe_main, hw->phy.ffe_pre, hw->phy.ffe_post);
+ value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0);
+ value = (value & ~0x3F3F) | (hw->phy.ffe_main << 8) |
+ hw->phy.ffe_pre;
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
+
+ value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1);
+ value = (value & ~0x7F) | hw->phy.ffe_post | (1 << 6);
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+
+ wr32_epcs(hw, 0x18035, 0x00FF);
+ wr32_epcs(hw, 0x18055, 0x00FF);
+ }
+}
+
/**
* txgbe_kr_handle - Handle the interrupt of auto-negotiation
* @hw: pointer to hardware structure
@@ -396,6 +396,14 @@
#define TXGBE_MD_PORT_CTRL 0xF001
#define TXGBE_MD_PORT_CTRL_RESET MS16(14, 0x1)
+#define TXGBE_BP_M_NULL 0
+#define TXGBE_BP_M_SFI 1
+#define TXGBE_BP_M_KR 2
+#define TXGBE_BP_M_KX4 3
+#define TXGBE_BP_M_KX 4
+#define TXGBE_BP_M_NAUTO 0
+#define TXGBE_BP_M_AUTO 1
+
#ifndef CL72_KRTR_PRBS_MODE_EN
#define CL72_KRTR_PRBS_MODE_EN 0xFFFF /* open kr prbs check */
#endif
@@ -453,6 +461,8 @@ s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset,
u8 eeprom_data);
u64 txgbe_autoc_read(struct txgbe_hw *hw);
void txgbe_autoc_write(struct txgbe_hw *hw, u64 value);
+void txgbe_bp_mode_set(struct txgbe_hw *hw);
+void txgbe_set_phy_temp(struct txgbe_hw *hw);
void txgbe_bp_down_event(struct txgbe_hw *hw);
s32 txgbe_kr_handle(struct txgbe_hw *hw);
@@ -686,7 +686,28 @@ struct txgbe_phy_info {
bool qsfp_shared_i2c_bus;
u32 nw_mng_if_sel;
u32 link_mode;
+
+ /* Some features need tri-state capability */
+ u8 ffe_set;
+ u8 ffe_main;
+ u8 ffe_pre;
+ u8 ffe_post;
};
+
+#ifdef RTE_TXGBE_FFE_SET
+#define TXGBE_FFE_SET RTE_TXGBE_FFE_SET
+#else
+#define TXGBE_FFE_SET TXGBE_BP_M_NULL
+#endif
+#ifdef RTE_TXGBE_FFE_MAIN
+#define TXGBE_FFE_MAIN RTE_TXGBE_FFE_MAIN
+#endif
+#ifdef RTE_TXGBE_FFE_PRE
+#define TXGBE_FFE_PRE RTE_TXGBE_FFE_PRE
+#endif
+#ifdef RTE_TXGBE_FFE_POST
+#define TXGBE_FFE_POST RTE_TXGBE_FFE_POST
+#endif
#ifdef RTE_TXGBE_BP_AUTO
#define TXGBE_BP_AN 1
#else
@@ -760,6 +781,7 @@ struct txgbe_hw {
u16 vendor_id;
u16 subsystem_device_id;
u16 subsystem_vendor_id;
+ u8 port_id;
u8 revision_id;
bool adapter_stopped;
int api_version;
@@ -541,6 +541,7 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
hw->isb_dma = TMZ_PADDR(mz);
hw->isb_mem = TMZ_VADDR(mz);
+ hw->port_id = eth_dev->data->port_id;
/* Initialize the shared code (base driver) */
err = txgbe_init_shared_code(hw);
if (err != 0) {