mirror of
git://nv-tegra.nvidia.com/kernel/nvethernetrm.git
synced 2025-12-22 17:34:29 +03:00
core: add pcs register readback after write support
As per T23X-MGBE_HSIv2-14 requirement for PCS register we need to perform readback for each write operation to verify write operation was successful Bug 3606649 Change-Id: I7cca6baa43feaa4207b6158f0abc796e656338dd Signed-off-by: Om Prakash Singh <omp@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/kernel/nvethernetrm/+/2700845 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Bhadram Varka
parent
e0e2a6b200
commit
0c754dc009
@@ -280,7 +280,7 @@ struct core_ops {
|
|||||||
struct osi_core_ptp_tsc_data *data);
|
struct osi_core_ptp_tsc_data *data);
|
||||||
#ifdef HSI_SUPPORT
|
#ifdef HSI_SUPPORT
|
||||||
/** Interface function called to initialize HSI */
|
/** Interface function called to initialize HSI */
|
||||||
void (*core_hsi_configure)(struct osi_core_priv_data *const osi_core,
|
int (*core_hsi_configure)(struct osi_core_priv_data *const osi_core,
|
||||||
const nveu32_t enable);
|
const nveu32_t enable);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1714,8 +1714,10 @@ static void eqos_configure_rxq_priority(
|
|||||||
* @param[in, out] osi_core: OSI core private data structure.
|
* @param[in, out] osi_core: OSI core private data structure.
|
||||||
* @param[in] enable: OSI_ENABLE for enabling HSI feature, else disable
|
* @param[in] enable: OSI_ENABLE for enabling HSI feature, else disable
|
||||||
*
|
*
|
||||||
|
* @retval 0 on success
|
||||||
|
* @retval -1 on failure
|
||||||
*/
|
*/
|
||||||
static void eqos_hsi_configure(struct osi_core_priv_data *const osi_core,
|
static int eqos_hsi_configure(struct osi_core_priv_data *const osi_core,
|
||||||
const nveu32_t enable)
|
const nveu32_t enable)
|
||||||
{
|
{
|
||||||
nveu32_t value;
|
nveu32_t value;
|
||||||
@@ -1841,6 +1843,7 @@ static void eqos_hsi_configure(struct osi_core_priv_data *const osi_core,
|
|||||||
osi_writela(osi_core, value, (nveu8_t *)osi_core->base +
|
osi_writela(osi_core, value, (nveu8_t *)osi_core->base +
|
||||||
EQOS_WRAP_COMMON_INTR_ENABLE);
|
EQOS_WRAP_COMMON_INTR_ENABLE);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2572,12 +2572,14 @@ static int mgbe_config_flow_control(struct osi_core_priv_data *const osi_core,
|
|||||||
* @param[in, out] osi_core: OSI core private data structure.
|
* @param[in, out] osi_core: OSI core private data structure.
|
||||||
* @param[in] enable: OSI_ENABLE for Enabling HSI feature, else disable
|
* @param[in] enable: OSI_ENABLE for Enabling HSI feature, else disable
|
||||||
*
|
*
|
||||||
|
* @retval 0 on success
|
||||||
|
* @retval -1 on failure
|
||||||
*/
|
*/
|
||||||
static void mgbe_hsi_configure(struct osi_core_priv_data *const osi_core,
|
static int mgbe_hsi_configure(struct osi_core_priv_data *const osi_core,
|
||||||
const nveu32_t enable)
|
const nveu32_t enable)
|
||||||
{
|
{
|
||||||
nveu32_t value = 0U;
|
nveu32_t value = 0U;
|
||||||
void *xpcs_base = osi_core->xpcs_base;
|
int ret = 0;
|
||||||
|
|
||||||
if (enable == OSI_ENABLE) {
|
if (enable == OSI_ENABLE) {
|
||||||
osi_core->hsi.enabled = OSI_ENABLE;
|
osi_core->hsi.enabled = OSI_ENABLE;
|
||||||
@@ -2585,13 +2587,17 @@ static void mgbe_hsi_configure(struct osi_core_priv_data *const osi_core,
|
|||||||
|
|
||||||
/* T23X-MGBE_HSIv2-10 Enable PCS ECC */
|
/* T23X-MGBE_HSIv2-10 Enable PCS ECC */
|
||||||
value = (EN_ERR_IND | FEC_EN);
|
value = (EN_ERR_IND | FEC_EN);
|
||||||
xpcs_write(xpcs_base, XPCS_BASE_PMA_MMD_SR_PMA_KR_FEC_CTRL, value);
|
ret = xpcs_write_safety(osi_core, XPCS_BASE_PMA_MMD_SR_PMA_KR_FEC_CTRL, value);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
/* T23X-MGBE_HSIv2-12:Initialization of Transaction Timeout in PCS */
|
/* T23X-MGBE_HSIv2-12:Initialization of Transaction Timeout in PCS */
|
||||||
/* T23X-MGBE_HSIv2-11:Initialization of Watchdog Timer */
|
/* T23X-MGBE_HSIv2-11:Initialization of Watchdog Timer */
|
||||||
value = (0xCCU << XPCS_SFTY_1US_MULT_SHIFT) & XPCS_SFTY_1US_MULT_MASK;
|
value = (0xCCU << XPCS_SFTY_1US_MULT_SHIFT) & XPCS_SFTY_1US_MULT_MASK;
|
||||||
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_SFTY_TMR_CTRL, value);
|
ret = xpcs_write_safety(osi_core, XPCS_VR_XS_PCS_SFTY_TMR_CTRL, value);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
/* T23X-MGBE_HSIv2-1 Configure ECC */
|
/* T23X-MGBE_HSIv2-1 Configure ECC */
|
||||||
value = osi_readla(osi_core,
|
value = osi_readla(osi_core,
|
||||||
(nveu8_t *)osi_core->base + MGBE_MTL_ECC_CONTROL);
|
(nveu8_t *)osi_core->base + MGBE_MTL_ECC_CONTROL);
|
||||||
@@ -2670,11 +2676,15 @@ static void mgbe_hsi_configure(struct osi_core_priv_data *const osi_core,
|
|||||||
osi_core->hsi.enabled = OSI_DISABLE;
|
osi_core->hsi.enabled = OSI_DISABLE;
|
||||||
|
|
||||||
/* T23X-MGBE_HSIv2-10 Disable PCS ECC */
|
/* T23X-MGBE_HSIv2-10 Disable PCS ECC */
|
||||||
xpcs_write(xpcs_base, XPCS_BASE_PMA_MMD_SR_PMA_KR_FEC_CTRL, 0);
|
ret = xpcs_write_safety(osi_core, XPCS_BASE_PMA_MMD_SR_PMA_KR_FEC_CTRL, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
/* T23X-MGBE_HSIv2-11:Deinitialization of Watchdog Timer */
|
/* T23X-MGBE_HSIv2-11:Deinitialization of Watchdog Timer */
|
||||||
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_SFTY_TMR_CTRL, 0);
|
ret = xpcs_write_safety(osi_core, XPCS_VR_XS_PCS_SFTY_TMR_CTRL, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
/* T23X-MGBE_HSIv2-1 Disable ECC */
|
/* T23X-MGBE_HSIv2-1 Disable ECC */
|
||||||
value = osi_readla(osi_core,
|
value = osi_readla(osi_core,
|
||||||
(nveu8_t *)osi_core->base + MGBE_MTL_ECC_CONTROL);
|
(nveu8_t *)osi_core->base + MGBE_MTL_ECC_CONTROL);
|
||||||
@@ -2732,6 +2742,7 @@ static void mgbe_hsi_configure(struct osi_core_priv_data *const osi_core,
|
|||||||
osi_writela(osi_core, value, (nveu8_t *)osi_core->xpcs_base +
|
osi_writela(osi_core, value, (nveu8_t *)osi_core->xpcs_base +
|
||||||
XPCS_WRAP_INTERRUPT_CONTROL);
|
XPCS_WRAP_INTERRUPT_CONTROL);
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -4250,11 +4261,11 @@ static void mgbe_handle_hsi_intr(struct osi_core_priv_data *osi_core)
|
|||||||
/* Clear status register for PCS error */
|
/* Clear status register for PCS error */
|
||||||
val = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_SFTY_UE_INTR0);
|
val = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_SFTY_UE_INTR0);
|
||||||
if (val != 0U) {
|
if (val != 0U) {
|
||||||
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_SFTY_UE_INTR0, 0);
|
(void)xpcs_write_safety(osi_core, XPCS_VR_XS_PCS_SFTY_UE_INTR0, 0);
|
||||||
}
|
}
|
||||||
val = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_SFTY_CE_INTR);
|
val = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_SFTY_CE_INTR);
|
||||||
if (val != 0U) {
|
if (val != 0U) {
|
||||||
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_SFTY_CE_INTR, 0);
|
(void)xpcs_write_safety(osi_core, XPCS_VR_XS_PCS_SFTY_CE_INTR, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5258,7 +5269,7 @@ static void mgbe_configure_eee(struct osi_core_priv_data *osi_core,
|
|||||||
unsigned int tic_counter = 0;
|
unsigned int tic_counter = 0;
|
||||||
void *addr = osi_core->base;
|
void *addr = osi_core->base;
|
||||||
|
|
||||||
if (xpcs_eee(osi_core->xpcs_base, tx_lpi_enabled) != 0) {
|
if (xpcs_eee(osi_core, tx_lpi_enabled) != 0) {
|
||||||
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID,
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID,
|
||||||
"xpcs_eee call failed\n", 0ULL);
|
"xpcs_eee call failed\n", 0ULL);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2054,8 +2054,7 @@ nve32_t osi_hal_handle_ioctl(struct osi_core_priv_data *osi_core,
|
|||||||
break;
|
break;
|
||||||
#ifdef HSI_SUPPORT
|
#ifdef HSI_SUPPORT
|
||||||
case OSI_CMD_HSI_CONFIGURE:
|
case OSI_CMD_HSI_CONFIGURE:
|
||||||
ops_p->core_hsi_configure(osi_core, data->arg1_u32);
|
ret = ops_p->core_hsi_configure(osi_core, data->arg1_u32);
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ static inline int xpcs_poll_for_an_complete(struct osi_core_priv_data *osi_core,
|
|||||||
unsigned int retry = 1000;
|
unsigned int retry = 1000;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
int cond = 1;
|
int cond = 1;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
/* 14. Poll for AN complete */
|
/* 14. Poll for AN complete */
|
||||||
cond = 1;
|
cond = 1;
|
||||||
@@ -70,7 +71,10 @@ static inline int xpcs_poll_for_an_complete(struct osi_core_priv_data *osi_core,
|
|||||||
} else {
|
} else {
|
||||||
/* 15. clear interrupt */
|
/* 15. clear interrupt */
|
||||||
status &= ~XPCS_VR_MII_AN_INTR_STS_CL37_ANCMPLT_INTR;
|
status &= ~XPCS_VR_MII_AN_INTR_STS_CL37_ANCMPLT_INTR;
|
||||||
xpcs_write(xpcs_base, XPCS_VR_MII_AN_INTR_STS, status);
|
ret = xpcs_write_safety(osi_core, XPCS_VR_MII_AN_INTR_STS, status);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
cond = 0;
|
cond = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,14 +94,18 @@ static inline int xpcs_poll_for_an_complete(struct osi_core_priv_data *osi_core,
|
|||||||
*
|
*
|
||||||
* Algorithm: This routine program XPCS speed based on AN status.
|
* Algorithm: This routine program XPCS speed based on AN status.
|
||||||
*
|
*
|
||||||
* @param[in] xpcs_base: XPCS base virtual address.
|
* @param[in] osi_core: OSI core data structure.
|
||||||
* @param[in] status: Autonegotation Status.
|
* @param[in] status: Autonegotation Status.
|
||||||
|
*
|
||||||
|
* @retval 0 on success
|
||||||
|
* @retval -1 on failure
|
||||||
*/
|
*/
|
||||||
static inline void xpcs_set_speed(void *xpcs_base,
|
static inline int xpcs_set_speed(struct osi_core_priv_data *osi_core,
|
||||||
unsigned int status)
|
unsigned int status)
|
||||||
{
|
{
|
||||||
unsigned int speed = status & XPCS_USXG_AN_STS_SPEED_MASK;
|
unsigned int speed = status & XPCS_USXG_AN_STS_SPEED_MASK;
|
||||||
unsigned int ctrl = 0;
|
unsigned int ctrl = 0;
|
||||||
|
void *xpcs_base = osi_core->xpcs_base;
|
||||||
|
|
||||||
ctrl = xpcs_read(xpcs_base, XPCS_SR_MII_CTRL);
|
ctrl = xpcs_read(xpcs_base, XPCS_SR_MII_CTRL);
|
||||||
|
|
||||||
@@ -120,7 +128,7 @@ static inline void xpcs_set_speed(void *xpcs_base,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
xpcs_write(xpcs_base, XPCS_SR_MII_CTRL, ctrl);
|
return xpcs_write_safety(osi_core, XPCS_SR_MII_CTRL, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,15 +162,19 @@ int xpcs_start(struct osi_core_priv_data *osi_core)
|
|||||||
(osi_core->phy_iface_mode == OSI_USXGMII_MODE_5G)) {
|
(osi_core->phy_iface_mode == OSI_USXGMII_MODE_5G)) {
|
||||||
ctrl = xpcs_read(xpcs_base, XPCS_SR_MII_CTRL);
|
ctrl = xpcs_read(xpcs_base, XPCS_SR_MII_CTRL);
|
||||||
ctrl |= XPCS_SR_MII_CTRL_AN_ENABLE;
|
ctrl |= XPCS_SR_MII_CTRL_AN_ENABLE;
|
||||||
xpcs_write(xpcs_base, XPCS_SR_MII_CTRL, ctrl);
|
ret = xpcs_write_safety(osi_core, XPCS_SR_MII_CTRL, ctrl);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
ret = xpcs_poll_for_an_complete(osi_core, &an_status);
|
ret = xpcs_poll_for_an_complete(osi_core, &an_status);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
xpcs_set_speed(xpcs_base, an_status);
|
ret = xpcs_set_speed(osi_core, an_status);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
/* USXGMII Rate Adaptor Reset before data transfer */
|
/* USXGMII Rate Adaptor Reset before data transfer */
|
||||||
ctrl = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_DIG_CTRL1);
|
ctrl = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_DIG_CTRL1);
|
||||||
ctrl |= XPCS_VR_XS_PCS_DIG_CTRL1_USRA_RST;
|
ctrl |= XPCS_VR_XS_PCS_DIG_CTRL1_USRA_RST;
|
||||||
@@ -446,6 +458,7 @@ int xpcs_init(struct osi_core_priv_data *osi_core)
|
|||||||
unsigned int count;
|
unsigned int count;
|
||||||
unsigned int ctrl = 0;
|
unsigned int ctrl = 0;
|
||||||
int cond = 1;
|
int cond = 1;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (osi_core->xpcs_base == OSI_NULL) {
|
if (osi_core->xpcs_base == OSI_NULL) {
|
||||||
OSI_CORE_ERR(OSI_NULL, OSI_LOG_ARG_HW_FAIL,
|
OSI_CORE_ERR(OSI_NULL, OSI_LOG_ARG_HW_FAIL,
|
||||||
@@ -469,8 +482,10 @@ int xpcs_init(struct osi_core_priv_data *osi_core)
|
|||||||
/* 1. switch DWC_xpcs to BASE-R mode */
|
/* 1. switch DWC_xpcs to BASE-R mode */
|
||||||
ctrl = xpcs_read(xpcs_base, XPCS_SR_XS_PCS_CTRL2);
|
ctrl = xpcs_read(xpcs_base, XPCS_SR_XS_PCS_CTRL2);
|
||||||
ctrl |= XPCS_SR_XS_PCS_CTRL2_PCS_TYPE_SEL_BASE_R;
|
ctrl |= XPCS_SR_XS_PCS_CTRL2_PCS_TYPE_SEL_BASE_R;
|
||||||
xpcs_write(xpcs_base, XPCS_SR_XS_PCS_CTRL2, ctrl);
|
ret = xpcs_write_safety(osi_core, XPCS_SR_XS_PCS_CTRL2, ctrl);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
/* 2. enable USXGMII Mode inside DWC_xpcs */
|
/* 2. enable USXGMII Mode inside DWC_xpcs */
|
||||||
|
|
||||||
/* 3. USXG_MODE = 10G - default it will be 10G mode */
|
/* 3. USXG_MODE = 10G - default it will be 10G mode */
|
||||||
@@ -484,8 +499,10 @@ int xpcs_init(struct osi_core_priv_data *osi_core)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_KR_CTRL, ctrl);
|
ret = xpcs_write_safety(osi_core, XPCS_VR_XS_PCS_KR_CTRL, ctrl);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
/* 4. Program PHY to operate at 10Gbps/5Gbps/2Gbps
|
/* 4. Program PHY to operate at 10Gbps/5Gbps/2Gbps
|
||||||
* this step not required since PHY speed programming
|
* this step not required since PHY speed programming
|
||||||
* already done as part of phy INIT
|
* already done as part of phy INIT
|
||||||
@@ -493,6 +510,14 @@ int xpcs_init(struct osi_core_priv_data *osi_core)
|
|||||||
/* 5. Vendor specific software reset */
|
/* 5. Vendor specific software reset */
|
||||||
ctrl = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_DIG_CTRL1);
|
ctrl = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_DIG_CTRL1);
|
||||||
ctrl |= XPCS_VR_XS_PCS_DIG_CTRL1_USXG_EN;
|
ctrl |= XPCS_VR_XS_PCS_DIG_CTRL1_USXG_EN;
|
||||||
|
ret = xpcs_write_safety(osi_core, XPCS_VR_XS_PCS_DIG_CTRL1, ctrl);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XPCS_VR_XS_PCS_DIG_CTRL1_VR_RST bit is self clearing
|
||||||
|
* value readback varification is not needed
|
||||||
|
*/
|
||||||
ctrl |= XPCS_VR_XS_PCS_DIG_CTRL1_VR_RST;
|
ctrl |= XPCS_VR_XS_PCS_DIG_CTRL1_VR_RST;
|
||||||
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_DIG_CTRL1, ctrl);
|
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_DIG_CTRL1, ctrl);
|
||||||
|
|
||||||
@@ -524,11 +549,16 @@ int xpcs_init(struct osi_core_priv_data *osi_core)
|
|||||||
(osi_core->phy_iface_mode == OSI_USXGMII_MODE_5G)) {
|
(osi_core->phy_iface_mode == OSI_USXGMII_MODE_5G)) {
|
||||||
ctrl = xpcs_read(xpcs_base, XPCS_SR_AN_CTRL);
|
ctrl = xpcs_read(xpcs_base, XPCS_SR_AN_CTRL);
|
||||||
ctrl &= ~XPCS_SR_AN_CTRL_AN_EN;
|
ctrl &= ~XPCS_SR_AN_CTRL_AN_EN;
|
||||||
xpcs_write(xpcs_base, XPCS_SR_AN_CTRL, ctrl);
|
ret = xpcs_write_safety(osi_core, XPCS_SR_AN_CTRL, ctrl);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
ctrl = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_DIG_CTRL1);
|
ctrl = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_DIG_CTRL1);
|
||||||
ctrl |= XPCS_VR_XS_PCS_DIG_CTRL1_CL37_BP;
|
ctrl |= XPCS_VR_XS_PCS_DIG_CTRL1_CL37_BP;
|
||||||
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_DIG_CTRL1, ctrl);
|
ret = xpcs_write_safety(osi_core, XPCS_VR_XS_PCS_DIG_CTRL1, ctrl);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: 9. MII_AN_INTR_EN to 1, to enable auto-negotiation
|
/* TODO: 9. MII_AN_INTR_EN to 1, to enable auto-negotiation
|
||||||
@@ -549,15 +579,17 @@ int xpcs_init(struct osi_core_priv_data *osi_core)
|
|||||||
* Algorithm: This routine update register related to EEE
|
* Algorithm: This routine update register related to EEE
|
||||||
* for XPCS.
|
* for XPCS.
|
||||||
*
|
*
|
||||||
* @param[in] xpcs_base: XPCS virtual base address
|
* @param[in] osi_core: OSI core data structure.
|
||||||
* @param[in] en_dis: enable - 1 or disable - 0
|
* @param[in] en_dis: enable - 1 or disable - 0
|
||||||
*
|
*
|
||||||
* @retval 0 on success
|
* @retval 0 on success
|
||||||
* @retval -1 on failure.
|
* @retval -1 on failure.
|
||||||
*/
|
*/
|
||||||
int xpcs_eee(void *xpcs_base, unsigned int en_dis)
|
int xpcs_eee(struct osi_core_priv_data *osi_core, unsigned int en_dis)
|
||||||
{
|
{
|
||||||
|
void *xpcs_base = osi_core->xpcs_base;
|
||||||
unsigned int val = 0x0U;
|
unsigned int val = 0x0U;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (en_dis != OSI_ENABLE && en_dis != OSI_DISABLE) {
|
if (en_dis != OSI_ENABLE && en_dis != OSI_DISABLE) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -570,7 +602,10 @@ int xpcs_eee(void *xpcs_base, unsigned int en_dis)
|
|||||||
val = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_EEE_MCTRL0);
|
val = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_EEE_MCTRL0);
|
||||||
val &= ~XPCS_VR_XS_PCS_EEE_MCTRL0_LTX_EN;
|
val &= ~XPCS_VR_XS_PCS_EEE_MCTRL0_LTX_EN;
|
||||||
val &= ~XPCS_VR_XS_PCS_EEE_MCTRL0_LRX_EN;
|
val &= ~XPCS_VR_XS_PCS_EEE_MCTRL0_LRX_EN;
|
||||||
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_EEE_MCTRL0, val);
|
ret = xpcs_write_safety(osi_core, XPCS_VR_XS_PCS_EEE_MCTRL0, val);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,12 +623,16 @@ int xpcs_eee(void *xpcs_base, unsigned int en_dis)
|
|||||||
/* 4. enable the EEE feature on the Tx path and Rx path */
|
/* 4. enable the EEE feature on the Tx path and Rx path */
|
||||||
val |= (XPCS_VR_XS_PCS_EEE_MCTRL0_LTX_EN |
|
val |= (XPCS_VR_XS_PCS_EEE_MCTRL0_LTX_EN |
|
||||||
XPCS_VR_XS_PCS_EEE_MCTRL0_LRX_EN);
|
XPCS_VR_XS_PCS_EEE_MCTRL0_LRX_EN);
|
||||||
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_EEE_MCTRL0, val);
|
ret = xpcs_write_safety(osi_core, XPCS_VR_XS_PCS_EEE_MCTRL0, val);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
/* Transparent Tx LPI Mode Enable */
|
/* Transparent Tx LPI Mode Enable */
|
||||||
val = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_EEE_MCTRL1);
|
val = xpcs_read(xpcs_base, XPCS_VR_XS_PCS_EEE_MCTRL1);
|
||||||
val |= XPCS_VR_XS_PCS_EEE_MCTRL1_TRN_LPI;
|
val |= XPCS_VR_XS_PCS_EEE_MCTRL1_TRN_LPI;
|
||||||
xpcs_write(xpcs_base, XPCS_VR_XS_PCS_EEE_MCTRL1, val);
|
ret = xpcs_write_safety(osi_core, XPCS_VR_XS_PCS_EEE_MCTRL1, val);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@
|
|||||||
|
|
||||||
int xpcs_init(struct osi_core_priv_data *osi_core);
|
int xpcs_init(struct osi_core_priv_data *osi_core);
|
||||||
int xpcs_start(struct osi_core_priv_data *osi_core);
|
int xpcs_start(struct osi_core_priv_data *osi_core);
|
||||||
int xpcs_eee(void *xpcs_base, unsigned int en_dis);
|
int xpcs_eee(struct osi_core_priv_data *osi_core, unsigned int en_dis);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief xpcs_read - read from xpcs.
|
* @brief xpcs_read - read from xpcs.
|
||||||
@@ -148,7 +148,7 @@ static inline unsigned int xpcs_read(void *xpcs_base, unsigned int reg_addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief xpcs_read - write to xpcs.
|
* @brief xpcs_write - write to xpcs.
|
||||||
*
|
*
|
||||||
* Algorithm: This routine writes data to XPCS register.
|
* Algorithm: This routine writes data to XPCS register.
|
||||||
*
|
*
|
||||||
@@ -164,4 +164,40 @@ static inline void xpcs_write(void *xpcs_base, unsigned int reg_addr,
|
|||||||
osi_writel(val, (unsigned char *)xpcs_base +
|
osi_writel(val, (unsigned char *)xpcs_base +
|
||||||
(((reg_addr) & XPCS_REG_VALUE_MASK)));
|
(((reg_addr) & XPCS_REG_VALUE_MASK)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief xpcs_write_safety - write to xpcs.
|
||||||
|
*
|
||||||
|
* Algorithm: This routine writes data to XPCS register.
|
||||||
|
* And verifiy by reading back the value
|
||||||
|
*
|
||||||
|
* @param[in] osi_core: OSI core data structure
|
||||||
|
* @param[in] reg_addr: register address for writing
|
||||||
|
* @param[in] val: write value to register address
|
||||||
|
*
|
||||||
|
* @retval 0 on success
|
||||||
|
* @retval -1 on failure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static inline int xpcs_write_safety(struct osi_core_priv_data *osi_core,
|
||||||
|
unsigned int reg_addr,
|
||||||
|
unsigned int val)
|
||||||
|
{
|
||||||
|
void *xpcs_base = osi_core->xpcs_base;
|
||||||
|
unsigned int read_val;
|
||||||
|
int retry = 10;
|
||||||
|
|
||||||
|
while (--retry > 0) {
|
||||||
|
xpcs_write(xpcs_base, reg_addr, val);
|
||||||
|
read_val = xpcs_read(xpcs_base, reg_addr);
|
||||||
|
if (val == read_val) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
osi_core->osd_ops.udelay(OSI_DELAY_1US);
|
||||||
|
}
|
||||||
|
|
||||||
|
OSI_CORE_ERR(OSI_NULL, OSI_LOG_ARG_HW_FAIL,
|
||||||
|
"xpcs_write_safety failed", reg_addr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user