/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2015-2020
+ * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd.
+ * Copyright(c) 2010-2017 Intel Corporation
*/
#include "txgbe_hw.h"
#include "txgbe_mng.h"
#include "txgbe_phy.h"
-static void txgbe_i2c_start(struct txgbe_hw *hw);
+static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr);
static void txgbe_i2c_stop(struct txgbe_hw *hw);
static s32 txgbe_handle_bp_flow(u32 link_mode, struct txgbe_hw *hw);
static void txgbe_get_bp_ability(struct txgbe_backplane_ability *ability,
u16 phy_addr = 0;
if (!txgbe_validate_phy_addr(hw, phy_addr)) {
- DEBUGOUT("Unable to validate PHY address 0x%04X\n",
+ DEBUGOUT("Unable to validate PHY address 0x%04X",
phy_addr);
return false;
}
{
s32 err = TXGBE_ERR_PHY_ADDR_INVALID;
- DEBUGFUNC("txgbe_identify_phy");
-
txgbe_read_phy_if(hw);
if (hw->phy.type != txgbe_phy_unknown)
{
u32 mmngc;
- DEBUGFUNC("txgbe_check_reset_blocked");
-
mmngc = rd32(hw, TXGBE_STAT);
if (mmngc & TXGBE_STAT_MNGVETO) {
- DEBUGOUT("MNG_VETO bit detected.\n");
+ DEBUGOUT("MNG_VETO bit detected.");
return true;
}
u16 phy_id = 0;
bool valid = false;
- DEBUGFUNC("txgbe_validate_phy_addr");
-
hw->phy.addr = phy_addr;
hw->phy.read_reg(hw, TXGBE_MD_PHY_ID_HIGH,
TXGBE_MD_DEV_PMA_PMD, &phy_id);
if (phy_id != 0xFFFF && phy_id != 0x0)
valid = true;
- DEBUGOUT("PHY ID HIGH is 0x%04X\n", phy_id);
+ DEBUGOUT("PHY ID HIGH is 0x%04X", phy_id);
return valid;
}
u16 phy_id_high = 0;
u16 phy_id_low = 0;
- DEBUGFUNC("txgbe_get_phy_id");
-
err = hw->phy.read_reg(hw, TXGBE_MD_PHY_ID_HIGH,
TXGBE_MD_DEV_PMA_PMD,
&phy_id_high);
hw->phy.id |= (u32)(phy_id_low & TXGBE_PHY_REVISION_MASK);
hw->phy.revision = (u32)(phy_id_low & ~TXGBE_PHY_REVISION_MASK);
}
- DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X\n",
+ DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X",
phy_id_high, phy_id_low);
return err;
{
enum txgbe_phy_type phy_type;
- DEBUGFUNC("txgbe_get_phy_type_from_id");
-
switch (phy_id) {
case TXGBE_PHYID_TN1010:
phy_type = txgbe_phy_tn;
if (ctrl & TXGBE_MD_PORT_CTRL_RESET) {
err = TXGBE_ERR_RESET_FAILED;
- DEBUGOUT("PHY reset polling failed to complete.\n");
+ DEBUGOUT("PHY reset polling failed to complete.");
}
return err;
{
s32 err = 0;
- DEBUGFUNC("txgbe_reset_phy");
-
if (hw->phy.type == txgbe_phy_unknown)
err = txgbe_identify_phy(hw);
*/
if (!po32m(hw, TXGBE_MDIOSCD, TXGBE_MDIOSCD_BUSY,
0, NULL, 100, 100)) {
- DEBUGOUT("PHY address command did not complete\n");
+ DEBUGOUT("PHY address command did not complete");
return TXGBE_ERR_PHY;
}
s32 err;
u32 gssr = hw->phy.phy_semaphore_mask;
- DEBUGFUNC("txgbe_read_phy_reg");
-
if (hw->mac.acquire_swfw_sync(hw, gssr))
return TXGBE_ERR_SWFW_SYNC;
/* wait for completion */
if (!po32m(hw, TXGBE_MDIOSCD, TXGBE_MDIOSCD_BUSY,
0, NULL, 100, 100)) {
- TLOG_DEBUG("PHY write cmd didn't complete\n");
+ DEBUGOUT("PHY write cmd didn't complete");
return -TERR_PHY;
}
s32 err;
u32 gssr = hw->phy.phy_semaphore_mask;
- DEBUGFUNC("txgbe_write_phy_reg");
-
if (hw->mac.acquire_swfw_sync(hw, gssr))
err = TXGBE_ERR_SWFW_SYNC;
bool autoneg = false;
u32 speed;
- DEBUGFUNC("txgbe_setup_phy_link");
-
txgbe_get_copper_link_capabilities(hw, &speed, &autoneg);
/* Set or unset auto-negotiation 10G advertisement */
{
UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
- DEBUGFUNC("txgbe_setup_phy_link_speed");
-
/*
* Clear autoneg_advertised and set new values based on input link
* speed.
{
s32 err = 0;
- DEBUGFUNC("txgbe_get_copper_link_capabilities");
-
*autoneg = true;
if (!hw->phy.speeds_supported)
err = txgbe_get_copper_speeds_supported(hw);
u16 phy_speed = 0;
u16 phy_data = 0;
- DEBUGFUNC("txgbe_check_phy_link_tnx");
-
/* Initialize speed and link to default case */
*link_up = false;
*speed = TXGBE_LINK_SPEED_10GB_FULL;
bool autoneg = false;
u32 speed;
- DEBUGFUNC("txgbe_setup_phy_link_tnx");
-
txgbe_get_copper_link_capabilities(hw, &speed, &autoneg);
if (speed & TXGBE_LINK_SPEED_10GB_FULL) {
{
s32 err = TXGBE_ERR_SFP_NOT_PRESENT;
- DEBUGFUNC("txgbe_identify_module");
-
switch (hw->phy.media_type) {
case txgbe_media_type_fiber:
err = txgbe_identify_sfp_module(hw);
u8 cable_spec = 0;
u16 enforce_sfp = 0;
- DEBUGFUNC("txgbe_identify_sfp_module");
-
if (hw->phy.media_type != txgbe_media_type_fiber) {
hw->phy.sfp_type = txgbe_sfp_type_not_present;
return TXGBE_ERR_SFP_NOT_PRESENT;
hw->phy.sfp_type == txgbe_sfp_type_1g_lx_core1 ||
hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core0 ||
hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) {
- DEBUGOUT("SFP+ module not supported\n");
+ DEBUGOUT("SFP+ module not supported");
hw->phy.type = txgbe_phy_sfp_unsupported;
return TXGBE_ERR_SFP_NOT_SUPPORTED;
}
u8 device_tech = 0;
bool active_cable = false;
- DEBUGFUNC("txgbe_identify_qsfp_module");
-
if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) {
hw->phy.sfp_type = txgbe_sfp_type_not_present;
err = TXGBE_ERR_SFP_NOT_PRESENT;
if (hw->allow_unsupported_sfp) {
DEBUGOUT("WARNING: Wangxun (R) Network Connections are quality tested using Wangxun (R) Ethernet Optics. "
"Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. "
- "Wangxun Corporation is not responsible for any harm caused by using untested modules.\n");
+ "Wangxun Corporation is not responsible for any harm caused by using untested modules.");
err = 0;
} else {
- DEBUGOUT("QSFP module not supported\n");
+ DEBUGOUT("QSFP module not supported");
hw->phy.type =
txgbe_phy_sfp_unsupported;
err = TXGBE_ERR_SFP_NOT_SUPPORTED;
s32 txgbe_read_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset,
u8 *eeprom_data)
{
- DEBUGFUNC("txgbe_read_i2c_eeprom");
-
return hw->phy.read_i2c_byte(hw, byte_offset,
TXGBE_I2C_EEPROM_DEV_ADDR,
eeprom_data);
s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset,
u8 eeprom_data)
{
- DEBUGFUNC("txgbe_write_i2c_eeprom");
-
return hw->phy.write_i2c_byte(hw, byte_offset,
TXGBE_I2C_EEPROM_DEV_ADDR,
eeprom_data);
s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data)
{
- UNREFERENCED_PARAMETER(dev_addr);
-
- DEBUGFUNC("txgbe_read_i2c_byte");
-
- txgbe_i2c_start(hw);
+ txgbe_i2c_start(hw, dev_addr);
/* wait tx empty */
if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_TXEMPTY,
s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data)
{
- UNREFERENCED_PARAMETER(dev_addr);
-
- DEBUGFUNC("txgbe_write_i2c_byte");
-
- txgbe_i2c_start(hw);
+ txgbe_i2c_start(hw, dev_addr);
/* wait tx empty */
if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_TXEMPTY,
*
* Sets I2C start condition (High -> Low on SDA while SCL is High)
**/
-static void txgbe_i2c_start(struct txgbe_hw *hw)
+static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr)
{
- DEBUGFUNC("txgbe_i2c_start");
-
wr32(hw, TXGBE_I2CENA, 0);
wr32(hw, TXGBE_I2CCON,
TXGBE_I2CCON_SPEED(1) |
TXGBE_I2CCON_RESTART |
TXGBE_I2CCON_SDIA));
- wr32(hw, TXGBE_I2CTAR, TXGBE_I2C_SLAVEADDR);
- wr32(hw, TXGBE_I2CSSSCLHCNT, 600);
- wr32(hw, TXGBE_I2CSSSCLLCNT, 600);
+ wr32(hw, TXGBE_I2CTAR, dev_addr >> 1);
+ wr32(hw, TXGBE_I2CSSSCLHCNT, 200);
+ wr32(hw, TXGBE_I2CSSSCLLCNT, 200);
wr32(hw, TXGBE_I2CRXTL, 0); /* 1byte for rx full signal */
wr32(hw, TXGBE_I2CTXTL, 4);
wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF);
**/
static void txgbe_i2c_stop(struct txgbe_hw *hw)
{
- DEBUGFUNC("txgbe_i2c_stop");
-
/* wait for completion */
if (!po32m(hw, TXGBE_I2CSTAT, TXGBE_I2CSTAT_MST,
0, NULL, 100, 100)) {
- DEBUGFUNC("i2c stop timeout.");
+ DEBUGOUT("i2c stop timeout.");
}
wr32(hw, TXGBE_I2CENA, 0);
txgbe_set_sgmii_an37_ability(struct txgbe_hw *hw)
{
u32 value;
+ u8 device_type = hw->subsystem_device_id & 0xF0;
wr32_epcs(hw, VR_XS_OR_PCS_MMD_DIGI_CTL1, 0x3002);
- wr32_epcs(hw, SR_MII_MMD_AN_CTL, 0x0105);
+ /* for sgmii + external phy, set to 0x0105 (phy sgmii mode) */
+ /* for sgmii direct link, set to 0x010c (mac sgmii mode) */
+ if (device_type == TXGBE_DEV_ID_MAC_SGMII ||
+ hw->phy.media_type == txgbe_media_type_fiber)
+ wr32_epcs(hw, SR_MII_MMD_AN_CTL, 0x010C);
+ else if (device_type == TXGBE_DEV_ID_SGMII ||
+ device_type == TXGBE_DEV_ID_XAUI)
+ wr32_epcs(hw, SR_MII_MMD_AN_CTL, 0x0105);
wr32_epcs(hw, SR_MII_MMD_DIGI_CTL, 0x0200);
value = rd32_epcs(hw, SR_MII_MMD_CTL);
value = (value & ~0x1200) | (0x1 << 12) | (0x1 << 9);
if (!(hw->devarg.auto_neg == 1)) {
wr32_epcs(hw, SR_AN_CTRL, 0);
wr32_epcs(hw, VR_AN_KR_MODE_CL, 0);
+ } else {
+ value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1);
+ value &= ~(1 << 6);
+ wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
}
- if (hw->devarg.present == 1) {
+ if (hw->devarg.present == 1) {
value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1);
value |= TXGBE_PHY_TX_EQ_CTL1_DEF;
wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
} 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;
}
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);
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);
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);
}
} else if (hw->phy.media_type == txgbe_media_type_fiber) {
txgbe_set_link_to_sfi(hw, speed);
+ if (speed == TXGBE_LINK_SPEED_1GB_FULL)
+ txgbe_set_sgmii_an37_ability(hw);
}
if (speed == TXGBE_LINK_SPEED_10GB_FULL)
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
u32 value;
s32 status = 0;
- DEBUGFUNC("txgbe_kr_handle");
-
value = rd32_epcs(hw, VR_AN_INTR);
BP_LOG("AN INTERRUPT!! value: 0x%x\n", value);
if (!(value & VR_AN_INTR_PG_RCV)) {
s32 status = 0;
struct txgbe_backplane_ability local_ability, lp_ability;
- DEBUGFUNC("txgbe_handle_bp_flow");
-
local_ability.current_link_mode = link_mode;
/* 1. Get the local AN73 Base Page Ability */
{
u32 value = 0;
- DEBUGFUNC("txgbe_get_bp_ability");
-
/* Link Partner Base Page */
if (link_partner == 1) {
/* Read the link partner AN73 Base Page Ability Registers */
u32 com_link_abi;
s32 ret = 0;
- DEBUGFUNC("txgbe_check_bp_ability");
-
com_link_abi = local_ability->link_ability & lp_ability->link_ability;
BP_LOG("com_link_abi = 0x%x, local_ability = 0x%x, lp_ability = 0x%x\n",
com_link_abi, local_ability->link_ability,
{
u32 rdata = 0, wdata, i;
- DEBUGFUNC("txgbe_clear_bp_intr");
-
rdata = rd32_epcs(hw, VR_AN_INTR);
BP_LOG("[Before clear]Read VR AN MMD Interrupt Register: 0x%x\n",
rdata);
s32 status = 0;
u32 value = 0;
- DEBUGFUNC("txgbe_enable_kr_training");
-
BP_LOG("Enable Clause 72 KR Training ...\n");
if (CL72_KRTR_PRBS_MODE_EN != 0xFFFF) {
{
s32 status = 0;
- DEBUGFUNC("txgbe_disable_kr_training");
-
BP_LOG("Disable Clause 72 KR Training ...\n");
/* Read PHY Lane0 TX EQ before Clause 72 KR Training. */
txgbe_read_phy_lane_tx_eq(0, hw, post, mode);
int i;
int times = hw->devarg.poll ? 35 : 20;
- DEBUGFUNC("txgbe_check_kr_training");
-
for (i = 0; i < times; i++) {
value = rd32_epcs(hw, SR_PMA_KR_LP_CEU);
BP_LOG("SR PMA MMD 10GBASE-KR LP Coefficient Update Register: 0x%x\n",
u32 addr;
u32 tx_main_cursor, tx_pre_cursor, tx_post_cursor, lmain;
- DEBUGFUNC("txgbe_read_phy_lane_tx_eq");
-
addr = TXGBE_PHY_LANE0_TX_EQ_CTL1 | (lane << 8);
value = rd32_ephy(hw, addr);
BP_LOG("PHY LANE TX EQ Read Value: %x\n", lane);