162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 2007 - 2018 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci/* e1000_82575 562306a36Sopenharmony_ci * e1000_82576 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/types.h> 1162306a36Sopenharmony_ci#include <linux/if_ether.h> 1262306a36Sopenharmony_ci#include <linux/i2c.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "e1000_mac.h" 1562306a36Sopenharmony_ci#include "e1000_82575.h" 1662306a36Sopenharmony_ci#include "e1000_i210.h" 1762306a36Sopenharmony_ci#include "igb.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic s32 igb_get_invariants_82575(struct e1000_hw *); 2062306a36Sopenharmony_cistatic s32 igb_acquire_phy_82575(struct e1000_hw *); 2162306a36Sopenharmony_cistatic void igb_release_phy_82575(struct e1000_hw *); 2262306a36Sopenharmony_cistatic s32 igb_acquire_nvm_82575(struct e1000_hw *); 2362306a36Sopenharmony_cistatic void igb_release_nvm_82575(struct e1000_hw *); 2462306a36Sopenharmony_cistatic s32 igb_check_for_link_82575(struct e1000_hw *); 2562306a36Sopenharmony_cistatic s32 igb_get_cfg_done_82575(struct e1000_hw *); 2662306a36Sopenharmony_cistatic s32 igb_init_hw_82575(struct e1000_hw *); 2762306a36Sopenharmony_cistatic s32 igb_phy_hw_reset_sgmii_82575(struct e1000_hw *); 2862306a36Sopenharmony_cistatic s32 igb_read_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16 *); 2962306a36Sopenharmony_cistatic s32 igb_reset_hw_82575(struct e1000_hw *); 3062306a36Sopenharmony_cistatic s32 igb_reset_hw_82580(struct e1000_hw *); 3162306a36Sopenharmony_cistatic s32 igb_set_d0_lplu_state_82575(struct e1000_hw *, bool); 3262306a36Sopenharmony_cistatic s32 igb_set_d0_lplu_state_82580(struct e1000_hw *, bool); 3362306a36Sopenharmony_cistatic s32 igb_set_d3_lplu_state_82580(struct e1000_hw *, bool); 3462306a36Sopenharmony_cistatic s32 igb_setup_copper_link_82575(struct e1000_hw *); 3562306a36Sopenharmony_cistatic s32 igb_setup_serdes_link_82575(struct e1000_hw *); 3662306a36Sopenharmony_cistatic s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16); 3762306a36Sopenharmony_cistatic void igb_clear_hw_cntrs_82575(struct e1000_hw *); 3862306a36Sopenharmony_cistatic s32 igb_acquire_swfw_sync_82575(struct e1000_hw *, u16); 3962306a36Sopenharmony_cistatic s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *, u16 *, 4062306a36Sopenharmony_ci u16 *); 4162306a36Sopenharmony_cistatic s32 igb_get_phy_id_82575(struct e1000_hw *); 4262306a36Sopenharmony_cistatic void igb_release_swfw_sync_82575(struct e1000_hw *, u16); 4362306a36Sopenharmony_cistatic bool igb_sgmii_active_82575(struct e1000_hw *); 4462306a36Sopenharmony_cistatic s32 igb_reset_init_script_82575(struct e1000_hw *); 4562306a36Sopenharmony_cistatic s32 igb_read_mac_addr_82575(struct e1000_hw *); 4662306a36Sopenharmony_cistatic s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw); 4762306a36Sopenharmony_cistatic s32 igb_reset_mdicnfg_82580(struct e1000_hw *hw); 4862306a36Sopenharmony_cistatic s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw); 4962306a36Sopenharmony_cistatic s32 igb_update_nvm_checksum_82580(struct e1000_hw *hw); 5062306a36Sopenharmony_cistatic s32 igb_validate_nvm_checksum_i350(struct e1000_hw *hw); 5162306a36Sopenharmony_cistatic s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw); 5262306a36Sopenharmony_cistatic const u16 e1000_82580_rxpbs_table[] = { 5362306a36Sopenharmony_ci 36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 }; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* Due to a hw errata, if the host tries to configure the VFTA register 5662306a36Sopenharmony_ci * while performing queries from the BMC or DMA, then the VFTA in some 5762306a36Sopenharmony_ci * cases won't be written. 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/** 6162306a36Sopenharmony_ci * igb_write_vfta_i350 - Write value to VLAN filter table 6262306a36Sopenharmony_ci * @hw: pointer to the HW structure 6362306a36Sopenharmony_ci * @offset: register offset in VLAN filter table 6462306a36Sopenharmony_ci * @value: register value written to VLAN filter table 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * Writes value at the given offset in the register array which stores 6762306a36Sopenharmony_ci * the VLAN filter table. 6862306a36Sopenharmony_ci **/ 6962306a36Sopenharmony_cistatic void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct igb_adapter *adapter = hw->back; 7262306a36Sopenharmony_ci int i; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci for (i = 10; i--;) 7562306a36Sopenharmony_ci array_wr32(E1000_VFTA, offset, value); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci wrfl(); 7862306a36Sopenharmony_ci adapter->shadow_vfta[offset] = value; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/** 8262306a36Sopenharmony_ci * igb_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO 8362306a36Sopenharmony_ci * @hw: pointer to the HW structure 8462306a36Sopenharmony_ci * 8562306a36Sopenharmony_ci * Called to determine if the I2C pins are being used for I2C or as an 8662306a36Sopenharmony_ci * external MDIO interface since the two options are mutually exclusive. 8762306a36Sopenharmony_ci **/ 8862306a36Sopenharmony_cistatic bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci u32 reg = 0; 9162306a36Sopenharmony_ci bool ext_mdio = false; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci switch (hw->mac.type) { 9462306a36Sopenharmony_ci case e1000_82575: 9562306a36Sopenharmony_ci case e1000_82576: 9662306a36Sopenharmony_ci reg = rd32(E1000_MDIC); 9762306a36Sopenharmony_ci ext_mdio = !!(reg & E1000_MDIC_DEST); 9862306a36Sopenharmony_ci break; 9962306a36Sopenharmony_ci case e1000_82580: 10062306a36Sopenharmony_ci case e1000_i350: 10162306a36Sopenharmony_ci case e1000_i354: 10262306a36Sopenharmony_ci case e1000_i210: 10362306a36Sopenharmony_ci case e1000_i211: 10462306a36Sopenharmony_ci reg = rd32(E1000_MDICNFG); 10562306a36Sopenharmony_ci ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); 10662306a36Sopenharmony_ci break; 10762306a36Sopenharmony_ci default: 10862306a36Sopenharmony_ci break; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci return ext_mdio; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/** 11462306a36Sopenharmony_ci * igb_check_for_link_media_swap - Check which M88E1112 interface linked 11562306a36Sopenharmony_ci * @hw: pointer to the HW structure 11662306a36Sopenharmony_ci * 11762306a36Sopenharmony_ci * Poll the M88E1112 interfaces to see which interface achieved link. 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_cistatic s32 igb_check_for_link_media_swap(struct e1000_hw *hw) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 12262306a36Sopenharmony_ci s32 ret_val; 12362306a36Sopenharmony_ci u16 data; 12462306a36Sopenharmony_ci u8 port = 0; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci /* Check the copper medium. */ 12762306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); 12862306a36Sopenharmony_ci if (ret_val) 12962306a36Sopenharmony_ci return ret_val; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); 13262306a36Sopenharmony_ci if (ret_val) 13362306a36Sopenharmony_ci return ret_val; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (data & E1000_M88E1112_STATUS_LINK) 13662306a36Sopenharmony_ci port = E1000_MEDIA_PORT_COPPER; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* Check the other medium. */ 13962306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); 14062306a36Sopenharmony_ci if (ret_val) 14162306a36Sopenharmony_ci return ret_val; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); 14462306a36Sopenharmony_ci if (ret_val) 14562306a36Sopenharmony_ci return ret_val; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (data & E1000_M88E1112_STATUS_LINK) 14962306a36Sopenharmony_ci port = E1000_MEDIA_PORT_OTHER; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* Determine if a swap needs to happen. */ 15262306a36Sopenharmony_ci if (port && (hw->dev_spec._82575.media_port != port)) { 15362306a36Sopenharmony_ci hw->dev_spec._82575.media_port = port; 15462306a36Sopenharmony_ci hw->dev_spec._82575.media_changed = true; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if (port == E1000_MEDIA_PORT_COPPER) { 15862306a36Sopenharmony_ci /* reset page to 0 */ 15962306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); 16062306a36Sopenharmony_ci if (ret_val) 16162306a36Sopenharmony_ci return ret_val; 16262306a36Sopenharmony_ci igb_check_for_link_82575(hw); 16362306a36Sopenharmony_ci } else { 16462306a36Sopenharmony_ci igb_check_for_link_82575(hw); 16562306a36Sopenharmony_ci /* reset page to 0 */ 16662306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); 16762306a36Sopenharmony_ci if (ret_val) 16862306a36Sopenharmony_ci return ret_val; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return 0; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/** 17562306a36Sopenharmony_ci * igb_init_phy_params_82575 - Init PHY func ptrs. 17662306a36Sopenharmony_ci * @hw: pointer to the HW structure 17762306a36Sopenharmony_ci **/ 17862306a36Sopenharmony_cistatic s32 igb_init_phy_params_82575(struct e1000_hw *hw) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 18162306a36Sopenharmony_ci s32 ret_val = 0; 18262306a36Sopenharmony_ci u32 ctrl_ext; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci if (hw->phy.media_type != e1000_media_type_copper) { 18562306a36Sopenharmony_ci phy->type = e1000_phy_none; 18662306a36Sopenharmony_ci goto out; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 19062306a36Sopenharmony_ci phy->reset_delay_us = 100; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci if (igb_sgmii_active_82575(hw)) { 19562306a36Sopenharmony_ci phy->ops.reset = igb_phy_hw_reset_sgmii_82575; 19662306a36Sopenharmony_ci ctrl_ext |= E1000_CTRL_I2C_ENA; 19762306a36Sopenharmony_ci } else { 19862306a36Sopenharmony_ci phy->ops.reset = igb_phy_hw_reset; 19962306a36Sopenharmony_ci ctrl_ext &= ~E1000_CTRL_I2C_ENA; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, ctrl_ext); 20362306a36Sopenharmony_ci igb_reset_mdicnfg_82580(hw); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (igb_sgmii_active_82575(hw) && !igb_sgmii_uses_mdio_82575(hw)) { 20662306a36Sopenharmony_ci phy->ops.read_reg = igb_read_phy_reg_sgmii_82575; 20762306a36Sopenharmony_ci phy->ops.write_reg = igb_write_phy_reg_sgmii_82575; 20862306a36Sopenharmony_ci } else { 20962306a36Sopenharmony_ci switch (hw->mac.type) { 21062306a36Sopenharmony_ci case e1000_82580: 21162306a36Sopenharmony_ci case e1000_i350: 21262306a36Sopenharmony_ci case e1000_i354: 21362306a36Sopenharmony_ci case e1000_i210: 21462306a36Sopenharmony_ci case e1000_i211: 21562306a36Sopenharmony_ci phy->ops.read_reg = igb_read_phy_reg_82580; 21662306a36Sopenharmony_ci phy->ops.write_reg = igb_write_phy_reg_82580; 21762306a36Sopenharmony_ci break; 21862306a36Sopenharmony_ci default: 21962306a36Sopenharmony_ci phy->ops.read_reg = igb_read_phy_reg_igp; 22062306a36Sopenharmony_ci phy->ops.write_reg = igb_write_phy_reg_igp; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci /* set lan id */ 22562306a36Sopenharmony_ci hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >> 22662306a36Sopenharmony_ci E1000_STATUS_FUNC_SHIFT; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci /* Set phy->phy_addr and phy->id. */ 22962306a36Sopenharmony_ci ret_val = igb_get_phy_id_82575(hw); 23062306a36Sopenharmony_ci if (ret_val) 23162306a36Sopenharmony_ci return ret_val; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* Verify phy id and set remaining function pointers */ 23462306a36Sopenharmony_ci switch (phy->id) { 23562306a36Sopenharmony_ci case M88E1543_E_PHY_ID: 23662306a36Sopenharmony_ci case M88E1512_E_PHY_ID: 23762306a36Sopenharmony_ci case I347AT4_E_PHY_ID: 23862306a36Sopenharmony_ci case M88E1112_E_PHY_ID: 23962306a36Sopenharmony_ci case M88E1111_I_PHY_ID: 24062306a36Sopenharmony_ci phy->type = e1000_phy_m88; 24162306a36Sopenharmony_ci phy->ops.check_polarity = igb_check_polarity_m88; 24262306a36Sopenharmony_ci phy->ops.get_phy_info = igb_get_phy_info_m88; 24362306a36Sopenharmony_ci if (phy->id != M88E1111_I_PHY_ID) 24462306a36Sopenharmony_ci phy->ops.get_cable_length = 24562306a36Sopenharmony_ci igb_get_cable_length_m88_gen2; 24662306a36Sopenharmony_ci else 24762306a36Sopenharmony_ci phy->ops.get_cable_length = igb_get_cable_length_m88; 24862306a36Sopenharmony_ci phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; 24962306a36Sopenharmony_ci /* Check if this PHY is configured for media swap. */ 25062306a36Sopenharmony_ci if (phy->id == M88E1112_E_PHY_ID) { 25162306a36Sopenharmony_ci u16 data; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, 25462306a36Sopenharmony_ci E1000_M88E1112_PAGE_ADDR, 25562306a36Sopenharmony_ci 2); 25662306a36Sopenharmony_ci if (ret_val) 25762306a36Sopenharmony_ci goto out; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci ret_val = phy->ops.read_reg(hw, 26062306a36Sopenharmony_ci E1000_M88E1112_MAC_CTRL_1, 26162306a36Sopenharmony_ci &data); 26262306a36Sopenharmony_ci if (ret_val) 26362306a36Sopenharmony_ci goto out; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >> 26662306a36Sopenharmony_ci E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT; 26762306a36Sopenharmony_ci if (data == E1000_M88E1112_AUTO_COPPER_SGMII || 26862306a36Sopenharmony_ci data == E1000_M88E1112_AUTO_COPPER_BASEX) 26962306a36Sopenharmony_ci hw->mac.ops.check_for_link = 27062306a36Sopenharmony_ci igb_check_for_link_media_swap; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci if (phy->id == M88E1512_E_PHY_ID) { 27362306a36Sopenharmony_ci ret_val = igb_initialize_M88E1512_phy(hw); 27462306a36Sopenharmony_ci if (ret_val) 27562306a36Sopenharmony_ci goto out; 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci if (phy->id == M88E1543_E_PHY_ID) { 27862306a36Sopenharmony_ci ret_val = igb_initialize_M88E1543_phy(hw); 27962306a36Sopenharmony_ci if (ret_val) 28062306a36Sopenharmony_ci goto out; 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci break; 28362306a36Sopenharmony_ci case IGP03E1000_E_PHY_ID: 28462306a36Sopenharmony_ci phy->type = e1000_phy_igp_3; 28562306a36Sopenharmony_ci phy->ops.get_phy_info = igb_get_phy_info_igp; 28662306a36Sopenharmony_ci phy->ops.get_cable_length = igb_get_cable_length_igp_2; 28762306a36Sopenharmony_ci phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_igp; 28862306a36Sopenharmony_ci phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82575; 28962306a36Sopenharmony_ci phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state; 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci case I82580_I_PHY_ID: 29262306a36Sopenharmony_ci case I350_I_PHY_ID: 29362306a36Sopenharmony_ci phy->type = e1000_phy_82580; 29462306a36Sopenharmony_ci phy->ops.force_speed_duplex = 29562306a36Sopenharmony_ci igb_phy_force_speed_duplex_82580; 29662306a36Sopenharmony_ci phy->ops.get_cable_length = igb_get_cable_length_82580; 29762306a36Sopenharmony_ci phy->ops.get_phy_info = igb_get_phy_info_82580; 29862306a36Sopenharmony_ci phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580; 29962306a36Sopenharmony_ci phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580; 30062306a36Sopenharmony_ci break; 30162306a36Sopenharmony_ci case I210_I_PHY_ID: 30262306a36Sopenharmony_ci phy->type = e1000_phy_i210; 30362306a36Sopenharmony_ci phy->ops.check_polarity = igb_check_polarity_m88; 30462306a36Sopenharmony_ci phy->ops.get_cfg_done = igb_get_cfg_done_i210; 30562306a36Sopenharmony_ci phy->ops.get_phy_info = igb_get_phy_info_m88; 30662306a36Sopenharmony_ci phy->ops.get_cable_length = igb_get_cable_length_m88_gen2; 30762306a36Sopenharmony_ci phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580; 30862306a36Sopenharmony_ci phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580; 30962306a36Sopenharmony_ci phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; 31062306a36Sopenharmony_ci break; 31162306a36Sopenharmony_ci case BCM54616_E_PHY_ID: 31262306a36Sopenharmony_ci phy->type = e1000_phy_bcm54616; 31362306a36Sopenharmony_ci break; 31462306a36Sopenharmony_ci default: 31562306a36Sopenharmony_ci ret_val = -E1000_ERR_PHY; 31662306a36Sopenharmony_ci goto out; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ciout: 32062306a36Sopenharmony_ci return ret_val; 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci/** 32462306a36Sopenharmony_ci * igb_init_nvm_params_82575 - Init NVM func ptrs. 32562306a36Sopenharmony_ci * @hw: pointer to the HW structure 32662306a36Sopenharmony_ci **/ 32762306a36Sopenharmony_cistatic s32 igb_init_nvm_params_82575(struct e1000_hw *hw) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci struct e1000_nvm_info *nvm = &hw->nvm; 33062306a36Sopenharmony_ci u32 eecd = rd32(E1000_EECD); 33162306a36Sopenharmony_ci u16 size; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> 33462306a36Sopenharmony_ci E1000_EECD_SIZE_EX_SHIFT); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* Added to a constant, "size" becomes the left-shift value 33762306a36Sopenharmony_ci * for setting word_size. 33862306a36Sopenharmony_ci */ 33962306a36Sopenharmony_ci size += NVM_WORD_SIZE_BASE_SHIFT; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* Just in case size is out of range, cap it to the largest 34262306a36Sopenharmony_ci * EEPROM size supported 34362306a36Sopenharmony_ci */ 34462306a36Sopenharmony_ci if (size > 15) 34562306a36Sopenharmony_ci size = 15; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci nvm->word_size = BIT(size); 34862306a36Sopenharmony_ci nvm->opcode_bits = 8; 34962306a36Sopenharmony_ci nvm->delay_usec = 1; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci switch (nvm->override) { 35262306a36Sopenharmony_ci case e1000_nvm_override_spi_large: 35362306a36Sopenharmony_ci nvm->page_size = 32; 35462306a36Sopenharmony_ci nvm->address_bits = 16; 35562306a36Sopenharmony_ci break; 35662306a36Sopenharmony_ci case e1000_nvm_override_spi_small: 35762306a36Sopenharmony_ci nvm->page_size = 8; 35862306a36Sopenharmony_ci nvm->address_bits = 8; 35962306a36Sopenharmony_ci break; 36062306a36Sopenharmony_ci default: 36162306a36Sopenharmony_ci nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; 36262306a36Sopenharmony_ci nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 36362306a36Sopenharmony_ci 16 : 8; 36462306a36Sopenharmony_ci break; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci if (nvm->word_size == BIT(15)) 36762306a36Sopenharmony_ci nvm->page_size = 128; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci nvm->type = e1000_nvm_eeprom_spi; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci /* NVM Function Pointers */ 37262306a36Sopenharmony_ci nvm->ops.acquire = igb_acquire_nvm_82575; 37362306a36Sopenharmony_ci nvm->ops.release = igb_release_nvm_82575; 37462306a36Sopenharmony_ci nvm->ops.write = igb_write_nvm_spi; 37562306a36Sopenharmony_ci nvm->ops.validate = igb_validate_nvm_checksum; 37662306a36Sopenharmony_ci nvm->ops.update = igb_update_nvm_checksum; 37762306a36Sopenharmony_ci if (nvm->word_size < BIT(15)) 37862306a36Sopenharmony_ci nvm->ops.read = igb_read_nvm_eerd; 37962306a36Sopenharmony_ci else 38062306a36Sopenharmony_ci nvm->ops.read = igb_read_nvm_spi; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* override generic family function pointers for specific descendants */ 38362306a36Sopenharmony_ci switch (hw->mac.type) { 38462306a36Sopenharmony_ci case e1000_82580: 38562306a36Sopenharmony_ci nvm->ops.validate = igb_validate_nvm_checksum_82580; 38662306a36Sopenharmony_ci nvm->ops.update = igb_update_nvm_checksum_82580; 38762306a36Sopenharmony_ci break; 38862306a36Sopenharmony_ci case e1000_i354: 38962306a36Sopenharmony_ci case e1000_i350: 39062306a36Sopenharmony_ci nvm->ops.validate = igb_validate_nvm_checksum_i350; 39162306a36Sopenharmony_ci nvm->ops.update = igb_update_nvm_checksum_i350; 39262306a36Sopenharmony_ci break; 39362306a36Sopenharmony_ci default: 39462306a36Sopenharmony_ci break; 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci return 0; 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci/** 40162306a36Sopenharmony_ci * igb_init_mac_params_82575 - Init MAC func ptrs. 40262306a36Sopenharmony_ci * @hw: pointer to the HW structure 40362306a36Sopenharmony_ci **/ 40462306a36Sopenharmony_cistatic s32 igb_init_mac_params_82575(struct e1000_hw *hw) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci struct e1000_mac_info *mac = &hw->mac; 40762306a36Sopenharmony_ci struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* Set mta register count */ 41062306a36Sopenharmony_ci mac->mta_reg_count = 128; 41162306a36Sopenharmony_ci /* Set uta register count */ 41262306a36Sopenharmony_ci mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128; 41362306a36Sopenharmony_ci /* Set rar entry count */ 41462306a36Sopenharmony_ci switch (mac->type) { 41562306a36Sopenharmony_ci case e1000_82576: 41662306a36Sopenharmony_ci mac->rar_entry_count = E1000_RAR_ENTRIES_82576; 41762306a36Sopenharmony_ci break; 41862306a36Sopenharmony_ci case e1000_82580: 41962306a36Sopenharmony_ci mac->rar_entry_count = E1000_RAR_ENTRIES_82580; 42062306a36Sopenharmony_ci break; 42162306a36Sopenharmony_ci case e1000_i350: 42262306a36Sopenharmony_ci case e1000_i354: 42362306a36Sopenharmony_ci mac->rar_entry_count = E1000_RAR_ENTRIES_I350; 42462306a36Sopenharmony_ci break; 42562306a36Sopenharmony_ci default: 42662306a36Sopenharmony_ci mac->rar_entry_count = E1000_RAR_ENTRIES_82575; 42762306a36Sopenharmony_ci break; 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci /* reset */ 43062306a36Sopenharmony_ci if (mac->type >= e1000_82580) 43162306a36Sopenharmony_ci mac->ops.reset_hw = igb_reset_hw_82580; 43262306a36Sopenharmony_ci else 43362306a36Sopenharmony_ci mac->ops.reset_hw = igb_reset_hw_82575; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci if (mac->type >= e1000_i210) { 43662306a36Sopenharmony_ci mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_i210; 43762306a36Sopenharmony_ci mac->ops.release_swfw_sync = igb_release_swfw_sync_i210; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci } else { 44062306a36Sopenharmony_ci mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_82575; 44162306a36Sopenharmony_ci mac->ops.release_swfw_sync = igb_release_swfw_sync_82575; 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if ((hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i354)) 44562306a36Sopenharmony_ci mac->ops.write_vfta = igb_write_vfta_i350; 44662306a36Sopenharmony_ci else 44762306a36Sopenharmony_ci mac->ops.write_vfta = igb_write_vfta; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* Set if part includes ASF firmware */ 45062306a36Sopenharmony_ci mac->asf_firmware_present = true; 45162306a36Sopenharmony_ci /* Set if manageability features are enabled. */ 45262306a36Sopenharmony_ci mac->arc_subsystem_valid = 45362306a36Sopenharmony_ci (rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK) 45462306a36Sopenharmony_ci ? true : false; 45562306a36Sopenharmony_ci /* enable EEE on i350 parts and later parts */ 45662306a36Sopenharmony_ci if (mac->type >= e1000_i350) 45762306a36Sopenharmony_ci dev_spec->eee_disable = false; 45862306a36Sopenharmony_ci else 45962306a36Sopenharmony_ci dev_spec->eee_disable = true; 46062306a36Sopenharmony_ci /* Allow a single clear of the SW semaphore on I210 and newer */ 46162306a36Sopenharmony_ci if (mac->type >= e1000_i210) 46262306a36Sopenharmony_ci dev_spec->clear_semaphore_once = true; 46362306a36Sopenharmony_ci /* physical interface link setup */ 46462306a36Sopenharmony_ci mac->ops.setup_physical_interface = 46562306a36Sopenharmony_ci (hw->phy.media_type == e1000_media_type_copper) 46662306a36Sopenharmony_ci ? igb_setup_copper_link_82575 46762306a36Sopenharmony_ci : igb_setup_serdes_link_82575; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci if (mac->type == e1000_82580 || mac->type == e1000_i350) { 47062306a36Sopenharmony_ci switch (hw->device_id) { 47162306a36Sopenharmony_ci /* feature not supported on these id's */ 47262306a36Sopenharmony_ci case E1000_DEV_ID_DH89XXCC_SGMII: 47362306a36Sopenharmony_ci case E1000_DEV_ID_DH89XXCC_SERDES: 47462306a36Sopenharmony_ci case E1000_DEV_ID_DH89XXCC_BACKPLANE: 47562306a36Sopenharmony_ci case E1000_DEV_ID_DH89XXCC_SFP: 47662306a36Sopenharmony_ci break; 47762306a36Sopenharmony_ci default: 47862306a36Sopenharmony_ci hw->dev_spec._82575.mas_capable = true; 47962306a36Sopenharmony_ci break; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci return 0; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci/** 48662306a36Sopenharmony_ci * igb_set_sfp_media_type_82575 - derives SFP module media type. 48762306a36Sopenharmony_ci * @hw: pointer to the HW structure 48862306a36Sopenharmony_ci * 48962306a36Sopenharmony_ci * The media type is chosen based on SFP module. 49062306a36Sopenharmony_ci * compatibility flags retrieved from SFP ID EEPROM. 49162306a36Sopenharmony_ci **/ 49262306a36Sopenharmony_cistatic s32 igb_set_sfp_media_type_82575(struct e1000_hw *hw) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci s32 ret_val = E1000_ERR_CONFIG; 49562306a36Sopenharmony_ci u32 ctrl_ext = 0; 49662306a36Sopenharmony_ci struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 49762306a36Sopenharmony_ci struct e1000_sfp_flags *eth_flags = &dev_spec->eth_flags; 49862306a36Sopenharmony_ci u8 tranceiver_type = 0; 49962306a36Sopenharmony_ci s32 timeout = 3; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci /* Turn I2C interface ON and power on sfp cage */ 50262306a36Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 50362306a36Sopenharmony_ci ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; 50462306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci wrfl(); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci /* Read SFP module data */ 50962306a36Sopenharmony_ci while (timeout) { 51062306a36Sopenharmony_ci ret_val = igb_read_sfp_data_byte(hw, 51162306a36Sopenharmony_ci E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), 51262306a36Sopenharmony_ci &tranceiver_type); 51362306a36Sopenharmony_ci if (ret_val == 0) 51462306a36Sopenharmony_ci break; 51562306a36Sopenharmony_ci msleep(100); 51662306a36Sopenharmony_ci timeout--; 51762306a36Sopenharmony_ci } 51862306a36Sopenharmony_ci if (ret_val != 0) 51962306a36Sopenharmony_ci goto out; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci ret_val = igb_read_sfp_data_byte(hw, 52262306a36Sopenharmony_ci E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), 52362306a36Sopenharmony_ci (u8 *)eth_flags); 52462306a36Sopenharmony_ci if (ret_val != 0) 52562306a36Sopenharmony_ci goto out; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci /* Check if there is some SFP module plugged and powered */ 52862306a36Sopenharmony_ci if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || 52962306a36Sopenharmony_ci (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { 53062306a36Sopenharmony_ci dev_spec->module_plugged = true; 53162306a36Sopenharmony_ci if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) { 53262306a36Sopenharmony_ci hw->phy.media_type = e1000_media_type_internal_serdes; 53362306a36Sopenharmony_ci } else if (eth_flags->e100_base_fx || eth_flags->e100_base_lx) { 53462306a36Sopenharmony_ci dev_spec->sgmii_active = true; 53562306a36Sopenharmony_ci hw->phy.media_type = e1000_media_type_internal_serdes; 53662306a36Sopenharmony_ci } else if (eth_flags->e1000_base_t) { 53762306a36Sopenharmony_ci dev_spec->sgmii_active = true; 53862306a36Sopenharmony_ci hw->phy.media_type = e1000_media_type_copper; 53962306a36Sopenharmony_ci } else { 54062306a36Sopenharmony_ci hw->phy.media_type = e1000_media_type_unknown; 54162306a36Sopenharmony_ci hw_dbg("PHY module has not been recognized\n"); 54262306a36Sopenharmony_ci goto out; 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci } else { 54562306a36Sopenharmony_ci hw->phy.media_type = e1000_media_type_unknown; 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci ret_val = 0; 54862306a36Sopenharmony_ciout: 54962306a36Sopenharmony_ci /* Restore I2C interface setting */ 55062306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, ctrl_ext); 55162306a36Sopenharmony_ci return ret_val; 55262306a36Sopenharmony_ci} 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_cistatic s32 igb_get_invariants_82575(struct e1000_hw *hw) 55562306a36Sopenharmony_ci{ 55662306a36Sopenharmony_ci struct e1000_mac_info *mac = &hw->mac; 55762306a36Sopenharmony_ci struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 55862306a36Sopenharmony_ci s32 ret_val; 55962306a36Sopenharmony_ci u32 ctrl_ext = 0; 56062306a36Sopenharmony_ci u32 link_mode = 0; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci switch (hw->device_id) { 56362306a36Sopenharmony_ci case E1000_DEV_ID_82575EB_COPPER: 56462306a36Sopenharmony_ci case E1000_DEV_ID_82575EB_FIBER_SERDES: 56562306a36Sopenharmony_ci case E1000_DEV_ID_82575GB_QUAD_COPPER: 56662306a36Sopenharmony_ci mac->type = e1000_82575; 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci case E1000_DEV_ID_82576: 56962306a36Sopenharmony_ci case E1000_DEV_ID_82576_NS: 57062306a36Sopenharmony_ci case E1000_DEV_ID_82576_NS_SERDES: 57162306a36Sopenharmony_ci case E1000_DEV_ID_82576_FIBER: 57262306a36Sopenharmony_ci case E1000_DEV_ID_82576_SERDES: 57362306a36Sopenharmony_ci case E1000_DEV_ID_82576_QUAD_COPPER: 57462306a36Sopenharmony_ci case E1000_DEV_ID_82576_QUAD_COPPER_ET2: 57562306a36Sopenharmony_ci case E1000_DEV_ID_82576_SERDES_QUAD: 57662306a36Sopenharmony_ci mac->type = e1000_82576; 57762306a36Sopenharmony_ci break; 57862306a36Sopenharmony_ci case E1000_DEV_ID_82580_COPPER: 57962306a36Sopenharmony_ci case E1000_DEV_ID_82580_FIBER: 58062306a36Sopenharmony_ci case E1000_DEV_ID_82580_QUAD_FIBER: 58162306a36Sopenharmony_ci case E1000_DEV_ID_82580_SERDES: 58262306a36Sopenharmony_ci case E1000_DEV_ID_82580_SGMII: 58362306a36Sopenharmony_ci case E1000_DEV_ID_82580_COPPER_DUAL: 58462306a36Sopenharmony_ci case E1000_DEV_ID_DH89XXCC_SGMII: 58562306a36Sopenharmony_ci case E1000_DEV_ID_DH89XXCC_SERDES: 58662306a36Sopenharmony_ci case E1000_DEV_ID_DH89XXCC_BACKPLANE: 58762306a36Sopenharmony_ci case E1000_DEV_ID_DH89XXCC_SFP: 58862306a36Sopenharmony_ci mac->type = e1000_82580; 58962306a36Sopenharmony_ci break; 59062306a36Sopenharmony_ci case E1000_DEV_ID_I350_COPPER: 59162306a36Sopenharmony_ci case E1000_DEV_ID_I350_FIBER: 59262306a36Sopenharmony_ci case E1000_DEV_ID_I350_SERDES: 59362306a36Sopenharmony_ci case E1000_DEV_ID_I350_SGMII: 59462306a36Sopenharmony_ci mac->type = e1000_i350; 59562306a36Sopenharmony_ci break; 59662306a36Sopenharmony_ci case E1000_DEV_ID_I210_COPPER: 59762306a36Sopenharmony_ci case E1000_DEV_ID_I210_FIBER: 59862306a36Sopenharmony_ci case E1000_DEV_ID_I210_SERDES: 59962306a36Sopenharmony_ci case E1000_DEV_ID_I210_SGMII: 60062306a36Sopenharmony_ci case E1000_DEV_ID_I210_COPPER_FLASHLESS: 60162306a36Sopenharmony_ci case E1000_DEV_ID_I210_SERDES_FLASHLESS: 60262306a36Sopenharmony_ci mac->type = e1000_i210; 60362306a36Sopenharmony_ci break; 60462306a36Sopenharmony_ci case E1000_DEV_ID_I211_COPPER: 60562306a36Sopenharmony_ci mac->type = e1000_i211; 60662306a36Sopenharmony_ci break; 60762306a36Sopenharmony_ci case E1000_DEV_ID_I354_BACKPLANE_1GBPS: 60862306a36Sopenharmony_ci case E1000_DEV_ID_I354_SGMII: 60962306a36Sopenharmony_ci case E1000_DEV_ID_I354_BACKPLANE_2_5GBPS: 61062306a36Sopenharmony_ci mac->type = e1000_i354; 61162306a36Sopenharmony_ci break; 61262306a36Sopenharmony_ci default: 61362306a36Sopenharmony_ci return -E1000_ERR_MAC_INIT; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci /* Set media type */ 61762306a36Sopenharmony_ci /* The 82575 uses bits 22:23 for link mode. The mode can be changed 61862306a36Sopenharmony_ci * based on the EEPROM. We cannot rely upon device ID. There 61962306a36Sopenharmony_ci * is no distinguishable difference between fiber and internal 62062306a36Sopenharmony_ci * SerDes mode on the 82575. There can be an external PHY attached 62162306a36Sopenharmony_ci * on the SGMII interface. For this, we'll set sgmii_active to true. 62262306a36Sopenharmony_ci */ 62362306a36Sopenharmony_ci hw->phy.media_type = e1000_media_type_copper; 62462306a36Sopenharmony_ci dev_spec->sgmii_active = false; 62562306a36Sopenharmony_ci dev_spec->module_plugged = false; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; 63062306a36Sopenharmony_ci switch (link_mode) { 63162306a36Sopenharmony_ci case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: 63262306a36Sopenharmony_ci hw->phy.media_type = e1000_media_type_internal_serdes; 63362306a36Sopenharmony_ci break; 63462306a36Sopenharmony_ci case E1000_CTRL_EXT_LINK_MODE_SGMII: 63562306a36Sopenharmony_ci /* Get phy control interface type set (MDIO vs. I2C)*/ 63662306a36Sopenharmony_ci if (igb_sgmii_uses_mdio_82575(hw)) { 63762306a36Sopenharmony_ci hw->phy.media_type = e1000_media_type_copper; 63862306a36Sopenharmony_ci dev_spec->sgmii_active = true; 63962306a36Sopenharmony_ci break; 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci fallthrough; /* for I2C based SGMII */ 64262306a36Sopenharmony_ci case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: 64362306a36Sopenharmony_ci /* read media type from SFP EEPROM */ 64462306a36Sopenharmony_ci ret_val = igb_set_sfp_media_type_82575(hw); 64562306a36Sopenharmony_ci if ((ret_val != 0) || 64662306a36Sopenharmony_ci (hw->phy.media_type == e1000_media_type_unknown)) { 64762306a36Sopenharmony_ci /* If media type was not identified then return media 64862306a36Sopenharmony_ci * type defined by the CTRL_EXT settings. 64962306a36Sopenharmony_ci */ 65062306a36Sopenharmony_ci hw->phy.media_type = e1000_media_type_internal_serdes; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) { 65362306a36Sopenharmony_ci hw->phy.media_type = e1000_media_type_copper; 65462306a36Sopenharmony_ci dev_spec->sgmii_active = true; 65562306a36Sopenharmony_ci } 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci break; 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci /* change current link mode setting */ 66162306a36Sopenharmony_ci ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci if (dev_spec->sgmii_active) 66462306a36Sopenharmony_ci ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII; 66562306a36Sopenharmony_ci else 66662306a36Sopenharmony_ci ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, ctrl_ext); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci break; 67162306a36Sopenharmony_ci default: 67262306a36Sopenharmony_ci break; 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* mac initialization and operations */ 67662306a36Sopenharmony_ci ret_val = igb_init_mac_params_82575(hw); 67762306a36Sopenharmony_ci if (ret_val) 67862306a36Sopenharmony_ci goto out; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci /* NVM initialization */ 68162306a36Sopenharmony_ci ret_val = igb_init_nvm_params_82575(hw); 68262306a36Sopenharmony_ci switch (hw->mac.type) { 68362306a36Sopenharmony_ci case e1000_i210: 68462306a36Sopenharmony_ci case e1000_i211: 68562306a36Sopenharmony_ci ret_val = igb_init_nvm_params_i210(hw); 68662306a36Sopenharmony_ci break; 68762306a36Sopenharmony_ci default: 68862306a36Sopenharmony_ci break; 68962306a36Sopenharmony_ci } 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci if (ret_val) 69262306a36Sopenharmony_ci goto out; 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci /* if part supports SR-IOV then initialize mailbox parameters */ 69562306a36Sopenharmony_ci switch (mac->type) { 69662306a36Sopenharmony_ci case e1000_82576: 69762306a36Sopenharmony_ci case e1000_i350: 69862306a36Sopenharmony_ci igb_init_mbx_params_pf(hw); 69962306a36Sopenharmony_ci break; 70062306a36Sopenharmony_ci default: 70162306a36Sopenharmony_ci break; 70262306a36Sopenharmony_ci } 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /* setup PHY parameters */ 70562306a36Sopenharmony_ci ret_val = igb_init_phy_params_82575(hw); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ciout: 70862306a36Sopenharmony_ci return ret_val; 70962306a36Sopenharmony_ci} 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci/** 71262306a36Sopenharmony_ci * igb_acquire_phy_82575 - Acquire rights to access PHY 71362306a36Sopenharmony_ci * @hw: pointer to the HW structure 71462306a36Sopenharmony_ci * 71562306a36Sopenharmony_ci * Acquire access rights to the correct PHY. This is a 71662306a36Sopenharmony_ci * function pointer entry point called by the api module. 71762306a36Sopenharmony_ci **/ 71862306a36Sopenharmony_cistatic s32 igb_acquire_phy_82575(struct e1000_hw *hw) 71962306a36Sopenharmony_ci{ 72062306a36Sopenharmony_ci u16 mask = E1000_SWFW_PHY0_SM; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci if (hw->bus.func == E1000_FUNC_1) 72362306a36Sopenharmony_ci mask = E1000_SWFW_PHY1_SM; 72462306a36Sopenharmony_ci else if (hw->bus.func == E1000_FUNC_2) 72562306a36Sopenharmony_ci mask = E1000_SWFW_PHY2_SM; 72662306a36Sopenharmony_ci else if (hw->bus.func == E1000_FUNC_3) 72762306a36Sopenharmony_ci mask = E1000_SWFW_PHY3_SM; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci return hw->mac.ops.acquire_swfw_sync(hw, mask); 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci/** 73362306a36Sopenharmony_ci * igb_release_phy_82575 - Release rights to access PHY 73462306a36Sopenharmony_ci * @hw: pointer to the HW structure 73562306a36Sopenharmony_ci * 73662306a36Sopenharmony_ci * A wrapper to release access rights to the correct PHY. This is a 73762306a36Sopenharmony_ci * function pointer entry point called by the api module. 73862306a36Sopenharmony_ci **/ 73962306a36Sopenharmony_cistatic void igb_release_phy_82575(struct e1000_hw *hw) 74062306a36Sopenharmony_ci{ 74162306a36Sopenharmony_ci u16 mask = E1000_SWFW_PHY0_SM; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci if (hw->bus.func == E1000_FUNC_1) 74462306a36Sopenharmony_ci mask = E1000_SWFW_PHY1_SM; 74562306a36Sopenharmony_ci else if (hw->bus.func == E1000_FUNC_2) 74662306a36Sopenharmony_ci mask = E1000_SWFW_PHY2_SM; 74762306a36Sopenharmony_ci else if (hw->bus.func == E1000_FUNC_3) 74862306a36Sopenharmony_ci mask = E1000_SWFW_PHY3_SM; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, mask); 75162306a36Sopenharmony_ci} 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci/** 75462306a36Sopenharmony_ci * igb_read_phy_reg_sgmii_82575 - Read PHY register using sgmii 75562306a36Sopenharmony_ci * @hw: pointer to the HW structure 75662306a36Sopenharmony_ci * @offset: register offset to be read 75762306a36Sopenharmony_ci * @data: pointer to the read data 75862306a36Sopenharmony_ci * 75962306a36Sopenharmony_ci * Reads the PHY register at offset using the serial gigabit media independent 76062306a36Sopenharmony_ci * interface and stores the retrieved information in data. 76162306a36Sopenharmony_ci **/ 76262306a36Sopenharmony_cistatic s32 igb_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, 76362306a36Sopenharmony_ci u16 *data) 76462306a36Sopenharmony_ci{ 76562306a36Sopenharmony_ci s32 ret_val = -E1000_ERR_PARAM; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { 76862306a36Sopenharmony_ci hw_dbg("PHY Address %u is out of range\n", offset); 76962306a36Sopenharmony_ci goto out; 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci ret_val = hw->phy.ops.acquire(hw); 77362306a36Sopenharmony_ci if (ret_val) 77462306a36Sopenharmony_ci goto out; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci ret_val = igb_read_phy_reg_i2c(hw, offset, data); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci hw->phy.ops.release(hw); 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ciout: 78162306a36Sopenharmony_ci return ret_val; 78262306a36Sopenharmony_ci} 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci/** 78562306a36Sopenharmony_ci * igb_write_phy_reg_sgmii_82575 - Write PHY register using sgmii 78662306a36Sopenharmony_ci * @hw: pointer to the HW structure 78762306a36Sopenharmony_ci * @offset: register offset to write to 78862306a36Sopenharmony_ci * @data: data to write at register offset 78962306a36Sopenharmony_ci * 79062306a36Sopenharmony_ci * Writes the data to PHY register at the offset using the serial gigabit 79162306a36Sopenharmony_ci * media independent interface. 79262306a36Sopenharmony_ci **/ 79362306a36Sopenharmony_cistatic s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, 79462306a36Sopenharmony_ci u16 data) 79562306a36Sopenharmony_ci{ 79662306a36Sopenharmony_ci s32 ret_val = -E1000_ERR_PARAM; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { 80062306a36Sopenharmony_ci hw_dbg("PHY Address %d is out of range\n", offset); 80162306a36Sopenharmony_ci goto out; 80262306a36Sopenharmony_ci } 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci ret_val = hw->phy.ops.acquire(hw); 80562306a36Sopenharmony_ci if (ret_val) 80662306a36Sopenharmony_ci goto out; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci ret_val = igb_write_phy_reg_i2c(hw, offset, data); 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci hw->phy.ops.release(hw); 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ciout: 81362306a36Sopenharmony_ci return ret_val; 81462306a36Sopenharmony_ci} 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci/** 81762306a36Sopenharmony_ci * igb_get_phy_id_82575 - Retrieve PHY addr and id 81862306a36Sopenharmony_ci * @hw: pointer to the HW structure 81962306a36Sopenharmony_ci * 82062306a36Sopenharmony_ci * Retrieves the PHY address and ID for both PHY's which do and do not use 82162306a36Sopenharmony_ci * sgmi interface. 82262306a36Sopenharmony_ci **/ 82362306a36Sopenharmony_cistatic s32 igb_get_phy_id_82575(struct e1000_hw *hw) 82462306a36Sopenharmony_ci{ 82562306a36Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 82662306a36Sopenharmony_ci s32 ret_val = 0; 82762306a36Sopenharmony_ci u16 phy_id; 82862306a36Sopenharmony_ci u32 ctrl_ext; 82962306a36Sopenharmony_ci u32 mdic; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* Extra read required for some PHY's on i354 */ 83262306a36Sopenharmony_ci if (hw->mac.type == e1000_i354) 83362306a36Sopenharmony_ci igb_get_phy_id(hw); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci /* For SGMII PHYs, we try the list of possible addresses until 83662306a36Sopenharmony_ci * we find one that works. For non-SGMII PHYs 83762306a36Sopenharmony_ci * (e.g. integrated copper PHYs), an address of 1 should 83862306a36Sopenharmony_ci * work. The result of this function should mean phy->phy_addr 83962306a36Sopenharmony_ci * and phy->id are set correctly. 84062306a36Sopenharmony_ci */ 84162306a36Sopenharmony_ci if (!(igb_sgmii_active_82575(hw))) { 84262306a36Sopenharmony_ci phy->addr = 1; 84362306a36Sopenharmony_ci ret_val = igb_get_phy_id(hw); 84462306a36Sopenharmony_ci goto out; 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci if (igb_sgmii_uses_mdio_82575(hw)) { 84862306a36Sopenharmony_ci switch (hw->mac.type) { 84962306a36Sopenharmony_ci case e1000_82575: 85062306a36Sopenharmony_ci case e1000_82576: 85162306a36Sopenharmony_ci mdic = rd32(E1000_MDIC); 85262306a36Sopenharmony_ci mdic &= E1000_MDIC_PHY_MASK; 85362306a36Sopenharmony_ci phy->addr = mdic >> E1000_MDIC_PHY_SHIFT; 85462306a36Sopenharmony_ci break; 85562306a36Sopenharmony_ci case e1000_82580: 85662306a36Sopenharmony_ci case e1000_i350: 85762306a36Sopenharmony_ci case e1000_i354: 85862306a36Sopenharmony_ci case e1000_i210: 85962306a36Sopenharmony_ci case e1000_i211: 86062306a36Sopenharmony_ci mdic = rd32(E1000_MDICNFG); 86162306a36Sopenharmony_ci mdic &= E1000_MDICNFG_PHY_MASK; 86262306a36Sopenharmony_ci phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; 86362306a36Sopenharmony_ci break; 86462306a36Sopenharmony_ci default: 86562306a36Sopenharmony_ci ret_val = -E1000_ERR_PHY; 86662306a36Sopenharmony_ci goto out; 86762306a36Sopenharmony_ci } 86862306a36Sopenharmony_ci ret_val = igb_get_phy_id(hw); 86962306a36Sopenharmony_ci goto out; 87062306a36Sopenharmony_ci } 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci /* Power on sgmii phy if it is disabled */ 87362306a36Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 87462306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); 87562306a36Sopenharmony_ci wrfl(); 87662306a36Sopenharmony_ci msleep(300); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci /* The address field in the I2CCMD register is 3 bits and 0 is invalid. 87962306a36Sopenharmony_ci * Therefore, we need to test 1-7 88062306a36Sopenharmony_ci */ 88162306a36Sopenharmony_ci for (phy->addr = 1; phy->addr < 8; phy->addr++) { 88262306a36Sopenharmony_ci ret_val = igb_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id); 88362306a36Sopenharmony_ci if (ret_val == 0) { 88462306a36Sopenharmony_ci hw_dbg("Vendor ID 0x%08X read at address %u\n", 88562306a36Sopenharmony_ci phy_id, phy->addr); 88662306a36Sopenharmony_ci /* At the time of this writing, The M88 part is 88762306a36Sopenharmony_ci * the only supported SGMII PHY product. 88862306a36Sopenharmony_ci */ 88962306a36Sopenharmony_ci if (phy_id == M88_VENDOR) 89062306a36Sopenharmony_ci break; 89162306a36Sopenharmony_ci } else { 89262306a36Sopenharmony_ci hw_dbg("PHY address %u was unreadable\n", phy->addr); 89362306a36Sopenharmony_ci } 89462306a36Sopenharmony_ci } 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci /* A valid PHY type couldn't be found. */ 89762306a36Sopenharmony_ci if (phy->addr == 8) { 89862306a36Sopenharmony_ci phy->addr = 0; 89962306a36Sopenharmony_ci ret_val = -E1000_ERR_PHY; 90062306a36Sopenharmony_ci goto out; 90162306a36Sopenharmony_ci } else { 90262306a36Sopenharmony_ci ret_val = igb_get_phy_id(hw); 90362306a36Sopenharmony_ci } 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci /* restore previous sfp cage power state */ 90662306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, ctrl_ext); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ciout: 90962306a36Sopenharmony_ci return ret_val; 91062306a36Sopenharmony_ci} 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci/** 91362306a36Sopenharmony_ci * igb_phy_hw_reset_sgmii_82575 - Performs a PHY reset 91462306a36Sopenharmony_ci * @hw: pointer to the HW structure 91562306a36Sopenharmony_ci * 91662306a36Sopenharmony_ci * Resets the PHY using the serial gigabit media independent interface. 91762306a36Sopenharmony_ci **/ 91862306a36Sopenharmony_cistatic s32 igb_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) 91962306a36Sopenharmony_ci{ 92062306a36Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 92162306a36Sopenharmony_ci s32 ret_val; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci /* This isn't a true "hard" reset, but is the only reset 92462306a36Sopenharmony_ci * available to us at this time. 92562306a36Sopenharmony_ci */ 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci hw_dbg("Soft resetting SGMII attached PHY...\n"); 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci /* SFP documentation requires the following to configure the SPF module 93062306a36Sopenharmony_ci * to work on SGMII. No further documentation is given. 93162306a36Sopenharmony_ci */ 93262306a36Sopenharmony_ci ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); 93362306a36Sopenharmony_ci if (ret_val) 93462306a36Sopenharmony_ci goto out; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci ret_val = igb_phy_sw_reset(hw); 93762306a36Sopenharmony_ci if (ret_val) 93862306a36Sopenharmony_ci goto out; 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci if (phy->id == M88E1512_E_PHY_ID) 94162306a36Sopenharmony_ci ret_val = igb_initialize_M88E1512_phy(hw); 94262306a36Sopenharmony_ci if (phy->id == M88E1543_E_PHY_ID) 94362306a36Sopenharmony_ci ret_val = igb_initialize_M88E1543_phy(hw); 94462306a36Sopenharmony_ciout: 94562306a36Sopenharmony_ci return ret_val; 94662306a36Sopenharmony_ci} 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci/** 94962306a36Sopenharmony_ci * igb_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state 95062306a36Sopenharmony_ci * @hw: pointer to the HW structure 95162306a36Sopenharmony_ci * @active: true to enable LPLU, false to disable 95262306a36Sopenharmony_ci * 95362306a36Sopenharmony_ci * Sets the LPLU D0 state according to the active flag. When 95462306a36Sopenharmony_ci * activating LPLU this function also disables smart speed 95562306a36Sopenharmony_ci * and vice versa. LPLU will not be activated unless the 95662306a36Sopenharmony_ci * device autonegotiation advertisement meets standards of 95762306a36Sopenharmony_ci * either 10 or 10/100 or 10/100/1000 at all duplexes. 95862306a36Sopenharmony_ci * This is a function pointer entry point only called by 95962306a36Sopenharmony_ci * PHY setup routines. 96062306a36Sopenharmony_ci **/ 96162306a36Sopenharmony_cistatic s32 igb_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) 96262306a36Sopenharmony_ci{ 96362306a36Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 96462306a36Sopenharmony_ci s32 ret_val; 96562306a36Sopenharmony_ci u16 data; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); 96862306a36Sopenharmony_ci if (ret_val) 96962306a36Sopenharmony_ci goto out; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci if (active) { 97262306a36Sopenharmony_ci data |= IGP02E1000_PM_D0_LPLU; 97362306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, 97462306a36Sopenharmony_ci data); 97562306a36Sopenharmony_ci if (ret_val) 97662306a36Sopenharmony_ci goto out; 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci /* When LPLU is enabled, we should disable SmartSpeed */ 97962306a36Sopenharmony_ci ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 98062306a36Sopenharmony_ci &data); 98162306a36Sopenharmony_ci data &= ~IGP01E1000_PSCFR_SMART_SPEED; 98262306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 98362306a36Sopenharmony_ci data); 98462306a36Sopenharmony_ci if (ret_val) 98562306a36Sopenharmony_ci goto out; 98662306a36Sopenharmony_ci } else { 98762306a36Sopenharmony_ci data &= ~IGP02E1000_PM_D0_LPLU; 98862306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, 98962306a36Sopenharmony_ci data); 99062306a36Sopenharmony_ci /* LPLU and SmartSpeed are mutually exclusive. LPLU is used 99162306a36Sopenharmony_ci * during Dx states where the power conservation is most 99262306a36Sopenharmony_ci * important. During driver activity we should enable 99362306a36Sopenharmony_ci * SmartSpeed, so performance is maintained. 99462306a36Sopenharmony_ci */ 99562306a36Sopenharmony_ci if (phy->smart_speed == e1000_smart_speed_on) { 99662306a36Sopenharmony_ci ret_val = phy->ops.read_reg(hw, 99762306a36Sopenharmony_ci IGP01E1000_PHY_PORT_CONFIG, &data); 99862306a36Sopenharmony_ci if (ret_val) 99962306a36Sopenharmony_ci goto out; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci data |= IGP01E1000_PSCFR_SMART_SPEED; 100262306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, 100362306a36Sopenharmony_ci IGP01E1000_PHY_PORT_CONFIG, data); 100462306a36Sopenharmony_ci if (ret_val) 100562306a36Sopenharmony_ci goto out; 100662306a36Sopenharmony_ci } else if (phy->smart_speed == e1000_smart_speed_off) { 100762306a36Sopenharmony_ci ret_val = phy->ops.read_reg(hw, 100862306a36Sopenharmony_ci IGP01E1000_PHY_PORT_CONFIG, &data); 100962306a36Sopenharmony_ci if (ret_val) 101062306a36Sopenharmony_ci goto out; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci data &= ~IGP01E1000_PSCFR_SMART_SPEED; 101362306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, 101462306a36Sopenharmony_ci IGP01E1000_PHY_PORT_CONFIG, data); 101562306a36Sopenharmony_ci if (ret_val) 101662306a36Sopenharmony_ci goto out; 101762306a36Sopenharmony_ci } 101862306a36Sopenharmony_ci } 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ciout: 102162306a36Sopenharmony_ci return ret_val; 102262306a36Sopenharmony_ci} 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci/** 102562306a36Sopenharmony_ci * igb_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state 102662306a36Sopenharmony_ci * @hw: pointer to the HW structure 102762306a36Sopenharmony_ci * @active: true to enable LPLU, false to disable 102862306a36Sopenharmony_ci * 102962306a36Sopenharmony_ci * Sets the LPLU D0 state according to the active flag. When 103062306a36Sopenharmony_ci * activating LPLU this function also disables smart speed 103162306a36Sopenharmony_ci * and vice versa. LPLU will not be activated unless the 103262306a36Sopenharmony_ci * device autonegotiation advertisement meets standards of 103362306a36Sopenharmony_ci * either 10 or 10/100 or 10/100/1000 at all duplexes. 103462306a36Sopenharmony_ci * This is a function pointer entry point only called by 103562306a36Sopenharmony_ci * PHY setup routines. 103662306a36Sopenharmony_ci **/ 103762306a36Sopenharmony_cistatic s32 igb_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) 103862306a36Sopenharmony_ci{ 103962306a36Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 104062306a36Sopenharmony_ci u16 data; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci data = rd32(E1000_82580_PHY_POWER_MGMT); 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci if (active) { 104562306a36Sopenharmony_ci data |= E1000_82580_PM_D0_LPLU; 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci /* When LPLU is enabled, we should disable SmartSpeed */ 104862306a36Sopenharmony_ci data &= ~E1000_82580_PM_SPD; 104962306a36Sopenharmony_ci } else { 105062306a36Sopenharmony_ci data &= ~E1000_82580_PM_D0_LPLU; 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci /* LPLU and SmartSpeed are mutually exclusive. LPLU is used 105362306a36Sopenharmony_ci * during Dx states where the power conservation is most 105462306a36Sopenharmony_ci * important. During driver activity we should enable 105562306a36Sopenharmony_ci * SmartSpeed, so performance is maintained. 105662306a36Sopenharmony_ci */ 105762306a36Sopenharmony_ci if (phy->smart_speed == e1000_smart_speed_on) 105862306a36Sopenharmony_ci data |= E1000_82580_PM_SPD; 105962306a36Sopenharmony_ci else if (phy->smart_speed == e1000_smart_speed_off) 106062306a36Sopenharmony_ci data &= ~E1000_82580_PM_SPD; } 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci wr32(E1000_82580_PHY_POWER_MGMT, data); 106362306a36Sopenharmony_ci return 0; 106462306a36Sopenharmony_ci} 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci/** 106762306a36Sopenharmony_ci * igb_set_d3_lplu_state_82580 - Sets low power link up state for D3 106862306a36Sopenharmony_ci * @hw: pointer to the HW structure 106962306a36Sopenharmony_ci * @active: boolean used to enable/disable lplu 107062306a36Sopenharmony_ci * 107162306a36Sopenharmony_ci * Success returns 0, Failure returns 1 107262306a36Sopenharmony_ci * 107362306a36Sopenharmony_ci * The low power link up (lplu) state is set to the power management level D3 107462306a36Sopenharmony_ci * and SmartSpeed is disabled when active is true, else clear lplu for D3 107562306a36Sopenharmony_ci * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU 107662306a36Sopenharmony_ci * is used during Dx states where the power conservation is most important. 107762306a36Sopenharmony_ci * During driver activity, SmartSpeed should be enabled so performance is 107862306a36Sopenharmony_ci * maintained. 107962306a36Sopenharmony_ci **/ 108062306a36Sopenharmony_cistatic s32 igb_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) 108162306a36Sopenharmony_ci{ 108262306a36Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 108362306a36Sopenharmony_ci u16 data; 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci data = rd32(E1000_82580_PHY_POWER_MGMT); 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci if (!active) { 108862306a36Sopenharmony_ci data &= ~E1000_82580_PM_D3_LPLU; 108962306a36Sopenharmony_ci /* LPLU and SmartSpeed are mutually exclusive. LPLU is used 109062306a36Sopenharmony_ci * during Dx states where the power conservation is most 109162306a36Sopenharmony_ci * important. During driver activity we should enable 109262306a36Sopenharmony_ci * SmartSpeed, so performance is maintained. 109362306a36Sopenharmony_ci */ 109462306a36Sopenharmony_ci if (phy->smart_speed == e1000_smart_speed_on) 109562306a36Sopenharmony_ci data |= E1000_82580_PM_SPD; 109662306a36Sopenharmony_ci else if (phy->smart_speed == e1000_smart_speed_off) 109762306a36Sopenharmony_ci data &= ~E1000_82580_PM_SPD; 109862306a36Sopenharmony_ci } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || 109962306a36Sopenharmony_ci (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || 110062306a36Sopenharmony_ci (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { 110162306a36Sopenharmony_ci data |= E1000_82580_PM_D3_LPLU; 110262306a36Sopenharmony_ci /* When LPLU is enabled, we should disable SmartSpeed */ 110362306a36Sopenharmony_ci data &= ~E1000_82580_PM_SPD; 110462306a36Sopenharmony_ci } 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci wr32(E1000_82580_PHY_POWER_MGMT, data); 110762306a36Sopenharmony_ci return 0; 110862306a36Sopenharmony_ci} 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci/** 111162306a36Sopenharmony_ci * igb_acquire_nvm_82575 - Request for access to EEPROM 111262306a36Sopenharmony_ci * @hw: pointer to the HW structure 111362306a36Sopenharmony_ci * 111462306a36Sopenharmony_ci * Acquire the necessary semaphores for exclusive access to the EEPROM. 111562306a36Sopenharmony_ci * Set the EEPROM access request bit and wait for EEPROM access grant bit. 111662306a36Sopenharmony_ci * Return successful if access grant bit set, else clear the request for 111762306a36Sopenharmony_ci * EEPROM access and return -E1000_ERR_NVM (-1). 111862306a36Sopenharmony_ci **/ 111962306a36Sopenharmony_cistatic s32 igb_acquire_nvm_82575(struct e1000_hw *hw) 112062306a36Sopenharmony_ci{ 112162306a36Sopenharmony_ci s32 ret_val; 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci ret_val = hw->mac.ops.acquire_swfw_sync(hw, E1000_SWFW_EEP_SM); 112462306a36Sopenharmony_ci if (ret_val) 112562306a36Sopenharmony_ci goto out; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci ret_val = igb_acquire_nvm(hw); 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci if (ret_val) 113062306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, E1000_SWFW_EEP_SM); 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ciout: 113362306a36Sopenharmony_ci return ret_val; 113462306a36Sopenharmony_ci} 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci/** 113762306a36Sopenharmony_ci * igb_release_nvm_82575 - Release exclusive access to EEPROM 113862306a36Sopenharmony_ci * @hw: pointer to the HW structure 113962306a36Sopenharmony_ci * 114062306a36Sopenharmony_ci * Stop any current commands to the EEPROM and clear the EEPROM request bit, 114162306a36Sopenharmony_ci * then release the semaphores acquired. 114262306a36Sopenharmony_ci **/ 114362306a36Sopenharmony_cistatic void igb_release_nvm_82575(struct e1000_hw *hw) 114462306a36Sopenharmony_ci{ 114562306a36Sopenharmony_ci igb_release_nvm(hw); 114662306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, E1000_SWFW_EEP_SM); 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci/** 115062306a36Sopenharmony_ci * igb_acquire_swfw_sync_82575 - Acquire SW/FW semaphore 115162306a36Sopenharmony_ci * @hw: pointer to the HW structure 115262306a36Sopenharmony_ci * @mask: specifies which semaphore to acquire 115362306a36Sopenharmony_ci * 115462306a36Sopenharmony_ci * Acquire the SW/FW semaphore to access the PHY or NVM. The mask 115562306a36Sopenharmony_ci * will also specify which port we're acquiring the lock for. 115662306a36Sopenharmony_ci **/ 115762306a36Sopenharmony_cistatic s32 igb_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask) 115862306a36Sopenharmony_ci{ 115962306a36Sopenharmony_ci u32 swfw_sync; 116062306a36Sopenharmony_ci u32 swmask = mask; 116162306a36Sopenharmony_ci u32 fwmask = mask << 16; 116262306a36Sopenharmony_ci s32 ret_val = 0; 116362306a36Sopenharmony_ci s32 i = 0, timeout = 200; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci while (i < timeout) { 116662306a36Sopenharmony_ci if (igb_get_hw_semaphore(hw)) { 116762306a36Sopenharmony_ci ret_val = -E1000_ERR_SWFW_SYNC; 116862306a36Sopenharmony_ci goto out; 116962306a36Sopenharmony_ci } 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci swfw_sync = rd32(E1000_SW_FW_SYNC); 117262306a36Sopenharmony_ci if (!(swfw_sync & (fwmask | swmask))) 117362306a36Sopenharmony_ci break; 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci /* Firmware currently using resource (fwmask) 117662306a36Sopenharmony_ci * or other software thread using resource (swmask) 117762306a36Sopenharmony_ci */ 117862306a36Sopenharmony_ci igb_put_hw_semaphore(hw); 117962306a36Sopenharmony_ci mdelay(5); 118062306a36Sopenharmony_ci i++; 118162306a36Sopenharmony_ci } 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci if (i == timeout) { 118462306a36Sopenharmony_ci hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); 118562306a36Sopenharmony_ci ret_val = -E1000_ERR_SWFW_SYNC; 118662306a36Sopenharmony_ci goto out; 118762306a36Sopenharmony_ci } 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci swfw_sync |= swmask; 119062306a36Sopenharmony_ci wr32(E1000_SW_FW_SYNC, swfw_sync); 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci igb_put_hw_semaphore(hw); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ciout: 119562306a36Sopenharmony_ci return ret_val; 119662306a36Sopenharmony_ci} 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci/** 119962306a36Sopenharmony_ci * igb_release_swfw_sync_82575 - Release SW/FW semaphore 120062306a36Sopenharmony_ci * @hw: pointer to the HW structure 120162306a36Sopenharmony_ci * @mask: specifies which semaphore to acquire 120262306a36Sopenharmony_ci * 120362306a36Sopenharmony_ci * Release the SW/FW semaphore used to access the PHY or NVM. The mask 120462306a36Sopenharmony_ci * will also specify which port we're releasing the lock for. 120562306a36Sopenharmony_ci **/ 120662306a36Sopenharmony_cistatic void igb_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask) 120762306a36Sopenharmony_ci{ 120862306a36Sopenharmony_ci u32 swfw_sync; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci while (igb_get_hw_semaphore(hw) != 0) 121162306a36Sopenharmony_ci ; /* Empty */ 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci swfw_sync = rd32(E1000_SW_FW_SYNC); 121462306a36Sopenharmony_ci swfw_sync &= ~mask; 121562306a36Sopenharmony_ci wr32(E1000_SW_FW_SYNC, swfw_sync); 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci igb_put_hw_semaphore(hw); 121862306a36Sopenharmony_ci} 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci/** 122162306a36Sopenharmony_ci * igb_get_cfg_done_82575 - Read config done bit 122262306a36Sopenharmony_ci * @hw: pointer to the HW structure 122362306a36Sopenharmony_ci * 122462306a36Sopenharmony_ci * Read the management control register for the config done bit for 122562306a36Sopenharmony_ci * completion status. NOTE: silicon which is EEPROM-less will fail trying 122662306a36Sopenharmony_ci * to read the config done bit, so an error is *ONLY* logged and returns 122762306a36Sopenharmony_ci * 0. If we were to return with error, EEPROM-less silicon 122862306a36Sopenharmony_ci * would not be able to be reset or change link. 122962306a36Sopenharmony_ci **/ 123062306a36Sopenharmony_cistatic s32 igb_get_cfg_done_82575(struct e1000_hw *hw) 123162306a36Sopenharmony_ci{ 123262306a36Sopenharmony_ci s32 timeout = PHY_CFG_TIMEOUT; 123362306a36Sopenharmony_ci u32 mask = E1000_NVM_CFG_DONE_PORT_0; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci if (hw->bus.func == 1) 123662306a36Sopenharmony_ci mask = E1000_NVM_CFG_DONE_PORT_1; 123762306a36Sopenharmony_ci else if (hw->bus.func == E1000_FUNC_2) 123862306a36Sopenharmony_ci mask = E1000_NVM_CFG_DONE_PORT_2; 123962306a36Sopenharmony_ci else if (hw->bus.func == E1000_FUNC_3) 124062306a36Sopenharmony_ci mask = E1000_NVM_CFG_DONE_PORT_3; 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci while (timeout) { 124362306a36Sopenharmony_ci if (rd32(E1000_EEMNGCTL) & mask) 124462306a36Sopenharmony_ci break; 124562306a36Sopenharmony_ci usleep_range(1000, 2000); 124662306a36Sopenharmony_ci timeout--; 124762306a36Sopenharmony_ci } 124862306a36Sopenharmony_ci if (!timeout) 124962306a36Sopenharmony_ci hw_dbg("MNG configuration cycle has not completed.\n"); 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci /* If EEPROM is not marked present, init the PHY manually */ 125262306a36Sopenharmony_ci if (((rd32(E1000_EECD) & E1000_EECD_PRES) == 0) && 125362306a36Sopenharmony_ci (hw->phy.type == e1000_phy_igp_3)) 125462306a36Sopenharmony_ci igb_phy_init_script_igp3(hw); 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci return 0; 125762306a36Sopenharmony_ci} 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci/** 126062306a36Sopenharmony_ci * igb_get_link_up_info_82575 - Get link speed/duplex info 126162306a36Sopenharmony_ci * @hw: pointer to the HW structure 126262306a36Sopenharmony_ci * @speed: stores the current speed 126362306a36Sopenharmony_ci * @duplex: stores the current duplex 126462306a36Sopenharmony_ci * 126562306a36Sopenharmony_ci * This is a wrapper function, if using the serial gigabit media independent 126662306a36Sopenharmony_ci * interface, use PCS to retrieve the link speed and duplex information. 126762306a36Sopenharmony_ci * Otherwise, use the generic function to get the link speed and duplex info. 126862306a36Sopenharmony_ci **/ 126962306a36Sopenharmony_cistatic s32 igb_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, 127062306a36Sopenharmony_ci u16 *duplex) 127162306a36Sopenharmony_ci{ 127262306a36Sopenharmony_ci s32 ret_val; 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci if (hw->phy.media_type != e1000_media_type_copper) 127562306a36Sopenharmony_ci ret_val = igb_get_pcs_speed_and_duplex_82575(hw, speed, 127662306a36Sopenharmony_ci duplex); 127762306a36Sopenharmony_ci else 127862306a36Sopenharmony_ci ret_val = igb_get_speed_and_duplex_copper(hw, speed, 127962306a36Sopenharmony_ci duplex); 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci return ret_val; 128262306a36Sopenharmony_ci} 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci/** 128562306a36Sopenharmony_ci * igb_check_for_link_82575 - Check for link 128662306a36Sopenharmony_ci * @hw: pointer to the HW structure 128762306a36Sopenharmony_ci * 128862306a36Sopenharmony_ci * If sgmii is enabled, then use the pcs register to determine link, otherwise 128962306a36Sopenharmony_ci * use the generic interface for determining link. 129062306a36Sopenharmony_ci **/ 129162306a36Sopenharmony_cistatic s32 igb_check_for_link_82575(struct e1000_hw *hw) 129262306a36Sopenharmony_ci{ 129362306a36Sopenharmony_ci s32 ret_val; 129462306a36Sopenharmony_ci u16 speed, duplex; 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci if (hw->phy.media_type != e1000_media_type_copper) { 129762306a36Sopenharmony_ci ret_val = igb_get_pcs_speed_and_duplex_82575(hw, &speed, 129862306a36Sopenharmony_ci &duplex); 129962306a36Sopenharmony_ci /* Use this flag to determine if link needs to be checked or 130062306a36Sopenharmony_ci * not. If we have link clear the flag so that we do not 130162306a36Sopenharmony_ci * continue to check for link. 130262306a36Sopenharmony_ci */ 130362306a36Sopenharmony_ci hw->mac.get_link_status = !hw->mac.serdes_has_link; 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci /* Configure Flow Control now that Auto-Neg has completed. 130662306a36Sopenharmony_ci * First, we need to restore the desired flow control 130762306a36Sopenharmony_ci * settings because we may have had to re-autoneg with a 130862306a36Sopenharmony_ci * different link partner. 130962306a36Sopenharmony_ci */ 131062306a36Sopenharmony_ci ret_val = igb_config_fc_after_link_up(hw); 131162306a36Sopenharmony_ci if (ret_val) 131262306a36Sopenharmony_ci hw_dbg("Error configuring flow control\n"); 131362306a36Sopenharmony_ci } else { 131462306a36Sopenharmony_ci ret_val = igb_check_for_copper_link(hw); 131562306a36Sopenharmony_ci } 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci return ret_val; 131862306a36Sopenharmony_ci} 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci/** 132162306a36Sopenharmony_ci * igb_power_up_serdes_link_82575 - Power up the serdes link after shutdown 132262306a36Sopenharmony_ci * @hw: pointer to the HW structure 132362306a36Sopenharmony_ci **/ 132462306a36Sopenharmony_civoid igb_power_up_serdes_link_82575(struct e1000_hw *hw) 132562306a36Sopenharmony_ci{ 132662306a36Sopenharmony_ci u32 reg; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 133062306a36Sopenharmony_ci !igb_sgmii_active_82575(hw)) 133162306a36Sopenharmony_ci return; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci /* Enable PCS to turn on link */ 133462306a36Sopenharmony_ci reg = rd32(E1000_PCS_CFG0); 133562306a36Sopenharmony_ci reg |= E1000_PCS_CFG_PCS_EN; 133662306a36Sopenharmony_ci wr32(E1000_PCS_CFG0, reg); 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci /* Power up the laser */ 133962306a36Sopenharmony_ci reg = rd32(E1000_CTRL_EXT); 134062306a36Sopenharmony_ci reg &= ~E1000_CTRL_EXT_SDP3_DATA; 134162306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, reg); 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci /* flush the write to verify completion */ 134462306a36Sopenharmony_ci wrfl(); 134562306a36Sopenharmony_ci usleep_range(1000, 2000); 134662306a36Sopenharmony_ci} 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci/** 134962306a36Sopenharmony_ci * igb_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex 135062306a36Sopenharmony_ci * @hw: pointer to the HW structure 135162306a36Sopenharmony_ci * @speed: stores the current speed 135262306a36Sopenharmony_ci * @duplex: stores the current duplex 135362306a36Sopenharmony_ci * 135462306a36Sopenharmony_ci * Using the physical coding sub-layer (PCS), retrieve the current speed and 135562306a36Sopenharmony_ci * duplex, then store the values in the pointers provided. 135662306a36Sopenharmony_ci **/ 135762306a36Sopenharmony_cistatic s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, 135862306a36Sopenharmony_ci u16 *duplex) 135962306a36Sopenharmony_ci{ 136062306a36Sopenharmony_ci struct e1000_mac_info *mac = &hw->mac; 136162306a36Sopenharmony_ci u32 pcs, status; 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci /* Set up defaults for the return values of this function */ 136462306a36Sopenharmony_ci mac->serdes_has_link = false; 136562306a36Sopenharmony_ci *speed = 0; 136662306a36Sopenharmony_ci *duplex = 0; 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci /* Read the PCS Status register for link state. For non-copper mode, 136962306a36Sopenharmony_ci * the status register is not accurate. The PCS status register is 137062306a36Sopenharmony_ci * used instead. 137162306a36Sopenharmony_ci */ 137262306a36Sopenharmony_ci pcs = rd32(E1000_PCS_LSTAT); 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci /* The link up bit determines when link is up on autoneg. The sync ok 137562306a36Sopenharmony_ci * gets set once both sides sync up and agree upon link. Stable link 137662306a36Sopenharmony_ci * can be determined by checking for both link up and link sync ok 137762306a36Sopenharmony_ci */ 137862306a36Sopenharmony_ci if ((pcs & E1000_PCS_LSTS_LINK_OK) && (pcs & E1000_PCS_LSTS_SYNK_OK)) { 137962306a36Sopenharmony_ci mac->serdes_has_link = true; 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci /* Detect and store PCS speed */ 138262306a36Sopenharmony_ci if (pcs & E1000_PCS_LSTS_SPEED_1000) 138362306a36Sopenharmony_ci *speed = SPEED_1000; 138462306a36Sopenharmony_ci else if (pcs & E1000_PCS_LSTS_SPEED_100) 138562306a36Sopenharmony_ci *speed = SPEED_100; 138662306a36Sopenharmony_ci else 138762306a36Sopenharmony_ci *speed = SPEED_10; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci /* Detect and store PCS duplex */ 139062306a36Sopenharmony_ci if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) 139162306a36Sopenharmony_ci *duplex = FULL_DUPLEX; 139262306a36Sopenharmony_ci else 139362306a36Sopenharmony_ci *duplex = HALF_DUPLEX; 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci /* Check if it is an I354 2.5Gb backplane connection. */ 139662306a36Sopenharmony_ci if (mac->type == e1000_i354) { 139762306a36Sopenharmony_ci status = rd32(E1000_STATUS); 139862306a36Sopenharmony_ci if ((status & E1000_STATUS_2P5_SKU) && 139962306a36Sopenharmony_ci !(status & E1000_STATUS_2P5_SKU_OVER)) { 140062306a36Sopenharmony_ci *speed = SPEED_2500; 140162306a36Sopenharmony_ci *duplex = FULL_DUPLEX; 140262306a36Sopenharmony_ci hw_dbg("2500 Mbs, "); 140362306a36Sopenharmony_ci hw_dbg("Full Duplex\n"); 140462306a36Sopenharmony_ci } 140562306a36Sopenharmony_ci } 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci } 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci return 0; 141062306a36Sopenharmony_ci} 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci/** 141362306a36Sopenharmony_ci * igb_shutdown_serdes_link_82575 - Remove link during power down 141462306a36Sopenharmony_ci * @hw: pointer to the HW structure 141562306a36Sopenharmony_ci * 141662306a36Sopenharmony_ci * In the case of fiber serdes, shut down optics and PCS on driver unload 141762306a36Sopenharmony_ci * when management pass thru is not enabled. 141862306a36Sopenharmony_ci **/ 141962306a36Sopenharmony_civoid igb_shutdown_serdes_link_82575(struct e1000_hw *hw) 142062306a36Sopenharmony_ci{ 142162306a36Sopenharmony_ci u32 reg; 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci if (hw->phy.media_type != e1000_media_type_internal_serdes && 142462306a36Sopenharmony_ci igb_sgmii_active_82575(hw)) 142562306a36Sopenharmony_ci return; 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_ci if (!igb_enable_mng_pass_thru(hw)) { 142862306a36Sopenharmony_ci /* Disable PCS to turn off link */ 142962306a36Sopenharmony_ci reg = rd32(E1000_PCS_CFG0); 143062306a36Sopenharmony_ci reg &= ~E1000_PCS_CFG_PCS_EN; 143162306a36Sopenharmony_ci wr32(E1000_PCS_CFG0, reg); 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci /* shutdown the laser */ 143462306a36Sopenharmony_ci reg = rd32(E1000_CTRL_EXT); 143562306a36Sopenharmony_ci reg |= E1000_CTRL_EXT_SDP3_DATA; 143662306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, reg); 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci /* flush the write to verify completion */ 143962306a36Sopenharmony_ci wrfl(); 144062306a36Sopenharmony_ci usleep_range(1000, 2000); 144162306a36Sopenharmony_ci } 144262306a36Sopenharmony_ci} 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci/** 144562306a36Sopenharmony_ci * igb_reset_hw_82575 - Reset hardware 144662306a36Sopenharmony_ci * @hw: pointer to the HW structure 144762306a36Sopenharmony_ci * 144862306a36Sopenharmony_ci * This resets the hardware into a known state. This is a 144962306a36Sopenharmony_ci * function pointer entry point called by the api module. 145062306a36Sopenharmony_ci **/ 145162306a36Sopenharmony_cistatic s32 igb_reset_hw_82575(struct e1000_hw *hw) 145262306a36Sopenharmony_ci{ 145362306a36Sopenharmony_ci u32 ctrl; 145462306a36Sopenharmony_ci s32 ret_val; 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci /* Prevent the PCI-E bus from sticking if there is no TLP connection 145762306a36Sopenharmony_ci * on the last TLP read/write transaction when MAC is reset. 145862306a36Sopenharmony_ci */ 145962306a36Sopenharmony_ci ret_val = igb_disable_pcie_master(hw); 146062306a36Sopenharmony_ci if (ret_val) 146162306a36Sopenharmony_ci hw_dbg("PCI-E Master disable polling has failed.\n"); 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci /* set the completion timeout for interface */ 146462306a36Sopenharmony_ci ret_val = igb_set_pcie_completion_timeout(hw); 146562306a36Sopenharmony_ci if (ret_val) 146662306a36Sopenharmony_ci hw_dbg("PCI-E Set completion timeout has failed.\n"); 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci hw_dbg("Masking off all interrupts\n"); 146962306a36Sopenharmony_ci wr32(E1000_IMC, 0xffffffff); 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci wr32(E1000_RCTL, 0); 147262306a36Sopenharmony_ci wr32(E1000_TCTL, E1000_TCTL_PSP); 147362306a36Sopenharmony_ci wrfl(); 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci usleep_range(10000, 20000); 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_ci ctrl = rd32(E1000_CTRL); 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci hw_dbg("Issuing a global reset to MAC\n"); 148062306a36Sopenharmony_ci wr32(E1000_CTRL, ctrl | E1000_CTRL_RST); 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci ret_val = igb_get_auto_rd_done(hw); 148362306a36Sopenharmony_ci if (ret_val) { 148462306a36Sopenharmony_ci /* When auto config read does not complete, do not 148562306a36Sopenharmony_ci * return with an error. This can happen in situations 148662306a36Sopenharmony_ci * where there is no eeprom and prevents getting link. 148762306a36Sopenharmony_ci */ 148862306a36Sopenharmony_ci hw_dbg("Auto Read Done did not complete\n"); 148962306a36Sopenharmony_ci } 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci /* If EEPROM is not present, run manual init scripts */ 149262306a36Sopenharmony_ci if ((rd32(E1000_EECD) & E1000_EECD_PRES) == 0) 149362306a36Sopenharmony_ci igb_reset_init_script_82575(hw); 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci /* Clear any pending interrupt events. */ 149662306a36Sopenharmony_ci wr32(E1000_IMC, 0xffffffff); 149762306a36Sopenharmony_ci rd32(E1000_ICR); 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci /* Install any alternate MAC address into RAR0 */ 150062306a36Sopenharmony_ci ret_val = igb_check_alt_mac_addr(hw); 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci return ret_val; 150362306a36Sopenharmony_ci} 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci/** 150662306a36Sopenharmony_ci * igb_init_hw_82575 - Initialize hardware 150762306a36Sopenharmony_ci * @hw: pointer to the HW structure 150862306a36Sopenharmony_ci * 150962306a36Sopenharmony_ci * This inits the hardware readying it for operation. 151062306a36Sopenharmony_ci **/ 151162306a36Sopenharmony_cistatic s32 igb_init_hw_82575(struct e1000_hw *hw) 151262306a36Sopenharmony_ci{ 151362306a36Sopenharmony_ci struct e1000_mac_info *mac = &hw->mac; 151462306a36Sopenharmony_ci s32 ret_val; 151562306a36Sopenharmony_ci u16 i, rar_count = mac->rar_entry_count; 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci if ((hw->mac.type >= e1000_i210) && 151862306a36Sopenharmony_ci !(igb_get_flash_presence_i210(hw))) { 151962306a36Sopenharmony_ci ret_val = igb_pll_workaround_i210(hw); 152062306a36Sopenharmony_ci if (ret_val) 152162306a36Sopenharmony_ci return ret_val; 152262306a36Sopenharmony_ci } 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ci /* Initialize identification LED */ 152562306a36Sopenharmony_ci ret_val = igb_id_led_init(hw); 152662306a36Sopenharmony_ci if (ret_val) { 152762306a36Sopenharmony_ci hw_dbg("Error initializing identification LED\n"); 152862306a36Sopenharmony_ci /* This is not fatal and we should not stop init due to this */ 152962306a36Sopenharmony_ci } 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci /* Disabling VLAN filtering */ 153262306a36Sopenharmony_ci hw_dbg("Initializing the IEEE VLAN\n"); 153362306a36Sopenharmony_ci igb_clear_vfta(hw); 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci /* Setup the receive address */ 153662306a36Sopenharmony_ci igb_init_rx_addrs(hw, rar_count); 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci /* Zero out the Multicast HASH table */ 153962306a36Sopenharmony_ci hw_dbg("Zeroing the MTA\n"); 154062306a36Sopenharmony_ci for (i = 0; i < mac->mta_reg_count; i++) 154162306a36Sopenharmony_ci array_wr32(E1000_MTA, i, 0); 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci /* Zero out the Unicast HASH table */ 154462306a36Sopenharmony_ci hw_dbg("Zeroing the UTA\n"); 154562306a36Sopenharmony_ci for (i = 0; i < mac->uta_reg_count; i++) 154662306a36Sopenharmony_ci array_wr32(E1000_UTA, i, 0); 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci /* Setup link and flow control */ 154962306a36Sopenharmony_ci ret_val = igb_setup_link(hw); 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci /* Clear all of the statistics registers (clear on read). It is 155262306a36Sopenharmony_ci * important that we do this after we have tried to establish link 155362306a36Sopenharmony_ci * because the symbol error count will increment wildly if there 155462306a36Sopenharmony_ci * is no link. 155562306a36Sopenharmony_ci */ 155662306a36Sopenharmony_ci igb_clear_hw_cntrs_82575(hw); 155762306a36Sopenharmony_ci return ret_val; 155862306a36Sopenharmony_ci} 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci/** 156162306a36Sopenharmony_ci * igb_setup_copper_link_82575 - Configure copper link settings 156262306a36Sopenharmony_ci * @hw: pointer to the HW structure 156362306a36Sopenharmony_ci * 156462306a36Sopenharmony_ci * Configures the link for auto-neg or forced speed and duplex. Then we check 156562306a36Sopenharmony_ci * for link, once link is established calls to configure collision distance 156662306a36Sopenharmony_ci * and flow control are called. 156762306a36Sopenharmony_ci **/ 156862306a36Sopenharmony_cistatic s32 igb_setup_copper_link_82575(struct e1000_hw *hw) 156962306a36Sopenharmony_ci{ 157062306a36Sopenharmony_ci u32 ctrl; 157162306a36Sopenharmony_ci s32 ret_val; 157262306a36Sopenharmony_ci u32 phpm_reg; 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ci ctrl = rd32(E1000_CTRL); 157562306a36Sopenharmony_ci ctrl |= E1000_CTRL_SLU; 157662306a36Sopenharmony_ci ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 157762306a36Sopenharmony_ci wr32(E1000_CTRL, ctrl); 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci /* Clear Go Link Disconnect bit on supported devices */ 158062306a36Sopenharmony_ci switch (hw->mac.type) { 158162306a36Sopenharmony_ci case e1000_82580: 158262306a36Sopenharmony_ci case e1000_i350: 158362306a36Sopenharmony_ci case e1000_i210: 158462306a36Sopenharmony_ci case e1000_i211: 158562306a36Sopenharmony_ci phpm_reg = rd32(E1000_82580_PHY_POWER_MGMT); 158662306a36Sopenharmony_ci phpm_reg &= ~E1000_82580_PM_GO_LINKD; 158762306a36Sopenharmony_ci wr32(E1000_82580_PHY_POWER_MGMT, phpm_reg); 158862306a36Sopenharmony_ci break; 158962306a36Sopenharmony_ci default: 159062306a36Sopenharmony_ci break; 159162306a36Sopenharmony_ci } 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci ret_val = igb_setup_serdes_link_82575(hw); 159462306a36Sopenharmony_ci if (ret_val) 159562306a36Sopenharmony_ci goto out; 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci if (igb_sgmii_active_82575(hw) && !hw->phy.reset_disable) { 159862306a36Sopenharmony_ci /* allow time for SFP cage time to power up phy */ 159962306a36Sopenharmony_ci msleep(300); 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci ret_val = hw->phy.ops.reset(hw); 160262306a36Sopenharmony_ci if (ret_val) { 160362306a36Sopenharmony_ci hw_dbg("Error resetting the PHY.\n"); 160462306a36Sopenharmony_ci goto out; 160562306a36Sopenharmony_ci } 160662306a36Sopenharmony_ci } 160762306a36Sopenharmony_ci switch (hw->phy.type) { 160862306a36Sopenharmony_ci case e1000_phy_i210: 160962306a36Sopenharmony_ci case e1000_phy_m88: 161062306a36Sopenharmony_ci switch (hw->phy.id) { 161162306a36Sopenharmony_ci case I347AT4_E_PHY_ID: 161262306a36Sopenharmony_ci case M88E1112_E_PHY_ID: 161362306a36Sopenharmony_ci case M88E1543_E_PHY_ID: 161462306a36Sopenharmony_ci case M88E1512_E_PHY_ID: 161562306a36Sopenharmony_ci case I210_I_PHY_ID: 161662306a36Sopenharmony_ci ret_val = igb_copper_link_setup_m88_gen2(hw); 161762306a36Sopenharmony_ci break; 161862306a36Sopenharmony_ci default: 161962306a36Sopenharmony_ci ret_val = igb_copper_link_setup_m88(hw); 162062306a36Sopenharmony_ci break; 162162306a36Sopenharmony_ci } 162262306a36Sopenharmony_ci break; 162362306a36Sopenharmony_ci case e1000_phy_igp_3: 162462306a36Sopenharmony_ci ret_val = igb_copper_link_setup_igp(hw); 162562306a36Sopenharmony_ci break; 162662306a36Sopenharmony_ci case e1000_phy_82580: 162762306a36Sopenharmony_ci ret_val = igb_copper_link_setup_82580(hw); 162862306a36Sopenharmony_ci break; 162962306a36Sopenharmony_ci case e1000_phy_bcm54616: 163062306a36Sopenharmony_ci ret_val = 0; 163162306a36Sopenharmony_ci break; 163262306a36Sopenharmony_ci default: 163362306a36Sopenharmony_ci ret_val = -E1000_ERR_PHY; 163462306a36Sopenharmony_ci break; 163562306a36Sopenharmony_ci } 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci if (ret_val) 163862306a36Sopenharmony_ci goto out; 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci ret_val = igb_setup_copper_link(hw); 164162306a36Sopenharmony_ciout: 164262306a36Sopenharmony_ci return ret_val; 164362306a36Sopenharmony_ci} 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci/** 164662306a36Sopenharmony_ci * igb_setup_serdes_link_82575 - Setup link for serdes 164762306a36Sopenharmony_ci * @hw: pointer to the HW structure 164862306a36Sopenharmony_ci * 164962306a36Sopenharmony_ci * Configure the physical coding sub-layer (PCS) link. The PCS link is 165062306a36Sopenharmony_ci * used on copper connections where the serialized gigabit media independent 165162306a36Sopenharmony_ci * interface (sgmii), or serdes fiber is being used. Configures the link 165262306a36Sopenharmony_ci * for auto-negotiation or forces speed/duplex. 165362306a36Sopenharmony_ci **/ 165462306a36Sopenharmony_cistatic s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) 165562306a36Sopenharmony_ci{ 165662306a36Sopenharmony_ci u32 ctrl_ext, ctrl_reg, reg, anadv_reg; 165762306a36Sopenharmony_ci bool pcs_autoneg; 165862306a36Sopenharmony_ci s32 ret_val = 0; 165962306a36Sopenharmony_ci u16 data; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 166262306a36Sopenharmony_ci !igb_sgmii_active_82575(hw)) 166362306a36Sopenharmony_ci return ret_val; 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci /* On the 82575, SerDes loopback mode persists until it is 166762306a36Sopenharmony_ci * explicitly turned off or a power cycle is performed. A read to 166862306a36Sopenharmony_ci * the register does not indicate its status. Therefore, we ensure 166962306a36Sopenharmony_ci * loopback mode is disabled during initialization. 167062306a36Sopenharmony_ci */ 167162306a36Sopenharmony_ci wr32(E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci /* power on the sfp cage if present and turn on I2C */ 167462306a36Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 167562306a36Sopenharmony_ci ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; 167662306a36Sopenharmony_ci ctrl_ext |= E1000_CTRL_I2C_ENA; 167762306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, ctrl_ext); 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci ctrl_reg = rd32(E1000_CTRL); 168062306a36Sopenharmony_ci ctrl_reg |= E1000_CTRL_SLU; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) { 168362306a36Sopenharmony_ci /* set both sw defined pins */ 168462306a36Sopenharmony_ci ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci /* Set switch control to serdes energy detect */ 168762306a36Sopenharmony_ci reg = rd32(E1000_CONNSW); 168862306a36Sopenharmony_ci reg |= E1000_CONNSW_ENRGSRC; 168962306a36Sopenharmony_ci wr32(E1000_CONNSW, reg); 169062306a36Sopenharmony_ci } 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci reg = rd32(E1000_PCS_LCTL); 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci /* default pcs_autoneg to the same setting as mac autoneg */ 169562306a36Sopenharmony_ci pcs_autoneg = hw->mac.autoneg; 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { 169862306a36Sopenharmony_ci case E1000_CTRL_EXT_LINK_MODE_SGMII: 169962306a36Sopenharmony_ci /* sgmii mode lets the phy handle forcing speed/duplex */ 170062306a36Sopenharmony_ci pcs_autoneg = true; 170162306a36Sopenharmony_ci /* autoneg time out should be disabled for SGMII mode */ 170262306a36Sopenharmony_ci reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); 170362306a36Sopenharmony_ci break; 170462306a36Sopenharmony_ci case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: 170562306a36Sopenharmony_ci /* disable PCS autoneg and support parallel detect only */ 170662306a36Sopenharmony_ci pcs_autoneg = false; 170762306a36Sopenharmony_ci fallthrough; 170862306a36Sopenharmony_ci default: 170962306a36Sopenharmony_ci if (hw->mac.type == e1000_82575 || 171062306a36Sopenharmony_ci hw->mac.type == e1000_82576) { 171162306a36Sopenharmony_ci ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data); 171262306a36Sopenharmony_ci if (ret_val) { 171362306a36Sopenharmony_ci hw_dbg(KERN_DEBUG "NVM Read Error\n\n"); 171462306a36Sopenharmony_ci return ret_val; 171562306a36Sopenharmony_ci } 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT) 171862306a36Sopenharmony_ci pcs_autoneg = false; 171962306a36Sopenharmony_ci } 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci /* non-SGMII modes only supports a speed of 1000/Full for the 172262306a36Sopenharmony_ci * link so it is best to just force the MAC and let the pcs 172362306a36Sopenharmony_ci * link either autoneg or be forced to 1000/Full 172462306a36Sopenharmony_ci */ 172562306a36Sopenharmony_ci ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD | 172662306a36Sopenharmony_ci E1000_CTRL_FD | E1000_CTRL_FRCDPX; 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci /* set speed of 1000/Full if speed/duplex is forced */ 172962306a36Sopenharmony_ci reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL; 173062306a36Sopenharmony_ci break; 173162306a36Sopenharmony_ci } 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_ci wr32(E1000_CTRL, ctrl_reg); 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci /* New SerDes mode allows for forcing speed or autonegotiating speed 173662306a36Sopenharmony_ci * at 1gb. Autoneg should be default set by most drivers. This is the 173762306a36Sopenharmony_ci * mode that will be compatible with older link partners and switches. 173862306a36Sopenharmony_ci * However, both are supported by the hardware and some drivers/tools. 173962306a36Sopenharmony_ci */ 174062306a36Sopenharmony_ci reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | 174162306a36Sopenharmony_ci E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci if (pcs_autoneg) { 174462306a36Sopenharmony_ci /* Set PCS register for autoneg */ 174562306a36Sopenharmony_ci reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ 174662306a36Sopenharmony_ci E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci /* Disable force flow control for autoneg */ 174962306a36Sopenharmony_ci reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ci /* Configure flow control advertisement for autoneg */ 175262306a36Sopenharmony_ci anadv_reg = rd32(E1000_PCS_ANADV); 175362306a36Sopenharmony_ci anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); 175462306a36Sopenharmony_ci switch (hw->fc.requested_mode) { 175562306a36Sopenharmony_ci case e1000_fc_full: 175662306a36Sopenharmony_ci case e1000_fc_rx_pause: 175762306a36Sopenharmony_ci anadv_reg |= E1000_TXCW_ASM_DIR; 175862306a36Sopenharmony_ci anadv_reg |= E1000_TXCW_PAUSE; 175962306a36Sopenharmony_ci break; 176062306a36Sopenharmony_ci case e1000_fc_tx_pause: 176162306a36Sopenharmony_ci anadv_reg |= E1000_TXCW_ASM_DIR; 176262306a36Sopenharmony_ci break; 176362306a36Sopenharmony_ci default: 176462306a36Sopenharmony_ci break; 176562306a36Sopenharmony_ci } 176662306a36Sopenharmony_ci wr32(E1000_PCS_ANADV, anadv_reg); 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci hw_dbg("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); 176962306a36Sopenharmony_ci } else { 177062306a36Sopenharmony_ci /* Set PCS register for forced link */ 177162306a36Sopenharmony_ci reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci /* Force flow control for forced link */ 177462306a36Sopenharmony_ci reg |= E1000_PCS_LCTL_FORCE_FCTRL; 177562306a36Sopenharmony_ci 177662306a36Sopenharmony_ci hw_dbg("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); 177762306a36Sopenharmony_ci } 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci wr32(E1000_PCS_LCTL, reg); 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci if (!pcs_autoneg && !igb_sgmii_active_82575(hw)) 178262306a36Sopenharmony_ci igb_force_mac_fc(hw); 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci return ret_val; 178562306a36Sopenharmony_ci} 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci/** 178862306a36Sopenharmony_ci * igb_sgmii_active_82575 - Return sgmii state 178962306a36Sopenharmony_ci * @hw: pointer to the HW structure 179062306a36Sopenharmony_ci * 179162306a36Sopenharmony_ci * 82575 silicon has a serialized gigabit media independent interface (sgmii) 179262306a36Sopenharmony_ci * which can be enabled for use in the embedded applications. Simply 179362306a36Sopenharmony_ci * return the current state of the sgmii interface. 179462306a36Sopenharmony_ci **/ 179562306a36Sopenharmony_cistatic bool igb_sgmii_active_82575(struct e1000_hw *hw) 179662306a36Sopenharmony_ci{ 179762306a36Sopenharmony_ci struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 179862306a36Sopenharmony_ci return dev_spec->sgmii_active; 179962306a36Sopenharmony_ci} 180062306a36Sopenharmony_ci 180162306a36Sopenharmony_ci/** 180262306a36Sopenharmony_ci * igb_reset_init_script_82575 - Inits HW defaults after reset 180362306a36Sopenharmony_ci * @hw: pointer to the HW structure 180462306a36Sopenharmony_ci * 180562306a36Sopenharmony_ci * Inits recommended HW defaults after a reset when there is no EEPROM 180662306a36Sopenharmony_ci * detected. This is only for the 82575. 180762306a36Sopenharmony_ci **/ 180862306a36Sopenharmony_cistatic s32 igb_reset_init_script_82575(struct e1000_hw *hw) 180962306a36Sopenharmony_ci{ 181062306a36Sopenharmony_ci if (hw->mac.type == e1000_82575) { 181162306a36Sopenharmony_ci hw_dbg("Running reset init script for 82575\n"); 181262306a36Sopenharmony_ci /* SerDes configuration via SERDESCTRL */ 181362306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x00, 0x0C); 181462306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x01, 0x78); 181562306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x1B, 0x23); 181662306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x23, 0x15); 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci /* CCM configuration via CCMCTL register */ 181962306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_CCMCTL, 0x14, 0x00); 182062306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_CCMCTL, 0x10, 0x00); 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci /* PCIe lanes configuration */ 182362306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x00, 0xEC); 182462306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x61, 0xDF); 182562306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x34, 0x05); 182662306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x2F, 0x81); 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ci /* PCIe PLL Configuration */ 182962306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x02, 0x47); 183062306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x14, 0x00); 183162306a36Sopenharmony_ci igb_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x10, 0x00); 183262306a36Sopenharmony_ci } 183362306a36Sopenharmony_ci 183462306a36Sopenharmony_ci return 0; 183562306a36Sopenharmony_ci} 183662306a36Sopenharmony_ci 183762306a36Sopenharmony_ci/** 183862306a36Sopenharmony_ci * igb_read_mac_addr_82575 - Read device MAC address 183962306a36Sopenharmony_ci * @hw: pointer to the HW structure 184062306a36Sopenharmony_ci **/ 184162306a36Sopenharmony_cistatic s32 igb_read_mac_addr_82575(struct e1000_hw *hw) 184262306a36Sopenharmony_ci{ 184362306a36Sopenharmony_ci s32 ret_val = 0; 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci /* If there's an alternate MAC address place it in RAR0 184662306a36Sopenharmony_ci * so that it will override the Si installed default perm 184762306a36Sopenharmony_ci * address. 184862306a36Sopenharmony_ci */ 184962306a36Sopenharmony_ci ret_val = igb_check_alt_mac_addr(hw); 185062306a36Sopenharmony_ci if (ret_val) 185162306a36Sopenharmony_ci goto out; 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci ret_val = igb_read_mac_addr(hw); 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ciout: 185662306a36Sopenharmony_ci return ret_val; 185762306a36Sopenharmony_ci} 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci/** 186062306a36Sopenharmony_ci * igb_power_down_phy_copper_82575 - Remove link during PHY power down 186162306a36Sopenharmony_ci * @hw: pointer to the HW structure 186262306a36Sopenharmony_ci * 186362306a36Sopenharmony_ci * In the case of a PHY power down to save power, or to turn off link during a 186462306a36Sopenharmony_ci * driver unload, or wake on lan is not enabled, remove the link. 186562306a36Sopenharmony_ci **/ 186662306a36Sopenharmony_civoid igb_power_down_phy_copper_82575(struct e1000_hw *hw) 186762306a36Sopenharmony_ci{ 186862306a36Sopenharmony_ci /* If the management interface is not enabled, then power down */ 186962306a36Sopenharmony_ci if (!(igb_enable_mng_pass_thru(hw) || igb_check_reset_block(hw))) 187062306a36Sopenharmony_ci igb_power_down_phy_copper(hw); 187162306a36Sopenharmony_ci} 187262306a36Sopenharmony_ci 187362306a36Sopenharmony_ci/** 187462306a36Sopenharmony_ci * igb_clear_hw_cntrs_82575 - Clear device specific hardware counters 187562306a36Sopenharmony_ci * @hw: pointer to the HW structure 187662306a36Sopenharmony_ci * 187762306a36Sopenharmony_ci * Clears the hardware counters by reading the counter registers. 187862306a36Sopenharmony_ci **/ 187962306a36Sopenharmony_cistatic void igb_clear_hw_cntrs_82575(struct e1000_hw *hw) 188062306a36Sopenharmony_ci{ 188162306a36Sopenharmony_ci igb_clear_hw_cntrs_base(hw); 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_ci rd32(E1000_PRC64); 188462306a36Sopenharmony_ci rd32(E1000_PRC127); 188562306a36Sopenharmony_ci rd32(E1000_PRC255); 188662306a36Sopenharmony_ci rd32(E1000_PRC511); 188762306a36Sopenharmony_ci rd32(E1000_PRC1023); 188862306a36Sopenharmony_ci rd32(E1000_PRC1522); 188962306a36Sopenharmony_ci rd32(E1000_PTC64); 189062306a36Sopenharmony_ci rd32(E1000_PTC127); 189162306a36Sopenharmony_ci rd32(E1000_PTC255); 189262306a36Sopenharmony_ci rd32(E1000_PTC511); 189362306a36Sopenharmony_ci rd32(E1000_PTC1023); 189462306a36Sopenharmony_ci rd32(E1000_PTC1522); 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci rd32(E1000_ALGNERRC); 189762306a36Sopenharmony_ci rd32(E1000_RXERRC); 189862306a36Sopenharmony_ci rd32(E1000_TNCRS); 189962306a36Sopenharmony_ci rd32(E1000_CEXTERR); 190062306a36Sopenharmony_ci rd32(E1000_TSCTC); 190162306a36Sopenharmony_ci rd32(E1000_TSCTFC); 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci rd32(E1000_MGTPRC); 190462306a36Sopenharmony_ci rd32(E1000_MGTPDC); 190562306a36Sopenharmony_ci rd32(E1000_MGTPTC); 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci rd32(E1000_IAC); 190862306a36Sopenharmony_ci rd32(E1000_ICRXOC); 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci rd32(E1000_ICRXPTC); 191162306a36Sopenharmony_ci rd32(E1000_ICRXATC); 191262306a36Sopenharmony_ci rd32(E1000_ICTXPTC); 191362306a36Sopenharmony_ci rd32(E1000_ICTXATC); 191462306a36Sopenharmony_ci rd32(E1000_ICTXQEC); 191562306a36Sopenharmony_ci rd32(E1000_ICTXQMTC); 191662306a36Sopenharmony_ci rd32(E1000_ICRXDMTC); 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_ci rd32(E1000_CBTMPC); 191962306a36Sopenharmony_ci rd32(E1000_HTDPMC); 192062306a36Sopenharmony_ci rd32(E1000_CBRMPC); 192162306a36Sopenharmony_ci rd32(E1000_RPTHC); 192262306a36Sopenharmony_ci rd32(E1000_HGPTC); 192362306a36Sopenharmony_ci rd32(E1000_HTCBDPC); 192462306a36Sopenharmony_ci rd32(E1000_HGORCL); 192562306a36Sopenharmony_ci rd32(E1000_HGORCH); 192662306a36Sopenharmony_ci rd32(E1000_HGOTCL); 192762306a36Sopenharmony_ci rd32(E1000_HGOTCH); 192862306a36Sopenharmony_ci rd32(E1000_LENERRS); 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci /* This register should not be read in copper configurations */ 193162306a36Sopenharmony_ci if (hw->phy.media_type == e1000_media_type_internal_serdes || 193262306a36Sopenharmony_ci igb_sgmii_active_82575(hw)) 193362306a36Sopenharmony_ci rd32(E1000_SCVPC); 193462306a36Sopenharmony_ci} 193562306a36Sopenharmony_ci 193662306a36Sopenharmony_ci/** 193762306a36Sopenharmony_ci * igb_rx_fifo_flush_82575 - Clean rx fifo after RX enable 193862306a36Sopenharmony_ci * @hw: pointer to the HW structure 193962306a36Sopenharmony_ci * 194062306a36Sopenharmony_ci * After rx enable if manageability is enabled then there is likely some 194162306a36Sopenharmony_ci * bad data at the start of the fifo and possibly in the DMA fifo. This 194262306a36Sopenharmony_ci * function clears the fifos and flushes any packets that came in as rx was 194362306a36Sopenharmony_ci * being enabled. 194462306a36Sopenharmony_ci **/ 194562306a36Sopenharmony_civoid igb_rx_fifo_flush_82575(struct e1000_hw *hw) 194662306a36Sopenharmony_ci{ 194762306a36Sopenharmony_ci u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; 194862306a36Sopenharmony_ci int i, ms_wait; 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci /* disable IPv6 options as per hardware errata */ 195162306a36Sopenharmony_ci rfctl = rd32(E1000_RFCTL); 195262306a36Sopenharmony_ci rfctl |= E1000_RFCTL_IPV6_EX_DIS; 195362306a36Sopenharmony_ci wr32(E1000_RFCTL, rfctl); 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci if (hw->mac.type != e1000_82575 || 195662306a36Sopenharmony_ci !(rd32(E1000_MANC) & E1000_MANC_RCV_TCO_EN)) 195762306a36Sopenharmony_ci return; 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci /* Disable all RX queues */ 196062306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 196162306a36Sopenharmony_ci rxdctl[i] = rd32(E1000_RXDCTL(i)); 196262306a36Sopenharmony_ci wr32(E1000_RXDCTL(i), 196362306a36Sopenharmony_ci rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE); 196462306a36Sopenharmony_ci } 196562306a36Sopenharmony_ci /* Poll all queues to verify they have shut down */ 196662306a36Sopenharmony_ci for (ms_wait = 0; ms_wait < 10; ms_wait++) { 196762306a36Sopenharmony_ci usleep_range(1000, 2000); 196862306a36Sopenharmony_ci rx_enabled = 0; 196962306a36Sopenharmony_ci for (i = 0; i < 4; i++) 197062306a36Sopenharmony_ci rx_enabled |= rd32(E1000_RXDCTL(i)); 197162306a36Sopenharmony_ci if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE)) 197262306a36Sopenharmony_ci break; 197362306a36Sopenharmony_ci } 197462306a36Sopenharmony_ci 197562306a36Sopenharmony_ci if (ms_wait == 10) 197662306a36Sopenharmony_ci hw_dbg("Queue disable timed out after 10ms\n"); 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ci /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all 197962306a36Sopenharmony_ci * incoming packets are rejected. Set enable and wait 2ms so that 198062306a36Sopenharmony_ci * any packet that was coming in as RCTL.EN was set is flushed 198162306a36Sopenharmony_ci */ 198262306a36Sopenharmony_ci wr32(E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); 198362306a36Sopenharmony_ci 198462306a36Sopenharmony_ci rlpml = rd32(E1000_RLPML); 198562306a36Sopenharmony_ci wr32(E1000_RLPML, 0); 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci rctl = rd32(E1000_RCTL); 198862306a36Sopenharmony_ci temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); 198962306a36Sopenharmony_ci temp_rctl |= E1000_RCTL_LPE; 199062306a36Sopenharmony_ci 199162306a36Sopenharmony_ci wr32(E1000_RCTL, temp_rctl); 199262306a36Sopenharmony_ci wr32(E1000_RCTL, temp_rctl | E1000_RCTL_EN); 199362306a36Sopenharmony_ci wrfl(); 199462306a36Sopenharmony_ci usleep_range(2000, 3000); 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci /* Enable RX queues that were previously enabled and restore our 199762306a36Sopenharmony_ci * previous state 199862306a36Sopenharmony_ci */ 199962306a36Sopenharmony_ci for (i = 0; i < 4; i++) 200062306a36Sopenharmony_ci wr32(E1000_RXDCTL(i), rxdctl[i]); 200162306a36Sopenharmony_ci wr32(E1000_RCTL, rctl); 200262306a36Sopenharmony_ci wrfl(); 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci wr32(E1000_RLPML, rlpml); 200562306a36Sopenharmony_ci wr32(E1000_RFCTL, rfctl); 200662306a36Sopenharmony_ci 200762306a36Sopenharmony_ci /* Flush receive errors generated by workaround */ 200862306a36Sopenharmony_ci rd32(E1000_ROC); 200962306a36Sopenharmony_ci rd32(E1000_RNBC); 201062306a36Sopenharmony_ci rd32(E1000_MPC); 201162306a36Sopenharmony_ci} 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_ci/** 201462306a36Sopenharmony_ci * igb_set_pcie_completion_timeout - set pci-e completion timeout 201562306a36Sopenharmony_ci * @hw: pointer to the HW structure 201662306a36Sopenharmony_ci * 201762306a36Sopenharmony_ci * The defaults for 82575 and 82576 should be in the range of 50us to 50ms, 201862306a36Sopenharmony_ci * however the hardware default for these parts is 500us to 1ms which is less 201962306a36Sopenharmony_ci * than the 10ms recommended by the pci-e spec. To address this we need to 202062306a36Sopenharmony_ci * increase the value to either 10ms to 200ms for capability version 1 config, 202162306a36Sopenharmony_ci * or 16ms to 55ms for version 2. 202262306a36Sopenharmony_ci **/ 202362306a36Sopenharmony_cistatic s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw) 202462306a36Sopenharmony_ci{ 202562306a36Sopenharmony_ci u32 gcr = rd32(E1000_GCR); 202662306a36Sopenharmony_ci s32 ret_val = 0; 202762306a36Sopenharmony_ci u16 pcie_devctl2; 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_ci /* only take action if timeout value is defaulted to 0 */ 203062306a36Sopenharmony_ci if (gcr & E1000_GCR_CMPL_TMOUT_MASK) 203162306a36Sopenharmony_ci goto out; 203262306a36Sopenharmony_ci 203362306a36Sopenharmony_ci /* if capabilities version is type 1 we can write the 203462306a36Sopenharmony_ci * timeout of 10ms to 200ms through the GCR register 203562306a36Sopenharmony_ci */ 203662306a36Sopenharmony_ci if (!(gcr & E1000_GCR_CAP_VER2)) { 203762306a36Sopenharmony_ci gcr |= E1000_GCR_CMPL_TMOUT_10ms; 203862306a36Sopenharmony_ci goto out; 203962306a36Sopenharmony_ci } 204062306a36Sopenharmony_ci 204162306a36Sopenharmony_ci /* for version 2 capabilities we need to write the config space 204262306a36Sopenharmony_ci * directly in order to set the completion timeout value for 204362306a36Sopenharmony_ci * 16ms to 55ms 204462306a36Sopenharmony_ci */ 204562306a36Sopenharmony_ci ret_val = igb_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, 204662306a36Sopenharmony_ci &pcie_devctl2); 204762306a36Sopenharmony_ci if (ret_val) 204862306a36Sopenharmony_ci goto out; 204962306a36Sopenharmony_ci 205062306a36Sopenharmony_ci pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms; 205162306a36Sopenharmony_ci 205262306a36Sopenharmony_ci ret_val = igb_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, 205362306a36Sopenharmony_ci &pcie_devctl2); 205462306a36Sopenharmony_ciout: 205562306a36Sopenharmony_ci /* disable completion timeout resend */ 205662306a36Sopenharmony_ci gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND; 205762306a36Sopenharmony_ci 205862306a36Sopenharmony_ci wr32(E1000_GCR, gcr); 205962306a36Sopenharmony_ci return ret_val; 206062306a36Sopenharmony_ci} 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci/** 206362306a36Sopenharmony_ci * igb_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing 206462306a36Sopenharmony_ci * @hw: pointer to the hardware struct 206562306a36Sopenharmony_ci * @enable: state to enter, either enabled or disabled 206662306a36Sopenharmony_ci * @pf: Physical Function pool - do not set anti-spoofing for the PF 206762306a36Sopenharmony_ci * 206862306a36Sopenharmony_ci * enables/disables L2 switch anti-spoofing functionality. 206962306a36Sopenharmony_ci **/ 207062306a36Sopenharmony_civoid igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) 207162306a36Sopenharmony_ci{ 207262306a36Sopenharmony_ci u32 reg_val, reg_offset; 207362306a36Sopenharmony_ci 207462306a36Sopenharmony_ci switch (hw->mac.type) { 207562306a36Sopenharmony_ci case e1000_82576: 207662306a36Sopenharmony_ci reg_offset = E1000_DTXSWC; 207762306a36Sopenharmony_ci break; 207862306a36Sopenharmony_ci case e1000_i350: 207962306a36Sopenharmony_ci case e1000_i354: 208062306a36Sopenharmony_ci reg_offset = E1000_TXSWC; 208162306a36Sopenharmony_ci break; 208262306a36Sopenharmony_ci default: 208362306a36Sopenharmony_ci return; 208462306a36Sopenharmony_ci } 208562306a36Sopenharmony_ci 208662306a36Sopenharmony_ci reg_val = rd32(reg_offset); 208762306a36Sopenharmony_ci if (enable) { 208862306a36Sopenharmony_ci reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK | 208962306a36Sopenharmony_ci E1000_DTXSWC_VLAN_SPOOF_MASK); 209062306a36Sopenharmony_ci /* The PF can spoof - it has to in order to 209162306a36Sopenharmony_ci * support emulation mode NICs 209262306a36Sopenharmony_ci */ 209362306a36Sopenharmony_ci reg_val ^= (BIT(pf) | BIT(pf + MAX_NUM_VFS)); 209462306a36Sopenharmony_ci } else { 209562306a36Sopenharmony_ci reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | 209662306a36Sopenharmony_ci E1000_DTXSWC_VLAN_SPOOF_MASK); 209762306a36Sopenharmony_ci } 209862306a36Sopenharmony_ci wr32(reg_offset, reg_val); 209962306a36Sopenharmony_ci} 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci/** 210262306a36Sopenharmony_ci * igb_vmdq_set_loopback_pf - enable or disable vmdq loopback 210362306a36Sopenharmony_ci * @hw: pointer to the hardware struct 210462306a36Sopenharmony_ci * @enable: state to enter, either enabled or disabled 210562306a36Sopenharmony_ci * 210662306a36Sopenharmony_ci * enables/disables L2 switch loopback functionality. 210762306a36Sopenharmony_ci **/ 210862306a36Sopenharmony_civoid igb_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) 210962306a36Sopenharmony_ci{ 211062306a36Sopenharmony_ci u32 dtxswc; 211162306a36Sopenharmony_ci 211262306a36Sopenharmony_ci switch (hw->mac.type) { 211362306a36Sopenharmony_ci case e1000_82576: 211462306a36Sopenharmony_ci dtxswc = rd32(E1000_DTXSWC); 211562306a36Sopenharmony_ci if (enable) 211662306a36Sopenharmony_ci dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; 211762306a36Sopenharmony_ci else 211862306a36Sopenharmony_ci dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; 211962306a36Sopenharmony_ci wr32(E1000_DTXSWC, dtxswc); 212062306a36Sopenharmony_ci break; 212162306a36Sopenharmony_ci case e1000_i354: 212262306a36Sopenharmony_ci case e1000_i350: 212362306a36Sopenharmony_ci dtxswc = rd32(E1000_TXSWC); 212462306a36Sopenharmony_ci if (enable) 212562306a36Sopenharmony_ci dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; 212662306a36Sopenharmony_ci else 212762306a36Sopenharmony_ci dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; 212862306a36Sopenharmony_ci wr32(E1000_TXSWC, dtxswc); 212962306a36Sopenharmony_ci break; 213062306a36Sopenharmony_ci default: 213162306a36Sopenharmony_ci /* Currently no other hardware supports loopback */ 213262306a36Sopenharmony_ci break; 213362306a36Sopenharmony_ci } 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_ci} 213662306a36Sopenharmony_ci 213762306a36Sopenharmony_ci/** 213862306a36Sopenharmony_ci * igb_vmdq_set_replication_pf - enable or disable vmdq replication 213962306a36Sopenharmony_ci * @hw: pointer to the hardware struct 214062306a36Sopenharmony_ci * @enable: state to enter, either enabled or disabled 214162306a36Sopenharmony_ci * 214262306a36Sopenharmony_ci * enables/disables replication of packets across multiple pools. 214362306a36Sopenharmony_ci **/ 214462306a36Sopenharmony_civoid igb_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) 214562306a36Sopenharmony_ci{ 214662306a36Sopenharmony_ci u32 vt_ctl = rd32(E1000_VT_CTL); 214762306a36Sopenharmony_ci 214862306a36Sopenharmony_ci if (enable) 214962306a36Sopenharmony_ci vt_ctl |= E1000_VT_CTL_VM_REPL_EN; 215062306a36Sopenharmony_ci else 215162306a36Sopenharmony_ci vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN; 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci wr32(E1000_VT_CTL, vt_ctl); 215462306a36Sopenharmony_ci} 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_ci/** 215762306a36Sopenharmony_ci * igb_read_phy_reg_82580 - Read 82580 MDI control register 215862306a36Sopenharmony_ci * @hw: pointer to the HW structure 215962306a36Sopenharmony_ci * @offset: register offset to be read 216062306a36Sopenharmony_ci * @data: pointer to the read data 216162306a36Sopenharmony_ci * 216262306a36Sopenharmony_ci * Reads the MDI control register in the PHY at offset and stores the 216362306a36Sopenharmony_ci * information read to data. 216462306a36Sopenharmony_ci **/ 216562306a36Sopenharmony_cis32 igb_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data) 216662306a36Sopenharmony_ci{ 216762306a36Sopenharmony_ci s32 ret_val; 216862306a36Sopenharmony_ci 216962306a36Sopenharmony_ci ret_val = hw->phy.ops.acquire(hw); 217062306a36Sopenharmony_ci if (ret_val) 217162306a36Sopenharmony_ci goto out; 217262306a36Sopenharmony_ci 217362306a36Sopenharmony_ci ret_val = igb_read_phy_reg_mdic(hw, offset, data); 217462306a36Sopenharmony_ci 217562306a36Sopenharmony_ci hw->phy.ops.release(hw); 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_ciout: 217862306a36Sopenharmony_ci return ret_val; 217962306a36Sopenharmony_ci} 218062306a36Sopenharmony_ci 218162306a36Sopenharmony_ci/** 218262306a36Sopenharmony_ci * igb_write_phy_reg_82580 - Write 82580 MDI control register 218362306a36Sopenharmony_ci * @hw: pointer to the HW structure 218462306a36Sopenharmony_ci * @offset: register offset to write to 218562306a36Sopenharmony_ci * @data: data to write to register at offset 218662306a36Sopenharmony_ci * 218762306a36Sopenharmony_ci * Writes data to MDI control register in the PHY at offset. 218862306a36Sopenharmony_ci **/ 218962306a36Sopenharmony_cis32 igb_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data) 219062306a36Sopenharmony_ci{ 219162306a36Sopenharmony_ci s32 ret_val; 219262306a36Sopenharmony_ci 219362306a36Sopenharmony_ci 219462306a36Sopenharmony_ci ret_val = hw->phy.ops.acquire(hw); 219562306a36Sopenharmony_ci if (ret_val) 219662306a36Sopenharmony_ci goto out; 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci ret_val = igb_write_phy_reg_mdic(hw, offset, data); 219962306a36Sopenharmony_ci 220062306a36Sopenharmony_ci hw->phy.ops.release(hw); 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ciout: 220362306a36Sopenharmony_ci return ret_val; 220462306a36Sopenharmony_ci} 220562306a36Sopenharmony_ci 220662306a36Sopenharmony_ci/** 220762306a36Sopenharmony_ci * igb_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits 220862306a36Sopenharmony_ci * @hw: pointer to the HW structure 220962306a36Sopenharmony_ci * 221062306a36Sopenharmony_ci * This resets the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on 221162306a36Sopenharmony_ci * the values found in the EEPROM. This addresses an issue in which these 221262306a36Sopenharmony_ci * bits are not restored from EEPROM after reset. 221362306a36Sopenharmony_ci **/ 221462306a36Sopenharmony_cistatic s32 igb_reset_mdicnfg_82580(struct e1000_hw *hw) 221562306a36Sopenharmony_ci{ 221662306a36Sopenharmony_ci s32 ret_val = 0; 221762306a36Sopenharmony_ci u32 mdicnfg; 221862306a36Sopenharmony_ci u16 nvm_data = 0; 221962306a36Sopenharmony_ci 222062306a36Sopenharmony_ci if (hw->mac.type != e1000_82580) 222162306a36Sopenharmony_ci goto out; 222262306a36Sopenharmony_ci if (!igb_sgmii_active_82575(hw)) 222362306a36Sopenharmony_ci goto out; 222462306a36Sopenharmony_ci 222562306a36Sopenharmony_ci ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + 222662306a36Sopenharmony_ci NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, 222762306a36Sopenharmony_ci &nvm_data); 222862306a36Sopenharmony_ci if (ret_val) { 222962306a36Sopenharmony_ci hw_dbg("NVM Read Error\n"); 223062306a36Sopenharmony_ci goto out; 223162306a36Sopenharmony_ci } 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci mdicnfg = rd32(E1000_MDICNFG); 223462306a36Sopenharmony_ci if (nvm_data & NVM_WORD24_EXT_MDIO) 223562306a36Sopenharmony_ci mdicnfg |= E1000_MDICNFG_EXT_MDIO; 223662306a36Sopenharmony_ci if (nvm_data & NVM_WORD24_COM_MDIO) 223762306a36Sopenharmony_ci mdicnfg |= E1000_MDICNFG_COM_MDIO; 223862306a36Sopenharmony_ci wr32(E1000_MDICNFG, mdicnfg); 223962306a36Sopenharmony_ciout: 224062306a36Sopenharmony_ci return ret_val; 224162306a36Sopenharmony_ci} 224262306a36Sopenharmony_ci 224362306a36Sopenharmony_ci/** 224462306a36Sopenharmony_ci * igb_reset_hw_82580 - Reset hardware 224562306a36Sopenharmony_ci * @hw: pointer to the HW structure 224662306a36Sopenharmony_ci * 224762306a36Sopenharmony_ci * This resets function or entire device (all ports, etc.) 224862306a36Sopenharmony_ci * to a known state. 224962306a36Sopenharmony_ci **/ 225062306a36Sopenharmony_cistatic s32 igb_reset_hw_82580(struct e1000_hw *hw) 225162306a36Sopenharmony_ci{ 225262306a36Sopenharmony_ci s32 ret_val = 0; 225362306a36Sopenharmony_ci /* BH SW mailbox bit in SW_FW_SYNC */ 225462306a36Sopenharmony_ci u16 swmbsw_mask = E1000_SW_SYNCH_MB; 225562306a36Sopenharmony_ci u32 ctrl; 225662306a36Sopenharmony_ci bool global_device_reset = hw->dev_spec._82575.global_device_reset; 225762306a36Sopenharmony_ci 225862306a36Sopenharmony_ci hw->dev_spec._82575.global_device_reset = false; 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci /* due to hw errata, global device reset doesn't always 226162306a36Sopenharmony_ci * work on 82580 226262306a36Sopenharmony_ci */ 226362306a36Sopenharmony_ci if (hw->mac.type == e1000_82580) 226462306a36Sopenharmony_ci global_device_reset = false; 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_ci /* Get current control state. */ 226762306a36Sopenharmony_ci ctrl = rd32(E1000_CTRL); 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_ci /* Prevent the PCI-E bus from sticking if there is no TLP connection 227062306a36Sopenharmony_ci * on the last TLP read/write transaction when MAC is reset. 227162306a36Sopenharmony_ci */ 227262306a36Sopenharmony_ci ret_val = igb_disable_pcie_master(hw); 227362306a36Sopenharmony_ci if (ret_val) 227462306a36Sopenharmony_ci hw_dbg("PCI-E Master disable polling has failed.\n"); 227562306a36Sopenharmony_ci 227662306a36Sopenharmony_ci hw_dbg("Masking off all interrupts\n"); 227762306a36Sopenharmony_ci wr32(E1000_IMC, 0xffffffff); 227862306a36Sopenharmony_ci wr32(E1000_RCTL, 0); 227962306a36Sopenharmony_ci wr32(E1000_TCTL, E1000_TCTL_PSP); 228062306a36Sopenharmony_ci wrfl(); 228162306a36Sopenharmony_ci 228262306a36Sopenharmony_ci usleep_range(10000, 11000); 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_ci /* Determine whether or not a global dev reset is requested */ 228562306a36Sopenharmony_ci if (global_device_reset && 228662306a36Sopenharmony_ci hw->mac.ops.acquire_swfw_sync(hw, swmbsw_mask)) 228762306a36Sopenharmony_ci global_device_reset = false; 228862306a36Sopenharmony_ci 228962306a36Sopenharmony_ci if (global_device_reset && 229062306a36Sopenharmony_ci !(rd32(E1000_STATUS) & E1000_STAT_DEV_RST_SET)) 229162306a36Sopenharmony_ci ctrl |= E1000_CTRL_DEV_RST; 229262306a36Sopenharmony_ci else 229362306a36Sopenharmony_ci ctrl |= E1000_CTRL_RST; 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_ci wr32(E1000_CTRL, ctrl); 229662306a36Sopenharmony_ci wrfl(); 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_ci /* Add delay to insure DEV_RST has time to complete */ 229962306a36Sopenharmony_ci if (global_device_reset) 230062306a36Sopenharmony_ci usleep_range(5000, 6000); 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_ci ret_val = igb_get_auto_rd_done(hw); 230362306a36Sopenharmony_ci if (ret_val) { 230462306a36Sopenharmony_ci /* When auto config read does not complete, do not 230562306a36Sopenharmony_ci * return with an error. This can happen in situations 230662306a36Sopenharmony_ci * where there is no eeprom and prevents getting link. 230762306a36Sopenharmony_ci */ 230862306a36Sopenharmony_ci hw_dbg("Auto Read Done did not complete\n"); 230962306a36Sopenharmony_ci } 231062306a36Sopenharmony_ci 231162306a36Sopenharmony_ci /* clear global device reset status bit */ 231262306a36Sopenharmony_ci wr32(E1000_STATUS, E1000_STAT_DEV_RST_SET); 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_ci /* Clear any pending interrupt events. */ 231562306a36Sopenharmony_ci wr32(E1000_IMC, 0xffffffff); 231662306a36Sopenharmony_ci rd32(E1000_ICR); 231762306a36Sopenharmony_ci 231862306a36Sopenharmony_ci ret_val = igb_reset_mdicnfg_82580(hw); 231962306a36Sopenharmony_ci if (ret_val) 232062306a36Sopenharmony_ci hw_dbg("Could not reset MDICNFG based on EEPROM\n"); 232162306a36Sopenharmony_ci 232262306a36Sopenharmony_ci /* Install any alternate MAC address into RAR0 */ 232362306a36Sopenharmony_ci ret_val = igb_check_alt_mac_addr(hw); 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_ci /* Release semaphore */ 232662306a36Sopenharmony_ci if (global_device_reset) 232762306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swmbsw_mask); 232862306a36Sopenharmony_ci 232962306a36Sopenharmony_ci return ret_val; 233062306a36Sopenharmony_ci} 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci/** 233362306a36Sopenharmony_ci * igb_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual RX PBA size 233462306a36Sopenharmony_ci * @data: data received by reading RXPBS register 233562306a36Sopenharmony_ci * 233662306a36Sopenharmony_ci * The 82580 uses a table based approach for packet buffer allocation sizes. 233762306a36Sopenharmony_ci * This function converts the retrieved value into the correct table value 233862306a36Sopenharmony_ci * 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 233962306a36Sopenharmony_ci * 0x0 36 72 144 1 2 4 8 16 234062306a36Sopenharmony_ci * 0x8 35 70 140 rsv rsv rsv rsv rsv 234162306a36Sopenharmony_ci */ 234262306a36Sopenharmony_ciu16 igb_rxpbs_adjust_82580(u32 data) 234362306a36Sopenharmony_ci{ 234462306a36Sopenharmony_ci u16 ret_val = 0; 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_ci if (data < ARRAY_SIZE(e1000_82580_rxpbs_table)) 234762306a36Sopenharmony_ci ret_val = e1000_82580_rxpbs_table[data]; 234862306a36Sopenharmony_ci 234962306a36Sopenharmony_ci return ret_val; 235062306a36Sopenharmony_ci} 235162306a36Sopenharmony_ci 235262306a36Sopenharmony_ci/** 235362306a36Sopenharmony_ci * igb_validate_nvm_checksum_with_offset - Validate EEPROM 235462306a36Sopenharmony_ci * checksum 235562306a36Sopenharmony_ci * @hw: pointer to the HW structure 235662306a36Sopenharmony_ci * @offset: offset in words of the checksum protected region 235762306a36Sopenharmony_ci * 235862306a36Sopenharmony_ci * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 235962306a36Sopenharmony_ci * and then verifies that the sum of the EEPROM is equal to 0xBABA. 236062306a36Sopenharmony_ci **/ 236162306a36Sopenharmony_cistatic s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw, 236262306a36Sopenharmony_ci u16 offset) 236362306a36Sopenharmony_ci{ 236462306a36Sopenharmony_ci s32 ret_val = 0; 236562306a36Sopenharmony_ci u16 checksum = 0; 236662306a36Sopenharmony_ci u16 i, nvm_data; 236762306a36Sopenharmony_ci 236862306a36Sopenharmony_ci for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) { 236962306a36Sopenharmony_ci ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 237062306a36Sopenharmony_ci if (ret_val) { 237162306a36Sopenharmony_ci hw_dbg("NVM Read Error\n"); 237262306a36Sopenharmony_ci goto out; 237362306a36Sopenharmony_ci } 237462306a36Sopenharmony_ci checksum += nvm_data; 237562306a36Sopenharmony_ci } 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci if (checksum != (u16) NVM_SUM) { 237862306a36Sopenharmony_ci hw_dbg("NVM Checksum Invalid\n"); 237962306a36Sopenharmony_ci ret_val = -E1000_ERR_NVM; 238062306a36Sopenharmony_ci goto out; 238162306a36Sopenharmony_ci } 238262306a36Sopenharmony_ci 238362306a36Sopenharmony_ciout: 238462306a36Sopenharmony_ci return ret_val; 238562306a36Sopenharmony_ci} 238662306a36Sopenharmony_ci 238762306a36Sopenharmony_ci/** 238862306a36Sopenharmony_ci * igb_update_nvm_checksum_with_offset - Update EEPROM 238962306a36Sopenharmony_ci * checksum 239062306a36Sopenharmony_ci * @hw: pointer to the HW structure 239162306a36Sopenharmony_ci * @offset: offset in words of the checksum protected region 239262306a36Sopenharmony_ci * 239362306a36Sopenharmony_ci * Updates the EEPROM checksum by reading/adding each word of the EEPROM 239462306a36Sopenharmony_ci * up to the checksum. Then calculates the EEPROM checksum and writes the 239562306a36Sopenharmony_ci * value to the EEPROM. 239662306a36Sopenharmony_ci **/ 239762306a36Sopenharmony_cistatic s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) 239862306a36Sopenharmony_ci{ 239962306a36Sopenharmony_ci s32 ret_val; 240062306a36Sopenharmony_ci u16 checksum = 0; 240162306a36Sopenharmony_ci u16 i, nvm_data; 240262306a36Sopenharmony_ci 240362306a36Sopenharmony_ci for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) { 240462306a36Sopenharmony_ci ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 240562306a36Sopenharmony_ci if (ret_val) { 240662306a36Sopenharmony_ci hw_dbg("NVM Read Error while updating checksum.\n"); 240762306a36Sopenharmony_ci goto out; 240862306a36Sopenharmony_ci } 240962306a36Sopenharmony_ci checksum += nvm_data; 241062306a36Sopenharmony_ci } 241162306a36Sopenharmony_ci checksum = (u16) NVM_SUM - checksum; 241262306a36Sopenharmony_ci ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1, 241362306a36Sopenharmony_ci &checksum); 241462306a36Sopenharmony_ci if (ret_val) 241562306a36Sopenharmony_ci hw_dbg("NVM Write Error while updating checksum.\n"); 241662306a36Sopenharmony_ci 241762306a36Sopenharmony_ciout: 241862306a36Sopenharmony_ci return ret_val; 241962306a36Sopenharmony_ci} 242062306a36Sopenharmony_ci 242162306a36Sopenharmony_ci/** 242262306a36Sopenharmony_ci * igb_validate_nvm_checksum_82580 - Validate EEPROM checksum 242362306a36Sopenharmony_ci * @hw: pointer to the HW structure 242462306a36Sopenharmony_ci * 242562306a36Sopenharmony_ci * Calculates the EEPROM section checksum by reading/adding each word of 242662306a36Sopenharmony_ci * the EEPROM and then verifies that the sum of the EEPROM is 242762306a36Sopenharmony_ci * equal to 0xBABA. 242862306a36Sopenharmony_ci **/ 242962306a36Sopenharmony_cistatic s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw) 243062306a36Sopenharmony_ci{ 243162306a36Sopenharmony_ci s32 ret_val = 0; 243262306a36Sopenharmony_ci u16 eeprom_regions_count = 1; 243362306a36Sopenharmony_ci u16 j, nvm_data; 243462306a36Sopenharmony_ci u16 nvm_offset; 243562306a36Sopenharmony_ci 243662306a36Sopenharmony_ci ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); 243762306a36Sopenharmony_ci if (ret_val) { 243862306a36Sopenharmony_ci hw_dbg("NVM Read Error\n"); 243962306a36Sopenharmony_ci goto out; 244062306a36Sopenharmony_ci } 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) { 244362306a36Sopenharmony_ci /* if checksums compatibility bit is set validate checksums 244462306a36Sopenharmony_ci * for all 4 ports. 244562306a36Sopenharmony_ci */ 244662306a36Sopenharmony_ci eeprom_regions_count = 4; 244762306a36Sopenharmony_ci } 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci for (j = 0; j < eeprom_regions_count; j++) { 245062306a36Sopenharmony_ci nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 245162306a36Sopenharmony_ci ret_val = igb_validate_nvm_checksum_with_offset(hw, 245262306a36Sopenharmony_ci nvm_offset); 245362306a36Sopenharmony_ci if (ret_val != 0) 245462306a36Sopenharmony_ci goto out; 245562306a36Sopenharmony_ci } 245662306a36Sopenharmony_ci 245762306a36Sopenharmony_ciout: 245862306a36Sopenharmony_ci return ret_val; 245962306a36Sopenharmony_ci} 246062306a36Sopenharmony_ci 246162306a36Sopenharmony_ci/** 246262306a36Sopenharmony_ci * igb_update_nvm_checksum_82580 - Update EEPROM checksum 246362306a36Sopenharmony_ci * @hw: pointer to the HW structure 246462306a36Sopenharmony_ci * 246562306a36Sopenharmony_ci * Updates the EEPROM section checksums for all 4 ports by reading/adding 246662306a36Sopenharmony_ci * each word of the EEPROM up to the checksum. Then calculates the EEPROM 246762306a36Sopenharmony_ci * checksum and writes the value to the EEPROM. 246862306a36Sopenharmony_ci **/ 246962306a36Sopenharmony_cistatic s32 igb_update_nvm_checksum_82580(struct e1000_hw *hw) 247062306a36Sopenharmony_ci{ 247162306a36Sopenharmony_ci s32 ret_val; 247262306a36Sopenharmony_ci u16 j, nvm_data; 247362306a36Sopenharmony_ci u16 nvm_offset; 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_ci ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); 247662306a36Sopenharmony_ci if (ret_val) { 247762306a36Sopenharmony_ci hw_dbg("NVM Read Error while updating checksum compatibility bit.\n"); 247862306a36Sopenharmony_ci goto out; 247962306a36Sopenharmony_ci } 248062306a36Sopenharmony_ci 248162306a36Sopenharmony_ci if ((nvm_data & NVM_COMPATIBILITY_BIT_MASK) == 0) { 248262306a36Sopenharmony_ci /* set compatibility bit to validate checksums appropriately */ 248362306a36Sopenharmony_ci nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK; 248462306a36Sopenharmony_ci ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1, 248562306a36Sopenharmony_ci &nvm_data); 248662306a36Sopenharmony_ci if (ret_val) { 248762306a36Sopenharmony_ci hw_dbg("NVM Write Error while updating checksum compatibility bit.\n"); 248862306a36Sopenharmony_ci goto out; 248962306a36Sopenharmony_ci } 249062306a36Sopenharmony_ci } 249162306a36Sopenharmony_ci 249262306a36Sopenharmony_ci for (j = 0; j < 4; j++) { 249362306a36Sopenharmony_ci nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 249462306a36Sopenharmony_ci ret_val = igb_update_nvm_checksum_with_offset(hw, nvm_offset); 249562306a36Sopenharmony_ci if (ret_val) 249662306a36Sopenharmony_ci goto out; 249762306a36Sopenharmony_ci } 249862306a36Sopenharmony_ci 249962306a36Sopenharmony_ciout: 250062306a36Sopenharmony_ci return ret_val; 250162306a36Sopenharmony_ci} 250262306a36Sopenharmony_ci 250362306a36Sopenharmony_ci/** 250462306a36Sopenharmony_ci * igb_validate_nvm_checksum_i350 - Validate EEPROM checksum 250562306a36Sopenharmony_ci * @hw: pointer to the HW structure 250662306a36Sopenharmony_ci * 250762306a36Sopenharmony_ci * Calculates the EEPROM section checksum by reading/adding each word of 250862306a36Sopenharmony_ci * the EEPROM and then verifies that the sum of the EEPROM is 250962306a36Sopenharmony_ci * equal to 0xBABA. 251062306a36Sopenharmony_ci **/ 251162306a36Sopenharmony_cistatic s32 igb_validate_nvm_checksum_i350(struct e1000_hw *hw) 251262306a36Sopenharmony_ci{ 251362306a36Sopenharmony_ci s32 ret_val = 0; 251462306a36Sopenharmony_ci u16 j; 251562306a36Sopenharmony_ci u16 nvm_offset; 251662306a36Sopenharmony_ci 251762306a36Sopenharmony_ci for (j = 0; j < 4; j++) { 251862306a36Sopenharmony_ci nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 251962306a36Sopenharmony_ci ret_val = igb_validate_nvm_checksum_with_offset(hw, 252062306a36Sopenharmony_ci nvm_offset); 252162306a36Sopenharmony_ci if (ret_val != 0) 252262306a36Sopenharmony_ci goto out; 252362306a36Sopenharmony_ci } 252462306a36Sopenharmony_ci 252562306a36Sopenharmony_ciout: 252662306a36Sopenharmony_ci return ret_val; 252762306a36Sopenharmony_ci} 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_ci/** 253062306a36Sopenharmony_ci * igb_update_nvm_checksum_i350 - Update EEPROM checksum 253162306a36Sopenharmony_ci * @hw: pointer to the HW structure 253262306a36Sopenharmony_ci * 253362306a36Sopenharmony_ci * Updates the EEPROM section checksums for all 4 ports by reading/adding 253462306a36Sopenharmony_ci * each word of the EEPROM up to the checksum. Then calculates the EEPROM 253562306a36Sopenharmony_ci * checksum and writes the value to the EEPROM. 253662306a36Sopenharmony_ci **/ 253762306a36Sopenharmony_cistatic s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw) 253862306a36Sopenharmony_ci{ 253962306a36Sopenharmony_ci s32 ret_val = 0; 254062306a36Sopenharmony_ci u16 j; 254162306a36Sopenharmony_ci u16 nvm_offset; 254262306a36Sopenharmony_ci 254362306a36Sopenharmony_ci for (j = 0; j < 4; j++) { 254462306a36Sopenharmony_ci nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 254562306a36Sopenharmony_ci ret_val = igb_update_nvm_checksum_with_offset(hw, nvm_offset); 254662306a36Sopenharmony_ci if (ret_val != 0) 254762306a36Sopenharmony_ci goto out; 254862306a36Sopenharmony_ci } 254962306a36Sopenharmony_ci 255062306a36Sopenharmony_ciout: 255162306a36Sopenharmony_ci return ret_val; 255262306a36Sopenharmony_ci} 255362306a36Sopenharmony_ci 255462306a36Sopenharmony_ci/** 255562306a36Sopenharmony_ci * __igb_access_emi_reg - Read/write EMI register 255662306a36Sopenharmony_ci * @hw: pointer to the HW structure 255762306a36Sopenharmony_ci * @address: EMI address to program 255862306a36Sopenharmony_ci * @data: pointer to value to read/write from/to the EMI address 255962306a36Sopenharmony_ci * @read: boolean flag to indicate read or write 256062306a36Sopenharmony_ci **/ 256162306a36Sopenharmony_cistatic s32 __igb_access_emi_reg(struct e1000_hw *hw, u16 address, 256262306a36Sopenharmony_ci u16 *data, bool read) 256362306a36Sopenharmony_ci{ 256462306a36Sopenharmony_ci s32 ret_val = 0; 256562306a36Sopenharmony_ci 256662306a36Sopenharmony_ci ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address); 256762306a36Sopenharmony_ci if (ret_val) 256862306a36Sopenharmony_ci return ret_val; 256962306a36Sopenharmony_ci 257062306a36Sopenharmony_ci if (read) 257162306a36Sopenharmony_ci ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data); 257262306a36Sopenharmony_ci else 257362306a36Sopenharmony_ci ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data); 257462306a36Sopenharmony_ci 257562306a36Sopenharmony_ci return ret_val; 257662306a36Sopenharmony_ci} 257762306a36Sopenharmony_ci 257862306a36Sopenharmony_ci/** 257962306a36Sopenharmony_ci * igb_read_emi_reg - Read Extended Management Interface register 258062306a36Sopenharmony_ci * @hw: pointer to the HW structure 258162306a36Sopenharmony_ci * @addr: EMI address to program 258262306a36Sopenharmony_ci * @data: value to be read from the EMI address 258362306a36Sopenharmony_ci **/ 258462306a36Sopenharmony_cis32 igb_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data) 258562306a36Sopenharmony_ci{ 258662306a36Sopenharmony_ci return __igb_access_emi_reg(hw, addr, data, true); 258762306a36Sopenharmony_ci} 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_ci/** 259062306a36Sopenharmony_ci * igb_set_eee_i350 - Enable/disable EEE support 259162306a36Sopenharmony_ci * @hw: pointer to the HW structure 259262306a36Sopenharmony_ci * @adv1G: boolean flag enabling 1G EEE advertisement 259362306a36Sopenharmony_ci * @adv100M: boolean flag enabling 100M EEE advertisement 259462306a36Sopenharmony_ci * 259562306a36Sopenharmony_ci * Enable/disable EEE based on setting in dev_spec structure. 259662306a36Sopenharmony_ci * 259762306a36Sopenharmony_ci **/ 259862306a36Sopenharmony_cis32 igb_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M) 259962306a36Sopenharmony_ci{ 260062306a36Sopenharmony_ci u32 ipcnfg, eeer; 260162306a36Sopenharmony_ci 260262306a36Sopenharmony_ci if ((hw->mac.type < e1000_i350) || 260362306a36Sopenharmony_ci (hw->phy.media_type != e1000_media_type_copper)) 260462306a36Sopenharmony_ci goto out; 260562306a36Sopenharmony_ci ipcnfg = rd32(E1000_IPCNFG); 260662306a36Sopenharmony_ci eeer = rd32(E1000_EEER); 260762306a36Sopenharmony_ci 260862306a36Sopenharmony_ci /* enable or disable per user setting */ 260962306a36Sopenharmony_ci if (!(hw->dev_spec._82575.eee_disable)) { 261062306a36Sopenharmony_ci u32 eee_su = rd32(E1000_EEE_SU); 261162306a36Sopenharmony_ci 261262306a36Sopenharmony_ci if (adv100M) 261362306a36Sopenharmony_ci ipcnfg |= E1000_IPCNFG_EEE_100M_AN; 261462306a36Sopenharmony_ci else 261562306a36Sopenharmony_ci ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN; 261662306a36Sopenharmony_ci 261762306a36Sopenharmony_ci if (adv1G) 261862306a36Sopenharmony_ci ipcnfg |= E1000_IPCNFG_EEE_1G_AN; 261962306a36Sopenharmony_ci else 262062306a36Sopenharmony_ci ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN; 262162306a36Sopenharmony_ci 262262306a36Sopenharmony_ci eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | 262362306a36Sopenharmony_ci E1000_EEER_LPI_FC); 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_ci /* This bit should not be set in normal operation. */ 262662306a36Sopenharmony_ci if (eee_su & E1000_EEE_SU_LPI_CLK_STP) 262762306a36Sopenharmony_ci hw_dbg("LPI Clock Stop Bit should not be set!\n"); 262862306a36Sopenharmony_ci 262962306a36Sopenharmony_ci } else { 263062306a36Sopenharmony_ci ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | 263162306a36Sopenharmony_ci E1000_IPCNFG_EEE_100M_AN); 263262306a36Sopenharmony_ci eeer &= ~(E1000_EEER_TX_LPI_EN | 263362306a36Sopenharmony_ci E1000_EEER_RX_LPI_EN | 263462306a36Sopenharmony_ci E1000_EEER_LPI_FC); 263562306a36Sopenharmony_ci } 263662306a36Sopenharmony_ci wr32(E1000_IPCNFG, ipcnfg); 263762306a36Sopenharmony_ci wr32(E1000_EEER, eeer); 263862306a36Sopenharmony_ci rd32(E1000_IPCNFG); 263962306a36Sopenharmony_ci rd32(E1000_EEER); 264062306a36Sopenharmony_ciout: 264162306a36Sopenharmony_ci 264262306a36Sopenharmony_ci return 0; 264362306a36Sopenharmony_ci} 264462306a36Sopenharmony_ci 264562306a36Sopenharmony_ci/** 264662306a36Sopenharmony_ci * igb_set_eee_i354 - Enable/disable EEE support 264762306a36Sopenharmony_ci * @hw: pointer to the HW structure 264862306a36Sopenharmony_ci * @adv1G: boolean flag enabling 1G EEE advertisement 264962306a36Sopenharmony_ci * @adv100M: boolean flag enabling 100M EEE advertisement 265062306a36Sopenharmony_ci * 265162306a36Sopenharmony_ci * Enable/disable EEE legacy mode based on setting in dev_spec structure. 265262306a36Sopenharmony_ci * 265362306a36Sopenharmony_ci **/ 265462306a36Sopenharmony_cis32 igb_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M) 265562306a36Sopenharmony_ci{ 265662306a36Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 265762306a36Sopenharmony_ci s32 ret_val = 0; 265862306a36Sopenharmony_ci u16 phy_data; 265962306a36Sopenharmony_ci 266062306a36Sopenharmony_ci if ((hw->phy.media_type != e1000_media_type_copper) || 266162306a36Sopenharmony_ci ((phy->id != M88E1543_E_PHY_ID) && 266262306a36Sopenharmony_ci (phy->id != M88E1512_E_PHY_ID))) 266362306a36Sopenharmony_ci goto out; 266462306a36Sopenharmony_ci 266562306a36Sopenharmony_ci if (!hw->dev_spec._82575.eee_disable) { 266662306a36Sopenharmony_ci /* Switch to PHY page 18. */ 266762306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18); 266862306a36Sopenharmony_ci if (ret_val) 266962306a36Sopenharmony_ci goto out; 267062306a36Sopenharmony_ci 267162306a36Sopenharmony_ci ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1, 267262306a36Sopenharmony_ci &phy_data); 267362306a36Sopenharmony_ci if (ret_val) 267462306a36Sopenharmony_ci goto out; 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci phy_data |= E1000_M88E1543_EEE_CTRL_1_MS; 267762306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1, 267862306a36Sopenharmony_ci phy_data); 267962306a36Sopenharmony_ci if (ret_val) 268062306a36Sopenharmony_ci goto out; 268162306a36Sopenharmony_ci 268262306a36Sopenharmony_ci /* Return the PHY to page 0. */ 268362306a36Sopenharmony_ci ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); 268462306a36Sopenharmony_ci if (ret_val) 268562306a36Sopenharmony_ci goto out; 268662306a36Sopenharmony_ci 268762306a36Sopenharmony_ci /* Turn on EEE advertisement. */ 268862306a36Sopenharmony_ci ret_val = igb_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 268962306a36Sopenharmony_ci E1000_EEE_ADV_DEV_I354, 269062306a36Sopenharmony_ci &phy_data); 269162306a36Sopenharmony_ci if (ret_val) 269262306a36Sopenharmony_ci goto out; 269362306a36Sopenharmony_ci 269462306a36Sopenharmony_ci if (adv100M) 269562306a36Sopenharmony_ci phy_data |= E1000_EEE_ADV_100_SUPPORTED; 269662306a36Sopenharmony_ci else 269762306a36Sopenharmony_ci phy_data &= ~E1000_EEE_ADV_100_SUPPORTED; 269862306a36Sopenharmony_ci 269962306a36Sopenharmony_ci if (adv1G) 270062306a36Sopenharmony_ci phy_data |= E1000_EEE_ADV_1000_SUPPORTED; 270162306a36Sopenharmony_ci else 270262306a36Sopenharmony_ci phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED; 270362306a36Sopenharmony_ci 270462306a36Sopenharmony_ci ret_val = igb_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 270562306a36Sopenharmony_ci E1000_EEE_ADV_DEV_I354, 270662306a36Sopenharmony_ci phy_data); 270762306a36Sopenharmony_ci } else { 270862306a36Sopenharmony_ci /* Turn off EEE advertisement. */ 270962306a36Sopenharmony_ci ret_val = igb_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 271062306a36Sopenharmony_ci E1000_EEE_ADV_DEV_I354, 271162306a36Sopenharmony_ci &phy_data); 271262306a36Sopenharmony_ci if (ret_val) 271362306a36Sopenharmony_ci goto out; 271462306a36Sopenharmony_ci 271562306a36Sopenharmony_ci phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED | 271662306a36Sopenharmony_ci E1000_EEE_ADV_1000_SUPPORTED); 271762306a36Sopenharmony_ci ret_val = igb_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 271862306a36Sopenharmony_ci E1000_EEE_ADV_DEV_I354, 271962306a36Sopenharmony_ci phy_data); 272062306a36Sopenharmony_ci } 272162306a36Sopenharmony_ci 272262306a36Sopenharmony_ciout: 272362306a36Sopenharmony_ci return ret_val; 272462306a36Sopenharmony_ci} 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_ci/** 272762306a36Sopenharmony_ci * igb_get_eee_status_i354 - Get EEE status 272862306a36Sopenharmony_ci * @hw: pointer to the HW structure 272962306a36Sopenharmony_ci * @status: EEE status 273062306a36Sopenharmony_ci * 273162306a36Sopenharmony_ci * Get EEE status by guessing based on whether Tx or Rx LPI indications have 273262306a36Sopenharmony_ci * been received. 273362306a36Sopenharmony_ci **/ 273462306a36Sopenharmony_cis32 igb_get_eee_status_i354(struct e1000_hw *hw, bool *status) 273562306a36Sopenharmony_ci{ 273662306a36Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 273762306a36Sopenharmony_ci s32 ret_val = 0; 273862306a36Sopenharmony_ci u16 phy_data; 273962306a36Sopenharmony_ci 274062306a36Sopenharmony_ci /* Check if EEE is supported on this device. */ 274162306a36Sopenharmony_ci if ((hw->phy.media_type != e1000_media_type_copper) || 274262306a36Sopenharmony_ci ((phy->id != M88E1543_E_PHY_ID) && 274362306a36Sopenharmony_ci (phy->id != M88E1512_E_PHY_ID))) 274462306a36Sopenharmony_ci goto out; 274562306a36Sopenharmony_ci 274662306a36Sopenharmony_ci ret_val = igb_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354, 274762306a36Sopenharmony_ci E1000_PCS_STATUS_DEV_I354, 274862306a36Sopenharmony_ci &phy_data); 274962306a36Sopenharmony_ci if (ret_val) 275062306a36Sopenharmony_ci goto out; 275162306a36Sopenharmony_ci 275262306a36Sopenharmony_ci *status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD | 275362306a36Sopenharmony_ci E1000_PCS_STATUS_RX_LPI_RCVD) ? true : false; 275462306a36Sopenharmony_ci 275562306a36Sopenharmony_ciout: 275662306a36Sopenharmony_ci return ret_val; 275762306a36Sopenharmony_ci} 275862306a36Sopenharmony_ci 275962306a36Sopenharmony_ci#ifdef CONFIG_IGB_HWMON 276062306a36Sopenharmony_cistatic const u8 e1000_emc_temp_data[4] = { 276162306a36Sopenharmony_ci E1000_EMC_INTERNAL_DATA, 276262306a36Sopenharmony_ci E1000_EMC_DIODE1_DATA, 276362306a36Sopenharmony_ci E1000_EMC_DIODE2_DATA, 276462306a36Sopenharmony_ci E1000_EMC_DIODE3_DATA 276562306a36Sopenharmony_ci}; 276662306a36Sopenharmony_cistatic const u8 e1000_emc_therm_limit[4] = { 276762306a36Sopenharmony_ci E1000_EMC_INTERNAL_THERM_LIMIT, 276862306a36Sopenharmony_ci E1000_EMC_DIODE1_THERM_LIMIT, 276962306a36Sopenharmony_ci E1000_EMC_DIODE2_THERM_LIMIT, 277062306a36Sopenharmony_ci E1000_EMC_DIODE3_THERM_LIMIT 277162306a36Sopenharmony_ci}; 277262306a36Sopenharmony_ci 277362306a36Sopenharmony_ci/** 277462306a36Sopenharmony_ci * igb_get_thermal_sensor_data_generic - Gathers thermal sensor data 277562306a36Sopenharmony_ci * @hw: pointer to hardware structure 277662306a36Sopenharmony_ci * 277762306a36Sopenharmony_ci * Updates the temperatures in mac.thermal_sensor_data 277862306a36Sopenharmony_ci **/ 277962306a36Sopenharmony_cistatic s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw) 278062306a36Sopenharmony_ci{ 278162306a36Sopenharmony_ci u16 ets_offset; 278262306a36Sopenharmony_ci u16 ets_cfg; 278362306a36Sopenharmony_ci u16 ets_sensor; 278462306a36Sopenharmony_ci u8 num_sensors; 278562306a36Sopenharmony_ci u8 sensor_index; 278662306a36Sopenharmony_ci u8 sensor_location; 278762306a36Sopenharmony_ci u8 i; 278862306a36Sopenharmony_ci struct e1000_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; 278962306a36Sopenharmony_ci 279062306a36Sopenharmony_ci if ((hw->mac.type != e1000_i350) || (hw->bus.func != 0)) 279162306a36Sopenharmony_ci return E1000_NOT_IMPLEMENTED; 279262306a36Sopenharmony_ci 279362306a36Sopenharmony_ci data->sensor[0].temp = (rd32(E1000_THMJT) & 0xFF); 279462306a36Sopenharmony_ci 279562306a36Sopenharmony_ci /* Return the internal sensor only if ETS is unsupported */ 279662306a36Sopenharmony_ci hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_offset); 279762306a36Sopenharmony_ci if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) 279862306a36Sopenharmony_ci return 0; 279962306a36Sopenharmony_ci 280062306a36Sopenharmony_ci hw->nvm.ops.read(hw, ets_offset, 1, &ets_cfg); 280162306a36Sopenharmony_ci if (((ets_cfg & NVM_ETS_TYPE_MASK) >> NVM_ETS_TYPE_SHIFT) 280262306a36Sopenharmony_ci != NVM_ETS_TYPE_EMC) 280362306a36Sopenharmony_ci return E1000_NOT_IMPLEMENTED; 280462306a36Sopenharmony_ci 280562306a36Sopenharmony_ci num_sensors = (ets_cfg & NVM_ETS_NUM_SENSORS_MASK); 280662306a36Sopenharmony_ci if (num_sensors > E1000_MAX_SENSORS) 280762306a36Sopenharmony_ci num_sensors = E1000_MAX_SENSORS; 280862306a36Sopenharmony_ci 280962306a36Sopenharmony_ci for (i = 1; i < num_sensors; i++) { 281062306a36Sopenharmony_ci hw->nvm.ops.read(hw, (ets_offset + i), 1, &ets_sensor); 281162306a36Sopenharmony_ci sensor_index = ((ets_sensor & NVM_ETS_DATA_INDEX_MASK) >> 281262306a36Sopenharmony_ci NVM_ETS_DATA_INDEX_SHIFT); 281362306a36Sopenharmony_ci sensor_location = ((ets_sensor & NVM_ETS_DATA_LOC_MASK) >> 281462306a36Sopenharmony_ci NVM_ETS_DATA_LOC_SHIFT); 281562306a36Sopenharmony_ci 281662306a36Sopenharmony_ci if (sensor_location != 0) 281762306a36Sopenharmony_ci hw->phy.ops.read_i2c_byte(hw, 281862306a36Sopenharmony_ci e1000_emc_temp_data[sensor_index], 281962306a36Sopenharmony_ci E1000_I2C_THERMAL_SENSOR_ADDR, 282062306a36Sopenharmony_ci &data->sensor[i].temp); 282162306a36Sopenharmony_ci } 282262306a36Sopenharmony_ci return 0; 282362306a36Sopenharmony_ci} 282462306a36Sopenharmony_ci 282562306a36Sopenharmony_ci/** 282662306a36Sopenharmony_ci * igb_init_thermal_sensor_thresh_generic - Sets thermal sensor thresholds 282762306a36Sopenharmony_ci * @hw: pointer to hardware structure 282862306a36Sopenharmony_ci * 282962306a36Sopenharmony_ci * Sets the thermal sensor thresholds according to the NVM map 283062306a36Sopenharmony_ci * and save off the threshold and location values into mac.thermal_sensor_data 283162306a36Sopenharmony_ci **/ 283262306a36Sopenharmony_cistatic s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *hw) 283362306a36Sopenharmony_ci{ 283462306a36Sopenharmony_ci u16 ets_offset; 283562306a36Sopenharmony_ci u16 ets_cfg; 283662306a36Sopenharmony_ci u16 ets_sensor; 283762306a36Sopenharmony_ci u8 low_thresh_delta; 283862306a36Sopenharmony_ci u8 num_sensors; 283962306a36Sopenharmony_ci u8 sensor_index; 284062306a36Sopenharmony_ci u8 sensor_location; 284162306a36Sopenharmony_ci u8 therm_limit; 284262306a36Sopenharmony_ci u8 i; 284362306a36Sopenharmony_ci struct e1000_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; 284462306a36Sopenharmony_ci 284562306a36Sopenharmony_ci if ((hw->mac.type != e1000_i350) || (hw->bus.func != 0)) 284662306a36Sopenharmony_ci return E1000_NOT_IMPLEMENTED; 284762306a36Sopenharmony_ci 284862306a36Sopenharmony_ci memset(data, 0, sizeof(struct e1000_thermal_sensor_data)); 284962306a36Sopenharmony_ci 285062306a36Sopenharmony_ci data->sensor[0].location = 0x1; 285162306a36Sopenharmony_ci data->sensor[0].caution_thresh = 285262306a36Sopenharmony_ci (rd32(E1000_THHIGHTC) & 0xFF); 285362306a36Sopenharmony_ci data->sensor[0].max_op_thresh = 285462306a36Sopenharmony_ci (rd32(E1000_THLOWTC) & 0xFF); 285562306a36Sopenharmony_ci 285662306a36Sopenharmony_ci /* Return the internal sensor only if ETS is unsupported */ 285762306a36Sopenharmony_ci hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_offset); 285862306a36Sopenharmony_ci if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) 285962306a36Sopenharmony_ci return 0; 286062306a36Sopenharmony_ci 286162306a36Sopenharmony_ci hw->nvm.ops.read(hw, ets_offset, 1, &ets_cfg); 286262306a36Sopenharmony_ci if (((ets_cfg & NVM_ETS_TYPE_MASK) >> NVM_ETS_TYPE_SHIFT) 286362306a36Sopenharmony_ci != NVM_ETS_TYPE_EMC) 286462306a36Sopenharmony_ci return E1000_NOT_IMPLEMENTED; 286562306a36Sopenharmony_ci 286662306a36Sopenharmony_ci low_thresh_delta = ((ets_cfg & NVM_ETS_LTHRES_DELTA_MASK) >> 286762306a36Sopenharmony_ci NVM_ETS_LTHRES_DELTA_SHIFT); 286862306a36Sopenharmony_ci num_sensors = (ets_cfg & NVM_ETS_NUM_SENSORS_MASK); 286962306a36Sopenharmony_ci 287062306a36Sopenharmony_ci for (i = 1; i <= num_sensors; i++) { 287162306a36Sopenharmony_ci hw->nvm.ops.read(hw, (ets_offset + i), 1, &ets_sensor); 287262306a36Sopenharmony_ci sensor_index = ((ets_sensor & NVM_ETS_DATA_INDEX_MASK) >> 287362306a36Sopenharmony_ci NVM_ETS_DATA_INDEX_SHIFT); 287462306a36Sopenharmony_ci sensor_location = ((ets_sensor & NVM_ETS_DATA_LOC_MASK) >> 287562306a36Sopenharmony_ci NVM_ETS_DATA_LOC_SHIFT); 287662306a36Sopenharmony_ci therm_limit = ets_sensor & NVM_ETS_DATA_HTHRESH_MASK; 287762306a36Sopenharmony_ci 287862306a36Sopenharmony_ci hw->phy.ops.write_i2c_byte(hw, 287962306a36Sopenharmony_ci e1000_emc_therm_limit[sensor_index], 288062306a36Sopenharmony_ci E1000_I2C_THERMAL_SENSOR_ADDR, 288162306a36Sopenharmony_ci therm_limit); 288262306a36Sopenharmony_ci 288362306a36Sopenharmony_ci if ((i < E1000_MAX_SENSORS) && (sensor_location != 0)) { 288462306a36Sopenharmony_ci data->sensor[i].location = sensor_location; 288562306a36Sopenharmony_ci data->sensor[i].caution_thresh = therm_limit; 288662306a36Sopenharmony_ci data->sensor[i].max_op_thresh = therm_limit - 288762306a36Sopenharmony_ci low_thresh_delta; 288862306a36Sopenharmony_ci } 288962306a36Sopenharmony_ci } 289062306a36Sopenharmony_ci return 0; 289162306a36Sopenharmony_ci} 289262306a36Sopenharmony_ci 289362306a36Sopenharmony_ci#endif 289462306a36Sopenharmony_cistatic struct e1000_mac_operations e1000_mac_ops_82575 = { 289562306a36Sopenharmony_ci .init_hw = igb_init_hw_82575, 289662306a36Sopenharmony_ci .check_for_link = igb_check_for_link_82575, 289762306a36Sopenharmony_ci .rar_set = igb_rar_set, 289862306a36Sopenharmony_ci .read_mac_addr = igb_read_mac_addr_82575, 289962306a36Sopenharmony_ci .get_speed_and_duplex = igb_get_link_up_info_82575, 290062306a36Sopenharmony_ci#ifdef CONFIG_IGB_HWMON 290162306a36Sopenharmony_ci .get_thermal_sensor_data = igb_get_thermal_sensor_data_generic, 290262306a36Sopenharmony_ci .init_thermal_sensor_thresh = igb_init_thermal_sensor_thresh_generic, 290362306a36Sopenharmony_ci#endif 290462306a36Sopenharmony_ci}; 290562306a36Sopenharmony_ci 290662306a36Sopenharmony_cistatic const struct e1000_phy_operations e1000_phy_ops_82575 = { 290762306a36Sopenharmony_ci .acquire = igb_acquire_phy_82575, 290862306a36Sopenharmony_ci .get_cfg_done = igb_get_cfg_done_82575, 290962306a36Sopenharmony_ci .release = igb_release_phy_82575, 291062306a36Sopenharmony_ci .write_i2c_byte = igb_write_i2c_byte, 291162306a36Sopenharmony_ci .read_i2c_byte = igb_read_i2c_byte, 291262306a36Sopenharmony_ci}; 291362306a36Sopenharmony_ci 291462306a36Sopenharmony_cistatic struct e1000_nvm_operations e1000_nvm_ops_82575 = { 291562306a36Sopenharmony_ci .acquire = igb_acquire_nvm_82575, 291662306a36Sopenharmony_ci .read = igb_read_nvm_eerd, 291762306a36Sopenharmony_ci .release = igb_release_nvm_82575, 291862306a36Sopenharmony_ci .write = igb_write_nvm_spi, 291962306a36Sopenharmony_ci}; 292062306a36Sopenharmony_ci 292162306a36Sopenharmony_ciconst struct e1000_info e1000_82575_info = { 292262306a36Sopenharmony_ci .get_invariants = igb_get_invariants_82575, 292362306a36Sopenharmony_ci .mac_ops = &e1000_mac_ops_82575, 292462306a36Sopenharmony_ci .phy_ops = &e1000_phy_ops_82575, 292562306a36Sopenharmony_ci .nvm_ops = &e1000_nvm_ops_82575, 292662306a36Sopenharmony_ci}; 292762306a36Sopenharmony_ci 2928