162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/pci.h> 562306a36Sopenharmony_ci#include <linux/delay.h> 662306a36Sopenharmony_ci#include <linux/sched.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "ixgbe.h" 962306a36Sopenharmony_ci#include "ixgbe_phy.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define IXGBE_82598_MAX_TX_QUEUES 32 1262306a36Sopenharmony_ci#define IXGBE_82598_MAX_RX_QUEUES 64 1362306a36Sopenharmony_ci#define IXGBE_82598_RAR_ENTRIES 16 1462306a36Sopenharmony_ci#define IXGBE_82598_MC_TBL_SIZE 128 1562306a36Sopenharmony_ci#define IXGBE_82598_VFT_TBL_SIZE 128 1662306a36Sopenharmony_ci#define IXGBE_82598_RX_PB_SIZE 512 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, 1962306a36Sopenharmony_ci ixgbe_link_speed speed, 2062306a36Sopenharmony_ci bool autoneg_wait_to_complete); 2162306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, 2262306a36Sopenharmony_ci u8 *eeprom_data); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/** 2562306a36Sopenharmony_ci * ixgbe_set_pcie_completion_timeout - set pci-e completion timeout 2662306a36Sopenharmony_ci * @hw: pointer to the HW structure 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * The defaults for 82598 should be in the range of 50us to 50ms, 2962306a36Sopenharmony_ci * however the hardware default for these parts is 500us to 1ms which is less 3062306a36Sopenharmony_ci * than the 10ms recommended by the pci-e spec. To address this we need to 3162306a36Sopenharmony_ci * increase the value to either 10ms to 250ms for capability version 1 config, 3262306a36Sopenharmony_ci * or 16ms to 55ms for version 2. 3362306a36Sopenharmony_ci **/ 3462306a36Sopenharmony_cistatic void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR); 3762306a36Sopenharmony_ci u16 pcie_devctl2; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci if (ixgbe_removed(hw->hw_addr)) 4062306a36Sopenharmony_ci return; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci /* only take action if timeout value is defaulted to 0 */ 4362306a36Sopenharmony_ci if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK) 4462306a36Sopenharmony_ci goto out; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci /* 4762306a36Sopenharmony_ci * if capababilities version is type 1 we can write the 4862306a36Sopenharmony_ci * timeout of 10ms to 250ms through the GCR register 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_ci if (!(gcr & IXGBE_GCR_CAP_VER2)) { 5162306a36Sopenharmony_ci gcr |= IXGBE_GCR_CMPL_TMOUT_10ms; 5262306a36Sopenharmony_ci goto out; 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* 5662306a36Sopenharmony_ci * for version 2 capabilities we need to write the config space 5762306a36Sopenharmony_ci * directly in order to set the completion timeout value for 5862306a36Sopenharmony_ci * 16ms to 55ms 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_ci pcie_devctl2 = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_CONTROL2); 6162306a36Sopenharmony_ci pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms; 6262306a36Sopenharmony_ci ixgbe_write_pci_cfg_word(hw, IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2); 6362306a36Sopenharmony_ciout: 6462306a36Sopenharmony_ci /* disable completion timeout resend */ 6562306a36Sopenharmony_ci gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND; 6662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci /* Call PHY identify routine to get the phy type */ 7462306a36Sopenharmony_ci ixgbe_identify_phy_generic(hw); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci mac->mcft_size = IXGBE_82598_MC_TBL_SIZE; 7762306a36Sopenharmony_ci mac->vft_size = IXGBE_82598_VFT_TBL_SIZE; 7862306a36Sopenharmony_ci mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES; 7962306a36Sopenharmony_ci mac->rx_pb_size = IXGBE_82598_RX_PB_SIZE; 8062306a36Sopenharmony_ci mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES; 8162306a36Sopenharmony_ci mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES; 8262306a36Sopenharmony_ci mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/** 8862306a36Sopenharmony_ci * ixgbe_init_phy_ops_82598 - PHY/SFP specific init 8962306a36Sopenharmony_ci * @hw: pointer to hardware structure 9062306a36Sopenharmony_ci * 9162306a36Sopenharmony_ci * Initialize any function pointers that were not able to be 9262306a36Sopenharmony_ci * set during get_invariants because the PHY/SFP type was 9362306a36Sopenharmony_ci * not known. Perform the SFP init if necessary. 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci **/ 9662306a36Sopenharmony_cistatic s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 9962306a36Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 10062306a36Sopenharmony_ci s32 ret_val; 10162306a36Sopenharmony_ci u16 list_offset, data_offset; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* Identify the PHY */ 10462306a36Sopenharmony_ci phy->ops.identify(hw); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci /* Overwrite the link function pointers if copper PHY */ 10762306a36Sopenharmony_ci if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { 10862306a36Sopenharmony_ci mac->ops.setup_link = &ixgbe_setup_copper_link_82598; 10962306a36Sopenharmony_ci mac->ops.get_link_capabilities = 11062306a36Sopenharmony_ci &ixgbe_get_copper_link_capabilities_generic; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci switch (hw->phy.type) { 11462306a36Sopenharmony_ci case ixgbe_phy_tn: 11562306a36Sopenharmony_ci phy->ops.setup_link = &ixgbe_setup_phy_link_tnx; 11662306a36Sopenharmony_ci phy->ops.check_link = &ixgbe_check_phy_link_tnx; 11762306a36Sopenharmony_ci break; 11862306a36Sopenharmony_ci case ixgbe_phy_nl: 11962306a36Sopenharmony_ci phy->ops.reset = &ixgbe_reset_phy_nl; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* Call SFP+ identify routine to get the SFP+ module type */ 12262306a36Sopenharmony_ci ret_val = phy->ops.identify_sfp(hw); 12362306a36Sopenharmony_ci if (ret_val) 12462306a36Sopenharmony_ci return ret_val; 12562306a36Sopenharmony_ci if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) 12662306a36Sopenharmony_ci return -EOPNOTSUPP; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* Check to see if SFP+ module is supported */ 12962306a36Sopenharmony_ci ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, 13062306a36Sopenharmony_ci &list_offset, 13162306a36Sopenharmony_ci &data_offset); 13262306a36Sopenharmony_ci if (ret_val) 13362306a36Sopenharmony_ci return -EOPNOTSUPP; 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci default: 13662306a36Sopenharmony_ci break; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return 0; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci/** 14362306a36Sopenharmony_ci * ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx 14462306a36Sopenharmony_ci * @hw: pointer to hardware structure 14562306a36Sopenharmony_ci * 14662306a36Sopenharmony_ci * Starts the hardware using the generic start_hw function. 14762306a36Sopenharmony_ci * Disables relaxed ordering for archs other than SPARC 14862306a36Sopenharmony_ci * Then set pcie completion timeout 14962306a36Sopenharmony_ci * 15062306a36Sopenharmony_ci **/ 15162306a36Sopenharmony_cistatic s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci s32 ret_val; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci ret_val = ixgbe_start_hw_generic(hw); 15662306a36Sopenharmony_ci if (ret_val) 15762306a36Sopenharmony_ci return ret_val; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* set the completion timeout for interface */ 16062306a36Sopenharmony_ci ixgbe_set_pcie_completion_timeout(hw); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci return 0; 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci/** 16662306a36Sopenharmony_ci * ixgbe_get_link_capabilities_82598 - Determines link capabilities 16762306a36Sopenharmony_ci * @hw: pointer to hardware structure 16862306a36Sopenharmony_ci * @speed: pointer to link speed 16962306a36Sopenharmony_ci * @autoneg: boolean auto-negotiation value 17062306a36Sopenharmony_ci * 17162306a36Sopenharmony_ci * Determines the link capabilities by reading the AUTOC register. 17262306a36Sopenharmony_ci **/ 17362306a36Sopenharmony_cistatic s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, 17462306a36Sopenharmony_ci ixgbe_link_speed *speed, 17562306a36Sopenharmony_ci bool *autoneg) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci u32 autoc = 0; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /* 18062306a36Sopenharmony_ci * Determine link capabilities based on the stored value of AUTOC, 18162306a36Sopenharmony_ci * which represents EEPROM defaults. If AUTOC value has not been 18262306a36Sopenharmony_ci * stored, use the current register value. 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_ci if (hw->mac.orig_link_settings_stored) 18562306a36Sopenharmony_ci autoc = hw->mac.orig_autoc; 18662306a36Sopenharmony_ci else 18762306a36Sopenharmony_ci autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci switch (autoc & IXGBE_AUTOC_LMS_MASK) { 19062306a36Sopenharmony_ci case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: 19162306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 19262306a36Sopenharmony_ci *autoneg = false; 19362306a36Sopenharmony_ci break; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: 19662306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL; 19762306a36Sopenharmony_ci *autoneg = false; 19862306a36Sopenharmony_ci break; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci case IXGBE_AUTOC_LMS_1G_AN: 20162306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 20262306a36Sopenharmony_ci *autoneg = true; 20362306a36Sopenharmony_ci break; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci case IXGBE_AUTOC_LMS_KX4_AN: 20662306a36Sopenharmony_ci case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: 20762306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_UNKNOWN; 20862306a36Sopenharmony_ci if (autoc & IXGBE_AUTOC_KX4_SUPP) 20962306a36Sopenharmony_ci *speed |= IXGBE_LINK_SPEED_10GB_FULL; 21062306a36Sopenharmony_ci if (autoc & IXGBE_AUTOC_KX_SUPP) 21162306a36Sopenharmony_ci *speed |= IXGBE_LINK_SPEED_1GB_FULL; 21262306a36Sopenharmony_ci *autoneg = true; 21362306a36Sopenharmony_ci break; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci default: 21662306a36Sopenharmony_ci return -EIO; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci return 0; 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci/** 22362306a36Sopenharmony_ci * ixgbe_get_media_type_82598 - Determines media type 22462306a36Sopenharmony_ci * @hw: pointer to hardware structure 22562306a36Sopenharmony_ci * 22662306a36Sopenharmony_ci * Returns the media type (fiber, copper, backplane) 22762306a36Sopenharmony_ci **/ 22862306a36Sopenharmony_cistatic enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci /* Detect if there is a copper PHY attached. */ 23162306a36Sopenharmony_ci switch (hw->phy.type) { 23262306a36Sopenharmony_ci case ixgbe_phy_cu_unknown: 23362306a36Sopenharmony_ci case ixgbe_phy_tn: 23462306a36Sopenharmony_ci return ixgbe_media_type_copper; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci default: 23762306a36Sopenharmony_ci break; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci /* Media type for I82598 is based on device ID */ 24162306a36Sopenharmony_ci switch (hw->device_id) { 24262306a36Sopenharmony_ci case IXGBE_DEV_ID_82598: 24362306a36Sopenharmony_ci case IXGBE_DEV_ID_82598_BX: 24462306a36Sopenharmony_ci /* Default device ID is mezzanine card KX/KX4 */ 24562306a36Sopenharmony_ci return ixgbe_media_type_backplane; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci case IXGBE_DEV_ID_82598AF_DUAL_PORT: 24862306a36Sopenharmony_ci case IXGBE_DEV_ID_82598AF_SINGLE_PORT: 24962306a36Sopenharmony_ci case IXGBE_DEV_ID_82598_DA_DUAL_PORT: 25062306a36Sopenharmony_ci case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: 25162306a36Sopenharmony_ci case IXGBE_DEV_ID_82598EB_XF_LR: 25262306a36Sopenharmony_ci case IXGBE_DEV_ID_82598EB_SFP_LOM: 25362306a36Sopenharmony_ci return ixgbe_media_type_fiber; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci case IXGBE_DEV_ID_82598EB_CX4: 25662306a36Sopenharmony_ci case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: 25762306a36Sopenharmony_ci return ixgbe_media_type_cx4; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci case IXGBE_DEV_ID_82598AT: 26062306a36Sopenharmony_ci case IXGBE_DEV_ID_82598AT2: 26162306a36Sopenharmony_ci return ixgbe_media_type_copper; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci default: 26462306a36Sopenharmony_ci return ixgbe_media_type_unknown; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci/** 26962306a36Sopenharmony_ci * ixgbe_fc_enable_82598 - Enable flow control 27062306a36Sopenharmony_ci * @hw: pointer to hardware structure 27162306a36Sopenharmony_ci * 27262306a36Sopenharmony_ci * Enable flow control according to the current settings. 27362306a36Sopenharmony_ci **/ 27462306a36Sopenharmony_cistatic s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci u32 fctrl_reg; 27762306a36Sopenharmony_ci u32 rmcs_reg; 27862306a36Sopenharmony_ci u32 reg; 27962306a36Sopenharmony_ci u32 fcrtl, fcrth; 28062306a36Sopenharmony_ci u32 link_speed = 0; 28162306a36Sopenharmony_ci int i; 28262306a36Sopenharmony_ci bool link_up; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci /* Validate the water mark configuration */ 28562306a36Sopenharmony_ci if (!hw->fc.pause_time) 28662306a36Sopenharmony_ci return -EINVAL; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* Low water mark of zero causes XOFF floods */ 28962306a36Sopenharmony_ci for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { 29062306a36Sopenharmony_ci if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 29162306a36Sopenharmony_ci hw->fc.high_water[i]) { 29262306a36Sopenharmony_ci if (!hw->fc.low_water[i] || 29362306a36Sopenharmony_ci hw->fc.low_water[i] >= hw->fc.high_water[i]) { 29462306a36Sopenharmony_ci hw_dbg(hw, "Invalid water mark configuration\n"); 29562306a36Sopenharmony_ci return -EINVAL; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* 30162306a36Sopenharmony_ci * On 82598 having Rx FC on causes resets while doing 1G 30262306a36Sopenharmony_ci * so if it's on turn it off once we know link_speed. For 30362306a36Sopenharmony_ci * more details see 82598 Specification update. 30462306a36Sopenharmony_ci */ 30562306a36Sopenharmony_ci hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 30662306a36Sopenharmony_ci if (link_up && link_speed == IXGBE_LINK_SPEED_1GB_FULL) { 30762306a36Sopenharmony_ci switch (hw->fc.requested_mode) { 30862306a36Sopenharmony_ci case ixgbe_fc_full: 30962306a36Sopenharmony_ci hw->fc.requested_mode = ixgbe_fc_tx_pause; 31062306a36Sopenharmony_ci break; 31162306a36Sopenharmony_ci case ixgbe_fc_rx_pause: 31262306a36Sopenharmony_ci hw->fc.requested_mode = ixgbe_fc_none; 31362306a36Sopenharmony_ci break; 31462306a36Sopenharmony_ci default: 31562306a36Sopenharmony_ci /* no change */ 31662306a36Sopenharmony_ci break; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci /* Negotiate the fc mode to use */ 32162306a36Sopenharmony_ci hw->mac.ops.fc_autoneg(hw); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* Disable any previous flow control settings */ 32462306a36Sopenharmony_ci fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); 32562306a36Sopenharmony_ci fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS); 32862306a36Sopenharmony_ci rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* 33162306a36Sopenharmony_ci * The possible values of fc.current_mode are: 33262306a36Sopenharmony_ci * 0: Flow control is completely disabled 33362306a36Sopenharmony_ci * 1: Rx flow control is enabled (we can receive pause frames, 33462306a36Sopenharmony_ci * but not send pause frames). 33562306a36Sopenharmony_ci * 2: Tx flow control is enabled (we can send pause frames but 33662306a36Sopenharmony_ci * we do not support receiving pause frames). 33762306a36Sopenharmony_ci * 3: Both Rx and Tx flow control (symmetric) are enabled. 33862306a36Sopenharmony_ci * other: Invalid. 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_ci switch (hw->fc.current_mode) { 34162306a36Sopenharmony_ci case ixgbe_fc_none: 34262306a36Sopenharmony_ci /* 34362306a36Sopenharmony_ci * Flow control is disabled by software override or autoneg. 34462306a36Sopenharmony_ci * The code below will actually disable it in the HW. 34562306a36Sopenharmony_ci */ 34662306a36Sopenharmony_ci break; 34762306a36Sopenharmony_ci case ixgbe_fc_rx_pause: 34862306a36Sopenharmony_ci /* 34962306a36Sopenharmony_ci * Rx Flow control is enabled and Tx Flow control is 35062306a36Sopenharmony_ci * disabled by software override. Since there really 35162306a36Sopenharmony_ci * isn't a way to advertise that we are capable of RX 35262306a36Sopenharmony_ci * Pause ONLY, we will advertise that we support both 35362306a36Sopenharmony_ci * symmetric and asymmetric Rx PAUSE. Later, we will 35462306a36Sopenharmony_ci * disable the adapter's ability to send PAUSE frames. 35562306a36Sopenharmony_ci */ 35662306a36Sopenharmony_ci fctrl_reg |= IXGBE_FCTRL_RFCE; 35762306a36Sopenharmony_ci break; 35862306a36Sopenharmony_ci case ixgbe_fc_tx_pause: 35962306a36Sopenharmony_ci /* 36062306a36Sopenharmony_ci * Tx Flow control is enabled, and Rx Flow control is 36162306a36Sopenharmony_ci * disabled by software override. 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_ci rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; 36462306a36Sopenharmony_ci break; 36562306a36Sopenharmony_ci case ixgbe_fc_full: 36662306a36Sopenharmony_ci /* Flow control (both Rx and Tx) is enabled by SW override. */ 36762306a36Sopenharmony_ci fctrl_reg |= IXGBE_FCTRL_RFCE; 36862306a36Sopenharmony_ci rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; 36962306a36Sopenharmony_ci break; 37062306a36Sopenharmony_ci default: 37162306a36Sopenharmony_ci hw_dbg(hw, "Flow control param set incorrectly\n"); 37262306a36Sopenharmony_ci return -EIO; 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci /* Set 802.3x based flow control settings. */ 37662306a36Sopenharmony_ci fctrl_reg |= IXGBE_FCTRL_DPF; 37762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg); 37862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* Set up and enable Rx high/low water mark thresholds, enable XON. */ 38162306a36Sopenharmony_ci for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { 38262306a36Sopenharmony_ci if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 38362306a36Sopenharmony_ci hw->fc.high_water[i]) { 38462306a36Sopenharmony_ci fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; 38562306a36Sopenharmony_ci fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; 38662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl); 38762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), fcrth); 38862306a36Sopenharmony_ci } else { 38962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0); 39062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0); 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci /* Configure pause time (2 TCs per register) */ 39662306a36Sopenharmony_ci reg = hw->fc.pause_time * 0x00010001; 39762306a36Sopenharmony_ci for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++) 39862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci /* Configure flow control refresh threshold value */ 40162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci return 0; 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci/** 40762306a36Sopenharmony_ci * ixgbe_start_mac_link_82598 - Configures MAC link settings 40862306a36Sopenharmony_ci * @hw: pointer to hardware structure 40962306a36Sopenharmony_ci * @autoneg_wait_to_complete: true when waiting for completion is needed 41062306a36Sopenharmony_ci * 41162306a36Sopenharmony_ci * Configures link settings based on values in the ixgbe_hw struct. 41262306a36Sopenharmony_ci * Restarts the link. Performs autonegotiation if needed. 41362306a36Sopenharmony_ci **/ 41462306a36Sopenharmony_cistatic s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw, 41562306a36Sopenharmony_ci bool autoneg_wait_to_complete) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci u32 autoc_reg; 41862306a36Sopenharmony_ci u32 links_reg; 41962306a36Sopenharmony_ci u32 i; 42062306a36Sopenharmony_ci s32 status = 0; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci /* Restart link */ 42362306a36Sopenharmony_ci autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 42462306a36Sopenharmony_ci autoc_reg |= IXGBE_AUTOC_AN_RESTART; 42562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci /* Only poll for autoneg to complete if specified to do so */ 42862306a36Sopenharmony_ci if (autoneg_wait_to_complete) { 42962306a36Sopenharmony_ci if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == 43062306a36Sopenharmony_ci IXGBE_AUTOC_LMS_KX4_AN || 43162306a36Sopenharmony_ci (autoc_reg & IXGBE_AUTOC_LMS_MASK) == 43262306a36Sopenharmony_ci IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { 43362306a36Sopenharmony_ci links_reg = 0; /* Just in case Autoneg time = 0 */ 43462306a36Sopenharmony_ci for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { 43562306a36Sopenharmony_ci links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 43662306a36Sopenharmony_ci if (links_reg & IXGBE_LINKS_KX_AN_COMP) 43762306a36Sopenharmony_ci break; 43862306a36Sopenharmony_ci msleep(100); 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { 44162306a36Sopenharmony_ci status = -EIO; 44262306a36Sopenharmony_ci hw_dbg(hw, "Autonegotiation did not complete.\n"); 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci /* Add delay to filter out noises during initial link setup */ 44862306a36Sopenharmony_ci msleep(50); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci return status; 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci/** 45462306a36Sopenharmony_ci * ixgbe_validate_link_ready - Function looks for phy link 45562306a36Sopenharmony_ci * @hw: pointer to hardware structure 45662306a36Sopenharmony_ci * 45762306a36Sopenharmony_ci * Function indicates success when phy link is available. If phy is not ready 45862306a36Sopenharmony_ci * within 5 seconds of MAC indicating link, the function returns error. 45962306a36Sopenharmony_ci **/ 46062306a36Sopenharmony_cistatic s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci u32 timeout; 46362306a36Sopenharmony_ci u16 an_reg; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci if (hw->device_id != IXGBE_DEV_ID_82598AT2) 46662306a36Sopenharmony_ci return 0; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci for (timeout = 0; 46962306a36Sopenharmony_ci timeout < IXGBE_VALIDATE_LINK_READY_TIMEOUT; timeout++) { 47062306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, &an_reg); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci if ((an_reg & MDIO_AN_STAT1_COMPLETE) && 47362306a36Sopenharmony_ci (an_reg & MDIO_STAT1_LSTATUS)) 47462306a36Sopenharmony_ci break; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci msleep(100); 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (timeout == IXGBE_VALIDATE_LINK_READY_TIMEOUT) { 48062306a36Sopenharmony_ci hw_dbg(hw, "Link was indicated but link is down\n"); 48162306a36Sopenharmony_ci return -EIO; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci return 0; 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci/** 48862306a36Sopenharmony_ci * ixgbe_check_mac_link_82598 - Get link/speed status 48962306a36Sopenharmony_ci * @hw: pointer to hardware structure 49062306a36Sopenharmony_ci * @speed: pointer to link speed 49162306a36Sopenharmony_ci * @link_up: true is link is up, false otherwise 49262306a36Sopenharmony_ci * @link_up_wait_to_complete: bool used to wait for link up or not 49362306a36Sopenharmony_ci * 49462306a36Sopenharmony_ci * Reads the links register to determine if link is up and the current speed 49562306a36Sopenharmony_ci **/ 49662306a36Sopenharmony_cistatic s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, 49762306a36Sopenharmony_ci ixgbe_link_speed *speed, bool *link_up, 49862306a36Sopenharmony_ci bool link_up_wait_to_complete) 49962306a36Sopenharmony_ci{ 50062306a36Sopenharmony_ci u32 links_reg; 50162306a36Sopenharmony_ci u32 i; 50262306a36Sopenharmony_ci u16 link_reg, adapt_comp_reg; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci /* 50562306a36Sopenharmony_ci * SERDES PHY requires us to read link status from register 0xC79F. 50662306a36Sopenharmony_ci * Bit 0 set indicates link is up/ready; clear indicates link down. 50762306a36Sopenharmony_ci * 0xC00C is read to check that the XAUI lanes are active. Bit 0 50862306a36Sopenharmony_ci * clear indicates active; set indicates inactive. 50962306a36Sopenharmony_ci */ 51062306a36Sopenharmony_ci if (hw->phy.type == ixgbe_phy_nl) { 51162306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, 0xC79F, MDIO_MMD_PMAPMD, &link_reg); 51262306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, 0xC79F, MDIO_MMD_PMAPMD, &link_reg); 51362306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, 0xC00C, MDIO_MMD_PMAPMD, 51462306a36Sopenharmony_ci &adapt_comp_reg); 51562306a36Sopenharmony_ci if (link_up_wait_to_complete) { 51662306a36Sopenharmony_ci for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { 51762306a36Sopenharmony_ci if ((link_reg & 1) && 51862306a36Sopenharmony_ci ((adapt_comp_reg & 1) == 0)) { 51962306a36Sopenharmony_ci *link_up = true; 52062306a36Sopenharmony_ci break; 52162306a36Sopenharmony_ci } else { 52262306a36Sopenharmony_ci *link_up = false; 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci msleep(100); 52562306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, 0xC79F, 52662306a36Sopenharmony_ci MDIO_MMD_PMAPMD, 52762306a36Sopenharmony_ci &link_reg); 52862306a36Sopenharmony_ci hw->phy.ops.read_reg(hw, 0xC00C, 52962306a36Sopenharmony_ci MDIO_MMD_PMAPMD, 53062306a36Sopenharmony_ci &adapt_comp_reg); 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci } else { 53362306a36Sopenharmony_ci if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0)) 53462306a36Sopenharmony_ci *link_up = true; 53562306a36Sopenharmony_ci else 53662306a36Sopenharmony_ci *link_up = false; 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci if (!*link_up) 54062306a36Sopenharmony_ci return 0; 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 54462306a36Sopenharmony_ci if (link_up_wait_to_complete) { 54562306a36Sopenharmony_ci for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { 54662306a36Sopenharmony_ci if (links_reg & IXGBE_LINKS_UP) { 54762306a36Sopenharmony_ci *link_up = true; 54862306a36Sopenharmony_ci break; 54962306a36Sopenharmony_ci } else { 55062306a36Sopenharmony_ci *link_up = false; 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci msleep(100); 55362306a36Sopenharmony_ci links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci } else { 55662306a36Sopenharmony_ci if (links_reg & IXGBE_LINKS_UP) 55762306a36Sopenharmony_ci *link_up = true; 55862306a36Sopenharmony_ci else 55962306a36Sopenharmony_ci *link_up = false; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (links_reg & IXGBE_LINKS_SPEED) 56362306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL; 56462306a36Sopenharmony_ci else 56562306a36Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && *link_up && 56862306a36Sopenharmony_ci (ixgbe_validate_link_ready(hw) != 0)) 56962306a36Sopenharmony_ci *link_up = false; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci return 0; 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci/** 57562306a36Sopenharmony_ci * ixgbe_setup_mac_link_82598 - Set MAC link speed 57662306a36Sopenharmony_ci * @hw: pointer to hardware structure 57762306a36Sopenharmony_ci * @speed: new link speed 57862306a36Sopenharmony_ci * @autoneg_wait_to_complete: true when waiting for completion is needed 57962306a36Sopenharmony_ci * 58062306a36Sopenharmony_ci * Set the link speed in the AUTOC register and restarts link. 58162306a36Sopenharmony_ci **/ 58262306a36Sopenharmony_cistatic s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw, 58362306a36Sopenharmony_ci ixgbe_link_speed speed, 58462306a36Sopenharmony_ci bool autoneg_wait_to_complete) 58562306a36Sopenharmony_ci{ 58662306a36Sopenharmony_ci bool autoneg = false; 58762306a36Sopenharmony_ci ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; 58862306a36Sopenharmony_ci u32 curr_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); 58962306a36Sopenharmony_ci u32 autoc = curr_autoc; 59062306a36Sopenharmony_ci u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci /* Check to see if speed passed in is supported. */ 59362306a36Sopenharmony_ci ixgbe_get_link_capabilities_82598(hw, &link_capabilities, &autoneg); 59462306a36Sopenharmony_ci speed &= link_capabilities; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci if (speed == IXGBE_LINK_SPEED_UNKNOWN) 59762306a36Sopenharmony_ci return -EINVAL; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci /* Set KX4/KX support according to speed requested */ 60062306a36Sopenharmony_ci else if (link_mode == IXGBE_AUTOC_LMS_KX4_AN || 60162306a36Sopenharmony_ci link_mode == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { 60262306a36Sopenharmony_ci autoc &= ~IXGBE_AUTOC_KX4_KX_SUPP_MASK; 60362306a36Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_10GB_FULL) 60462306a36Sopenharmony_ci autoc |= IXGBE_AUTOC_KX4_SUPP; 60562306a36Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_1GB_FULL) 60662306a36Sopenharmony_ci autoc |= IXGBE_AUTOC_KX_SUPP; 60762306a36Sopenharmony_ci if (autoc != curr_autoc) 60862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci /* Setup and restart the link based on the new values in 61262306a36Sopenharmony_ci * ixgbe_hw This will write the AUTOC register based on the new 61362306a36Sopenharmony_ci * stored values 61462306a36Sopenharmony_ci */ 61562306a36Sopenharmony_ci return ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete); 61662306a36Sopenharmony_ci} 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci/** 62062306a36Sopenharmony_ci * ixgbe_setup_copper_link_82598 - Set the PHY autoneg advertised field 62162306a36Sopenharmony_ci * @hw: pointer to hardware structure 62262306a36Sopenharmony_ci * @speed: new link speed 62362306a36Sopenharmony_ci * @autoneg_wait_to_complete: true if waiting is needed to complete 62462306a36Sopenharmony_ci * 62562306a36Sopenharmony_ci * Sets the link speed in the AUTOC register in the MAC and restarts link. 62662306a36Sopenharmony_ci **/ 62762306a36Sopenharmony_cistatic s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, 62862306a36Sopenharmony_ci ixgbe_link_speed speed, 62962306a36Sopenharmony_ci bool autoneg_wait_to_complete) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci s32 status; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci /* Setup the PHY according to input speed */ 63462306a36Sopenharmony_ci status = hw->phy.ops.setup_link_speed(hw, speed, 63562306a36Sopenharmony_ci autoneg_wait_to_complete); 63662306a36Sopenharmony_ci /* Set up MAC */ 63762306a36Sopenharmony_ci ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci return status; 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci/** 64362306a36Sopenharmony_ci * ixgbe_reset_hw_82598 - Performs hardware reset 64462306a36Sopenharmony_ci * @hw: pointer to hardware structure 64562306a36Sopenharmony_ci * 64662306a36Sopenharmony_ci * Resets the hardware by resetting the transmit and receive units, masks and 64762306a36Sopenharmony_ci * clears all interrupts, performing a PHY reset, and performing a link (MAC) 64862306a36Sopenharmony_ci * reset. 64962306a36Sopenharmony_ci **/ 65062306a36Sopenharmony_cistatic s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) 65162306a36Sopenharmony_ci{ 65262306a36Sopenharmony_ci s32 status; 65362306a36Sopenharmony_ci s32 phy_status = 0; 65462306a36Sopenharmony_ci u32 ctrl; 65562306a36Sopenharmony_ci u32 gheccr; 65662306a36Sopenharmony_ci u32 i; 65762306a36Sopenharmony_ci u32 autoc; 65862306a36Sopenharmony_ci u8 analog_val; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci /* Call adapter stop to disable tx/rx and clear interrupts */ 66162306a36Sopenharmony_ci status = hw->mac.ops.stop_adapter(hw); 66262306a36Sopenharmony_ci if (status) 66362306a36Sopenharmony_ci return status; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci /* 66662306a36Sopenharmony_ci * Power up the Atlas Tx lanes if they are currently powered down. 66762306a36Sopenharmony_ci * Atlas Tx lanes are powered down for MAC loopback tests, but 66862306a36Sopenharmony_ci * they are not automatically restored on reset. 66962306a36Sopenharmony_ci */ 67062306a36Sopenharmony_ci hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); 67162306a36Sopenharmony_ci if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) { 67262306a36Sopenharmony_ci /* Enable Tx Atlas so packets can be transmitted again */ 67362306a36Sopenharmony_ci hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, 67462306a36Sopenharmony_ci &analog_val); 67562306a36Sopenharmony_ci analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN; 67662306a36Sopenharmony_ci hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, 67762306a36Sopenharmony_ci analog_val); 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, 68062306a36Sopenharmony_ci &analog_val); 68162306a36Sopenharmony_ci analog_val &= ~IXGBE_ATLAS_PDN_TX_10G_QL_ALL; 68262306a36Sopenharmony_ci hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, 68362306a36Sopenharmony_ci analog_val); 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, 68662306a36Sopenharmony_ci &analog_val); 68762306a36Sopenharmony_ci analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL; 68862306a36Sopenharmony_ci hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, 68962306a36Sopenharmony_ci analog_val); 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, 69262306a36Sopenharmony_ci &analog_val); 69362306a36Sopenharmony_ci analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL; 69462306a36Sopenharmony_ci hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, 69562306a36Sopenharmony_ci analog_val); 69662306a36Sopenharmony_ci } 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci /* Reset PHY */ 69962306a36Sopenharmony_ci if (hw->phy.reset_disable == false) { 70062306a36Sopenharmony_ci /* PHY ops must be identified and initialized prior to reset */ 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci /* Init PHY and function pointers, perform SFP setup */ 70362306a36Sopenharmony_ci phy_status = hw->phy.ops.init(hw); 70462306a36Sopenharmony_ci if (phy_status == -EOPNOTSUPP) 70562306a36Sopenharmony_ci return phy_status; 70662306a36Sopenharmony_ci if (phy_status == -ENOENT) 70762306a36Sopenharmony_ci goto mac_reset_top; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci hw->phy.ops.reset(hw); 71062306a36Sopenharmony_ci } 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_cimac_reset_top: 71362306a36Sopenharmony_ci /* 71462306a36Sopenharmony_ci * Issue global reset to the MAC. This needs to be a SW reset. 71562306a36Sopenharmony_ci * If link reset is used, it might reset the MAC when mng is using it 71662306a36Sopenharmony_ci */ 71762306a36Sopenharmony_ci ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL) | IXGBE_CTRL_RST; 71862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 71962306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 72062306a36Sopenharmony_ci usleep_range(1000, 1200); 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci /* Poll for reset bit to self-clear indicating reset is complete */ 72362306a36Sopenharmony_ci for (i = 0; i < 10; i++) { 72462306a36Sopenharmony_ci ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 72562306a36Sopenharmony_ci if (!(ctrl & IXGBE_CTRL_RST)) 72662306a36Sopenharmony_ci break; 72762306a36Sopenharmony_ci udelay(1); 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci if (ctrl & IXGBE_CTRL_RST) { 73062306a36Sopenharmony_ci status = -EIO; 73162306a36Sopenharmony_ci hw_dbg(hw, "Reset polling failed to complete.\n"); 73262306a36Sopenharmony_ci } 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci msleep(50); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci /* 73762306a36Sopenharmony_ci * Double resets are required for recovery from certain error 73862306a36Sopenharmony_ci * conditions. Between resets, it is necessary to stall to allow time 73962306a36Sopenharmony_ci * for any pending HW events to complete. 74062306a36Sopenharmony_ci */ 74162306a36Sopenharmony_ci if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 74262306a36Sopenharmony_ci hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 74362306a36Sopenharmony_ci goto mac_reset_top; 74462306a36Sopenharmony_ci } 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR); 74762306a36Sopenharmony_ci gheccr &= ~(BIT(21) | BIT(18) | BIT(9) | BIT(6)); 74862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci /* 75162306a36Sopenharmony_ci * Store the original AUTOC value if it has not been 75262306a36Sopenharmony_ci * stored off yet. Otherwise restore the stored original 75362306a36Sopenharmony_ci * AUTOC value since the reset operation sets back to deaults. 75462306a36Sopenharmony_ci */ 75562306a36Sopenharmony_ci autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); 75662306a36Sopenharmony_ci if (hw->mac.orig_link_settings_stored == false) { 75762306a36Sopenharmony_ci hw->mac.orig_autoc = autoc; 75862306a36Sopenharmony_ci hw->mac.orig_link_settings_stored = true; 75962306a36Sopenharmony_ci } else if (autoc != hw->mac.orig_autoc) { 76062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc); 76162306a36Sopenharmony_ci } 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci /* Store the permanent mac address */ 76462306a36Sopenharmony_ci hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci /* 76762306a36Sopenharmony_ci * Store MAC address from RAR0, clear receive address registers, and 76862306a36Sopenharmony_ci * clear the multicast table 76962306a36Sopenharmony_ci */ 77062306a36Sopenharmony_ci hw->mac.ops.init_rx_addrs(hw); 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci if (phy_status) 77362306a36Sopenharmony_ci status = phy_status; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci return status; 77662306a36Sopenharmony_ci} 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci/** 77962306a36Sopenharmony_ci * ixgbe_set_vmdq_82598 - Associate a VMDq set index with a rx address 78062306a36Sopenharmony_ci * @hw: pointer to hardware struct 78162306a36Sopenharmony_ci * @rar: receive address register index to associate with a VMDq index 78262306a36Sopenharmony_ci * @vmdq: VMDq set index 78362306a36Sopenharmony_ci **/ 78462306a36Sopenharmony_cistatic s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci u32 rar_high; 78762306a36Sopenharmony_ci u32 rar_entries = hw->mac.num_rar_entries; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci /* Make sure we are using a valid rar index range */ 79062306a36Sopenharmony_ci if (rar >= rar_entries) { 79162306a36Sopenharmony_ci hw_dbg(hw, "RAR index %d is out of range.\n", rar); 79262306a36Sopenharmony_ci return -EINVAL; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); 79662306a36Sopenharmony_ci rar_high &= ~IXGBE_RAH_VIND_MASK; 79762306a36Sopenharmony_ci rar_high |= ((vmdq << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK); 79862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high); 79962306a36Sopenharmony_ci return 0; 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci/** 80362306a36Sopenharmony_ci * ixgbe_clear_vmdq_82598 - Disassociate a VMDq set index from an rx address 80462306a36Sopenharmony_ci * @hw: pointer to hardware struct 80562306a36Sopenharmony_ci * @rar: receive address register index to associate with a VMDq index 80662306a36Sopenharmony_ci * @vmdq: VMDq clear index (not used in 82598, but elsewhere) 80762306a36Sopenharmony_ci **/ 80862306a36Sopenharmony_cistatic s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 80962306a36Sopenharmony_ci{ 81062306a36Sopenharmony_ci u32 rar_high; 81162306a36Sopenharmony_ci u32 rar_entries = hw->mac.num_rar_entries; 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci /* Make sure we are using a valid rar index range */ 81562306a36Sopenharmony_ci if (rar >= rar_entries) { 81662306a36Sopenharmony_ci hw_dbg(hw, "RAR index %d is out of range.\n", rar); 81762306a36Sopenharmony_ci return -EINVAL; 81862306a36Sopenharmony_ci } 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); 82162306a36Sopenharmony_ci if (rar_high & IXGBE_RAH_VIND_MASK) { 82262306a36Sopenharmony_ci rar_high &= ~IXGBE_RAH_VIND_MASK; 82362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high); 82462306a36Sopenharmony_ci } 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci return 0; 82762306a36Sopenharmony_ci} 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci/** 83062306a36Sopenharmony_ci * ixgbe_set_vfta_82598 - Set VLAN filter table 83162306a36Sopenharmony_ci * @hw: pointer to hardware structure 83262306a36Sopenharmony_ci * @vlan: VLAN id to write to VLAN filter 83362306a36Sopenharmony_ci * @vind: VMDq output index that maps queue to VLAN id in VFTA 83462306a36Sopenharmony_ci * @vlan_on: boolean flag to turn on/off VLAN in VFTA 83562306a36Sopenharmony_ci * @vlvf_bypass: boolean flag - unused 83662306a36Sopenharmony_ci * 83762306a36Sopenharmony_ci * Turn on/off specified VLAN in the VLAN filter table. 83862306a36Sopenharmony_ci **/ 83962306a36Sopenharmony_cistatic s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, 84062306a36Sopenharmony_ci bool vlan_on, bool vlvf_bypass) 84162306a36Sopenharmony_ci{ 84262306a36Sopenharmony_ci u32 regindex; 84362306a36Sopenharmony_ci u32 bitindex; 84462306a36Sopenharmony_ci u32 bits; 84562306a36Sopenharmony_ci u32 vftabyte; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci if (vlan > 4095) 84862306a36Sopenharmony_ci return -EINVAL; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci /* Determine 32-bit word position in array */ 85162306a36Sopenharmony_ci regindex = (vlan >> 5) & 0x7F; /* upper seven bits */ 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci /* Determine the location of the (VMD) queue index */ 85462306a36Sopenharmony_ci vftabyte = ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */ 85562306a36Sopenharmony_ci bitindex = (vlan & 0x7) << 2; /* lower 3 bits indicate nibble */ 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci /* Set the nibble for VMD queue index */ 85862306a36Sopenharmony_ci bits = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex)); 85962306a36Sopenharmony_ci bits &= (~(0x0F << bitindex)); 86062306a36Sopenharmony_ci bits |= (vind << bitindex); 86162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex), bits); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci /* Determine the location of the bit for this VLAN id */ 86462306a36Sopenharmony_ci bitindex = vlan & 0x1F; /* lower five bits */ 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); 86762306a36Sopenharmony_ci if (vlan_on) 86862306a36Sopenharmony_ci /* Turn on this VLAN id */ 86962306a36Sopenharmony_ci bits |= BIT(bitindex); 87062306a36Sopenharmony_ci else 87162306a36Sopenharmony_ci /* Turn off this VLAN id */ 87262306a36Sopenharmony_ci bits &= ~BIT(bitindex); 87362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci return 0; 87662306a36Sopenharmony_ci} 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci/** 87962306a36Sopenharmony_ci * ixgbe_clear_vfta_82598 - Clear VLAN filter table 88062306a36Sopenharmony_ci * @hw: pointer to hardware structure 88162306a36Sopenharmony_ci * 88262306a36Sopenharmony_ci * Clears the VLAN filter table, and the VMDq index associated with the filter 88362306a36Sopenharmony_ci **/ 88462306a36Sopenharmony_cistatic s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw) 88562306a36Sopenharmony_ci{ 88662306a36Sopenharmony_ci u32 offset; 88762306a36Sopenharmony_ci u32 vlanbyte; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci for (offset = 0; offset < hw->mac.vft_size; offset++) 89062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci for (vlanbyte = 0; vlanbyte < 4; vlanbyte++) 89362306a36Sopenharmony_ci for (offset = 0; offset < hw->mac.vft_size; offset++) 89462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset), 89562306a36Sopenharmony_ci 0); 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci return 0; 89862306a36Sopenharmony_ci} 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci/** 90162306a36Sopenharmony_ci * ixgbe_read_analog_reg8_82598 - Reads 8 bit Atlas analog register 90262306a36Sopenharmony_ci * @hw: pointer to hardware structure 90362306a36Sopenharmony_ci * @reg: analog register to read 90462306a36Sopenharmony_ci * @val: read value 90562306a36Sopenharmony_ci * 90662306a36Sopenharmony_ci * Performs read operation to Atlas analog register specified. 90762306a36Sopenharmony_ci **/ 90862306a36Sopenharmony_cistatic s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val) 90962306a36Sopenharmony_ci{ 91062306a36Sopenharmony_ci u32 atlas_ctl; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, 91362306a36Sopenharmony_ci IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); 91462306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 91562306a36Sopenharmony_ci udelay(10); 91662306a36Sopenharmony_ci atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); 91762306a36Sopenharmony_ci *val = (u8)atlas_ctl; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci return 0; 92062306a36Sopenharmony_ci} 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci/** 92362306a36Sopenharmony_ci * ixgbe_write_analog_reg8_82598 - Writes 8 bit Atlas analog register 92462306a36Sopenharmony_ci * @hw: pointer to hardware structure 92562306a36Sopenharmony_ci * @reg: atlas register to write 92662306a36Sopenharmony_ci * @val: value to write 92762306a36Sopenharmony_ci * 92862306a36Sopenharmony_ci * Performs write operation to Atlas analog register specified. 92962306a36Sopenharmony_ci **/ 93062306a36Sopenharmony_cistatic s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val) 93162306a36Sopenharmony_ci{ 93262306a36Sopenharmony_ci u32 atlas_ctl; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci atlas_ctl = (reg << 8) | val; 93562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); 93662306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 93762306a36Sopenharmony_ci udelay(10); 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci return 0; 94062306a36Sopenharmony_ci} 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci/** 94362306a36Sopenharmony_ci * ixgbe_read_i2c_phy_82598 - Reads 8 bit word over I2C interface. 94462306a36Sopenharmony_ci * @hw: pointer to hardware structure 94562306a36Sopenharmony_ci * @dev_addr: address to read from 94662306a36Sopenharmony_ci * @byte_offset: byte offset to read from dev_addr 94762306a36Sopenharmony_ci * @eeprom_data: value read 94862306a36Sopenharmony_ci * 94962306a36Sopenharmony_ci * Performs 8 byte read operation to SFP module's data over I2C interface. 95062306a36Sopenharmony_ci **/ 95162306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_phy_82598(struct ixgbe_hw *hw, u8 dev_addr, 95262306a36Sopenharmony_ci u8 byte_offset, u8 *eeprom_data) 95362306a36Sopenharmony_ci{ 95462306a36Sopenharmony_ci s32 status = 0; 95562306a36Sopenharmony_ci u16 sfp_addr = 0; 95662306a36Sopenharmony_ci u16 sfp_data = 0; 95762306a36Sopenharmony_ci u16 sfp_stat = 0; 95862306a36Sopenharmony_ci u16 gssr; 95962306a36Sopenharmony_ci u32 i; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1) 96262306a36Sopenharmony_ci gssr = IXGBE_GSSR_PHY1_SM; 96362306a36Sopenharmony_ci else 96462306a36Sopenharmony_ci gssr = IXGBE_GSSR_PHY0_SM; 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0) 96762306a36Sopenharmony_ci return -EBUSY; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci if (hw->phy.type == ixgbe_phy_nl) { 97062306a36Sopenharmony_ci /* 97162306a36Sopenharmony_ci * phy SDA/SCL registers are at addresses 0xC30A to 97262306a36Sopenharmony_ci * 0xC30D. These registers are used to talk to the SFP+ 97362306a36Sopenharmony_ci * module's EEPROM through the SDA/SCL (I2C) interface. 97462306a36Sopenharmony_ci */ 97562306a36Sopenharmony_ci sfp_addr = (dev_addr << 8) + byte_offset; 97662306a36Sopenharmony_ci sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK); 97762306a36Sopenharmony_ci hw->phy.ops.write_reg_mdi(hw, 97862306a36Sopenharmony_ci IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR, 97962306a36Sopenharmony_ci MDIO_MMD_PMAPMD, 98062306a36Sopenharmony_ci sfp_addr); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci /* Poll status */ 98362306a36Sopenharmony_ci for (i = 0; i < 100; i++) { 98462306a36Sopenharmony_ci hw->phy.ops.read_reg_mdi(hw, 98562306a36Sopenharmony_ci IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT, 98662306a36Sopenharmony_ci MDIO_MMD_PMAPMD, 98762306a36Sopenharmony_ci &sfp_stat); 98862306a36Sopenharmony_ci sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK; 98962306a36Sopenharmony_ci if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS) 99062306a36Sopenharmony_ci break; 99162306a36Sopenharmony_ci usleep_range(10000, 20000); 99262306a36Sopenharmony_ci } 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) { 99562306a36Sopenharmony_ci hw_dbg(hw, "EEPROM read did not pass.\n"); 99662306a36Sopenharmony_ci status = -ENOENT; 99762306a36Sopenharmony_ci goto out; 99862306a36Sopenharmony_ci } 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci /* Read data */ 100162306a36Sopenharmony_ci hw->phy.ops.read_reg_mdi(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA, 100262306a36Sopenharmony_ci MDIO_MMD_PMAPMD, &sfp_data); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci *eeprom_data = (u8)(sfp_data >> 8); 100562306a36Sopenharmony_ci } else { 100662306a36Sopenharmony_ci status = -EIO; 100762306a36Sopenharmony_ci } 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ciout: 101062306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, gssr); 101162306a36Sopenharmony_ci return status; 101262306a36Sopenharmony_ci} 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci/** 101562306a36Sopenharmony_ci * ixgbe_read_i2c_eeprom_82598 - Reads 8 bit word over I2C interface. 101662306a36Sopenharmony_ci * @hw: pointer to hardware structure 101762306a36Sopenharmony_ci * @byte_offset: EEPROM byte offset to read 101862306a36Sopenharmony_ci * @eeprom_data: value read 101962306a36Sopenharmony_ci * 102062306a36Sopenharmony_ci * Performs 8 byte read operation to SFP module's EEPROM over I2C interface. 102162306a36Sopenharmony_ci **/ 102262306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, 102362306a36Sopenharmony_ci u8 *eeprom_data) 102462306a36Sopenharmony_ci{ 102562306a36Sopenharmony_ci return ixgbe_read_i2c_phy_82598(hw, IXGBE_I2C_EEPROM_DEV_ADDR, 102662306a36Sopenharmony_ci byte_offset, eeprom_data); 102762306a36Sopenharmony_ci} 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci/** 103062306a36Sopenharmony_ci * ixgbe_read_i2c_sff8472_82598 - Reads 8 bit word over I2C interface. 103162306a36Sopenharmony_ci * @hw: pointer to hardware structure 103262306a36Sopenharmony_ci * @byte_offset: byte offset at address 0xA2 103362306a36Sopenharmony_ci * @sff8472_data: value read 103462306a36Sopenharmony_ci * 103562306a36Sopenharmony_ci * Performs 8 byte read operation to SFP module's SFF-8472 data over I2C 103662306a36Sopenharmony_ci **/ 103762306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_sff8472_82598(struct ixgbe_hw *hw, u8 byte_offset, 103862306a36Sopenharmony_ci u8 *sff8472_data) 103962306a36Sopenharmony_ci{ 104062306a36Sopenharmony_ci return ixgbe_read_i2c_phy_82598(hw, IXGBE_I2C_EEPROM_DEV_ADDR2, 104162306a36Sopenharmony_ci byte_offset, sff8472_data); 104262306a36Sopenharmony_ci} 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci/** 104562306a36Sopenharmony_ci * ixgbe_set_lan_id_multi_port_pcie_82598 - Set LAN id for PCIe multiple 104662306a36Sopenharmony_ci * port devices. 104762306a36Sopenharmony_ci * @hw: pointer to the HW structure 104862306a36Sopenharmony_ci * 104962306a36Sopenharmony_ci * Calls common function and corrects issue with some single port devices 105062306a36Sopenharmony_ci * that enable LAN1 but not LAN0. 105162306a36Sopenharmony_ci **/ 105262306a36Sopenharmony_cistatic void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw) 105362306a36Sopenharmony_ci{ 105462306a36Sopenharmony_ci struct ixgbe_bus_info *bus = &hw->bus; 105562306a36Sopenharmony_ci u16 pci_gen = 0; 105662306a36Sopenharmony_ci u16 pci_ctrl2 = 0; 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci ixgbe_set_lan_id_multi_port_pcie(hw); 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci /* check if LAN0 is disabled */ 106162306a36Sopenharmony_ci hw->eeprom.ops.read(hw, IXGBE_PCIE_GENERAL_PTR, &pci_gen); 106262306a36Sopenharmony_ci if ((pci_gen != 0) && (pci_gen != 0xFFFF)) { 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci hw->eeprom.ops.read(hw, pci_gen + IXGBE_PCIE_CTRL2, &pci_ctrl2); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci /* if LAN0 is completely disabled force function to 0 */ 106762306a36Sopenharmony_ci if ((pci_ctrl2 & IXGBE_PCIE_CTRL2_LAN_DISABLE) && 106862306a36Sopenharmony_ci !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DISABLE_SELECT) && 106962306a36Sopenharmony_ci !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DUMMY_ENABLE)) { 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci bus->func = 0; 107262306a36Sopenharmony_ci } 107362306a36Sopenharmony_ci } 107462306a36Sopenharmony_ci} 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci/** 107762306a36Sopenharmony_ci * ixgbe_set_rxpba_82598 - Initialize RX packet buffer 107862306a36Sopenharmony_ci * @hw: pointer to hardware structure 107962306a36Sopenharmony_ci * @num_pb: number of packet buffers to allocate 108062306a36Sopenharmony_ci * @headroom: reserve n KB of headroom 108162306a36Sopenharmony_ci * @strategy: packet buffer allocation strategy 108262306a36Sopenharmony_ci **/ 108362306a36Sopenharmony_cistatic void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb, 108462306a36Sopenharmony_ci u32 headroom, int strategy) 108562306a36Sopenharmony_ci{ 108662306a36Sopenharmony_ci u32 rxpktsize = IXGBE_RXPBSIZE_64KB; 108762306a36Sopenharmony_ci u8 i = 0; 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci if (!num_pb) 109062306a36Sopenharmony_ci return; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci /* Setup Rx packet buffer sizes */ 109362306a36Sopenharmony_ci switch (strategy) { 109462306a36Sopenharmony_ci case PBA_STRATEGY_WEIGHTED: 109562306a36Sopenharmony_ci /* Setup the first four at 80KB */ 109662306a36Sopenharmony_ci rxpktsize = IXGBE_RXPBSIZE_80KB; 109762306a36Sopenharmony_ci for (; i < 4; i++) 109862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 109962306a36Sopenharmony_ci /* Setup the last four at 48KB...don't re-init i */ 110062306a36Sopenharmony_ci rxpktsize = IXGBE_RXPBSIZE_48KB; 110162306a36Sopenharmony_ci fallthrough; 110262306a36Sopenharmony_ci case PBA_STRATEGY_EQUAL: 110362306a36Sopenharmony_ci default: 110462306a36Sopenharmony_ci /* Divide the remaining Rx packet buffer evenly among the TCs */ 110562306a36Sopenharmony_ci for (; i < IXGBE_MAX_PACKET_BUFFERS; i++) 110662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 110762306a36Sopenharmony_ci break; 110862306a36Sopenharmony_ci } 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci /* Setup Tx packet buffer sizes */ 111162306a36Sopenharmony_ci for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) 111262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), IXGBE_TXPBSIZE_40KB); 111362306a36Sopenharmony_ci} 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_82598 = { 111662306a36Sopenharmony_ci .init_hw = &ixgbe_init_hw_generic, 111762306a36Sopenharmony_ci .reset_hw = &ixgbe_reset_hw_82598, 111862306a36Sopenharmony_ci .start_hw = &ixgbe_start_hw_82598, 111962306a36Sopenharmony_ci .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, 112062306a36Sopenharmony_ci .get_media_type = &ixgbe_get_media_type_82598, 112162306a36Sopenharmony_ci .enable_rx_dma = &ixgbe_enable_rx_dma_generic, 112262306a36Sopenharmony_ci .get_mac_addr = &ixgbe_get_mac_addr_generic, 112362306a36Sopenharmony_ci .stop_adapter = &ixgbe_stop_adapter_generic, 112462306a36Sopenharmony_ci .get_bus_info = &ixgbe_get_bus_info_generic, 112562306a36Sopenharmony_ci .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie_82598, 112662306a36Sopenharmony_ci .read_analog_reg8 = &ixgbe_read_analog_reg8_82598, 112762306a36Sopenharmony_ci .write_analog_reg8 = &ixgbe_write_analog_reg8_82598, 112862306a36Sopenharmony_ci .setup_link = &ixgbe_setup_mac_link_82598, 112962306a36Sopenharmony_ci .set_rxpba = &ixgbe_set_rxpba_82598, 113062306a36Sopenharmony_ci .check_link = &ixgbe_check_mac_link_82598, 113162306a36Sopenharmony_ci .get_link_capabilities = &ixgbe_get_link_capabilities_82598, 113262306a36Sopenharmony_ci .led_on = &ixgbe_led_on_generic, 113362306a36Sopenharmony_ci .led_off = &ixgbe_led_off_generic, 113462306a36Sopenharmony_ci .init_led_link_act = ixgbe_init_led_link_act_generic, 113562306a36Sopenharmony_ci .blink_led_start = &ixgbe_blink_led_start_generic, 113662306a36Sopenharmony_ci .blink_led_stop = &ixgbe_blink_led_stop_generic, 113762306a36Sopenharmony_ci .set_rar = &ixgbe_set_rar_generic, 113862306a36Sopenharmony_ci .clear_rar = &ixgbe_clear_rar_generic, 113962306a36Sopenharmony_ci .set_vmdq = &ixgbe_set_vmdq_82598, 114062306a36Sopenharmony_ci .clear_vmdq = &ixgbe_clear_vmdq_82598, 114162306a36Sopenharmony_ci .init_rx_addrs = &ixgbe_init_rx_addrs_generic, 114262306a36Sopenharmony_ci .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, 114362306a36Sopenharmony_ci .enable_mc = &ixgbe_enable_mc_generic, 114462306a36Sopenharmony_ci .disable_mc = &ixgbe_disable_mc_generic, 114562306a36Sopenharmony_ci .clear_vfta = &ixgbe_clear_vfta_82598, 114662306a36Sopenharmony_ci .set_vfta = &ixgbe_set_vfta_82598, 114762306a36Sopenharmony_ci .fc_enable = &ixgbe_fc_enable_82598, 114862306a36Sopenharmony_ci .setup_fc = ixgbe_setup_fc_generic, 114962306a36Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 115062306a36Sopenharmony_ci .set_fw_drv_ver = NULL, 115162306a36Sopenharmony_ci .acquire_swfw_sync = &ixgbe_acquire_swfw_sync, 115262306a36Sopenharmony_ci .release_swfw_sync = &ixgbe_release_swfw_sync, 115362306a36Sopenharmony_ci .init_swfw_sync = NULL, 115462306a36Sopenharmony_ci .get_thermal_sensor_data = NULL, 115562306a36Sopenharmony_ci .init_thermal_sensor_thresh = NULL, 115662306a36Sopenharmony_ci .prot_autoc_read = &prot_autoc_read_generic, 115762306a36Sopenharmony_ci .prot_autoc_write = &prot_autoc_write_generic, 115862306a36Sopenharmony_ci .enable_rx = &ixgbe_enable_rx_generic, 115962306a36Sopenharmony_ci .disable_rx = &ixgbe_disable_rx_generic, 116062306a36Sopenharmony_ci}; 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_cistatic const struct ixgbe_eeprom_operations eeprom_ops_82598 = { 116362306a36Sopenharmony_ci .init_params = &ixgbe_init_eeprom_params_generic, 116462306a36Sopenharmony_ci .read = &ixgbe_read_eerd_generic, 116562306a36Sopenharmony_ci .write = &ixgbe_write_eeprom_generic, 116662306a36Sopenharmony_ci .write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic, 116762306a36Sopenharmony_ci .read_buffer = &ixgbe_read_eerd_buffer_generic, 116862306a36Sopenharmony_ci .calc_checksum = &ixgbe_calc_eeprom_checksum_generic, 116962306a36Sopenharmony_ci .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, 117062306a36Sopenharmony_ci .update_checksum = &ixgbe_update_eeprom_checksum_generic, 117162306a36Sopenharmony_ci}; 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_82598 = { 117462306a36Sopenharmony_ci .identify = &ixgbe_identify_phy_generic, 117562306a36Sopenharmony_ci .identify_sfp = &ixgbe_identify_module_generic, 117662306a36Sopenharmony_ci .init = &ixgbe_init_phy_ops_82598, 117762306a36Sopenharmony_ci .reset = &ixgbe_reset_phy_generic, 117862306a36Sopenharmony_ci .read_reg = &ixgbe_read_phy_reg_generic, 117962306a36Sopenharmony_ci .write_reg = &ixgbe_write_phy_reg_generic, 118062306a36Sopenharmony_ci .read_reg_mdi = &ixgbe_read_phy_reg_mdi, 118162306a36Sopenharmony_ci .write_reg_mdi = &ixgbe_write_phy_reg_mdi, 118262306a36Sopenharmony_ci .setup_link = &ixgbe_setup_phy_link_generic, 118362306a36Sopenharmony_ci .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, 118462306a36Sopenharmony_ci .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_82598, 118562306a36Sopenharmony_ci .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598, 118662306a36Sopenharmony_ci .check_overtemp = &ixgbe_tn_check_overtemp, 118762306a36Sopenharmony_ci}; 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_82598_info = { 119062306a36Sopenharmony_ci .mac = ixgbe_mac_82598EB, 119162306a36Sopenharmony_ci .get_invariants = &ixgbe_get_invariants_82598, 119262306a36Sopenharmony_ci .mac_ops = &mac_ops_82598, 119362306a36Sopenharmony_ci .eeprom_ops = &eeprom_ops_82598, 119462306a36Sopenharmony_ci .phy_ops = &phy_ops_82598, 119562306a36Sopenharmony_ci .mvals = ixgbe_mvals_8259X, 119662306a36Sopenharmony_ci}; 1197