18cfa0ad2SJack F Vogel /****************************************************************************** 28cfa0ad2SJack F Vogel 38cfa0ad2SJack F Vogel Copyright (c) 2001-2008, Intel Corporation 48cfa0ad2SJack F Vogel All rights reserved. 58cfa0ad2SJack F Vogel 68cfa0ad2SJack F Vogel Redistribution and use in source and binary forms, with or without 78cfa0ad2SJack F Vogel modification, are permitted provided that the following conditions are met: 88cfa0ad2SJack F Vogel 98cfa0ad2SJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 108cfa0ad2SJack F Vogel this list of conditions and the following disclaimer. 118cfa0ad2SJack F Vogel 128cfa0ad2SJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 138cfa0ad2SJack F Vogel notice, this list of conditions and the following disclaimer in the 148cfa0ad2SJack F Vogel documentation and/or other materials provided with the distribution. 158cfa0ad2SJack F Vogel 168cfa0ad2SJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 178cfa0ad2SJack F Vogel contributors may be used to endorse or promote products derived from 188cfa0ad2SJack F Vogel this software without specific prior written permission. 198cfa0ad2SJack F Vogel 208cfa0ad2SJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 218cfa0ad2SJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 228cfa0ad2SJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 238cfa0ad2SJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 248cfa0ad2SJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 258cfa0ad2SJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 268cfa0ad2SJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 278cfa0ad2SJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 288cfa0ad2SJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 298cfa0ad2SJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 308cfa0ad2SJack F Vogel POSSIBILITY OF SUCH DAMAGE. 318cfa0ad2SJack F Vogel 328cfa0ad2SJack F Vogel ******************************************************************************/ 338cfa0ad2SJack F Vogel /*$FreeBSD$*/ 348cfa0ad2SJack F Vogel 358cfa0ad2SJack F Vogel /* e1000_82541 368cfa0ad2SJack F Vogel * e1000_82547 378cfa0ad2SJack F Vogel * e1000_82541_rev_2 388cfa0ad2SJack F Vogel * e1000_82547_rev_2 398cfa0ad2SJack F Vogel */ 408cfa0ad2SJack F Vogel 418cfa0ad2SJack F Vogel #include "e1000_api.h" 428cfa0ad2SJack F Vogel 438cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82541(struct e1000_hw *hw); 448cfa0ad2SJack F Vogel static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw); 458cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82541(struct e1000_hw *hw); 468cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82541(struct e1000_hw *hw); 478cfa0ad2SJack F Vogel static s32 e1000_init_hw_82541(struct e1000_hw *hw); 488cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed, 498cfa0ad2SJack F Vogel u16 *duplex); 508cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw); 518cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw); 528cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82541(struct e1000_hw *hw); 538cfa0ad2SJack F Vogel static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw); 548cfa0ad2SJack F Vogel static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, 558cfa0ad2SJack F Vogel bool active); 568cfa0ad2SJack F Vogel static s32 e1000_setup_led_82541(struct e1000_hw *hw); 578cfa0ad2SJack F Vogel static s32 e1000_cleanup_led_82541(struct e1000_hw *hw); 588cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw); 598cfa0ad2SJack F Vogel static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, 608cfa0ad2SJack F Vogel bool link_up); 618cfa0ad2SJack F Vogel static s32 e1000_phy_init_script_82541(struct e1000_hw *hw); 628cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw); 638cfa0ad2SJack F Vogel 648cfa0ad2SJack F Vogel static const u16 e1000_igp_cable_length_table[] = 658cfa0ad2SJack F Vogel { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 668cfa0ad2SJack F Vogel 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, 678cfa0ad2SJack F Vogel 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, 688cfa0ad2SJack F Vogel 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, 698cfa0ad2SJack F Vogel 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, 708cfa0ad2SJack F Vogel 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 718cfa0ad2SJack F Vogel 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 728cfa0ad2SJack F Vogel 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; 738cfa0ad2SJack F Vogel #define IGP01E1000_AGC_LENGTH_TABLE_SIZE \ 748cfa0ad2SJack F Vogel (sizeof(e1000_igp_cable_length_table) / \ 758cfa0ad2SJack F Vogel sizeof(e1000_igp_cable_length_table[0])) 768cfa0ad2SJack F Vogel 778cfa0ad2SJack F Vogel struct e1000_dev_spec_82541 { 788cfa0ad2SJack F Vogel enum e1000_dsp_config dsp_config; 798cfa0ad2SJack F Vogel enum e1000_ffe_config ffe_config; 808cfa0ad2SJack F Vogel u16 spd_default; 818cfa0ad2SJack F Vogel bool phy_init_script; 828cfa0ad2SJack F Vogel }; 838cfa0ad2SJack F Vogel 848cfa0ad2SJack F Vogel /** 858cfa0ad2SJack F Vogel * e1000_init_phy_params_82541 - Init PHY func ptrs. 868cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 878cfa0ad2SJack F Vogel * 888cfa0ad2SJack F Vogel * This is a function pointer entry point called by the api module. 898cfa0ad2SJack F Vogel **/ 908cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82541(struct e1000_hw *hw) 918cfa0ad2SJack F Vogel { 928cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 938cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 948cfa0ad2SJack F Vogel 958cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_phy_params_82541"); 968cfa0ad2SJack F Vogel 978cfa0ad2SJack F Vogel phy->addr = 1; 988cfa0ad2SJack F Vogel phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 998cfa0ad2SJack F Vogel phy->reset_delay_us = 10000; 1008cfa0ad2SJack F Vogel phy->type = e1000_phy_igp; 1018cfa0ad2SJack F Vogel 1028cfa0ad2SJack F Vogel /* Function Pointers */ 1038cfa0ad2SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_igp; 1048cfa0ad2SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; 1058cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_igp_82541; 1068cfa0ad2SJack F Vogel phy->ops.get_cfg_done = e1000_get_cfg_done_generic; 1078cfa0ad2SJack F Vogel phy->ops.get_info = e1000_get_phy_info_igp; 1088cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_igp; 1098cfa0ad2SJack F Vogel phy->ops.reset = e1000_phy_hw_reset_82541; 1108cfa0ad2SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82541; 1118cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_igp; 1128cfa0ad2SJack F Vogel phy->ops.power_up = e1000_power_up_phy_copper; 1138cfa0ad2SJack F Vogel phy->ops.power_down = e1000_power_down_phy_copper_82541; 1148cfa0ad2SJack F Vogel 1158cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id(hw); 1168cfa0ad2SJack F Vogel if (ret_val) 1178cfa0ad2SJack F Vogel goto out; 1188cfa0ad2SJack F Vogel 1198cfa0ad2SJack F Vogel /* Verify phy id */ 1208cfa0ad2SJack F Vogel if (phy->id != IGP01E1000_I_PHY_ID) { 1218cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 1228cfa0ad2SJack F Vogel goto out; 1238cfa0ad2SJack F Vogel } 1248cfa0ad2SJack F Vogel 1258cfa0ad2SJack F Vogel out: 1268cfa0ad2SJack F Vogel return ret_val; 1278cfa0ad2SJack F Vogel } 1288cfa0ad2SJack F Vogel 1298cfa0ad2SJack F Vogel /** 1308cfa0ad2SJack F Vogel * e1000_init_nvm_params_82541 - Init NVM func ptrs. 1318cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 1328cfa0ad2SJack F Vogel * 1338cfa0ad2SJack F Vogel * This is a function pointer entry point called by the api module. 1348cfa0ad2SJack F Vogel **/ 1358cfa0ad2SJack F Vogel static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw) 1368cfa0ad2SJack F Vogel { 1378cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 1388cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 1398cfa0ad2SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD); 1408cfa0ad2SJack F Vogel u16 size; 1418cfa0ad2SJack F Vogel 1428cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_nvm_params_82541"); 1438cfa0ad2SJack F Vogel 1448cfa0ad2SJack F Vogel switch (nvm->override) { 1458cfa0ad2SJack F Vogel case e1000_nvm_override_spi_large: 1468cfa0ad2SJack F Vogel nvm->type = e1000_nvm_eeprom_spi; 1478cfa0ad2SJack F Vogel eecd |= E1000_EECD_ADDR_BITS; 1488cfa0ad2SJack F Vogel break; 1498cfa0ad2SJack F Vogel case e1000_nvm_override_spi_small: 1508cfa0ad2SJack F Vogel nvm->type = e1000_nvm_eeprom_spi; 1518cfa0ad2SJack F Vogel eecd &= ~E1000_EECD_ADDR_BITS; 1528cfa0ad2SJack F Vogel break; 1538cfa0ad2SJack F Vogel case e1000_nvm_override_microwire_large: 1548cfa0ad2SJack F Vogel nvm->type = e1000_nvm_eeprom_microwire; 1558cfa0ad2SJack F Vogel eecd |= E1000_EECD_SIZE; 1568cfa0ad2SJack F Vogel break; 1578cfa0ad2SJack F Vogel case e1000_nvm_override_microwire_small: 1588cfa0ad2SJack F Vogel nvm->type = e1000_nvm_eeprom_microwire; 1598cfa0ad2SJack F Vogel eecd &= ~E1000_EECD_SIZE; 1608cfa0ad2SJack F Vogel break; 1618cfa0ad2SJack F Vogel default: 1628cfa0ad2SJack F Vogel nvm->type = eecd & E1000_EECD_TYPE 1638cfa0ad2SJack F Vogel ? e1000_nvm_eeprom_spi 1648cfa0ad2SJack F Vogel : e1000_nvm_eeprom_microwire; 1658cfa0ad2SJack F Vogel break; 1668cfa0ad2SJack F Vogel } 1678cfa0ad2SJack F Vogel 1688cfa0ad2SJack F Vogel if (nvm->type == e1000_nvm_eeprom_spi) { 1698cfa0ad2SJack F Vogel nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) 1708cfa0ad2SJack F Vogel ? 16 : 8; 1718cfa0ad2SJack F Vogel nvm->delay_usec = 1; 1728cfa0ad2SJack F Vogel nvm->opcode_bits = 8; 1738cfa0ad2SJack F Vogel nvm->page_size = (eecd & E1000_EECD_ADDR_BITS) 1748cfa0ad2SJack F Vogel ? 32 : 8; 1758cfa0ad2SJack F Vogel 1768cfa0ad2SJack F Vogel /* Function Pointers */ 1778cfa0ad2SJack F Vogel nvm->ops.acquire = e1000_acquire_nvm_generic; 1788cfa0ad2SJack F Vogel nvm->ops.read = e1000_read_nvm_spi; 1798cfa0ad2SJack F Vogel nvm->ops.release = e1000_release_nvm_generic; 1808cfa0ad2SJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_generic; 1818cfa0ad2SJack F Vogel nvm->ops.valid_led_default = e1000_valid_led_default_generic; 1828cfa0ad2SJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_generic; 1838cfa0ad2SJack F Vogel nvm->ops.write = e1000_write_nvm_spi; 1848cfa0ad2SJack F Vogel 1858cfa0ad2SJack F Vogel /* 1868cfa0ad2SJack F Vogel * nvm->word_size must be discovered after the pointers 1878cfa0ad2SJack F Vogel * are set so we can verify the size from the nvm image 1888cfa0ad2SJack F Vogel * itself. Temporarily set it to a dummy value so the 1898cfa0ad2SJack F Vogel * read will work. 1908cfa0ad2SJack F Vogel */ 1918cfa0ad2SJack F Vogel nvm->word_size = 64; 1928cfa0ad2SJack F Vogel ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size); 1938cfa0ad2SJack F Vogel if (ret_val) 1948cfa0ad2SJack F Vogel goto out; 1958cfa0ad2SJack F Vogel size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT; 1968cfa0ad2SJack F Vogel /* 1978cfa0ad2SJack F Vogel * if size != 0, it can be added to a constant and become 1988cfa0ad2SJack F Vogel * the left-shift value to set the word_size. Otherwise, 1998cfa0ad2SJack F Vogel * word_size stays at 64. 2008cfa0ad2SJack F Vogel */ 2018cfa0ad2SJack F Vogel if (size) { 2028cfa0ad2SJack F Vogel size += NVM_WORD_SIZE_BASE_SHIFT_82541; 2038cfa0ad2SJack F Vogel nvm->word_size = 1 << size; 2048cfa0ad2SJack F Vogel } 2058cfa0ad2SJack F Vogel } else { 2068cfa0ad2SJack F Vogel nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) 2078cfa0ad2SJack F Vogel ? 8 : 6; 2088cfa0ad2SJack F Vogel nvm->delay_usec = 50; 2098cfa0ad2SJack F Vogel nvm->opcode_bits = 3; 2108cfa0ad2SJack F Vogel nvm->word_size = (eecd & E1000_EECD_ADDR_BITS) 2118cfa0ad2SJack F Vogel ? 256 : 64; 2128cfa0ad2SJack F Vogel 2138cfa0ad2SJack F Vogel /* Function Pointers */ 2148cfa0ad2SJack F Vogel nvm->ops.acquire = e1000_acquire_nvm_generic; 2158cfa0ad2SJack F Vogel nvm->ops.read = e1000_read_nvm_microwire; 2168cfa0ad2SJack F Vogel nvm->ops.release = e1000_release_nvm_generic; 2178cfa0ad2SJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_generic; 2188cfa0ad2SJack F Vogel nvm->ops.valid_led_default = e1000_valid_led_default_generic; 2198cfa0ad2SJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_generic; 2208cfa0ad2SJack F Vogel nvm->ops.write = e1000_write_nvm_microwire; 2218cfa0ad2SJack F Vogel } 2228cfa0ad2SJack F Vogel 2238cfa0ad2SJack F Vogel out: 2248cfa0ad2SJack F Vogel return ret_val; 2258cfa0ad2SJack F Vogel } 2268cfa0ad2SJack F Vogel 2278cfa0ad2SJack F Vogel /** 2288cfa0ad2SJack F Vogel * e1000_init_mac_params_82541 - Init MAC func ptrs. 2298cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 2308cfa0ad2SJack F Vogel * 2318cfa0ad2SJack F Vogel * This is a function pointer entry point called by the api module. 2328cfa0ad2SJack F Vogel **/ 2338cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82541(struct e1000_hw *hw) 2348cfa0ad2SJack F Vogel { 2358cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 2368cfa0ad2SJack F Vogel s32 ret_val; 2378cfa0ad2SJack F Vogel 2388cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_mac_params_82541"); 2398cfa0ad2SJack F Vogel 2408cfa0ad2SJack F Vogel /* Set media type */ 2418cfa0ad2SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 2428cfa0ad2SJack F Vogel /* Set mta register count */ 2438cfa0ad2SJack F Vogel mac->mta_reg_count = 128; 2448cfa0ad2SJack F Vogel /* Set rar entry count */ 2458cfa0ad2SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES; 2468cfa0ad2SJack F Vogel /* Set if part includes ASF firmware */ 2478cfa0ad2SJack F Vogel mac->asf_firmware_present = TRUE; 2488cfa0ad2SJack F Vogel 2498cfa0ad2SJack F Vogel /* Function Pointers */ 2508cfa0ad2SJack F Vogel 2518cfa0ad2SJack F Vogel /* bus type/speed/width */ 2528cfa0ad2SJack F Vogel mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; 2538cfa0ad2SJack F Vogel /* reset */ 2548cfa0ad2SJack F Vogel mac->ops.reset_hw = e1000_reset_hw_82541; 2558cfa0ad2SJack F Vogel /* hw initialization */ 2568cfa0ad2SJack F Vogel mac->ops.init_hw = e1000_init_hw_82541; 2578cfa0ad2SJack F Vogel /* link setup */ 2588cfa0ad2SJack F Vogel mac->ops.setup_link = e1000_setup_link_generic; 2598cfa0ad2SJack F Vogel /* physical interface link setup */ 2608cfa0ad2SJack F Vogel mac->ops.setup_physical_interface = e1000_setup_copper_link_82541; 2618cfa0ad2SJack F Vogel /* check for link */ 2628cfa0ad2SJack F Vogel mac->ops.check_for_link = e1000_check_for_link_82541; 2638cfa0ad2SJack F Vogel /* link info */ 2648cfa0ad2SJack F Vogel mac->ops.get_link_up_info = e1000_get_link_up_info_82541; 2658cfa0ad2SJack F Vogel /* multicast address update */ 2668cfa0ad2SJack F Vogel mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; 2678cfa0ad2SJack F Vogel /* writing VFTA */ 2688cfa0ad2SJack F Vogel mac->ops.write_vfta = e1000_write_vfta_generic; 2698cfa0ad2SJack F Vogel /* clearing VFTA */ 2708cfa0ad2SJack F Vogel mac->ops.clear_vfta = e1000_clear_vfta_generic; 2718cfa0ad2SJack F Vogel /* setting MTA */ 2728cfa0ad2SJack F Vogel mac->ops.mta_set = e1000_mta_set_generic; 2738cfa0ad2SJack F Vogel /* setup LED */ 2748cfa0ad2SJack F Vogel mac->ops.setup_led = e1000_setup_led_82541; 2758cfa0ad2SJack F Vogel /* cleanup LED */ 2768cfa0ad2SJack F Vogel mac->ops.cleanup_led = e1000_cleanup_led_82541; 2778cfa0ad2SJack F Vogel /* turn on/off LED */ 2788cfa0ad2SJack F Vogel mac->ops.led_on = e1000_led_on_generic; 2798cfa0ad2SJack F Vogel mac->ops.led_off = e1000_led_off_generic; 2808cfa0ad2SJack F Vogel /* remove device */ 2818cfa0ad2SJack F Vogel mac->ops.remove_device = e1000_remove_device_generic; 2828cfa0ad2SJack F Vogel /* clear hardware counters */ 2838cfa0ad2SJack F Vogel mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541; 2848cfa0ad2SJack F Vogel 2858cfa0ad2SJack F Vogel hw->dev_spec_size = sizeof(struct e1000_dev_spec_82541); 2868cfa0ad2SJack F Vogel 2878cfa0ad2SJack F Vogel /* Device-specific structure allocation */ 2888cfa0ad2SJack F Vogel ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); 2898cfa0ad2SJack F Vogel 2908cfa0ad2SJack F Vogel return ret_val; 2918cfa0ad2SJack F Vogel } 2928cfa0ad2SJack F Vogel 2938cfa0ad2SJack F Vogel /** 2948cfa0ad2SJack F Vogel * e1000_init_function_pointers_82541 - Init func ptrs. 2958cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 2968cfa0ad2SJack F Vogel * 2978cfa0ad2SJack F Vogel * The only function explicitly called by the api module to initialize 2988cfa0ad2SJack F Vogel * all function pointers and parameters. 2998cfa0ad2SJack F Vogel **/ 3008cfa0ad2SJack F Vogel void e1000_init_function_pointers_82541(struct e1000_hw *hw) 3018cfa0ad2SJack F Vogel { 3028cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_function_pointers_82541"); 3038cfa0ad2SJack F Vogel 3048cfa0ad2SJack F Vogel hw->mac.ops.init_params = e1000_init_mac_params_82541; 3058cfa0ad2SJack F Vogel hw->nvm.ops.init_params = e1000_init_nvm_params_82541; 3068cfa0ad2SJack F Vogel hw->phy.ops.init_params = e1000_init_phy_params_82541; 3078cfa0ad2SJack F Vogel } 3088cfa0ad2SJack F Vogel 3098cfa0ad2SJack F Vogel /** 3108cfa0ad2SJack F Vogel * e1000_reset_hw_82541 - Reset hardware 3118cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 3128cfa0ad2SJack F Vogel * 3138cfa0ad2SJack F Vogel * This resets the hardware into a known state. This is a 3148cfa0ad2SJack F Vogel * function pointer entry point called by the api module. 3158cfa0ad2SJack F Vogel **/ 3168cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82541(struct e1000_hw *hw) 3178cfa0ad2SJack F Vogel { 3188cfa0ad2SJack F Vogel u32 ledctl, ctrl, icr, manc; 3198cfa0ad2SJack F Vogel 3208cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_hw_82541"); 3218cfa0ad2SJack F Vogel 3228cfa0ad2SJack F Vogel DEBUGOUT("Masking off all interrupts\n"); 3238cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); 3248cfa0ad2SJack F Vogel 3258cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0); 3268cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); 3278cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 3288cfa0ad2SJack F Vogel 3298cfa0ad2SJack F Vogel /* 3308cfa0ad2SJack F Vogel * Delay to allow any outstanding PCI transactions to complete 3318cfa0ad2SJack F Vogel * before resetting the device. 3328cfa0ad2SJack F Vogel */ 3338cfa0ad2SJack F Vogel msec_delay(10); 3348cfa0ad2SJack F Vogel 3358cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 3368cfa0ad2SJack F Vogel 3378cfa0ad2SJack F Vogel /* Must reset the Phy before resetting the MAC */ 3388cfa0ad2SJack F Vogel if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { 3398cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST)); 3408cfa0ad2SJack F Vogel msec_delay(5); 3418cfa0ad2SJack F Vogel } 3428cfa0ad2SJack F Vogel 3438cfa0ad2SJack F Vogel DEBUGOUT("Issuing a global reset to 82541/82547 MAC\n"); 3448cfa0ad2SJack F Vogel switch (hw->mac.type) { 3458cfa0ad2SJack F Vogel case e1000_82541: 3468cfa0ad2SJack F Vogel case e1000_82541_rev_2: 3478cfa0ad2SJack F Vogel /* 3488cfa0ad2SJack F Vogel * These controllers can't ack the 64-bit write when 3498cfa0ad2SJack F Vogel * issuing the reset, so we use IO-mapping as a 3508cfa0ad2SJack F Vogel * workaround to issue the reset. 3518cfa0ad2SJack F Vogel */ 3528cfa0ad2SJack F Vogel E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); 3538cfa0ad2SJack F Vogel break; 3548cfa0ad2SJack F Vogel default: 3558cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); 3568cfa0ad2SJack F Vogel break; 3578cfa0ad2SJack F Vogel } 3588cfa0ad2SJack F Vogel 3598cfa0ad2SJack F Vogel /* Wait for NVM reload */ 3608cfa0ad2SJack F Vogel msec_delay(20); 3618cfa0ad2SJack F Vogel 3628cfa0ad2SJack F Vogel /* Disable HW ARPs on ASF enabled adapters */ 3638cfa0ad2SJack F Vogel manc = E1000_READ_REG(hw, E1000_MANC); 3648cfa0ad2SJack F Vogel manc &= ~E1000_MANC_ARP_EN; 3658cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_MANC, manc); 3668cfa0ad2SJack F Vogel 3678cfa0ad2SJack F Vogel if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { 3688cfa0ad2SJack F Vogel e1000_phy_init_script_82541(hw); 3698cfa0ad2SJack F Vogel 3708cfa0ad2SJack F Vogel /* Configure activity LED after Phy reset */ 3718cfa0ad2SJack F Vogel ledctl = E1000_READ_REG(hw, E1000_LEDCTL); 3728cfa0ad2SJack F Vogel ledctl &= IGP_ACTIVITY_LED_MASK; 3738cfa0ad2SJack F Vogel ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); 3748cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); 3758cfa0ad2SJack F Vogel } 3768cfa0ad2SJack F Vogel 3778cfa0ad2SJack F Vogel /* Once again, mask the interrupts */ 3788cfa0ad2SJack F Vogel DEBUGOUT("Masking off all interrupts\n"); 3798cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); 3808cfa0ad2SJack F Vogel 3818cfa0ad2SJack F Vogel /* Clear any pending interrupt events. */ 3828cfa0ad2SJack F Vogel icr = E1000_READ_REG(hw, E1000_ICR); 3838cfa0ad2SJack F Vogel 3848cfa0ad2SJack F Vogel return E1000_SUCCESS; 3858cfa0ad2SJack F Vogel } 3868cfa0ad2SJack F Vogel 3878cfa0ad2SJack F Vogel /** 3888cfa0ad2SJack F Vogel * e1000_init_hw_82541 - Initialize hardware 3898cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 3908cfa0ad2SJack F Vogel * 3918cfa0ad2SJack F Vogel * This inits the hardware readying it for operation. This is a 3928cfa0ad2SJack F Vogel * function pointer entry point called by the api module. 3938cfa0ad2SJack F Vogel **/ 3948cfa0ad2SJack F Vogel static s32 e1000_init_hw_82541(struct e1000_hw *hw) 3958cfa0ad2SJack F Vogel { 3968cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 3978cfa0ad2SJack F Vogel u32 i, txdctl; 3988cfa0ad2SJack F Vogel s32 ret_val; 3998cfa0ad2SJack F Vogel 4008cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_hw_82541"); 4018cfa0ad2SJack F Vogel 4028cfa0ad2SJack F Vogel /* Initialize identification LED */ 4038cfa0ad2SJack F Vogel ret_val = e1000_id_led_init_generic(hw); 4048cfa0ad2SJack F Vogel if (ret_val) { 4058cfa0ad2SJack F Vogel DEBUGOUT("Error initializing identification LED\n"); 4068cfa0ad2SJack F Vogel /* This is not fatal and we should not stop init due to this */ 4078cfa0ad2SJack F Vogel } 4088cfa0ad2SJack F Vogel 4098cfa0ad2SJack F Vogel /* Disabling VLAN filtering */ 4108cfa0ad2SJack F Vogel DEBUGOUT("Initializing the IEEE VLAN\n"); 4118cfa0ad2SJack F Vogel mac->ops.clear_vfta(hw); 4128cfa0ad2SJack F Vogel 4138cfa0ad2SJack F Vogel /* Setup the receive address. */ 4148cfa0ad2SJack F Vogel e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); 4158cfa0ad2SJack F Vogel 4168cfa0ad2SJack F Vogel /* Zero out the Multicast HASH table */ 4178cfa0ad2SJack F Vogel DEBUGOUT("Zeroing the MTA\n"); 4188cfa0ad2SJack F Vogel for (i = 0; i < mac->mta_reg_count; i++) { 4198cfa0ad2SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); 4208cfa0ad2SJack F Vogel /* 4218cfa0ad2SJack F Vogel * Avoid back to back register writes by adding the register 4228cfa0ad2SJack F Vogel * read (flush). This is to protect against some strange 4238cfa0ad2SJack F Vogel * bridge configurations that may issue Memory Write Block 4248cfa0ad2SJack F Vogel * (MWB) to our register space. 4258cfa0ad2SJack F Vogel */ 4268cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 4278cfa0ad2SJack F Vogel } 4288cfa0ad2SJack F Vogel 4298cfa0ad2SJack F Vogel /* Setup link and flow control */ 4308cfa0ad2SJack F Vogel ret_val = mac->ops.setup_link(hw); 4318cfa0ad2SJack F Vogel 4328cfa0ad2SJack F Vogel txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); 4338cfa0ad2SJack F Vogel txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | 4348cfa0ad2SJack F Vogel E1000_TXDCTL_FULL_TX_DESC_WB; 4358cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); 4368cfa0ad2SJack F Vogel 4378cfa0ad2SJack F Vogel /* 4388cfa0ad2SJack F Vogel * Clear all of the statistics registers (clear on read). It is 4398cfa0ad2SJack F Vogel * important that we do this after we have tried to establish link 4408cfa0ad2SJack F Vogel * because the symbol error count will increment wildly if there 4418cfa0ad2SJack F Vogel * is no link. 4428cfa0ad2SJack F Vogel */ 4438cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_82541(hw); 4448cfa0ad2SJack F Vogel 4458cfa0ad2SJack F Vogel return ret_val; 4468cfa0ad2SJack F Vogel } 4478cfa0ad2SJack F Vogel 4488cfa0ad2SJack F Vogel /** 4498cfa0ad2SJack F Vogel * e1000_get_link_up_info_82541 - Report speed and duplex 4508cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 4518cfa0ad2SJack F Vogel * @speed: pointer to speed buffer 4528cfa0ad2SJack F Vogel * @duplex: pointer to duplex buffer 4538cfa0ad2SJack F Vogel * 4548cfa0ad2SJack F Vogel * Retrieve the current speed and duplex configuration. 4558cfa0ad2SJack F Vogel * This is a function pointer entry point called by the api module. 4568cfa0ad2SJack F Vogel **/ 4578cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed, 4588cfa0ad2SJack F Vogel u16 *duplex) 4598cfa0ad2SJack F Vogel { 4608cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 4618cfa0ad2SJack F Vogel s32 ret_val; 4628cfa0ad2SJack F Vogel u16 data; 4638cfa0ad2SJack F Vogel 4648cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_link_up_info_82541"); 4658cfa0ad2SJack F Vogel 4668cfa0ad2SJack F Vogel ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); 4678cfa0ad2SJack F Vogel if (ret_val) 4688cfa0ad2SJack F Vogel goto out; 4698cfa0ad2SJack F Vogel 4708cfa0ad2SJack F Vogel if (!phy->speed_downgraded) 4718cfa0ad2SJack F Vogel goto out; 4728cfa0ad2SJack F Vogel 4738cfa0ad2SJack F Vogel /* 4748cfa0ad2SJack F Vogel * IGP01 PHY may advertise full duplex operation after speed 4758cfa0ad2SJack F Vogel * downgrade even if it is operating at half duplex. 4768cfa0ad2SJack F Vogel * Here we set the duplex settings to match the duplex in the 4778cfa0ad2SJack F Vogel * link partner's capabilities. 4788cfa0ad2SJack F Vogel */ 4798cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data); 4808cfa0ad2SJack F Vogel if (ret_val) 4818cfa0ad2SJack F Vogel goto out; 4828cfa0ad2SJack F Vogel 4838cfa0ad2SJack F Vogel if (!(data & NWAY_ER_LP_NWAY_CAPS)) { 4848cfa0ad2SJack F Vogel *duplex = HALF_DUPLEX; 4858cfa0ad2SJack F Vogel } else { 4868cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data); 4878cfa0ad2SJack F Vogel if (ret_val) 4888cfa0ad2SJack F Vogel goto out; 4898cfa0ad2SJack F Vogel 4908cfa0ad2SJack F Vogel if (*speed == SPEED_100) { 4918cfa0ad2SJack F Vogel if (!(data & NWAY_LPAR_100TX_FD_CAPS)) 4928cfa0ad2SJack F Vogel *duplex = HALF_DUPLEX; 4938cfa0ad2SJack F Vogel } else if (*speed == SPEED_10) { 4948cfa0ad2SJack F Vogel if (!(data & NWAY_LPAR_10T_FD_CAPS)) 4958cfa0ad2SJack F Vogel *duplex = HALF_DUPLEX; 4968cfa0ad2SJack F Vogel } 4978cfa0ad2SJack F Vogel } 4988cfa0ad2SJack F Vogel 4998cfa0ad2SJack F Vogel out: 5008cfa0ad2SJack F Vogel return ret_val; 5018cfa0ad2SJack F Vogel } 5028cfa0ad2SJack F Vogel 5038cfa0ad2SJack F Vogel /** 5048cfa0ad2SJack F Vogel * e1000_phy_hw_reset_82541 - PHY hardware reset 5058cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5068cfa0ad2SJack F Vogel * 5078cfa0ad2SJack F Vogel * Verify the reset block is not blocking us from resetting. Acquire 5088cfa0ad2SJack F Vogel * semaphore (if necessary) and read/set/write the device control reset 5098cfa0ad2SJack F Vogel * bit in the PHY. Wait the appropriate delay time for the device to 5108cfa0ad2SJack F Vogel * reset and release the semaphore (if necessary). 5118cfa0ad2SJack F Vogel * This is a function pointer entry point called by the api module. 5128cfa0ad2SJack F Vogel **/ 5138cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw) 5148cfa0ad2SJack F Vogel { 5158cfa0ad2SJack F Vogel s32 ret_val; 5168cfa0ad2SJack F Vogel u32 ledctl; 5178cfa0ad2SJack F Vogel 5188cfa0ad2SJack F Vogel DEBUGFUNC("e1000_phy_hw_reset_82541"); 5198cfa0ad2SJack F Vogel 5208cfa0ad2SJack F Vogel ret_val = e1000_phy_hw_reset_generic(hw); 5218cfa0ad2SJack F Vogel if (ret_val) 5228cfa0ad2SJack F Vogel goto out; 5238cfa0ad2SJack F Vogel 5248cfa0ad2SJack F Vogel e1000_phy_init_script_82541(hw); 5258cfa0ad2SJack F Vogel 5268cfa0ad2SJack F Vogel if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { 5278cfa0ad2SJack F Vogel /* Configure activity LED after PHY reset */ 5288cfa0ad2SJack F Vogel ledctl = E1000_READ_REG(hw, E1000_LEDCTL); 5298cfa0ad2SJack F Vogel ledctl &= IGP_ACTIVITY_LED_MASK; 5308cfa0ad2SJack F Vogel ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); 5318cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); 5328cfa0ad2SJack F Vogel } 5338cfa0ad2SJack F Vogel 5348cfa0ad2SJack F Vogel out: 5358cfa0ad2SJack F Vogel return ret_val; 5368cfa0ad2SJack F Vogel } 5378cfa0ad2SJack F Vogel 5388cfa0ad2SJack F Vogel /** 5398cfa0ad2SJack F Vogel * e1000_setup_copper_link_82541 - Configure copper link settings 5408cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5418cfa0ad2SJack F Vogel * 5428cfa0ad2SJack F Vogel * Calls the appropriate function to configure the link for auto-neg or forced 5438cfa0ad2SJack F Vogel * speed and duplex. Then we check for link, once link is established calls 5448cfa0ad2SJack F Vogel * to configure collision distance and flow control are called. If link is 5458cfa0ad2SJack F Vogel * not established, we return -E1000_ERR_PHY (-2). This is a function 5468cfa0ad2SJack F Vogel * pointer entry point called by the api module. 5478cfa0ad2SJack F Vogel **/ 5488cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw) 5498cfa0ad2SJack F Vogel { 5508cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 5518cfa0ad2SJack F Vogel struct e1000_dev_spec_82541 *dev_spec; 5528cfa0ad2SJack F Vogel s32 ret_val; 5538cfa0ad2SJack F Vogel u32 ctrl, ledctl; 5548cfa0ad2SJack F Vogel 5558cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_copper_link_82541"); 5568cfa0ad2SJack F Vogel 5578cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 5588cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SLU; 5598cfa0ad2SJack F Vogel ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 5608cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 5618cfa0ad2SJack F Vogel 5628cfa0ad2SJack F Vogel hw->phy.reset_disable = FALSE; 5638cfa0ad2SJack F Vogel 5648cfa0ad2SJack F Vogel dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; 5658cfa0ad2SJack F Vogel 5668cfa0ad2SJack F Vogel /* Earlier revs of the IGP phy require us to force MDI. */ 5678cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) { 5688cfa0ad2SJack F Vogel dev_spec->dsp_config = e1000_dsp_config_disabled; 5698cfa0ad2SJack F Vogel phy->mdix = 1; 5708cfa0ad2SJack F Vogel } else { 5718cfa0ad2SJack F Vogel dev_spec->dsp_config = e1000_dsp_config_enabled; 5728cfa0ad2SJack F Vogel } 5738cfa0ad2SJack F Vogel 5748cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_igp(hw); 5758cfa0ad2SJack F Vogel if (ret_val) 5768cfa0ad2SJack F Vogel goto out; 5778cfa0ad2SJack F Vogel 5788cfa0ad2SJack F Vogel if (hw->mac.autoneg) { 5798cfa0ad2SJack F Vogel if (dev_spec->ffe_config == e1000_ffe_config_active) 5808cfa0ad2SJack F Vogel dev_spec->ffe_config = e1000_ffe_config_enabled; 5818cfa0ad2SJack F Vogel } 5828cfa0ad2SJack F Vogel 5838cfa0ad2SJack F Vogel /* Configure activity LED after Phy reset */ 5848cfa0ad2SJack F Vogel ledctl = E1000_READ_REG(hw, E1000_LEDCTL); 5858cfa0ad2SJack F Vogel ledctl &= IGP_ACTIVITY_LED_MASK; 5868cfa0ad2SJack F Vogel ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); 5878cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); 5888cfa0ad2SJack F Vogel 5898cfa0ad2SJack F Vogel ret_val = e1000_setup_copper_link_generic(hw); 5908cfa0ad2SJack F Vogel 5918cfa0ad2SJack F Vogel out: 5928cfa0ad2SJack F Vogel return ret_val; 5938cfa0ad2SJack F Vogel } 5948cfa0ad2SJack F Vogel 5958cfa0ad2SJack F Vogel /** 5968cfa0ad2SJack F Vogel * e1000_check_for_link_82541 - Check/Store link connection 5978cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5988cfa0ad2SJack F Vogel * 5998cfa0ad2SJack F Vogel * This checks the link condition of the adapter and stores the 6008cfa0ad2SJack F Vogel * results in the hw->mac structure. This is a function pointer entry 6018cfa0ad2SJack F Vogel * point called by the api module. 6028cfa0ad2SJack F Vogel **/ 6038cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82541(struct e1000_hw *hw) 6048cfa0ad2SJack F Vogel { 6058cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 6068cfa0ad2SJack F Vogel s32 ret_val; 6078cfa0ad2SJack F Vogel bool link; 6088cfa0ad2SJack F Vogel 6098cfa0ad2SJack F Vogel DEBUGFUNC("e1000_check_for_link_82541"); 6108cfa0ad2SJack F Vogel 6118cfa0ad2SJack F Vogel /* 6128cfa0ad2SJack F Vogel * We only want to go out to the PHY registers to see if Auto-Neg 6138cfa0ad2SJack F Vogel * has completed and/or if our link status has changed. The 6148cfa0ad2SJack F Vogel * get_link_status flag is set upon receiving a Link Status 6158cfa0ad2SJack F Vogel * Change or Rx Sequence Error interrupt. 6168cfa0ad2SJack F Vogel */ 6178cfa0ad2SJack F Vogel if (!mac->get_link_status) { 6188cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 6198cfa0ad2SJack F Vogel goto out; 6208cfa0ad2SJack F Vogel } 6218cfa0ad2SJack F Vogel 6228cfa0ad2SJack F Vogel /* 6238cfa0ad2SJack F Vogel * First we want to see if the MII Status Register reports 6248cfa0ad2SJack F Vogel * link. If so, then we want to get the current speed/duplex 6258cfa0ad2SJack F Vogel * of the PHY. 6268cfa0ad2SJack F Vogel */ 6278cfa0ad2SJack F Vogel ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); 6288cfa0ad2SJack F Vogel if (ret_val) 6298cfa0ad2SJack F Vogel goto out; 6308cfa0ad2SJack F Vogel 6318cfa0ad2SJack F Vogel if (!link) { 6328cfa0ad2SJack F Vogel ret_val = e1000_config_dsp_after_link_change_82541(hw, FALSE); 6338cfa0ad2SJack F Vogel goto out; /* No link detected */ 6348cfa0ad2SJack F Vogel } 6358cfa0ad2SJack F Vogel 6368cfa0ad2SJack F Vogel mac->get_link_status = FALSE; 6378cfa0ad2SJack F Vogel 6388cfa0ad2SJack F Vogel /* 6398cfa0ad2SJack F Vogel * Check if there was DownShift, must be checked 6408cfa0ad2SJack F Vogel * immediately after link-up 6418cfa0ad2SJack F Vogel */ 6428cfa0ad2SJack F Vogel e1000_check_downshift_generic(hw); 6438cfa0ad2SJack F Vogel 6448cfa0ad2SJack F Vogel /* 6458cfa0ad2SJack F Vogel * If we are forcing speed/duplex, then we simply return since 6468cfa0ad2SJack F Vogel * we have already determined whether we have link or not. 6478cfa0ad2SJack F Vogel */ 6488cfa0ad2SJack F Vogel if (!mac->autoneg) { 6498cfa0ad2SJack F Vogel ret_val = -E1000_ERR_CONFIG; 6508cfa0ad2SJack F Vogel goto out; 6518cfa0ad2SJack F Vogel } 6528cfa0ad2SJack F Vogel 6538cfa0ad2SJack F Vogel ret_val = e1000_config_dsp_after_link_change_82541(hw, TRUE); 6548cfa0ad2SJack F Vogel 6558cfa0ad2SJack F Vogel /* 6568cfa0ad2SJack F Vogel * Auto-Neg is enabled. Auto Speed Detection takes care 6578cfa0ad2SJack F Vogel * of MAC speed/duplex configuration. So we only need to 6588cfa0ad2SJack F Vogel * configure Collision Distance in the MAC. 6598cfa0ad2SJack F Vogel */ 6608cfa0ad2SJack F Vogel e1000_config_collision_dist_generic(hw); 6618cfa0ad2SJack F Vogel 6628cfa0ad2SJack F Vogel /* 6638cfa0ad2SJack F Vogel * Configure Flow Control now that Auto-Neg has completed. 6648cfa0ad2SJack F Vogel * First, we need to restore the desired flow control 6658cfa0ad2SJack F Vogel * settings because we may have had to re-autoneg with a 6668cfa0ad2SJack F Vogel * different link partner. 6678cfa0ad2SJack F Vogel */ 6688cfa0ad2SJack F Vogel ret_val = e1000_config_fc_after_link_up_generic(hw); 6698cfa0ad2SJack F Vogel if (ret_val) { 6708cfa0ad2SJack F Vogel DEBUGOUT("Error configuring flow control\n"); 6718cfa0ad2SJack F Vogel } 6728cfa0ad2SJack F Vogel 6738cfa0ad2SJack F Vogel out: 6748cfa0ad2SJack F Vogel return ret_val; 6758cfa0ad2SJack F Vogel } 6768cfa0ad2SJack F Vogel 6778cfa0ad2SJack F Vogel /** 6788cfa0ad2SJack F Vogel * e1000_config_dsp_after_link_change_82541 - Config DSP after link 6798cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6808cfa0ad2SJack F Vogel * @link_up: boolean flag for link up status 6818cfa0ad2SJack F Vogel * 6828cfa0ad2SJack F Vogel * Return E1000_ERR_PHY when failing to read/write the PHY, else E1000_SUCCESS 6838cfa0ad2SJack F Vogel * at any other case. 6848cfa0ad2SJack F Vogel * 6858cfa0ad2SJack F Vogel * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a 6868cfa0ad2SJack F Vogel * gigabit link is achieved to improve link quality. 6878cfa0ad2SJack F Vogel * This is a function pointer entry point called by the api module. 6888cfa0ad2SJack F Vogel **/ 6898cfa0ad2SJack F Vogel static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, 6908cfa0ad2SJack F Vogel bool link_up) 6918cfa0ad2SJack F Vogel { 6928cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 6938cfa0ad2SJack F Vogel struct e1000_dev_spec_82541 *dev_spec; 6948cfa0ad2SJack F Vogel s32 ret_val; 6958cfa0ad2SJack F Vogel u32 idle_errs = 0; 6968cfa0ad2SJack F Vogel u16 phy_data, phy_saved_data, speed, duplex, i; 6978cfa0ad2SJack F Vogel u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; 6988cfa0ad2SJack F Vogel u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = 6998cfa0ad2SJack F Vogel {IGP01E1000_PHY_AGC_PARAM_A, 7008cfa0ad2SJack F Vogel IGP01E1000_PHY_AGC_PARAM_B, 7018cfa0ad2SJack F Vogel IGP01E1000_PHY_AGC_PARAM_C, 7028cfa0ad2SJack F Vogel IGP01E1000_PHY_AGC_PARAM_D}; 7038cfa0ad2SJack F Vogel 7048cfa0ad2SJack F Vogel DEBUGFUNC("e1000_config_dsp_after_link_change_82541"); 7058cfa0ad2SJack F Vogel 7068cfa0ad2SJack F Vogel dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; 7078cfa0ad2SJack F Vogel 7088cfa0ad2SJack F Vogel if (link_up) { 7098cfa0ad2SJack F Vogel ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex); 7108cfa0ad2SJack F Vogel if (ret_val) { 7118cfa0ad2SJack F Vogel DEBUGOUT("Error getting link speed and duplex\n"); 7128cfa0ad2SJack F Vogel goto out; 7138cfa0ad2SJack F Vogel } 7148cfa0ad2SJack F Vogel 7158cfa0ad2SJack F Vogel if (speed != SPEED_1000) { 7168cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 7178cfa0ad2SJack F Vogel goto out; 7188cfa0ad2SJack F Vogel } 7198cfa0ad2SJack F Vogel 7208cfa0ad2SJack F Vogel ret_val = phy->ops.get_cable_length(hw); 7218cfa0ad2SJack F Vogel if (ret_val) 7228cfa0ad2SJack F Vogel goto out; 7238cfa0ad2SJack F Vogel 7248cfa0ad2SJack F Vogel if ((dev_spec->dsp_config == e1000_dsp_config_enabled) && 7258cfa0ad2SJack F Vogel phy->min_cable_length >= 50) { 7268cfa0ad2SJack F Vogel 7278cfa0ad2SJack F Vogel for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { 7288cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 7298cfa0ad2SJack F Vogel dsp_reg_array[i], 7308cfa0ad2SJack F Vogel &phy_data); 7318cfa0ad2SJack F Vogel if (ret_val) 7328cfa0ad2SJack F Vogel goto out; 7338cfa0ad2SJack F Vogel 7348cfa0ad2SJack F Vogel phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; 7358cfa0ad2SJack F Vogel 7368cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 7378cfa0ad2SJack F Vogel dsp_reg_array[i], 7388cfa0ad2SJack F Vogel phy_data); 7398cfa0ad2SJack F Vogel if (ret_val) 7408cfa0ad2SJack F Vogel goto out; 7418cfa0ad2SJack F Vogel } 7428cfa0ad2SJack F Vogel dev_spec->dsp_config = e1000_dsp_config_activated; 7438cfa0ad2SJack F Vogel } 7448cfa0ad2SJack F Vogel 7458cfa0ad2SJack F Vogel if ((dev_spec->ffe_config != e1000_ffe_config_enabled) || 7468cfa0ad2SJack F Vogel (phy->min_cable_length >= 50)) { 7478cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 7488cfa0ad2SJack F Vogel goto out; 7498cfa0ad2SJack F Vogel } 7508cfa0ad2SJack F Vogel 7518cfa0ad2SJack F Vogel /* clear previous idle error counts */ 7528cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); 7538cfa0ad2SJack F Vogel if (ret_val) 7548cfa0ad2SJack F Vogel goto out; 7558cfa0ad2SJack F Vogel 7568cfa0ad2SJack F Vogel for (i = 0; i < ffe_idle_err_timeout; i++) { 7578cfa0ad2SJack F Vogel usec_delay(1000); 7588cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 7598cfa0ad2SJack F Vogel PHY_1000T_STATUS, 7608cfa0ad2SJack F Vogel &phy_data); 7618cfa0ad2SJack F Vogel if (ret_val) 7628cfa0ad2SJack F Vogel goto out; 7638cfa0ad2SJack F Vogel 7648cfa0ad2SJack F Vogel idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); 7658cfa0ad2SJack F Vogel if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { 7668cfa0ad2SJack F Vogel dev_spec->ffe_config = e1000_ffe_config_active; 7678cfa0ad2SJack F Vogel 7688cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 7698cfa0ad2SJack F Vogel IGP01E1000_PHY_DSP_FFE, 7708cfa0ad2SJack F Vogel IGP01E1000_PHY_DSP_FFE_CM_CP); 7718cfa0ad2SJack F Vogel if (ret_val) 7728cfa0ad2SJack F Vogel goto out; 7738cfa0ad2SJack F Vogel break; 7748cfa0ad2SJack F Vogel } 7758cfa0ad2SJack F Vogel 7768cfa0ad2SJack F Vogel if (idle_errs) 7778cfa0ad2SJack F Vogel ffe_idle_err_timeout = 7788cfa0ad2SJack F Vogel FFE_IDLE_ERR_COUNT_TIMEOUT_100; 7798cfa0ad2SJack F Vogel } 7808cfa0ad2SJack F Vogel } else { 7818cfa0ad2SJack F Vogel if (dev_spec->dsp_config == e1000_dsp_config_activated) { 7828cfa0ad2SJack F Vogel /* 7838cfa0ad2SJack F Vogel * Save off the current value of register 0x2F5B 7848cfa0ad2SJack F Vogel * to be restored at the end of the routines. 7858cfa0ad2SJack F Vogel */ 7868cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 7878cfa0ad2SJack F Vogel 0x2F5B, 7888cfa0ad2SJack F Vogel &phy_saved_data); 7898cfa0ad2SJack F Vogel if (ret_val) 7908cfa0ad2SJack F Vogel goto out; 7918cfa0ad2SJack F Vogel 7928cfa0ad2SJack F Vogel /* Disable the PHY transmitter */ 7938cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003); 7948cfa0ad2SJack F Vogel if (ret_val) 7958cfa0ad2SJack F Vogel goto out; 7968cfa0ad2SJack F Vogel 7978cfa0ad2SJack F Vogel msec_delay_irq(20); 7988cfa0ad2SJack F Vogel 7998cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8008cfa0ad2SJack F Vogel 0x0000, 8018cfa0ad2SJack F Vogel IGP01E1000_IEEE_FORCE_GIG); 8028cfa0ad2SJack F Vogel if (ret_val) 8038cfa0ad2SJack F Vogel goto out; 8048cfa0ad2SJack F Vogel for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { 8058cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 8068cfa0ad2SJack F Vogel dsp_reg_array[i], 8078cfa0ad2SJack F Vogel &phy_data); 8088cfa0ad2SJack F Vogel if (ret_val) 8098cfa0ad2SJack F Vogel goto out; 8108cfa0ad2SJack F Vogel 8118cfa0ad2SJack F Vogel phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; 8128cfa0ad2SJack F Vogel phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; 8138cfa0ad2SJack F Vogel 8148cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8158cfa0ad2SJack F Vogel dsp_reg_array[i], 8168cfa0ad2SJack F Vogel phy_data); 8178cfa0ad2SJack F Vogel if (ret_val) 8188cfa0ad2SJack F Vogel goto out; 8198cfa0ad2SJack F Vogel } 8208cfa0ad2SJack F Vogel 8218cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8228cfa0ad2SJack F Vogel 0x0000, 8238cfa0ad2SJack F Vogel IGP01E1000_IEEE_RESTART_AUTONEG); 8248cfa0ad2SJack F Vogel if (ret_val) 8258cfa0ad2SJack F Vogel goto out; 8268cfa0ad2SJack F Vogel 8278cfa0ad2SJack F Vogel msec_delay_irq(20); 8288cfa0ad2SJack F Vogel 8298cfa0ad2SJack F Vogel /* Now enable the transmitter */ 8308cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8318cfa0ad2SJack F Vogel 0x2F5B, 8328cfa0ad2SJack F Vogel phy_saved_data); 8338cfa0ad2SJack F Vogel if (ret_val) 8348cfa0ad2SJack F Vogel goto out; 8358cfa0ad2SJack F Vogel 8368cfa0ad2SJack F Vogel dev_spec->dsp_config = e1000_dsp_config_enabled; 8378cfa0ad2SJack F Vogel } 8388cfa0ad2SJack F Vogel 8398cfa0ad2SJack F Vogel if (dev_spec->ffe_config != e1000_ffe_config_active) { 8408cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 8418cfa0ad2SJack F Vogel goto out; 8428cfa0ad2SJack F Vogel } 8438cfa0ad2SJack F Vogel 8448cfa0ad2SJack F Vogel /* 8458cfa0ad2SJack F Vogel * Save off the current value of register 0x2F5B 8468cfa0ad2SJack F Vogel * to be restored at the end of the routines. 8478cfa0ad2SJack F Vogel */ 8488cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data); 8498cfa0ad2SJack F Vogel if (ret_val) 8508cfa0ad2SJack F Vogel goto out; 8518cfa0ad2SJack F Vogel 8528cfa0ad2SJack F Vogel /* Disable the PHY transmitter */ 8538cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003); 8548cfa0ad2SJack F Vogel if (ret_val) 8558cfa0ad2SJack F Vogel goto out; 8568cfa0ad2SJack F Vogel 8578cfa0ad2SJack F Vogel msec_delay_irq(20); 8588cfa0ad2SJack F Vogel 8598cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8608cfa0ad2SJack F Vogel 0x0000, 8618cfa0ad2SJack F Vogel IGP01E1000_IEEE_FORCE_GIG); 8628cfa0ad2SJack F Vogel if (ret_val) 8638cfa0ad2SJack F Vogel goto out; 8648cfa0ad2SJack F Vogel 8658cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8668cfa0ad2SJack F Vogel IGP01E1000_PHY_DSP_FFE, 8678cfa0ad2SJack F Vogel IGP01E1000_PHY_DSP_FFE_DEFAULT); 8688cfa0ad2SJack F Vogel if (ret_val) 8698cfa0ad2SJack F Vogel goto out; 8708cfa0ad2SJack F Vogel 8718cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8728cfa0ad2SJack F Vogel 0x0000, 8738cfa0ad2SJack F Vogel IGP01E1000_IEEE_RESTART_AUTONEG); 8748cfa0ad2SJack F Vogel if (ret_val) 8758cfa0ad2SJack F Vogel goto out; 8768cfa0ad2SJack F Vogel 8778cfa0ad2SJack F Vogel msec_delay_irq(20); 8788cfa0ad2SJack F Vogel 8798cfa0ad2SJack F Vogel /* Now enable the transmitter */ 8808cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data); 8818cfa0ad2SJack F Vogel 8828cfa0ad2SJack F Vogel if (ret_val) 8838cfa0ad2SJack F Vogel goto out; 8848cfa0ad2SJack F Vogel 8858cfa0ad2SJack F Vogel dev_spec->ffe_config = e1000_ffe_config_enabled; 8868cfa0ad2SJack F Vogel } 8878cfa0ad2SJack F Vogel 8888cfa0ad2SJack F Vogel out: 8898cfa0ad2SJack F Vogel return ret_val; 8908cfa0ad2SJack F Vogel } 8918cfa0ad2SJack F Vogel 8928cfa0ad2SJack F Vogel /** 8938cfa0ad2SJack F Vogel * e1000_get_cable_length_igp_82541 - Determine cable length for igp PHY 8948cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 8958cfa0ad2SJack F Vogel * 8968cfa0ad2SJack F Vogel * The automatic gain control (agc) normalizes the amplitude of the 8978cfa0ad2SJack F Vogel * received signal, adjusting for the attenuation produced by the 8988cfa0ad2SJack F Vogel * cable. By reading the AGC registers, which represent the 8998cfa0ad2SJack F Vogel * combination of coarse and fine gain value, the value can be put 9008cfa0ad2SJack F Vogel * into a lookup table to obtain the approximate cable length 9018cfa0ad2SJack F Vogel * for each channel. This is a function pointer entry point called by the 9028cfa0ad2SJack F Vogel * api module. 9038cfa0ad2SJack F Vogel **/ 9048cfa0ad2SJack F Vogel static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw) 9058cfa0ad2SJack F Vogel { 9068cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 9078cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 9088cfa0ad2SJack F Vogel u16 i, data; 9098cfa0ad2SJack F Vogel u16 cur_agc_value, agc_value = 0; 9108cfa0ad2SJack F Vogel u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE; 9118cfa0ad2SJack F Vogel u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = 9128cfa0ad2SJack F Vogel {IGP01E1000_PHY_AGC_A, 9138cfa0ad2SJack F Vogel IGP01E1000_PHY_AGC_B, 9148cfa0ad2SJack F Vogel IGP01E1000_PHY_AGC_C, 9158cfa0ad2SJack F Vogel IGP01E1000_PHY_AGC_D}; 9168cfa0ad2SJack F Vogel 9178cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_cable_length_igp_82541"); 9188cfa0ad2SJack F Vogel 9198cfa0ad2SJack F Vogel /* Read the AGC registers for all channels */ 9208cfa0ad2SJack F Vogel for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { 9218cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data); 9228cfa0ad2SJack F Vogel if (ret_val) 9238cfa0ad2SJack F Vogel goto out; 9248cfa0ad2SJack F Vogel 9258cfa0ad2SJack F Vogel cur_agc_value = data >> IGP01E1000_AGC_LENGTH_SHIFT; 9268cfa0ad2SJack F Vogel 9278cfa0ad2SJack F Vogel /* Bounds checking */ 9288cfa0ad2SJack F Vogel if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) || 9298cfa0ad2SJack F Vogel (cur_agc_value == 0)) { 9308cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 9318cfa0ad2SJack F Vogel goto out; 9328cfa0ad2SJack F Vogel } 9338cfa0ad2SJack F Vogel 9348cfa0ad2SJack F Vogel agc_value += cur_agc_value; 9358cfa0ad2SJack F Vogel 9368cfa0ad2SJack F Vogel if (min_agc_value > cur_agc_value) 9378cfa0ad2SJack F Vogel min_agc_value = cur_agc_value; 9388cfa0ad2SJack F Vogel } 9398cfa0ad2SJack F Vogel 9408cfa0ad2SJack F Vogel /* Remove the minimal AGC result for length < 50m */ 9418cfa0ad2SJack F Vogel if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * 50) { 9428cfa0ad2SJack F Vogel agc_value -= min_agc_value; 9438cfa0ad2SJack F Vogel /* Average the three remaining channels for the length. */ 9448cfa0ad2SJack F Vogel agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); 9458cfa0ad2SJack F Vogel } else { 9468cfa0ad2SJack F Vogel /* Average the channels for the length. */ 9478cfa0ad2SJack F Vogel agc_value /= IGP01E1000_PHY_CHANNEL_NUM; 9488cfa0ad2SJack F Vogel } 9498cfa0ad2SJack F Vogel 9508cfa0ad2SJack F Vogel phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] > 9518cfa0ad2SJack F Vogel IGP01E1000_AGC_RANGE) 9528cfa0ad2SJack F Vogel ? (e1000_igp_cable_length_table[agc_value] - 9538cfa0ad2SJack F Vogel IGP01E1000_AGC_RANGE) 9548cfa0ad2SJack F Vogel : 0; 9558cfa0ad2SJack F Vogel phy->max_cable_length = e1000_igp_cable_length_table[agc_value] + 9568cfa0ad2SJack F Vogel IGP01E1000_AGC_RANGE; 9578cfa0ad2SJack F Vogel 9588cfa0ad2SJack F Vogel phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; 9598cfa0ad2SJack F Vogel 9608cfa0ad2SJack F Vogel out: 9618cfa0ad2SJack F Vogel return ret_val; 9628cfa0ad2SJack F Vogel } 9638cfa0ad2SJack F Vogel 9648cfa0ad2SJack F Vogel /** 9658cfa0ad2SJack F Vogel * e1000_set_d3_lplu_state_82541 - Sets low power link up state for D3 9668cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 9678cfa0ad2SJack F Vogel * @active: boolean used to enable/disable lplu 9688cfa0ad2SJack F Vogel * 9698cfa0ad2SJack F Vogel * Success returns 0, Failure returns 1 9708cfa0ad2SJack F Vogel * 9718cfa0ad2SJack F Vogel * The low power link up (lplu) state is set to the power management level D3 9728cfa0ad2SJack F Vogel * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3 9738cfa0ad2SJack F Vogel * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU 9748cfa0ad2SJack F Vogel * is used during Dx states where the power conservation is most important. 9758cfa0ad2SJack F Vogel * During driver activity, SmartSpeed should be enabled so performance is 9768cfa0ad2SJack F Vogel * maintained. This is a function pointer entry point called by the 9778cfa0ad2SJack F Vogel * api module. 9788cfa0ad2SJack F Vogel **/ 9798cfa0ad2SJack F Vogel static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active) 9808cfa0ad2SJack F Vogel { 9818cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 9828cfa0ad2SJack F Vogel s32 ret_val; 9838cfa0ad2SJack F Vogel u16 data; 9848cfa0ad2SJack F Vogel 9858cfa0ad2SJack F Vogel DEBUGFUNC("e1000_set_d3_lplu_state_82541"); 9868cfa0ad2SJack F Vogel 9878cfa0ad2SJack F Vogel switch (hw->mac.type) { 9888cfa0ad2SJack F Vogel case e1000_82541_rev_2: 9898cfa0ad2SJack F Vogel case e1000_82547_rev_2: 9908cfa0ad2SJack F Vogel break; 9918cfa0ad2SJack F Vogel default: 9928cfa0ad2SJack F Vogel ret_val = e1000_set_d3_lplu_state_generic(hw, active); 9938cfa0ad2SJack F Vogel goto out; 9948cfa0ad2SJack F Vogel break; 9958cfa0ad2SJack F Vogel } 9968cfa0ad2SJack F Vogel 9978cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, IGP01E1000_GMII_FIFO, &data); 9988cfa0ad2SJack F Vogel if (ret_val) 9998cfa0ad2SJack F Vogel goto out; 10008cfa0ad2SJack F Vogel 10018cfa0ad2SJack F Vogel if (!active) { 10028cfa0ad2SJack F Vogel data &= ~IGP01E1000_GMII_FLEX_SPD; 10038cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data); 10048cfa0ad2SJack F Vogel if (ret_val) 10058cfa0ad2SJack F Vogel goto out; 10068cfa0ad2SJack F Vogel 10078cfa0ad2SJack F Vogel /* 10088cfa0ad2SJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 10098cfa0ad2SJack F Vogel * during Dx states where the power conservation is most 10108cfa0ad2SJack F Vogel * important. During driver activity we should enable 10118cfa0ad2SJack F Vogel * SmartSpeed, so performance is maintained. 10128cfa0ad2SJack F Vogel */ 10138cfa0ad2SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) { 10148cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 10158cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 10168cfa0ad2SJack F Vogel &data); 10178cfa0ad2SJack F Vogel if (ret_val) 10188cfa0ad2SJack F Vogel goto out; 10198cfa0ad2SJack F Vogel 10208cfa0ad2SJack F Vogel data |= IGP01E1000_PSCFR_SMART_SPEED; 10218cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 10228cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 10238cfa0ad2SJack F Vogel data); 10248cfa0ad2SJack F Vogel if (ret_val) 10258cfa0ad2SJack F Vogel goto out; 10268cfa0ad2SJack F Vogel } else if (phy->smart_speed == e1000_smart_speed_off) { 10278cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 10288cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 10298cfa0ad2SJack F Vogel &data); 10308cfa0ad2SJack F Vogel if (ret_val) 10318cfa0ad2SJack F Vogel goto out; 10328cfa0ad2SJack F Vogel 10338cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 10348cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 10358cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 10368cfa0ad2SJack F Vogel data); 10378cfa0ad2SJack F Vogel if (ret_val) 10388cfa0ad2SJack F Vogel goto out; 10398cfa0ad2SJack F Vogel } 10408cfa0ad2SJack F Vogel } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || 10418cfa0ad2SJack F Vogel (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || 10428cfa0ad2SJack F Vogel (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { 10438cfa0ad2SJack F Vogel data |= IGP01E1000_GMII_FLEX_SPD; 10448cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data); 10458cfa0ad2SJack F Vogel if (ret_val) 10468cfa0ad2SJack F Vogel goto out; 10478cfa0ad2SJack F Vogel 10488cfa0ad2SJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 10498cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 10508cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 10518cfa0ad2SJack F Vogel &data); 10528cfa0ad2SJack F Vogel if (ret_val) 10538cfa0ad2SJack F Vogel goto out; 10548cfa0ad2SJack F Vogel 10558cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 10568cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 10578cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 10588cfa0ad2SJack F Vogel data); 10598cfa0ad2SJack F Vogel } 10608cfa0ad2SJack F Vogel 10618cfa0ad2SJack F Vogel out: 10628cfa0ad2SJack F Vogel return ret_val; 10638cfa0ad2SJack F Vogel } 10648cfa0ad2SJack F Vogel 10658cfa0ad2SJack F Vogel /** 10668cfa0ad2SJack F Vogel * e1000_setup_led_82541 - Configures SW controllable LED 10678cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10688cfa0ad2SJack F Vogel * 10698cfa0ad2SJack F Vogel * This prepares the SW controllable LED for use and saves the current state 10708cfa0ad2SJack F Vogel * of the LED so it can be later restored. This is a function pointer entry 10718cfa0ad2SJack F Vogel * point called by the api module. 10728cfa0ad2SJack F Vogel **/ 10738cfa0ad2SJack F Vogel static s32 e1000_setup_led_82541(struct e1000_hw *hw) 10748cfa0ad2SJack F Vogel { 10758cfa0ad2SJack F Vogel struct e1000_dev_spec_82541 *dev_spec; 10768cfa0ad2SJack F Vogel s32 ret_val; 10778cfa0ad2SJack F Vogel 10788cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_led_82541"); 10798cfa0ad2SJack F Vogel 10808cfa0ad2SJack F Vogel dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; 10818cfa0ad2SJack F Vogel 10828cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, 10838cfa0ad2SJack F Vogel IGP01E1000_GMII_FIFO, 10848cfa0ad2SJack F Vogel &dev_spec->spd_default); 10858cfa0ad2SJack F Vogel if (ret_val) 10868cfa0ad2SJack F Vogel goto out; 10878cfa0ad2SJack F Vogel 10888cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, 10898cfa0ad2SJack F Vogel IGP01E1000_GMII_FIFO, 10908cfa0ad2SJack F Vogel (u16)(dev_spec->spd_default & 10918cfa0ad2SJack F Vogel ~IGP01E1000_GMII_SPD)); 10928cfa0ad2SJack F Vogel if (ret_val) 10938cfa0ad2SJack F Vogel goto out; 10948cfa0ad2SJack F Vogel 10958cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); 10968cfa0ad2SJack F Vogel 10978cfa0ad2SJack F Vogel out: 10988cfa0ad2SJack F Vogel return ret_val; 10998cfa0ad2SJack F Vogel } 11008cfa0ad2SJack F Vogel 11018cfa0ad2SJack F Vogel /** 11028cfa0ad2SJack F Vogel * e1000_cleanup_led_82541 - Set LED config to default operation 11038cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11048cfa0ad2SJack F Vogel * 11058cfa0ad2SJack F Vogel * Remove the current LED configuration and set the LED configuration 11068cfa0ad2SJack F Vogel * to the default value, saved from the EEPROM. This is a function pointer 11078cfa0ad2SJack F Vogel * entry point called by the api module. 11088cfa0ad2SJack F Vogel **/ 11098cfa0ad2SJack F Vogel static s32 e1000_cleanup_led_82541(struct e1000_hw *hw) 11108cfa0ad2SJack F Vogel { 11118cfa0ad2SJack F Vogel struct e1000_dev_spec_82541 *dev_spec; 11128cfa0ad2SJack F Vogel s32 ret_val; 11138cfa0ad2SJack F Vogel 11148cfa0ad2SJack F Vogel DEBUGFUNC("e1000_cleanup_led_82541"); 11158cfa0ad2SJack F Vogel 11168cfa0ad2SJack F Vogel dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; 11178cfa0ad2SJack F Vogel 11188cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, 11198cfa0ad2SJack F Vogel IGP01E1000_GMII_FIFO, 11208cfa0ad2SJack F Vogel dev_spec->spd_default); 11218cfa0ad2SJack F Vogel if (ret_val) 11228cfa0ad2SJack F Vogel goto out; 11238cfa0ad2SJack F Vogel 11248cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); 11258cfa0ad2SJack F Vogel 11268cfa0ad2SJack F Vogel out: 11278cfa0ad2SJack F Vogel return ret_val; 11288cfa0ad2SJack F Vogel } 11298cfa0ad2SJack F Vogel 11308cfa0ad2SJack F Vogel /** 11318cfa0ad2SJack F Vogel * e1000_phy_init_script_82541 - Initialize GbE PHY 11328cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11338cfa0ad2SJack F Vogel * 11348cfa0ad2SJack F Vogel * Initializes the IGP PHY. 11358cfa0ad2SJack F Vogel **/ 11368cfa0ad2SJack F Vogel static s32 e1000_phy_init_script_82541(struct e1000_hw *hw) 11378cfa0ad2SJack F Vogel { 11388cfa0ad2SJack F Vogel struct e1000_dev_spec_82541 *dev_spec; 11398cfa0ad2SJack F Vogel u32 ret_val; 11408cfa0ad2SJack F Vogel u16 phy_saved_data; 11418cfa0ad2SJack F Vogel 11428cfa0ad2SJack F Vogel DEBUGFUNC("e1000_phy_init_script_82541"); 11438cfa0ad2SJack F Vogel 11448cfa0ad2SJack F Vogel dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; 11458cfa0ad2SJack F Vogel 11468cfa0ad2SJack F Vogel if (!dev_spec->phy_init_script) { 11478cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 11488cfa0ad2SJack F Vogel goto out; 11498cfa0ad2SJack F Vogel } 11508cfa0ad2SJack F Vogel 11518cfa0ad2SJack F Vogel /* Delay after phy reset to enable NVM configuration to load */ 11528cfa0ad2SJack F Vogel msec_delay(20); 11538cfa0ad2SJack F Vogel 11548cfa0ad2SJack F Vogel /* 11558cfa0ad2SJack F Vogel * Save off the current value of register 0x2F5B to be restored at 11568cfa0ad2SJack F Vogel * the end of this routine. 11578cfa0ad2SJack F Vogel */ 11588cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data); 11598cfa0ad2SJack F Vogel 11608cfa0ad2SJack F Vogel /* Disabled the PHY transmitter */ 11618cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003); 11628cfa0ad2SJack F Vogel 11638cfa0ad2SJack F Vogel msec_delay(20); 11648cfa0ad2SJack F Vogel 11658cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x0000, 0x0140); 11668cfa0ad2SJack F Vogel 11678cfa0ad2SJack F Vogel msec_delay(5); 11688cfa0ad2SJack F Vogel 11698cfa0ad2SJack F Vogel switch (hw->mac.type) { 11708cfa0ad2SJack F Vogel case e1000_82541: 11718cfa0ad2SJack F Vogel case e1000_82547: 11728cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x1F95, 0x0001); 11738cfa0ad2SJack F Vogel 11748cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21); 11758cfa0ad2SJack F Vogel 11768cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x1F79, 0x0018); 11778cfa0ad2SJack F Vogel 11788cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x1F30, 0x1600); 11798cfa0ad2SJack F Vogel 11808cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x1F31, 0x0014); 11818cfa0ad2SJack F Vogel 11828cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x1F32, 0x161C); 11838cfa0ad2SJack F Vogel 11848cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x1F94, 0x0003); 11858cfa0ad2SJack F Vogel 11868cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x1F96, 0x003F); 11878cfa0ad2SJack F Vogel 11888cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x2010, 0x0008); 11898cfa0ad2SJack F Vogel break; 11908cfa0ad2SJack F Vogel case e1000_82541_rev_2: 11918cfa0ad2SJack F Vogel case e1000_82547_rev_2: 11928cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x1F73, 0x0099); 11938cfa0ad2SJack F Vogel break; 11948cfa0ad2SJack F Vogel default: 11958cfa0ad2SJack F Vogel break; 11968cfa0ad2SJack F Vogel } 11978cfa0ad2SJack F Vogel 11988cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x0000, 0x3300); 11998cfa0ad2SJack F Vogel 12008cfa0ad2SJack F Vogel msec_delay(20); 12018cfa0ad2SJack F Vogel 12028cfa0ad2SJack F Vogel /* Now enable the transmitter */ 12038cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data); 12048cfa0ad2SJack F Vogel 12058cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82547) { 12068cfa0ad2SJack F Vogel u16 fused, fine, coarse; 12078cfa0ad2SJack F Vogel 12088cfa0ad2SJack F Vogel /* Move to analog registers page */ 12098cfa0ad2SJack F Vogel hw->phy.ops.read_reg(hw, 12108cfa0ad2SJack F Vogel IGP01E1000_ANALOG_SPARE_FUSE_STATUS, 12118cfa0ad2SJack F Vogel &fused); 12128cfa0ad2SJack F Vogel 12138cfa0ad2SJack F Vogel if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { 12148cfa0ad2SJack F Vogel hw->phy.ops.read_reg(hw, 12158cfa0ad2SJack F Vogel IGP01E1000_ANALOG_FUSE_STATUS, 12168cfa0ad2SJack F Vogel &fused); 12178cfa0ad2SJack F Vogel 12188cfa0ad2SJack F Vogel fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK; 12198cfa0ad2SJack F Vogel coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK; 12208cfa0ad2SJack F Vogel 12218cfa0ad2SJack F Vogel if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { 12228cfa0ad2SJack F Vogel coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10; 12238cfa0ad2SJack F Vogel fine -= IGP01E1000_ANALOG_FUSE_FINE_1; 12248cfa0ad2SJack F Vogel } else if (coarse == 12258cfa0ad2SJack F Vogel IGP01E1000_ANALOG_FUSE_COARSE_THRESH) 12268cfa0ad2SJack F Vogel fine -= IGP01E1000_ANALOG_FUSE_FINE_10; 12278cfa0ad2SJack F Vogel 12288cfa0ad2SJack F Vogel fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | 12298cfa0ad2SJack F Vogel (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | 12308cfa0ad2SJack F Vogel (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK); 12318cfa0ad2SJack F Vogel 12328cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 12338cfa0ad2SJack F Vogel IGP01E1000_ANALOG_FUSE_CONTROL, 12348cfa0ad2SJack F Vogel fused); 12358cfa0ad2SJack F Vogel hw->phy.ops.write_reg(hw, 12368cfa0ad2SJack F Vogel IGP01E1000_ANALOG_FUSE_BYPASS, 12378cfa0ad2SJack F Vogel IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); 12388cfa0ad2SJack F Vogel } 12398cfa0ad2SJack F Vogel } 12408cfa0ad2SJack F Vogel 12418cfa0ad2SJack F Vogel out: 12428cfa0ad2SJack F Vogel return ret_val; 12438cfa0ad2SJack F Vogel } 12448cfa0ad2SJack F Vogel 12458cfa0ad2SJack F Vogel /** 12468cfa0ad2SJack F Vogel * e1000_init_script_state_82541 - Enable/Disable PHY init script 12478cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 12488cfa0ad2SJack F Vogel * @state: boolean value used to enable/disable PHY init script 12498cfa0ad2SJack F Vogel * 12508cfa0ad2SJack F Vogel * Allows the driver to enable/disable the PHY init script, if the PHY is an 12518cfa0ad2SJack F Vogel * IGP PHY. This is a function pointer entry point called by the api module. 12528cfa0ad2SJack F Vogel **/ 12538cfa0ad2SJack F Vogel void e1000_init_script_state_82541(struct e1000_hw *hw, bool state) 12548cfa0ad2SJack F Vogel { 12558cfa0ad2SJack F Vogel struct e1000_dev_spec_82541 *dev_spec; 12568cfa0ad2SJack F Vogel 12578cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_script_state_82541"); 12588cfa0ad2SJack F Vogel 12598cfa0ad2SJack F Vogel if (hw->phy.type != e1000_phy_igp) { 12608cfa0ad2SJack F Vogel DEBUGOUT("Initialization script not necessary.\n"); 12618cfa0ad2SJack F Vogel goto out; 12628cfa0ad2SJack F Vogel } 12638cfa0ad2SJack F Vogel 12648cfa0ad2SJack F Vogel dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; 12658cfa0ad2SJack F Vogel 12668cfa0ad2SJack F Vogel if (!dev_spec) { 12678cfa0ad2SJack F Vogel DEBUGOUT("dev_spec pointer is set to NULL.\n"); 12688cfa0ad2SJack F Vogel goto out; 12698cfa0ad2SJack F Vogel } 12708cfa0ad2SJack F Vogel 12718cfa0ad2SJack F Vogel dev_spec->phy_init_script = state; 12728cfa0ad2SJack F Vogel 12738cfa0ad2SJack F Vogel out: 12748cfa0ad2SJack F Vogel return; 12758cfa0ad2SJack F Vogel } 12768cfa0ad2SJack F Vogel 12778cfa0ad2SJack F Vogel /** 12788cfa0ad2SJack F Vogel * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down 12798cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 12808cfa0ad2SJack F Vogel * 12818cfa0ad2SJack F Vogel * In the case of a PHY power down to save power, or to turn off link during a 12828cfa0ad2SJack F Vogel * driver unload, or wake on lan is not enabled, remove the link. 12838cfa0ad2SJack F Vogel **/ 12848cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw) 12858cfa0ad2SJack F Vogel { 12868cfa0ad2SJack F Vogel /* If the management interface is not enabled, then power down */ 12878cfa0ad2SJack F Vogel if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN)) 12888cfa0ad2SJack F Vogel e1000_power_down_phy_copper(hw); 12898cfa0ad2SJack F Vogel 12908cfa0ad2SJack F Vogel return; 12918cfa0ad2SJack F Vogel } 12928cfa0ad2SJack F Vogel 12938cfa0ad2SJack F Vogel /** 12948cfa0ad2SJack F Vogel * e1000_clear_hw_cntrs_82541 - Clear device specific hardware counters 12958cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 12968cfa0ad2SJack F Vogel * 12978cfa0ad2SJack F Vogel * Clears the hardware counters by reading the counter registers. 12988cfa0ad2SJack F Vogel **/ 12998cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw) 13008cfa0ad2SJack F Vogel { 13018cfa0ad2SJack F Vogel volatile u32 temp; 13028cfa0ad2SJack F Vogel 13038cfa0ad2SJack F Vogel DEBUGFUNC("e1000_clear_hw_cntrs_82541"); 13048cfa0ad2SJack F Vogel 13058cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_base_generic(hw); 13068cfa0ad2SJack F Vogel 13078cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PRC64); 13088cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PRC127); 13098cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PRC255); 13108cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PRC511); 13118cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PRC1023); 13128cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PRC1522); 13138cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PTC64); 13148cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PTC127); 13158cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PTC255); 13168cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PTC511); 13178cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PTC1023); 13188cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_PTC1522); 13198cfa0ad2SJack F Vogel 13208cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_ALGNERRC); 13218cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_RXERRC); 13228cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_TNCRS); 13238cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_CEXTERR); 13248cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_TSCTC); 13258cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_TSCTFC); 13268cfa0ad2SJack F Vogel 13278cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_MGTPRC); 13288cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_MGTPDC); 13298cfa0ad2SJack F Vogel temp = E1000_READ_REG(hw, E1000_MGTPTC); 13308cfa0ad2SJack F Vogel } 1331