ixgbe/base: add X550em LPLU support
This patch adds SW Low Power Link Up (LPLU) support for x550em PHY. Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com> Acked-by: Helin Zhang <helin.zhang@intel.com>
This commit is contained in:
parent
f3430431ab
commit
64b91e05b1
@ -1267,6 +1267,19 @@ void ixgbe_restore_mdd_vf(struct ixgbe_hw *hw, u32 vf)
|
||||
hw->mac.ops.restore_mdd_vf(hw, vf);
|
||||
}
|
||||
|
||||
/**
|
||||
* ixgbe_enter_lplu - Transition to low power states
|
||||
* @hw: pointer to hardware structure
|
||||
*
|
||||
* Configures Low Power Link Up on transition to low power states
|
||||
* (from D0 to non-D0).
|
||||
**/
|
||||
s32 ixgbe_enter_lplu(struct ixgbe_hw *hw)
|
||||
{
|
||||
return ixgbe_call_func(hw, hw->phy.ops.enter_lplu, (hw),
|
||||
IXGBE_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* ixgbe_read_analog_reg8 - Reads 8 bit analog register
|
||||
* @hw: pointer to hardware structure
|
||||
|
@ -210,6 +210,7 @@ void ixgbe_disable_mdd(struct ixgbe_hw *hw);
|
||||
void ixgbe_enable_mdd(struct ixgbe_hw *hw);
|
||||
void ixgbe_mdd_event(struct ixgbe_hw *hw, u32 *vf_bitmap);
|
||||
void ixgbe_restore_mdd_vf(struct ixgbe_hw *hw, u32 vf);
|
||||
s32 ixgbe_enter_lplu(struct ixgbe_hw *hw);
|
||||
void ixgbe_set_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed);
|
||||
void ixgbe_disable_rx(struct ixgbe_hw *hw);
|
||||
void ixgbe_enable_rx(struct ixgbe_hw *hw);
|
||||
|
@ -1377,6 +1377,7 @@ struct ixgbe_dmac_config {
|
||||
#define IXGBE_MDIO_AUTO_NEG_CONTROL 0x0 /* AUTO_NEG Control Reg */
|
||||
#define IXGBE_MDIO_AUTO_NEG_STATUS 0x1 /* AUTO_NEG Status Reg */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STAT 0xC800 /* AUTO_NEG Vendor Status Reg */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM 0xCC00 /* AUTO_NEG Vendor TX Reg */
|
||||
#define IXGBE_MDIO_AUTO_NEG_ADVT 0x10 /* AUTO_NEG Advt Reg */
|
||||
#define IXGBE_MDIO_AUTO_NEG_LP 0x13 /* AUTO_NEG LP Status Reg */
|
||||
#define IXGBE_MDIO_AUTO_NEG_EEE_ADVT 0x3C /* AUTO_NEG EEE Advt Reg */
|
||||
@ -1396,6 +1397,10 @@ struct ixgbe_dmac_config {
|
||||
#define IXGBE_MDIO_PHY_1000BASET_ABILITY 0x0020 /* 1000BaseT capable */
|
||||
#define IXGBE_MDIO_PHY_100BASETX_ABILITY 0x0080 /* 100BaseTX capable */
|
||||
#define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE 0x0800 /* Set low power mode */
|
||||
#define IXGBE_AUTO_NEG_LP_STATUS 0xE820 /* AUTO NEG Rx LP Status Reg */
|
||||
#define IXGBE_AUTO_NEG_LP_1000BASE_CAP 0x8000 /* AUTO NEG Rx LP 1000BaseT Cap */
|
||||
#define IXGBE_AUTO_NEG_LP_10GBASE_CAP 0x0800 /* AUTO NEG Rx LP 10GBaseT Cap */
|
||||
#define IXGBE_AUTO_NEG_10GBASET_STAT 0x0021 /* AUTO NEG 10G BaseT Stat */
|
||||
|
||||
#define IXGBE_MDIO_TX_VENDOR_ALARMS_3 0xCC02 /* Vendor Alarms 3 Reg */
|
||||
#define IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK 0x3 /* PHY Reset Complete Mask */
|
||||
@ -1423,7 +1428,8 @@ struct ixgbe_dmac_config {
|
||||
|
||||
#define IXGBE_MDIO_AUTO_NEG_LINK_STATUS 0x4 /* Indicates if link is up */
|
||||
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK 0x7 /* Speed/Duplex Mask */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK 0x7 /* Speed/Duplex Mask */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK 0x6 /* Speed Mask */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10M_HALF 0x0 /* 10Mb/s Half Duplex */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10M_FULL 0x1 /* 10Mb/s Full Duplex */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_100M_HALF 0x2 /* 100Mb/s Half Duplex */
|
||||
@ -1432,6 +1438,8 @@ struct ixgbe_dmac_config {
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL 0x5 /* 1Gb/s Full Duplex */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_HALF 0x6 /* 10Gb/s Half Duplex */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL 0x7 /* 10Gb/s Full Duplex */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB 0x4 /* 1Gb/s */
|
||||
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB 0x6 /* 10Gb/s */
|
||||
|
||||
#define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG 0x20 /* 10G Control Reg */
|
||||
#define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */
|
||||
@ -2165,6 +2173,11 @@ enum {
|
||||
#define IXGBE_NVM_POLL_WRITE 1 /* Flag for polling for wr complete */
|
||||
#define IXGBE_NVM_POLL_READ 0 /* Flag for polling for rd complete */
|
||||
|
||||
#define NVM_INIT_CTRL_3 0x38
|
||||
#define NVM_INIT_CTRL_3_LPLU 0x8
|
||||
#define NVM_INIT_CTRL_3_D10GMP_PORT0 0x40
|
||||
#define NVM_INIT_CTRL_3_D10GMP_PORT1 0x100
|
||||
|
||||
#define IXGBE_ETH_LENGTH_OF_ADDRESS 6
|
||||
|
||||
#define IXGBE_EEPROM_PAGE_SIZE_MAX 128
|
||||
@ -3627,6 +3640,7 @@ struct ixgbe_phy_operations {
|
||||
s32 (*write_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val);
|
||||
s32 (*check_overtemp)(struct ixgbe_hw *);
|
||||
s32 (*set_phy_power)(struct ixgbe_hw *, bool on);
|
||||
s32 (*enter_lplu)(struct ixgbe_hw *);
|
||||
s32 (*read_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
|
||||
u16 *value);
|
||||
s32 (*write_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
|
||||
@ -3644,6 +3658,7 @@ struct ixgbe_eeprom_info {
|
||||
u16 word_size;
|
||||
u16 address_bits;
|
||||
u16 word_page_size;
|
||||
u16 ctrl_word_3;
|
||||
};
|
||||
|
||||
#define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED 0x01
|
||||
|
@ -1143,6 +1143,7 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
|
||||
break;
|
||||
case ixgbe_phy_x550em_ext_t:
|
||||
phy->ops.setup_internal_link = ixgbe_setup_internal_phy_x550em;
|
||||
phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -2334,3 +2335,175 @@ void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ixgbe_enter_lplu_x550em - Transition to low power states
|
||||
* @hw: pointer to hardware structure
|
||||
*
|
||||
* Configures Low Power Link Up on transition to low power states
|
||||
* (from D0 to non-D0). Link is required to enter LPLU so avoid resetting the
|
||||
* X557 PHY immediately prior to entering LPLU.
|
||||
**/
|
||||
s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
|
||||
{
|
||||
u16 autoneg_status, an_10g_cntl_reg, autoneg_reg, speed;
|
||||
s32 status;
|
||||
ixgbe_link_speed lcd_speed;
|
||||
|
||||
/* If blocked by MNG FW, then don't restart AN */
|
||||
if (ixgbe_check_reset_blocked(hw))
|
||||
return IXGBE_SUCCESS;
|
||||
|
||||
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
|
||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
|
||||
&autoneg_status);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = ixgbe_read_eeprom(hw, NVM_INIT_CTRL_3, &hw->eeprom.ctrl_word_3);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* If link is down, LPLU disabled in NVM, WoL disabled, or manageability
|
||||
* disabled, then force link down by entering low power mode.
|
||||
*/
|
||||
if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS) ||
|
||||
!(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
|
||||
!(hw->wol_enabled || ixgbe_mng_present(hw)))
|
||||
return ixgbe_set_copper_phy_power(hw, FALSE);
|
||||
|
||||
/* Determine LCD */
|
||||
status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* If no valid LCD link speed, then force link down and exit. */
|
||||
if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN)
|
||||
return ixgbe_set_copper_phy_power(hw, FALSE);
|
||||
|
||||
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
|
||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
|
||||
&speed);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* clear everything but the speed bits */
|
||||
speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK;
|
||||
|
||||
/* If current speed is already LCD, then exit. */
|
||||
if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) &&
|
||||
(lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) ||
|
||||
((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) &&
|
||||
(lcd_speed == IXGBE_LINK_SPEED_10GB_FULL)))
|
||||
return status;
|
||||
|
||||
/* Clear AN completed indication */
|
||||
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
|
||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
|
||||
&autoneg_status);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
|
||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
|
||||
&an_10g_cntl_reg);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = hw->phy.ops.read_reg(hw,
|
||||
IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
|
||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
|
||||
&autoneg_reg);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* Set AN advertizement to only include LCD */
|
||||
if (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL) {
|
||||
an_10g_cntl_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE;
|
||||
autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE;
|
||||
}
|
||||
|
||||
if (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL) {
|
||||
an_10g_cntl_reg |= IXGBE_MII_10GBASE_T_ADVERTISE;
|
||||
autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE;
|
||||
}
|
||||
|
||||
status = hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
|
||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
|
||||
an_10g_cntl_reg);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = hw->phy.ops.write_reg(hw,
|
||||
IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
|
||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
|
||||
autoneg_reg);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* Restart PHY auto-negotiation. */
|
||||
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
|
||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
autoneg_reg |= IXGBE_MII_RESTART;
|
||||
|
||||
status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
|
||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = ixgbe_setup_ixfi_x550em(hw, &lcd_speed);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ixgbe_get_lcd_x550em - Determine lowest common denominator
|
||||
* @hw: pointer to hardware structure
|
||||
* @lcd_speed: pointer to lowest common link speed
|
||||
*
|
||||
* Determine lowest common link speed with link partner.
|
||||
**/
|
||||
s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed)
|
||||
{
|
||||
u16 an_lp_status;
|
||||
s32 status;
|
||||
u16 word = hw->eeprom.ctrl_word_3;
|
||||
|
||||
*lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
|
||||
|
||||
status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
|
||||
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
|
||||
&an_lp_status);
|
||||
|
||||
if (status != IXGBE_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* If link partner advertised 1G, return 1G */
|
||||
if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) {
|
||||
*lcd_speed = IXGBE_LINK_SPEED_1GB_FULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */
|
||||
if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) ||
|
||||
(word & NVM_INIT_CTRL_3_D10GMP_PORT0))
|
||||
return status;
|
||||
|
||||
/* Link partner not capable of lower speeds, return 10G */
|
||||
*lcd_speed = IXGBE_LINK_SPEED_10GB_FULL;
|
||||
return status;
|
||||
}
|
||||
|
@ -87,6 +87,8 @@ s32 ixgbe_setup_internal_phy_x550em(struct ixgbe_hw *hw);
|
||||
s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw);
|
||||
u32 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw);
|
||||
void ixgbe_disable_rx_x550(struct ixgbe_hw *hw);
|
||||
s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed);
|
||||
s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw);
|
||||
s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
|
||||
ixgbe_link_speed speed,
|
||||
bool autoneg_wait_to_complete);
|
||||
|
Loading…
x
Reference in New Issue
Block a user