175eba5b6SRobert Mustacchi /******************************************************************************
275eba5b6SRobert Mustacchi
3*42cc51e0SRobert Mustacchi Copyright (c) 2001-2015, Intel Corporation
475eba5b6SRobert Mustacchi All rights reserved.
575eba5b6SRobert Mustacchi
675eba5b6SRobert Mustacchi Redistribution and use in source and binary forms, with or without
775eba5b6SRobert Mustacchi modification, are permitted provided that the following conditions are met:
875eba5b6SRobert Mustacchi
975eba5b6SRobert Mustacchi 1. Redistributions of source code must retain the above copyright notice,
1075eba5b6SRobert Mustacchi this list of conditions and the following disclaimer.
1175eba5b6SRobert Mustacchi
1275eba5b6SRobert Mustacchi 2. Redistributions in binary form must reproduce the above copyright
1375eba5b6SRobert Mustacchi notice, this list of conditions and the following disclaimer in the
1475eba5b6SRobert Mustacchi documentation and/or other materials provided with the distribution.
1575eba5b6SRobert Mustacchi
1675eba5b6SRobert Mustacchi 3. Neither the name of the Intel Corporation nor the names of its
1775eba5b6SRobert Mustacchi contributors may be used to endorse or promote products derived from
1875eba5b6SRobert Mustacchi this software without specific prior written permission.
1975eba5b6SRobert Mustacchi
2075eba5b6SRobert Mustacchi THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2175eba5b6SRobert Mustacchi AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2275eba5b6SRobert Mustacchi IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2375eba5b6SRobert Mustacchi ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2475eba5b6SRobert Mustacchi LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2575eba5b6SRobert Mustacchi CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2675eba5b6SRobert Mustacchi SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2775eba5b6SRobert Mustacchi INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2875eba5b6SRobert Mustacchi CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2975eba5b6SRobert Mustacchi ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3075eba5b6SRobert Mustacchi POSSIBILITY OF SUCH DAMAGE.
3175eba5b6SRobert Mustacchi
3275eba5b6SRobert Mustacchi ******************************************************************************/
3375eba5b6SRobert Mustacchi /*$FreeBSD$*/
3475eba5b6SRobert Mustacchi
3575eba5b6SRobert Mustacchi /*
3675eba5b6SRobert Mustacchi * 82541EI Gigabit Ethernet Controller
3775eba5b6SRobert Mustacchi * 82541ER Gigabit Ethernet Controller
3875eba5b6SRobert Mustacchi * 82541GI Gigabit Ethernet Controller
3975eba5b6SRobert Mustacchi * 82541PI Gigabit Ethernet Controller
4075eba5b6SRobert Mustacchi * 82547EI Gigabit Ethernet Controller
4175eba5b6SRobert Mustacchi * 82547GI Gigabit Ethernet Controller
4275eba5b6SRobert Mustacchi */
4375eba5b6SRobert Mustacchi
4475eba5b6SRobert Mustacchi #include "e1000_api.h"
4575eba5b6SRobert Mustacchi
4675eba5b6SRobert Mustacchi static s32 e1000_init_phy_params_82541(struct e1000_hw *hw);
4775eba5b6SRobert Mustacchi static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw);
4875eba5b6SRobert Mustacchi static s32 e1000_init_mac_params_82541(struct e1000_hw *hw);
4975eba5b6SRobert Mustacchi static s32 e1000_reset_hw_82541(struct e1000_hw *hw);
5075eba5b6SRobert Mustacchi static s32 e1000_init_hw_82541(struct e1000_hw *hw);
5175eba5b6SRobert Mustacchi static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
5275eba5b6SRobert Mustacchi u16 *duplex);
5375eba5b6SRobert Mustacchi static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw);
5475eba5b6SRobert Mustacchi static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw);
5575eba5b6SRobert Mustacchi static s32 e1000_check_for_link_82541(struct e1000_hw *hw);
5675eba5b6SRobert Mustacchi static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw);
5775eba5b6SRobert Mustacchi static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw,
5875eba5b6SRobert Mustacchi bool active);
5975eba5b6SRobert Mustacchi static s32 e1000_setup_led_82541(struct e1000_hw *hw);
6075eba5b6SRobert Mustacchi static s32 e1000_cleanup_led_82541(struct e1000_hw *hw);
6175eba5b6SRobert Mustacchi static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw);
6275eba5b6SRobert Mustacchi static s32 e1000_read_mac_addr_82541(struct e1000_hw *hw);
6375eba5b6SRobert Mustacchi static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
6475eba5b6SRobert Mustacchi bool link_up);
6575eba5b6SRobert Mustacchi static s32 e1000_phy_init_script_82541(struct e1000_hw *hw);
6675eba5b6SRobert Mustacchi static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw);
6775eba5b6SRobert Mustacchi
68*42cc51e0SRobert Mustacchi static const u16 e1000_igp_cable_length_table[] = {
69*42cc51e0SRobert Mustacchi 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10,
70*42cc51e0SRobert Mustacchi 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30,
71*42cc51e0SRobert Mustacchi 40, 40, 40, 40, 40, 40, 40, 40, 40, 50, 50, 50, 50, 50, 50, 50, 60, 60,
72*42cc51e0SRobert Mustacchi 60, 60, 60, 60, 60, 60, 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80,
73*42cc51e0SRobert Mustacchi 80, 90, 90, 90, 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100,
74*42cc51e0SRobert Mustacchi 100, 100, 100, 100, 100, 100, 100, 100, 110, 110, 110, 110, 110, 110,
75*42cc51e0SRobert Mustacchi 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 120, 120,
76*42cc51e0SRobert Mustacchi 120, 120, 120, 120, 120, 120, 120, 120};
7775eba5b6SRobert Mustacchi #define IGP01E1000_AGC_LENGTH_TABLE_SIZE \
7875eba5b6SRobert Mustacchi (sizeof(e1000_igp_cable_length_table) / \
7975eba5b6SRobert Mustacchi sizeof(e1000_igp_cable_length_table[0]))
8075eba5b6SRobert Mustacchi
8175eba5b6SRobert Mustacchi /**
8275eba5b6SRobert Mustacchi * e1000_init_phy_params_82541 - Init PHY func ptrs.
8375eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
8475eba5b6SRobert Mustacchi **/
e1000_init_phy_params_82541(struct e1000_hw * hw)8575eba5b6SRobert Mustacchi static s32 e1000_init_phy_params_82541(struct e1000_hw *hw)
8675eba5b6SRobert Mustacchi {
8775eba5b6SRobert Mustacchi struct e1000_phy_info *phy = &hw->phy;
88*42cc51e0SRobert Mustacchi s32 ret_val;
8975eba5b6SRobert Mustacchi
9075eba5b6SRobert Mustacchi DEBUGFUNC("e1000_init_phy_params_82541");
9175eba5b6SRobert Mustacchi
9275eba5b6SRobert Mustacchi phy->addr = 1;
9375eba5b6SRobert Mustacchi phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
9475eba5b6SRobert Mustacchi phy->reset_delay_us = 10000;
9575eba5b6SRobert Mustacchi phy->type = e1000_phy_igp;
9675eba5b6SRobert Mustacchi
9775eba5b6SRobert Mustacchi /* Function Pointers */
9875eba5b6SRobert Mustacchi phy->ops.check_polarity = e1000_check_polarity_igp;
9975eba5b6SRobert Mustacchi phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
10075eba5b6SRobert Mustacchi phy->ops.get_cable_length = e1000_get_cable_length_igp_82541;
10175eba5b6SRobert Mustacchi phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
10275eba5b6SRobert Mustacchi phy->ops.get_info = e1000_get_phy_info_igp;
10375eba5b6SRobert Mustacchi phy->ops.read_reg = e1000_read_phy_reg_igp;
10475eba5b6SRobert Mustacchi phy->ops.reset = e1000_phy_hw_reset_82541;
10575eba5b6SRobert Mustacchi phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82541;
10675eba5b6SRobert Mustacchi phy->ops.write_reg = e1000_write_phy_reg_igp;
10775eba5b6SRobert Mustacchi phy->ops.power_up = e1000_power_up_phy_copper;
10875eba5b6SRobert Mustacchi phy->ops.power_down = e1000_power_down_phy_copper_82541;
10975eba5b6SRobert Mustacchi
11075eba5b6SRobert Mustacchi ret_val = e1000_get_phy_id(hw);
11175eba5b6SRobert Mustacchi if (ret_val)
11275eba5b6SRobert Mustacchi goto out;
11375eba5b6SRobert Mustacchi
11475eba5b6SRobert Mustacchi /* Verify phy id */
11575eba5b6SRobert Mustacchi if (phy->id != IGP01E1000_I_PHY_ID) {
11675eba5b6SRobert Mustacchi ret_val = -E1000_ERR_PHY;
11775eba5b6SRobert Mustacchi goto out;
11875eba5b6SRobert Mustacchi }
11975eba5b6SRobert Mustacchi
12075eba5b6SRobert Mustacchi out:
12175eba5b6SRobert Mustacchi return ret_val;
12275eba5b6SRobert Mustacchi }
12375eba5b6SRobert Mustacchi
12475eba5b6SRobert Mustacchi /**
12575eba5b6SRobert Mustacchi * e1000_init_nvm_params_82541 - Init NVM func ptrs.
12675eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
12775eba5b6SRobert Mustacchi **/
e1000_init_nvm_params_82541(struct e1000_hw * hw)12875eba5b6SRobert Mustacchi static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw)
12975eba5b6SRobert Mustacchi {
13075eba5b6SRobert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
13175eba5b6SRobert Mustacchi s32 ret_val = E1000_SUCCESS;
13275eba5b6SRobert Mustacchi u32 eecd = E1000_READ_REG(hw, E1000_EECD);
13375eba5b6SRobert Mustacchi u16 size;
13475eba5b6SRobert Mustacchi
13575eba5b6SRobert Mustacchi DEBUGFUNC("e1000_init_nvm_params_82541");
13675eba5b6SRobert Mustacchi
13775eba5b6SRobert Mustacchi switch (nvm->override) {
13875eba5b6SRobert Mustacchi case e1000_nvm_override_spi_large:
13975eba5b6SRobert Mustacchi nvm->type = e1000_nvm_eeprom_spi;
14075eba5b6SRobert Mustacchi eecd |= E1000_EECD_ADDR_BITS;
14175eba5b6SRobert Mustacchi break;
14275eba5b6SRobert Mustacchi case e1000_nvm_override_spi_small:
14375eba5b6SRobert Mustacchi nvm->type = e1000_nvm_eeprom_spi;
14475eba5b6SRobert Mustacchi eecd &= ~E1000_EECD_ADDR_BITS;
14575eba5b6SRobert Mustacchi break;
14675eba5b6SRobert Mustacchi case e1000_nvm_override_microwire_large:
14775eba5b6SRobert Mustacchi nvm->type = e1000_nvm_eeprom_microwire;
14875eba5b6SRobert Mustacchi eecd |= E1000_EECD_SIZE;
14975eba5b6SRobert Mustacchi break;
15075eba5b6SRobert Mustacchi case e1000_nvm_override_microwire_small:
15175eba5b6SRobert Mustacchi nvm->type = e1000_nvm_eeprom_microwire;
15275eba5b6SRobert Mustacchi eecd &= ~E1000_EECD_SIZE;
15375eba5b6SRobert Mustacchi break;
15475eba5b6SRobert Mustacchi default:
155*42cc51e0SRobert Mustacchi nvm->type = eecd & E1000_EECD_TYPE ? e1000_nvm_eeprom_spi
15675eba5b6SRobert Mustacchi : e1000_nvm_eeprom_microwire;
15775eba5b6SRobert Mustacchi break;
15875eba5b6SRobert Mustacchi }
15975eba5b6SRobert Mustacchi
16075eba5b6SRobert Mustacchi if (nvm->type == e1000_nvm_eeprom_spi) {
161*42cc51e0SRobert Mustacchi nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) ? 16 : 8;
16275eba5b6SRobert Mustacchi nvm->delay_usec = 1;
16375eba5b6SRobert Mustacchi nvm->opcode_bits = 8;
164*42cc51e0SRobert Mustacchi nvm->page_size = (eecd & E1000_EECD_ADDR_BITS) ? 32 : 8;
16575eba5b6SRobert Mustacchi
16675eba5b6SRobert Mustacchi /* Function Pointers */
16775eba5b6SRobert Mustacchi nvm->ops.acquire = e1000_acquire_nvm_generic;
16875eba5b6SRobert Mustacchi nvm->ops.read = e1000_read_nvm_spi;
16975eba5b6SRobert Mustacchi nvm->ops.release = e1000_release_nvm_generic;
17075eba5b6SRobert Mustacchi nvm->ops.update = e1000_update_nvm_checksum_generic;
17175eba5b6SRobert Mustacchi nvm->ops.valid_led_default = e1000_valid_led_default_generic;
17275eba5b6SRobert Mustacchi nvm->ops.validate = e1000_validate_nvm_checksum_generic;
17375eba5b6SRobert Mustacchi nvm->ops.write = e1000_write_nvm_spi;
17475eba5b6SRobert Mustacchi
17575eba5b6SRobert Mustacchi /*
17675eba5b6SRobert Mustacchi * nvm->word_size must be discovered after the pointers
17775eba5b6SRobert Mustacchi * are set so we can verify the size from the nvm image
17875eba5b6SRobert Mustacchi * itself. Temporarily set it to a dummy value so the
17975eba5b6SRobert Mustacchi * read will work.
18075eba5b6SRobert Mustacchi */
18175eba5b6SRobert Mustacchi nvm->word_size = 64;
18275eba5b6SRobert Mustacchi ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size);
18375eba5b6SRobert Mustacchi if (ret_val)
18475eba5b6SRobert Mustacchi goto out;
18575eba5b6SRobert Mustacchi size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT;
18675eba5b6SRobert Mustacchi /*
18775eba5b6SRobert Mustacchi * if size != 0, it can be added to a constant and become
18875eba5b6SRobert Mustacchi * the left-shift value to set the word_size. Otherwise,
18975eba5b6SRobert Mustacchi * word_size stays at 64.
19075eba5b6SRobert Mustacchi */
19175eba5b6SRobert Mustacchi if (size) {
19275eba5b6SRobert Mustacchi size += NVM_WORD_SIZE_BASE_SHIFT_82541;
19375eba5b6SRobert Mustacchi nvm->word_size = 1 << size;
19475eba5b6SRobert Mustacchi }
19575eba5b6SRobert Mustacchi } else {
196*42cc51e0SRobert Mustacchi nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) ? 8 : 6;
19775eba5b6SRobert Mustacchi nvm->delay_usec = 50;
19875eba5b6SRobert Mustacchi nvm->opcode_bits = 3;
199*42cc51e0SRobert Mustacchi nvm->word_size = (eecd & E1000_EECD_ADDR_BITS) ? 256 : 64;
20075eba5b6SRobert Mustacchi
20175eba5b6SRobert Mustacchi /* Function Pointers */
20275eba5b6SRobert Mustacchi nvm->ops.acquire = e1000_acquire_nvm_generic;
20375eba5b6SRobert Mustacchi nvm->ops.read = e1000_read_nvm_microwire;
20475eba5b6SRobert Mustacchi nvm->ops.release = e1000_release_nvm_generic;
20575eba5b6SRobert Mustacchi nvm->ops.update = e1000_update_nvm_checksum_generic;
20675eba5b6SRobert Mustacchi nvm->ops.valid_led_default = e1000_valid_led_default_generic;
20775eba5b6SRobert Mustacchi nvm->ops.validate = e1000_validate_nvm_checksum_generic;
20875eba5b6SRobert Mustacchi nvm->ops.write = e1000_write_nvm_microwire;
20975eba5b6SRobert Mustacchi }
21075eba5b6SRobert Mustacchi
21175eba5b6SRobert Mustacchi out:
21275eba5b6SRobert Mustacchi return ret_val;
21375eba5b6SRobert Mustacchi }
21475eba5b6SRobert Mustacchi
21575eba5b6SRobert Mustacchi /**
21675eba5b6SRobert Mustacchi * e1000_init_mac_params_82541 - Init MAC func ptrs.
21775eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
21875eba5b6SRobert Mustacchi **/
e1000_init_mac_params_82541(struct e1000_hw * hw)21975eba5b6SRobert Mustacchi static s32 e1000_init_mac_params_82541(struct e1000_hw *hw)
22075eba5b6SRobert Mustacchi {
22175eba5b6SRobert Mustacchi struct e1000_mac_info *mac = &hw->mac;
22275eba5b6SRobert Mustacchi
22375eba5b6SRobert Mustacchi DEBUGFUNC("e1000_init_mac_params_82541");
22475eba5b6SRobert Mustacchi
22575eba5b6SRobert Mustacchi /* Set media type */
22675eba5b6SRobert Mustacchi hw->phy.media_type = e1000_media_type_copper;
22775eba5b6SRobert Mustacchi /* Set mta register count */
22875eba5b6SRobert Mustacchi mac->mta_reg_count = 128;
22975eba5b6SRobert Mustacchi /* Set rar entry count */
23075eba5b6SRobert Mustacchi mac->rar_entry_count = E1000_RAR_ENTRIES;
23175eba5b6SRobert Mustacchi /* Set if part includes ASF firmware */
23275eba5b6SRobert Mustacchi mac->asf_firmware_present = TRUE;
23375eba5b6SRobert Mustacchi
23475eba5b6SRobert Mustacchi /* Function Pointers */
23575eba5b6SRobert Mustacchi
23675eba5b6SRobert Mustacchi /* bus type/speed/width */
23775eba5b6SRobert Mustacchi mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
23875eba5b6SRobert Mustacchi /* function id */
23975eba5b6SRobert Mustacchi mac->ops.set_lan_id = e1000_set_lan_id_single_port;
24075eba5b6SRobert Mustacchi /* reset */
24175eba5b6SRobert Mustacchi mac->ops.reset_hw = e1000_reset_hw_82541;
24275eba5b6SRobert Mustacchi /* hw initialization */
24375eba5b6SRobert Mustacchi mac->ops.init_hw = e1000_init_hw_82541;
24475eba5b6SRobert Mustacchi /* link setup */
24575eba5b6SRobert Mustacchi mac->ops.setup_link = e1000_setup_link_generic;
24675eba5b6SRobert Mustacchi /* physical interface link setup */
24775eba5b6SRobert Mustacchi mac->ops.setup_physical_interface = e1000_setup_copper_link_82541;
24875eba5b6SRobert Mustacchi /* check for link */
24975eba5b6SRobert Mustacchi mac->ops.check_for_link = e1000_check_for_link_82541;
25075eba5b6SRobert Mustacchi /* link info */
25175eba5b6SRobert Mustacchi mac->ops.get_link_up_info = e1000_get_link_up_info_82541;
25275eba5b6SRobert Mustacchi /* multicast address update */
25375eba5b6SRobert Mustacchi mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
25475eba5b6SRobert Mustacchi /* writing VFTA */
25575eba5b6SRobert Mustacchi mac->ops.write_vfta = e1000_write_vfta_generic;
25675eba5b6SRobert Mustacchi /* clearing VFTA */
25775eba5b6SRobert Mustacchi mac->ops.clear_vfta = e1000_clear_vfta_generic;
25875eba5b6SRobert Mustacchi /* read mac address */
25975eba5b6SRobert Mustacchi mac->ops.read_mac_addr = e1000_read_mac_addr_82541;
26075eba5b6SRobert Mustacchi /* ID LED init */
26175eba5b6SRobert Mustacchi mac->ops.id_led_init = e1000_id_led_init_generic;
26275eba5b6SRobert Mustacchi /* setup LED */
26375eba5b6SRobert Mustacchi mac->ops.setup_led = e1000_setup_led_82541;
26475eba5b6SRobert Mustacchi /* cleanup LED */
26575eba5b6SRobert Mustacchi mac->ops.cleanup_led = e1000_cleanup_led_82541;
26675eba5b6SRobert Mustacchi /* turn on/off LED */
26775eba5b6SRobert Mustacchi mac->ops.led_on = e1000_led_on_generic;
26875eba5b6SRobert Mustacchi mac->ops.led_off = e1000_led_off_generic;
26975eba5b6SRobert Mustacchi /* clear hardware counters */
27075eba5b6SRobert Mustacchi mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541;
27175eba5b6SRobert Mustacchi
27275eba5b6SRobert Mustacchi return E1000_SUCCESS;
27375eba5b6SRobert Mustacchi }
27475eba5b6SRobert Mustacchi
27575eba5b6SRobert Mustacchi /**
27675eba5b6SRobert Mustacchi * e1000_init_function_pointers_82541 - Init func ptrs.
27775eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
27875eba5b6SRobert Mustacchi *
27975eba5b6SRobert Mustacchi * Called to initialize all function pointers and parameters.
28075eba5b6SRobert Mustacchi **/
e1000_init_function_pointers_82541(struct e1000_hw * hw)28175eba5b6SRobert Mustacchi void e1000_init_function_pointers_82541(struct e1000_hw *hw)
28275eba5b6SRobert Mustacchi {
28375eba5b6SRobert Mustacchi DEBUGFUNC("e1000_init_function_pointers_82541");
28475eba5b6SRobert Mustacchi
28575eba5b6SRobert Mustacchi hw->mac.ops.init_params = e1000_init_mac_params_82541;
28675eba5b6SRobert Mustacchi hw->nvm.ops.init_params = e1000_init_nvm_params_82541;
28775eba5b6SRobert Mustacchi hw->phy.ops.init_params = e1000_init_phy_params_82541;
28875eba5b6SRobert Mustacchi }
28975eba5b6SRobert Mustacchi
29075eba5b6SRobert Mustacchi /**
29175eba5b6SRobert Mustacchi * e1000_reset_hw_82541 - Reset hardware
29275eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
29375eba5b6SRobert Mustacchi *
29475eba5b6SRobert Mustacchi * This resets the hardware into a known state.
29575eba5b6SRobert Mustacchi **/
e1000_reset_hw_82541(struct e1000_hw * hw)29675eba5b6SRobert Mustacchi static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
29775eba5b6SRobert Mustacchi {
298*42cc51e0SRobert Mustacchi u32 ledctl, ctrl, manc;
29975eba5b6SRobert Mustacchi
30075eba5b6SRobert Mustacchi DEBUGFUNC("e1000_reset_hw_82541");
30175eba5b6SRobert Mustacchi
30275eba5b6SRobert Mustacchi DEBUGOUT("Masking off all interrupts\n");
30375eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
30475eba5b6SRobert Mustacchi
30575eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_RCTL, 0);
30675eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
30775eba5b6SRobert Mustacchi E1000_WRITE_FLUSH(hw);
30875eba5b6SRobert Mustacchi
30975eba5b6SRobert Mustacchi /*
31075eba5b6SRobert Mustacchi * Delay to allow any outstanding PCI transactions to complete
31175eba5b6SRobert Mustacchi * before resetting the device.
31275eba5b6SRobert Mustacchi */
31375eba5b6SRobert Mustacchi msec_delay(10);
31475eba5b6SRobert Mustacchi
31575eba5b6SRobert Mustacchi ctrl = E1000_READ_REG(hw, E1000_CTRL);
31675eba5b6SRobert Mustacchi
31775eba5b6SRobert Mustacchi /* Must reset the Phy before resetting the MAC */
31875eba5b6SRobert Mustacchi if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
31975eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST));
320*42cc51e0SRobert Mustacchi E1000_WRITE_FLUSH(hw);
32175eba5b6SRobert Mustacchi msec_delay(5);
32275eba5b6SRobert Mustacchi }
32375eba5b6SRobert Mustacchi
32475eba5b6SRobert Mustacchi DEBUGOUT("Issuing a global reset to 82541/82547 MAC\n");
32575eba5b6SRobert Mustacchi switch (hw->mac.type) {
32675eba5b6SRobert Mustacchi case e1000_82541:
32775eba5b6SRobert Mustacchi case e1000_82541_rev_2:
32875eba5b6SRobert Mustacchi /*
32975eba5b6SRobert Mustacchi * These controllers can't ack the 64-bit write when
33075eba5b6SRobert Mustacchi * issuing the reset, so we use IO-mapping as a
33175eba5b6SRobert Mustacchi * workaround to issue the reset.
33275eba5b6SRobert Mustacchi */
33375eba5b6SRobert Mustacchi E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
33475eba5b6SRobert Mustacchi break;
33575eba5b6SRobert Mustacchi default:
33675eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
33775eba5b6SRobert Mustacchi break;
33875eba5b6SRobert Mustacchi }
33975eba5b6SRobert Mustacchi
34075eba5b6SRobert Mustacchi /* Wait for NVM reload */
34175eba5b6SRobert Mustacchi msec_delay(20);
34275eba5b6SRobert Mustacchi
34375eba5b6SRobert Mustacchi /* Disable HW ARPs on ASF enabled adapters */
34475eba5b6SRobert Mustacchi manc = E1000_READ_REG(hw, E1000_MANC);
34575eba5b6SRobert Mustacchi manc &= ~E1000_MANC_ARP_EN;
34675eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_MANC, manc);
34775eba5b6SRobert Mustacchi
34875eba5b6SRobert Mustacchi if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
34975eba5b6SRobert Mustacchi e1000_phy_init_script_82541(hw);
35075eba5b6SRobert Mustacchi
35175eba5b6SRobert Mustacchi /* Configure activity LED after Phy reset */
35275eba5b6SRobert Mustacchi ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
35375eba5b6SRobert Mustacchi ledctl &= IGP_ACTIVITY_LED_MASK;
35475eba5b6SRobert Mustacchi ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
35575eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
35675eba5b6SRobert Mustacchi }
35775eba5b6SRobert Mustacchi
35875eba5b6SRobert Mustacchi /* Once again, mask the interrupts */
35975eba5b6SRobert Mustacchi DEBUGOUT("Masking off all interrupts\n");
36075eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
36175eba5b6SRobert Mustacchi
36275eba5b6SRobert Mustacchi /* Clear any pending interrupt events. */
363*42cc51e0SRobert Mustacchi E1000_READ_REG(hw, E1000_ICR);
36475eba5b6SRobert Mustacchi
36575eba5b6SRobert Mustacchi return E1000_SUCCESS;
36675eba5b6SRobert Mustacchi }
36775eba5b6SRobert Mustacchi
36875eba5b6SRobert Mustacchi /**
36975eba5b6SRobert Mustacchi * e1000_init_hw_82541 - Initialize hardware
37075eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
37175eba5b6SRobert Mustacchi *
37275eba5b6SRobert Mustacchi * This inits the hardware readying it for operation.
37375eba5b6SRobert Mustacchi **/
e1000_init_hw_82541(struct e1000_hw * hw)37475eba5b6SRobert Mustacchi static s32 e1000_init_hw_82541(struct e1000_hw *hw)
37575eba5b6SRobert Mustacchi {
37675eba5b6SRobert Mustacchi struct e1000_mac_info *mac = &hw->mac;
37775eba5b6SRobert Mustacchi struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
37875eba5b6SRobert Mustacchi u32 i, txdctl;
37975eba5b6SRobert Mustacchi s32 ret_val;
38075eba5b6SRobert Mustacchi
38175eba5b6SRobert Mustacchi DEBUGFUNC("e1000_init_hw_82541");
38275eba5b6SRobert Mustacchi
38375eba5b6SRobert Mustacchi /* Initialize identification LED */
38475eba5b6SRobert Mustacchi ret_val = mac->ops.id_led_init(hw);
38575eba5b6SRobert Mustacchi if (ret_val) {
38675eba5b6SRobert Mustacchi DEBUGOUT("Error initializing identification LED\n");
38775eba5b6SRobert Mustacchi /* This is not fatal and we should not stop init due to this */
38875eba5b6SRobert Mustacchi }
38975eba5b6SRobert Mustacchi
39075eba5b6SRobert Mustacchi /* Storing the Speed Power Down value for later use */
391*42cc51e0SRobert Mustacchi ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO,
39275eba5b6SRobert Mustacchi &dev_spec->spd_default);
39375eba5b6SRobert Mustacchi if (ret_val)
39475eba5b6SRobert Mustacchi goto out;
39575eba5b6SRobert Mustacchi
39675eba5b6SRobert Mustacchi /* Disabling VLAN filtering */
39775eba5b6SRobert Mustacchi DEBUGOUT("Initializing the IEEE VLAN\n");
39875eba5b6SRobert Mustacchi mac->ops.clear_vfta(hw);
39975eba5b6SRobert Mustacchi
40075eba5b6SRobert Mustacchi /* Setup the receive address. */
40175eba5b6SRobert Mustacchi e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
40275eba5b6SRobert Mustacchi
40375eba5b6SRobert Mustacchi /* Zero out the Multicast HASH table */
40475eba5b6SRobert Mustacchi DEBUGOUT("Zeroing the MTA\n");
40575eba5b6SRobert Mustacchi for (i = 0; i < mac->mta_reg_count; i++) {
40675eba5b6SRobert Mustacchi E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
40775eba5b6SRobert Mustacchi /*
40875eba5b6SRobert Mustacchi * Avoid back to back register writes by adding the register
40975eba5b6SRobert Mustacchi * read (flush). This is to protect against some strange
41075eba5b6SRobert Mustacchi * bridge configurations that may issue Memory Write Block
41175eba5b6SRobert Mustacchi * (MWB) to our register space.
41275eba5b6SRobert Mustacchi */
41375eba5b6SRobert Mustacchi E1000_WRITE_FLUSH(hw);
41475eba5b6SRobert Mustacchi }
41575eba5b6SRobert Mustacchi
41675eba5b6SRobert Mustacchi /* Setup link and flow control */
41775eba5b6SRobert Mustacchi ret_val = mac->ops.setup_link(hw);
41875eba5b6SRobert Mustacchi
41975eba5b6SRobert Mustacchi txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
42075eba5b6SRobert Mustacchi txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
42175eba5b6SRobert Mustacchi E1000_TXDCTL_FULL_TX_DESC_WB;
42275eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
42375eba5b6SRobert Mustacchi
42475eba5b6SRobert Mustacchi /*
42575eba5b6SRobert Mustacchi * Clear all of the statistics registers (clear on read). It is
42675eba5b6SRobert Mustacchi * important that we do this after we have tried to establish link
42775eba5b6SRobert Mustacchi * because the symbol error count will increment wildly if there
42875eba5b6SRobert Mustacchi * is no link.
42975eba5b6SRobert Mustacchi */
43075eba5b6SRobert Mustacchi e1000_clear_hw_cntrs_82541(hw);
43175eba5b6SRobert Mustacchi
43275eba5b6SRobert Mustacchi out:
43375eba5b6SRobert Mustacchi return ret_val;
43475eba5b6SRobert Mustacchi }
43575eba5b6SRobert Mustacchi
43675eba5b6SRobert Mustacchi /**
43775eba5b6SRobert Mustacchi * e1000_get_link_up_info_82541 - Report speed and duplex
43875eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
43975eba5b6SRobert Mustacchi * @speed: pointer to speed buffer
44075eba5b6SRobert Mustacchi * @duplex: pointer to duplex buffer
44175eba5b6SRobert Mustacchi *
44275eba5b6SRobert Mustacchi * Retrieve the current speed and duplex configuration.
44375eba5b6SRobert Mustacchi **/
e1000_get_link_up_info_82541(struct e1000_hw * hw,u16 * speed,u16 * duplex)44475eba5b6SRobert Mustacchi static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
44575eba5b6SRobert Mustacchi u16 *duplex)
44675eba5b6SRobert Mustacchi {
44775eba5b6SRobert Mustacchi struct e1000_phy_info *phy = &hw->phy;
44875eba5b6SRobert Mustacchi s32 ret_val;
44975eba5b6SRobert Mustacchi u16 data;
45075eba5b6SRobert Mustacchi
45175eba5b6SRobert Mustacchi DEBUGFUNC("e1000_get_link_up_info_82541");
45275eba5b6SRobert Mustacchi
45375eba5b6SRobert Mustacchi ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex);
45475eba5b6SRobert Mustacchi if (ret_val)
45575eba5b6SRobert Mustacchi goto out;
45675eba5b6SRobert Mustacchi
45775eba5b6SRobert Mustacchi if (!phy->speed_downgraded)
45875eba5b6SRobert Mustacchi goto out;
45975eba5b6SRobert Mustacchi
46075eba5b6SRobert Mustacchi /*
46175eba5b6SRobert Mustacchi * IGP01 PHY may advertise full duplex operation after speed
46275eba5b6SRobert Mustacchi * downgrade even if it is operating at half duplex.
46375eba5b6SRobert Mustacchi * Here we set the duplex settings to match the duplex in the
46475eba5b6SRobert Mustacchi * link partner's capabilities.
46575eba5b6SRobert Mustacchi */
46675eba5b6SRobert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data);
46775eba5b6SRobert Mustacchi if (ret_val)
46875eba5b6SRobert Mustacchi goto out;
46975eba5b6SRobert Mustacchi
47075eba5b6SRobert Mustacchi if (!(data & NWAY_ER_LP_NWAY_CAPS)) {
47175eba5b6SRobert Mustacchi *duplex = HALF_DUPLEX;
47275eba5b6SRobert Mustacchi } else {
47375eba5b6SRobert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data);
47475eba5b6SRobert Mustacchi if (ret_val)
47575eba5b6SRobert Mustacchi goto out;
47675eba5b6SRobert Mustacchi
47775eba5b6SRobert Mustacchi if (*speed == SPEED_100) {
47875eba5b6SRobert Mustacchi if (!(data & NWAY_LPAR_100TX_FD_CAPS))
47975eba5b6SRobert Mustacchi *duplex = HALF_DUPLEX;
48075eba5b6SRobert Mustacchi } else if (*speed == SPEED_10) {
48175eba5b6SRobert Mustacchi if (!(data & NWAY_LPAR_10T_FD_CAPS))
48275eba5b6SRobert Mustacchi *duplex = HALF_DUPLEX;
48375eba5b6SRobert Mustacchi }
48475eba5b6SRobert Mustacchi }
48575eba5b6SRobert Mustacchi
48675eba5b6SRobert Mustacchi out:
48775eba5b6SRobert Mustacchi return ret_val;
48875eba5b6SRobert Mustacchi }
48975eba5b6SRobert Mustacchi
49075eba5b6SRobert Mustacchi /**
49175eba5b6SRobert Mustacchi * e1000_phy_hw_reset_82541 - PHY hardware reset
49275eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
49375eba5b6SRobert Mustacchi *
49475eba5b6SRobert Mustacchi * Verify the reset block is not blocking us from resetting. Acquire
49575eba5b6SRobert Mustacchi * semaphore (if necessary) and read/set/write the device control reset
49675eba5b6SRobert Mustacchi * bit in the PHY. Wait the appropriate delay time for the device to
49775eba5b6SRobert Mustacchi * reset and release the semaphore (if necessary).
49875eba5b6SRobert Mustacchi **/
e1000_phy_hw_reset_82541(struct e1000_hw * hw)49975eba5b6SRobert Mustacchi static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw)
50075eba5b6SRobert Mustacchi {
50175eba5b6SRobert Mustacchi s32 ret_val;
50275eba5b6SRobert Mustacchi u32 ledctl;
50375eba5b6SRobert Mustacchi
50475eba5b6SRobert Mustacchi DEBUGFUNC("e1000_phy_hw_reset_82541");
50575eba5b6SRobert Mustacchi
50675eba5b6SRobert Mustacchi ret_val = e1000_phy_hw_reset_generic(hw);
50775eba5b6SRobert Mustacchi if (ret_val)
50875eba5b6SRobert Mustacchi goto out;
50975eba5b6SRobert Mustacchi
51075eba5b6SRobert Mustacchi e1000_phy_init_script_82541(hw);
51175eba5b6SRobert Mustacchi
51275eba5b6SRobert Mustacchi if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
51375eba5b6SRobert Mustacchi /* Configure activity LED after PHY reset */
51475eba5b6SRobert Mustacchi ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
51575eba5b6SRobert Mustacchi ledctl &= IGP_ACTIVITY_LED_MASK;
51675eba5b6SRobert Mustacchi ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
51775eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
51875eba5b6SRobert Mustacchi }
51975eba5b6SRobert Mustacchi
52075eba5b6SRobert Mustacchi out:
52175eba5b6SRobert Mustacchi return ret_val;
52275eba5b6SRobert Mustacchi }
52375eba5b6SRobert Mustacchi
52475eba5b6SRobert Mustacchi /**
52575eba5b6SRobert Mustacchi * e1000_setup_copper_link_82541 - Configure copper link settings
52675eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
52775eba5b6SRobert Mustacchi *
52875eba5b6SRobert Mustacchi * Calls the appropriate function to configure the link for auto-neg or forced
52975eba5b6SRobert Mustacchi * speed and duplex. Then we check for link, once link is established calls
53075eba5b6SRobert Mustacchi * to configure collision distance and flow control are called. If link is
53175eba5b6SRobert Mustacchi * not established, we return -E1000_ERR_PHY (-2).
53275eba5b6SRobert Mustacchi **/
e1000_setup_copper_link_82541(struct e1000_hw * hw)53375eba5b6SRobert Mustacchi static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw)
53475eba5b6SRobert Mustacchi {
53575eba5b6SRobert Mustacchi struct e1000_phy_info *phy = &hw->phy;
53675eba5b6SRobert Mustacchi struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
53775eba5b6SRobert Mustacchi s32 ret_val;
53875eba5b6SRobert Mustacchi u32 ctrl, ledctl;
53975eba5b6SRobert Mustacchi
54075eba5b6SRobert Mustacchi DEBUGFUNC("e1000_setup_copper_link_82541");
54175eba5b6SRobert Mustacchi
54275eba5b6SRobert Mustacchi ctrl = E1000_READ_REG(hw, E1000_CTRL);
54375eba5b6SRobert Mustacchi ctrl |= E1000_CTRL_SLU;
54475eba5b6SRobert Mustacchi ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
54575eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
54675eba5b6SRobert Mustacchi
547*42cc51e0SRobert Mustacchi
54875eba5b6SRobert Mustacchi /* Earlier revs of the IGP phy require us to force MDI. */
54975eba5b6SRobert Mustacchi if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) {
55075eba5b6SRobert Mustacchi dev_spec->dsp_config = e1000_dsp_config_disabled;
55175eba5b6SRobert Mustacchi phy->mdix = 1;
55275eba5b6SRobert Mustacchi } else {
55375eba5b6SRobert Mustacchi dev_spec->dsp_config = e1000_dsp_config_enabled;
55475eba5b6SRobert Mustacchi }
55575eba5b6SRobert Mustacchi
55675eba5b6SRobert Mustacchi ret_val = e1000_copper_link_setup_igp(hw);
55775eba5b6SRobert Mustacchi if (ret_val)
55875eba5b6SRobert Mustacchi goto out;
55975eba5b6SRobert Mustacchi
56075eba5b6SRobert Mustacchi if (hw->mac.autoneg) {
56175eba5b6SRobert Mustacchi if (dev_spec->ffe_config == e1000_ffe_config_active)
56275eba5b6SRobert Mustacchi dev_spec->ffe_config = e1000_ffe_config_enabled;
56375eba5b6SRobert Mustacchi }
56475eba5b6SRobert Mustacchi
56575eba5b6SRobert Mustacchi /* Configure activity LED after Phy reset */
56675eba5b6SRobert Mustacchi ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
56775eba5b6SRobert Mustacchi ledctl &= IGP_ACTIVITY_LED_MASK;
56875eba5b6SRobert Mustacchi ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
56975eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
57075eba5b6SRobert Mustacchi
57175eba5b6SRobert Mustacchi ret_val = e1000_setup_copper_link_generic(hw);
57275eba5b6SRobert Mustacchi
57375eba5b6SRobert Mustacchi out:
57475eba5b6SRobert Mustacchi return ret_val;
57575eba5b6SRobert Mustacchi }
57675eba5b6SRobert Mustacchi
57775eba5b6SRobert Mustacchi /**
57875eba5b6SRobert Mustacchi * e1000_check_for_link_82541 - Check/Store link connection
57975eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
58075eba5b6SRobert Mustacchi *
58175eba5b6SRobert Mustacchi * This checks the link condition of the adapter and stores the
58275eba5b6SRobert Mustacchi * results in the hw->mac structure.
58375eba5b6SRobert Mustacchi **/
e1000_check_for_link_82541(struct e1000_hw * hw)58475eba5b6SRobert Mustacchi static s32 e1000_check_for_link_82541(struct e1000_hw *hw)
58575eba5b6SRobert Mustacchi {
58675eba5b6SRobert Mustacchi struct e1000_mac_info *mac = &hw->mac;
58775eba5b6SRobert Mustacchi s32 ret_val;
58875eba5b6SRobert Mustacchi bool link;
58975eba5b6SRobert Mustacchi
59075eba5b6SRobert Mustacchi DEBUGFUNC("e1000_check_for_link_82541");
59175eba5b6SRobert Mustacchi
59275eba5b6SRobert Mustacchi /*
59375eba5b6SRobert Mustacchi * We only want to go out to the PHY registers to see if Auto-Neg
59475eba5b6SRobert Mustacchi * has completed and/or if our link status has changed. The
59575eba5b6SRobert Mustacchi * get_link_status flag is set upon receiving a Link Status
59675eba5b6SRobert Mustacchi * Change or Rx Sequence Error interrupt.
59775eba5b6SRobert Mustacchi */
59875eba5b6SRobert Mustacchi if (!mac->get_link_status) {
59975eba5b6SRobert Mustacchi ret_val = E1000_SUCCESS;
60075eba5b6SRobert Mustacchi goto out;
60175eba5b6SRobert Mustacchi }
60275eba5b6SRobert Mustacchi
60375eba5b6SRobert Mustacchi /*
60475eba5b6SRobert Mustacchi * First we want to see if the MII Status Register reports
60575eba5b6SRobert Mustacchi * link. If so, then we want to get the current speed/duplex
60675eba5b6SRobert Mustacchi * of the PHY.
60775eba5b6SRobert Mustacchi */
60875eba5b6SRobert Mustacchi ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
60975eba5b6SRobert Mustacchi if (ret_val)
61075eba5b6SRobert Mustacchi goto out;
61175eba5b6SRobert Mustacchi
61275eba5b6SRobert Mustacchi if (!link) {
61375eba5b6SRobert Mustacchi ret_val = e1000_config_dsp_after_link_change_82541(hw, FALSE);
61475eba5b6SRobert Mustacchi goto out; /* No link detected */
61575eba5b6SRobert Mustacchi }
61675eba5b6SRobert Mustacchi
61775eba5b6SRobert Mustacchi mac->get_link_status = FALSE;
61875eba5b6SRobert Mustacchi
61975eba5b6SRobert Mustacchi /*
62075eba5b6SRobert Mustacchi * Check if there was DownShift, must be checked
62175eba5b6SRobert Mustacchi * immediately after link-up
62275eba5b6SRobert Mustacchi */
62375eba5b6SRobert Mustacchi e1000_check_downshift_generic(hw);
62475eba5b6SRobert Mustacchi
62575eba5b6SRobert Mustacchi /*
62675eba5b6SRobert Mustacchi * If we are forcing speed/duplex, then we simply return since
62775eba5b6SRobert Mustacchi * we have already determined whether we have link or not.
62875eba5b6SRobert Mustacchi */
62975eba5b6SRobert Mustacchi if (!mac->autoneg) {
63075eba5b6SRobert Mustacchi ret_val = -E1000_ERR_CONFIG;
63175eba5b6SRobert Mustacchi goto out;
63275eba5b6SRobert Mustacchi }
63375eba5b6SRobert Mustacchi
63475eba5b6SRobert Mustacchi ret_val = e1000_config_dsp_after_link_change_82541(hw, TRUE);
63575eba5b6SRobert Mustacchi
63675eba5b6SRobert Mustacchi /*
63775eba5b6SRobert Mustacchi * Auto-Neg is enabled. Auto Speed Detection takes care
63875eba5b6SRobert Mustacchi * of MAC speed/duplex configuration. So we only need to
63975eba5b6SRobert Mustacchi * configure Collision Distance in the MAC.
64075eba5b6SRobert Mustacchi */
64175eba5b6SRobert Mustacchi mac->ops.config_collision_dist(hw);
64275eba5b6SRobert Mustacchi
64375eba5b6SRobert Mustacchi /*
64475eba5b6SRobert Mustacchi * Configure Flow Control now that Auto-Neg has completed.
64575eba5b6SRobert Mustacchi * First, we need to restore the desired flow control
64675eba5b6SRobert Mustacchi * settings because we may have had to re-autoneg with a
64775eba5b6SRobert Mustacchi * different link partner.
64875eba5b6SRobert Mustacchi */
64975eba5b6SRobert Mustacchi ret_val = e1000_config_fc_after_link_up_generic(hw);
650*42cc51e0SRobert Mustacchi if (ret_val)
65175eba5b6SRobert Mustacchi DEBUGOUT("Error configuring flow control\n");
65275eba5b6SRobert Mustacchi
65375eba5b6SRobert Mustacchi out:
65475eba5b6SRobert Mustacchi return ret_val;
65575eba5b6SRobert Mustacchi }
65675eba5b6SRobert Mustacchi
65775eba5b6SRobert Mustacchi /**
65875eba5b6SRobert Mustacchi * e1000_config_dsp_after_link_change_82541 - Config DSP after link
65975eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
66075eba5b6SRobert Mustacchi * @link_up: boolean flag for link up status
66175eba5b6SRobert Mustacchi *
66275eba5b6SRobert Mustacchi * Return E1000_ERR_PHY when failing to read/write the PHY, else E1000_SUCCESS
66375eba5b6SRobert Mustacchi * at any other case.
66475eba5b6SRobert Mustacchi *
66575eba5b6SRobert Mustacchi * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
66675eba5b6SRobert Mustacchi * gigabit link is achieved to improve link quality.
66775eba5b6SRobert Mustacchi **/
e1000_config_dsp_after_link_change_82541(struct e1000_hw * hw,bool link_up)66875eba5b6SRobert Mustacchi static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
66975eba5b6SRobert Mustacchi bool link_up)
67075eba5b6SRobert Mustacchi {
67175eba5b6SRobert Mustacchi struct e1000_phy_info *phy = &hw->phy;
67275eba5b6SRobert Mustacchi struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
67375eba5b6SRobert Mustacchi s32 ret_val;
67475eba5b6SRobert Mustacchi u32 idle_errs = 0;
67575eba5b6SRobert Mustacchi u16 phy_data, phy_saved_data, speed, duplex, i;
67675eba5b6SRobert Mustacchi u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
677*42cc51e0SRobert Mustacchi u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
678*42cc51e0SRobert Mustacchi IGP01E1000_PHY_AGC_PARAM_A,
67975eba5b6SRobert Mustacchi IGP01E1000_PHY_AGC_PARAM_B,
68075eba5b6SRobert Mustacchi IGP01E1000_PHY_AGC_PARAM_C,
68175eba5b6SRobert Mustacchi IGP01E1000_PHY_AGC_PARAM_D};
68275eba5b6SRobert Mustacchi
68375eba5b6SRobert Mustacchi DEBUGFUNC("e1000_config_dsp_after_link_change_82541");
68475eba5b6SRobert Mustacchi
68575eba5b6SRobert Mustacchi if (link_up) {
68675eba5b6SRobert Mustacchi ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
68775eba5b6SRobert Mustacchi if (ret_val) {
68875eba5b6SRobert Mustacchi DEBUGOUT("Error getting link speed and duplex\n");
68975eba5b6SRobert Mustacchi goto out;
69075eba5b6SRobert Mustacchi }
69175eba5b6SRobert Mustacchi
69275eba5b6SRobert Mustacchi if (speed != SPEED_1000) {
69375eba5b6SRobert Mustacchi ret_val = E1000_SUCCESS;
69475eba5b6SRobert Mustacchi goto out;
69575eba5b6SRobert Mustacchi }
69675eba5b6SRobert Mustacchi
69775eba5b6SRobert Mustacchi ret_val = phy->ops.get_cable_length(hw);
69875eba5b6SRobert Mustacchi if (ret_val)
69975eba5b6SRobert Mustacchi goto out;
70075eba5b6SRobert Mustacchi
70175eba5b6SRobert Mustacchi if ((dev_spec->dsp_config == e1000_dsp_config_enabled) &&
70275eba5b6SRobert Mustacchi phy->min_cable_length >= 50) {
70375eba5b6SRobert Mustacchi
70475eba5b6SRobert Mustacchi for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
70575eba5b6SRobert Mustacchi ret_val = phy->ops.read_reg(hw,
70675eba5b6SRobert Mustacchi dsp_reg_array[i],
70775eba5b6SRobert Mustacchi &phy_data);
70875eba5b6SRobert Mustacchi if (ret_val)
70975eba5b6SRobert Mustacchi goto out;
71075eba5b6SRobert Mustacchi
71175eba5b6SRobert Mustacchi phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
71275eba5b6SRobert Mustacchi
71375eba5b6SRobert Mustacchi ret_val = phy->ops.write_reg(hw,
71475eba5b6SRobert Mustacchi dsp_reg_array[i],
71575eba5b6SRobert Mustacchi phy_data);
71675eba5b6SRobert Mustacchi if (ret_val)
71775eba5b6SRobert Mustacchi goto out;
71875eba5b6SRobert Mustacchi }
71975eba5b6SRobert Mustacchi dev_spec->dsp_config = e1000_dsp_config_activated;
72075eba5b6SRobert Mustacchi }
72175eba5b6SRobert Mustacchi
72275eba5b6SRobert Mustacchi if ((dev_spec->ffe_config != e1000_ffe_config_enabled) ||
72375eba5b6SRobert Mustacchi (phy->min_cable_length >= 50)) {
72475eba5b6SRobert Mustacchi ret_val = E1000_SUCCESS;
72575eba5b6SRobert Mustacchi goto out;
72675eba5b6SRobert Mustacchi }
72775eba5b6SRobert Mustacchi
72875eba5b6SRobert Mustacchi /* clear previous idle error counts */
72975eba5b6SRobert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
73075eba5b6SRobert Mustacchi if (ret_val)
73175eba5b6SRobert Mustacchi goto out;
73275eba5b6SRobert Mustacchi
73375eba5b6SRobert Mustacchi for (i = 0; i < ffe_idle_err_timeout; i++) {
73475eba5b6SRobert Mustacchi usec_delay(1000);
735*42cc51e0SRobert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS,
73675eba5b6SRobert Mustacchi &phy_data);
73775eba5b6SRobert Mustacchi if (ret_val)
73875eba5b6SRobert Mustacchi goto out;
73975eba5b6SRobert Mustacchi
74075eba5b6SRobert Mustacchi idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
74175eba5b6SRobert Mustacchi if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
74275eba5b6SRobert Mustacchi dev_spec->ffe_config = e1000_ffe_config_active;
74375eba5b6SRobert Mustacchi
74475eba5b6SRobert Mustacchi ret_val = phy->ops.write_reg(hw,
74575eba5b6SRobert Mustacchi IGP01E1000_PHY_DSP_FFE,
74675eba5b6SRobert Mustacchi IGP01E1000_PHY_DSP_FFE_CM_CP);
74775eba5b6SRobert Mustacchi if (ret_val)
74875eba5b6SRobert Mustacchi goto out;
74975eba5b6SRobert Mustacchi break;
75075eba5b6SRobert Mustacchi }
75175eba5b6SRobert Mustacchi
75275eba5b6SRobert Mustacchi if (idle_errs)
75375eba5b6SRobert Mustacchi ffe_idle_err_timeout =
75475eba5b6SRobert Mustacchi FFE_IDLE_ERR_COUNT_TIMEOUT_100;
75575eba5b6SRobert Mustacchi }
75675eba5b6SRobert Mustacchi } else {
75775eba5b6SRobert Mustacchi if (dev_spec->dsp_config == e1000_dsp_config_activated) {
75875eba5b6SRobert Mustacchi /*
75975eba5b6SRobert Mustacchi * Save off the current value of register 0x2F5B
76075eba5b6SRobert Mustacchi * to be restored at the end of the routines.
76175eba5b6SRobert Mustacchi */
762*42cc51e0SRobert Mustacchi ret_val = phy->ops.read_reg(hw, 0x2F5B,
76375eba5b6SRobert Mustacchi &phy_saved_data);
76475eba5b6SRobert Mustacchi if (ret_val)
76575eba5b6SRobert Mustacchi goto out;
76675eba5b6SRobert Mustacchi
76775eba5b6SRobert Mustacchi /* Disable the PHY transmitter */
76875eba5b6SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
76975eba5b6SRobert Mustacchi if (ret_val)
77075eba5b6SRobert Mustacchi goto out;
77175eba5b6SRobert Mustacchi
77275eba5b6SRobert Mustacchi msec_delay_irq(20);
77375eba5b6SRobert Mustacchi
774*42cc51e0SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x0000,
77575eba5b6SRobert Mustacchi IGP01E1000_IEEE_FORCE_GIG);
77675eba5b6SRobert Mustacchi if (ret_val)
77775eba5b6SRobert Mustacchi goto out;
77875eba5b6SRobert Mustacchi for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
77975eba5b6SRobert Mustacchi ret_val = phy->ops.read_reg(hw,
78075eba5b6SRobert Mustacchi dsp_reg_array[i],
78175eba5b6SRobert Mustacchi &phy_data);
78275eba5b6SRobert Mustacchi if (ret_val)
78375eba5b6SRobert Mustacchi goto out;
78475eba5b6SRobert Mustacchi
78575eba5b6SRobert Mustacchi phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
78675eba5b6SRobert Mustacchi phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
78775eba5b6SRobert Mustacchi
78875eba5b6SRobert Mustacchi ret_val = phy->ops.write_reg(hw,
78975eba5b6SRobert Mustacchi dsp_reg_array[i],
79075eba5b6SRobert Mustacchi phy_data);
79175eba5b6SRobert Mustacchi if (ret_val)
79275eba5b6SRobert Mustacchi goto out;
79375eba5b6SRobert Mustacchi }
79475eba5b6SRobert Mustacchi
795*42cc51e0SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x0000,
79675eba5b6SRobert Mustacchi IGP01E1000_IEEE_RESTART_AUTONEG);
79775eba5b6SRobert Mustacchi if (ret_val)
79875eba5b6SRobert Mustacchi goto out;
79975eba5b6SRobert Mustacchi
80075eba5b6SRobert Mustacchi msec_delay_irq(20);
80175eba5b6SRobert Mustacchi
80275eba5b6SRobert Mustacchi /* Now enable the transmitter */
803*42cc51e0SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x2F5B,
80475eba5b6SRobert Mustacchi phy_saved_data);
80575eba5b6SRobert Mustacchi if (ret_val)
80675eba5b6SRobert Mustacchi goto out;
80775eba5b6SRobert Mustacchi
80875eba5b6SRobert Mustacchi dev_spec->dsp_config = e1000_dsp_config_enabled;
80975eba5b6SRobert Mustacchi }
81075eba5b6SRobert Mustacchi
81175eba5b6SRobert Mustacchi if (dev_spec->ffe_config != e1000_ffe_config_active) {
81275eba5b6SRobert Mustacchi ret_val = E1000_SUCCESS;
81375eba5b6SRobert Mustacchi goto out;
81475eba5b6SRobert Mustacchi }
81575eba5b6SRobert Mustacchi
81675eba5b6SRobert Mustacchi /*
81775eba5b6SRobert Mustacchi * Save off the current value of register 0x2F5B
81875eba5b6SRobert Mustacchi * to be restored at the end of the routines.
81975eba5b6SRobert Mustacchi */
82075eba5b6SRobert Mustacchi ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data);
82175eba5b6SRobert Mustacchi if (ret_val)
82275eba5b6SRobert Mustacchi goto out;
82375eba5b6SRobert Mustacchi
82475eba5b6SRobert Mustacchi /* Disable the PHY transmitter */
82575eba5b6SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
82675eba5b6SRobert Mustacchi if (ret_val)
82775eba5b6SRobert Mustacchi goto out;
82875eba5b6SRobert Mustacchi
82975eba5b6SRobert Mustacchi msec_delay_irq(20);
83075eba5b6SRobert Mustacchi
831*42cc51e0SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x0000,
83275eba5b6SRobert Mustacchi IGP01E1000_IEEE_FORCE_GIG);
83375eba5b6SRobert Mustacchi if (ret_val)
83475eba5b6SRobert Mustacchi goto out;
83575eba5b6SRobert Mustacchi
836*42cc51e0SRobert Mustacchi ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_DSP_FFE,
83775eba5b6SRobert Mustacchi IGP01E1000_PHY_DSP_FFE_DEFAULT);
83875eba5b6SRobert Mustacchi if (ret_val)
83975eba5b6SRobert Mustacchi goto out;
84075eba5b6SRobert Mustacchi
841*42cc51e0SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x0000,
84275eba5b6SRobert Mustacchi IGP01E1000_IEEE_RESTART_AUTONEG);
84375eba5b6SRobert Mustacchi if (ret_val)
84475eba5b6SRobert Mustacchi goto out;
84575eba5b6SRobert Mustacchi
84675eba5b6SRobert Mustacchi msec_delay_irq(20);
84775eba5b6SRobert Mustacchi
84875eba5b6SRobert Mustacchi /* Now enable the transmitter */
84975eba5b6SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data);
85075eba5b6SRobert Mustacchi
85175eba5b6SRobert Mustacchi if (ret_val)
85275eba5b6SRobert Mustacchi goto out;
85375eba5b6SRobert Mustacchi
85475eba5b6SRobert Mustacchi dev_spec->ffe_config = e1000_ffe_config_enabled;
85575eba5b6SRobert Mustacchi }
85675eba5b6SRobert Mustacchi
85775eba5b6SRobert Mustacchi out:
85875eba5b6SRobert Mustacchi return ret_val;
85975eba5b6SRobert Mustacchi }
86075eba5b6SRobert Mustacchi
86175eba5b6SRobert Mustacchi /**
86275eba5b6SRobert Mustacchi * e1000_get_cable_length_igp_82541 - Determine cable length for igp PHY
86375eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
86475eba5b6SRobert Mustacchi *
86575eba5b6SRobert Mustacchi * The automatic gain control (agc) normalizes the amplitude of the
86675eba5b6SRobert Mustacchi * received signal, adjusting for the attenuation produced by the
86775eba5b6SRobert Mustacchi * cable. By reading the AGC registers, which represent the
86875eba5b6SRobert Mustacchi * combination of coarse and fine gain value, the value can be put
86975eba5b6SRobert Mustacchi * into a lookup table to obtain the approximate cable length
87075eba5b6SRobert Mustacchi * for each channel.
87175eba5b6SRobert Mustacchi **/
e1000_get_cable_length_igp_82541(struct e1000_hw * hw)87275eba5b6SRobert Mustacchi static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw)
87375eba5b6SRobert Mustacchi {
87475eba5b6SRobert Mustacchi struct e1000_phy_info *phy = &hw->phy;
87575eba5b6SRobert Mustacchi s32 ret_val = E1000_SUCCESS;
87675eba5b6SRobert Mustacchi u16 i, data;
87775eba5b6SRobert Mustacchi u16 cur_agc_value, agc_value = 0;
87875eba5b6SRobert Mustacchi u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
879*42cc51e0SRobert Mustacchi u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {IGP01E1000_PHY_AGC_A,
88075eba5b6SRobert Mustacchi IGP01E1000_PHY_AGC_B,
88175eba5b6SRobert Mustacchi IGP01E1000_PHY_AGC_C,
88275eba5b6SRobert Mustacchi IGP01E1000_PHY_AGC_D};
88375eba5b6SRobert Mustacchi
88475eba5b6SRobert Mustacchi DEBUGFUNC("e1000_get_cable_length_igp_82541");
88575eba5b6SRobert Mustacchi
88675eba5b6SRobert Mustacchi /* Read the AGC registers for all channels */
88775eba5b6SRobert Mustacchi for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
88875eba5b6SRobert Mustacchi ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data);
88975eba5b6SRobert Mustacchi if (ret_val)
89075eba5b6SRobert Mustacchi goto out;
89175eba5b6SRobert Mustacchi
89275eba5b6SRobert Mustacchi cur_agc_value = data >> IGP01E1000_AGC_LENGTH_SHIFT;
89375eba5b6SRobert Mustacchi
89475eba5b6SRobert Mustacchi /* Bounds checking */
89575eba5b6SRobert Mustacchi if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
89675eba5b6SRobert Mustacchi (cur_agc_value == 0)) {
89775eba5b6SRobert Mustacchi ret_val = -E1000_ERR_PHY;
89875eba5b6SRobert Mustacchi goto out;
89975eba5b6SRobert Mustacchi }
90075eba5b6SRobert Mustacchi
90175eba5b6SRobert Mustacchi agc_value += cur_agc_value;
90275eba5b6SRobert Mustacchi
90375eba5b6SRobert Mustacchi if (min_agc_value > cur_agc_value)
90475eba5b6SRobert Mustacchi min_agc_value = cur_agc_value;
90575eba5b6SRobert Mustacchi }
90675eba5b6SRobert Mustacchi
90775eba5b6SRobert Mustacchi /* Remove the minimal AGC result for length < 50m */
90875eba5b6SRobert Mustacchi if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * 50) {
90975eba5b6SRobert Mustacchi agc_value -= min_agc_value;
91075eba5b6SRobert Mustacchi /* Average the three remaining channels for the length. */
91175eba5b6SRobert Mustacchi agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
91275eba5b6SRobert Mustacchi } else {
91375eba5b6SRobert Mustacchi /* Average the channels for the length. */
91475eba5b6SRobert Mustacchi agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
91575eba5b6SRobert Mustacchi }
91675eba5b6SRobert Mustacchi
91775eba5b6SRobert Mustacchi phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] >
91875eba5b6SRobert Mustacchi IGP01E1000_AGC_RANGE)
91975eba5b6SRobert Mustacchi ? (e1000_igp_cable_length_table[agc_value] -
92075eba5b6SRobert Mustacchi IGP01E1000_AGC_RANGE)
92175eba5b6SRobert Mustacchi : 0;
92275eba5b6SRobert Mustacchi phy->max_cable_length = e1000_igp_cable_length_table[agc_value] +
92375eba5b6SRobert Mustacchi IGP01E1000_AGC_RANGE;
92475eba5b6SRobert Mustacchi
92575eba5b6SRobert Mustacchi phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
92675eba5b6SRobert Mustacchi
92775eba5b6SRobert Mustacchi out:
92875eba5b6SRobert Mustacchi return ret_val;
92975eba5b6SRobert Mustacchi }
93075eba5b6SRobert Mustacchi
93175eba5b6SRobert Mustacchi /**
93275eba5b6SRobert Mustacchi * e1000_set_d3_lplu_state_82541 - Sets low power link up state for D3
93375eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
93475eba5b6SRobert Mustacchi * @active: boolean used to enable/disable lplu
93575eba5b6SRobert Mustacchi *
93675eba5b6SRobert Mustacchi * Success returns 0, Failure returns 1
93775eba5b6SRobert Mustacchi *
93875eba5b6SRobert Mustacchi * The low power link up (lplu) state is set to the power management level D3
93975eba5b6SRobert Mustacchi * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
94075eba5b6SRobert Mustacchi * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
94175eba5b6SRobert Mustacchi * is used during Dx states where the power conservation is most important.
94275eba5b6SRobert Mustacchi * During driver activity, SmartSpeed should be enabled so performance is
94375eba5b6SRobert Mustacchi * maintained.
94475eba5b6SRobert Mustacchi **/
e1000_set_d3_lplu_state_82541(struct e1000_hw * hw,bool active)94575eba5b6SRobert Mustacchi static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active)
94675eba5b6SRobert Mustacchi {
94775eba5b6SRobert Mustacchi struct e1000_phy_info *phy = &hw->phy;
94875eba5b6SRobert Mustacchi s32 ret_val;
94975eba5b6SRobert Mustacchi u16 data;
95075eba5b6SRobert Mustacchi
95175eba5b6SRobert Mustacchi DEBUGFUNC("e1000_set_d3_lplu_state_82541");
95275eba5b6SRobert Mustacchi
95375eba5b6SRobert Mustacchi switch (hw->mac.type) {
95475eba5b6SRobert Mustacchi case e1000_82541_rev_2:
95575eba5b6SRobert Mustacchi case e1000_82547_rev_2:
95675eba5b6SRobert Mustacchi break;
95775eba5b6SRobert Mustacchi default:
95875eba5b6SRobert Mustacchi ret_val = e1000_set_d3_lplu_state_generic(hw, active);
95975eba5b6SRobert Mustacchi goto out;
96075eba5b6SRobert Mustacchi break;
96175eba5b6SRobert Mustacchi }
96275eba5b6SRobert Mustacchi
96375eba5b6SRobert Mustacchi ret_val = phy->ops.read_reg(hw, IGP01E1000_GMII_FIFO, &data);
96475eba5b6SRobert Mustacchi if (ret_val)
96575eba5b6SRobert Mustacchi goto out;
96675eba5b6SRobert Mustacchi
96775eba5b6SRobert Mustacchi if (!active) {
96875eba5b6SRobert Mustacchi data &= ~IGP01E1000_GMII_FLEX_SPD;
96975eba5b6SRobert Mustacchi ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
97075eba5b6SRobert Mustacchi if (ret_val)
97175eba5b6SRobert Mustacchi goto out;
97275eba5b6SRobert Mustacchi
97375eba5b6SRobert Mustacchi /*
97475eba5b6SRobert Mustacchi * LPLU and SmartSpeed are mutually exclusive. LPLU is used
97575eba5b6SRobert Mustacchi * during Dx states where the power conservation is most
97675eba5b6SRobert Mustacchi * important. During driver activity we should enable
97775eba5b6SRobert Mustacchi * SmartSpeed, so performance is maintained.
97875eba5b6SRobert Mustacchi */
97975eba5b6SRobert Mustacchi if (phy->smart_speed == e1000_smart_speed_on) {
98075eba5b6SRobert Mustacchi ret_val = phy->ops.read_reg(hw,
98175eba5b6SRobert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
98275eba5b6SRobert Mustacchi &data);
98375eba5b6SRobert Mustacchi if (ret_val)
98475eba5b6SRobert Mustacchi goto out;
98575eba5b6SRobert Mustacchi
98675eba5b6SRobert Mustacchi data |= IGP01E1000_PSCFR_SMART_SPEED;
98775eba5b6SRobert Mustacchi ret_val = phy->ops.write_reg(hw,
98875eba5b6SRobert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
98975eba5b6SRobert Mustacchi data);
99075eba5b6SRobert Mustacchi if (ret_val)
99175eba5b6SRobert Mustacchi goto out;
99275eba5b6SRobert Mustacchi } else if (phy->smart_speed == e1000_smart_speed_off) {
99375eba5b6SRobert Mustacchi ret_val = phy->ops.read_reg(hw,
99475eba5b6SRobert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
99575eba5b6SRobert Mustacchi &data);
99675eba5b6SRobert Mustacchi if (ret_val)
99775eba5b6SRobert Mustacchi goto out;
99875eba5b6SRobert Mustacchi
99975eba5b6SRobert Mustacchi data &= ~IGP01E1000_PSCFR_SMART_SPEED;
100075eba5b6SRobert Mustacchi ret_val = phy->ops.write_reg(hw,
100175eba5b6SRobert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
100275eba5b6SRobert Mustacchi data);
100375eba5b6SRobert Mustacchi if (ret_val)
100475eba5b6SRobert Mustacchi goto out;
100575eba5b6SRobert Mustacchi }
100675eba5b6SRobert Mustacchi } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
100775eba5b6SRobert Mustacchi (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
100875eba5b6SRobert Mustacchi (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
100975eba5b6SRobert Mustacchi data |= IGP01E1000_GMII_FLEX_SPD;
101075eba5b6SRobert Mustacchi ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
101175eba5b6SRobert Mustacchi if (ret_val)
101275eba5b6SRobert Mustacchi goto out;
101375eba5b6SRobert Mustacchi
101475eba5b6SRobert Mustacchi /* When LPLU is enabled, we should disable SmartSpeed */
1015*42cc51e0SRobert Mustacchi ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
101675eba5b6SRobert Mustacchi &data);
101775eba5b6SRobert Mustacchi if (ret_val)
101875eba5b6SRobert Mustacchi goto out;
101975eba5b6SRobert Mustacchi
102075eba5b6SRobert Mustacchi data &= ~IGP01E1000_PSCFR_SMART_SPEED;
1021*42cc51e0SRobert Mustacchi ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
102275eba5b6SRobert Mustacchi data);
102375eba5b6SRobert Mustacchi }
102475eba5b6SRobert Mustacchi
102575eba5b6SRobert Mustacchi out:
102675eba5b6SRobert Mustacchi return ret_val;
102775eba5b6SRobert Mustacchi }
102875eba5b6SRobert Mustacchi
102975eba5b6SRobert Mustacchi /**
103075eba5b6SRobert Mustacchi * e1000_setup_led_82541 - Configures SW controllable LED
103175eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
103275eba5b6SRobert Mustacchi *
103375eba5b6SRobert Mustacchi * This prepares the SW controllable LED for use and saves the current state
103475eba5b6SRobert Mustacchi * of the LED so it can be later restored.
103575eba5b6SRobert Mustacchi **/
e1000_setup_led_82541(struct e1000_hw * hw)103675eba5b6SRobert Mustacchi static s32 e1000_setup_led_82541(struct e1000_hw *hw)
103775eba5b6SRobert Mustacchi {
103875eba5b6SRobert Mustacchi struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
103975eba5b6SRobert Mustacchi s32 ret_val;
104075eba5b6SRobert Mustacchi
104175eba5b6SRobert Mustacchi DEBUGFUNC("e1000_setup_led_82541");
104275eba5b6SRobert Mustacchi
1043*42cc51e0SRobert Mustacchi ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO,
104475eba5b6SRobert Mustacchi &dev_spec->spd_default);
104575eba5b6SRobert Mustacchi if (ret_val)
104675eba5b6SRobert Mustacchi goto out;
104775eba5b6SRobert Mustacchi
1048*42cc51e0SRobert Mustacchi ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO,
104975eba5b6SRobert Mustacchi (u16)(dev_spec->spd_default &
105075eba5b6SRobert Mustacchi ~IGP01E1000_GMII_SPD));
105175eba5b6SRobert Mustacchi if (ret_val)
105275eba5b6SRobert Mustacchi goto out;
105375eba5b6SRobert Mustacchi
105475eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
105575eba5b6SRobert Mustacchi
105675eba5b6SRobert Mustacchi out:
105775eba5b6SRobert Mustacchi return ret_val;
105875eba5b6SRobert Mustacchi }
105975eba5b6SRobert Mustacchi
106075eba5b6SRobert Mustacchi /**
106175eba5b6SRobert Mustacchi * e1000_cleanup_led_82541 - Set LED config to default operation
106275eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
106375eba5b6SRobert Mustacchi *
106475eba5b6SRobert Mustacchi * Remove the current LED configuration and set the LED configuration
106575eba5b6SRobert Mustacchi * to the default value, saved from the EEPROM.
106675eba5b6SRobert Mustacchi **/
e1000_cleanup_led_82541(struct e1000_hw * hw)106775eba5b6SRobert Mustacchi static s32 e1000_cleanup_led_82541(struct e1000_hw *hw)
106875eba5b6SRobert Mustacchi {
106975eba5b6SRobert Mustacchi struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
107075eba5b6SRobert Mustacchi s32 ret_val;
107175eba5b6SRobert Mustacchi
107275eba5b6SRobert Mustacchi DEBUGFUNC("e1000_cleanup_led_82541");
107375eba5b6SRobert Mustacchi
1074*42cc51e0SRobert Mustacchi ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO,
107575eba5b6SRobert Mustacchi dev_spec->spd_default);
107675eba5b6SRobert Mustacchi if (ret_val)
107775eba5b6SRobert Mustacchi goto out;
107875eba5b6SRobert Mustacchi
107975eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default);
108075eba5b6SRobert Mustacchi
108175eba5b6SRobert Mustacchi out:
108275eba5b6SRobert Mustacchi return ret_val;
108375eba5b6SRobert Mustacchi }
108475eba5b6SRobert Mustacchi
108575eba5b6SRobert Mustacchi /**
108675eba5b6SRobert Mustacchi * e1000_phy_init_script_82541 - Initialize GbE PHY
108775eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
108875eba5b6SRobert Mustacchi *
108975eba5b6SRobert Mustacchi * Initializes the IGP PHY.
109075eba5b6SRobert Mustacchi **/
e1000_phy_init_script_82541(struct e1000_hw * hw)109175eba5b6SRobert Mustacchi static s32 e1000_phy_init_script_82541(struct e1000_hw *hw)
109275eba5b6SRobert Mustacchi {
109375eba5b6SRobert Mustacchi struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
109475eba5b6SRobert Mustacchi u32 ret_val;
109575eba5b6SRobert Mustacchi u16 phy_saved_data;
109675eba5b6SRobert Mustacchi
109775eba5b6SRobert Mustacchi DEBUGFUNC("e1000_phy_init_script_82541");
109875eba5b6SRobert Mustacchi
109975eba5b6SRobert Mustacchi if (!dev_spec->phy_init_script) {
110075eba5b6SRobert Mustacchi ret_val = E1000_SUCCESS;
110175eba5b6SRobert Mustacchi goto out;
110275eba5b6SRobert Mustacchi }
110375eba5b6SRobert Mustacchi
110475eba5b6SRobert Mustacchi /* Delay after phy reset to enable NVM configuration to load */
110575eba5b6SRobert Mustacchi msec_delay(20);
110675eba5b6SRobert Mustacchi
110775eba5b6SRobert Mustacchi /*
110875eba5b6SRobert Mustacchi * Save off the current value of register 0x2F5B to be restored at
110975eba5b6SRobert Mustacchi * the end of this routine.
111075eba5b6SRobert Mustacchi */
111175eba5b6SRobert Mustacchi ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data);
111275eba5b6SRobert Mustacchi
111375eba5b6SRobert Mustacchi /* Disabled the PHY transmitter */
111475eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003);
111575eba5b6SRobert Mustacchi
111675eba5b6SRobert Mustacchi msec_delay(20);
111775eba5b6SRobert Mustacchi
111875eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
111975eba5b6SRobert Mustacchi
112075eba5b6SRobert Mustacchi msec_delay(5);
112175eba5b6SRobert Mustacchi
112275eba5b6SRobert Mustacchi switch (hw->mac.type) {
112375eba5b6SRobert Mustacchi case e1000_82541:
112475eba5b6SRobert Mustacchi case e1000_82547:
112575eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x1F95, 0x0001);
112675eba5b6SRobert Mustacchi
112775eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21);
112875eba5b6SRobert Mustacchi
112975eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x1F79, 0x0018);
113075eba5b6SRobert Mustacchi
113175eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x1F30, 0x1600);
113275eba5b6SRobert Mustacchi
113375eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x1F31, 0x0014);
113475eba5b6SRobert Mustacchi
113575eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x1F32, 0x161C);
113675eba5b6SRobert Mustacchi
113775eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x1F94, 0x0003);
113875eba5b6SRobert Mustacchi
113975eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x1F96, 0x003F);
114075eba5b6SRobert Mustacchi
114175eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x2010, 0x0008);
114275eba5b6SRobert Mustacchi break;
114375eba5b6SRobert Mustacchi case e1000_82541_rev_2:
114475eba5b6SRobert Mustacchi case e1000_82547_rev_2:
114575eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x1F73, 0x0099);
114675eba5b6SRobert Mustacchi break;
114775eba5b6SRobert Mustacchi default:
114875eba5b6SRobert Mustacchi break;
114975eba5b6SRobert Mustacchi }
115075eba5b6SRobert Mustacchi
115175eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x0000, 0x3300);
115275eba5b6SRobert Mustacchi
115375eba5b6SRobert Mustacchi msec_delay(20);
115475eba5b6SRobert Mustacchi
115575eba5b6SRobert Mustacchi /* Now enable the transmitter */
115675eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data);
115775eba5b6SRobert Mustacchi
115875eba5b6SRobert Mustacchi if (hw->mac.type == e1000_82547) {
115975eba5b6SRobert Mustacchi u16 fused, fine, coarse;
116075eba5b6SRobert Mustacchi
116175eba5b6SRobert Mustacchi /* Move to analog registers page */
1162*42cc51e0SRobert Mustacchi hw->phy.ops.read_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
116375eba5b6SRobert Mustacchi &fused);
116475eba5b6SRobert Mustacchi
116575eba5b6SRobert Mustacchi if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
1166*42cc51e0SRobert Mustacchi hw->phy.ops.read_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS,
116775eba5b6SRobert Mustacchi &fused);
116875eba5b6SRobert Mustacchi
116975eba5b6SRobert Mustacchi fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
117075eba5b6SRobert Mustacchi coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
117175eba5b6SRobert Mustacchi
117275eba5b6SRobert Mustacchi if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
117375eba5b6SRobert Mustacchi coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
117475eba5b6SRobert Mustacchi fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
117575eba5b6SRobert Mustacchi } else if (coarse ==
117675eba5b6SRobert Mustacchi IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
117775eba5b6SRobert Mustacchi fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
117875eba5b6SRobert Mustacchi
117975eba5b6SRobert Mustacchi fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
118075eba5b6SRobert Mustacchi (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
118175eba5b6SRobert Mustacchi (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
118275eba5b6SRobert Mustacchi
118375eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw,
118475eba5b6SRobert Mustacchi IGP01E1000_ANALOG_FUSE_CONTROL,
118575eba5b6SRobert Mustacchi fused);
118675eba5b6SRobert Mustacchi hw->phy.ops.write_reg(hw,
118775eba5b6SRobert Mustacchi IGP01E1000_ANALOG_FUSE_BYPASS,
118875eba5b6SRobert Mustacchi IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
118975eba5b6SRobert Mustacchi }
119075eba5b6SRobert Mustacchi }
119175eba5b6SRobert Mustacchi
119275eba5b6SRobert Mustacchi out:
119375eba5b6SRobert Mustacchi return ret_val;
119475eba5b6SRobert Mustacchi }
119575eba5b6SRobert Mustacchi
119675eba5b6SRobert Mustacchi /**
119775eba5b6SRobert Mustacchi * e1000_init_script_state_82541 - Enable/Disable PHY init script
119875eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
119975eba5b6SRobert Mustacchi * @state: boolean value used to enable/disable PHY init script
120075eba5b6SRobert Mustacchi *
120175eba5b6SRobert Mustacchi * Allows the driver to enable/disable the PHY init script, if the PHY is an
120275eba5b6SRobert Mustacchi * IGP PHY.
120375eba5b6SRobert Mustacchi **/
e1000_init_script_state_82541(struct e1000_hw * hw,bool state)120475eba5b6SRobert Mustacchi void e1000_init_script_state_82541(struct e1000_hw *hw, bool state)
120575eba5b6SRobert Mustacchi {
120675eba5b6SRobert Mustacchi struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
120775eba5b6SRobert Mustacchi
120875eba5b6SRobert Mustacchi DEBUGFUNC("e1000_init_script_state_82541");
120975eba5b6SRobert Mustacchi
121075eba5b6SRobert Mustacchi if (hw->phy.type != e1000_phy_igp) {
121175eba5b6SRobert Mustacchi DEBUGOUT("Initialization script not necessary.\n");
121275eba5b6SRobert Mustacchi goto out;
121375eba5b6SRobert Mustacchi }
121475eba5b6SRobert Mustacchi
121575eba5b6SRobert Mustacchi dev_spec->phy_init_script = state;
121675eba5b6SRobert Mustacchi
121775eba5b6SRobert Mustacchi out:
121875eba5b6SRobert Mustacchi return;
121975eba5b6SRobert Mustacchi }
122075eba5b6SRobert Mustacchi
122175eba5b6SRobert Mustacchi /**
122275eba5b6SRobert Mustacchi * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down
122375eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
122475eba5b6SRobert Mustacchi *
122575eba5b6SRobert Mustacchi * In the case of a PHY power down to save power, or to turn off link during a
122675eba5b6SRobert Mustacchi * driver unload, or wake on lan is not enabled, remove the link.
122775eba5b6SRobert Mustacchi **/
e1000_power_down_phy_copper_82541(struct e1000_hw * hw)122875eba5b6SRobert Mustacchi static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw)
122975eba5b6SRobert Mustacchi {
123075eba5b6SRobert Mustacchi /* If the management interface is not enabled, then power down */
123175eba5b6SRobert Mustacchi if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN))
123275eba5b6SRobert Mustacchi e1000_power_down_phy_copper(hw);
123375eba5b6SRobert Mustacchi
123475eba5b6SRobert Mustacchi return;
123575eba5b6SRobert Mustacchi }
123675eba5b6SRobert Mustacchi
123775eba5b6SRobert Mustacchi /**
123875eba5b6SRobert Mustacchi * e1000_clear_hw_cntrs_82541 - Clear device specific hardware counters
123975eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
124075eba5b6SRobert Mustacchi *
124175eba5b6SRobert Mustacchi * Clears the hardware counters by reading the counter registers.
124275eba5b6SRobert Mustacchi **/
e1000_clear_hw_cntrs_82541(struct e1000_hw * hw)124375eba5b6SRobert Mustacchi static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw)
124475eba5b6SRobert Mustacchi {
124575eba5b6SRobert Mustacchi DEBUGFUNC("e1000_clear_hw_cntrs_82541");
124675eba5b6SRobert Mustacchi
124775eba5b6SRobert Mustacchi e1000_clear_hw_cntrs_base_generic(hw);
124875eba5b6SRobert Mustacchi
124975eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC64);
125075eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC127);
125175eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC255);
125275eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC511);
125375eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC1023);
125475eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC1522);
125575eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC64);
125675eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC127);
125775eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC255);
125875eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC511);
125975eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC1023);
126075eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC1522);
126175eba5b6SRobert Mustacchi
126275eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_ALGNERRC);
126375eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_RXERRC);
126475eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_TNCRS);
126575eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_CEXTERR);
126675eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_TSCTC);
126775eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_TSCTFC);
126875eba5b6SRobert Mustacchi
126975eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_MGTPRC);
127075eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_MGTPDC);
127175eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_MGTPTC);
127275eba5b6SRobert Mustacchi }
127375eba5b6SRobert Mustacchi
127475eba5b6SRobert Mustacchi /**
127575eba5b6SRobert Mustacchi * e1000_read_mac_addr_82541 - Read device MAC address
127675eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
127775eba5b6SRobert Mustacchi *
127875eba5b6SRobert Mustacchi * Reads the device MAC address from the EEPROM and stores the value.
127975eba5b6SRobert Mustacchi **/
e1000_read_mac_addr_82541(struct e1000_hw * hw)128075eba5b6SRobert Mustacchi static s32 e1000_read_mac_addr_82541(struct e1000_hw *hw)
128175eba5b6SRobert Mustacchi {
128275eba5b6SRobert Mustacchi s32 ret_val = E1000_SUCCESS;
128375eba5b6SRobert Mustacchi u16 offset, nvm_data, i;
128475eba5b6SRobert Mustacchi
128575eba5b6SRobert Mustacchi DEBUGFUNC("e1000_read_mac_addr");
128675eba5b6SRobert Mustacchi
128775eba5b6SRobert Mustacchi for (i = 0; i < ETH_ADDR_LEN; i += 2) {
128875eba5b6SRobert Mustacchi offset = i >> 1;
128975eba5b6SRobert Mustacchi ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
129075eba5b6SRobert Mustacchi if (ret_val) {
129175eba5b6SRobert Mustacchi DEBUGOUT("NVM Read Error\n");
129275eba5b6SRobert Mustacchi goto out;
129375eba5b6SRobert Mustacchi }
129475eba5b6SRobert Mustacchi hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
129575eba5b6SRobert Mustacchi hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
129675eba5b6SRobert Mustacchi }
129775eba5b6SRobert Mustacchi
129875eba5b6SRobert Mustacchi for (i = 0; i < ETH_ADDR_LEN; i++)
129975eba5b6SRobert Mustacchi hw->mac.addr[i] = hw->mac.perm_addr[i];
130075eba5b6SRobert Mustacchi
130175eba5b6SRobert Mustacchi out:
130275eba5b6SRobert Mustacchi return ret_val;
130375eba5b6SRobert Mustacchi }
130475eba5b6SRobert Mustacchi
1305