162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "ixgbe_x540.h" 562306a36Sopenharmony_ci#include "ixgbe_type.h" 662306a36Sopenharmony_ci#include "ixgbe_common.h" 762306a36Sopenharmony_ci#include "ixgbe_phy.h" 862306a36Sopenharmony_ci 962306a36Sopenharmony_cistatic s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed); 1062306a36Sopenharmony_cistatic s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *); 1162306a36Sopenharmony_cistatic void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *); 1262306a36Sopenharmony_cistatic void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *); 1362306a36Sopenharmony_cistatic s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *); 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 1862306a36Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 1962306a36Sopenharmony_ci struct ixgbe_link_info *link = &hw->link; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci /* Start with X540 invariants, since so simular */ 2262306a36Sopenharmony_ci ixgbe_get_invariants_X540(hw); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 2562306a36Sopenharmony_ci phy->ops.set_phy_power = NULL; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci link->addr = IXGBE_CS4227; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci return 0; 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_x_fw(struct ixgbe_hw *hw) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci /* Start with X540 invariants, since so similar */ 3762306a36Sopenharmony_ci ixgbe_get_invariants_X540(hw); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci phy->ops.set_phy_power = NULL; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci return 0; 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 4762306a36Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci /* Start with X540 invariants, since so simular */ 5062306a36Sopenharmony_ci ixgbe_get_invariants_X540(hw); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 5362306a36Sopenharmony_ci phy->ops.set_phy_power = NULL; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci return 0; 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_a_fw(struct ixgbe_hw *hw) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci /* Start with X540 invariants, since so similar */ 6362306a36Sopenharmony_ci ixgbe_get_invariants_X540(hw); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci phy->ops.set_phy_power = NULL; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci return 0; 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control 7162306a36Sopenharmony_ci * @hw: pointer to hardware structure 7262306a36Sopenharmony_ci **/ 7362306a36Sopenharmony_cistatic void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci if (hw->bus.lan_id) { 7862306a36Sopenharmony_ci esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 7962306a36Sopenharmony_ci esdp |= IXGBE_ESDP_SDP1_DIR; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 8262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 8362306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/** 8762306a36Sopenharmony_ci * ixgbe_read_cs4227 - Read CS4227 register 8862306a36Sopenharmony_ci * @hw: pointer to hardware structure 8962306a36Sopenharmony_ci * @reg: register number to write 9062306a36Sopenharmony_ci * @value: pointer to receive value read 9162306a36Sopenharmony_ci * 9262306a36Sopenharmony_ci * Returns status code 9362306a36Sopenharmony_ci */ 9462306a36Sopenharmony_cistatic s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/** 10062306a36Sopenharmony_ci * ixgbe_write_cs4227 - Write CS4227 register 10162306a36Sopenharmony_ci * @hw: pointer to hardware structure 10262306a36Sopenharmony_ci * @reg: register number to write 10362306a36Sopenharmony_ci * @value: value to write to register 10462306a36Sopenharmony_ci * 10562306a36Sopenharmony_ci * Returns status code 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_cistatic s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci/** 11362306a36Sopenharmony_ci * ixgbe_read_pe - Read register from port expander 11462306a36Sopenharmony_ci * @hw: pointer to hardware structure 11562306a36Sopenharmony_ci * @reg: register number to read 11662306a36Sopenharmony_ci * @value: pointer to receive read value 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci * Returns status code 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_cistatic s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci s32 status; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, value); 12562306a36Sopenharmony_ci if (status) 12662306a36Sopenharmony_ci hw_err(hw, "port expander access failed with %d\n", status); 12762306a36Sopenharmony_ci return status; 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/** 13162306a36Sopenharmony_ci * ixgbe_write_pe - Write register to port expander 13262306a36Sopenharmony_ci * @hw: pointer to hardware structure 13362306a36Sopenharmony_ci * @reg: register number to write 13462306a36Sopenharmony_ci * @value: value to write 13562306a36Sopenharmony_ci * 13662306a36Sopenharmony_ci * Returns status code 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_cistatic s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci s32 status; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, 14362306a36Sopenharmony_ci value); 14462306a36Sopenharmony_ci if (status) 14562306a36Sopenharmony_ci hw_err(hw, "port expander access failed with %d\n", status); 14662306a36Sopenharmony_ci return status; 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/** 15062306a36Sopenharmony_ci * ixgbe_reset_cs4227 - Reset CS4227 using port expander 15162306a36Sopenharmony_ci * @hw: pointer to hardware structure 15262306a36Sopenharmony_ci * 15362306a36Sopenharmony_ci * This function assumes that the caller has acquired the proper semaphore. 15462306a36Sopenharmony_ci * Returns error code 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_cistatic s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci s32 status; 15962306a36Sopenharmony_ci u32 retry; 16062306a36Sopenharmony_ci u16 value; 16162306a36Sopenharmony_ci u8 reg; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci /* Trigger hard reset. */ 16462306a36Sopenharmony_ci status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 16562306a36Sopenharmony_ci if (status) 16662306a36Sopenharmony_ci return status; 16762306a36Sopenharmony_ci reg |= IXGBE_PE_BIT1; 16862306a36Sopenharmony_ci status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 16962306a36Sopenharmony_ci if (status) 17062306a36Sopenharmony_ci return status; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); 17362306a36Sopenharmony_ci if (status) 17462306a36Sopenharmony_ci return status; 17562306a36Sopenharmony_ci reg &= ~IXGBE_PE_BIT1; 17662306a36Sopenharmony_ci status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); 17762306a36Sopenharmony_ci if (status) 17862306a36Sopenharmony_ci return status; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 18162306a36Sopenharmony_ci if (status) 18262306a36Sopenharmony_ci return status; 18362306a36Sopenharmony_ci reg &= ~IXGBE_PE_BIT1; 18462306a36Sopenharmony_ci status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 18562306a36Sopenharmony_ci if (status) 18662306a36Sopenharmony_ci return status; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 19162306a36Sopenharmony_ci if (status) 19262306a36Sopenharmony_ci return status; 19362306a36Sopenharmony_ci reg |= IXGBE_PE_BIT1; 19462306a36Sopenharmony_ci status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 19562306a36Sopenharmony_ci if (status) 19662306a36Sopenharmony_ci return status; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci /* Wait for the reset to complete. */ 19962306a36Sopenharmony_ci msleep(IXGBE_CS4227_RESET_DELAY); 20062306a36Sopenharmony_ci for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 20162306a36Sopenharmony_ci status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, 20262306a36Sopenharmony_ci &value); 20362306a36Sopenharmony_ci if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK) 20462306a36Sopenharmony_ci break; 20562306a36Sopenharmony_ci msleep(IXGBE_CS4227_CHECK_DELAY); 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci if (retry == IXGBE_CS4227_RETRIES) { 20862306a36Sopenharmony_ci hw_err(hw, "CS4227 reset did not complete\n"); 20962306a36Sopenharmony_ci return -EIO; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value); 21362306a36Sopenharmony_ci if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { 21462306a36Sopenharmony_ci hw_err(hw, "CS4227 EEPROM did not load successfully\n"); 21562306a36Sopenharmony_ci return -EIO; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci return 0; 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci/** 22262306a36Sopenharmony_ci * ixgbe_check_cs4227 - Check CS4227 and reset as needed 22362306a36Sopenharmony_ci * @hw: pointer to hardware structure 22462306a36Sopenharmony_ci */ 22562306a36Sopenharmony_cistatic void ixgbe_check_cs4227(struct ixgbe_hw *hw) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci u32 swfw_mask = hw->phy.phy_semaphore_mask; 22862306a36Sopenharmony_ci s32 status; 22962306a36Sopenharmony_ci u16 value; 23062306a36Sopenharmony_ci u8 retry; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 23362306a36Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 23462306a36Sopenharmony_ci if (status) { 23562306a36Sopenharmony_ci hw_err(hw, "semaphore failed with %d\n", status); 23662306a36Sopenharmony_ci msleep(IXGBE_CS4227_CHECK_DELAY); 23762306a36Sopenharmony_ci continue; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci /* Get status of reset flow. */ 24162306a36Sopenharmony_ci status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); 24262306a36Sopenharmony_ci if (!status && value == IXGBE_CS4227_RESET_COMPLETE) 24362306a36Sopenharmony_ci goto out; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci if (status || value != IXGBE_CS4227_RESET_PENDING) 24662306a36Sopenharmony_ci break; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci /* Reset is pending. Wait and check again. */ 24962306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 25062306a36Sopenharmony_ci msleep(IXGBE_CS4227_CHECK_DELAY); 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci /* If still pending, assume other instance failed. */ 25362306a36Sopenharmony_ci if (retry == IXGBE_CS4227_RETRIES) { 25462306a36Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 25562306a36Sopenharmony_ci if (status) { 25662306a36Sopenharmony_ci hw_err(hw, "semaphore failed with %d\n", status); 25762306a36Sopenharmony_ci return; 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci /* Reset the CS4227. */ 26262306a36Sopenharmony_ci status = ixgbe_reset_cs4227(hw); 26362306a36Sopenharmony_ci if (status) { 26462306a36Sopenharmony_ci hw_err(hw, "CS4227 reset failed: %d", status); 26562306a36Sopenharmony_ci goto out; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* Reset takes so long, temporarily release semaphore in case the 26962306a36Sopenharmony_ci * other driver instance is waiting for the reset indication. 27062306a36Sopenharmony_ci */ 27162306a36Sopenharmony_ci ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 27262306a36Sopenharmony_ci IXGBE_CS4227_RESET_PENDING); 27362306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 27462306a36Sopenharmony_ci usleep_range(10000, 12000); 27562306a36Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 27662306a36Sopenharmony_ci if (status) { 27762306a36Sopenharmony_ci hw_err(hw, "semaphore failed with %d", status); 27862306a36Sopenharmony_ci return; 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* Record completion for next time. */ 28262306a36Sopenharmony_ci status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 28362306a36Sopenharmony_ci IXGBE_CS4227_RESET_COMPLETE); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ciout: 28662306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 28762306a36Sopenharmony_ci msleep(hw->eeprom.semaphore_delay); 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci/** ixgbe_identify_phy_x550em - Get PHY type based on device id 29162306a36Sopenharmony_ci * @hw: pointer to hardware structure 29262306a36Sopenharmony_ci * 29362306a36Sopenharmony_ci * Returns error code 29462306a36Sopenharmony_ci */ 29562306a36Sopenharmony_cistatic s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci switch (hw->device_id) { 29862306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP: 29962306a36Sopenharmony_ci if (hw->bus.lan_id) 30062306a36Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 30162306a36Sopenharmony_ci else 30262306a36Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 30362306a36Sopenharmony_ci return ixgbe_identify_module_generic(hw); 30462306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_SFP: 30562306a36Sopenharmony_ci /* set up for CS4227 usage */ 30662306a36Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 30762306a36Sopenharmony_ci ixgbe_setup_mux_ctl(hw); 30862306a36Sopenharmony_ci ixgbe_check_cs4227(hw); 30962306a36Sopenharmony_ci fallthrough; 31062306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP_N: 31162306a36Sopenharmony_ci return ixgbe_identify_module_generic(hw); 31262306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KX4: 31362306a36Sopenharmony_ci hw->phy.type = ixgbe_phy_x550em_kx4; 31462306a36Sopenharmony_ci break; 31562306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_XFI: 31662306a36Sopenharmony_ci hw->phy.type = ixgbe_phy_x550em_xfi; 31762306a36Sopenharmony_ci break; 31862306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KR: 31962306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR: 32062306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR_L: 32162306a36Sopenharmony_ci hw->phy.type = ixgbe_phy_x550em_kr; 32262306a36Sopenharmony_ci break; 32362306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_10G_T: 32462306a36Sopenharmony_ci if (hw->bus.lan_id) 32562306a36Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 32662306a36Sopenharmony_ci else 32762306a36Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 32862306a36Sopenharmony_ci fallthrough; 32962306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_10G_T: 33062306a36Sopenharmony_ci return ixgbe_identify_phy_generic(hw); 33162306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_1G_T: 33262306a36Sopenharmony_ci hw->phy.type = ixgbe_phy_ext_1g_t; 33362306a36Sopenharmony_ci break; 33462306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T: 33562306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T_L: 33662306a36Sopenharmony_ci hw->phy.type = ixgbe_phy_fw; 33762306a36Sopenharmony_ci hw->phy.ops.read_reg = NULL; 33862306a36Sopenharmony_ci hw->phy.ops.write_reg = NULL; 33962306a36Sopenharmony_ci if (hw->bus.lan_id) 34062306a36Sopenharmony_ci hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; 34162306a36Sopenharmony_ci else 34262306a36Sopenharmony_ci hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM; 34362306a36Sopenharmony_ci break; 34462306a36Sopenharmony_ci default: 34562306a36Sopenharmony_ci break; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci return 0; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 35162306a36Sopenharmony_ci u32 device_type, u16 *phy_data) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci return -EOPNOTSUPP; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 35762306a36Sopenharmony_ci u32 device_type, u16 phy_data) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci return -EOPNOTSUPP; 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci/** 36362306a36Sopenharmony_ci * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation 36462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 36562306a36Sopenharmony_ci * @addr: I2C bus address to read from 36662306a36Sopenharmony_ci * @reg: I2C device register to read from 36762306a36Sopenharmony_ci * @val: pointer to location to receive read value 36862306a36Sopenharmony_ci * 36962306a36Sopenharmony_ci * Returns an error code on error. 37062306a36Sopenharmony_ci **/ 37162306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, 37262306a36Sopenharmony_ci u16 reg, u16 *val) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci/** 37862306a36Sopenharmony_ci * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation 37962306a36Sopenharmony_ci * @hw: pointer to the hardware structure 38062306a36Sopenharmony_ci * @addr: I2C bus address to read from 38162306a36Sopenharmony_ci * @reg: I2C device register to read from 38262306a36Sopenharmony_ci * @val: pointer to location to receive read value 38362306a36Sopenharmony_ci * 38462306a36Sopenharmony_ci * Returns an error code on error. 38562306a36Sopenharmony_ci **/ 38662306a36Sopenharmony_cistatic s32 38762306a36Sopenharmony_ciixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, 38862306a36Sopenharmony_ci u16 reg, u16 *val) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci/** 39462306a36Sopenharmony_ci * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation 39562306a36Sopenharmony_ci * @hw: pointer to the hardware structure 39662306a36Sopenharmony_ci * @addr: I2C bus address to write to 39762306a36Sopenharmony_ci * @reg: I2C device register to write to 39862306a36Sopenharmony_ci * @val: value to write 39962306a36Sopenharmony_ci * 40062306a36Sopenharmony_ci * Returns an error code on error. 40162306a36Sopenharmony_ci **/ 40262306a36Sopenharmony_cistatic s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, 40362306a36Sopenharmony_ci u8 addr, u16 reg, u16 val) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); 40662306a36Sopenharmony_ci} 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci/** 40962306a36Sopenharmony_ci * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation 41062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 41162306a36Sopenharmony_ci * @addr: I2C bus address to write to 41262306a36Sopenharmony_ci * @reg: I2C device register to write to 41362306a36Sopenharmony_ci * @val: value to write 41462306a36Sopenharmony_ci * 41562306a36Sopenharmony_ci * Returns an error code on error. 41662306a36Sopenharmony_ci **/ 41762306a36Sopenharmony_cistatic s32 41862306a36Sopenharmony_ciixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, 41962306a36Sopenharmony_ci u8 addr, u16 reg, u16 val) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); 42262306a36Sopenharmony_ci} 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci/** 42562306a36Sopenharmony_ci * ixgbe_fw_phy_activity - Perform an activity on a PHY 42662306a36Sopenharmony_ci * @hw: pointer to hardware structure 42762306a36Sopenharmony_ci * @activity: activity to perform 42862306a36Sopenharmony_ci * @data: Pointer to 4 32-bit words of data 42962306a36Sopenharmony_ci */ 43062306a36Sopenharmony_cis32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity, 43162306a36Sopenharmony_ci u32 (*data)[FW_PHY_ACT_DATA_COUNT]) 43262306a36Sopenharmony_ci{ 43362306a36Sopenharmony_ci union { 43462306a36Sopenharmony_ci struct ixgbe_hic_phy_activity_req cmd; 43562306a36Sopenharmony_ci struct ixgbe_hic_phy_activity_resp rsp; 43662306a36Sopenharmony_ci } hic; 43762306a36Sopenharmony_ci u16 retries = FW_PHY_ACT_RETRIES; 43862306a36Sopenharmony_ci s32 rc; 43962306a36Sopenharmony_ci u32 i; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci do { 44262306a36Sopenharmony_ci memset(&hic, 0, sizeof(hic)); 44362306a36Sopenharmony_ci hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD; 44462306a36Sopenharmony_ci hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN; 44562306a36Sopenharmony_ci hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 44662306a36Sopenharmony_ci hic.cmd.port_number = hw->bus.lan_id; 44762306a36Sopenharmony_ci hic.cmd.activity_id = cpu_to_le16(activity); 44862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(hic.cmd.data); ++i) 44962306a36Sopenharmony_ci hic.cmd.data[i] = cpu_to_be32((*data)[i]); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci rc = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 45262306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, 45362306a36Sopenharmony_ci true); 45462306a36Sopenharmony_ci if (rc) 45562306a36Sopenharmony_ci return rc; 45662306a36Sopenharmony_ci if (hic.rsp.hdr.cmd_or_resp.ret_status == 45762306a36Sopenharmony_ci FW_CEM_RESP_STATUS_SUCCESS) { 45862306a36Sopenharmony_ci for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i) 45962306a36Sopenharmony_ci (*data)[i] = be32_to_cpu(hic.rsp.data[i]); 46062306a36Sopenharmony_ci return 0; 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci usleep_range(20, 30); 46362306a36Sopenharmony_ci --retries; 46462306a36Sopenharmony_ci } while (retries > 0); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci return -EIO; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic const struct { 47062306a36Sopenharmony_ci u16 fw_speed; 47162306a36Sopenharmony_ci ixgbe_link_speed phy_speed; 47262306a36Sopenharmony_ci} ixgbe_fw_map[] = { 47362306a36Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL }, 47462306a36Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL }, 47562306a36Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL }, 47662306a36Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL }, 47762306a36Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL }, 47862306a36Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL }, 47962306a36Sopenharmony_ci}; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci/** 48262306a36Sopenharmony_ci * ixgbe_get_phy_id_fw - Get the phy ID via firmware command 48362306a36Sopenharmony_ci * @hw: pointer to hardware structure 48462306a36Sopenharmony_ci * 48562306a36Sopenharmony_ci * Returns error code 48662306a36Sopenharmony_ci */ 48762306a36Sopenharmony_cistatic s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 }; 49062306a36Sopenharmony_ci u16 phy_speeds; 49162306a36Sopenharmony_ci u16 phy_id_lo; 49262306a36Sopenharmony_ci s32 rc; 49362306a36Sopenharmony_ci u16 i; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci if (hw->phy.id) 49662306a36Sopenharmony_ci return 0; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info); 49962306a36Sopenharmony_ci if (rc) 50062306a36Sopenharmony_ci return rc; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci hw->phy.speeds_supported = 0; 50362306a36Sopenharmony_ci phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK; 50462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) { 50562306a36Sopenharmony_ci if (phy_speeds & ixgbe_fw_map[i].fw_speed) 50662306a36Sopenharmony_ci hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed; 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK; 51062306a36Sopenharmony_ci phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK; 51162306a36Sopenharmony_ci hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK; 51262306a36Sopenharmony_ci hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK; 51362306a36Sopenharmony_ci if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK) 51462306a36Sopenharmony_ci return -EFAULT; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci hw->phy.autoneg_advertised = hw->phy.speeds_supported; 51762306a36Sopenharmony_ci hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL | 51862306a36Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL; 51962306a36Sopenharmony_ci hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported; 52062306a36Sopenharmony_ci return 0; 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci/** 52462306a36Sopenharmony_ci * ixgbe_identify_phy_fw - Get PHY type based on firmware command 52562306a36Sopenharmony_ci * @hw: pointer to hardware structure 52662306a36Sopenharmony_ci * 52762306a36Sopenharmony_ci * Returns error code 52862306a36Sopenharmony_ci */ 52962306a36Sopenharmony_cistatic s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci if (hw->bus.lan_id) 53262306a36Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 53362306a36Sopenharmony_ci else 53462306a36Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci hw->phy.type = ixgbe_phy_fw; 53762306a36Sopenharmony_ci hw->phy.ops.read_reg = NULL; 53862306a36Sopenharmony_ci hw->phy.ops.write_reg = NULL; 53962306a36Sopenharmony_ci return ixgbe_get_phy_id_fw(hw); 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci/** 54362306a36Sopenharmony_ci * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY 54462306a36Sopenharmony_ci * @hw: pointer to hardware structure 54562306a36Sopenharmony_ci * 54662306a36Sopenharmony_ci * Returns error code 54762306a36Sopenharmony_ci */ 54862306a36Sopenharmony_cistatic s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 }; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF; 55362306a36Sopenharmony_ci return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup); 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci/** 55762306a36Sopenharmony_ci * ixgbe_setup_fw_link - Setup firmware-controlled PHYs 55862306a36Sopenharmony_ci * @hw: pointer to hardware structure 55962306a36Sopenharmony_ci */ 56062306a36Sopenharmony_cistatic s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 }; 56362306a36Sopenharmony_ci s32 rc; 56462306a36Sopenharmony_ci u16 i; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) 56762306a36Sopenharmony_ci return 0; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 57062306a36Sopenharmony_ci hw_err(hw, "rx_pause not valid in strict IEEE mode\n"); 57162306a36Sopenharmony_ci return -EINVAL; 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci switch (hw->fc.requested_mode) { 57562306a36Sopenharmony_ci case ixgbe_fc_full: 57662306a36Sopenharmony_ci setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX << 57762306a36Sopenharmony_ci FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 57862306a36Sopenharmony_ci break; 57962306a36Sopenharmony_ci case ixgbe_fc_rx_pause: 58062306a36Sopenharmony_ci setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX << 58162306a36Sopenharmony_ci FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 58262306a36Sopenharmony_ci break; 58362306a36Sopenharmony_ci case ixgbe_fc_tx_pause: 58462306a36Sopenharmony_ci setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX << 58562306a36Sopenharmony_ci FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 58662306a36Sopenharmony_ci break; 58762306a36Sopenharmony_ci default: 58862306a36Sopenharmony_ci break; 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) { 59262306a36Sopenharmony_ci if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed) 59362306a36Sopenharmony_ci setup[0] |= ixgbe_fw_map[i].fw_speed; 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci if (hw->phy.eee_speeds_advertised) 59862306a36Sopenharmony_ci setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup); 60162306a36Sopenharmony_ci if (rc) 60262306a36Sopenharmony_ci return rc; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN) 60562306a36Sopenharmony_ci return -EIO; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci return 0; 60862306a36Sopenharmony_ci} 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci/** 61162306a36Sopenharmony_ci * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs 61262306a36Sopenharmony_ci * @hw: pointer to hardware structure 61362306a36Sopenharmony_ci * 61462306a36Sopenharmony_ci * Called at init time to set up flow control. 61562306a36Sopenharmony_ci */ 61662306a36Sopenharmony_cistatic s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci if (hw->fc.requested_mode == ixgbe_fc_default) 61962306a36Sopenharmony_ci hw->fc.requested_mode = ixgbe_fc_full; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci return ixgbe_setup_fw_link(hw); 62262306a36Sopenharmony_ci} 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci/** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 62562306a36Sopenharmony_ci * @hw: pointer to hardware structure 62662306a36Sopenharmony_ci * 62762306a36Sopenharmony_ci * Initializes the EEPROM parameters ixgbe_eeprom_info within the 62862306a36Sopenharmony_ci * ixgbe_hw struct in order to set up EEPROM access. 62962306a36Sopenharmony_ci **/ 63062306a36Sopenharmony_cistatic s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 63162306a36Sopenharmony_ci{ 63262306a36Sopenharmony_ci struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 63362306a36Sopenharmony_ci u32 eec; 63462306a36Sopenharmony_ci u16 eeprom_size; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci if (eeprom->type == ixgbe_eeprom_uninitialized) { 63762306a36Sopenharmony_ci eeprom->semaphore_delay = 10; 63862306a36Sopenharmony_ci eeprom->type = ixgbe_flash; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 64162306a36Sopenharmony_ci eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 64262306a36Sopenharmony_ci IXGBE_EEC_SIZE_SHIFT); 64362306a36Sopenharmony_ci eeprom->word_size = BIT(eeprom_size + 64462306a36Sopenharmony_ci IXGBE_EEPROM_WORD_SIZE_SHIFT); 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 64762306a36Sopenharmony_ci eeprom->type, eeprom->word_size); 64862306a36Sopenharmony_ci } 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci return 0; 65162306a36Sopenharmony_ci} 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci/** 65462306a36Sopenharmony_ci * ixgbe_iosf_wait - Wait for IOSF command completion 65562306a36Sopenharmony_ci * @hw: pointer to hardware structure 65662306a36Sopenharmony_ci * @ctrl: pointer to location to receive final IOSF control value 65762306a36Sopenharmony_ci * 65862306a36Sopenharmony_ci * Return: failing status on timeout 65962306a36Sopenharmony_ci * 66062306a36Sopenharmony_ci * Note: ctrl can be NULL if the IOSF control register value is not needed 66162306a36Sopenharmony_ci */ 66262306a36Sopenharmony_cistatic s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 66362306a36Sopenharmony_ci{ 66462306a36Sopenharmony_ci u32 i, command; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci /* Check every 10 usec to see if the address cycle completed. 66762306a36Sopenharmony_ci * The SB IOSF BUSY bit will clear when the operation is 66862306a36Sopenharmony_ci * complete. 66962306a36Sopenharmony_ci */ 67062306a36Sopenharmony_ci for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 67162306a36Sopenharmony_ci command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 67262306a36Sopenharmony_ci if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 67362306a36Sopenharmony_ci break; 67462306a36Sopenharmony_ci udelay(10); 67562306a36Sopenharmony_ci } 67662306a36Sopenharmony_ci if (ctrl) 67762306a36Sopenharmony_ci *ctrl = command; 67862306a36Sopenharmony_ci if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 67962306a36Sopenharmony_ci hw_dbg(hw, "IOSF wait timed out\n"); 68062306a36Sopenharmony_ci return -EIO; 68162306a36Sopenharmony_ci } 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci return 0; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci/** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 68762306a36Sopenharmony_ci * IOSF device 68862306a36Sopenharmony_ci * @hw: pointer to hardware structure 68962306a36Sopenharmony_ci * @reg_addr: 32 bit PHY register to write 69062306a36Sopenharmony_ci * @device_type: 3 bit device type 69162306a36Sopenharmony_ci * @phy_data: Pointer to read data from the register 69262306a36Sopenharmony_ci **/ 69362306a36Sopenharmony_cistatic s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 69462306a36Sopenharmony_ci u32 device_type, u32 *data) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 69762306a36Sopenharmony_ci u32 command, error; 69862306a36Sopenharmony_ci s32 ret; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 70162306a36Sopenharmony_ci if (ret) 70262306a36Sopenharmony_ci return ret; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci ret = ixgbe_iosf_wait(hw, NULL); 70562306a36Sopenharmony_ci if (ret) 70662306a36Sopenharmony_ci goto out; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 70962306a36Sopenharmony_ci (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci /* Write IOSF control register */ 71262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci ret = ixgbe_iosf_wait(hw, &command); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 71762306a36Sopenharmony_ci error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 71862306a36Sopenharmony_ci IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 71962306a36Sopenharmony_ci hw_dbg(hw, "Failed to read, error %x\n", error); 72062306a36Sopenharmony_ci ret = -EIO; 72162306a36Sopenharmony_ci goto out; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci if (!ret) 72562306a36Sopenharmony_ci *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ciout: 72862306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, gssr); 72962306a36Sopenharmony_ci return ret; 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci/** 73362306a36Sopenharmony_ci * ixgbe_get_phy_token - Get the token for shared PHY access 73462306a36Sopenharmony_ci * @hw: Pointer to hardware structure 73562306a36Sopenharmony_ci */ 73662306a36Sopenharmony_cistatic s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) 73762306a36Sopenharmony_ci{ 73862306a36Sopenharmony_ci struct ixgbe_hic_phy_token_req token_cmd; 73962306a36Sopenharmony_ci s32 status; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 74262306a36Sopenharmony_ci token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 74362306a36Sopenharmony_ci token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 74462306a36Sopenharmony_ci token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 74562306a36Sopenharmony_ci token_cmd.port_number = hw->bus.lan_id; 74662306a36Sopenharmony_ci token_cmd.command_type = FW_PHY_TOKEN_REQ; 74762306a36Sopenharmony_ci token_cmd.pad = 0; 74862306a36Sopenharmony_ci status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 74962306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, 75062306a36Sopenharmony_ci true); 75162306a36Sopenharmony_ci if (status) 75262306a36Sopenharmony_ci return status; 75362306a36Sopenharmony_ci if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 75462306a36Sopenharmony_ci return 0; 75562306a36Sopenharmony_ci if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) 75662306a36Sopenharmony_ci return -EIO; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci return -EAGAIN; 75962306a36Sopenharmony_ci} 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci/** 76262306a36Sopenharmony_ci * ixgbe_put_phy_token - Put the token for shared PHY access 76362306a36Sopenharmony_ci * @hw: Pointer to hardware structure 76462306a36Sopenharmony_ci */ 76562306a36Sopenharmony_cistatic s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) 76662306a36Sopenharmony_ci{ 76762306a36Sopenharmony_ci struct ixgbe_hic_phy_token_req token_cmd; 76862306a36Sopenharmony_ci s32 status; 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 77162306a36Sopenharmony_ci token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 77262306a36Sopenharmony_ci token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 77362306a36Sopenharmony_ci token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 77462306a36Sopenharmony_ci token_cmd.port_number = hw->bus.lan_id; 77562306a36Sopenharmony_ci token_cmd.command_type = FW_PHY_TOKEN_REL; 77662306a36Sopenharmony_ci token_cmd.pad = 0; 77762306a36Sopenharmony_ci status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 77862306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, 77962306a36Sopenharmony_ci true); 78062306a36Sopenharmony_ci if (status) 78162306a36Sopenharmony_ci return status; 78262306a36Sopenharmony_ci if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 78362306a36Sopenharmony_ci return 0; 78462306a36Sopenharmony_ci return -EIO; 78562306a36Sopenharmony_ci} 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci/** 78862306a36Sopenharmony_ci * ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register 78962306a36Sopenharmony_ci * @hw: pointer to hardware structure 79062306a36Sopenharmony_ci * @reg_addr: 32 bit PHY register to write 79162306a36Sopenharmony_ci * @device_type: 3 bit device type 79262306a36Sopenharmony_ci * @data: Data to write to the register 79362306a36Sopenharmony_ci **/ 79462306a36Sopenharmony_cistatic s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 79562306a36Sopenharmony_ci __always_unused u32 device_type, 79662306a36Sopenharmony_ci u32 data) 79762306a36Sopenharmony_ci{ 79862306a36Sopenharmony_ci struct ixgbe_hic_internal_phy_req write_cmd; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci memset(&write_cmd, 0, sizeof(write_cmd)); 80162306a36Sopenharmony_ci write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 80262306a36Sopenharmony_ci write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 80362306a36Sopenharmony_ci write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 80462306a36Sopenharmony_ci write_cmd.port_number = hw->bus.lan_id; 80562306a36Sopenharmony_ci write_cmd.command_type = FW_INT_PHY_REQ_WRITE; 80662306a36Sopenharmony_ci write_cmd.address = cpu_to_be16(reg_addr); 80762306a36Sopenharmony_ci write_cmd.write_data = cpu_to_be32(data); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd), 81062306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, false); 81162306a36Sopenharmony_ci} 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci/** 81462306a36Sopenharmony_ci * ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register 81562306a36Sopenharmony_ci * @hw: pointer to hardware structure 81662306a36Sopenharmony_ci * @reg_addr: 32 bit PHY register to write 81762306a36Sopenharmony_ci * @device_type: 3 bit device type 81862306a36Sopenharmony_ci * @data: Pointer to read data from the register 81962306a36Sopenharmony_ci **/ 82062306a36Sopenharmony_cistatic s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 82162306a36Sopenharmony_ci __always_unused u32 device_type, 82262306a36Sopenharmony_ci u32 *data) 82362306a36Sopenharmony_ci{ 82462306a36Sopenharmony_ci union { 82562306a36Sopenharmony_ci struct ixgbe_hic_internal_phy_req cmd; 82662306a36Sopenharmony_ci struct ixgbe_hic_internal_phy_resp rsp; 82762306a36Sopenharmony_ci } hic; 82862306a36Sopenharmony_ci s32 status; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci memset(&hic, 0, sizeof(hic)); 83162306a36Sopenharmony_ci hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 83262306a36Sopenharmony_ci hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 83362306a36Sopenharmony_ci hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 83462306a36Sopenharmony_ci hic.cmd.port_number = hw->bus.lan_id; 83562306a36Sopenharmony_ci hic.cmd.command_type = FW_INT_PHY_REQ_READ; 83662306a36Sopenharmony_ci hic.cmd.address = cpu_to_be16(reg_addr); 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 83962306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, true); 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci /* Extract the register value from the response. */ 84262306a36Sopenharmony_ci *data = be32_to_cpu(hic.rsp.read_data); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci return status; 84562306a36Sopenharmony_ci} 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci/** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 84862306a36Sopenharmony_ci * @hw: pointer to hardware structure 84962306a36Sopenharmony_ci * @offset: offset of word in the EEPROM to read 85062306a36Sopenharmony_ci * @words: number of words 85162306a36Sopenharmony_ci * @data: word(s) read from the EEPROM 85262306a36Sopenharmony_ci * 85362306a36Sopenharmony_ci * Reads a 16 bit word(s) from the EEPROM using the hostif. 85462306a36Sopenharmony_ci **/ 85562306a36Sopenharmony_cistatic s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 85662306a36Sopenharmony_ci u16 offset, u16 words, u16 *data) 85762306a36Sopenharmony_ci{ 85862306a36Sopenharmony_ci const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; 85962306a36Sopenharmony_ci struct ixgbe_hic_read_shadow_ram buffer; 86062306a36Sopenharmony_ci u32 current_word = 0; 86162306a36Sopenharmony_ci u16 words_to_read; 86262306a36Sopenharmony_ci s32 status; 86362306a36Sopenharmony_ci u32 i; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci /* Take semaphore for the entire operation. */ 86662306a36Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, mask); 86762306a36Sopenharmony_ci if (status) { 86862306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 86962306a36Sopenharmony_ci return status; 87062306a36Sopenharmony_ci } 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci while (words) { 87362306a36Sopenharmony_ci if (words > FW_MAX_READ_BUFFER_SIZE / 2) 87462306a36Sopenharmony_ci words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 87562306a36Sopenharmony_ci else 87662306a36Sopenharmony_ci words_to_read = words; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 87962306a36Sopenharmony_ci buffer.hdr.req.buf_lenh = 0; 88062306a36Sopenharmony_ci buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 88162306a36Sopenharmony_ci buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci /* convert offset from words to bytes */ 88462306a36Sopenharmony_ci buffer.address = (__force u32)cpu_to_be32((offset + 88562306a36Sopenharmony_ci current_word) * 2); 88662306a36Sopenharmony_ci buffer.length = (__force u16)cpu_to_be16(words_to_read * 2); 88762306a36Sopenharmony_ci buffer.pad2 = 0; 88862306a36Sopenharmony_ci buffer.pad3 = 0; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), 89162306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT); 89262306a36Sopenharmony_ci if (status) { 89362306a36Sopenharmony_ci hw_dbg(hw, "Host interface command failed\n"); 89462306a36Sopenharmony_ci goto out; 89562306a36Sopenharmony_ci } 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci for (i = 0; i < words_to_read; i++) { 89862306a36Sopenharmony_ci u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 89962306a36Sopenharmony_ci 2 * i; 90062306a36Sopenharmony_ci u32 value = IXGBE_READ_REG(hw, reg); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci data[current_word] = (u16)(value & 0xffff); 90362306a36Sopenharmony_ci current_word++; 90462306a36Sopenharmony_ci i++; 90562306a36Sopenharmony_ci if (i < words_to_read) { 90662306a36Sopenharmony_ci value >>= 16; 90762306a36Sopenharmony_ci data[current_word] = (u16)(value & 0xffff); 90862306a36Sopenharmony_ci current_word++; 90962306a36Sopenharmony_ci } 91062306a36Sopenharmony_ci } 91162306a36Sopenharmony_ci words -= words_to_read; 91262306a36Sopenharmony_ci } 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ciout: 91562306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, mask); 91662306a36Sopenharmony_ci return status; 91762306a36Sopenharmony_ci} 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci/** ixgbe_checksum_ptr_x550 - Checksum one pointer region 92062306a36Sopenharmony_ci * @hw: pointer to hardware structure 92162306a36Sopenharmony_ci * @ptr: pointer offset in eeprom 92262306a36Sopenharmony_ci * @size: size of section pointed by ptr, if 0 first word will be used as size 92362306a36Sopenharmony_ci * @csum: address of checksum to update 92462306a36Sopenharmony_ci * 92562306a36Sopenharmony_ci * Returns error status for any failure 92662306a36Sopenharmony_ci **/ 92762306a36Sopenharmony_cistatic s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 92862306a36Sopenharmony_ci u16 size, u16 *csum, u16 *buffer, 92962306a36Sopenharmony_ci u32 buffer_size) 93062306a36Sopenharmony_ci{ 93162306a36Sopenharmony_ci u16 buf[256]; 93262306a36Sopenharmony_ci s32 status; 93362306a36Sopenharmony_ci u16 length, bufsz, i, start; 93462306a36Sopenharmony_ci u16 *local_buffer; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci bufsz = ARRAY_SIZE(buf); 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci /* Read a chunk at the pointer location */ 93962306a36Sopenharmony_ci if (!buffer) { 94062306a36Sopenharmony_ci status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 94162306a36Sopenharmony_ci if (status) { 94262306a36Sopenharmony_ci hw_dbg(hw, "Failed to read EEPROM image\n"); 94362306a36Sopenharmony_ci return status; 94462306a36Sopenharmony_ci } 94562306a36Sopenharmony_ci local_buffer = buf; 94662306a36Sopenharmony_ci } else { 94762306a36Sopenharmony_ci if (buffer_size < ptr) 94862306a36Sopenharmony_ci return -EINVAL; 94962306a36Sopenharmony_ci local_buffer = &buffer[ptr]; 95062306a36Sopenharmony_ci } 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci if (size) { 95362306a36Sopenharmony_ci start = 0; 95462306a36Sopenharmony_ci length = size; 95562306a36Sopenharmony_ci } else { 95662306a36Sopenharmony_ci start = 1; 95762306a36Sopenharmony_ci length = local_buffer[0]; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci /* Skip pointer section if length is invalid. */ 96062306a36Sopenharmony_ci if (length == 0xFFFF || length == 0 || 96162306a36Sopenharmony_ci (ptr + length) >= hw->eeprom.word_size) 96262306a36Sopenharmony_ci return 0; 96362306a36Sopenharmony_ci } 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci if (buffer && ((u32)start + (u32)length > buffer_size)) 96662306a36Sopenharmony_ci return -EINVAL; 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci for (i = start; length; i++, length--) { 96962306a36Sopenharmony_ci if (i == bufsz && !buffer) { 97062306a36Sopenharmony_ci ptr += bufsz; 97162306a36Sopenharmony_ci i = 0; 97262306a36Sopenharmony_ci if (length < bufsz) 97362306a36Sopenharmony_ci bufsz = length; 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci /* Read a chunk at the pointer location */ 97662306a36Sopenharmony_ci status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 97762306a36Sopenharmony_ci bufsz, buf); 97862306a36Sopenharmony_ci if (status) { 97962306a36Sopenharmony_ci hw_dbg(hw, "Failed to read EEPROM image\n"); 98062306a36Sopenharmony_ci return status; 98162306a36Sopenharmony_ci } 98262306a36Sopenharmony_ci } 98362306a36Sopenharmony_ci *csum += local_buffer[i]; 98462306a36Sopenharmony_ci } 98562306a36Sopenharmony_ci return 0; 98662306a36Sopenharmony_ci} 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci/** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 98962306a36Sopenharmony_ci * @hw: pointer to hardware structure 99062306a36Sopenharmony_ci * @buffer: pointer to buffer containing calculated checksum 99162306a36Sopenharmony_ci * @buffer_size: size of buffer 99262306a36Sopenharmony_ci * 99362306a36Sopenharmony_ci * Returns a negative error code on error, or the 16-bit checksum 99462306a36Sopenharmony_ci **/ 99562306a36Sopenharmony_cistatic s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 99662306a36Sopenharmony_ci u32 buffer_size) 99762306a36Sopenharmony_ci{ 99862306a36Sopenharmony_ci u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 99962306a36Sopenharmony_ci u16 *local_buffer; 100062306a36Sopenharmony_ci s32 status; 100162306a36Sopenharmony_ci u16 checksum = 0; 100262306a36Sopenharmony_ci u16 pointer, i, size; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci hw->eeprom.ops.init_params(hw); 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci if (!buffer) { 100762306a36Sopenharmony_ci /* Read pointer area */ 100862306a36Sopenharmony_ci status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 100962306a36Sopenharmony_ci IXGBE_EEPROM_LAST_WORD + 1, 101062306a36Sopenharmony_ci eeprom_ptrs); 101162306a36Sopenharmony_ci if (status) { 101262306a36Sopenharmony_ci hw_dbg(hw, "Failed to read EEPROM image\n"); 101362306a36Sopenharmony_ci return status; 101462306a36Sopenharmony_ci } 101562306a36Sopenharmony_ci local_buffer = eeprom_ptrs; 101662306a36Sopenharmony_ci } else { 101762306a36Sopenharmony_ci if (buffer_size < IXGBE_EEPROM_LAST_WORD) 101862306a36Sopenharmony_ci return -EINVAL; 101962306a36Sopenharmony_ci local_buffer = buffer; 102062306a36Sopenharmony_ci } 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci /* For X550 hardware include 0x0-0x41 in the checksum, skip the 102362306a36Sopenharmony_ci * checksum word itself 102462306a36Sopenharmony_ci */ 102562306a36Sopenharmony_ci for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 102662306a36Sopenharmony_ci if (i != IXGBE_EEPROM_CHECKSUM) 102762306a36Sopenharmony_ci checksum += local_buffer[i]; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 103062306a36Sopenharmony_ci * FW, PHY module, and PCIe Expansion/Option ROM pointers. 103162306a36Sopenharmony_ci */ 103262306a36Sopenharmony_ci for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 103362306a36Sopenharmony_ci if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 103462306a36Sopenharmony_ci continue; 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci pointer = local_buffer[i]; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci /* Skip pointer section if the pointer is invalid. */ 103962306a36Sopenharmony_ci if (pointer == 0xFFFF || pointer == 0 || 104062306a36Sopenharmony_ci pointer >= hw->eeprom.word_size) 104162306a36Sopenharmony_ci continue; 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci switch (i) { 104462306a36Sopenharmony_ci case IXGBE_PCIE_GENERAL_PTR: 104562306a36Sopenharmony_ci size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 104662306a36Sopenharmony_ci break; 104762306a36Sopenharmony_ci case IXGBE_PCIE_CONFIG0_PTR: 104862306a36Sopenharmony_ci case IXGBE_PCIE_CONFIG1_PTR: 104962306a36Sopenharmony_ci size = IXGBE_PCIE_CONFIG_SIZE; 105062306a36Sopenharmony_ci break; 105162306a36Sopenharmony_ci default: 105262306a36Sopenharmony_ci size = 0; 105362306a36Sopenharmony_ci break; 105462306a36Sopenharmony_ci } 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 105762306a36Sopenharmony_ci buffer, buffer_size); 105862306a36Sopenharmony_ci if (status) 105962306a36Sopenharmony_ci return status; 106062306a36Sopenharmony_ci } 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci checksum = (u16)IXGBE_EEPROM_SUM - checksum; 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci return (s32)checksum; 106562306a36Sopenharmony_ci} 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci/** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 106862306a36Sopenharmony_ci * @hw: pointer to hardware structure 106962306a36Sopenharmony_ci * 107062306a36Sopenharmony_ci * Returns a negative error code on error, or the 16-bit checksum 107162306a36Sopenharmony_ci **/ 107262306a36Sopenharmony_cistatic s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 107362306a36Sopenharmony_ci{ 107462306a36Sopenharmony_ci return ixgbe_calc_checksum_X550(hw, NULL, 0); 107562306a36Sopenharmony_ci} 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci/** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 107862306a36Sopenharmony_ci * @hw: pointer to hardware structure 107962306a36Sopenharmony_ci * @offset: offset of word in the EEPROM to read 108062306a36Sopenharmony_ci * @data: word read from the EEPROM 108162306a36Sopenharmony_ci * 108262306a36Sopenharmony_ci * Reads a 16 bit word from the EEPROM using the hostif. 108362306a36Sopenharmony_ci **/ 108462306a36Sopenharmony_cistatic s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 108562306a36Sopenharmony_ci{ 108662306a36Sopenharmony_ci const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; 108762306a36Sopenharmony_ci struct ixgbe_hic_read_shadow_ram buffer; 108862306a36Sopenharmony_ci s32 status; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 109162306a36Sopenharmony_ci buffer.hdr.req.buf_lenh = 0; 109262306a36Sopenharmony_ci buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 109362306a36Sopenharmony_ci buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci /* convert offset from words to bytes */ 109662306a36Sopenharmony_ci buffer.address = (__force u32)cpu_to_be32(offset * 2); 109762306a36Sopenharmony_ci /* one word */ 109862306a36Sopenharmony_ci buffer.length = (__force u16)cpu_to_be16(sizeof(u16)); 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, mask); 110162306a36Sopenharmony_ci if (status) 110262306a36Sopenharmony_ci return status; 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), 110562306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT); 110662306a36Sopenharmony_ci if (!status) { 110762306a36Sopenharmony_ci *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 110862306a36Sopenharmony_ci FW_NVM_DATA_OFFSET); 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, mask); 111262306a36Sopenharmony_ci return status; 111362306a36Sopenharmony_ci} 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci/** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 111662306a36Sopenharmony_ci * @hw: pointer to hardware structure 111762306a36Sopenharmony_ci * @checksum_val: calculated checksum 111862306a36Sopenharmony_ci * 111962306a36Sopenharmony_ci * Performs checksum calculation and validates the EEPROM checksum. If the 112062306a36Sopenharmony_ci * caller does not need checksum_val, the value can be NULL. 112162306a36Sopenharmony_ci **/ 112262306a36Sopenharmony_cistatic s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 112362306a36Sopenharmony_ci u16 *checksum_val) 112462306a36Sopenharmony_ci{ 112562306a36Sopenharmony_ci s32 status; 112662306a36Sopenharmony_ci u16 checksum; 112762306a36Sopenharmony_ci u16 read_checksum = 0; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci /* Read the first word from the EEPROM. If this times out or fails, do 113062306a36Sopenharmony_ci * not continue or we could be in for a very long wait while every 113162306a36Sopenharmony_ci * EEPROM read fails 113262306a36Sopenharmony_ci */ 113362306a36Sopenharmony_ci status = hw->eeprom.ops.read(hw, 0, &checksum); 113462306a36Sopenharmony_ci if (status) { 113562306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 113662306a36Sopenharmony_ci return status; 113762306a36Sopenharmony_ci } 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci status = hw->eeprom.ops.calc_checksum(hw); 114062306a36Sopenharmony_ci if (status < 0) 114162306a36Sopenharmony_ci return status; 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci checksum = (u16)(status & 0xffff); 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 114662306a36Sopenharmony_ci &read_checksum); 114762306a36Sopenharmony_ci if (status) 114862306a36Sopenharmony_ci return status; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci /* Verify read checksum from EEPROM is the same as 115162306a36Sopenharmony_ci * calculated checksum 115262306a36Sopenharmony_ci */ 115362306a36Sopenharmony_ci if (read_checksum != checksum) { 115462306a36Sopenharmony_ci status = -EIO; 115562306a36Sopenharmony_ci hw_dbg(hw, "Invalid EEPROM checksum"); 115662306a36Sopenharmony_ci } 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci /* If the user cares, return the calculated checksum */ 115962306a36Sopenharmony_ci if (checksum_val) 116062306a36Sopenharmony_ci *checksum_val = checksum; 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci return status; 116362306a36Sopenharmony_ci} 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci/** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 116662306a36Sopenharmony_ci * @hw: pointer to hardware structure 116762306a36Sopenharmony_ci * @offset: offset of word in the EEPROM to write 116862306a36Sopenharmony_ci * @data: word write to the EEPROM 116962306a36Sopenharmony_ci * 117062306a36Sopenharmony_ci * Write a 16 bit word to the EEPROM using the hostif. 117162306a36Sopenharmony_ci **/ 117262306a36Sopenharmony_cistatic s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 117362306a36Sopenharmony_ci u16 data) 117462306a36Sopenharmony_ci{ 117562306a36Sopenharmony_ci s32 status; 117662306a36Sopenharmony_ci struct ixgbe_hic_write_shadow_ram buffer; 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 117962306a36Sopenharmony_ci buffer.hdr.req.buf_lenh = 0; 118062306a36Sopenharmony_ci buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 118162306a36Sopenharmony_ci buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci /* one word */ 118462306a36Sopenharmony_ci buffer.length = cpu_to_be16(sizeof(u16)); 118562306a36Sopenharmony_ci buffer.data = data; 118662306a36Sopenharmony_ci buffer.address = cpu_to_be32(offset * 2); 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 118962306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, false); 119062306a36Sopenharmony_ci return status; 119162306a36Sopenharmony_ci} 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci/** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 119462306a36Sopenharmony_ci * @hw: pointer to hardware structure 119562306a36Sopenharmony_ci * @offset: offset of word in the EEPROM to write 119662306a36Sopenharmony_ci * @data: word write to the EEPROM 119762306a36Sopenharmony_ci * 119862306a36Sopenharmony_ci * Write a 16 bit word to the EEPROM using the hostif. 119962306a36Sopenharmony_ci **/ 120062306a36Sopenharmony_cistatic s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 120162306a36Sopenharmony_ci{ 120262306a36Sopenharmony_ci s32 status = 0; 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 120562306a36Sopenharmony_ci status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 120662306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 120762306a36Sopenharmony_ci } else { 120862306a36Sopenharmony_ci hw_dbg(hw, "write ee hostif failed to get semaphore"); 120962306a36Sopenharmony_ci status = -EBUSY; 121062306a36Sopenharmony_ci } 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci return status; 121362306a36Sopenharmony_ci} 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci/** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 121662306a36Sopenharmony_ci * @hw: pointer to hardware structure 121762306a36Sopenharmony_ci * 121862306a36Sopenharmony_ci * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 121962306a36Sopenharmony_ci **/ 122062306a36Sopenharmony_cistatic s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 122162306a36Sopenharmony_ci{ 122262306a36Sopenharmony_ci s32 status = 0; 122362306a36Sopenharmony_ci union ixgbe_hic_hdr2 buffer; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 122662306a36Sopenharmony_ci buffer.req.buf_lenh = 0; 122762306a36Sopenharmony_ci buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 122862306a36Sopenharmony_ci buffer.req.checksum = FW_DEFAULT_CHECKSUM; 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 123162306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, false); 123262306a36Sopenharmony_ci return status; 123362306a36Sopenharmony_ci} 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci/** 123662306a36Sopenharmony_ci * ixgbe_get_bus_info_X550em - Set PCI bus info 123762306a36Sopenharmony_ci * @hw: pointer to hardware structure 123862306a36Sopenharmony_ci * 123962306a36Sopenharmony_ci * Sets bus link width and speed to unknown because X550em is 124062306a36Sopenharmony_ci * not a PCI device. 124162306a36Sopenharmony_ci **/ 124262306a36Sopenharmony_cistatic s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) 124362306a36Sopenharmony_ci{ 124462306a36Sopenharmony_ci hw->bus.type = ixgbe_bus_type_internal; 124562306a36Sopenharmony_ci hw->bus.width = ixgbe_bus_width_unknown; 124662306a36Sopenharmony_ci hw->bus.speed = ixgbe_bus_speed_unknown; 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci hw->mac.ops.set_lan_id(hw); 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci return 0; 125162306a36Sopenharmony_ci} 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci/** 125462306a36Sopenharmony_ci * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode 125562306a36Sopenharmony_ci * @hw: pointer t hardware structure 125662306a36Sopenharmony_ci * 125762306a36Sopenharmony_ci * Returns true if in FW NVM recovery mode. 125862306a36Sopenharmony_ci */ 125962306a36Sopenharmony_cistatic bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw) 126062306a36Sopenharmony_ci{ 126162306a36Sopenharmony_ci u32 fwsm; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw)); 126462306a36Sopenharmony_ci return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE); 126562306a36Sopenharmony_ci} 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci/** ixgbe_disable_rx_x550 - Disable RX unit 126862306a36Sopenharmony_ci * 126962306a36Sopenharmony_ci * Enables the Rx DMA unit for x550 127062306a36Sopenharmony_ci **/ 127162306a36Sopenharmony_cistatic void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 127262306a36Sopenharmony_ci{ 127362306a36Sopenharmony_ci u32 rxctrl, pfdtxgswc; 127462306a36Sopenharmony_ci s32 status; 127562306a36Sopenharmony_ci struct ixgbe_hic_disable_rxen fw_cmd; 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 127862306a36Sopenharmony_ci if (rxctrl & IXGBE_RXCTRL_RXEN) { 127962306a36Sopenharmony_ci pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 128062306a36Sopenharmony_ci if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 128162306a36Sopenharmony_ci pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 128262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 128362306a36Sopenharmony_ci hw->mac.set_lben = true; 128462306a36Sopenharmony_ci } else { 128562306a36Sopenharmony_ci hw->mac.set_lben = false; 128662306a36Sopenharmony_ci } 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 128962306a36Sopenharmony_ci fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 129062306a36Sopenharmony_ci fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 129162306a36Sopenharmony_ci fw_cmd.port_number = hw->bus.lan_id; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci status = ixgbe_host_interface_command(hw, &fw_cmd, 129462306a36Sopenharmony_ci sizeof(struct ixgbe_hic_disable_rxen), 129562306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, true); 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci /* If we fail - disable RX using register write */ 129862306a36Sopenharmony_ci if (status) { 129962306a36Sopenharmony_ci rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 130062306a36Sopenharmony_ci if (rxctrl & IXGBE_RXCTRL_RXEN) { 130162306a36Sopenharmony_ci rxctrl &= ~IXGBE_RXCTRL_RXEN; 130262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 130362306a36Sopenharmony_ci } 130462306a36Sopenharmony_ci } 130562306a36Sopenharmony_ci } 130662306a36Sopenharmony_ci} 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci/** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 130962306a36Sopenharmony_ci * @hw: pointer to hardware structure 131062306a36Sopenharmony_ci * 131162306a36Sopenharmony_ci * After writing EEPROM to shadow RAM using EEWR register, software calculates 131262306a36Sopenharmony_ci * checksum and updates the EEPROM and instructs the hardware to update 131362306a36Sopenharmony_ci * the flash. 131462306a36Sopenharmony_ci **/ 131562306a36Sopenharmony_cistatic s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 131662306a36Sopenharmony_ci{ 131762306a36Sopenharmony_ci s32 status; 131862306a36Sopenharmony_ci u16 checksum = 0; 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci /* Read the first word from the EEPROM. If this times out or fails, do 132162306a36Sopenharmony_ci * not continue or we could be in for a very long wait while every 132262306a36Sopenharmony_ci * EEPROM read fails 132362306a36Sopenharmony_ci */ 132462306a36Sopenharmony_ci status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 132562306a36Sopenharmony_ci if (status) { 132662306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 132762306a36Sopenharmony_ci return status; 132862306a36Sopenharmony_ci } 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci status = ixgbe_calc_eeprom_checksum_X550(hw); 133162306a36Sopenharmony_ci if (status < 0) 133262306a36Sopenharmony_ci return status; 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci checksum = (u16)(status & 0xffff); 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 133762306a36Sopenharmony_ci checksum); 133862306a36Sopenharmony_ci if (status) 133962306a36Sopenharmony_ci return status; 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci status = ixgbe_update_flash_X550(hw); 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci return status; 134462306a36Sopenharmony_ci} 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci/** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 134762306a36Sopenharmony_ci * @hw: pointer to hardware structure 134862306a36Sopenharmony_ci * @offset: offset of word in the EEPROM to write 134962306a36Sopenharmony_ci * @words: number of words 135062306a36Sopenharmony_ci * @data: word(s) write to the EEPROM 135162306a36Sopenharmony_ci * 135262306a36Sopenharmony_ci * 135362306a36Sopenharmony_ci * Write a 16 bit word(s) to the EEPROM using the hostif. 135462306a36Sopenharmony_ci **/ 135562306a36Sopenharmony_cistatic s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 135662306a36Sopenharmony_ci u16 offset, u16 words, 135762306a36Sopenharmony_ci u16 *data) 135862306a36Sopenharmony_ci{ 135962306a36Sopenharmony_ci s32 status = 0; 136062306a36Sopenharmony_ci u32 i = 0; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci /* Take semaphore for the entire operation. */ 136362306a36Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 136462306a36Sopenharmony_ci if (status) { 136562306a36Sopenharmony_ci hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 136662306a36Sopenharmony_ci return status; 136762306a36Sopenharmony_ci } 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci for (i = 0; i < words; i++) { 137062306a36Sopenharmony_ci status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 137162306a36Sopenharmony_ci data[i]); 137262306a36Sopenharmony_ci if (status) { 137362306a36Sopenharmony_ci hw_dbg(hw, "Eeprom buffered write failed\n"); 137462306a36Sopenharmony_ci break; 137562306a36Sopenharmony_ci } 137662306a36Sopenharmony_ci } 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci return status; 138162306a36Sopenharmony_ci} 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci/** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 138462306a36Sopenharmony_ci * IOSF device 138562306a36Sopenharmony_ci * 138662306a36Sopenharmony_ci * @hw: pointer to hardware structure 138762306a36Sopenharmony_ci * @reg_addr: 32 bit PHY register to write 138862306a36Sopenharmony_ci * @device_type: 3 bit device type 138962306a36Sopenharmony_ci * @data: Data to write to the register 139062306a36Sopenharmony_ci **/ 139162306a36Sopenharmony_cistatic s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 139262306a36Sopenharmony_ci u32 device_type, u32 data) 139362306a36Sopenharmony_ci{ 139462306a36Sopenharmony_ci u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 139562306a36Sopenharmony_ci u32 command, error; 139662306a36Sopenharmony_ci s32 ret; 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 139962306a36Sopenharmony_ci if (ret) 140062306a36Sopenharmony_ci return ret; 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci ret = ixgbe_iosf_wait(hw, NULL); 140362306a36Sopenharmony_ci if (ret) 140462306a36Sopenharmony_ci goto out; 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 140762306a36Sopenharmony_ci (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci /* Write IOSF control register */ 141062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci /* Write IOSF data register */ 141362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci ret = ixgbe_iosf_wait(hw, &command); 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 141862306a36Sopenharmony_ci error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 141962306a36Sopenharmony_ci IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 142062306a36Sopenharmony_ci hw_dbg(hw, "Failed to write, error %x\n", error); 142162306a36Sopenharmony_ci return -EIO; 142262306a36Sopenharmony_ci } 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_ciout: 142562306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, gssr); 142662306a36Sopenharmony_ci return ret; 142762306a36Sopenharmony_ci} 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci/** 143062306a36Sopenharmony_ci * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration 143162306a36Sopenharmony_ci * @hw: pointer to hardware structure 143262306a36Sopenharmony_ci * 143362306a36Sopenharmony_ci * iXfI configuration needed for ixgbe_mac_X550EM_x devices. 143462306a36Sopenharmony_ci **/ 143562306a36Sopenharmony_cistatic s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) 143662306a36Sopenharmony_ci{ 143762306a36Sopenharmony_ci s32 status; 143862306a36Sopenharmony_ci u32 reg_val; 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci /* Disable training protocol FSM. */ 144162306a36Sopenharmony_ci status = ixgbe_read_iosf_sb_reg_x550(hw, 144262306a36Sopenharmony_ci IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 144362306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 144462306a36Sopenharmony_ci if (status) 144562306a36Sopenharmony_ci return status; 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 144862306a36Sopenharmony_ci status = ixgbe_write_iosf_sb_reg_x550(hw, 144962306a36Sopenharmony_ci IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 145062306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 145162306a36Sopenharmony_ci if (status) 145262306a36Sopenharmony_ci return status; 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci /* Disable Flex from training TXFFE. */ 145562306a36Sopenharmony_ci status = ixgbe_read_iosf_sb_reg_x550(hw, 145662306a36Sopenharmony_ci IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 145762306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 145862306a36Sopenharmony_ci if (status) 145962306a36Sopenharmony_ci return status; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 146262306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 146362306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 146462306a36Sopenharmony_ci status = ixgbe_write_iosf_sb_reg_x550(hw, 146562306a36Sopenharmony_ci IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 146662306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 146762306a36Sopenharmony_ci if (status) 146862306a36Sopenharmony_ci return status; 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci status = ixgbe_read_iosf_sb_reg_x550(hw, 147162306a36Sopenharmony_ci IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 147262306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 147362306a36Sopenharmony_ci if (status) 147462306a36Sopenharmony_ci return status; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 147762306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 147862306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 147962306a36Sopenharmony_ci status = ixgbe_write_iosf_sb_reg_x550(hw, 148062306a36Sopenharmony_ci IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 148162306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 148262306a36Sopenharmony_ci if (status) 148362306a36Sopenharmony_ci return status; 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci /* Enable override for coefficients. */ 148662306a36Sopenharmony_ci status = ixgbe_read_iosf_sb_reg_x550(hw, 148762306a36Sopenharmony_ci IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 148862306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 148962306a36Sopenharmony_ci if (status) 149062306a36Sopenharmony_ci return status; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 149362306a36Sopenharmony_ci reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 149462306a36Sopenharmony_ci reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 149562306a36Sopenharmony_ci reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 149662306a36Sopenharmony_ci status = ixgbe_write_iosf_sb_reg_x550(hw, 149762306a36Sopenharmony_ci IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 149862306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 149962306a36Sopenharmony_ci return status; 150062306a36Sopenharmony_ci} 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci/** 150362306a36Sopenharmony_ci * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the 150462306a36Sopenharmony_ci * internal PHY 150562306a36Sopenharmony_ci * @hw: pointer to hardware structure 150662306a36Sopenharmony_ci **/ 150762306a36Sopenharmony_cistatic s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw) 150862306a36Sopenharmony_ci{ 150962306a36Sopenharmony_ci s32 status; 151062306a36Sopenharmony_ci u32 link_ctrl; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci /* Restart auto-negotiation. */ 151362306a36Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 151462306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 151562306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci if (status) { 151862306a36Sopenharmony_ci hw_dbg(hw, "Auto-negotiation did not complete\n"); 151962306a36Sopenharmony_ci return status; 152062306a36Sopenharmony_ci } 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 152362306a36Sopenharmony_ci status = hw->mac.ops.write_iosf_sb_reg(hw, 152462306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 152562306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_x550em_a) { 152862306a36Sopenharmony_ci u32 flx_mask_st20; 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci /* Indicate to FW that AN restart has been asserted */ 153162306a36Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 153262306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 153362306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20); 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci if (status) { 153662306a36Sopenharmony_ci hw_dbg(hw, "Auto-negotiation did not complete\n"); 153762306a36Sopenharmony_ci return status; 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART; 154162306a36Sopenharmony_ci status = hw->mac.ops.write_iosf_sb_reg(hw, 154262306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 154362306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20); 154462306a36Sopenharmony_ci } 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci return status; 154762306a36Sopenharmony_ci} 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 155062306a36Sopenharmony_ci * @hw: pointer to hardware structure 155162306a36Sopenharmony_ci * @speed: the link speed to force 155262306a36Sopenharmony_ci * 155362306a36Sopenharmony_ci * Configures the integrated KR PHY to use iXFI mode. Used to connect an 155462306a36Sopenharmony_ci * internal and external PHY at a specific speed, without autonegotiation. 155562306a36Sopenharmony_ci **/ 155662306a36Sopenharmony_cistatic s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 155762306a36Sopenharmony_ci{ 155862306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 155962306a36Sopenharmony_ci s32 status; 156062306a36Sopenharmony_ci u32 reg_val; 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci /* iXFI is only supported with X552 */ 156362306a36Sopenharmony_ci if (mac->type != ixgbe_mac_X550EM_x) 156462306a36Sopenharmony_ci return -EIO; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci /* Disable AN and force speed to 10G Serial. */ 156762306a36Sopenharmony_ci status = ixgbe_read_iosf_sb_reg_x550(hw, 156862306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 156962306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 157062306a36Sopenharmony_ci if (status) 157162306a36Sopenharmony_ci return status; 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 157462306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci /* Select forced link speed for internal PHY. */ 157762306a36Sopenharmony_ci switch (*speed) { 157862306a36Sopenharmony_ci case IXGBE_LINK_SPEED_10GB_FULL: 157962306a36Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 158062306a36Sopenharmony_ci break; 158162306a36Sopenharmony_ci case IXGBE_LINK_SPEED_1GB_FULL: 158262306a36Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 158362306a36Sopenharmony_ci break; 158462306a36Sopenharmony_ci default: 158562306a36Sopenharmony_ci /* Other link speeds are not supported by internal KR PHY. */ 158662306a36Sopenharmony_ci return -EINVAL; 158762306a36Sopenharmony_ci } 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci status = ixgbe_write_iosf_sb_reg_x550(hw, 159062306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 159162306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 159262306a36Sopenharmony_ci if (status) 159362306a36Sopenharmony_ci return status; 159462306a36Sopenharmony_ci 159562306a36Sopenharmony_ci /* Additional configuration needed for x550em_x */ 159662306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_X550EM_x) { 159762306a36Sopenharmony_ci status = ixgbe_setup_ixfi_x550em_x(hw); 159862306a36Sopenharmony_ci if (status) 159962306a36Sopenharmony_ci return status; 160062306a36Sopenharmony_ci } 160162306a36Sopenharmony_ci 160262306a36Sopenharmony_ci /* Toggle port SW reset by AN reset. */ 160362306a36Sopenharmony_ci status = ixgbe_restart_an_internal_phy_x550em(hw); 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci return status; 160662306a36Sopenharmony_ci} 160762306a36Sopenharmony_ci 160862306a36Sopenharmony_ci/** 160962306a36Sopenharmony_ci * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported 161062306a36Sopenharmony_ci * @hw: pointer to hardware structure 161162306a36Sopenharmony_ci * @linear: true if SFP module is linear 161262306a36Sopenharmony_ci */ 161362306a36Sopenharmony_cistatic s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) 161462306a36Sopenharmony_ci{ 161562306a36Sopenharmony_ci switch (hw->phy.sfp_type) { 161662306a36Sopenharmony_ci case ixgbe_sfp_type_not_present: 161762306a36Sopenharmony_ci return -ENOENT; 161862306a36Sopenharmony_ci case ixgbe_sfp_type_da_cu_core0: 161962306a36Sopenharmony_ci case ixgbe_sfp_type_da_cu_core1: 162062306a36Sopenharmony_ci *linear = true; 162162306a36Sopenharmony_ci break; 162262306a36Sopenharmony_ci case ixgbe_sfp_type_srlr_core0: 162362306a36Sopenharmony_ci case ixgbe_sfp_type_srlr_core1: 162462306a36Sopenharmony_ci case ixgbe_sfp_type_da_act_lmt_core0: 162562306a36Sopenharmony_ci case ixgbe_sfp_type_da_act_lmt_core1: 162662306a36Sopenharmony_ci case ixgbe_sfp_type_1g_sx_core0: 162762306a36Sopenharmony_ci case ixgbe_sfp_type_1g_sx_core1: 162862306a36Sopenharmony_ci case ixgbe_sfp_type_1g_lx_core0: 162962306a36Sopenharmony_ci case ixgbe_sfp_type_1g_lx_core1: 163062306a36Sopenharmony_ci *linear = false; 163162306a36Sopenharmony_ci break; 163262306a36Sopenharmony_ci case ixgbe_sfp_type_unknown: 163362306a36Sopenharmony_ci case ixgbe_sfp_type_1g_cu_core0: 163462306a36Sopenharmony_ci case ixgbe_sfp_type_1g_cu_core1: 163562306a36Sopenharmony_ci default: 163662306a36Sopenharmony_ci return -EOPNOTSUPP; 163762306a36Sopenharmony_ci } 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci return 0; 164062306a36Sopenharmony_ci} 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci/** 164362306a36Sopenharmony_ci * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. 164462306a36Sopenharmony_ci * @hw: pointer to hardware structure 164562306a36Sopenharmony_ci * @speed: the link speed to force 164662306a36Sopenharmony_ci * @autoneg_wait_to_complete: unused 164762306a36Sopenharmony_ci * 164862306a36Sopenharmony_ci * Configures the extern PHY and the integrated KR PHY for SFP support. 164962306a36Sopenharmony_ci */ 165062306a36Sopenharmony_cistatic s32 165162306a36Sopenharmony_ciixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, 165262306a36Sopenharmony_ci ixgbe_link_speed speed, 165362306a36Sopenharmony_ci __always_unused bool autoneg_wait_to_complete) 165462306a36Sopenharmony_ci{ 165562306a36Sopenharmony_ci s32 status; 165662306a36Sopenharmony_ci u16 reg_slice, reg_val; 165762306a36Sopenharmony_ci bool setup_linear = false; 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci /* Check if SFP module is supported and linear */ 166062306a36Sopenharmony_ci status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci /* If no SFP module present, then return success. Return success since 166362306a36Sopenharmony_ci * there is no reason to configure CS4227 and SFP not present error is 166462306a36Sopenharmony_ci * not accepted in the setup MAC link flow. 166562306a36Sopenharmony_ci */ 166662306a36Sopenharmony_ci if (status == -ENOENT) 166762306a36Sopenharmony_ci return 0; 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci if (status) 167062306a36Sopenharmony_ci return status; 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci /* Configure internal PHY for KR/KX. */ 167362306a36Sopenharmony_ci ixgbe_setup_kr_speed_x550em(hw, speed); 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci /* Configure CS4227 LINE side to proper mode. */ 167662306a36Sopenharmony_ci reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 167762306a36Sopenharmony_ci if (setup_linear) 167862306a36Sopenharmony_ci reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; 167962306a36Sopenharmony_ci else 168062306a36Sopenharmony_ci reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, 168362306a36Sopenharmony_ci reg_val); 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci return status; 168662306a36Sopenharmony_ci} 168762306a36Sopenharmony_ci 168862306a36Sopenharmony_ci/** 168962306a36Sopenharmony_ci * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode 169062306a36Sopenharmony_ci * @hw: pointer to hardware structure 169162306a36Sopenharmony_ci * @speed: the link speed to force 169262306a36Sopenharmony_ci * 169362306a36Sopenharmony_ci * Configures the integrated PHY for native SFI mode. Used to connect the 169462306a36Sopenharmony_ci * internal PHY directly to an SFP cage, without autonegotiation. 169562306a36Sopenharmony_ci **/ 169662306a36Sopenharmony_cistatic s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 169762306a36Sopenharmony_ci{ 169862306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 169962306a36Sopenharmony_ci s32 status; 170062306a36Sopenharmony_ci u32 reg_val; 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci /* Disable all AN and force speed to 10G Serial. */ 170362306a36Sopenharmony_ci status = mac->ops.read_iosf_sb_reg(hw, 170462306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 170562306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 170662306a36Sopenharmony_ci if (status) 170762306a36Sopenharmony_ci return status; 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 171062306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 171162306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 171262306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci /* Select forced link speed for internal PHY. */ 171562306a36Sopenharmony_ci switch (*speed) { 171662306a36Sopenharmony_ci case IXGBE_LINK_SPEED_10GB_FULL: 171762306a36Sopenharmony_ci reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G; 171862306a36Sopenharmony_ci break; 171962306a36Sopenharmony_ci case IXGBE_LINK_SPEED_1GB_FULL: 172062306a36Sopenharmony_ci reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; 172162306a36Sopenharmony_ci break; 172262306a36Sopenharmony_ci default: 172362306a36Sopenharmony_ci /* Other link speeds are not supported by internal PHY. */ 172462306a36Sopenharmony_ci return -EINVAL; 172562306a36Sopenharmony_ci } 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci (void)mac->ops.write_iosf_sb_reg(hw, 172862306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 172962306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci /* change mode enforcement rules to hybrid */ 173262306a36Sopenharmony_ci (void)mac->ops.read_iosf_sb_reg(hw, 173362306a36Sopenharmony_ci IXGBE_KRM_FLX_TMRS_CTRL_ST31(hw->bus.lan_id), 173462306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 173562306a36Sopenharmony_ci reg_val |= 0x0400; 173662306a36Sopenharmony_ci 173762306a36Sopenharmony_ci (void)mac->ops.write_iosf_sb_reg(hw, 173862306a36Sopenharmony_ci IXGBE_KRM_FLX_TMRS_CTRL_ST31(hw->bus.lan_id), 173962306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci /* manually control the config */ 174262306a36Sopenharmony_ci (void)mac->ops.read_iosf_sb_reg(hw, 174362306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 174462306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 174562306a36Sopenharmony_ci reg_val |= 0x20002240; 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci (void)mac->ops.write_iosf_sb_reg(hw, 174862306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 174962306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ci /* move the AN base page values */ 175262306a36Sopenharmony_ci (void)mac->ops.read_iosf_sb_reg(hw, 175362306a36Sopenharmony_ci IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id), 175462306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 175562306a36Sopenharmony_ci reg_val |= 0x1; 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci (void)mac->ops.write_iosf_sb_reg(hw, 175862306a36Sopenharmony_ci IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id), 175962306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci /* set the AN37 over CB mode */ 176262306a36Sopenharmony_ci (void)mac->ops.read_iosf_sb_reg(hw, 176362306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_4(hw->bus.lan_id), 176462306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 176562306a36Sopenharmony_ci reg_val |= 0x20000000; 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci (void)mac->ops.write_iosf_sb_reg(hw, 176862306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_4(hw->bus.lan_id), 176962306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci /* restart AN manually */ 177262306a36Sopenharmony_ci (void)mac->ops.read_iosf_sb_reg(hw, 177362306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 177462306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 177562306a36Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci (void)mac->ops.write_iosf_sb_reg(hw, 177862306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 177962306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci /* Toggle port SW reset by AN reset. */ 178262306a36Sopenharmony_ci status = ixgbe_restart_an_internal_phy_x550em(hw); 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci return status; 178562306a36Sopenharmony_ci} 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci/** 178862306a36Sopenharmony_ci * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP 178962306a36Sopenharmony_ci * @hw: pointer to hardware structure 179062306a36Sopenharmony_ci * @speed: link speed 179162306a36Sopenharmony_ci * @autoneg_wait_to_complete: unused 179262306a36Sopenharmony_ci * 179362306a36Sopenharmony_ci * Configure the integrated PHY for native SFP support. 179462306a36Sopenharmony_ci */ 179562306a36Sopenharmony_cistatic s32 179662306a36Sopenharmony_ciixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, 179762306a36Sopenharmony_ci __always_unused bool autoneg_wait_to_complete) 179862306a36Sopenharmony_ci{ 179962306a36Sopenharmony_ci bool setup_linear = false; 180062306a36Sopenharmony_ci u32 reg_phy_int; 180162306a36Sopenharmony_ci s32 ret_val; 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci /* Check if SFP module is supported and linear */ 180462306a36Sopenharmony_ci ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci /* If no SFP module present, then return success. Return success since 180762306a36Sopenharmony_ci * SFP not present error is not excepted in the setup MAC link flow. 180862306a36Sopenharmony_ci */ 180962306a36Sopenharmony_ci if (ret_val == -ENOENT) 181062306a36Sopenharmony_ci return 0; 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci if (ret_val) 181362306a36Sopenharmony_ci return ret_val; 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci /* Configure internal PHY for native SFI based on module type */ 181662306a36Sopenharmony_ci ret_val = hw->mac.ops.read_iosf_sb_reg(hw, 181762306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 181862306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int); 181962306a36Sopenharmony_ci if (ret_val) 182062306a36Sopenharmony_ci return ret_val; 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA; 182362306a36Sopenharmony_ci if (!setup_linear) 182462306a36Sopenharmony_ci reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR; 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci ret_val = hw->mac.ops.write_iosf_sb_reg(hw, 182762306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 182862306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int); 182962306a36Sopenharmony_ci if (ret_val) 183062306a36Sopenharmony_ci return ret_val; 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci /* Setup SFI internal link. */ 183362306a36Sopenharmony_ci return ixgbe_setup_sfi_x550a(hw, &speed); 183462306a36Sopenharmony_ci} 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci/** 183762306a36Sopenharmony_ci * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP 183862306a36Sopenharmony_ci * @hw: pointer to hardware structure 183962306a36Sopenharmony_ci * @speed: link speed 184062306a36Sopenharmony_ci * @autoneg_wait_to_complete: unused 184162306a36Sopenharmony_ci * 184262306a36Sopenharmony_ci * Configure the integrated PHY for SFP support. 184362306a36Sopenharmony_ci */ 184462306a36Sopenharmony_cistatic s32 184562306a36Sopenharmony_ciixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, 184662306a36Sopenharmony_ci __always_unused bool autoneg_wait_to_complete) 184762306a36Sopenharmony_ci{ 184862306a36Sopenharmony_ci u32 reg_slice, slice_offset; 184962306a36Sopenharmony_ci bool setup_linear = false; 185062306a36Sopenharmony_ci u16 reg_phy_ext; 185162306a36Sopenharmony_ci s32 ret_val; 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci /* Check if SFP module is supported and linear */ 185462306a36Sopenharmony_ci ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci /* If no SFP module present, then return success. Return success since 185762306a36Sopenharmony_ci * SFP not present error is not excepted in the setup MAC link flow. 185862306a36Sopenharmony_ci */ 185962306a36Sopenharmony_ci if (ret_val == -ENOENT) 186062306a36Sopenharmony_ci return 0; 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci if (ret_val) 186362306a36Sopenharmony_ci return ret_val; 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_ci /* Configure internal PHY for KR/KX. */ 186662306a36Sopenharmony_ci ixgbe_setup_kr_speed_x550em(hw, speed); 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE) 186962306a36Sopenharmony_ci return -EFAULT; 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci /* Get external PHY SKU id */ 187262306a36Sopenharmony_ci ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU, 187362306a36Sopenharmony_ci IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 187462306a36Sopenharmony_ci if (ret_val) 187562306a36Sopenharmony_ci return ret_val; 187662306a36Sopenharmony_ci 187762306a36Sopenharmony_ci /* When configuring quad port CS4223, the MAC instance is part 187862306a36Sopenharmony_ci * of the slice offset. 187962306a36Sopenharmony_ci */ 188062306a36Sopenharmony_ci if (reg_phy_ext == IXGBE_CS4223_SKU_ID) 188162306a36Sopenharmony_ci slice_offset = (hw->bus.lan_id + 188262306a36Sopenharmony_ci (hw->bus.instance_id << 1)) << 12; 188362306a36Sopenharmony_ci else 188462306a36Sopenharmony_ci slice_offset = hw->bus.lan_id << 12; 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci /* Configure CS4227/CS4223 LINE side to proper mode. */ 188762306a36Sopenharmony_ci reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci ret_val = hw->phy.ops.read_reg(hw, reg_slice, 189062306a36Sopenharmony_ci IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 189162306a36Sopenharmony_ci if (ret_val) 189262306a36Sopenharmony_ci return ret_val; 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) | 189562306a36Sopenharmony_ci (IXGBE_CS4227_EDC_MODE_SR << 1)); 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci if (setup_linear) 189862306a36Sopenharmony_ci reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 189962306a36Sopenharmony_ci else 190062306a36Sopenharmony_ci reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci ret_val = hw->phy.ops.write_reg(hw, reg_slice, 190362306a36Sopenharmony_ci IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext); 190462306a36Sopenharmony_ci if (ret_val) 190562306a36Sopenharmony_ci return ret_val; 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci /* Flush previous write with a read */ 190862306a36Sopenharmony_ci return hw->phy.ops.read_reg(hw, reg_slice, 190962306a36Sopenharmony_ci IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 191062306a36Sopenharmony_ci} 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci/** 191362306a36Sopenharmony_ci * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 191462306a36Sopenharmony_ci * @hw: pointer to hardware structure 191562306a36Sopenharmony_ci * @speed: new link speed 191662306a36Sopenharmony_ci * @autoneg_wait: true when waiting for completion is needed 191762306a36Sopenharmony_ci * 191862306a36Sopenharmony_ci * Setup internal/external PHY link speed based on link speed, then set 191962306a36Sopenharmony_ci * external PHY auto advertised link speed. 192062306a36Sopenharmony_ci * 192162306a36Sopenharmony_ci * Returns error status for any failure 192262306a36Sopenharmony_ci **/ 192362306a36Sopenharmony_cistatic s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 192462306a36Sopenharmony_ci ixgbe_link_speed speed, 192562306a36Sopenharmony_ci bool autoneg_wait) 192662306a36Sopenharmony_ci{ 192762306a36Sopenharmony_ci s32 status; 192862306a36Sopenharmony_ci ixgbe_link_speed force_speed; 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci /* Setup internal/external PHY link speed to iXFI (10G), unless 193162306a36Sopenharmony_ci * only 1G is auto advertised then setup KX link. 193262306a36Sopenharmony_ci */ 193362306a36Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_10GB_FULL) 193462306a36Sopenharmony_ci force_speed = IXGBE_LINK_SPEED_10GB_FULL; 193562306a36Sopenharmony_ci else 193662306a36Sopenharmony_ci force_speed = IXGBE_LINK_SPEED_1GB_FULL; 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_ci /* If X552 and internal link mode is XFI, then setup XFI internal link. 193962306a36Sopenharmony_ci */ 194062306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_X550EM_x && 194162306a36Sopenharmony_ci !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 194262306a36Sopenharmony_ci status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci if (status) 194562306a36Sopenharmony_ci return status; 194662306a36Sopenharmony_ci } 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_ci return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 194962306a36Sopenharmony_ci} 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci/** ixgbe_check_link_t_X550em - Determine link and speed status 195262306a36Sopenharmony_ci * @hw: pointer to hardware structure 195362306a36Sopenharmony_ci * @speed: pointer to link speed 195462306a36Sopenharmony_ci * @link_up: true when link is up 195562306a36Sopenharmony_ci * @link_up_wait_to_complete: bool used to wait for link up or not 195662306a36Sopenharmony_ci * 195762306a36Sopenharmony_ci * Check that both the MAC and X557 external PHY have link. 195862306a36Sopenharmony_ci **/ 195962306a36Sopenharmony_cistatic s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, 196062306a36Sopenharmony_ci ixgbe_link_speed *speed, 196162306a36Sopenharmony_ci bool *link_up, 196262306a36Sopenharmony_ci bool link_up_wait_to_complete) 196362306a36Sopenharmony_ci{ 196462306a36Sopenharmony_ci u32 status; 196562306a36Sopenharmony_ci u16 i, autoneg_status; 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 196862306a36Sopenharmony_ci return -EIO; 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci status = ixgbe_check_mac_link_generic(hw, speed, link_up, 197162306a36Sopenharmony_ci link_up_wait_to_complete); 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_ci /* If check link fails or MAC link is not up, then return */ 197462306a36Sopenharmony_ci if (status || !(*link_up)) 197562306a36Sopenharmony_ci return status; 197662306a36Sopenharmony_ci 197762306a36Sopenharmony_ci /* MAC link is up, so check external PHY link. 197862306a36Sopenharmony_ci * Link status is latching low, and can only be used to detect link 197962306a36Sopenharmony_ci * drop, and not the current status of the link without performing 198062306a36Sopenharmony_ci * back-to-back reads. 198162306a36Sopenharmony_ci */ 198262306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 198362306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 198462306a36Sopenharmony_ci &autoneg_status); 198562306a36Sopenharmony_ci 198662306a36Sopenharmony_ci if (status) 198762306a36Sopenharmony_ci return status; 198862306a36Sopenharmony_ci } 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci /* If external PHY link is not up, then indicate link not up */ 199162306a36Sopenharmony_ci if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 199262306a36Sopenharmony_ci *link_up = false; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci return 0; 199562306a36Sopenharmony_ci} 199662306a36Sopenharmony_ci 199762306a36Sopenharmony_ci/** 199862306a36Sopenharmony_ci * ixgbe_setup_sgmii - Set up link for sgmii 199962306a36Sopenharmony_ci * @hw: pointer to hardware structure 200062306a36Sopenharmony_ci * @speed: unused 200162306a36Sopenharmony_ci * @autoneg_wait_to_complete: unused 200262306a36Sopenharmony_ci */ 200362306a36Sopenharmony_cistatic s32 200462306a36Sopenharmony_ciixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, 200562306a36Sopenharmony_ci __always_unused bool autoneg_wait_to_complete) 200662306a36Sopenharmony_ci{ 200762306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 200862306a36Sopenharmony_ci u32 lval, sval, flx_val; 200962306a36Sopenharmony_ci s32 rc; 201062306a36Sopenharmony_ci 201162306a36Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 201262306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 201362306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 201462306a36Sopenharmony_ci if (rc) 201562306a36Sopenharmony_ci return rc; 201662306a36Sopenharmony_ci 201762306a36Sopenharmony_ci lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 201862306a36Sopenharmony_ci lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 201962306a36Sopenharmony_ci lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 202062306a36Sopenharmony_ci lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 202162306a36Sopenharmony_ci lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 202262306a36Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 202362306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 202462306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 202562306a36Sopenharmony_ci if (rc) 202662306a36Sopenharmony_ci return rc; 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 202962306a36Sopenharmony_ci IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 203062306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 203162306a36Sopenharmony_ci if (rc) 203262306a36Sopenharmony_ci return rc; 203362306a36Sopenharmony_ci 203462306a36Sopenharmony_ci sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 203562306a36Sopenharmony_ci sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 203662306a36Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 203762306a36Sopenharmony_ci IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 203862306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 203962306a36Sopenharmony_ci if (rc) 204062306a36Sopenharmony_ci return rc; 204162306a36Sopenharmony_ci 204262306a36Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 204362306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 204462306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 204562306a36Sopenharmony_ci if (rc) 204662306a36Sopenharmony_ci return rc; 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 204962306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 205062306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 205162306a36Sopenharmony_ci if (rc) 205262306a36Sopenharmony_ci return rc; 205362306a36Sopenharmony_ci 205462306a36Sopenharmony_ci flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 205562306a36Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; 205662306a36Sopenharmony_ci flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 205762306a36Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 205862306a36Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 206162306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 206262306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); 206362306a36Sopenharmony_ci if (rc) 206462306a36Sopenharmony_ci return rc; 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci rc = ixgbe_restart_an_internal_phy_x550em(hw); 206762306a36Sopenharmony_ci return rc; 206862306a36Sopenharmony_ci} 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci/** 207162306a36Sopenharmony_ci * ixgbe_setup_sgmii_fw - Set up link for sgmii with firmware-controlled PHYs 207262306a36Sopenharmony_ci * @hw: pointer to hardware structure 207362306a36Sopenharmony_ci * @speed: the link speed to force 207462306a36Sopenharmony_ci * @autoneg_wait: true when waiting for completion is needed 207562306a36Sopenharmony_ci */ 207662306a36Sopenharmony_cistatic s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed, 207762306a36Sopenharmony_ci bool autoneg_wait) 207862306a36Sopenharmony_ci{ 207962306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 208062306a36Sopenharmony_ci u32 lval, sval, flx_val; 208162306a36Sopenharmony_ci s32 rc; 208262306a36Sopenharmony_ci 208362306a36Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 208462306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 208562306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 208662306a36Sopenharmony_ci if (rc) 208762306a36Sopenharmony_ci return rc; 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 209062306a36Sopenharmony_ci lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 209162306a36Sopenharmony_ci lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 209262306a36Sopenharmony_ci lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 209362306a36Sopenharmony_ci lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 209462306a36Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 209562306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 209662306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 209762306a36Sopenharmony_ci if (rc) 209862306a36Sopenharmony_ci return rc; 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 210162306a36Sopenharmony_ci IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 210262306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 210362306a36Sopenharmony_ci if (rc) 210462306a36Sopenharmony_ci return rc; 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 210762306a36Sopenharmony_ci sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 210862306a36Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 210962306a36Sopenharmony_ci IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 211062306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 211162306a36Sopenharmony_ci if (rc) 211262306a36Sopenharmony_ci return rc; 211362306a36Sopenharmony_ci 211462306a36Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 211562306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 211662306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 211762306a36Sopenharmony_ci if (rc) 211862306a36Sopenharmony_ci return rc; 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 212162306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 212262306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 212362306a36Sopenharmony_ci if (rc) 212462306a36Sopenharmony_ci return rc; 212562306a36Sopenharmony_ci 212662306a36Sopenharmony_ci flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 212762306a36Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; 212862306a36Sopenharmony_ci flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 212962306a36Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 213062306a36Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 213162306a36Sopenharmony_ci 213262306a36Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 213362306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 213462306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); 213562306a36Sopenharmony_ci if (rc) 213662306a36Sopenharmony_ci return rc; 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_ci ixgbe_restart_an_internal_phy_x550em(hw); 213962306a36Sopenharmony_ci 214062306a36Sopenharmony_ci return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 214162306a36Sopenharmony_ci} 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci/** 214462306a36Sopenharmony_ci * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37 214562306a36Sopenharmony_ci * @hw: pointer to hardware structure 214662306a36Sopenharmony_ci * 214762306a36Sopenharmony_ci * Enable flow control according to IEEE clause 37. 214862306a36Sopenharmony_ci */ 214962306a36Sopenharmony_cistatic void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw) 215062306a36Sopenharmony_ci{ 215162306a36Sopenharmony_ci u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 }; 215262306a36Sopenharmony_ci ixgbe_link_speed speed; 215362306a36Sopenharmony_ci s32 status = -EIO; 215462306a36Sopenharmony_ci bool link_up; 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_ci /* AN should have completed when the cable was plugged in. 215762306a36Sopenharmony_ci * Look for reasons to bail out. Bail out if: 215862306a36Sopenharmony_ci * - FC autoneg is disabled, or if 215962306a36Sopenharmony_ci * - link is not up. 216062306a36Sopenharmony_ci */ 216162306a36Sopenharmony_ci if (hw->fc.disable_fc_autoneg) 216262306a36Sopenharmony_ci goto out; 216362306a36Sopenharmony_ci 216462306a36Sopenharmony_ci hw->mac.ops.check_link(hw, &speed, &link_up, false); 216562306a36Sopenharmony_ci if (!link_up) 216662306a36Sopenharmony_ci goto out; 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci /* Check if auto-negotiation has completed */ 216962306a36Sopenharmony_ci status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info); 217062306a36Sopenharmony_ci if (status || !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) { 217162306a36Sopenharmony_ci status = -EIO; 217262306a36Sopenharmony_ci goto out; 217362306a36Sopenharmony_ci } 217462306a36Sopenharmony_ci 217562306a36Sopenharmony_ci /* Negotiate the flow control */ 217662306a36Sopenharmony_ci status = ixgbe_negotiate_fc(hw, info[0], info[0], 217762306a36Sopenharmony_ci FW_PHY_ACT_GET_LINK_INFO_FC_RX, 217862306a36Sopenharmony_ci FW_PHY_ACT_GET_LINK_INFO_FC_TX, 217962306a36Sopenharmony_ci FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX, 218062306a36Sopenharmony_ci FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX); 218162306a36Sopenharmony_ci 218262306a36Sopenharmony_ciout: 218362306a36Sopenharmony_ci if (!status) { 218462306a36Sopenharmony_ci hw->fc.fc_was_autonegged = true; 218562306a36Sopenharmony_ci } else { 218662306a36Sopenharmony_ci hw->fc.fc_was_autonegged = false; 218762306a36Sopenharmony_ci hw->fc.current_mode = hw->fc.requested_mode; 218862306a36Sopenharmony_ci } 218962306a36Sopenharmony_ci} 219062306a36Sopenharmony_ci 219162306a36Sopenharmony_ci/** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers 219262306a36Sopenharmony_ci * @hw: pointer to hardware structure 219362306a36Sopenharmony_ci **/ 219462306a36Sopenharmony_cistatic void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw) 219562306a36Sopenharmony_ci{ 219662306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci switch (mac->ops.get_media_type(hw)) { 219962306a36Sopenharmony_ci case ixgbe_media_type_fiber: 220062306a36Sopenharmony_ci mac->ops.setup_fc = NULL; 220162306a36Sopenharmony_ci mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; 220262306a36Sopenharmony_ci break; 220362306a36Sopenharmony_ci case ixgbe_media_type_copper: 220462306a36Sopenharmony_ci if (hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T && 220562306a36Sopenharmony_ci hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T_L) { 220662306a36Sopenharmony_ci mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 220762306a36Sopenharmony_ci break; 220862306a36Sopenharmony_ci } 220962306a36Sopenharmony_ci mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a; 221062306a36Sopenharmony_ci mac->ops.setup_fc = ixgbe_fc_autoneg_fw; 221162306a36Sopenharmony_ci mac->ops.setup_link = ixgbe_setup_sgmii_fw; 221262306a36Sopenharmony_ci mac->ops.check_link = ixgbe_check_mac_link_generic; 221362306a36Sopenharmony_ci break; 221462306a36Sopenharmony_ci case ixgbe_media_type_backplane: 221562306a36Sopenharmony_ci mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; 221662306a36Sopenharmony_ci mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; 221762306a36Sopenharmony_ci break; 221862306a36Sopenharmony_ci default: 221962306a36Sopenharmony_ci break; 222062306a36Sopenharmony_ci } 222162306a36Sopenharmony_ci} 222262306a36Sopenharmony_ci 222362306a36Sopenharmony_ci/** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 222462306a36Sopenharmony_ci * @hw: pointer to hardware structure 222562306a36Sopenharmony_ci **/ 222662306a36Sopenharmony_cistatic void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 222762306a36Sopenharmony_ci{ 222862306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ci mac->ops.setup_fc = ixgbe_setup_fc_x550em; 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_ci switch (mac->ops.get_media_type(hw)) { 223362306a36Sopenharmony_ci case ixgbe_media_type_fiber: 223462306a36Sopenharmony_ci /* CS4227 does not support autoneg, so disable the laser control 223562306a36Sopenharmony_ci * functions for SFP+ fiber 223662306a36Sopenharmony_ci */ 223762306a36Sopenharmony_ci mac->ops.disable_tx_laser = NULL; 223862306a36Sopenharmony_ci mac->ops.enable_tx_laser = NULL; 223962306a36Sopenharmony_ci mac->ops.flap_tx_laser = NULL; 224062306a36Sopenharmony_ci mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; 224162306a36Sopenharmony_ci switch (hw->device_id) { 224262306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP_N: 224362306a36Sopenharmony_ci mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; 224462306a36Sopenharmony_ci break; 224562306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP: 224662306a36Sopenharmony_ci mac->ops.setup_mac_link = 224762306a36Sopenharmony_ci ixgbe_setup_mac_link_sfp_x550a; 224862306a36Sopenharmony_ci break; 224962306a36Sopenharmony_ci default: 225062306a36Sopenharmony_ci mac->ops.setup_mac_link = 225162306a36Sopenharmony_ci ixgbe_setup_mac_link_sfp_x550em; 225262306a36Sopenharmony_ci break; 225362306a36Sopenharmony_ci } 225462306a36Sopenharmony_ci mac->ops.set_rate_select_speed = 225562306a36Sopenharmony_ci ixgbe_set_soft_rate_select_speed; 225662306a36Sopenharmony_ci break; 225762306a36Sopenharmony_ci case ixgbe_media_type_copper: 225862306a36Sopenharmony_ci if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T) 225962306a36Sopenharmony_ci break; 226062306a36Sopenharmony_ci mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 226162306a36Sopenharmony_ci mac->ops.setup_fc = ixgbe_setup_fc_generic; 226262306a36Sopenharmony_ci mac->ops.check_link = ixgbe_check_link_t_X550em; 226362306a36Sopenharmony_ci break; 226462306a36Sopenharmony_ci case ixgbe_media_type_backplane: 226562306a36Sopenharmony_ci if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || 226662306a36Sopenharmony_ci hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) 226762306a36Sopenharmony_ci mac->ops.setup_link = ixgbe_setup_sgmii; 226862306a36Sopenharmony_ci break; 226962306a36Sopenharmony_ci default: 227062306a36Sopenharmony_ci break; 227162306a36Sopenharmony_ci } 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_ci /* Additional modification for X550em_a devices */ 227462306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_x550em_a) 227562306a36Sopenharmony_ci ixgbe_init_mac_link_ops_X550em_a(hw); 227662306a36Sopenharmony_ci} 227762306a36Sopenharmony_ci 227862306a36Sopenharmony_ci/** ixgbe_setup_sfp_modules_X550em - Setup SFP module 227962306a36Sopenharmony_ci * @hw: pointer to hardware structure 228062306a36Sopenharmony_ci */ 228162306a36Sopenharmony_cistatic s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 228262306a36Sopenharmony_ci{ 228362306a36Sopenharmony_ci s32 status; 228462306a36Sopenharmony_ci bool linear; 228562306a36Sopenharmony_ci 228662306a36Sopenharmony_ci /* Check if SFP module is supported */ 228762306a36Sopenharmony_ci status = ixgbe_supported_sfp_modules_X550em(hw, &linear); 228862306a36Sopenharmony_ci if (status) 228962306a36Sopenharmony_ci return status; 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci ixgbe_init_mac_link_ops_X550em(hw); 229262306a36Sopenharmony_ci hw->phy.ops.reset = NULL; 229362306a36Sopenharmony_ci 229462306a36Sopenharmony_ci return 0; 229562306a36Sopenharmony_ci} 229662306a36Sopenharmony_ci 229762306a36Sopenharmony_ci/** ixgbe_get_link_capabilities_x550em - Determines link capabilities 229862306a36Sopenharmony_ci * @hw: pointer to hardware structure 229962306a36Sopenharmony_ci * @speed: pointer to link speed 230062306a36Sopenharmony_ci * @autoneg: true when autoneg or autotry is enabled 230162306a36Sopenharmony_ci **/ 230262306a36Sopenharmony_cistatic s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 230362306a36Sopenharmony_ci ixgbe_link_speed *speed, 230462306a36Sopenharmony_ci bool *autoneg) 230562306a36Sopenharmony_ci{ 230662306a36Sopenharmony_ci if (hw->phy.type == ixgbe_phy_fw) { 230762306a36Sopenharmony_ci *autoneg = true; 230862306a36Sopenharmony_ci *speed = hw->phy.speeds_supported; 230962306a36Sopenharmony_ci return 0; 231062306a36Sopenharmony_ci } 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci /* SFP */ 231362306a36Sopenharmony_ci if (hw->phy.media_type == ixgbe_media_type_fiber) { 231462306a36Sopenharmony_ci /* CS4227 SFP must not enable auto-negotiation */ 231562306a36Sopenharmony_ci *autoneg = false; 231662306a36Sopenharmony_ci 231762306a36Sopenharmony_ci if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 231862306a36Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 || 231962306a36Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || 232062306a36Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) { 232162306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 232262306a36Sopenharmony_ci return 0; 232362306a36Sopenharmony_ci } 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_ci /* Link capabilities are based on SFP */ 232662306a36Sopenharmony_ci if (hw->phy.multispeed_fiber) 232762306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL | 232862306a36Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL; 232962306a36Sopenharmony_ci else 233062306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL; 233162306a36Sopenharmony_ci } else { 233262306a36Sopenharmony_ci switch (hw->phy.type) { 233362306a36Sopenharmony_ci case ixgbe_phy_x550em_kx4: 233462306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL | 233562306a36Sopenharmony_ci IXGBE_LINK_SPEED_2_5GB_FULL | 233662306a36Sopenharmony_ci IXGBE_LINK_SPEED_10GB_FULL; 233762306a36Sopenharmony_ci break; 233862306a36Sopenharmony_ci case ixgbe_phy_x550em_xfi: 233962306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL | 234062306a36Sopenharmony_ci IXGBE_LINK_SPEED_10GB_FULL; 234162306a36Sopenharmony_ci break; 234262306a36Sopenharmony_ci case ixgbe_phy_ext_1g_t: 234362306a36Sopenharmony_ci case ixgbe_phy_sgmii: 234462306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 234562306a36Sopenharmony_ci break; 234662306a36Sopenharmony_ci case ixgbe_phy_x550em_kr: 234762306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_x550em_a) { 234862306a36Sopenharmony_ci /* check different backplane modes */ 234962306a36Sopenharmony_ci if (hw->phy.nw_mng_if_sel & 235062306a36Sopenharmony_ci IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) { 235162306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 235262306a36Sopenharmony_ci break; 235362306a36Sopenharmony_ci } else if (hw->device_id == 235462306a36Sopenharmony_ci IXGBE_DEV_ID_X550EM_A_KR_L) { 235562306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 235662306a36Sopenharmony_ci break; 235762306a36Sopenharmony_ci } 235862306a36Sopenharmony_ci } 235962306a36Sopenharmony_ci fallthrough; 236062306a36Sopenharmony_ci default: 236162306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL | 236262306a36Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL; 236362306a36Sopenharmony_ci break; 236462306a36Sopenharmony_ci } 236562306a36Sopenharmony_ci *autoneg = true; 236662306a36Sopenharmony_ci } 236762306a36Sopenharmony_ci return 0; 236862306a36Sopenharmony_ci} 236962306a36Sopenharmony_ci 237062306a36Sopenharmony_ci/** 237162306a36Sopenharmony_ci * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause 237262306a36Sopenharmony_ci * @hw: pointer to hardware structure 237362306a36Sopenharmony_ci * @lsc: pointer to boolean flag which indicates whether external Base T 237462306a36Sopenharmony_ci * PHY interrupt is lsc 237562306a36Sopenharmony_ci * @is_overtemp: indicate whether an overtemp event encountered 237662306a36Sopenharmony_ci * 237762306a36Sopenharmony_ci * Determime if external Base T PHY interrupt cause is high temperature 237862306a36Sopenharmony_ci * failure alarm or link status change. 237962306a36Sopenharmony_ci **/ 238062306a36Sopenharmony_cistatic s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc, 238162306a36Sopenharmony_ci bool *is_overtemp) 238262306a36Sopenharmony_ci{ 238362306a36Sopenharmony_ci u32 status; 238462306a36Sopenharmony_ci u16 reg; 238562306a36Sopenharmony_ci 238662306a36Sopenharmony_ci *is_overtemp = false; 238762306a36Sopenharmony_ci *lsc = false; 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci /* Vendor alarm triggered */ 239062306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 239162306a36Sopenharmony_ci MDIO_MMD_VEND1, 239262306a36Sopenharmony_ci ®); 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_ci if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 239562306a36Sopenharmony_ci return status; 239662306a36Sopenharmony_ci 239762306a36Sopenharmony_ci /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 239862306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 239962306a36Sopenharmony_ci MDIO_MMD_VEND1, 240062306a36Sopenharmony_ci ®); 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 240362306a36Sopenharmony_ci IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 240462306a36Sopenharmony_ci return status; 240562306a36Sopenharmony_ci 240662306a36Sopenharmony_ci /* Global alarm triggered */ 240762306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 240862306a36Sopenharmony_ci MDIO_MMD_VEND1, 240962306a36Sopenharmony_ci ®); 241062306a36Sopenharmony_ci 241162306a36Sopenharmony_ci if (status) 241262306a36Sopenharmony_ci return status; 241362306a36Sopenharmony_ci 241462306a36Sopenharmony_ci /* If high temperature failure, then return over temp error and exit */ 241562306a36Sopenharmony_ci if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 241662306a36Sopenharmony_ci /* power down the PHY in case the PHY FW didn't already */ 241762306a36Sopenharmony_ci ixgbe_set_copper_phy_power(hw, false); 241862306a36Sopenharmony_ci *is_overtemp = true; 241962306a36Sopenharmony_ci return -EIO; 242062306a36Sopenharmony_ci } 242162306a36Sopenharmony_ci if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { 242262306a36Sopenharmony_ci /* device fault alarm triggered */ 242362306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, 242462306a36Sopenharmony_ci MDIO_MMD_VEND1, 242562306a36Sopenharmony_ci ®); 242662306a36Sopenharmony_ci if (status) 242762306a36Sopenharmony_ci return status; 242862306a36Sopenharmony_ci 242962306a36Sopenharmony_ci /* if device fault was due to high temp alarm handle and exit */ 243062306a36Sopenharmony_ci if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { 243162306a36Sopenharmony_ci /* power down the PHY in case the PHY FW didn't */ 243262306a36Sopenharmony_ci ixgbe_set_copper_phy_power(hw, false); 243362306a36Sopenharmony_ci *is_overtemp = true; 243462306a36Sopenharmony_ci return -EIO; 243562306a36Sopenharmony_ci } 243662306a36Sopenharmony_ci } 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_ci /* Vendor alarm 2 triggered */ 243962306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 244062306a36Sopenharmony_ci MDIO_MMD_AN, ®); 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 244362306a36Sopenharmony_ci return status; 244462306a36Sopenharmony_ci 244562306a36Sopenharmony_ci /* link connect/disconnect event occurred */ 244662306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 244762306a36Sopenharmony_ci MDIO_MMD_AN, ®); 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci if (status) 245062306a36Sopenharmony_ci return status; 245162306a36Sopenharmony_ci 245262306a36Sopenharmony_ci /* Indicate LSC */ 245362306a36Sopenharmony_ci if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 245462306a36Sopenharmony_ci *lsc = true; 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_ci return 0; 245762306a36Sopenharmony_ci} 245862306a36Sopenharmony_ci 245962306a36Sopenharmony_ci/** 246062306a36Sopenharmony_ci * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 246162306a36Sopenharmony_ci * @hw: pointer to hardware structure 246262306a36Sopenharmony_ci * 246362306a36Sopenharmony_ci * Enable link status change and temperature failure alarm for the external 246462306a36Sopenharmony_ci * Base T PHY 246562306a36Sopenharmony_ci * 246662306a36Sopenharmony_ci * Returns PHY access status 246762306a36Sopenharmony_ci **/ 246862306a36Sopenharmony_cistatic s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 246962306a36Sopenharmony_ci{ 247062306a36Sopenharmony_ci bool lsc, overtemp; 247162306a36Sopenharmony_ci u32 status; 247262306a36Sopenharmony_ci u16 reg; 247362306a36Sopenharmony_ci 247462306a36Sopenharmony_ci /* Clear interrupt flags */ 247562306a36Sopenharmony_ci status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, &overtemp); 247662306a36Sopenharmony_ci 247762306a36Sopenharmony_ci /* Enable link status change alarm */ 247862306a36Sopenharmony_ci 247962306a36Sopenharmony_ci /* Enable the LASI interrupts on X552 devices to receive notifications 248062306a36Sopenharmony_ci * of the link configurations of the external PHY and correspondingly 248162306a36Sopenharmony_ci * support the configuration of the internal iXFI link, since iXFI does 248262306a36Sopenharmony_ci * not support auto-negotiation. This is not required for X553 devices 248362306a36Sopenharmony_ci * having KR support, which performs auto-negotiations and which is used 248462306a36Sopenharmony_ci * as the internal link to the external PHY. Hence adding a check here 248562306a36Sopenharmony_ci * to avoid enabling LASI interrupts for X553 devices. 248662306a36Sopenharmony_ci */ 248762306a36Sopenharmony_ci if (hw->mac.type != ixgbe_mac_x550em_a) { 248862306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, 248962306a36Sopenharmony_ci IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 249062306a36Sopenharmony_ci MDIO_MMD_AN, ®); 249162306a36Sopenharmony_ci if (status) 249262306a36Sopenharmony_ci return status; 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_ci reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_ci status = hw->phy.ops.write_reg(hw, 249762306a36Sopenharmony_ci IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 249862306a36Sopenharmony_ci MDIO_MMD_AN, reg); 249962306a36Sopenharmony_ci if (status) 250062306a36Sopenharmony_ci return status; 250162306a36Sopenharmony_ci } 250262306a36Sopenharmony_ci 250362306a36Sopenharmony_ci /* Enable high temperature failure and global fault alarms */ 250462306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 250562306a36Sopenharmony_ci MDIO_MMD_VEND1, 250662306a36Sopenharmony_ci ®); 250762306a36Sopenharmony_ci if (status) 250862306a36Sopenharmony_ci return status; 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_ci reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | 251162306a36Sopenharmony_ci IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); 251262306a36Sopenharmony_ci 251362306a36Sopenharmony_ci status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 251462306a36Sopenharmony_ci MDIO_MMD_VEND1, 251562306a36Sopenharmony_ci reg); 251662306a36Sopenharmony_ci if (status) 251762306a36Sopenharmony_ci return status; 251862306a36Sopenharmony_ci 251962306a36Sopenharmony_ci /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 252062306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 252162306a36Sopenharmony_ci MDIO_MMD_VEND1, 252262306a36Sopenharmony_ci ®); 252362306a36Sopenharmony_ci if (status) 252462306a36Sopenharmony_ci return status; 252562306a36Sopenharmony_ci 252662306a36Sopenharmony_ci reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 252762306a36Sopenharmony_ci IXGBE_MDIO_GLOBAL_ALARM_1_INT); 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_ci status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 253062306a36Sopenharmony_ci MDIO_MMD_VEND1, 253162306a36Sopenharmony_ci reg); 253262306a36Sopenharmony_ci if (status) 253362306a36Sopenharmony_ci return status; 253462306a36Sopenharmony_ci 253562306a36Sopenharmony_ci /* Enable chip-wide vendor alarm */ 253662306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 253762306a36Sopenharmony_ci MDIO_MMD_VEND1, 253862306a36Sopenharmony_ci ®); 253962306a36Sopenharmony_ci if (status) 254062306a36Sopenharmony_ci return status; 254162306a36Sopenharmony_ci 254262306a36Sopenharmony_ci reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 254362306a36Sopenharmony_ci 254462306a36Sopenharmony_ci status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 254562306a36Sopenharmony_ci MDIO_MMD_VEND1, 254662306a36Sopenharmony_ci reg); 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci return status; 254962306a36Sopenharmony_ci} 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ci/** 255262306a36Sopenharmony_ci * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 255362306a36Sopenharmony_ci * @hw: pointer to hardware structure 255462306a36Sopenharmony_ci * @is_overtemp: indicate whether an overtemp event encountered 255562306a36Sopenharmony_ci * 255662306a36Sopenharmony_ci * Handle external Base T PHY interrupt. If high temperature 255762306a36Sopenharmony_ci * failure alarm then return error, else if link status change 255862306a36Sopenharmony_ci * then setup internal/external PHY link 255962306a36Sopenharmony_ci **/ 256062306a36Sopenharmony_cistatic s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw, 256162306a36Sopenharmony_ci bool *is_overtemp) 256262306a36Sopenharmony_ci{ 256362306a36Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 256462306a36Sopenharmony_ci bool lsc; 256562306a36Sopenharmony_ci u32 status; 256662306a36Sopenharmony_ci 256762306a36Sopenharmony_ci status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, is_overtemp); 256862306a36Sopenharmony_ci if (status) 256962306a36Sopenharmony_ci return status; 257062306a36Sopenharmony_ci 257162306a36Sopenharmony_ci if (lsc && phy->ops.setup_internal_link) 257262306a36Sopenharmony_ci return phy->ops.setup_internal_link(hw); 257362306a36Sopenharmony_ci 257462306a36Sopenharmony_ci return 0; 257562306a36Sopenharmony_ci} 257662306a36Sopenharmony_ci 257762306a36Sopenharmony_ci/** 257862306a36Sopenharmony_ci * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 257962306a36Sopenharmony_ci * @hw: pointer to hardware structure 258062306a36Sopenharmony_ci * @speed: link speed 258162306a36Sopenharmony_ci * 258262306a36Sopenharmony_ci * Configures the integrated KR PHY. 258362306a36Sopenharmony_ci **/ 258462306a36Sopenharmony_cistatic s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 258562306a36Sopenharmony_ci ixgbe_link_speed speed) 258662306a36Sopenharmony_ci{ 258762306a36Sopenharmony_ci s32 status; 258862306a36Sopenharmony_ci u32 reg_val; 258962306a36Sopenharmony_ci 259062306a36Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 259162306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 259262306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 259362306a36Sopenharmony_ci if (status) 259462306a36Sopenharmony_ci return status; 259562306a36Sopenharmony_ci 259662306a36Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 259762306a36Sopenharmony_ci reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 259862306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_ci /* Advertise 10G support. */ 260162306a36Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_10GB_FULL) 260262306a36Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 260362306a36Sopenharmony_ci 260462306a36Sopenharmony_ci /* Advertise 1G support. */ 260562306a36Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_1GB_FULL) 260662306a36Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 260762306a36Sopenharmony_ci 260862306a36Sopenharmony_ci status = hw->mac.ops.write_iosf_sb_reg(hw, 260962306a36Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 261062306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 261162306a36Sopenharmony_ci 261262306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_x550em_a) { 261362306a36Sopenharmony_ci /* Set lane mode to KR auto negotiation */ 261462306a36Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 261562306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 261662306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ci if (status) 261962306a36Sopenharmony_ci return status; 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 262262306a36Sopenharmony_ci reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; 262362306a36Sopenharmony_ci reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 262462306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 262562306a36Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 262662306a36Sopenharmony_ci 262762306a36Sopenharmony_ci status = hw->mac.ops.write_iosf_sb_reg(hw, 262862306a36Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 262962306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 263062306a36Sopenharmony_ci } 263162306a36Sopenharmony_ci 263262306a36Sopenharmony_ci return ixgbe_restart_an_internal_phy_x550em(hw); 263362306a36Sopenharmony_ci} 263462306a36Sopenharmony_ci 263562306a36Sopenharmony_ci/** 263662306a36Sopenharmony_ci * ixgbe_setup_kr_x550em - Configure the KR PHY 263762306a36Sopenharmony_ci * @hw: pointer to hardware structure 263862306a36Sopenharmony_ci **/ 263962306a36Sopenharmony_cistatic s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 264062306a36Sopenharmony_ci{ 264162306a36Sopenharmony_ci /* leave link alone for 2.5G */ 264262306a36Sopenharmony_ci if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) 264362306a36Sopenharmony_ci return 0; 264462306a36Sopenharmony_ci 264562306a36Sopenharmony_ci if (ixgbe_check_reset_blocked(hw)) 264662306a36Sopenharmony_ci return 0; 264762306a36Sopenharmony_ci 264862306a36Sopenharmony_ci return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 264962306a36Sopenharmony_ci} 265062306a36Sopenharmony_ci 265162306a36Sopenharmony_ci/** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 265262306a36Sopenharmony_ci * @hw: address of hardware structure 265362306a36Sopenharmony_ci * @link_up: address of boolean to indicate link status 265462306a36Sopenharmony_ci * 265562306a36Sopenharmony_ci * Returns error code if unable to get link status. 265662306a36Sopenharmony_ci **/ 265762306a36Sopenharmony_cistatic s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 265862306a36Sopenharmony_ci{ 265962306a36Sopenharmony_ci u32 ret; 266062306a36Sopenharmony_ci u16 autoneg_status; 266162306a36Sopenharmony_ci 266262306a36Sopenharmony_ci *link_up = false; 266362306a36Sopenharmony_ci 266462306a36Sopenharmony_ci /* read this twice back to back to indicate current status */ 266562306a36Sopenharmony_ci ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 266662306a36Sopenharmony_ci &autoneg_status); 266762306a36Sopenharmony_ci if (ret) 266862306a36Sopenharmony_ci return ret; 266962306a36Sopenharmony_ci 267062306a36Sopenharmony_ci ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 267162306a36Sopenharmony_ci &autoneg_status); 267262306a36Sopenharmony_ci if (ret) 267362306a36Sopenharmony_ci return ret; 267462306a36Sopenharmony_ci 267562306a36Sopenharmony_ci *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 267662306a36Sopenharmony_ci 267762306a36Sopenharmony_ci return 0; 267862306a36Sopenharmony_ci} 267962306a36Sopenharmony_ci 268062306a36Sopenharmony_ci/** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 268162306a36Sopenharmony_ci * @hw: point to hardware structure 268262306a36Sopenharmony_ci * 268362306a36Sopenharmony_ci * Configures the link between the integrated KR PHY and the external X557 PHY 268462306a36Sopenharmony_ci * The driver will call this function when it gets a link status change 268562306a36Sopenharmony_ci * interrupt from the X557 PHY. This function configures the link speed 268662306a36Sopenharmony_ci * between the PHYs to match the link speed of the BASE-T link. 268762306a36Sopenharmony_ci * 268862306a36Sopenharmony_ci * A return of a non-zero value indicates an error, and the base driver should 268962306a36Sopenharmony_ci * not report link up. 269062306a36Sopenharmony_ci **/ 269162306a36Sopenharmony_cistatic s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 269262306a36Sopenharmony_ci{ 269362306a36Sopenharmony_ci ixgbe_link_speed force_speed; 269462306a36Sopenharmony_ci bool link_up; 269562306a36Sopenharmony_ci u32 status; 269662306a36Sopenharmony_ci u16 speed; 269762306a36Sopenharmony_ci 269862306a36Sopenharmony_ci if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 269962306a36Sopenharmony_ci return -EIO; 270062306a36Sopenharmony_ci 270162306a36Sopenharmony_ci if (!(hw->mac.type == ixgbe_mac_X550EM_x && 270262306a36Sopenharmony_ci !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))) { 270362306a36Sopenharmony_ci speed = IXGBE_LINK_SPEED_10GB_FULL | 270462306a36Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL; 270562306a36Sopenharmony_ci return ixgbe_setup_kr_speed_x550em(hw, speed); 270662306a36Sopenharmony_ci } 270762306a36Sopenharmony_ci 270862306a36Sopenharmony_ci /* If link is not up, then there is no setup necessary so return */ 270962306a36Sopenharmony_ci status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 271062306a36Sopenharmony_ci if (status) 271162306a36Sopenharmony_ci return status; 271262306a36Sopenharmony_ci 271362306a36Sopenharmony_ci if (!link_up) 271462306a36Sopenharmony_ci return 0; 271562306a36Sopenharmony_ci 271662306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 271762306a36Sopenharmony_ci MDIO_MMD_AN, 271862306a36Sopenharmony_ci &speed); 271962306a36Sopenharmony_ci if (status) 272062306a36Sopenharmony_ci return status; 272162306a36Sopenharmony_ci 272262306a36Sopenharmony_ci /* If link is not still up, then no setup is necessary so return */ 272362306a36Sopenharmony_ci status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 272462306a36Sopenharmony_ci if (status) 272562306a36Sopenharmony_ci return status; 272662306a36Sopenharmony_ci 272762306a36Sopenharmony_ci if (!link_up) 272862306a36Sopenharmony_ci return 0; 272962306a36Sopenharmony_ci 273062306a36Sopenharmony_ci /* clear everything but the speed and duplex bits */ 273162306a36Sopenharmony_ci speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 273262306a36Sopenharmony_ci 273362306a36Sopenharmony_ci switch (speed) { 273462306a36Sopenharmony_ci case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 273562306a36Sopenharmony_ci force_speed = IXGBE_LINK_SPEED_10GB_FULL; 273662306a36Sopenharmony_ci break; 273762306a36Sopenharmony_ci case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 273862306a36Sopenharmony_ci force_speed = IXGBE_LINK_SPEED_1GB_FULL; 273962306a36Sopenharmony_ci break; 274062306a36Sopenharmony_ci default: 274162306a36Sopenharmony_ci /* Internal PHY does not support anything else */ 274262306a36Sopenharmony_ci return -EINVAL; 274362306a36Sopenharmony_ci } 274462306a36Sopenharmony_ci 274562306a36Sopenharmony_ci return ixgbe_setup_ixfi_x550em(hw, &force_speed); 274662306a36Sopenharmony_ci} 274762306a36Sopenharmony_ci 274862306a36Sopenharmony_ci/** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 274962306a36Sopenharmony_ci * @hw: pointer to hardware structure 275062306a36Sopenharmony_ci **/ 275162306a36Sopenharmony_cistatic s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 275262306a36Sopenharmony_ci{ 275362306a36Sopenharmony_ci s32 status; 275462306a36Sopenharmony_ci 275562306a36Sopenharmony_ci status = ixgbe_reset_phy_generic(hw); 275662306a36Sopenharmony_ci 275762306a36Sopenharmony_ci if (status) 275862306a36Sopenharmony_ci return status; 275962306a36Sopenharmony_ci 276062306a36Sopenharmony_ci /* Configure Link Status Alarm and Temperature Threshold interrupts */ 276162306a36Sopenharmony_ci return ixgbe_enable_lasi_ext_t_x550em(hw); 276262306a36Sopenharmony_ci} 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci/** 276562306a36Sopenharmony_ci * ixgbe_led_on_t_x550em - Turns on the software controllable LEDs. 276662306a36Sopenharmony_ci * @hw: pointer to hardware structure 276762306a36Sopenharmony_ci * @led_idx: led number to turn on 276862306a36Sopenharmony_ci **/ 276962306a36Sopenharmony_cistatic s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 277062306a36Sopenharmony_ci{ 277162306a36Sopenharmony_ci u16 phy_data; 277262306a36Sopenharmony_ci 277362306a36Sopenharmony_ci if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 277462306a36Sopenharmony_ci return -EINVAL; 277562306a36Sopenharmony_ci 277662306a36Sopenharmony_ci /* To turn on the LED, set mode to ON. */ 277762306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 277862306a36Sopenharmony_ci MDIO_MMD_VEND1, &phy_data); 277962306a36Sopenharmony_ci phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; 278062306a36Sopenharmony_ci hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 278162306a36Sopenharmony_ci MDIO_MMD_VEND1, phy_data); 278262306a36Sopenharmony_ci 278362306a36Sopenharmony_ci return 0; 278462306a36Sopenharmony_ci} 278562306a36Sopenharmony_ci 278662306a36Sopenharmony_ci/** 278762306a36Sopenharmony_ci * ixgbe_led_off_t_x550em - Turns off the software controllable LEDs. 278862306a36Sopenharmony_ci * @hw: pointer to hardware structure 278962306a36Sopenharmony_ci * @led_idx: led number to turn off 279062306a36Sopenharmony_ci **/ 279162306a36Sopenharmony_cistatic s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 279262306a36Sopenharmony_ci{ 279362306a36Sopenharmony_ci u16 phy_data; 279462306a36Sopenharmony_ci 279562306a36Sopenharmony_ci if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 279662306a36Sopenharmony_ci return -EINVAL; 279762306a36Sopenharmony_ci 279862306a36Sopenharmony_ci /* To turn on the LED, set mode to ON. */ 279962306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 280062306a36Sopenharmony_ci MDIO_MMD_VEND1, &phy_data); 280162306a36Sopenharmony_ci phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; 280262306a36Sopenharmony_ci hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 280362306a36Sopenharmony_ci MDIO_MMD_VEND1, phy_data); 280462306a36Sopenharmony_ci 280562306a36Sopenharmony_ci return 0; 280662306a36Sopenharmony_ci} 280762306a36Sopenharmony_ci 280862306a36Sopenharmony_ci/** 280962306a36Sopenharmony_ci * ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware 281062306a36Sopenharmony_ci * @hw: pointer to the HW structure 281162306a36Sopenharmony_ci * @maj: driver version major number 281262306a36Sopenharmony_ci * @min: driver version minor number 281362306a36Sopenharmony_ci * @build: driver version build number 281462306a36Sopenharmony_ci * @sub: driver version sub build number 281562306a36Sopenharmony_ci * @len: length of driver_ver string 281662306a36Sopenharmony_ci * @driver_ver: driver string 281762306a36Sopenharmony_ci * 281862306a36Sopenharmony_ci * Sends driver version number to firmware through the manageability 281962306a36Sopenharmony_ci * block. On success return 0 282062306a36Sopenharmony_ci * else returns -EBUSY when encountering an error acquiring 282162306a36Sopenharmony_ci * semaphore, -EIO when command fails or -ENIVAL when incorrect 282262306a36Sopenharmony_ci * params passed. 282362306a36Sopenharmony_ci **/ 282462306a36Sopenharmony_cistatic s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min, 282562306a36Sopenharmony_ci u8 build, u8 sub, u16 len, 282662306a36Sopenharmony_ci const char *driver_ver) 282762306a36Sopenharmony_ci{ 282862306a36Sopenharmony_ci struct ixgbe_hic_drv_info2 fw_cmd; 282962306a36Sopenharmony_ci s32 ret_val; 283062306a36Sopenharmony_ci int i; 283162306a36Sopenharmony_ci 283262306a36Sopenharmony_ci if (!len || !driver_ver || (len > sizeof(fw_cmd.driver_string))) 283362306a36Sopenharmony_ci return -EINVAL; 283462306a36Sopenharmony_ci 283562306a36Sopenharmony_ci fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 283662306a36Sopenharmony_ci fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len; 283762306a36Sopenharmony_ci fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 283862306a36Sopenharmony_ci fw_cmd.port_num = (u8)hw->bus.func; 283962306a36Sopenharmony_ci fw_cmd.ver_maj = maj; 284062306a36Sopenharmony_ci fw_cmd.ver_min = min; 284162306a36Sopenharmony_ci fw_cmd.ver_build = build; 284262306a36Sopenharmony_ci fw_cmd.ver_sub = sub; 284362306a36Sopenharmony_ci fw_cmd.hdr.checksum = 0; 284462306a36Sopenharmony_ci memcpy(fw_cmd.driver_string, driver_ver, len); 284562306a36Sopenharmony_ci fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 284662306a36Sopenharmony_ci (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 284762306a36Sopenharmony_ci 284862306a36Sopenharmony_ci for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 284962306a36Sopenharmony_ci ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 285062306a36Sopenharmony_ci sizeof(fw_cmd), 285162306a36Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, 285262306a36Sopenharmony_ci true); 285362306a36Sopenharmony_ci if (ret_val) 285462306a36Sopenharmony_ci continue; 285562306a36Sopenharmony_ci 285662306a36Sopenharmony_ci if (fw_cmd.hdr.cmd_or_resp.ret_status != 285762306a36Sopenharmony_ci FW_CEM_RESP_STATUS_SUCCESS) 285862306a36Sopenharmony_ci return -EIO; 285962306a36Sopenharmony_ci return 0; 286062306a36Sopenharmony_ci } 286162306a36Sopenharmony_ci 286262306a36Sopenharmony_ci return ret_val; 286362306a36Sopenharmony_ci} 286462306a36Sopenharmony_ci 286562306a36Sopenharmony_ci/** ixgbe_get_lcd_x550em - Determine lowest common denominator 286662306a36Sopenharmony_ci * @hw: pointer to hardware structure 286762306a36Sopenharmony_ci * @lcd_speed: pointer to lowest common link speed 286862306a36Sopenharmony_ci * 286962306a36Sopenharmony_ci * Determine lowest common link speed with link partner. 287062306a36Sopenharmony_ci **/ 287162306a36Sopenharmony_cistatic s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, 287262306a36Sopenharmony_ci ixgbe_link_speed *lcd_speed) 287362306a36Sopenharmony_ci{ 287462306a36Sopenharmony_ci u16 an_lp_status; 287562306a36Sopenharmony_ci s32 status; 287662306a36Sopenharmony_ci u16 word = hw->eeprom.ctrl_word_3; 287762306a36Sopenharmony_ci 287862306a36Sopenharmony_ci *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; 287962306a36Sopenharmony_ci 288062306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, 288162306a36Sopenharmony_ci MDIO_MMD_AN, 288262306a36Sopenharmony_ci &an_lp_status); 288362306a36Sopenharmony_ci if (status) 288462306a36Sopenharmony_ci return status; 288562306a36Sopenharmony_ci 288662306a36Sopenharmony_ci /* If link partner advertised 1G, return 1G */ 288762306a36Sopenharmony_ci if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { 288862306a36Sopenharmony_ci *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; 288962306a36Sopenharmony_ci return status; 289062306a36Sopenharmony_ci } 289162306a36Sopenharmony_ci 289262306a36Sopenharmony_ci /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ 289362306a36Sopenharmony_ci if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || 289462306a36Sopenharmony_ci (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) 289562306a36Sopenharmony_ci return status; 289662306a36Sopenharmony_ci 289762306a36Sopenharmony_ci /* Link partner not capable of lower speeds, return 10G */ 289862306a36Sopenharmony_ci *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; 289962306a36Sopenharmony_ci return status; 290062306a36Sopenharmony_ci} 290162306a36Sopenharmony_ci 290262306a36Sopenharmony_ci/** 290362306a36Sopenharmony_ci * ixgbe_setup_fc_x550em - Set up flow control 290462306a36Sopenharmony_ci * @hw: pointer to hardware structure 290562306a36Sopenharmony_ci */ 290662306a36Sopenharmony_cistatic s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) 290762306a36Sopenharmony_ci{ 290862306a36Sopenharmony_ci bool pause, asm_dir; 290962306a36Sopenharmony_ci u32 reg_val; 291062306a36Sopenharmony_ci s32 rc = 0; 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_ci /* Validate the requested mode */ 291362306a36Sopenharmony_ci if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 291462306a36Sopenharmony_ci hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 291562306a36Sopenharmony_ci return -EINVAL; 291662306a36Sopenharmony_ci } 291762306a36Sopenharmony_ci 291862306a36Sopenharmony_ci /* 10gig parts do not have a word in the EEPROM to determine the 291962306a36Sopenharmony_ci * default flow control setting, so we explicitly set it to full. 292062306a36Sopenharmony_ci */ 292162306a36Sopenharmony_ci if (hw->fc.requested_mode == ixgbe_fc_default) 292262306a36Sopenharmony_ci hw->fc.requested_mode = ixgbe_fc_full; 292362306a36Sopenharmony_ci 292462306a36Sopenharmony_ci /* Determine PAUSE and ASM_DIR bits. */ 292562306a36Sopenharmony_ci switch (hw->fc.requested_mode) { 292662306a36Sopenharmony_ci case ixgbe_fc_none: 292762306a36Sopenharmony_ci pause = false; 292862306a36Sopenharmony_ci asm_dir = false; 292962306a36Sopenharmony_ci break; 293062306a36Sopenharmony_ci case ixgbe_fc_tx_pause: 293162306a36Sopenharmony_ci pause = false; 293262306a36Sopenharmony_ci asm_dir = true; 293362306a36Sopenharmony_ci break; 293462306a36Sopenharmony_ci case ixgbe_fc_rx_pause: 293562306a36Sopenharmony_ci /* Rx Flow control is enabled and Tx Flow control is 293662306a36Sopenharmony_ci * disabled by software override. Since there really 293762306a36Sopenharmony_ci * isn't a way to advertise that we are capable of RX 293862306a36Sopenharmony_ci * Pause ONLY, we will advertise that we support both 293962306a36Sopenharmony_ci * symmetric and asymmetric Rx PAUSE, as such we fall 294062306a36Sopenharmony_ci * through to the fc_full statement. Later, we will 294162306a36Sopenharmony_ci * disable the adapter's ability to send PAUSE frames. 294262306a36Sopenharmony_ci */ 294362306a36Sopenharmony_ci fallthrough; 294462306a36Sopenharmony_ci case ixgbe_fc_full: 294562306a36Sopenharmony_ci pause = true; 294662306a36Sopenharmony_ci asm_dir = true; 294762306a36Sopenharmony_ci break; 294862306a36Sopenharmony_ci default: 294962306a36Sopenharmony_ci hw_err(hw, "Flow control param set incorrectly\n"); 295062306a36Sopenharmony_ci return -EIO; 295162306a36Sopenharmony_ci } 295262306a36Sopenharmony_ci 295362306a36Sopenharmony_ci switch (hw->device_id) { 295462306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KR: 295562306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR: 295662306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR_L: 295762306a36Sopenharmony_ci rc = hw->mac.ops.read_iosf_sb_reg(hw, 295862306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 295962306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, 296062306a36Sopenharmony_ci ®_val); 296162306a36Sopenharmony_ci if (rc) 296262306a36Sopenharmony_ci return rc; 296362306a36Sopenharmony_ci 296462306a36Sopenharmony_ci reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 296562306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 296662306a36Sopenharmony_ci if (pause) 296762306a36Sopenharmony_ci reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 296862306a36Sopenharmony_ci if (asm_dir) 296962306a36Sopenharmony_ci reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 297062306a36Sopenharmony_ci rc = hw->mac.ops.write_iosf_sb_reg(hw, 297162306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 297262306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, 297362306a36Sopenharmony_ci reg_val); 297462306a36Sopenharmony_ci 297562306a36Sopenharmony_ci /* This device does not fully support AN. */ 297662306a36Sopenharmony_ci hw->fc.disable_fc_autoneg = true; 297762306a36Sopenharmony_ci break; 297862306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_XFI: 297962306a36Sopenharmony_ci hw->fc.disable_fc_autoneg = true; 298062306a36Sopenharmony_ci break; 298162306a36Sopenharmony_ci default: 298262306a36Sopenharmony_ci break; 298362306a36Sopenharmony_ci } 298462306a36Sopenharmony_ci return rc; 298562306a36Sopenharmony_ci} 298662306a36Sopenharmony_ci 298762306a36Sopenharmony_ci/** 298862306a36Sopenharmony_ci * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 298962306a36Sopenharmony_ci * @hw: pointer to hardware structure 299062306a36Sopenharmony_ci **/ 299162306a36Sopenharmony_cistatic void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) 299262306a36Sopenharmony_ci{ 299362306a36Sopenharmony_ci u32 link_s1, lp_an_page_low, an_cntl_1; 299462306a36Sopenharmony_ci ixgbe_link_speed speed; 299562306a36Sopenharmony_ci s32 status = -EIO; 299662306a36Sopenharmony_ci bool link_up; 299762306a36Sopenharmony_ci 299862306a36Sopenharmony_ci /* AN should have completed when the cable was plugged in. 299962306a36Sopenharmony_ci * Look for reasons to bail out. Bail out if: 300062306a36Sopenharmony_ci * - FC autoneg is disabled, or if 300162306a36Sopenharmony_ci * - link is not up. 300262306a36Sopenharmony_ci */ 300362306a36Sopenharmony_ci if (hw->fc.disable_fc_autoneg) { 300462306a36Sopenharmony_ci hw_err(hw, "Flow control autoneg is disabled"); 300562306a36Sopenharmony_ci goto out; 300662306a36Sopenharmony_ci } 300762306a36Sopenharmony_ci 300862306a36Sopenharmony_ci hw->mac.ops.check_link(hw, &speed, &link_up, false); 300962306a36Sopenharmony_ci if (!link_up) { 301062306a36Sopenharmony_ci hw_err(hw, "The link is down"); 301162306a36Sopenharmony_ci goto out; 301262306a36Sopenharmony_ci } 301362306a36Sopenharmony_ci 301462306a36Sopenharmony_ci /* Check at auto-negotiation has completed */ 301562306a36Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 301662306a36Sopenharmony_ci IXGBE_KRM_LINK_S1(hw->bus.lan_id), 301762306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); 301862306a36Sopenharmony_ci 301962306a36Sopenharmony_ci if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { 302062306a36Sopenharmony_ci hw_dbg(hw, "Auto-Negotiation did not complete\n"); 302162306a36Sopenharmony_ci status = -EIO; 302262306a36Sopenharmony_ci goto out; 302362306a36Sopenharmony_ci } 302462306a36Sopenharmony_ci 302562306a36Sopenharmony_ci /* Read the 10g AN autoc and LP ability registers and resolve 302662306a36Sopenharmony_ci * local flow control settings accordingly 302762306a36Sopenharmony_ci */ 302862306a36Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 302962306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 303062306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1); 303162306a36Sopenharmony_ci 303262306a36Sopenharmony_ci if (status) { 303362306a36Sopenharmony_ci hw_dbg(hw, "Auto-Negotiation did not complete\n"); 303462306a36Sopenharmony_ci goto out; 303562306a36Sopenharmony_ci } 303662306a36Sopenharmony_ci 303762306a36Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 303862306a36Sopenharmony_ci IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id), 303962306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low); 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_ci if (status) { 304262306a36Sopenharmony_ci hw_dbg(hw, "Auto-Negotiation did not complete\n"); 304362306a36Sopenharmony_ci goto out; 304462306a36Sopenharmony_ci } 304562306a36Sopenharmony_ci 304662306a36Sopenharmony_ci status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low, 304762306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_1_SYM_PAUSE, 304862306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_1_ASM_PAUSE, 304962306a36Sopenharmony_ci IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE, 305062306a36Sopenharmony_ci IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE); 305162306a36Sopenharmony_ci 305262306a36Sopenharmony_ciout: 305362306a36Sopenharmony_ci if (!status) { 305462306a36Sopenharmony_ci hw->fc.fc_was_autonegged = true; 305562306a36Sopenharmony_ci } else { 305662306a36Sopenharmony_ci hw->fc.fc_was_autonegged = false; 305762306a36Sopenharmony_ci hw->fc.current_mode = hw->fc.requested_mode; 305862306a36Sopenharmony_ci } 305962306a36Sopenharmony_ci} 306062306a36Sopenharmony_ci 306162306a36Sopenharmony_ci/** 306262306a36Sopenharmony_ci * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings 306362306a36Sopenharmony_ci * @hw: pointer to hardware structure 306462306a36Sopenharmony_ci **/ 306562306a36Sopenharmony_cistatic void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) 306662306a36Sopenharmony_ci{ 306762306a36Sopenharmony_ci hw->fc.fc_was_autonegged = false; 306862306a36Sopenharmony_ci hw->fc.current_mode = hw->fc.requested_mode; 306962306a36Sopenharmony_ci} 307062306a36Sopenharmony_ci 307162306a36Sopenharmony_ci/** ixgbe_enter_lplu_x550em - Transition to low power states 307262306a36Sopenharmony_ci * @hw: pointer to hardware structure 307362306a36Sopenharmony_ci * 307462306a36Sopenharmony_ci * Configures Low Power Link Up on transition to low power states 307562306a36Sopenharmony_ci * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting 307662306a36Sopenharmony_ci * the X557 PHY immediately prior to entering LPLU. 307762306a36Sopenharmony_ci **/ 307862306a36Sopenharmony_cistatic s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) 307962306a36Sopenharmony_ci{ 308062306a36Sopenharmony_ci u16 an_10g_cntl_reg, autoneg_reg, speed; 308162306a36Sopenharmony_ci s32 status; 308262306a36Sopenharmony_ci ixgbe_link_speed lcd_speed; 308362306a36Sopenharmony_ci u32 save_autoneg; 308462306a36Sopenharmony_ci bool link_up; 308562306a36Sopenharmony_ci 308662306a36Sopenharmony_ci /* If blocked by MNG FW, then don't restart AN */ 308762306a36Sopenharmony_ci if (ixgbe_check_reset_blocked(hw)) 308862306a36Sopenharmony_ci return 0; 308962306a36Sopenharmony_ci 309062306a36Sopenharmony_ci status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 309162306a36Sopenharmony_ci if (status) 309262306a36Sopenharmony_ci return status; 309362306a36Sopenharmony_ci 309462306a36Sopenharmony_ci status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, 309562306a36Sopenharmony_ci &hw->eeprom.ctrl_word_3); 309662306a36Sopenharmony_ci if (status) 309762306a36Sopenharmony_ci return status; 309862306a36Sopenharmony_ci 309962306a36Sopenharmony_ci /* If link is down, LPLU disabled in NVM, WoL disabled, or 310062306a36Sopenharmony_ci * manageability disabled, then force link down by entering 310162306a36Sopenharmony_ci * low power mode. 310262306a36Sopenharmony_ci */ 310362306a36Sopenharmony_ci if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || 310462306a36Sopenharmony_ci !(hw->wol_enabled || ixgbe_mng_present(hw))) 310562306a36Sopenharmony_ci return ixgbe_set_copper_phy_power(hw, false); 310662306a36Sopenharmony_ci 310762306a36Sopenharmony_ci /* Determine LCD */ 310862306a36Sopenharmony_ci status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); 310962306a36Sopenharmony_ci if (status) 311062306a36Sopenharmony_ci return status; 311162306a36Sopenharmony_ci 311262306a36Sopenharmony_ci /* If no valid LCD link speed, then force link down and exit. */ 311362306a36Sopenharmony_ci if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) 311462306a36Sopenharmony_ci return ixgbe_set_copper_phy_power(hw, false); 311562306a36Sopenharmony_ci 311662306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 311762306a36Sopenharmony_ci MDIO_MMD_AN, 311862306a36Sopenharmony_ci &speed); 311962306a36Sopenharmony_ci if (status) 312062306a36Sopenharmony_ci return status; 312162306a36Sopenharmony_ci 312262306a36Sopenharmony_ci /* If no link now, speed is invalid so take link down */ 312362306a36Sopenharmony_ci status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 312462306a36Sopenharmony_ci if (status) 312562306a36Sopenharmony_ci return ixgbe_set_copper_phy_power(hw, false); 312662306a36Sopenharmony_ci 312762306a36Sopenharmony_ci /* clear everything but the speed bits */ 312862306a36Sopenharmony_ci speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; 312962306a36Sopenharmony_ci 313062306a36Sopenharmony_ci /* If current speed is already LCD, then exit. */ 313162306a36Sopenharmony_ci if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && 313262306a36Sopenharmony_ci (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || 313362306a36Sopenharmony_ci ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && 313462306a36Sopenharmony_ci (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) 313562306a36Sopenharmony_ci return status; 313662306a36Sopenharmony_ci 313762306a36Sopenharmony_ci /* Clear AN completed indication */ 313862306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, 313962306a36Sopenharmony_ci MDIO_MMD_AN, 314062306a36Sopenharmony_ci &autoneg_reg); 314162306a36Sopenharmony_ci if (status) 314262306a36Sopenharmony_ci return status; 314362306a36Sopenharmony_ci 314462306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, 314562306a36Sopenharmony_ci MDIO_MMD_AN, 314662306a36Sopenharmony_ci &an_10g_cntl_reg); 314762306a36Sopenharmony_ci if (status) 314862306a36Sopenharmony_ci return status; 314962306a36Sopenharmony_ci 315062306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, 315162306a36Sopenharmony_ci IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, 315262306a36Sopenharmony_ci MDIO_MMD_AN, 315362306a36Sopenharmony_ci &autoneg_reg); 315462306a36Sopenharmony_ci if (status) 315562306a36Sopenharmony_ci return status; 315662306a36Sopenharmony_ci 315762306a36Sopenharmony_ci save_autoneg = hw->phy.autoneg_advertised; 315862306a36Sopenharmony_ci 315962306a36Sopenharmony_ci /* Setup link at least common link speed */ 316062306a36Sopenharmony_ci status = hw->mac.ops.setup_link(hw, lcd_speed, false); 316162306a36Sopenharmony_ci 316262306a36Sopenharmony_ci /* restore autoneg from before setting lplu speed */ 316362306a36Sopenharmony_ci hw->phy.autoneg_advertised = save_autoneg; 316462306a36Sopenharmony_ci 316562306a36Sopenharmony_ci return status; 316662306a36Sopenharmony_ci} 316762306a36Sopenharmony_ci 316862306a36Sopenharmony_ci/** 316962306a36Sopenharmony_ci * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs 317062306a36Sopenharmony_ci * @hw: pointer to hardware structure 317162306a36Sopenharmony_ci */ 317262306a36Sopenharmony_cistatic s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw) 317362306a36Sopenharmony_ci{ 317462306a36Sopenharmony_ci u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 }; 317562306a36Sopenharmony_ci s32 rc; 317662306a36Sopenharmony_ci 317762306a36Sopenharmony_ci if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) 317862306a36Sopenharmony_ci return 0; 317962306a36Sopenharmony_ci 318062306a36Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store); 318162306a36Sopenharmony_ci if (rc) 318262306a36Sopenharmony_ci return rc; 318362306a36Sopenharmony_ci memset(store, 0, sizeof(store)); 318462306a36Sopenharmony_ci 318562306a36Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store); 318662306a36Sopenharmony_ci if (rc) 318762306a36Sopenharmony_ci return rc; 318862306a36Sopenharmony_ci 318962306a36Sopenharmony_ci return ixgbe_setup_fw_link(hw); 319062306a36Sopenharmony_ci} 319162306a36Sopenharmony_ci 319262306a36Sopenharmony_ci/** 319362306a36Sopenharmony_ci * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp 319462306a36Sopenharmony_ci * @hw: pointer to hardware structure 319562306a36Sopenharmony_ci * 319662306a36Sopenharmony_ci * Return true when an overtemp event detected, otherwise false. 319762306a36Sopenharmony_ci */ 319862306a36Sopenharmony_cistatic bool ixgbe_check_overtemp_fw(struct ixgbe_hw *hw) 319962306a36Sopenharmony_ci{ 320062306a36Sopenharmony_ci u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 }; 320162306a36Sopenharmony_ci s32 rc; 320262306a36Sopenharmony_ci 320362306a36Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store); 320462306a36Sopenharmony_ci if (rc) 320562306a36Sopenharmony_ci return false; 320662306a36Sopenharmony_ci 320762306a36Sopenharmony_ci if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) { 320862306a36Sopenharmony_ci ixgbe_shutdown_fw_phy(hw); 320962306a36Sopenharmony_ci return true; 321062306a36Sopenharmony_ci } 321162306a36Sopenharmony_ci return false; 321262306a36Sopenharmony_ci} 321362306a36Sopenharmony_ci 321462306a36Sopenharmony_ci/** 321562306a36Sopenharmony_ci * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register 321662306a36Sopenharmony_ci * @hw: pointer to hardware structure 321762306a36Sopenharmony_ci * 321862306a36Sopenharmony_ci * Read NW_MNG_IF_SEL register and save field values. 321962306a36Sopenharmony_ci */ 322062306a36Sopenharmony_cistatic void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) 322162306a36Sopenharmony_ci{ 322262306a36Sopenharmony_ci /* Save NW management interface connected on board. This is used 322362306a36Sopenharmony_ci * to determine internal PHY mode. 322462306a36Sopenharmony_ci */ 322562306a36Sopenharmony_ci hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 322662306a36Sopenharmony_ci 322762306a36Sopenharmony_ci /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set 322862306a36Sopenharmony_ci * PHY address. This register field was has only been used for X552. 322962306a36Sopenharmony_ci */ 323062306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_x550em_a && 323162306a36Sopenharmony_ci hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) { 323262306a36Sopenharmony_ci hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel & 323362306a36Sopenharmony_ci IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> 323462306a36Sopenharmony_ci IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; 323562306a36Sopenharmony_ci } 323662306a36Sopenharmony_ci} 323762306a36Sopenharmony_ci 323862306a36Sopenharmony_ci/** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 323962306a36Sopenharmony_ci * @hw: pointer to hardware structure 324062306a36Sopenharmony_ci * 324162306a36Sopenharmony_ci * Initialize any function pointers that were not able to be 324262306a36Sopenharmony_ci * set during init_shared_code because the PHY/SFP type was 324362306a36Sopenharmony_ci * not known. Perform the SFP init if necessary. 324462306a36Sopenharmony_ci **/ 324562306a36Sopenharmony_cistatic s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 324662306a36Sopenharmony_ci{ 324762306a36Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 324862306a36Sopenharmony_ci s32 ret_val; 324962306a36Sopenharmony_ci 325062306a36Sopenharmony_ci hw->mac.ops.set_lan_id(hw); 325162306a36Sopenharmony_ci 325262306a36Sopenharmony_ci ixgbe_read_mng_if_sel_x550em(hw); 325362306a36Sopenharmony_ci 325462306a36Sopenharmony_ci if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 325562306a36Sopenharmony_ci phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 325662306a36Sopenharmony_ci ixgbe_setup_mux_ctl(hw); 325762306a36Sopenharmony_ci } 325862306a36Sopenharmony_ci 325962306a36Sopenharmony_ci /* Identify the PHY or SFP module */ 326062306a36Sopenharmony_ci ret_val = phy->ops.identify(hw); 326162306a36Sopenharmony_ci if (ret_val == -EOPNOTSUPP || ret_val == -EFAULT) 326262306a36Sopenharmony_ci return ret_val; 326362306a36Sopenharmony_ci 326462306a36Sopenharmony_ci /* Setup function pointers based on detected hardware */ 326562306a36Sopenharmony_ci ixgbe_init_mac_link_ops_X550em(hw); 326662306a36Sopenharmony_ci if (phy->sfp_type != ixgbe_sfp_type_unknown) 326762306a36Sopenharmony_ci phy->ops.reset = NULL; 326862306a36Sopenharmony_ci 326962306a36Sopenharmony_ci /* Set functions pointers based on phy type */ 327062306a36Sopenharmony_ci switch (hw->phy.type) { 327162306a36Sopenharmony_ci case ixgbe_phy_x550em_kx4: 327262306a36Sopenharmony_ci phy->ops.setup_link = NULL; 327362306a36Sopenharmony_ci phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 327462306a36Sopenharmony_ci phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 327562306a36Sopenharmony_ci break; 327662306a36Sopenharmony_ci case ixgbe_phy_x550em_kr: 327762306a36Sopenharmony_ci phy->ops.setup_link = ixgbe_setup_kr_x550em; 327862306a36Sopenharmony_ci phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 327962306a36Sopenharmony_ci phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 328062306a36Sopenharmony_ci break; 328162306a36Sopenharmony_ci case ixgbe_phy_x550em_xfi: 328262306a36Sopenharmony_ci /* link is managed by HW */ 328362306a36Sopenharmony_ci phy->ops.setup_link = NULL; 328462306a36Sopenharmony_ci phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 328562306a36Sopenharmony_ci phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 328662306a36Sopenharmony_ci break; 328762306a36Sopenharmony_ci case ixgbe_phy_x550em_ext_t: 328862306a36Sopenharmony_ci /* Save NW management interface connected on board. This is used 328962306a36Sopenharmony_ci * to determine internal PHY mode 329062306a36Sopenharmony_ci */ 329162306a36Sopenharmony_ci phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 329262306a36Sopenharmony_ci 329362306a36Sopenharmony_ci /* If internal link mode is XFI, then setup iXFI internal link, 329462306a36Sopenharmony_ci * else setup KR now. 329562306a36Sopenharmony_ci */ 329662306a36Sopenharmony_ci phy->ops.setup_internal_link = 329762306a36Sopenharmony_ci ixgbe_setup_internal_phy_t_x550em; 329862306a36Sopenharmony_ci 329962306a36Sopenharmony_ci /* setup SW LPLU only for first revision */ 330062306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_X550EM_x && 330162306a36Sopenharmony_ci !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) & 330262306a36Sopenharmony_ci IXGBE_FUSES0_REV_MASK)) 330362306a36Sopenharmony_ci phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; 330462306a36Sopenharmony_ci 330562306a36Sopenharmony_ci phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 330662306a36Sopenharmony_ci phy->ops.reset = ixgbe_reset_phy_t_X550em; 330762306a36Sopenharmony_ci break; 330862306a36Sopenharmony_ci case ixgbe_phy_sgmii: 330962306a36Sopenharmony_ci phy->ops.setup_link = NULL; 331062306a36Sopenharmony_ci break; 331162306a36Sopenharmony_ci case ixgbe_phy_fw: 331262306a36Sopenharmony_ci phy->ops.setup_link = ixgbe_setup_fw_link; 331362306a36Sopenharmony_ci phy->ops.reset = ixgbe_reset_phy_fw; 331462306a36Sopenharmony_ci break; 331562306a36Sopenharmony_ci case ixgbe_phy_ext_1g_t: 331662306a36Sopenharmony_ci phy->ops.setup_link = NULL; 331762306a36Sopenharmony_ci phy->ops.read_reg = NULL; 331862306a36Sopenharmony_ci phy->ops.write_reg = NULL; 331962306a36Sopenharmony_ci phy->ops.reset = NULL; 332062306a36Sopenharmony_ci break; 332162306a36Sopenharmony_ci default: 332262306a36Sopenharmony_ci break; 332362306a36Sopenharmony_ci } 332462306a36Sopenharmony_ci 332562306a36Sopenharmony_ci return ret_val; 332662306a36Sopenharmony_ci} 332762306a36Sopenharmony_ci 332862306a36Sopenharmony_ci/** ixgbe_get_media_type_X550em - Get media type 332962306a36Sopenharmony_ci * @hw: pointer to hardware structure 333062306a36Sopenharmony_ci * 333162306a36Sopenharmony_ci * Returns the media type (fiber, copper, backplane) 333262306a36Sopenharmony_ci * 333362306a36Sopenharmony_ci */ 333462306a36Sopenharmony_cistatic enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 333562306a36Sopenharmony_ci{ 333662306a36Sopenharmony_ci enum ixgbe_media_type media_type; 333762306a36Sopenharmony_ci 333862306a36Sopenharmony_ci /* Detect if there is a copper PHY attached. */ 333962306a36Sopenharmony_ci switch (hw->device_id) { 334062306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SGMII: 334162306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SGMII_L: 334262306a36Sopenharmony_ci hw->phy.type = ixgbe_phy_sgmii; 334362306a36Sopenharmony_ci fallthrough; 334462306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KR: 334562306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KX4: 334662306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_XFI: 334762306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR: 334862306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR_L: 334962306a36Sopenharmony_ci media_type = ixgbe_media_type_backplane; 335062306a36Sopenharmony_ci break; 335162306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_SFP: 335262306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP: 335362306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP_N: 335462306a36Sopenharmony_ci media_type = ixgbe_media_type_fiber; 335562306a36Sopenharmony_ci break; 335662306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_1G_T: 335762306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_10G_T: 335862306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_10G_T: 335962306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T: 336062306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T_L: 336162306a36Sopenharmony_ci media_type = ixgbe_media_type_copper; 336262306a36Sopenharmony_ci break; 336362306a36Sopenharmony_ci default: 336462306a36Sopenharmony_ci media_type = ixgbe_media_type_unknown; 336562306a36Sopenharmony_ci break; 336662306a36Sopenharmony_ci } 336762306a36Sopenharmony_ci return media_type; 336862306a36Sopenharmony_ci} 336962306a36Sopenharmony_ci 337062306a36Sopenharmony_ci/** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 337162306a36Sopenharmony_ci ** @hw: pointer to hardware structure 337262306a36Sopenharmony_ci **/ 337362306a36Sopenharmony_cistatic s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 337462306a36Sopenharmony_ci{ 337562306a36Sopenharmony_ci s32 status; 337662306a36Sopenharmony_ci u16 reg; 337762306a36Sopenharmony_ci 337862306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, 337962306a36Sopenharmony_ci IXGBE_MDIO_TX_VENDOR_ALARMS_3, 338062306a36Sopenharmony_ci MDIO_MMD_PMAPMD, 338162306a36Sopenharmony_ci ®); 338262306a36Sopenharmony_ci if (status) 338362306a36Sopenharmony_ci return status; 338462306a36Sopenharmony_ci 338562306a36Sopenharmony_ci /* If PHY FW reset completed bit is set then this is the first 338662306a36Sopenharmony_ci * SW instance after a power on so the PHY FW must be un-stalled. 338762306a36Sopenharmony_ci */ 338862306a36Sopenharmony_ci if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 338962306a36Sopenharmony_ci status = hw->phy.ops.read_reg(hw, 339062306a36Sopenharmony_ci IXGBE_MDIO_GLOBAL_RES_PR_10, 339162306a36Sopenharmony_ci MDIO_MMD_VEND1, 339262306a36Sopenharmony_ci ®); 339362306a36Sopenharmony_ci if (status) 339462306a36Sopenharmony_ci return status; 339562306a36Sopenharmony_ci 339662306a36Sopenharmony_ci reg &= ~IXGBE_MDIO_POWER_UP_STALL; 339762306a36Sopenharmony_ci 339862306a36Sopenharmony_ci status = hw->phy.ops.write_reg(hw, 339962306a36Sopenharmony_ci IXGBE_MDIO_GLOBAL_RES_PR_10, 340062306a36Sopenharmony_ci MDIO_MMD_VEND1, 340162306a36Sopenharmony_ci reg); 340262306a36Sopenharmony_ci if (status) 340362306a36Sopenharmony_ci return status; 340462306a36Sopenharmony_ci } 340562306a36Sopenharmony_ci 340662306a36Sopenharmony_ci return status; 340762306a36Sopenharmony_ci} 340862306a36Sopenharmony_ci 340962306a36Sopenharmony_ci/** 341062306a36Sopenharmony_ci * ixgbe_set_mdio_speed - Set MDIO clock speed 341162306a36Sopenharmony_ci * @hw: pointer to hardware structure 341262306a36Sopenharmony_ci */ 341362306a36Sopenharmony_cistatic void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) 341462306a36Sopenharmony_ci{ 341562306a36Sopenharmony_ci u32 hlreg0; 341662306a36Sopenharmony_ci 341762306a36Sopenharmony_ci switch (hw->device_id) { 341862306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_10G_T: 341962306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SGMII: 342062306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SGMII_L: 342162306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_10G_T: 342262306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP: 342362306a36Sopenharmony_ci /* Config MDIO clock speed before the first MDIO PHY access */ 342462306a36Sopenharmony_ci hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 342562306a36Sopenharmony_ci hlreg0 &= ~IXGBE_HLREG0_MDCSPD; 342662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 342762306a36Sopenharmony_ci break; 342862306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T: 342962306a36Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T_L: 343062306a36Sopenharmony_ci /* Select fast MDIO clock speed for these devices */ 343162306a36Sopenharmony_ci hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 343262306a36Sopenharmony_ci hlreg0 |= IXGBE_HLREG0_MDCSPD; 343362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 343462306a36Sopenharmony_ci break; 343562306a36Sopenharmony_ci default: 343662306a36Sopenharmony_ci break; 343762306a36Sopenharmony_ci } 343862306a36Sopenharmony_ci} 343962306a36Sopenharmony_ci 344062306a36Sopenharmony_ci/** ixgbe_reset_hw_X550em - Perform hardware reset 344162306a36Sopenharmony_ci ** @hw: pointer to hardware structure 344262306a36Sopenharmony_ci ** 344362306a36Sopenharmony_ci ** Resets the hardware by resetting the transmit and receive units, masks 344462306a36Sopenharmony_ci ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 344562306a36Sopenharmony_ci ** reset. 344662306a36Sopenharmony_ci **/ 344762306a36Sopenharmony_cistatic s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 344862306a36Sopenharmony_ci{ 344962306a36Sopenharmony_ci ixgbe_link_speed link_speed; 345062306a36Sopenharmony_ci s32 status; 345162306a36Sopenharmony_ci u32 ctrl = 0; 345262306a36Sopenharmony_ci u32 i; 345362306a36Sopenharmony_ci bool link_up = false; 345462306a36Sopenharmony_ci u32 swfw_mask = hw->phy.phy_semaphore_mask; 345562306a36Sopenharmony_ci 345662306a36Sopenharmony_ci /* Call adapter stop to disable Tx/Rx and clear interrupts */ 345762306a36Sopenharmony_ci status = hw->mac.ops.stop_adapter(hw); 345862306a36Sopenharmony_ci if (status) 345962306a36Sopenharmony_ci return status; 346062306a36Sopenharmony_ci 346162306a36Sopenharmony_ci /* flush pending Tx transactions */ 346262306a36Sopenharmony_ci ixgbe_clear_tx_pending(hw); 346362306a36Sopenharmony_ci 346462306a36Sopenharmony_ci /* set MDIO speed before talking to the PHY in case it's the 1st time */ 346562306a36Sopenharmony_ci ixgbe_set_mdio_speed(hw); 346662306a36Sopenharmony_ci 346762306a36Sopenharmony_ci /* PHY ops must be identified and initialized prior to reset */ 346862306a36Sopenharmony_ci status = hw->phy.ops.init(hw); 346962306a36Sopenharmony_ci if (status == -EOPNOTSUPP || status == -EFAULT) 347062306a36Sopenharmony_ci return status; 347162306a36Sopenharmony_ci 347262306a36Sopenharmony_ci /* start the external PHY */ 347362306a36Sopenharmony_ci if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 347462306a36Sopenharmony_ci status = ixgbe_init_ext_t_x550em(hw); 347562306a36Sopenharmony_ci if (status) 347662306a36Sopenharmony_ci return status; 347762306a36Sopenharmony_ci } 347862306a36Sopenharmony_ci 347962306a36Sopenharmony_ci /* Setup SFP module if there is one present. */ 348062306a36Sopenharmony_ci if (hw->phy.sfp_setup_needed) { 348162306a36Sopenharmony_ci status = hw->mac.ops.setup_sfp(hw); 348262306a36Sopenharmony_ci hw->phy.sfp_setup_needed = false; 348362306a36Sopenharmony_ci } 348462306a36Sopenharmony_ci 348562306a36Sopenharmony_ci if (status == -EOPNOTSUPP) 348662306a36Sopenharmony_ci return status; 348762306a36Sopenharmony_ci 348862306a36Sopenharmony_ci /* Reset PHY */ 348962306a36Sopenharmony_ci if (!hw->phy.reset_disable && hw->phy.ops.reset) 349062306a36Sopenharmony_ci hw->phy.ops.reset(hw); 349162306a36Sopenharmony_ci 349262306a36Sopenharmony_cimac_reset_top: 349362306a36Sopenharmony_ci /* Issue global reset to the MAC. Needs to be SW reset if link is up. 349462306a36Sopenharmony_ci * If link reset is used when link is up, it might reset the PHY when 349562306a36Sopenharmony_ci * mng is using it. If link is down or the flag to force full link 349662306a36Sopenharmony_ci * reset is set, then perform link reset. 349762306a36Sopenharmony_ci */ 349862306a36Sopenharmony_ci ctrl = IXGBE_CTRL_LNK_RST; 349962306a36Sopenharmony_ci 350062306a36Sopenharmony_ci if (!hw->force_full_reset) { 350162306a36Sopenharmony_ci hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 350262306a36Sopenharmony_ci if (link_up) 350362306a36Sopenharmony_ci ctrl = IXGBE_CTRL_RST; 350462306a36Sopenharmony_ci } 350562306a36Sopenharmony_ci 350662306a36Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 350762306a36Sopenharmony_ci if (status) { 350862306a36Sopenharmony_ci hw_dbg(hw, "semaphore failed with %d", status); 350962306a36Sopenharmony_ci return -EBUSY; 351062306a36Sopenharmony_ci } 351162306a36Sopenharmony_ci 351262306a36Sopenharmony_ci ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 351362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 351462306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 351562306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 351662306a36Sopenharmony_ci usleep_range(1000, 1200); 351762306a36Sopenharmony_ci 351862306a36Sopenharmony_ci /* Poll for reset bit to self-clear meaning reset is complete */ 351962306a36Sopenharmony_ci for (i = 0; i < 10; i++) { 352062306a36Sopenharmony_ci ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 352162306a36Sopenharmony_ci if (!(ctrl & IXGBE_CTRL_RST_MASK)) 352262306a36Sopenharmony_ci break; 352362306a36Sopenharmony_ci udelay(1); 352462306a36Sopenharmony_ci } 352562306a36Sopenharmony_ci 352662306a36Sopenharmony_ci if (ctrl & IXGBE_CTRL_RST_MASK) { 352762306a36Sopenharmony_ci status = -EIO; 352862306a36Sopenharmony_ci hw_dbg(hw, "Reset polling failed to complete.\n"); 352962306a36Sopenharmony_ci } 353062306a36Sopenharmony_ci 353162306a36Sopenharmony_ci msleep(50); 353262306a36Sopenharmony_ci 353362306a36Sopenharmony_ci /* Double resets are required for recovery from certain error 353462306a36Sopenharmony_ci * clear the multicast table. Also reset num_rar_entries to 128, 353562306a36Sopenharmony_ci * since we modify this value when programming the SAN MAC address. 353662306a36Sopenharmony_ci */ 353762306a36Sopenharmony_ci if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 353862306a36Sopenharmony_ci hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 353962306a36Sopenharmony_ci goto mac_reset_top; 354062306a36Sopenharmony_ci } 354162306a36Sopenharmony_ci 354262306a36Sopenharmony_ci /* Store the permanent mac address */ 354362306a36Sopenharmony_ci hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 354462306a36Sopenharmony_ci 354562306a36Sopenharmony_ci /* Store MAC address from RAR0, clear receive address registers, and 354662306a36Sopenharmony_ci * clear the multicast table. Also reset num_rar_entries to 128, 354762306a36Sopenharmony_ci * since we modify this value when programming the SAN MAC address. 354862306a36Sopenharmony_ci */ 354962306a36Sopenharmony_ci hw->mac.num_rar_entries = 128; 355062306a36Sopenharmony_ci hw->mac.ops.init_rx_addrs(hw); 355162306a36Sopenharmony_ci 355262306a36Sopenharmony_ci ixgbe_set_mdio_speed(hw); 355362306a36Sopenharmony_ci 355462306a36Sopenharmony_ci if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 355562306a36Sopenharmony_ci ixgbe_setup_mux_ctl(hw); 355662306a36Sopenharmony_ci 355762306a36Sopenharmony_ci return status; 355862306a36Sopenharmony_ci} 355962306a36Sopenharmony_ci 356062306a36Sopenharmony_ci/** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 356162306a36Sopenharmony_ci * anti-spoofing 356262306a36Sopenharmony_ci * @hw: pointer to hardware structure 356362306a36Sopenharmony_ci * @enable: enable or disable switch for Ethertype anti-spoofing 356462306a36Sopenharmony_ci * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 356562306a36Sopenharmony_ci **/ 356662306a36Sopenharmony_cistatic void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 356762306a36Sopenharmony_ci bool enable, int vf) 356862306a36Sopenharmony_ci{ 356962306a36Sopenharmony_ci int vf_target_reg = vf >> 3; 357062306a36Sopenharmony_ci int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 357162306a36Sopenharmony_ci u32 pfvfspoof; 357262306a36Sopenharmony_ci 357362306a36Sopenharmony_ci pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 357462306a36Sopenharmony_ci if (enable) 357562306a36Sopenharmony_ci pfvfspoof |= BIT(vf_target_shift); 357662306a36Sopenharmony_ci else 357762306a36Sopenharmony_ci pfvfspoof &= ~BIT(vf_target_shift); 357862306a36Sopenharmony_ci 357962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 358062306a36Sopenharmony_ci} 358162306a36Sopenharmony_ci 358262306a36Sopenharmony_ci/** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 358362306a36Sopenharmony_ci * @hw: pointer to hardware structure 358462306a36Sopenharmony_ci * @enable: enable or disable source address pruning 358562306a36Sopenharmony_ci * @pool: Rx pool to set source address pruning for 358662306a36Sopenharmony_ci **/ 358762306a36Sopenharmony_cistatic void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 358862306a36Sopenharmony_ci bool enable, 358962306a36Sopenharmony_ci unsigned int pool) 359062306a36Sopenharmony_ci{ 359162306a36Sopenharmony_ci u64 pfflp; 359262306a36Sopenharmony_ci 359362306a36Sopenharmony_ci /* max rx pool is 63 */ 359462306a36Sopenharmony_ci if (pool > 63) 359562306a36Sopenharmony_ci return; 359662306a36Sopenharmony_ci 359762306a36Sopenharmony_ci pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 359862306a36Sopenharmony_ci pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 359962306a36Sopenharmony_ci 360062306a36Sopenharmony_ci if (enable) 360162306a36Sopenharmony_ci pfflp |= (1ULL << pool); 360262306a36Sopenharmony_ci else 360362306a36Sopenharmony_ci pfflp &= ~(1ULL << pool); 360462306a36Sopenharmony_ci 360562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 360662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 360762306a36Sopenharmony_ci} 360862306a36Sopenharmony_ci 360962306a36Sopenharmony_ci/** 361062306a36Sopenharmony_ci * ixgbe_setup_fc_backplane_x550em_a - Set up flow control 361162306a36Sopenharmony_ci * @hw: pointer to hardware structure 361262306a36Sopenharmony_ci * 361362306a36Sopenharmony_ci * Called at init time to set up flow control. 361462306a36Sopenharmony_ci **/ 361562306a36Sopenharmony_cistatic s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) 361662306a36Sopenharmony_ci{ 361762306a36Sopenharmony_ci s32 status = 0; 361862306a36Sopenharmony_ci u32 an_cntl = 0; 361962306a36Sopenharmony_ci 362062306a36Sopenharmony_ci /* Validate the requested mode */ 362162306a36Sopenharmony_ci if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 362262306a36Sopenharmony_ci hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 362362306a36Sopenharmony_ci return -EINVAL; 362462306a36Sopenharmony_ci } 362562306a36Sopenharmony_ci 362662306a36Sopenharmony_ci if (hw->fc.requested_mode == ixgbe_fc_default) 362762306a36Sopenharmony_ci hw->fc.requested_mode = ixgbe_fc_full; 362862306a36Sopenharmony_ci 362962306a36Sopenharmony_ci /* Set up the 1G and 10G flow control advertisement registers so the 363062306a36Sopenharmony_ci * HW will be able to do FC autoneg once the cable is plugged in. If 363162306a36Sopenharmony_ci * we link at 10G, the 1G advertisement is harmless and vice versa. 363262306a36Sopenharmony_ci */ 363362306a36Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 363462306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 363562306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl); 363662306a36Sopenharmony_ci 363762306a36Sopenharmony_ci if (status) { 363862306a36Sopenharmony_ci hw_dbg(hw, "Auto-Negotiation did not complete\n"); 363962306a36Sopenharmony_ci return status; 364062306a36Sopenharmony_ci } 364162306a36Sopenharmony_ci 364262306a36Sopenharmony_ci /* The possible values of fc.requested_mode are: 364362306a36Sopenharmony_ci * 0: Flow control is completely disabled 364462306a36Sopenharmony_ci * 1: Rx flow control is enabled (we can receive pause frames, 364562306a36Sopenharmony_ci * but not send pause frames). 364662306a36Sopenharmony_ci * 2: Tx flow control is enabled (we can send pause frames but 364762306a36Sopenharmony_ci * we do not support receiving pause frames). 364862306a36Sopenharmony_ci * 3: Both Rx and Tx flow control (symmetric) are enabled. 364962306a36Sopenharmony_ci * other: Invalid. 365062306a36Sopenharmony_ci */ 365162306a36Sopenharmony_ci switch (hw->fc.requested_mode) { 365262306a36Sopenharmony_ci case ixgbe_fc_none: 365362306a36Sopenharmony_ci /* Flow control completely disabled by software override. */ 365462306a36Sopenharmony_ci an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 365562306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 365662306a36Sopenharmony_ci break; 365762306a36Sopenharmony_ci case ixgbe_fc_tx_pause: 365862306a36Sopenharmony_ci /* Tx Flow control is enabled, and Rx Flow control is 365962306a36Sopenharmony_ci * disabled by software override. 366062306a36Sopenharmony_ci */ 366162306a36Sopenharmony_ci an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 366262306a36Sopenharmony_ci an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 366362306a36Sopenharmony_ci break; 366462306a36Sopenharmony_ci case ixgbe_fc_rx_pause: 366562306a36Sopenharmony_ci /* Rx Flow control is enabled and Tx Flow control is 366662306a36Sopenharmony_ci * disabled by software override. Since there really 366762306a36Sopenharmony_ci * isn't a way to advertise that we are capable of RX 366862306a36Sopenharmony_ci * Pause ONLY, we will advertise that we support both 366962306a36Sopenharmony_ci * symmetric and asymmetric Rx PAUSE, as such we fall 367062306a36Sopenharmony_ci * through to the fc_full statement. Later, we will 367162306a36Sopenharmony_ci * disable the adapter's ability to send PAUSE frames. 367262306a36Sopenharmony_ci */ 367362306a36Sopenharmony_ci case ixgbe_fc_full: 367462306a36Sopenharmony_ci /* Flow control (both Rx and Tx) is enabled by SW override. */ 367562306a36Sopenharmony_ci an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 367662306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 367762306a36Sopenharmony_ci break; 367862306a36Sopenharmony_ci default: 367962306a36Sopenharmony_ci hw_err(hw, "Flow control param set incorrectly\n"); 368062306a36Sopenharmony_ci return -EIO; 368162306a36Sopenharmony_ci } 368262306a36Sopenharmony_ci 368362306a36Sopenharmony_ci status = hw->mac.ops.write_iosf_sb_reg(hw, 368462306a36Sopenharmony_ci IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 368562306a36Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); 368662306a36Sopenharmony_ci 368762306a36Sopenharmony_ci /* Restart auto-negotiation. */ 368862306a36Sopenharmony_ci status = ixgbe_restart_an_internal_phy_x550em(hw); 368962306a36Sopenharmony_ci 369062306a36Sopenharmony_ci return status; 369162306a36Sopenharmony_ci} 369262306a36Sopenharmony_ci 369362306a36Sopenharmony_ci/** 369462306a36Sopenharmony_ci * ixgbe_set_mux - Set mux for port 1 access with CS4227 369562306a36Sopenharmony_ci * @hw: pointer to hardware structure 369662306a36Sopenharmony_ci * @state: set mux if 1, clear if 0 369762306a36Sopenharmony_ci */ 369862306a36Sopenharmony_cistatic void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) 369962306a36Sopenharmony_ci{ 370062306a36Sopenharmony_ci u32 esdp; 370162306a36Sopenharmony_ci 370262306a36Sopenharmony_ci if (!hw->bus.lan_id) 370362306a36Sopenharmony_ci return; 370462306a36Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 370562306a36Sopenharmony_ci if (state) 370662306a36Sopenharmony_ci esdp |= IXGBE_ESDP_SDP1; 370762306a36Sopenharmony_ci else 370862306a36Sopenharmony_ci esdp &= ~IXGBE_ESDP_SDP1; 370962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 371062306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 371162306a36Sopenharmony_ci} 371262306a36Sopenharmony_ci 371362306a36Sopenharmony_ci/** 371462306a36Sopenharmony_ci * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore 371562306a36Sopenharmony_ci * @hw: pointer to hardware structure 371662306a36Sopenharmony_ci * @mask: Mask to specify which semaphore to acquire 371762306a36Sopenharmony_ci * 371862306a36Sopenharmony_ci * Acquires the SWFW semaphore and sets the I2C MUX 371962306a36Sopenharmony_ci */ 372062306a36Sopenharmony_cistatic s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 372162306a36Sopenharmony_ci{ 372262306a36Sopenharmony_ci s32 status; 372362306a36Sopenharmony_ci 372462306a36Sopenharmony_ci status = ixgbe_acquire_swfw_sync_X540(hw, mask); 372562306a36Sopenharmony_ci if (status) 372662306a36Sopenharmony_ci return status; 372762306a36Sopenharmony_ci 372862306a36Sopenharmony_ci if (mask & IXGBE_GSSR_I2C_MASK) 372962306a36Sopenharmony_ci ixgbe_set_mux(hw, 1); 373062306a36Sopenharmony_ci 373162306a36Sopenharmony_ci return 0; 373262306a36Sopenharmony_ci} 373362306a36Sopenharmony_ci 373462306a36Sopenharmony_ci/** 373562306a36Sopenharmony_ci * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore 373662306a36Sopenharmony_ci * @hw: pointer to hardware structure 373762306a36Sopenharmony_ci * @mask: Mask to specify which semaphore to release 373862306a36Sopenharmony_ci * 373962306a36Sopenharmony_ci * Releases the SWFW semaphore and sets the I2C MUX 374062306a36Sopenharmony_ci */ 374162306a36Sopenharmony_cistatic void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 374262306a36Sopenharmony_ci{ 374362306a36Sopenharmony_ci if (mask & IXGBE_GSSR_I2C_MASK) 374462306a36Sopenharmony_ci ixgbe_set_mux(hw, 0); 374562306a36Sopenharmony_ci 374662306a36Sopenharmony_ci ixgbe_release_swfw_sync_X540(hw, mask); 374762306a36Sopenharmony_ci} 374862306a36Sopenharmony_ci 374962306a36Sopenharmony_ci/** 375062306a36Sopenharmony_ci * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore 375162306a36Sopenharmony_ci * @hw: pointer to hardware structure 375262306a36Sopenharmony_ci * @mask: Mask to specify which semaphore to acquire 375362306a36Sopenharmony_ci * 375462306a36Sopenharmony_ci * Acquires the SWFW semaphore and get the shared PHY token as needed 375562306a36Sopenharmony_ci */ 375662306a36Sopenharmony_cistatic s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 375762306a36Sopenharmony_ci{ 375862306a36Sopenharmony_ci u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 375962306a36Sopenharmony_ci int retries = FW_PHY_TOKEN_RETRIES; 376062306a36Sopenharmony_ci s32 status; 376162306a36Sopenharmony_ci 376262306a36Sopenharmony_ci while (--retries) { 376362306a36Sopenharmony_ci status = 0; 376462306a36Sopenharmony_ci if (hmask) 376562306a36Sopenharmony_ci status = ixgbe_acquire_swfw_sync_X540(hw, hmask); 376662306a36Sopenharmony_ci if (status) 376762306a36Sopenharmony_ci return status; 376862306a36Sopenharmony_ci if (!(mask & IXGBE_GSSR_TOKEN_SM)) 376962306a36Sopenharmony_ci return 0; 377062306a36Sopenharmony_ci 377162306a36Sopenharmony_ci status = ixgbe_get_phy_token(hw); 377262306a36Sopenharmony_ci if (!status) 377362306a36Sopenharmony_ci return 0; 377462306a36Sopenharmony_ci if (hmask) 377562306a36Sopenharmony_ci ixgbe_release_swfw_sync_X540(hw, hmask); 377662306a36Sopenharmony_ci if (status != -EAGAIN) 377762306a36Sopenharmony_ci return status; 377862306a36Sopenharmony_ci msleep(FW_PHY_TOKEN_DELAY); 377962306a36Sopenharmony_ci } 378062306a36Sopenharmony_ci 378162306a36Sopenharmony_ci return status; 378262306a36Sopenharmony_ci} 378362306a36Sopenharmony_ci 378462306a36Sopenharmony_ci/** 378562306a36Sopenharmony_ci * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore 378662306a36Sopenharmony_ci * @hw: pointer to hardware structure 378762306a36Sopenharmony_ci * @mask: Mask to specify which semaphore to release 378862306a36Sopenharmony_ci * 378962306a36Sopenharmony_ci * Release the SWFW semaphore and puts the shared PHY token as needed 379062306a36Sopenharmony_ci */ 379162306a36Sopenharmony_cistatic void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 379262306a36Sopenharmony_ci{ 379362306a36Sopenharmony_ci u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 379462306a36Sopenharmony_ci 379562306a36Sopenharmony_ci if (mask & IXGBE_GSSR_TOKEN_SM) 379662306a36Sopenharmony_ci ixgbe_put_phy_token(hw); 379762306a36Sopenharmony_ci 379862306a36Sopenharmony_ci if (hmask) 379962306a36Sopenharmony_ci ixgbe_release_swfw_sync_X540(hw, hmask); 380062306a36Sopenharmony_ci} 380162306a36Sopenharmony_ci 380262306a36Sopenharmony_ci/** 380362306a36Sopenharmony_ci * ixgbe_read_phy_reg_x550a - Reads specified PHY register 380462306a36Sopenharmony_ci * @hw: pointer to hardware structure 380562306a36Sopenharmony_ci * @reg_addr: 32 bit address of PHY register to read 380662306a36Sopenharmony_ci * @device_type: 5 bit device type 380762306a36Sopenharmony_ci * @phy_data: Pointer to read data from PHY register 380862306a36Sopenharmony_ci * 380962306a36Sopenharmony_ci * Reads a value from a specified PHY register using the SWFW lock and PHY 381062306a36Sopenharmony_ci * Token. The PHY Token is needed since the MDIO is shared between to MAC 381162306a36Sopenharmony_ci * instances. 381262306a36Sopenharmony_ci */ 381362306a36Sopenharmony_cistatic s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 381462306a36Sopenharmony_ci u32 device_type, u16 *phy_data) 381562306a36Sopenharmony_ci{ 381662306a36Sopenharmony_ci u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 381762306a36Sopenharmony_ci s32 status; 381862306a36Sopenharmony_ci 381962306a36Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 382062306a36Sopenharmony_ci return -EBUSY; 382162306a36Sopenharmony_ci 382262306a36Sopenharmony_ci status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); 382362306a36Sopenharmony_ci 382462306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, mask); 382562306a36Sopenharmony_ci 382662306a36Sopenharmony_ci return status; 382762306a36Sopenharmony_ci} 382862306a36Sopenharmony_ci 382962306a36Sopenharmony_ci/** 383062306a36Sopenharmony_ci * ixgbe_write_phy_reg_x550a - Writes specified PHY register 383162306a36Sopenharmony_ci * @hw: pointer to hardware structure 383262306a36Sopenharmony_ci * @reg_addr: 32 bit PHY register to write 383362306a36Sopenharmony_ci * @device_type: 5 bit device type 383462306a36Sopenharmony_ci * @phy_data: Data to write to the PHY register 383562306a36Sopenharmony_ci * 383662306a36Sopenharmony_ci * Writes a value to specified PHY register using the SWFW lock and PHY Token. 383762306a36Sopenharmony_ci * The PHY Token is needed since the MDIO is shared between to MAC instances. 383862306a36Sopenharmony_ci */ 383962306a36Sopenharmony_cistatic s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 384062306a36Sopenharmony_ci u32 device_type, u16 phy_data) 384162306a36Sopenharmony_ci{ 384262306a36Sopenharmony_ci u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 384362306a36Sopenharmony_ci s32 status; 384462306a36Sopenharmony_ci 384562306a36Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 384662306a36Sopenharmony_ci return -EBUSY; 384762306a36Sopenharmony_ci 384862306a36Sopenharmony_ci status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data); 384962306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, mask); 385062306a36Sopenharmony_ci 385162306a36Sopenharmony_ci return status; 385262306a36Sopenharmony_ci} 385362306a36Sopenharmony_ci 385462306a36Sopenharmony_ci#define X550_COMMON_MAC \ 385562306a36Sopenharmony_ci .init_hw = &ixgbe_init_hw_generic, \ 385662306a36Sopenharmony_ci .start_hw = &ixgbe_start_hw_X540, \ 385762306a36Sopenharmony_ci .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 385862306a36Sopenharmony_ci .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 385962306a36Sopenharmony_ci .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 386062306a36Sopenharmony_ci .get_device_caps = &ixgbe_get_device_caps_generic, \ 386162306a36Sopenharmony_ci .stop_adapter = &ixgbe_stop_adapter_generic, \ 386262306a36Sopenharmony_ci .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 386362306a36Sopenharmony_ci .read_analog_reg8 = NULL, \ 386462306a36Sopenharmony_ci .write_analog_reg8 = NULL, \ 386562306a36Sopenharmony_ci .set_rxpba = &ixgbe_set_rxpba_generic, \ 386662306a36Sopenharmony_ci .check_link = &ixgbe_check_mac_link_generic, \ 386762306a36Sopenharmony_ci .blink_led_start = &ixgbe_blink_led_start_X540, \ 386862306a36Sopenharmony_ci .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 386962306a36Sopenharmony_ci .set_rar = &ixgbe_set_rar_generic, \ 387062306a36Sopenharmony_ci .clear_rar = &ixgbe_clear_rar_generic, \ 387162306a36Sopenharmony_ci .set_vmdq = &ixgbe_set_vmdq_generic, \ 387262306a36Sopenharmony_ci .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 387362306a36Sopenharmony_ci .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 387462306a36Sopenharmony_ci .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 387562306a36Sopenharmony_ci .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 387662306a36Sopenharmony_ci .enable_mc = &ixgbe_enable_mc_generic, \ 387762306a36Sopenharmony_ci .disable_mc = &ixgbe_disable_mc_generic, \ 387862306a36Sopenharmony_ci .clear_vfta = &ixgbe_clear_vfta_generic, \ 387962306a36Sopenharmony_ci .set_vfta = &ixgbe_set_vfta_generic, \ 388062306a36Sopenharmony_ci .fc_enable = &ixgbe_fc_enable_generic, \ 388162306a36Sopenharmony_ci .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_x550, \ 388262306a36Sopenharmony_ci .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 388362306a36Sopenharmony_ci .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 388462306a36Sopenharmony_ci .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 388562306a36Sopenharmony_ci .set_source_address_pruning = \ 388662306a36Sopenharmony_ci &ixgbe_set_source_address_pruning_X550, \ 388762306a36Sopenharmony_ci .set_ethertype_anti_spoofing = \ 388862306a36Sopenharmony_ci &ixgbe_set_ethertype_anti_spoofing_X550, \ 388962306a36Sopenharmony_ci .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 389062306a36Sopenharmony_ci .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 389162306a36Sopenharmony_ci .get_thermal_sensor_data = NULL, \ 389262306a36Sopenharmony_ci .init_thermal_sensor_thresh = NULL, \ 389362306a36Sopenharmony_ci .fw_recovery_mode = &ixgbe_fw_recovery_mode_X550, \ 389462306a36Sopenharmony_ci .enable_rx = &ixgbe_enable_rx_generic, \ 389562306a36Sopenharmony_ci .disable_rx = &ixgbe_disable_rx_x550, \ 389662306a36Sopenharmony_ci 389762306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_X550 = { 389862306a36Sopenharmony_ci X550_COMMON_MAC 389962306a36Sopenharmony_ci .led_on = ixgbe_led_on_generic, 390062306a36Sopenharmony_ci .led_off = ixgbe_led_off_generic, 390162306a36Sopenharmony_ci .init_led_link_act = ixgbe_init_led_link_act_generic, 390262306a36Sopenharmony_ci .reset_hw = &ixgbe_reset_hw_X540, 390362306a36Sopenharmony_ci .get_media_type = &ixgbe_get_media_type_X540, 390462306a36Sopenharmony_ci .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 390562306a36Sopenharmony_ci .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 390662306a36Sopenharmony_ci .setup_link = &ixgbe_setup_mac_link_X540, 390762306a36Sopenharmony_ci .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 390862306a36Sopenharmony_ci .get_bus_info = &ixgbe_get_bus_info_generic, 390962306a36Sopenharmony_ci .setup_sfp = NULL, 391062306a36Sopenharmony_ci .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, 391162306a36Sopenharmony_ci .release_swfw_sync = &ixgbe_release_swfw_sync_X540, 391262306a36Sopenharmony_ci .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 391362306a36Sopenharmony_ci .prot_autoc_read = prot_autoc_read_generic, 391462306a36Sopenharmony_ci .prot_autoc_write = prot_autoc_write_generic, 391562306a36Sopenharmony_ci .setup_fc = ixgbe_setup_fc_generic, 391662306a36Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 391762306a36Sopenharmony_ci}; 391862306a36Sopenharmony_ci 391962306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_X550EM_x = { 392062306a36Sopenharmony_ci X550_COMMON_MAC 392162306a36Sopenharmony_ci .led_on = ixgbe_led_on_t_x550em, 392262306a36Sopenharmony_ci .led_off = ixgbe_led_off_t_x550em, 392362306a36Sopenharmony_ci .init_led_link_act = ixgbe_init_led_link_act_generic, 392462306a36Sopenharmony_ci .reset_hw = &ixgbe_reset_hw_X550em, 392562306a36Sopenharmony_ci .get_media_type = &ixgbe_get_media_type_X550em, 392662306a36Sopenharmony_ci .get_san_mac_addr = NULL, 392762306a36Sopenharmony_ci .get_wwn_prefix = NULL, 392862306a36Sopenharmony_ci .setup_link = &ixgbe_setup_mac_link_X540, 392962306a36Sopenharmony_ci .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 393062306a36Sopenharmony_ci .get_bus_info = &ixgbe_get_bus_info_X550em, 393162306a36Sopenharmony_ci .setup_sfp = ixgbe_setup_sfp_modules_X550em, 393262306a36Sopenharmony_ci .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 393362306a36Sopenharmony_ci .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 393462306a36Sopenharmony_ci .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 393562306a36Sopenharmony_ci .setup_fc = NULL, /* defined later */ 393662306a36Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 393762306a36Sopenharmony_ci .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, 393862306a36Sopenharmony_ci .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, 393962306a36Sopenharmony_ci}; 394062306a36Sopenharmony_ci 394162306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_X550EM_x_fw = { 394262306a36Sopenharmony_ci X550_COMMON_MAC 394362306a36Sopenharmony_ci .led_on = NULL, 394462306a36Sopenharmony_ci .led_off = NULL, 394562306a36Sopenharmony_ci .init_led_link_act = NULL, 394662306a36Sopenharmony_ci .reset_hw = &ixgbe_reset_hw_X550em, 394762306a36Sopenharmony_ci .get_media_type = &ixgbe_get_media_type_X550em, 394862306a36Sopenharmony_ci .get_san_mac_addr = NULL, 394962306a36Sopenharmony_ci .get_wwn_prefix = NULL, 395062306a36Sopenharmony_ci .setup_link = &ixgbe_setup_mac_link_X540, 395162306a36Sopenharmony_ci .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 395262306a36Sopenharmony_ci .get_bus_info = &ixgbe_get_bus_info_X550em, 395362306a36Sopenharmony_ci .setup_sfp = ixgbe_setup_sfp_modules_X550em, 395462306a36Sopenharmony_ci .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 395562306a36Sopenharmony_ci .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 395662306a36Sopenharmony_ci .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 395762306a36Sopenharmony_ci .setup_fc = NULL, 395862306a36Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 395962306a36Sopenharmony_ci .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, 396062306a36Sopenharmony_ci .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, 396162306a36Sopenharmony_ci}; 396262306a36Sopenharmony_ci 396362306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_x550em_a = { 396462306a36Sopenharmony_ci X550_COMMON_MAC 396562306a36Sopenharmony_ci .led_on = ixgbe_led_on_t_x550em, 396662306a36Sopenharmony_ci .led_off = ixgbe_led_off_t_x550em, 396762306a36Sopenharmony_ci .init_led_link_act = ixgbe_init_led_link_act_generic, 396862306a36Sopenharmony_ci .reset_hw = ixgbe_reset_hw_X550em, 396962306a36Sopenharmony_ci .get_media_type = ixgbe_get_media_type_X550em, 397062306a36Sopenharmony_ci .get_san_mac_addr = NULL, 397162306a36Sopenharmony_ci .get_wwn_prefix = NULL, 397262306a36Sopenharmony_ci .setup_link = &ixgbe_setup_mac_link_X540, 397362306a36Sopenharmony_ci .get_link_capabilities = ixgbe_get_link_capabilities_X550em, 397462306a36Sopenharmony_ci .get_bus_info = ixgbe_get_bus_info_X550em, 397562306a36Sopenharmony_ci .setup_sfp = ixgbe_setup_sfp_modules_X550em, 397662306a36Sopenharmony_ci .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, 397762306a36Sopenharmony_ci .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, 397862306a36Sopenharmony_ci .setup_fc = ixgbe_setup_fc_x550em, 397962306a36Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 398062306a36Sopenharmony_ci .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, 398162306a36Sopenharmony_ci .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, 398262306a36Sopenharmony_ci}; 398362306a36Sopenharmony_ci 398462306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_x550em_a_fw = { 398562306a36Sopenharmony_ci X550_COMMON_MAC 398662306a36Sopenharmony_ci .led_on = ixgbe_led_on_generic, 398762306a36Sopenharmony_ci .led_off = ixgbe_led_off_generic, 398862306a36Sopenharmony_ci .init_led_link_act = ixgbe_init_led_link_act_generic, 398962306a36Sopenharmony_ci .reset_hw = ixgbe_reset_hw_X550em, 399062306a36Sopenharmony_ci .get_media_type = ixgbe_get_media_type_X550em, 399162306a36Sopenharmony_ci .get_san_mac_addr = NULL, 399262306a36Sopenharmony_ci .get_wwn_prefix = NULL, 399362306a36Sopenharmony_ci .setup_link = NULL, /* defined later */ 399462306a36Sopenharmony_ci .get_link_capabilities = ixgbe_get_link_capabilities_X550em, 399562306a36Sopenharmony_ci .get_bus_info = ixgbe_get_bus_info_X550em, 399662306a36Sopenharmony_ci .setup_sfp = ixgbe_setup_sfp_modules_X550em, 399762306a36Sopenharmony_ci .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, 399862306a36Sopenharmony_ci .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, 399962306a36Sopenharmony_ci .setup_fc = ixgbe_setup_fc_x550em, 400062306a36Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 400162306a36Sopenharmony_ci .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, 400262306a36Sopenharmony_ci .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, 400362306a36Sopenharmony_ci}; 400462306a36Sopenharmony_ci 400562306a36Sopenharmony_ci#define X550_COMMON_EEP \ 400662306a36Sopenharmony_ci .read = &ixgbe_read_ee_hostif_X550, \ 400762306a36Sopenharmony_ci .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 400862306a36Sopenharmony_ci .write = &ixgbe_write_ee_hostif_X550, \ 400962306a36Sopenharmony_ci .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 401062306a36Sopenharmony_ci .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 401162306a36Sopenharmony_ci .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 401262306a36Sopenharmony_ci .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 401362306a36Sopenharmony_ci 401462306a36Sopenharmony_cistatic const struct ixgbe_eeprom_operations eeprom_ops_X550 = { 401562306a36Sopenharmony_ci X550_COMMON_EEP 401662306a36Sopenharmony_ci .init_params = &ixgbe_init_eeprom_params_X550, 401762306a36Sopenharmony_ci}; 401862306a36Sopenharmony_ci 401962306a36Sopenharmony_cistatic const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 402062306a36Sopenharmony_ci X550_COMMON_EEP 402162306a36Sopenharmony_ci .init_params = &ixgbe_init_eeprom_params_X540, 402262306a36Sopenharmony_ci}; 402362306a36Sopenharmony_ci 402462306a36Sopenharmony_ci#define X550_COMMON_PHY \ 402562306a36Sopenharmony_ci .identify_sfp = &ixgbe_identify_module_generic, \ 402662306a36Sopenharmony_ci .reset = NULL, \ 402762306a36Sopenharmony_ci .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 402862306a36Sopenharmony_ci .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 402962306a36Sopenharmony_ci .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 403062306a36Sopenharmony_ci .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 403162306a36Sopenharmony_ci .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 403262306a36Sopenharmony_ci .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 403362306a36Sopenharmony_ci .setup_link = &ixgbe_setup_phy_link_generic, \ 403462306a36Sopenharmony_ci .set_phy_power = NULL, 403562306a36Sopenharmony_ci 403662306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_X550 = { 403762306a36Sopenharmony_ci X550_COMMON_PHY 403862306a36Sopenharmony_ci .check_overtemp = &ixgbe_tn_check_overtemp, 403962306a36Sopenharmony_ci .init = NULL, 404062306a36Sopenharmony_ci .identify = &ixgbe_identify_phy_generic, 404162306a36Sopenharmony_ci .read_reg = &ixgbe_read_phy_reg_generic, 404262306a36Sopenharmony_ci .write_reg = &ixgbe_write_phy_reg_generic, 404362306a36Sopenharmony_ci}; 404462306a36Sopenharmony_ci 404562306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_X550EM_x = { 404662306a36Sopenharmony_ci X550_COMMON_PHY 404762306a36Sopenharmony_ci .check_overtemp = &ixgbe_tn_check_overtemp, 404862306a36Sopenharmony_ci .init = &ixgbe_init_phy_ops_X550em, 404962306a36Sopenharmony_ci .identify = &ixgbe_identify_phy_x550em, 405062306a36Sopenharmony_ci .read_reg = &ixgbe_read_phy_reg_generic, 405162306a36Sopenharmony_ci .write_reg = &ixgbe_write_phy_reg_generic, 405262306a36Sopenharmony_ci}; 405362306a36Sopenharmony_ci 405462306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_x550em_x_fw = { 405562306a36Sopenharmony_ci X550_COMMON_PHY 405662306a36Sopenharmony_ci .check_overtemp = NULL, 405762306a36Sopenharmony_ci .init = ixgbe_init_phy_ops_X550em, 405862306a36Sopenharmony_ci .identify = ixgbe_identify_phy_x550em, 405962306a36Sopenharmony_ci .read_reg = NULL, 406062306a36Sopenharmony_ci .write_reg = NULL, 406162306a36Sopenharmony_ci .read_reg_mdi = NULL, 406262306a36Sopenharmony_ci .write_reg_mdi = NULL, 406362306a36Sopenharmony_ci}; 406462306a36Sopenharmony_ci 406562306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_x550em_a = { 406662306a36Sopenharmony_ci X550_COMMON_PHY 406762306a36Sopenharmony_ci .check_overtemp = &ixgbe_tn_check_overtemp, 406862306a36Sopenharmony_ci .init = &ixgbe_init_phy_ops_X550em, 406962306a36Sopenharmony_ci .identify = &ixgbe_identify_phy_x550em, 407062306a36Sopenharmony_ci .read_reg = &ixgbe_read_phy_reg_x550a, 407162306a36Sopenharmony_ci .write_reg = &ixgbe_write_phy_reg_x550a, 407262306a36Sopenharmony_ci .read_reg_mdi = &ixgbe_read_phy_reg_mdi, 407362306a36Sopenharmony_ci .write_reg_mdi = &ixgbe_write_phy_reg_mdi, 407462306a36Sopenharmony_ci}; 407562306a36Sopenharmony_ci 407662306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_x550em_a_fw = { 407762306a36Sopenharmony_ci X550_COMMON_PHY 407862306a36Sopenharmony_ci .check_overtemp = ixgbe_check_overtemp_fw, 407962306a36Sopenharmony_ci .init = ixgbe_init_phy_ops_X550em, 408062306a36Sopenharmony_ci .identify = ixgbe_identify_phy_fw, 408162306a36Sopenharmony_ci .read_reg = NULL, 408262306a36Sopenharmony_ci .write_reg = NULL, 408362306a36Sopenharmony_ci .read_reg_mdi = NULL, 408462306a36Sopenharmony_ci .write_reg_mdi = NULL, 408562306a36Sopenharmony_ci}; 408662306a36Sopenharmony_ci 408762306a36Sopenharmony_cistatic const struct ixgbe_link_operations link_ops_x550em_x = { 408862306a36Sopenharmony_ci .read_link = &ixgbe_read_i2c_combined_generic, 408962306a36Sopenharmony_ci .read_link_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, 409062306a36Sopenharmony_ci .write_link = &ixgbe_write_i2c_combined_generic, 409162306a36Sopenharmony_ci .write_link_unlocked = &ixgbe_write_i2c_combined_generic_unlocked, 409262306a36Sopenharmony_ci}; 409362306a36Sopenharmony_ci 409462306a36Sopenharmony_cistatic const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 409562306a36Sopenharmony_ci IXGBE_MVALS_INIT(X550) 409662306a36Sopenharmony_ci}; 409762306a36Sopenharmony_ci 409862306a36Sopenharmony_cistatic const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 409962306a36Sopenharmony_ci IXGBE_MVALS_INIT(X550EM_x) 410062306a36Sopenharmony_ci}; 410162306a36Sopenharmony_ci 410262306a36Sopenharmony_cistatic const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = { 410362306a36Sopenharmony_ci IXGBE_MVALS_INIT(X550EM_a) 410462306a36Sopenharmony_ci}; 410562306a36Sopenharmony_ci 410662306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_X550_info = { 410762306a36Sopenharmony_ci .mac = ixgbe_mac_X550, 410862306a36Sopenharmony_ci .get_invariants = &ixgbe_get_invariants_X540, 410962306a36Sopenharmony_ci .mac_ops = &mac_ops_X550, 411062306a36Sopenharmony_ci .eeprom_ops = &eeprom_ops_X550, 411162306a36Sopenharmony_ci .phy_ops = &phy_ops_X550, 411262306a36Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 411362306a36Sopenharmony_ci .mvals = ixgbe_mvals_X550, 411462306a36Sopenharmony_ci}; 411562306a36Sopenharmony_ci 411662306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_X550EM_x_info = { 411762306a36Sopenharmony_ci .mac = ixgbe_mac_X550EM_x, 411862306a36Sopenharmony_ci .get_invariants = &ixgbe_get_invariants_X550_x, 411962306a36Sopenharmony_ci .mac_ops = &mac_ops_X550EM_x, 412062306a36Sopenharmony_ci .eeprom_ops = &eeprom_ops_X550EM_x, 412162306a36Sopenharmony_ci .phy_ops = &phy_ops_X550EM_x, 412262306a36Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 412362306a36Sopenharmony_ci .mvals = ixgbe_mvals_X550EM_x, 412462306a36Sopenharmony_ci .link_ops = &link_ops_x550em_x, 412562306a36Sopenharmony_ci}; 412662306a36Sopenharmony_ci 412762306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_x550em_x_fw_info = { 412862306a36Sopenharmony_ci .mac = ixgbe_mac_X550EM_x, 412962306a36Sopenharmony_ci .get_invariants = ixgbe_get_invariants_X550_x_fw, 413062306a36Sopenharmony_ci .mac_ops = &mac_ops_X550EM_x_fw, 413162306a36Sopenharmony_ci .eeprom_ops = &eeprom_ops_X550EM_x, 413262306a36Sopenharmony_ci .phy_ops = &phy_ops_x550em_x_fw, 413362306a36Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 413462306a36Sopenharmony_ci .mvals = ixgbe_mvals_X550EM_x, 413562306a36Sopenharmony_ci}; 413662306a36Sopenharmony_ci 413762306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_x550em_a_info = { 413862306a36Sopenharmony_ci .mac = ixgbe_mac_x550em_a, 413962306a36Sopenharmony_ci .get_invariants = &ixgbe_get_invariants_X550_a, 414062306a36Sopenharmony_ci .mac_ops = &mac_ops_x550em_a, 414162306a36Sopenharmony_ci .eeprom_ops = &eeprom_ops_X550EM_x, 414262306a36Sopenharmony_ci .phy_ops = &phy_ops_x550em_a, 414362306a36Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 414462306a36Sopenharmony_ci .mvals = ixgbe_mvals_x550em_a, 414562306a36Sopenharmony_ci}; 414662306a36Sopenharmony_ci 414762306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_x550em_a_fw_info = { 414862306a36Sopenharmony_ci .mac = ixgbe_mac_x550em_a, 414962306a36Sopenharmony_ci .get_invariants = ixgbe_get_invariants_X550_a_fw, 415062306a36Sopenharmony_ci .mac_ops = &mac_ops_x550em_a_fw, 415162306a36Sopenharmony_ci .eeprom_ops = &eeprom_ops_X550EM_x, 415262306a36Sopenharmony_ci .phy_ops = &phy_ops_x550em_a_fw, 415362306a36Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 415462306a36Sopenharmony_ci .mvals = ixgbe_mvals_x550em_a, 415562306a36Sopenharmony_ci}; 4156