From 9997a0cb647e30f31978a1ec609ac756a160dd8d Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Mon, 29 Mar 2021 11:17:24 +0800 Subject: [PATCH] net/txgbe: add FFE parameters for user debugging Support to set PHY link mode by user defined. Signed-off-by: Jiawen Wu --- doc/guides/nics/txgbe.rst | 21 +++++++ drivers/net/txgbe/base/txgbe_hw.c | 11 ++++ drivers/net/txgbe/base/txgbe_phy.c | 98 ++++++++++++++++++++++++++++- drivers/net/txgbe/base/txgbe_phy.h | 10 +++ drivers/net/txgbe/base/txgbe_type.h | 15 +++++ drivers/net/txgbe/txgbe_ethdev.c | 22 ++++++- 6 files changed, 173 insertions(+), 4 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 14243079d6..39a157eb87 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -118,6 +118,27 @@ Please note that following ``devargs`` are only set for backplane NICs. Special treatment for KX SGMII cards. +- ``ffe_set`` (default **0**) + + Use to set PHY link mode and enable FFE parameters for user debugging. + If disabled, the FFE parameters will not take effect. Otherwise, set 1 + for SFI mode, set 2 for KR mode, set 3 for KX4 mode, set 4 for KX mode. + +- ``ffe_main`` (default **27**) + + PHY parameter used for user debugging. Setting other values to + take effect requires setting the ``ffe_set``. + +- ``ffe_pre`` (default **8**) + + PHY parameter used for user debugging. Setting other values to + take effect requires setting the ``ffe_set``. + +- ``ffe_post`` (default **44**) + + PHY parameter used for user debugging. Setting other values to + take effect requires setting the ``ffe_set``. + Driver compilation and testing ------------------------------ diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 917bd947f2..3e7f2f9a3f 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -2951,6 +2951,9 @@ u32 txgbe_get_media_type_raptor(struct txgbe_hw *hw) DEBUGFUNC("txgbe_get_media_type_raptor"); + if (hw->phy.ffe_set) + txgbe_bp_mode_set(hw); + /* Detect if there is a copper PHY attached. */ switch (hw->phy.type) { case txgbe_phy_cu_unknown: @@ -3544,6 +3547,14 @@ mac_reset_top: hw->mac.orig_autoc = autoc; } + if (hw->phy.ffe_set) { + /* Make sure phy power is up */ + msec_delay(50); + + /* A temporary solution to set phy */ + txgbe_set_phy_temp(hw); + } + /* Store the permanent mac address */ hw->mac.get_mac_addr(hw, hw->mac.perm_addr); diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 5402a064f3..dabc346f5f 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1513,6 +1513,15 @@ 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) { + 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; } @@ -1710,7 +1719,14 @@ txgbe_set_link_to_kx4(struct txgbe_hw *hw, bool autoneg) goto out; } - if (hw->fw_version <= TXGBE_FW_N_TXEQ) { + if (hw->phy.ffe_set == TXGBE_BP_M_KX4) { + 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 (hw->fw_version <= TXGBE_FW_N_TXEQ) { value = (0x1804 & ~0x3F3F); wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value); @@ -1917,7 +1933,15 @@ txgbe_set_link_to_kx(struct txgbe_hw *hw, goto out; } - if (hw->fw_version <= TXGBE_FW_N_TXEQ) { + if (hw->phy.ffe_set == TXGBE_BP_M_KX) { + 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 (hw->fw_version <= TXGBE_FW_N_TXEQ) { value = (0x1804 & ~0x3F3F) | (24 << 8) | 4; wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value); @@ -2144,7 +2168,15 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw, goto out; } - if (hw->fw_version <= TXGBE_FW_N_TXEQ) { + if (hw->phy.ffe_set == TXGBE_BP_M_SFI) { + 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 (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); @@ -2318,6 +2350,66 @@ 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) +{ + 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; + + 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 diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index d2f2b2f8e7..56531c4f87 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -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 @@ -454,6 +462,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); diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 363e707335..b69e7b85ba 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -687,18 +687,33 @@ struct txgbe_phy_info { bool qsfp_shared_i2c_bus; u32 nw_mng_if_sel; u32 link_mode; + + /* Some features need tri-state capability */ + u16 ffe_set; + u16 ffe_main; + u16 ffe_pre; + u16 ffe_post; }; #define TXGBE_DEVARG_BP_AUTO "auto_neg" #define TXGBE_DEVARG_KR_POLL "poll" #define TXGBE_DEVARG_KR_PRESENT "present" #define TXGBE_DEVARG_KX_SGMII "sgmii" +#define TXGBE_DEVARG_FFE_SET "ffe_set" +#define TXGBE_DEVARG_FFE_MAIN "ffe_main" +#define TXGBE_DEVARG_FFE_PRE "ffe_pre" +#define TXGBE_DEVARG_FFE_POST "ffe_post" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, TXGBE_DEVARG_KR_POLL, TXGBE_DEVARG_KR_PRESENT, TXGBE_DEVARG_KX_SGMII, + TXGBE_DEVARG_FFE_SET, + TXGBE_DEVARG_FFE_MAIN, + TXGBE_DEVARG_FFE_PRE, + TXGBE_DEVARG_FFE_POST, + NULL }; struct txgbe_mbx_stats { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 3b36fd89e2..97796f040b 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -495,6 +495,10 @@ txgbe_parse_devargs(struct txgbe_hw *hw, struct rte_devargs *devargs) u16 poll = 0; u16 present = 1; u16 sgmii = 0; + u16 ffe_set = 0; + u16 ffe_main = 27; + u16 ffe_pre = 8; + u16 ffe_post = 44; if (devargs == NULL) goto null; @@ -511,6 +515,14 @@ txgbe_parse_devargs(struct txgbe_hw *hw, struct rte_devargs *devargs) &txgbe_handle_devarg, &present); rte_kvargs_process(kvlist, TXGBE_DEVARG_KX_SGMII, &txgbe_handle_devarg, &sgmii); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_SET, + &txgbe_handle_devarg, &ffe_set); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_MAIN, + &txgbe_handle_devarg, &ffe_main); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE, + &txgbe_handle_devarg, &ffe_pre); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST, + &txgbe_handle_devarg, &ffe_post); rte_kvargs_free(kvlist); null: @@ -518,6 +530,10 @@ null: hw->devarg.poll = poll; hw->devarg.present = present; hw->devarg.sgmii = sgmii; + hw->phy.ffe_set = ffe_set; + hw->phy.ffe_main = ffe_main; + hw->phy.ffe_pre = ffe_pre; + hw->phy.ffe_post = ffe_post; } static int @@ -5315,7 +5331,11 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_BP_AUTO "=<0|1>" TXGBE_DEVARG_KR_POLL "=<0|1>" TXGBE_DEVARG_KR_PRESENT "=<0|1>" - TXGBE_DEVARG_KX_SGMII "=<0|1>"); + TXGBE_DEVARG_KX_SGMII "=<0|1>" + TXGBE_DEVARG_FFE_SET "=<0-4>" + TXGBE_DEVARG_FFE_MAIN "=" + TXGBE_DEVARG_FFE_PRE "=" + TXGBE_DEVARG_FFE_POST "="); RTE_LOG_REGISTER(txgbe_logtype_init, pmd.net.txgbe.init, NOTICE); RTE_LOG_REGISTER(txgbe_logtype_driver, pmd.net.txgbe.driver, NOTICE); -- 2.20.1