mirror of
git://nv-tegra.nvidia.com/kernel/nvethernetrm.git
synced 2025-12-22 17:34:29 +03:00
osi: Add RX_EQ training via SW override method
Add RX_EQ training after mgbe link up to overcome insertion loss Bug 5277708 Bug 5017313 Change-Id: I19270c68cc570b3320c1db24298439cfbf412170 Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com> (cherry picked from commit ac35e507b220de89de9d856e2ba0cdae59656b1f) Reviewed-on: https://git-master.nvidia.com/r/c/kernel/nvethernetrm/+/3383664 Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com> Reviewed-by: Narayana Reddy P <narayanr@nvidia.com> Reviewed-by: Bhadram Varka <vbhadram@nvidia.com> Reviewed-by: svcacv <svcacv@nvidia.com>
This commit is contained in:
committed by
Amulya Yarlagadda
parent
53c6e3ffc4
commit
8a43cf10fb
@@ -776,6 +776,16 @@ typedef my_lint_64 nvel64_t;
|
|||||||
/** @} */
|
/** @} */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup RX EQ related information
|
||||||
|
*
|
||||||
|
* @brief RX EQ Software override
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/** @brief RX EQ Software override is enabled */
|
||||||
|
#define OSI_RX_EQ_SW_OVRD 1U
|
||||||
|
/** @} */
|
||||||
|
|
||||||
struct osi_core_priv_data;
|
struct osi_core_priv_data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1892,6 +1902,8 @@ struct osi_core_priv_data {
|
|||||||
nveu32_t skip_usxgmii_an;
|
nveu32_t skip_usxgmii_an;
|
||||||
/** MAC common interrupt received */
|
/** MAC common interrupt received */
|
||||||
nveu32_t mac_common_intr_rcvd;
|
nveu32_t mac_common_intr_rcvd;
|
||||||
|
/** Flag to enable pcs RX EQ SW override logic */
|
||||||
|
nveu32_t pcs_rx_eq_sw_ovrd_en;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -613,15 +613,18 @@ static inline nveu64_t osi_update_stats_counter(nveu64_t last_value,
|
|||||||
*/
|
*/
|
||||||
#define RETRY_COUNT 1000U
|
#define RETRY_COUNT 1000U
|
||||||
#define RETRY_DELAY 1U
|
#define RETRY_DELAY 1U
|
||||||
|
#define OSI_DELAY_2US 2U
|
||||||
#define OSI_DELAY_4US 4U
|
#define OSI_DELAY_4US 4U
|
||||||
#define OSI_DELAY_10US 10U
|
#define OSI_DELAY_10US 10U
|
||||||
#ifndef OSI_STRIPPED_LIB
|
#ifndef OSI_STRIPPED_LIB
|
||||||
#define OSI_DELAY_100US 100U
|
#define OSI_DELAY_100US 100U
|
||||||
#endif
|
#endif
|
||||||
#define OSI_DELAY_200US 200U
|
#define OSI_DELAY_200US 200U
|
||||||
|
#define OSI_DELAY_500US 500U
|
||||||
#define OSI_DELAY_1000US 1000U
|
#define OSI_DELAY_1000US 1000U
|
||||||
#define OSI_DELAY_10000US 10000U
|
#define OSI_DELAY_10000US 10000U
|
||||||
#define OSI_DELAY_30000US 30000U
|
#define OSI_DELAY_30000US 30000U
|
||||||
|
#define OSI_DELAY_1000000US 1000000U
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|||||||
137
osi/core/xpcs.c
137
osi/core/xpcs.c
@@ -575,6 +575,136 @@ fail:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief xpcs_rx_eq_sw_override - Execute RX EQ training
|
||||||
|
*
|
||||||
|
* Algorithm: This routine executes RX EQ training through
|
||||||
|
* sw override method.
|
||||||
|
*
|
||||||
|
* @param[in] osi_core: OSI core data structure.
|
||||||
|
*
|
||||||
|
* @retval 0 on success
|
||||||
|
* @retval -1 on failure.
|
||||||
|
*/
|
||||||
|
nve32_t xpcs_rx_eq_sw_override(struct osi_core_priv_data *osi_core)
|
||||||
|
{
|
||||||
|
nveu32_t val = 0;
|
||||||
|
nve32_t ret = 0;
|
||||||
|
nveu32_t count;
|
||||||
|
nve32_t cond;
|
||||||
|
nveu32_t rx_eq_retry = RETRY_COUNT;
|
||||||
|
|
||||||
|
osi_writela(osi_core, XPCS_WRAP_UPHY_RX_CTRL_12_0_SLEEP_DLY,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_12_0);
|
||||||
|
|
||||||
|
val = osi_readla(osi_core,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_12_0);
|
||||||
|
if (val != XPCS_WRAP_UPHY_RX_CTRL_12_0_SLEEP_DLY) {
|
||||||
|
ret = -1;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = osi_readla(osi_core,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0);
|
||||||
|
|
||||||
|
val |= XPCS_WRAP_UPHY_RX_CTRL_0_0_PRE_RX_EQ_MASK_1;
|
||||||
|
|
||||||
|
val &= ~(XPCS_WRAP_UPHY_RX_CTRL_0_0_PRE_RX_EQ_MASK_2);
|
||||||
|
|
||||||
|
osi_writela(osi_core, val,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0);
|
||||||
|
|
||||||
|
val = osi_readla(osi_core,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0);
|
||||||
|
/* Enable RX_SW_OVRD */
|
||||||
|
val |= XPCS_WRAP_UPHY_RX_CTRL_0_0_RX_SW_OVRD;
|
||||||
|
osi_writela(osi_core, val,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0);
|
||||||
|
|
||||||
|
/* wait 1 second */
|
||||||
|
osi_core->osd_ops.usleep(OSI_DELAY_1000000US);
|
||||||
|
|
||||||
|
val = osi_readla(osi_core,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0);
|
||||||
|
/* RX_EQ_RESET */
|
||||||
|
val |= XPCS_WRAP_UPHY_RX_CTRL_0_0_RX_EQ_RESET;
|
||||||
|
osi_writela(osi_core, val,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0);
|
||||||
|
|
||||||
|
cond = COND_NOT_MET;
|
||||||
|
count = 0;
|
||||||
|
while (cond == COND_NOT_MET) {
|
||||||
|
val = osi_readla(osi_core,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0);
|
||||||
|
|
||||||
|
if ((val & XPCS_WRAP_UPHY_RX_CTRL_0_0_RX_EQ_RESET) != 0) {
|
||||||
|
if (count > rx_eq_retry) {
|
||||||
|
ret = -1;
|
||||||
|
OSI_CORE_INFO(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
||||||
|
"RX_EQ_RESET failed\n", 0ULL);
|
||||||
|
goto fail; // RX_EQ_RESET failed
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
osi_core->osd_ops.udelay(OSI_DELAY_2US);
|
||||||
|
} else {
|
||||||
|
cond = COND_MET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait 1 second */
|
||||||
|
osi_core->osd_ops.usleep(OSI_DELAY_1000000US);
|
||||||
|
|
||||||
|
/* RX_EQ_TRAIN_EN */
|
||||||
|
val |= XPCS_WRAP_UPHY_RX_CTRL_0_0_RX_EQ_TRAIN_EN;
|
||||||
|
osi_writela(osi_core, val,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0);
|
||||||
|
|
||||||
|
/* Poll until bit 11 clears or timeout */
|
||||||
|
|
||||||
|
cond = COND_NOT_MET;
|
||||||
|
count = 0;
|
||||||
|
while (cond == COND_NOT_MET) {
|
||||||
|
val = osi_readla(osi_core,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0);
|
||||||
|
|
||||||
|
if ((val & XPCS_WRAP_UPHY_RX_CTRL_0_0_RX_EQ_TRAIN_EN) != 0) {
|
||||||
|
if (count > rx_eq_retry) {
|
||||||
|
ret = -1;
|
||||||
|
OSI_CORE_INFO(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
||||||
|
"RX_EQ_TRAIN_EN failed\n", 0ULL);
|
||||||
|
goto fail; // RX_EQ_TRAIN_EN failed
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
osi_core->osd_ops.usleep(OSI_DELAY_500US);
|
||||||
|
} else {
|
||||||
|
cond = COND_MET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable RX_SW_OVRD */
|
||||||
|
val &= ~XPCS_WRAP_UPHY_RX_CTRL_0_0_RX_SW_OVRD;
|
||||||
|
osi_writela(osi_core, val,
|
||||||
|
(nveu8_t *)osi_core->xpcs_base +
|
||||||
|
T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0);
|
||||||
|
|
||||||
|
/* wait 2 micro seconds */
|
||||||
|
osi_core->osd_ops.udelay(OSI_DELAY_2US);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief xpcs_lane_bring_up - Bring up UPHY Tx/Rx lanes
|
* @brief xpcs_lane_bring_up - Bring up UPHY Tx/Rx lanes
|
||||||
*
|
*
|
||||||
@@ -769,6 +899,13 @@ step10:
|
|||||||
OSI_CORE_INFO(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
OSI_CORE_INFO(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
||||||
"PCS block lock SUCCESS\n", 0ULL);
|
"PCS block lock SUCCESS\n", 0ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (osi_core->pcs_rx_eq_sw_ovrd_en == OSI_RX_EQ_SW_OVRD) {
|
||||||
|
if (xpcs_rx_eq_sw_override(osi_core)) {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,8 @@
|
|||||||
#define T26X_XPCS_WRAP_UPHY_RX_CTRL_2 0x8040
|
#define T26X_XPCS_WRAP_UPHY_RX_CTRL_2 0x8040
|
||||||
#define T26X_XPCS_WRAP_UPHY_RX_CTRL_3 0x8044
|
#define T26X_XPCS_WRAP_UPHY_RX_CTRL_3 0x8044
|
||||||
#define T26X_XPCS_WRAP_UPHY_TIMEOUT_CONTROL_0_0 0x8070
|
#define T26X_XPCS_WRAP_UPHY_TIMEOUT_CONTROL_0_0 0x8070
|
||||||
|
#define T26X_XPCS_WRAP_UPHY_RX_CTRL_0_0 0x8034
|
||||||
|
#define T26X_XPCS_WRAP_UPHY_RX_CTRL_12_0 0x8058
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
@@ -195,6 +197,13 @@
|
|||||||
#define XPCS_SR_PMA_KR_FEC_CTRL_FEC_EN OSI_BIT(0)
|
#define XPCS_SR_PMA_KR_FEC_CTRL_FEC_EN OSI_BIT(0)
|
||||||
#define XPCS_SR_PMA_KR_FEC_CTRL_EN_ERR_IND OSI_BIT(1)
|
#define XPCS_SR_PMA_KR_FEC_CTRL_EN_ERR_IND OSI_BIT(1)
|
||||||
|
|
||||||
|
#define XPCS_WRAP_UPHY_RX_CTRL_0_0_PRE_RX_EQ_MASK_1 OSI_BIT(0) | OSI_BIT(10)
|
||||||
|
#define XPCS_WRAP_UPHY_RX_CTRL_0_0_PRE_RX_EQ_MASK_2 OSI_BIT(4) | OSI_BIT(5) | OSI_BIT(6) | OSI_BIT(7)
|
||||||
|
#define XPCS_WRAP_UPHY_RX_CTRL_0_0_RX_EQ_TRAIN_EN OSI_BIT(11)
|
||||||
|
#define XPCS_WRAP_UPHY_RX_CTRL_0_0_RX_EQ_RESET OSI_BIT(12)
|
||||||
|
#define XPCS_WRAP_UPHY_RX_CTRL_0_0_RX_SW_OVRD OSI_BIT(31)
|
||||||
|
#define XPCS_WRAP_UPHY_RX_CTRL_12_0_SLEEP_DLY 0x200U
|
||||||
|
|
||||||
#ifdef HSI_SUPPORT
|
#ifdef HSI_SUPPORT
|
||||||
#define XPCS_WRAP_INTERRUPT_CONTROL 0x8048
|
#define XPCS_WRAP_INTERRUPT_CONTROL 0x8048
|
||||||
#define T26X_XPCS_WRAP_INTERRUPT_CONTROL 0x8084
|
#define T26X_XPCS_WRAP_INTERRUPT_CONTROL 0x8084
|
||||||
@@ -327,4 +336,31 @@ static inline nve32_t xpcs_write_safety(struct osi_core_priv_data *osi_core,
|
|||||||
#endif /* !OSI_STRIPPED_LIB */
|
#endif /* !OSI_STRIPPED_LIB */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Description: Execute RX EQ training through SW Override method.
|
||||||
|
*
|
||||||
|
* @param[in] osi_core: A pointer to the osi_core_priv_data structure
|
||||||
|
* * Range: A non-null pointer to NVETHERNETRM_PIF$osi_core_priv_data structure.
|
||||||
|
* * Refer NVETHERNETRM_PIF$osi_core_priv_data
|
||||||
|
*
|
||||||
|
* @usage
|
||||||
|
* - Allowed context for the API call
|
||||||
|
* - Interrupt handler: No
|
||||||
|
* - Signal handler: No
|
||||||
|
* - Thread safe: No
|
||||||
|
* - Async/Sync: Sync
|
||||||
|
* - Required Privileges: None
|
||||||
|
* - API Group:
|
||||||
|
* - Initialization: Yes
|
||||||
|
* - Run time: No
|
||||||
|
* - De-initialization: No
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* 0 on success
|
||||||
|
* -1 on failure
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
nve32_t xpcs_rx_eq_sw_override(struct osi_core_priv_data *osi_core);
|
||||||
#endif /* INCLUDED_XPCS_H_ */
|
#endif /* INCLUDED_XPCS_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user