📄 e1000_80003es2lan.c
字号:
/******************************************************************************* Intel PRO/1000 Linux driver Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: Linux NICS <linux.nics@intel.com> e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************//* * 80003ES2LAN Gigabit Ethernet Controller (Copper) * 80003ES2LAN Gigabit Ethernet Controller (Serdes) */#include "e1000.h"static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw);static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw);static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw);static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw);static void e1000_release_phy_80003es2lan(struct e1000_hw *hw);static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw);static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data);static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data);static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw);static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw);static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw);static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, u16 *duplex);static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw);static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw);static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw);static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex);static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw);static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw);static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data);static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data);static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw);static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw);static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);/* * A table for the GG82563 cable length where the range is defined * with a lower bound at "index" and the upper bound at * "index + 5". */static const u16 e1000_gg82563_cable_length_table[] = { 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };#define GG82563_CABLE_LENGTH_TABLE_SIZE \ (sizeof(e1000_gg82563_cable_length_table) / \ sizeof(e1000_gg82563_cable_length_table[0]))/** * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. * @hw: pointer to the HW structure **/static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw){ struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; goto out; } else { phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan; } phy->addr = 1; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 100; phy->type = e1000_phy_gg82563; phy->ops.acquire = e1000_acquire_phy_80003es2lan; phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.check_reset_block = e1000e_check_reset_block_generic; phy->ops.commit = e1000e_phy_sw_reset; phy->ops.get_cfg_done = e1000_get_cfg_done_80003es2lan; phy->ops.get_info = e1000e_get_phy_info_m88; phy->ops.release = e1000_release_phy_80003es2lan; phy->ops.reset = e1000e_phy_hw_reset_generic; phy->ops.set_d3_lplu_state = e1000e_set_d3_lplu_state; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan; phy->ops.get_cable_length = e1000_get_cable_length_80003es2lan; phy->ops.read_reg = e1000_read_phy_reg_gg82563_80003es2lan; phy->ops.write_reg = e1000_write_phy_reg_gg82563_80003es2lan; phy->ops.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan; /* This can only be done after all function pointers are setup. */ ret_val = e1000e_get_phy_id(hw); /* Verify phy id */ if (phy->id != GG82563_E_PHY_ID) { ret_val = -E1000_ERR_PHY; goto out; }out: return ret_val;}/** * e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs. * @hw: pointer to the HW structure **/static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw){ struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = er32(EECD); u16 size; nvm->opcode_bits = 8; nvm->delay_usec = 1; switch (nvm->override) { case e1000_nvm_override_spi_large: nvm->page_size = 32; nvm->address_bits = 16; break; case e1000_nvm_override_spi_small: nvm->page_size = 8; nvm->address_bits = 8; break; default: nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; break; } nvm->type = e1000_nvm_eeprom_spi; size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> E1000_EECD_SIZE_EX_SHIFT); /* * Added to a constant, "size" becomes the left-shift value * for setting word_size. */ size += NVM_WORD_SIZE_BASE_SHIFT; /* EEPROM access above 16k is unsupported */ if (size > 14) size = 14; nvm->word_size = 1 << size; /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_80003es2lan; nvm->ops.read = e1000e_read_nvm_eerd; nvm->ops.release = e1000_release_nvm_80003es2lan; nvm->ops.update = e1000e_update_nvm_checksum_generic; nvm->ops.valid_led_default = e1000e_valid_led_default; nvm->ops.validate = e1000e_validate_nvm_checksum_generic; nvm->ops.write = e1000_write_nvm_80003es2lan; return E1000_SUCCESS;}/** * e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs. * @hw: pointer to the HW structure **/static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; /* Set media type */ switch (hw->device_id) { case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: hw->phy.media_type = e1000_media_type_internal_serdes; break; default: hw->phy.media_type = e1000_media_type_copper; break; } /* Set mta register count */ mac->mta_reg_count = 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES; /* Set if part includes ASF firmware */ mac->asf_firmware_present = true; /* Set if manageability features are enabled. */ mac->arc_subsystem_valid = (er32(FWSM) & E1000_FWSM_MODE_MASK) ? true : false; /* Function pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000e_get_bus_info_pcie; /* reset */ mac->ops.reset_hw = e1000_reset_hw_80003es2lan; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_80003es2lan; /* link setup */ mac->ops.setup_link = e1000e_setup_link; /* physical interface link setup */ mac->ops.setup_physical_interface = (hw->phy.media_type == e1000_media_type_copper) ? e1000_setup_copper_link_80003es2lan : e1000e_setup_fiber_serdes_link; /* check for link */ switch (hw->phy.media_type) { case e1000_media_type_copper: mac->ops.check_for_link = e1000e_check_for_copper_link; break; case e1000_media_type_fiber: mac->ops.check_for_link = e1000e_check_for_fiber_link; break; case e1000_media_type_internal_serdes: mac->ops.check_for_link = e1000e_check_for_serdes_link; break; default: ret_val = -E1000_ERR_CONFIG; goto out; break; } /* check management mode */ mac->ops.check_mng_mode = e1000_check_mng_mode_generic; /* multicast address update */ mac->ops.update_mc_addr_list = e1000e_update_mc_addr_list_generic; /* writing VFTA */ mac->ops.write_vfta = e1000e_write_vfta_generic; /* clearing VFTA */ mac->ops.clear_vfta = e1000e_clear_vfta_generic; /* setting MTA */ mac->ops.mta_set = e1000_mta_set_generic; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan; /* ID LED init */ mac->ops.id_led_init = e1000e_id_led_init; /* blink LED */ mac->ops.blink_led = e1000e_blink_led; /* setup LED */ mac->ops.setup_led = e1000_setup_led_generic; /* cleanup LED */ mac->ops.cleanup_led = e1000e_cleanup_led_generic; /* turn on/off LED */ mac->ops.led_on = e1000e_led_on_generic; mac->ops.led_off = e1000e_led_off_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan; /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_80003es2lan;out: return ret_val;}/** * e1000_init_function_pointers_80003es2lan - Init ESB2 func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw){ e1000_init_mac_ops_generic(hw); e1000_init_nvm_ops_generic(hw); hw->mac.ops.init_params = e1000_init_mac_params_80003es2lan; hw->nvm.ops.init_params = e1000_init_nvm_params_80003es2lan; hw->phy.ops.init_params = e1000_init_phy_params_80003es2lan; e1000e_get_bus_info_pcie(hw);}/** * e1000_acquire_phy_80003es2lan - Acquire rights to access PHY * @hw: pointer to the HW structure * * A wrapper to acquire access rights to the correct PHY. **/static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw){ u16 mask; mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; return e1000_acquire_swfw_sync_80003es2lan(hw, mask);}/** * e1000_release_phy_80003es2lan - Release rights to access PHY * @hw: pointer to the HW structure * * A wrapper to release access rights to the correct PHY. **/static void e1000_release_phy_80003es2lan(struct e1000_hw *hw){ u16 mask; mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; e1000_release_swfw_sync_80003es2lan(hw, mask);}/** * e1000_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran register * @hw: pointer to the HW structure * * Acquire the semaphore to access the Kumeran interface. * **/static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw){ u16 mask; mask = E1000_SWFW_CSR_SM; return e1000_acquire_swfw_sync_80003es2lan(hw, mask);}/** * e1000_release_mac_csr_80003es2lan - Release rights to access Kumeran Register * @hw: pointer to the HW structure * * Release the semaphore used to access the Kumeran interface **/static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw){ u16 mask; mask = E1000_SWFW_CSR_SM; e1000_release_swfw_sync_80003es2lan(hw, mask);}/** * e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM * @hw: pointer to the HW structure * * Acquire the semaphore to access the EEPROM. **/static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw){ s32 ret_val; ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); if (ret_val) goto out; ret_val = e1000e_acquire_nvm(hw); if (ret_val) e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);out: return ret_val;}/** * e1000_release_nvm_80003es2lan - Relinquish rights to access NVM * @hw: pointer to the HW structure * * Release the semaphore used to access the EEPROM. **/static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw){ e1000e_release_nvm(hw); e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);}/** * e1000_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Acquire the SW/FW semaphore to access the PHY or NVM. The mask * will also specify which port we're acquiring the lock for. **/static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask){ u32 swfw_sync; u32 swmask = mask; u32 fwmask = mask << 16; s32 ret_val = E1000_SUCCESS; s32 i = 0, timeout = 50; while (i < timeout) { if (e1000e_get_hw_semaphore(hw)) { ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync = er32(SW_FW_SYNC); if (!(swfw_sync & (fwmask | swmask))) break; /* * Firmware currently using resource (fwmask) * or other software thread using resource (swmask) */ e1000e_put_hw_semaphore(hw); mdelay(5); i++; } if (i == timeout) { e_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync |= swmask; ew32(SW_FW_SYNC, swfw_sync); e1000e_put_hw_semaphore(hw);out: return ret_val;}/** * e1000_release_swfw_sync_80003es2lan - Release SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Release the SW/FW semaphore used to access the PHY or NVM. The mask * will also specify which port we're releasing the lock for. **/static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask){ u32 swfw_sync; while (e1000e_get_hw_semaphore(hw) != E1000_SUCCESS) ; /* Empty */ swfw_sync = er32(SW_FW_SYNC); swfw_sync &= ~mask; ew32(SW_FW_SYNC, swfw_sync); e1000e_put_hw_semaphore(hw);}/** * e1000_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register * @hw: pointer to the HW structure * @offset: offset of the register to read * @data: pointer to the data returned from the operation * * Read the GG82563 PHY register. **/static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data){ s32 ret_val; u32 page_select; u16 temp; ret_val = e1000_acquire_phy_80003es2lan(hw); if (ret_val) goto out; /* Select Configuration Page */ if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -