net/ixgbe/base: add link MAC setup for X550a SFP+

This patch updates ixgbe_setup_mac_link_sfp_x550a for X550 SFP+.
ixgbe_set_lan_id_multi_port_pcie has been updated to set the MAC
instance(0/1) which is needed when configuring the external PHY,
since X550a has two instances of MGPK. The MAC instance is read
from the EEPROM.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
This commit is contained in:
Beilei Xing 2016-06-23 15:22:17 +08:00 committed by Bruce Richardson
parent eb540e47c6
commit fc0559bdb5
4 changed files with 89 additions and 26 deletions

View File

@ -1020,13 +1020,15 @@ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
* ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
* @hw: pointer to the HW structure
*
* Determines the LAN function id by reading memory-mapped registers
* and swaps the port value if requested.
* Determines the LAN function id by reading memory-mapped registers and swaps
* the port value if requested, and set MAC instance for devices that share
* CS4227.
**/
void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
{
struct ixgbe_bus_info *bus = &hw->bus;
u32 reg;
u16 ee_ctrl_4;
DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie");
@ -1038,6 +1040,13 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
if (reg & IXGBE_FACTPS_LFS)
bus->func ^= 0x1;
/* Get MAC instance from EEPROM for configuring CS4227 */
if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) {
hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4);
bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >>
IXGBE_EE_CTRL_4_INST_ID_SHIFT;
}
}
/**

View File

@ -89,8 +89,11 @@ POSSIBILITY OF SUCH DAMAGE.
#define IXGBE_CS4227 0xBE /* CS4227 address */
#define IXGBE_CS4227_GLOBAL_ID_LSB 0
#define IXGBE_CS4227_GLOBAL_ID_MSB 1
#define IXGBE_CS4227_SCRATCH 2
#define IXGBE_CS4227_GLOBAL_ID_VALUE 0x03E5
#define IXGBE_CS4223_PHY_ID 0x7003/* Quad port */
#define IXGBE_CS4227_PHY_ID 0x3003/* Dual port */
#define IXGBE_CS4227_RESET_PENDING 0x1357
#define IXGBE_CS4227_RESET_COMPLETE 0x5AA5
#define IXGBE_CS4227_RETRIES 15

View File

@ -1472,6 +1472,7 @@ struct ixgbe_dmac_config {
#define IXGBE_CORECTL_WRITE_CMD 0x00010000
/* Device Type definitions for new protocol MDIO commands */
#define IXGBE_MDIO_ZERO_DEV_TYPE 0x0
#define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1
#define IXGBE_MDIO_PCS_DEV_TYPE 0x3
#define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4
@ -2247,6 +2248,9 @@ enum {
#define IXGBE_PBANUM_PTR_GUARD 0xFAFA
#define IXGBE_EEPROM_CHECKSUM 0x3F
#define IXGBE_EEPROM_SUM 0xBABA
#define IXGBE_EEPROM_CTRL_4 0x45
#define IXGBE_EE_CTRL_4_INST_ID 0x10
#define IXGBE_EE_CTRL_4_INST_ID_SHIFT 4
#define IXGBE_PCIE_ANALOG_PTR 0x03
#define IXGBE_ATLAS0_CONFIG_PTR 0x04
#define IXGBE_PHY_PTR 0x04
@ -3630,6 +3634,7 @@ struct ixgbe_bus_info {
u16 func;
u16 lan_id;
u16 instance_id;
};
/* Flow control parameters */
@ -4130,5 +4135,8 @@ struct ixgbe_hw {
#define IXGBE_NW_MNG_IF_SEL 0x00011178
#define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE (1 << 24)
#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT 3
#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD \
(0x1F << IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT)
#endif /* _IXGBE_TYPE_H_ */

View File

@ -1551,7 +1551,8 @@ void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
mac->ops.set_rate_select_speed =
ixgbe_set_soft_rate_select_speed;
if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N)
if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) ||
(hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP))
mac->ops.setup_mac_link =
ixgbe_setup_mac_link_sfp_x550a;
else
@ -2207,8 +2208,9 @@ s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
bool autoneg_wait_to_complete)
{
s32 ret_val;
u32 reg_val;
u16 reg_phy_ext;
bool setup_linear = false;
u32 reg_slice, reg_phy_int, slice_offset;
UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
@ -2224,32 +2226,73 @@ s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
if (ret_val != IXGBE_SUCCESS)
return ret_val;
if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) {
/* Configure internal PHY for native SFI */
ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
if (ret_val != IXGBE_SUCCESS)
return ret_val;
if (setup_linear) {
reg_val &= ~IXGBE_KRM_AN_CNTL_8_LIMITING;
reg_val |= IXGBE_KRM_AN_CNTL_8_LINEAR;
reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING;
reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR;
} else {
reg_val |= IXGBE_KRM_AN_CNTL_8_LIMITING;
reg_val &= ~IXGBE_KRM_AN_CNTL_8_LINEAR;
reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING;
reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR;
}
ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
if (ret_val != IXGBE_SUCCESS)
return ret_val;
/* Setup XFI/SFI internal link. */
ret_val = ixgbe_setup_ixfi_x550em(hw, &speed);
} else {
/* Configure internal PHY for KR/KX. */
ixgbe_setup_kr_speed_x550em(hw, speed);
/* Get CS4227 MDIO address */
hw->phy.addr =
(hw->phy.nw_mng_if_sel &
IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD)
>> IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
if (hw->phy.addr == 0x0 || hw->phy.addr == 0xFFFF) {
/* Find Address */
DEBUGOUT("Invalid NW_MNG_IF_SEL.MDIO_PHY_ADD value\n");
return IXGBE_ERR_PHY_ADDR_INVALID;
}
/* Get external PHY device id */
ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB,
IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
if (ret_val != IXGBE_SUCCESS)
return ret_val;
/* When configuring quad port CS4223, the MAC instance is part
* of the slice offset.
*/
if (reg_phy_ext == IXGBE_CS4223_PHY_ID)
slice_offset = (hw->bus.lan_id +
(hw->bus.instance_id << 1)) << 12;
else
slice_offset = hw->bus.lan_id << 12;
/* Configure CS4227/CS4223 LINE side to proper mode. */
reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
if (setup_linear)
reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
else
reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
ret_val = hw->phy.ops.write_reg(hw, reg_slice,
IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
}
return ret_val;
}