xref: /titanic_53/usr/src/uts/common/io/e1000api/e1000_82541.c (revision 42cc51e07cdbcad3b9aca8d9d991fc09b251feb7)
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