e1000_82541.c revision 190872
161822Sgreen/****************************************************************************** 255992Swpaul 355992Swpaul Copyright (c) 2001-2009, Intel Corporation 455992Swpaul All rights reserved. 555992Swpaul 655992Swpaul Redistribution and use in source and binary forms, with or without 755992Swpaul modification, are permitted provided that the following conditions are met: 855992Swpaul 955992Swpaul 1. Redistributions of source code must retain the above copyright notice, 1055992Swpaul this list of conditions and the following disclaimer. 1155992Swpaul 1255992Swpaul 2. Redistributions in binary form must reproduce the above copyright 1355992Swpaul notice, this list of conditions and the following disclaimer in the 1455992Swpaul documentation and/or other materials provided with the distribution. 1555992Swpaul 1655992Swpaul 3. Neither the name of the Intel Corporation nor the names of its 1755992Swpaul contributors may be used to endorse or promote products derived from 1855992Swpaul this software without specific prior written permission. 1955992Swpaul 2055992Swpaul THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2155992Swpaul AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2255992Swpaul IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2355992Swpaul ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2455992Swpaul LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2555992Swpaul CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2655992Swpaul SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2755992Swpaul INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2855992Swpaul CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2955992Swpaul ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3055992Swpaul POSSIBILITY OF SUCH DAMAGE. 3155992Swpaul 3255992Swpaul******************************************************************************/ 33114601Sobrien/*$FreeBSD: head/sys/dev/e1000/e1000_82541.c 190872 2009-04-10 00:05:46Z jfv $*/ 3481586Sru 3581586Sru/* 3681586Sru * 82541EI Gigabit Ethernet Controller 3781586Sru * 82541ER Gigabit Ethernet Controller 38114601Sobrien * 82541GI Gigabit Ethernet Controller 39114601Sobrien * 82541PI Gigabit Ethernet Controller 40114601Sobrien * 82547EI Gigabit Ethernet Controller 4181586Sru * 82547GI Gigabit Ethernet Controller 4255992Swpaul */ 4355992Swpaul 4455992Swpaul#include "e1000_api.h" 4555992Swpaul 4690868Smikestatic s32 e1000_init_phy_params_82541(struct e1000_hw *hw); 4790868Smikestatic s32 e1000_init_nvm_params_82541(struct e1000_hw *hw); 4855992Swpaulstatic s32 e1000_init_mac_params_82541(struct e1000_hw *hw); 4955992Swpaulstatic s32 e1000_reset_hw_82541(struct e1000_hw *hw); 5055992Swpaulstatic s32 e1000_init_hw_82541(struct e1000_hw *hw); 5155992Swpaulstatic s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed, 5255992Swpaul u16 *duplex); 5355992Swpaulstatic s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw); 5455992Swpaulstatic s32 e1000_setup_copper_link_82541(struct e1000_hw *hw); 5555992Swpaulstatic s32 e1000_check_for_link_82541(struct e1000_hw *hw); 5655992Swpaulstatic s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw); 5755992Swpaulstatic s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, 5855992Swpaul bool active); 5955992Swpaulstatic s32 e1000_setup_led_82541(struct e1000_hw *hw); 6088748Sambriskostatic s32 e1000_cleanup_led_82541(struct e1000_hw *hw); 61108401Sambriskostatic void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw); 6255992Swpaulstatic s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, 63108401Sambrisko bool link_up); 6499800Salfredstatic s32 e1000_phy_init_script_82541(struct e1000_hw *hw); 65132860Snjlstatic void e1000_power_down_phy_copper_82541(struct e1000_hw *hw); 66132860Snjl 6799800Salfredstatic const u16 e1000_igp_cable_length_table[] = 68132860Snjl { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6999800Salfred 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, 7099800Salfred 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, 7199800Salfred 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, 7299800Salfred 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, 7399800Salfred 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 7499800Salfred 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 7599800Salfred 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; 7699800Salfred#define IGP01E1000_AGC_LENGTH_TABLE_SIZE \ 7799800Salfred (sizeof(e1000_igp_cable_length_table) / \ 7899800Salfred sizeof(e1000_igp_cable_length_table[0])) 7999800Salfred 8099800Salfred/** 8155992Swpaul * e1000_init_phy_params_82541 - Init PHY func ptrs. 8299800Salfred * @hw: pointer to the HW structure 8399800Salfred **/ 8455992Swpaulstatic s32 e1000_init_phy_params_82541(struct e1000_hw *hw) 8599800Salfred{ 86132860Snjl struct e1000_phy_info *phy = &hw->phy; 87132860Snjl s32 ret_val = E1000_SUCCESS; 88132860Snjl 89132860Snjl DEBUGFUNC("e1000_init_phy_params_82541"); 90108401Sambrisko 91132860Snjl phy->addr = 1; 9255992Swpaul phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 9355992Swpaul phy->reset_delay_us = 10000; 9455992Swpaul phy->type = e1000_phy_igp; 9555992Swpaul 9655992Swpaul /* Function Pointers */ 9755992Swpaul phy->ops.check_polarity = e1000_check_polarity_igp; 9855992Swpaul phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; 9955992Swpaul phy->ops.get_cable_length = e1000_get_cable_length_igp_82541; 10055992Swpaul phy->ops.get_cfg_done = e1000_get_cfg_done_generic; 101119156Sambrisko phy->ops.get_info = e1000_get_phy_info_igp; 10255992Swpaul phy->ops.read_reg = e1000_read_phy_reg_igp; 10355992Swpaul phy->ops.reset = e1000_phy_hw_reset_82541; 10455992Swpaul phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82541; 10555992Swpaul phy->ops.write_reg = e1000_write_phy_reg_igp; 10655992Swpaul phy->ops.power_up = e1000_power_up_phy_copper; 10755992Swpaul phy->ops.power_down = e1000_power_down_phy_copper_82541; 10855992Swpaul 10955992Swpaul ret_val = e1000_get_phy_id(hw); 11055992Swpaul if (ret_val) 11155992Swpaul goto out; 11255992Swpaul 11355992Swpaul /* Verify phy id */ 11455992Swpaul if (phy->id != IGP01E1000_I_PHY_ID) { 11555992Swpaul ret_val = -E1000_ERR_PHY; 11655992Swpaul goto out; 11755992Swpaul } 11855992Swpaul 11955992Swpaulout: 12055992Swpaul return ret_val; 12155992Swpaul} 12255992Swpaul 12355992Swpaul/** 12455992Swpaul * e1000_init_nvm_params_82541 - Init NVM func ptrs. 12555992Swpaul * @hw: pointer to the HW structure 12668692Swpaul **/ 12768692Swpaulstatic s32 e1000_init_nvm_params_82541(struct e1000_hw *hw) 12868692Swpaul{ 12969772Sarchie struct e1000_nvm_info *nvm = &hw->nvm; 13083269Sbrooks s32 ret_val = E1000_SUCCESS; 13188748Sambrisko u32 eecd = E1000_READ_REG(hw, E1000_EECD); 13268692Swpaul u16 size; 133108401Sambrisko 134108401Sambrisko DEBUGFUNC("e1000_init_nvm_params_82541"); 135132860Snjl 136132860Snjl switch (nvm->override) { 13755992Swpaul case e1000_nvm_override_spi_large: 13855992Swpaul nvm->type = e1000_nvm_eeprom_spi; 139108401Sambrisko eecd |= E1000_EECD_ADDR_BITS; 14055992Swpaul break; 141132900Snjl case e1000_nvm_override_spi_small: 14255992Swpaul nvm->type = e1000_nvm_eeprom_spi; 14361815Sroberto eecd &= ~E1000_EECD_ADDR_BITS; 14455992Swpaul break; 14555992Swpaul case e1000_nvm_override_microwire_large: 14655992Swpaul nvm->type = e1000_nvm_eeprom_microwire; 14755992Swpaul eecd |= E1000_EECD_SIZE; 14855992Swpaul break; 14955992Swpaul case e1000_nvm_override_microwire_small: 15055992Swpaul nvm->type = e1000_nvm_eeprom_microwire; 151108401Sambrisko eecd &= ~E1000_EECD_SIZE; 152108401Sambrisko break; 15355992Swpaul default: 154108401Sambrisko nvm->type = eecd & E1000_EECD_TYPE 15555992Swpaul ? e1000_nvm_eeprom_spi 15655992Swpaul : e1000_nvm_eeprom_microwire; 15755992Swpaul break; 158132860Snjl } 15955992Swpaul 16055992Swpaul if (nvm->type == e1000_nvm_eeprom_spi) { 161132860Snjl nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) 162132860Snjl ? 16 : 8; 16355992Swpaul nvm->delay_usec = 1; 16455992Swpaul nvm->opcode_bits = 8; 16555992Swpaul nvm->page_size = (eecd & E1000_EECD_ADDR_BITS) 16655992Swpaul ? 32 : 8; 167132900Snjl 16855992Swpaul /* Function Pointers */ 16961815Sroberto nvm->ops.acquire = e1000_acquire_nvm_generic; 17055992Swpaul nvm->ops.read = e1000_read_nvm_spi; 17155992Swpaul nvm->ops.release = e1000_release_nvm_generic; 17255992Swpaul nvm->ops.update = e1000_update_nvm_checksum_generic; 17355992Swpaul nvm->ops.valid_led_default = e1000_valid_led_default_generic; 17455992Swpaul nvm->ops.validate = e1000_validate_nvm_checksum_generic; 17555992Swpaul nvm->ops.write = e1000_write_nvm_spi; 17655992Swpaul 17755992Swpaul /* 17855992Swpaul * nvm->word_size must be discovered after the pointers 17955992Swpaul * are set so we can verify the size from the nvm image 18055992Swpaul * itself. Temporarily set it to a dummy value so the 18155992Swpaul * read will work. 18255992Swpaul */ 18355992Swpaul nvm->word_size = 64; 18455992Swpaul ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size); 185132860Snjl if (ret_val) 186132860Snjl goto out; 18755992Swpaul size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT; 18855992Swpaul /* 18955992Swpaul * if size != 0, it can be added to a constant and become 19055992Swpaul * the left-shift value to set the word_size. Otherwise, 19155992Swpaul * word_size stays at 64. 19255992Swpaul */ 19355992Swpaul if (size) { 19455992Swpaul size += NVM_WORD_SIZE_BASE_SHIFT_82541; 19555992Swpaul nvm->word_size = 1 << size; 19655992Swpaul } 19755992Swpaul } else { 198132860Snjl nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) 199132860Snjl ? 8 : 6; 20055992Swpaul nvm->delay_usec = 50; 20155992Swpaul nvm->opcode_bits = 3; 20255992Swpaul nvm->word_size = (eecd & E1000_EECD_ADDR_BITS) 20355992Swpaul ? 256 : 64; 20455992Swpaul 205132860Snjl /* Function Pointers */ 20655992Swpaul nvm->ops.acquire = e1000_acquire_nvm_generic; 20755992Swpaul nvm->ops.read = e1000_read_nvm_microwire; 20855992Swpaul nvm->ops.release = e1000_release_nvm_generic; 209132860Snjl nvm->ops.update = e1000_update_nvm_checksum_generic; 210132860Snjl nvm->ops.valid_led_default = e1000_valid_led_default_generic; 21155992Swpaul nvm->ops.validate = e1000_validate_nvm_checksum_generic; 21255992Swpaul nvm->ops.write = e1000_write_nvm_microwire; 21355992Swpaul } 21455992Swpaul 21555992Swpaulout: 21655992Swpaul return ret_val; 21755992Swpaul} 21855992Swpaul 21955992Swpaul/** 220132860Snjl * e1000_init_mac_params_82541 - Init MAC func ptrs. 221132860Snjl * @hw: pointer to the HW structure 22255992Swpaul **/ 22355992Swpaulstatic s32 e1000_init_mac_params_82541(struct e1000_hw *hw) 22455992Swpaul{ 22555992Swpaul struct e1000_mac_info *mac = &hw->mac; 22655992Swpaul 22755992Swpaul DEBUGFUNC("e1000_init_mac_params_82541"); 22855992Swpaul 229132860Snjl /* Set media type */ 230132860Snjl hw->phy.media_type = e1000_media_type_copper; 23155992Swpaul /* Set mta register count */ 23255992Swpaul mac->mta_reg_count = 128; 23355992Swpaul /* Set rar entry count */ 23455992Swpaul mac->rar_entry_count = E1000_RAR_ENTRIES; 23555992Swpaul /* Set if part includes ASF firmware */ 23655992Swpaul mac->asf_firmware_present = TRUE; 23755992Swpaul 23855992Swpaul /* Function Pointers */ 23955992Swpaul 24055992Swpaul /* bus type/speed/width */ 24155992Swpaul mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; 24255992Swpaul /* function id */ 24355992Swpaul mac->ops.set_lan_id = e1000_set_lan_id_single_port; 24468692Swpaul /* reset */ 24568692Swpaul mac->ops.reset_hw = e1000_reset_hw_82541; 246132860Snjl /* hw initialization */ 247132860Snjl mac->ops.init_hw = e1000_init_hw_82541; 24855992Swpaul /* link setup */ 24955992Swpaul mac->ops.setup_link = e1000_setup_link_generic; 25055992Swpaul /* physical interface link setup */ 251108401Sambrisko mac->ops.setup_physical_interface = e1000_setup_copper_link_82541; 252108401Sambrisko /* check for link */ 25355992Swpaul mac->ops.check_for_link = e1000_check_for_link_82541; 254108401Sambrisko /* link info */ 255108401Sambrisko mac->ops.get_link_up_info = e1000_get_link_up_info_82541; 256108401Sambrisko /* multicast address update */ 257108401Sambrisko mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; 258108401Sambrisko /* writing VFTA */ 259108401Sambrisko mac->ops.write_vfta = e1000_write_vfta_generic; 260108401Sambrisko /* clearing VFTA */ 261108401Sambrisko mac->ops.clear_vfta = e1000_clear_vfta_generic; 262108401Sambrisko /* setting MTA */ 263108401Sambrisko mac->ops.mta_set = e1000_mta_set_generic; 264108401Sambrisko /* ID LED init */ 265108401Sambrisko mac->ops.id_led_init = e1000_id_led_init_generic; 266108401Sambrisko /* setup LED */ 26755992Swpaul mac->ops.setup_led = e1000_setup_led_82541; 26855992Swpaul /* cleanup LED */ 26955992Swpaul mac->ops.cleanup_led = e1000_cleanup_led_82541; 27055992Swpaul /* turn on/off LED */ 27155992Swpaul mac->ops.led_on = e1000_led_on_generic; 27255992Swpaul mac->ops.led_off = e1000_led_off_generic; 27355992Swpaul /* clear hardware counters */ 27455992Swpaul mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541; 27555992Swpaul 27655992Swpaul return E1000_SUCCESS; 27755992Swpaul} 27855992Swpaul 27955992Swpaul/** 28055992Swpaul * e1000_init_function_pointers_82541 - Init func ptrs. 28155992Swpaul * @hw: pointer to the HW structure 28255992Swpaul * 28355992Swpaul * Called to initialize all function pointers and parameters. 28455992Swpaul **/ 28555992Swpaulvoid e1000_init_function_pointers_82541(struct e1000_hw *hw) 28655992Swpaul{ 28788748Sambrisko DEBUGFUNC("e1000_init_function_pointers_82541"); 28888748Sambrisko 28955992Swpaul hw->mac.ops.init_params = e1000_init_mac_params_82541; 29055992Swpaul hw->nvm.ops.init_params = e1000_init_nvm_params_82541; 29155992Swpaul hw->phy.ops.init_params = e1000_init_phy_params_82541; 29255992Swpaul} 29355992Swpaul 294108401Sambrisko/** 295132860Snjl * e1000_reset_hw_82541 - Reset hardware 296108401Sambrisko * @hw: pointer to the HW structure 297108401Sambrisko * 298108401Sambrisko * This resets the hardware into a known state. 299132860Snjl **/ 300108401Sambriskostatic s32 e1000_reset_hw_82541(struct e1000_hw *hw) 301132860Snjl{ 302108401Sambrisko u32 ledctl, ctrl, icr, manc; 303132860Snjl 304108401Sambrisko DEBUGFUNC("e1000_reset_hw_82541"); 305108401Sambrisko 306108401Sambrisko DEBUGOUT("Masking off all interrupts\n"); 307132860Snjl E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); 308108401Sambrisko 309132860Snjl E1000_WRITE_REG(hw, E1000_RCTL, 0); 31078788Sbrooks E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); 31178788Sbrooks E1000_WRITE_FLUSH(hw); 31278788Sbrooks 31378788Sbrooks /* 31478788Sbrooks * Delay to allow any outstanding PCI transactions to complete 31578788Sbrooks * before resetting the device. 31678788Sbrooks */ 31778788Sbrooks msec_delay(10); 31878788Sbrooks 319132860Snjl ctrl = E1000_READ_REG(hw, E1000_CTRL); 32078788Sbrooks 32155992Swpaul /* Must reset the Phy before resetting the MAC */ 32255992Swpaul if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { 32355992Swpaul E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST)); 32455992Swpaul msec_delay(5); 32555992Swpaul } 32655992Swpaul 32755992Swpaul DEBUGOUT("Issuing a global reset to 82541/82547 MAC\n"); 32855992Swpaul switch (hw->mac.type) { 32955992Swpaul case e1000_82541: 33055992Swpaul case e1000_82541_rev_2: 33155992Swpaul /* 33255992Swpaul * These controllers can't ack the 64-bit write when 33355992Swpaul * issuing the reset, so we use IO-mapping as a 33455992Swpaul * workaround to issue the reset. 33555992Swpaul */ 33655992Swpaul E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); 33755992Swpaul break; 33855992Swpaul default: 33955992Swpaul E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); 34055992Swpaul break; 34155992Swpaul } 34255992Swpaul 34355992Swpaul /* Wait for NVM reload */ 34455992Swpaul msec_delay(20); 34555992Swpaul 34655992Swpaul /* Disable HW ARPs on ASF enabled adapters */ 34755992Swpaul manc = E1000_READ_REG(hw, E1000_MANC); 34855992Swpaul manc &= ~E1000_MANC_ARP_EN; 34955992Swpaul E1000_WRITE_REG(hw, E1000_MANC, manc); 35055992Swpaul 351132860Snjl if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { 352132860Snjl e1000_phy_init_script_82541(hw); 35355992Swpaul 35455992Swpaul /* Configure activity LED after Phy reset */ 35555992Swpaul ledctl = E1000_READ_REG(hw, E1000_LEDCTL); 35655992Swpaul ledctl &= IGP_ACTIVITY_LED_MASK; 35755992Swpaul ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); 35855992Swpaul E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); 35955992Swpaul } 36055992Swpaul 36155992Swpaul /* Once again, mask the interrupts */ 36255992Swpaul DEBUGOUT("Masking off all interrupts\n"); 36355992Swpaul E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); 36455992Swpaul 36555992Swpaul /* Clear any pending interrupt events. */ 36655992Swpaul icr = E1000_READ_REG(hw, E1000_ICR); 36755992Swpaul 36855992Swpaul return E1000_SUCCESS; 36955992Swpaul} 37055992Swpaul 37155992Swpaul/** 37255992Swpaul * e1000_init_hw_82541 - Initialize hardware 37355992Swpaul * @hw: pointer to the HW structure 37455992Swpaul * 37555992Swpaul * This inits the hardware readying it for operation. 37655992Swpaul **/ 37755992Swpaulstatic s32 e1000_init_hw_82541(struct e1000_hw *hw) 37855992Swpaul{ 37955992Swpaul struct e1000_mac_info *mac = &hw->mac; 38055992Swpaul u32 i, txdctl; 38155992Swpaul s32 ret_val; 38255992Swpaul 38355992Swpaul DEBUGFUNC("e1000_init_hw_82541"); 38455992Swpaul 38555992Swpaul /* Initialize identification LED */ 38655992Swpaul ret_val = mac->ops.id_led_init(hw); 38755992Swpaul if (ret_val) { 38855992Swpaul DEBUGOUT("Error initializing identification LED\n"); 38955992Swpaul /* This is not fatal and we should not stop init due to this */ 39055992Swpaul } 39155992Swpaul 39255992Swpaul /* Disabling VLAN filtering */ 39355992Swpaul DEBUGOUT("Initializing the IEEE VLAN\n"); 39455992Swpaul mac->ops.clear_vfta(hw); 39555992Swpaul 396108401Sambrisko /* Setup the receive address. */ 397108401Sambrisko e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); 398108401Sambrisko 39955992Swpaul /* Zero out the Multicast HASH table */ 40055992Swpaul DEBUGOUT("Zeroing the MTA\n"); 40155992Swpaul for (i = 0; i < mac->mta_reg_count; i++) { 40255992Swpaul E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); 40355992Swpaul /* 40455992Swpaul * Avoid back to back register writes by adding the register 40555992Swpaul * read (flush). This is to protect against some strange 406108401Sambrisko * bridge configurations that may issue Memory Write Block 407108401Sambrisko * (MWB) to our register space. 408108401Sambrisko */ 40955992Swpaul E1000_WRITE_FLUSH(hw); 410108401Sambrisko } 41155992Swpaul 412108401Sambrisko /* Setup link and flow control */ 41355992Swpaul ret_val = mac->ops.setup_link(hw); 41455992Swpaul 41555992Swpaul txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); 41655992Swpaul txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | 41755992Swpaul E1000_TXDCTL_FULL_TX_DESC_WB; 41855992Swpaul E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); 41955992Swpaul 42055992Swpaul /* 42155992Swpaul * Clear all of the statistics registers (clear on read). It is 42255992Swpaul * important that we do this after we have tried to establish link 42355992Swpaul * because the symbol error count will increment wildly if there 42455992Swpaul * is no link. 42555992Swpaul */ 42655992Swpaul e1000_clear_hw_cntrs_82541(hw); 42755992Swpaul 42855992Swpaul return ret_val; 42955992Swpaul} 43055992Swpaul 43155992Swpaul/** 43255992Swpaul * e1000_get_link_up_info_82541 - Report speed and duplex 43355992Swpaul * @hw: pointer to the HW structure 43455992Swpaul * @speed: pointer to speed buffer 43555992Swpaul * @duplex: pointer to duplex buffer 436132860Snjl * 437132860Snjl * Retrieve the current speed and duplex configuration. 43855992Swpaul **/ 43955992Swpaulstatic s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed, 44055992Swpaul u16 *duplex) 44155992Swpaul{ 44255992Swpaul struct e1000_phy_info *phy = &hw->phy; 44355992Swpaul s32 ret_val; 44455992Swpaul u16 data; 44555992Swpaul 44655992Swpaul DEBUGFUNC("e1000_get_link_up_info_82541"); 447132900Snjl 44855992Swpaul ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); 449132860Snjl if (ret_val) 450132860Snjl goto out; 45155992Swpaul 452132860Snjl if (!phy->speed_downgraded) 45355992Swpaul goto out; 454132860Snjl 45555992Swpaul /* 456132860Snjl * IGP01 PHY may advertise full duplex operation after speed 45755992Swpaul * downgrade even if it is operating at half duplex. 458132860Snjl * Here we set the duplex settings to match the duplex in the 45955992Swpaul * link partner's capabilities. 460132860Snjl */ 46155992Swpaul ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data); 462132860Snjl if (ret_val) 46355992Swpaul goto out; 464132860Snjl 46555992Swpaul if (!(data & NWAY_ER_LP_NWAY_CAPS)) { 466132860Snjl *duplex = HALF_DUPLEX; 46755992Swpaul } else { 468132860Snjl ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data); 46955992Swpaul if (ret_val) 470132860Snjl goto out; 47155992Swpaul 472132860Snjl if (*speed == SPEED_100) { 47355992Swpaul if (!(data & NWAY_LPAR_100TX_FD_CAPS)) 474132860Snjl *duplex = HALF_DUPLEX; 47555992Swpaul } else if (*speed == SPEED_10) { 476132860Snjl if (!(data & NWAY_LPAR_10T_FD_CAPS)) 47755992Swpaul *duplex = HALF_DUPLEX; 478132860Snjl } 47955992Swpaul } 480132860Snjl 48155992Swpaulout: 482132860Snjl return ret_val; 48355992Swpaul} 484132860Snjl 48555992Swpaul/** 486132860Snjl * e1000_phy_hw_reset_82541 - PHY hardware reset 48755992Swpaul * @hw: pointer to the HW structure 488132860Snjl * 48955992Swpaul * Verify the reset block is not blocking us from resetting. Acquire 490132860Snjl * semaphore (if necessary) and read/set/write the device control reset 49155992Swpaul * bit in the PHY. Wait the appropriate delay time for the device to 492132860Snjl * reset and release the semaphore (if necessary). 49355992Swpaul **/ 494132860Snjlstatic s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw) 49555992Swpaul{ 496132860Snjl s32 ret_val; 49755992Swpaul u32 ledctl; 498132860Snjl 49955992Swpaul DEBUGFUNC("e1000_phy_hw_reset_82541"); 500132860Snjl 50155992Swpaul ret_val = e1000_phy_hw_reset_generic(hw); 502132860Snjl if (ret_val) 50355992Swpaul goto out; 504132860Snjl 50555992Swpaul e1000_phy_init_script_82541(hw); 506132860Snjl 50755992Swpaul if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { 508132860Snjl /* Configure activity LED after PHY reset */ 50955992Swpaul ledctl = E1000_READ_REG(hw, E1000_LEDCTL); 510132860Snjl ledctl &= IGP_ACTIVITY_LED_MASK; 51155992Swpaul ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); 512132860Snjl E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); 51355992Swpaul } 514132860Snjl 51555992Swpaulout: 516132860Snjl return ret_val; 51755992Swpaul} 518132860Snjl 51955992Swpaul/** 520132860Snjl * e1000_setup_copper_link_82541 - Configure copper link settings 52155992Swpaul * @hw: pointer to the HW structure 522132860Snjl * 52355992Swpaul * Calls the appropriate function to configure the link for auto-neg or forced 524132860Snjl * speed and duplex. Then we check for link, once link is established calls 52555992Swpaul * to configure collision distance and flow control are called. If link is 526132860Snjl * not established, we return -E1000_ERR_PHY (-2). 52755992Swpaul **/ 528132860Snjlstatic s32 e1000_setup_copper_link_82541(struct e1000_hw *hw) 52955992Swpaul{ 530132860Snjl struct e1000_phy_info *phy = &hw->phy; 53155992Swpaul struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 532132860Snjl s32 ret_val; 53355992Swpaul u32 ctrl, ledctl; 534132860Snjl 53555992Swpaul DEBUGFUNC("e1000_setup_copper_link_82541"); 536132860Snjl 53755992Swpaul ctrl = E1000_READ_REG(hw, E1000_CTRL); 538132860Snjl ctrl |= E1000_CTRL_SLU; 53955992Swpaul ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 540132860Snjl E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 54155992Swpaul 542132860Snjl hw->phy.reset_disable = FALSE; 54355992Swpaul 544132860Snjl /* Earlier revs of the IGP phy require us to force MDI. */ 54555992Swpaul if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) { 546132860Snjl dev_spec->dsp_config = e1000_dsp_config_disabled; 54755992Swpaul phy->mdix = 1; 548132860Snjl } else { 54955992Swpaul dev_spec->dsp_config = e1000_dsp_config_enabled; 550132860Snjl } 55155992Swpaul 552132860Snjl ret_val = e1000_copper_link_setup_igp(hw); 55355992Swpaul if (ret_val) 554132860Snjl goto out; 55555992Swpaul 556132860Snjl if (hw->mac.autoneg) { 55755992Swpaul if (dev_spec->ffe_config == e1000_ffe_config_active) 558132860Snjl dev_spec->ffe_config = e1000_ffe_config_enabled; 55955992Swpaul } 560132860Snjl 56155992Swpaul /* Configure activity LED after Phy reset */ 562132860Snjl ledctl = E1000_READ_REG(hw, E1000_LEDCTL); 56355992Swpaul ledctl &= IGP_ACTIVITY_LED_MASK; 564132860Snjl ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); 56555992Swpaul E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); 566132860Snjl 56755992Swpaul ret_val = e1000_setup_copper_link_generic(hw); 568132860Snjl 56955992Swpaulout: 570132860Snjl return ret_val; 57155992Swpaul} 572132860Snjl 57355992Swpaul/** 574132860Snjl * e1000_check_for_link_82541 - Check/Store link connection 57555992Swpaul * @hw: pointer to the HW structure 576132860Snjl * 577305619Spfg * This checks the link condition of the adapter and stores the 578132860Snjl * results in the hw->mac structure. 579305619Spfg **/ 580132860Snjlstatic s32 e1000_check_for_link_82541(struct e1000_hw *hw) 58155992Swpaul{ 582132860Snjl struct e1000_mac_info *mac = &hw->mac; 58355992Swpaul s32 ret_val; 584132860Snjl bool link; 58555992Swpaul 586132860Snjl DEBUGFUNC("e1000_check_for_link_82541"); 58755992Swpaul 588132860Snjl /* 58955992Swpaul * We only want to go out to the PHY registers to see if Auto-Neg 590132860Snjl * has completed and/or if our link status has changed. The 59155992Swpaul * get_link_status flag is set upon receiving a Link Status 592132860Snjl * Change or Rx Sequence Error interrupt. 59355992Swpaul */ 594132860Snjl if (!mac->get_link_status) { 59555992Swpaul ret_val = E1000_SUCCESS; 59655992Swpaul goto out; 59755992Swpaul } 598132860Snjl 599132860Snjl /* 60055992Swpaul * First we want to see if the MII Status Register reports 60155992Swpaul * link. If so, then we want to get the current speed/duplex 60255992Swpaul * of the PHY. 60355992Swpaul */ 60455992Swpaul ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); 60555992Swpaul if (ret_val) 60655992Swpaul goto out; 60755992Swpaul 60855992Swpaul if (!link) { 60955992Swpaul ret_val = e1000_config_dsp_after_link_change_82541(hw, FALSE); 61055992Swpaul goto out; /* No link detected */ 61155992Swpaul } 61255992Swpaul 61355992Swpaul mac->get_link_status = FALSE; 61455992Swpaul 61555992Swpaul /* 61655992Swpaul * Check if there was DownShift, must be checked 61755992Swpaul * immediately after link-up 61855992Swpaul */ 61955992Swpaul e1000_check_downshift_generic(hw); 62055992Swpaul 62155992Swpaul /* 62255992Swpaul * If we are forcing speed/duplex, then we simply return since 623132860Snjl * we have already determined whether we have link or not. 624132860Snjl */ 62555992Swpaul if (!mac->autoneg) { 626119156Sambrisko ret_val = -E1000_ERR_CONFIG; 62755992Swpaul goto out; 628119156Sambrisko } 62955992Swpaul 63055992Swpaul ret_val = e1000_config_dsp_after_link_change_82541(hw, TRUE); 63155992Swpaul 63255992Swpaul /* 63355992Swpaul * Auto-Neg is enabled. Auto Speed Detection takes care 63455992Swpaul * of MAC speed/duplex configuration. So we only need to 635119156Sambrisko * configure Collision Distance in the MAC. 636119156Sambrisko */ 637132860Snjl e1000_config_collision_dist_generic(hw); 638119156Sambrisko 639119156Sambrisko /* 640119156Sambrisko * Configure Flow Control now that Auto-Neg has completed. 641119156Sambrisko * First, we need to restore the desired flow control 642119156Sambrisko * settings because we may have had to re-autoneg with a 643119156Sambrisko * different link partner. 644119156Sambrisko */ 645119156Sambrisko ret_val = e1000_config_fc_after_link_up_generic(hw); 64655992Swpaul if (ret_val) { 64755992Swpaul DEBUGOUT("Error configuring flow control\n"); 64855992Swpaul } 64955992Swpaul 650132860Snjlout: 651132860Snjl return ret_val; 65255992Swpaul} 65355992Swpaul 65455992Swpaul/** 65580454Sbrooks * e1000_config_dsp_after_link_change_82541 - Config DSP after link 65655992Swpaul * @hw: pointer to the HW structure 65755992Swpaul * @link_up: boolean flag for link up status 65855992Swpaul * 65955992Swpaul * Return E1000_ERR_PHY when failing to read/write the PHY, else E1000_SUCCESS 66055992Swpaul * at any other case. 66155992Swpaul * 66255992Swpaul * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a 66355992Swpaul * gigabit link is achieved to improve link quality. 66455992Swpaul **/ 66555992Swpaulstatic s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, 66655992Swpaul bool link_up) 66755992Swpaul{ 66855992Swpaul struct e1000_phy_info *phy = &hw->phy; 66955992Swpaul struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 67055992Swpaul s32 ret_val; 67155992Swpaul u32 idle_errs = 0; 67255992Swpaul u16 phy_data, phy_saved_data, speed, duplex, i; 67355992Swpaul u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; 67455992Swpaul u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = 67555992Swpaul {IGP01E1000_PHY_AGC_PARAM_A, 67655992Swpaul IGP01E1000_PHY_AGC_PARAM_B, 67755992Swpaul IGP01E1000_PHY_AGC_PARAM_C, 67855992Swpaul IGP01E1000_PHY_AGC_PARAM_D}; 67955992Swpaul 68055992Swpaul DEBUGFUNC("e1000_config_dsp_after_link_change_82541"); 68155992Swpaul 68255992Swpaul if (link_up) { 68355992Swpaul ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex); 68455992Swpaul if (ret_val) { 68555992Swpaul DEBUGOUT("Error getting link speed and duplex\n"); 68655992Swpaul goto out; 68755992Swpaul } 68855992Swpaul 68955992Swpaul if (speed != SPEED_1000) { 69055992Swpaul ret_val = E1000_SUCCESS; 69155992Swpaul goto out; 69255992Swpaul } 69355992Swpaul 69455992Swpaul ret_val = phy->ops.get_cable_length(hw); 69555992Swpaul if (ret_val) 69655992Swpaul goto out; 69755992Swpaul 69855992Swpaul if ((dev_spec->dsp_config == e1000_dsp_config_enabled) && 69955992Swpaul phy->min_cable_length >= 50) { 70055992Swpaul 70155992Swpaul for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { 70255992Swpaul ret_val = phy->ops.read_reg(hw, 70355992Swpaul dsp_reg_array[i], 70455992Swpaul &phy_data); 70555992Swpaul if (ret_val) 70655992Swpaul goto out; 70755992Swpaul 70855992Swpaul phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; 70955992Swpaul 71055992Swpaul ret_val = phy->ops.write_reg(hw, 71155992Swpaul dsp_reg_array[i], 71255992Swpaul phy_data); 71355992Swpaul if (ret_val) 71455992Swpaul goto out; 71555992Swpaul } 71655992Swpaul dev_spec->dsp_config = e1000_dsp_config_activated; 71755992Swpaul } 71855992Swpaul 71955992Swpaul if ((dev_spec->ffe_config != e1000_ffe_config_enabled) || 72055992Swpaul (phy->min_cable_length >= 50)) { 72155992Swpaul ret_val = E1000_SUCCESS; 72255992Swpaul goto out; 72355992Swpaul } 72455992Swpaul 72555992Swpaul /* clear previous idle error counts */ 72655992Swpaul ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); 72755992Swpaul if (ret_val) 72855992Swpaul goto out; 72955992Swpaul 73055992Swpaul for (i = 0; i < ffe_idle_err_timeout; i++) { 73155992Swpaul usec_delay(1000); 73255992Swpaul ret_val = phy->ops.read_reg(hw, 73355992Swpaul PHY_1000T_STATUS, 73455992Swpaul &phy_data); 73555992Swpaul if (ret_val) 73668692Swpaul goto out; 73769772Sarchie 73869772Sarchie idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); 73988748Sambrisko if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { 74088748Sambrisko dev_spec->ffe_config = e1000_ffe_config_active; 74188748Sambrisko 74269772Sarchie ret_val = phy->ops.write_reg(hw, 74369772Sarchie IGP01E1000_PHY_DSP_FFE, 74469772Sarchie IGP01E1000_PHY_DSP_FFE_CM_CP); 74569772Sarchie if (ret_val) 74668692Swpaul goto out; 74768692Swpaul break; 74868692Swpaul } 74955992Swpaul 75068692Swpaul if (idle_errs) 75168692Swpaul ffe_idle_err_timeout = 75268692Swpaul FFE_IDLE_ERR_COUNT_TIMEOUT_100; 75355992Swpaul } 75468692Swpaul } else { 75555992Swpaul if (dev_spec->dsp_config == e1000_dsp_config_activated) { 75655992Swpaul /* 75755992Swpaul * Save off the current value of register 0x2F5B 75855992Swpaul * to be restored at the end of the routines. 75955992Swpaul */ 76055992Swpaul ret_val = phy->ops.read_reg(hw, 76155992Swpaul 0x2F5B, 76255992Swpaul &phy_saved_data); 76355992Swpaul if (ret_val) 76455992Swpaul goto out; 76555992Swpaul 76655992Swpaul /* Disable the PHY transmitter */ 76755992Swpaul ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003); 76855992Swpaul if (ret_val) 76955992Swpaul goto out; 77055992Swpaul 77155992Swpaul msec_delay_irq(20); 77255992Swpaul 77355992Swpaul ret_val = phy->ops.write_reg(hw, 77455992Swpaul 0x0000, 77555992Swpaul IGP01E1000_IEEE_FORCE_GIG); 77655992Swpaul if (ret_val) 77755992Swpaul goto out; 77855992Swpaul for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { 77955992Swpaul ret_val = phy->ops.read_reg(hw, 78055992Swpaul dsp_reg_array[i], 78155992Swpaul &phy_data); 78255992Swpaul if (ret_val) 78355992Swpaul goto out; 78455992Swpaul 78555992Swpaul phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; 78655992Swpaul phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; 78755992Swpaul 78855992Swpaul ret_val = phy->ops.write_reg(hw, 78955992Swpaul dsp_reg_array[i], 79055992Swpaul phy_data); 79155992Swpaul if (ret_val) 79255992Swpaul goto out; 79355992Swpaul } 79455992Swpaul 79555992Swpaul ret_val = phy->ops.write_reg(hw, 79655992Swpaul 0x0000, 79755992Swpaul IGP01E1000_IEEE_RESTART_AUTONEG); 79855992Swpaul if (ret_val) 79955992Swpaul goto out; 80055992Swpaul 80155992Swpaul msec_delay_irq(20); 80255992Swpaul 80355992Swpaul /* Now enable the transmitter */ 80455992Swpaul ret_val = phy->ops.write_reg(hw, 80555992Swpaul 0x2F5B, 80655992Swpaul phy_saved_data); 80755992Swpaul if (ret_val) 80855992Swpaul goto out; 80955992Swpaul 81080454Sbrooks dev_spec->dsp_config = e1000_dsp_config_enabled; 811108401Sambrisko } 812108401Sambrisko 813108401Sambrisko if (dev_spec->ffe_config != e1000_ffe_config_active) { 81455992Swpaul ret_val = E1000_SUCCESS; 81580454Sbrooks goto out; 81655992Swpaul } 81780454Sbrooks 81855992Swpaul /* 81955992Swpaul * Save off the current value of register 0x2F5B 82055992Swpaul * to be restored at the end of the routines. 82180454Sbrooks */ 822108401Sambrisko ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data); 823108401Sambrisko if (ret_val) 824108401Sambrisko goto out; 82555992Swpaul 82680454Sbrooks /* Disable the PHY transmitter */ 82755992Swpaul ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003); 82880454Sbrooks if (ret_val) 82955992Swpaul goto out; 83055992Swpaul 83155992Swpaul msec_delay_irq(20); 83255992Swpaul 83355992Swpaul ret_val = phy->ops.write_reg(hw, 83455992Swpaul 0x0000, 83555992Swpaul IGP01E1000_IEEE_FORCE_GIG); 83655992Swpaul if (ret_val) 83755992Swpaul goto out; 83855992Swpaul 83955992Swpaul ret_val = phy->ops.write_reg(hw, 84055992Swpaul IGP01E1000_PHY_DSP_FFE, 84155992Swpaul IGP01E1000_PHY_DSP_FFE_DEFAULT); 84255992Swpaul if (ret_val) 84388748Sambrisko goto out; 84488748Sambrisko 84588748Sambrisko ret_val = phy->ops.write_reg(hw, 84688748Sambrisko 0x0000, 84788748Sambrisko IGP01E1000_IEEE_RESTART_AUTONEG); 84888748Sambrisko if (ret_val) 84955992Swpaul goto out; 85055992Swpaul 85169772Sarchie msec_delay_irq(20); 85269772Sarchie 85355992Swpaul /* Now enable the transmitter */ 85455992Swpaul ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data); 855132860Snjl 856132860Snjl if (ret_val) 857108401Sambrisko goto out; 858108401Sambrisko 859108401Sambrisko dev_spec->ffe_config = e1000_ffe_config_enabled; 860108401Sambrisko } 86155992Swpaul 862108401Sambriskoout: 863108401Sambrisko return ret_val; 864108401Sambrisko} 865108401Sambrisko 866108401Sambrisko/** 867108401Sambrisko * e1000_get_cable_length_igp_82541 - Determine cable length for igp PHY 868108401Sambrisko * @hw: pointer to the HW structure 869108401Sambrisko * 870108401Sambrisko * The automatic gain control (agc) normalizes the amplitude of the 871108401Sambrisko * received signal, adjusting for the attenuation produced by the 872108401Sambrisko * cable. By reading the AGC registers, which represent the 873108401Sambrisko * combination of coarse and fine gain value, the value can be put 874108401Sambrisko * into a lookup table to obtain the approximate cable length 875108401Sambrisko * for each channel. 876108401Sambrisko **/ 877108401Sambriskostatic s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw) 878108401Sambrisko{ 879108401Sambrisko struct e1000_phy_info *phy = &hw->phy; 880108401Sambrisko s32 ret_val = E1000_SUCCESS; 881108401Sambrisko u16 i, data; 882132860Snjl u16 cur_agc_value, agc_value = 0; 883132860Snjl u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE; 88455992Swpaul u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = 88555992Swpaul {IGP01E1000_PHY_AGC_A, 88655992Swpaul IGP01E1000_PHY_AGC_B, 88755992Swpaul IGP01E1000_PHY_AGC_C, 88855992Swpaul IGP01E1000_PHY_AGC_D}; 88955992Swpaul 89055992Swpaul DEBUGFUNC("e1000_get_cable_length_igp_82541"); 891108401Sambrisko 89289380Sambrisko /* Read the AGC registers for all channels */ 89389380Sambrisko for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { 89489380Sambrisko ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data); 89555992Swpaul if (ret_val) 89655992Swpaul goto out; 89755992Swpaul 89889380Sambrisko cur_agc_value = data >> IGP01E1000_AGC_LENGTH_SHIFT; 89989380Sambrisko 90089380Sambrisko /* Bounds checking */ 90189380Sambrisko if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) || 90255992Swpaul (cur_agc_value == 0)) { 90355992Swpaul ret_val = -E1000_ERR_PHY; 90489380Sambrisko goto out; 90555992Swpaul } 90655992Swpaul 90755992Swpaul agc_value += cur_agc_value; 90855992Swpaul 90955992Swpaul if (min_agc_value > cur_agc_value) 91083269Sbrooks min_agc_value = cur_agc_value; 91188748Sambrisko } 91255992Swpaul 91355992Swpaul /* Remove the minimal AGC result for length < 50m */ 91455992Swpaul if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * 50) { 91555992Swpaul agc_value -= min_agc_value; 91655992Swpaul /* Average the three remaining channels for the length. */ 91755992Swpaul agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); 91855992Swpaul } else { 91955992Swpaul /* Average the channels for the length. */ 92055992Swpaul agc_value /= IGP01E1000_PHY_CHANNEL_NUM; 92155992Swpaul } 922132860Snjl 923132860Snjl phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] > 92455992Swpaul IGP01E1000_AGC_RANGE) 92555992Swpaul ? (e1000_igp_cable_length_table[agc_value] - 92655992Swpaul IGP01E1000_AGC_RANGE) 92755992Swpaul : 0; 92855992Swpaul phy->max_cable_length = e1000_igp_cable_length_table[agc_value] + 92955992Swpaul IGP01E1000_AGC_RANGE; 93055992Swpaul 93155992Swpaul phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; 93255992Swpaul 93355992Swpaulout: 93455992Swpaul return ret_val; 93555992Swpaul} 93655992Swpaul 93755992Swpaul/** 93855992Swpaul * e1000_set_d3_lplu_state_82541 - Sets low power link up state for D3 93955992Swpaul * @hw: pointer to the HW structure 94055992Swpaul * @active: boolean used to enable/disable lplu 94155992Swpaul * 94255992Swpaul * Success returns 0, Failure returns 1 94355992Swpaul * 94455992Swpaul * The low power link up (lplu) state is set to the power management level D3 94555992Swpaul * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3 94655992Swpaul * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU 94755992Swpaul * is used during Dx states where the power conservation is most important. 94855992Swpaul * During driver activity, SmartSpeed should be enabled so performance is 94955992Swpaul * maintained. 95055992Swpaul **/ 95155992Swpaulstatic s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active) 95255992Swpaul{ 95355992Swpaul struct e1000_phy_info *phy = &hw->phy; 95455992Swpaul s32 ret_val; 95555992Swpaul u16 data; 95655992Swpaul 95755992Swpaul DEBUGFUNC("e1000_set_d3_lplu_state_82541"); 95855992Swpaul 95955992Swpaul switch (hw->mac.type) { 96055992Swpaul case e1000_82541_rev_2: 96155992Swpaul case e1000_82547_rev_2: 96255992Swpaul break; 96355992Swpaul default: 96455992Swpaul ret_val = e1000_set_d3_lplu_state_generic(hw, active); 96555992Swpaul goto out; 96655992Swpaul break; 96755992Swpaul } 96855992Swpaul 96955992Swpaul ret_val = phy->ops.read_reg(hw, IGP01E1000_GMII_FIFO, &data); 97055992Swpaul if (ret_val) 97155992Swpaul goto out; 972132860Snjl 97355992Swpaul if (!active) { 97455992Swpaul data &= ~IGP01E1000_GMII_FLEX_SPD; 975108401Sambrisko ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data); 976108401Sambrisko if (ret_val) 977108401Sambrisko goto out; 978108401Sambrisko 97955992Swpaul /* 98055992Swpaul * LPLU and SmartSpeed are mutually exclusive. LPLU is used 98155992Swpaul * during Dx states where the power conservation is most 98255992Swpaul * important. During driver activity we should enable 98355992Swpaul * SmartSpeed, so performance is maintained. 98455992Swpaul */ 98555992Swpaul if (phy->smart_speed == e1000_smart_speed_on) { 98655992Swpaul ret_val = phy->ops.read_reg(hw, 98755992Swpaul IGP01E1000_PHY_PORT_CONFIG, 98855992Swpaul &data); 98955992Swpaul if (ret_val) 99055992Swpaul goto out; 99155992Swpaul 99255992Swpaul data |= IGP01E1000_PSCFR_SMART_SPEED; 99355992Swpaul ret_val = phy->ops.write_reg(hw, 99455992Swpaul IGP01E1000_PHY_PORT_CONFIG, 99555992Swpaul data); 99655992Swpaul if (ret_val) 99755992Swpaul goto out; 99855992Swpaul } else if (phy->smart_speed == e1000_smart_speed_off) { 99955992Swpaul ret_val = phy->ops.read_reg(hw, 100055992Swpaul IGP01E1000_PHY_PORT_CONFIG, 100155992Swpaul &data); 100255992Swpaul if (ret_val) 100355992Swpaul goto out; 100455992Swpaul 100555992Swpaul data &= ~IGP01E1000_PSCFR_SMART_SPEED; 100655992Swpaul ret_val = phy->ops.write_reg(hw, 100755992Swpaul IGP01E1000_PHY_PORT_CONFIG, 100855992Swpaul data); 100955992Swpaul if (ret_val) 101055992Swpaul goto out; 101155992Swpaul } 101255992Swpaul } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || 101355992Swpaul (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || 101455992Swpaul (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { 101555992Swpaul data |= IGP01E1000_GMII_FLEX_SPD; 101655992Swpaul ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data); 101755992Swpaul if (ret_val) 101855992Swpaul goto out; 101955992Swpaul 102055992Swpaul /* When LPLU is enabled, we should disable SmartSpeed */ 102155992Swpaul ret_val = phy->ops.read_reg(hw, 1022132900Snjl IGP01E1000_PHY_PORT_CONFIG, 102355992Swpaul &data); 102468692Swpaul if (ret_val) 102569772Sarchie goto out; 102669772Sarchie 102769772Sarchie data &= ~IGP01E1000_PSCFR_SMART_SPEED; 102869772Sarchie ret_val = phy->ops.write_reg(hw, 102988748Sambrisko IGP01E1000_PHY_PORT_CONFIG, 103088748Sambrisko data); 103169772Sarchie } 103269772Sarchie 103369772Sarchieout: 103469772Sarchie return ret_val; 103569772Sarchie} 103688748Sambrisko 103769772Sarchie/** 103869772Sarchie * e1000_setup_led_82541 - Configures SW controllable LED 103969772Sarchie * @hw: pointer to the HW structure 104069772Sarchie * 104169772Sarchie * This prepares the SW controllable LED for use and saves the current state 104269772Sarchie * of the LED so it can be later restored. 104369772Sarchie **/ 104468692Swpaulstatic s32 e1000_setup_led_82541(struct e1000_hw *hw) 104568692Swpaul{ 104668692Swpaul struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 104768692Swpaul s32 ret_val; 104868692Swpaul 104983269Sbrooks DEBUGFUNC("e1000_setup_led_82541"); 105083269Sbrooks 105183269Sbrooks ret_val = hw->phy.ops.read_reg(hw, 105283269Sbrooks IGP01E1000_GMII_FIFO, 105355992Swpaul &dev_spec->spd_default); 105455992Swpaul if (ret_val) 105555992Swpaul goto out; 105655992Swpaul 105755992Swpaul ret_val = hw->phy.ops.write_reg(hw, 105855992Swpaul IGP01E1000_GMII_FIFO, 105955992Swpaul (u16)(dev_spec->spd_default & 106055992Swpaul ~IGP01E1000_GMII_SPD)); 106155992Swpaul if (ret_val) 1062132860Snjl goto out; 1063132860Snjl 106455992Swpaul E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); 106555992Swpaul 106655992Swpaulout: 106755992Swpaul return ret_val; 106855992Swpaul} 106955992Swpaul 107055992Swpaul/** 107155992Swpaul * e1000_cleanup_led_82541 - Set LED config to default operation 107255992Swpaul * @hw: pointer to the HW structure 107355992Swpaul * 107455992Swpaul * Remove the current LED configuration and set the LED configuration 107555992Swpaul * to the default value, saved from the EEPROM. 107655992Swpaul **/ 107755992Swpaulstatic s32 e1000_cleanup_led_82541(struct e1000_hw *hw) 107855992Swpaul{ 107955992Swpaul struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 108055992Swpaul s32 ret_val; 108155992Swpaul 108255992Swpaul DEBUGFUNC("e1000_cleanup_led_82541"); 108355992Swpaul 108455992Swpaul ret_val = hw->phy.ops.write_reg(hw, 108555992Swpaul IGP01E1000_GMII_FIFO, 108655992Swpaul dev_spec->spd_default); 108755992Swpaul if (ret_val) 108855992Swpaul goto out; 108955992Swpaul 109055992Swpaul E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); 109155992Swpaul 109255992Swpaulout: 109355992Swpaul return ret_val; 109455992Swpaul} 109555992Swpaul 109655992Swpaul/** 109755992Swpaul * e1000_phy_init_script_82541 - Initialize GbE PHY 109855992Swpaul * @hw: pointer to the HW structure 109955992Swpaul * 110055992Swpaul * Initializes the IGP PHY. 110155992Swpaul **/ 110255992Swpaulstatic s32 e1000_phy_init_script_82541(struct e1000_hw *hw) 110355992Swpaul{ 110455992Swpaul struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 110555992Swpaul u32 ret_val; 110655992Swpaul u16 phy_saved_data; 110755992Swpaul 1108132860Snjl DEBUGFUNC("e1000_phy_init_script_82541"); 1109132860Snjl 111055992Swpaul if (!dev_spec->phy_init_script) { 111155992Swpaul ret_val = E1000_SUCCESS; 111255992Swpaul goto out; 111355992Swpaul } 111455992Swpaul 111555992Swpaul /* Delay after phy reset to enable NVM configuration to load */ 111655992Swpaul msec_delay(20); 111755992Swpaul 111855992Swpaul /* 111955992Swpaul * Save off the current value of register 0x2F5B to be restored at 112055992Swpaul * the end of this routine. 112155992Swpaul */ 112255992Swpaul ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data); 112355992Swpaul 112455992Swpaul /* Disabled the PHY transmitter */ 112555992Swpaul hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003); 112655992Swpaul 112755992Swpaul msec_delay(20); 112855992Swpaul 1129132900Snjl hw->phy.ops.write_reg(hw, 0x0000, 0x0140); 113055992Swpaul 113155992Swpaul msec_delay(5); 113255992Swpaul 1133132900Snjl switch (hw->mac.type) { 113455992Swpaul case e1000_82541: 113555992Swpaul case e1000_82547: 113655992Swpaul hw->phy.ops.write_reg(hw, 0x1F95, 0x0001); 1137132900Snjl 113855992Swpaul hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21); 113955992Swpaul 114055992Swpaul hw->phy.ops.write_reg(hw, 0x1F79, 0x0018); 1141132900Snjl 114255992Swpaul hw->phy.ops.write_reg(hw, 0x1F30, 0x1600); 114355992Swpaul 114455992Swpaul hw->phy.ops.write_reg(hw, 0x1F31, 0x0014); 114555992Swpaul 114655992Swpaul hw->phy.ops.write_reg(hw, 0x1F32, 0x161C); 114755992Swpaul 114855992Swpaul hw->phy.ops.write_reg(hw, 0x1F94, 0x0003); 114955992Swpaul 115055992Swpaul hw->phy.ops.write_reg(hw, 0x1F96, 0x003F); 115155992Swpaul 1152132860Snjl hw->phy.ops.write_reg(hw, 0x2010, 0x0008); 1153132860Snjl break; 115455992Swpaul case e1000_82541_rev_2: 1155119156Sambrisko case e1000_82547_rev_2: 115655992Swpaul hw->phy.ops.write_reg(hw, 0x1F73, 0x0099); 1157119156Sambrisko break; 115855992Swpaul default: 115955992Swpaul break; 116055992Swpaul } 116155992Swpaul 116255992Swpaul hw->phy.ops.write_reg(hw, 0x0000, 0x3300); 1163119156Sambrisko 116455992Swpaul msec_delay(20); 1165119156Sambrisko 1166119156Sambrisko /* Now enable the transmitter */ 1167132860Snjl hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data); 1168119156Sambrisko 1169119156Sambrisko if (hw->mac.type == e1000_82547) { 117055992Swpaul u16 fused, fine, coarse; 117155992Swpaul 1172119156Sambrisko /* Move to analog registers page */ 1173119156Sambrisko hw->phy.ops.read_reg(hw, 1174119156Sambrisko IGP01E1000_ANALOG_SPARE_FUSE_STATUS, 1175119156Sambrisko &fused); 1176119156Sambrisko 1177119156Sambrisko if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { 1178119156Sambrisko hw->phy.ops.read_reg(hw, 1179119156Sambrisko IGP01E1000_ANALOG_FUSE_STATUS, 1180119156Sambrisko &fused); 1181119156Sambrisko 1182119156Sambrisko fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK; 1183119156Sambrisko coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK; 1184119156Sambrisko 118555992Swpaul if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { 1186119156Sambrisko coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10; 118755992Swpaul fine -= IGP01E1000_ANALOG_FUSE_FINE_1; 118855992Swpaul } else if (coarse == 118955992Swpaul IGP01E1000_ANALOG_FUSE_COARSE_THRESH) 119055992Swpaul fine -= IGP01E1000_ANALOG_FUSE_FINE_10; 1191132860Snjl 1192132860Snjl fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | 119355992Swpaul (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | 119455992Swpaul (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK); 119555992Swpaul 1196132900Snjl hw->phy.ops.write_reg(hw, 119755992Swpaul IGP01E1000_ANALOG_FUSE_CONTROL, 119855992Swpaul fused); 119955992Swpaul hw->phy.ops.write_reg(hw, 120055992Swpaul IGP01E1000_ANALOG_FUSE_BYPASS, 120155992Swpaul IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); 120255992Swpaul } 1203132860Snjl } 1204132860Snjl 120555992Swpaulout: 120655992Swpaul return ret_val; 1207132900Snjl} 120855992Swpaul 120955992Swpaul/** 121055992Swpaul * e1000_init_script_state_82541 - Enable/Disable PHY init script 121155992Swpaul * @hw: pointer to the HW structure 121255992Swpaul * @state: boolean value used to enable/disable PHY init script 121355992Swpaul * 1214132900Snjl * Allows the driver to enable/disable the PHY init script, if the PHY is an 121555992Swpaul * IGP PHY. 121655992Swpaul **/ 121755992Swpaulvoid e1000_init_script_state_82541(struct e1000_hw *hw, bool state) 121855992Swpaul{ 121955992Swpaul struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 1220132900Snjl 1221132900Snjl DEBUGFUNC("e1000_init_script_state_82541"); 122255992Swpaul 122355992Swpaul if (hw->phy.type != e1000_phy_igp) { 122455992Swpaul DEBUGOUT("Initialization script not necessary.\n"); 122555992Swpaul goto out; 122655992Swpaul } 122755992Swpaul 122855992Swpaul dev_spec->phy_init_script = state; 122955992Swpaul 123055992Swpaulout: 123155992Swpaul return; 123255992Swpaul} 123355992Swpaul 123455992Swpaul/** 123555992Swpaul * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down 123655992Swpaul * @hw: pointer to the HW structure 123755992Swpaul * 123855992Swpaul * In the case of a PHY power down to save power, or to turn off link during a 123955992Swpaul * driver unload, or wake on lan is not enabled, remove the link. 124055992Swpaul **/ 124155992Swpaulstatic void e1000_power_down_phy_copper_82541(struct e1000_hw *hw) 124255992Swpaul{ 124355992Swpaul /* If the management interface is not enabled, then power down */ 124455992Swpaul if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN)) 1245132860Snjl e1000_power_down_phy_copper(hw); 1246132860Snjl 124768692Swpaul return; 124868692Swpaul} 124968692Swpaul 125068692Swpaul/** 125168692Swpaul * e1000_clear_hw_cntrs_82541 - Clear device specific hardware counters 125268692Swpaul * @hw: pointer to the HW structure 125368692Swpaul * 125455992Swpaul * Clears the hardware counters by reading the counter registers. 125568692Swpaul **/ 125668692Swpaulstatic void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw) 125768692Swpaul{ 1258132860Snjl DEBUGFUNC("e1000_clear_hw_cntrs_82541"); 1259132860Snjl 126068692Swpaul e1000_clear_hw_cntrs_base_generic(hw); 126168692Swpaul 126268692Swpaul E1000_READ_REG(hw, E1000_PRC64); 126368692Swpaul E1000_READ_REG(hw, E1000_PRC127); 126468692Swpaul E1000_READ_REG(hw, E1000_PRC255); 126568692Swpaul E1000_READ_REG(hw, E1000_PRC511); 126668692Swpaul E1000_READ_REG(hw, E1000_PRC1023); 126768692Swpaul E1000_READ_REG(hw, E1000_PRC1522); 126868692Swpaul E1000_READ_REG(hw, E1000_PTC64); 126980454Sbrooks E1000_READ_REG(hw, E1000_PTC127); 127068692Swpaul E1000_READ_REG(hw, E1000_PTC255); 127168692Swpaul E1000_READ_REG(hw, E1000_PTC511); 127268692Swpaul E1000_READ_REG(hw, E1000_PTC1023); 127380454Sbrooks E1000_READ_REG(hw, E1000_PTC1522); 127480454Sbrooks 127568692Swpaul E1000_READ_REG(hw, E1000_ALGNERRC); 127668692Swpaul E1000_READ_REG(hw, E1000_RXERRC); 127768692Swpaul E1000_READ_REG(hw, E1000_TNCRS); 127868692Swpaul E1000_READ_REG(hw, E1000_CEXTERR); 127968692Swpaul E1000_READ_REG(hw, E1000_TSCTC); 128068692Swpaul E1000_READ_REG(hw, E1000_TSCTFC); 128168692Swpaul 128268692Swpaul E1000_READ_REG(hw, E1000_MGTPRC); 128368692Swpaul E1000_READ_REG(hw, E1000_MGTPDC); 128468692Swpaul E1000_READ_REG(hw, E1000_MGTPTC); 1285132860Snjl} 1286132860Snjl