175eba5b6SRobert Mustacchi /******************************************************************************
275eba5b6SRobert Mustacchi 
3*49b78600SRobert 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$*/
34592a4d85Scc 
3525f2d433Sxy /*
36d5c3073dSchenlu chen - Sun Microsystems - Beijing China  * 82541EI Gigabit Ethernet Controller
37d5c3073dSchenlu chen - Sun Microsystems - Beijing China  * 82541ER Gigabit Ethernet Controller
38d5c3073dSchenlu chen - Sun Microsystems - Beijing China  * 82541GI Gigabit Ethernet Controller
39d5c3073dSchenlu chen - Sun Microsystems - Beijing China  * 82541PI Gigabit Ethernet Controller
40d5c3073dSchenlu chen - Sun Microsystems - Beijing China  * 82547EI Gigabit Ethernet Controller
41d5c3073dSchenlu chen - Sun Microsystems - Beijing China  * 82547GI Gigabit Ethernet Controller
4225f2d433Sxy  */
4325f2d433Sxy 
4425f2d433Sxy #include "e1000_api.h"
4525f2d433Sxy 
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,
52*49b78600SRobert 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,
58*49b78600SRobert 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);
6125f2d433Sxy 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,
64*49b78600SRobert Mustacchi 						     bool link_up);
6575eba5b6SRobert Mustacchi static s32  e1000_phy_init_script_82541(struct e1000_hw *hw);
66592a4d85Scc static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw);
6725f2d433Sxy 
68*49b78600SRobert Mustacchi static const u16 e1000_igp_cable_length_table[] = {
69*49b78600SRobert Mustacchi 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10,
70*49b78600SRobert Mustacchi 	10, 10, 20, 20, 20, 20, 20, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30,
71*49b78600SRobert Mustacchi 	40, 40, 40, 40, 40, 40, 40, 40, 40, 50, 50, 50, 50, 50, 50, 50, 60, 60,
72*49b78600SRobert Mustacchi 	60, 60, 60, 60, 60, 60, 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80,
73*49b78600SRobert Mustacchi 	80, 90, 90, 90, 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100,
74*49b78600SRobert Mustacchi 	100, 100, 100, 100, 100, 100, 100, 100, 110, 110, 110, 110, 110, 110,
75*49b78600SRobert Mustacchi 	110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 120, 120,
76*49b78600SRobert Mustacchi 	120, 120, 120, 120, 120, 120, 120, 120};
7775eba5b6SRobert Mustacchi #define IGP01E1000_AGC_LENGTH_TABLE_SIZE \
78*49b78600SRobert Mustacchi 		(sizeof(e1000_igp_cable_length_table) / \
79*49b78600SRobert 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)
8625f2d433Sxy {
8725f2d433Sxy 	struct e1000_phy_info *phy = &hw->phy;
88*49b78600SRobert Mustacchi 	s32 ret_val;
8925f2d433Sxy 
9025f2d433Sxy 	DEBUGFUNC("e1000_init_phy_params_82541");
9125f2d433Sxy 
92*49b78600SRobert Mustacchi 	phy->addr		= 1;
93*49b78600SRobert Mustacchi 	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
94*49b78600SRobert Mustacchi 	phy->reset_delay_us	= 10000;
95*49b78600SRobert Mustacchi 	phy->type		= e1000_phy_igp;
9625f2d433Sxy 
9725f2d433Sxy 	/* Function Pointers */
98*49b78600SRobert Mustacchi 	phy->ops.check_polarity	= e1000_check_polarity_igp;
99*49b78600SRobert Mustacchi 	phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
100*49b78600SRobert Mustacchi 	phy->ops.get_cable_length = e1000_get_cable_length_igp_82541;
101*49b78600SRobert Mustacchi 	phy->ops.get_cfg_done	= e1000_get_cfg_done_generic;
102*49b78600SRobert Mustacchi 	phy->ops.get_info	= e1000_get_phy_info_igp;
103*49b78600SRobert Mustacchi 	phy->ops.read_reg	= e1000_read_phy_reg_igp;
104*49b78600SRobert Mustacchi 	phy->ops.reset		= e1000_phy_hw_reset_82541;
105*49b78600SRobert Mustacchi 	phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82541;
106*49b78600SRobert Mustacchi 	phy->ops.write_reg	= e1000_write_phy_reg_igp;
107*49b78600SRobert Mustacchi 	phy->ops.power_up	= e1000_power_up_phy_copper;
108*49b78600SRobert Mustacchi 	phy->ops.power_down	= e1000_power_down_phy_copper_82541;
10925f2d433Sxy 
11025f2d433Sxy 	ret_val = e1000_get_phy_id(hw);
11125f2d433Sxy 	if (ret_val)
11225f2d433Sxy 		goto out;
11325f2d433Sxy 
11425f2d433Sxy 	/* Verify phy id */
11525f2d433Sxy 	if (phy->id != IGP01E1000_I_PHY_ID) {
11625f2d433Sxy 		ret_val = -E1000_ERR_PHY;
11725f2d433Sxy 		goto out;
11825f2d433Sxy 	}
119caf05df5SMiles Xu, Sun Microsystems 
12025f2d433Sxy out:
12175eba5b6SRobert Mustacchi 	return ret_val;
12225f2d433Sxy }
12325f2d433Sxy 
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)
12925f2d433Sxy {
130*49b78600SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
131*49b78600SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
13225f2d433Sxy 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
13325f2d433Sxy 	u16 size;
13425f2d433Sxy 
13525f2d433Sxy 	DEBUGFUNC("e1000_init_nvm_params_82541");
13625f2d433Sxy 
13725f2d433Sxy 	switch (nvm->override) {
13825f2d433Sxy 	case e1000_nvm_override_spi_large:
13925f2d433Sxy 		nvm->type = e1000_nvm_eeprom_spi;
14025f2d433Sxy 		eecd |= E1000_EECD_ADDR_BITS;
14125f2d433Sxy 		break;
14225f2d433Sxy 	case e1000_nvm_override_spi_small:
14325f2d433Sxy 		nvm->type = e1000_nvm_eeprom_spi;
14425f2d433Sxy 		eecd &= ~E1000_EECD_ADDR_BITS;
14525f2d433Sxy 		break;
14625f2d433Sxy 	case e1000_nvm_override_microwire_large:
14725f2d433Sxy 		nvm->type = e1000_nvm_eeprom_microwire;
14825f2d433Sxy 		eecd |= E1000_EECD_SIZE;
14925f2d433Sxy 		break;
15025f2d433Sxy 	case e1000_nvm_override_microwire_small:
15125f2d433Sxy 		nvm->type = e1000_nvm_eeprom_microwire;
15225f2d433Sxy 		eecd &= ~E1000_EECD_SIZE;
15325f2d433Sxy 		break;
15425f2d433Sxy 	default:
155*49b78600SRobert Mustacchi 		nvm->type = eecd & E1000_EECD_TYPE ? e1000_nvm_eeprom_spi
156*49b78600SRobert Mustacchi 			    : e1000_nvm_eeprom_microwire;
15725f2d433Sxy 		break;
15825f2d433Sxy 	}
15925f2d433Sxy 
16025f2d433Sxy 	if (nvm->type == e1000_nvm_eeprom_spi) {
161*49b78600SRobert Mustacchi 		nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) ? 16 : 8;
162*49b78600SRobert Mustacchi 		nvm->delay_usec = 1;
163*49b78600SRobert Mustacchi 		nvm->opcode_bits = 8;
164*49b78600SRobert Mustacchi 		nvm->page_size = (eecd & E1000_EECD_ADDR_BITS) ? 32 : 8;
16525f2d433Sxy 
16625f2d433Sxy 		/* Function Pointers */
167*49b78600SRobert Mustacchi 		nvm->ops.acquire	= e1000_acquire_nvm_generic;
168*49b78600SRobert Mustacchi 		nvm->ops.read		= e1000_read_nvm_spi;
169*49b78600SRobert Mustacchi 		nvm->ops.release	= e1000_release_nvm_generic;
170*49b78600SRobert Mustacchi 		nvm->ops.update		= e1000_update_nvm_checksum_generic;
171592a4d85Scc 		nvm->ops.valid_led_default = e1000_valid_led_default_generic;
172*49b78600SRobert Mustacchi 		nvm->ops.validate	= e1000_validate_nvm_checksum_generic;
173*49b78600SRobert Mustacchi 		nvm->ops.write		= e1000_write_nvm_spi;
17425f2d433Sxy 
17525f2d433Sxy 		/*
17625f2d433Sxy 		 * nvm->word_size must be discovered after the pointers
17725f2d433Sxy 		 * are set so we can verify the size from the nvm image
17875eba5b6SRobert Mustacchi 		 * itself.  Temporarily set it to a dummy value so the
17925f2d433Sxy 		 * read will work.
18025f2d433Sxy 		 */
18125f2d433Sxy 		nvm->word_size = 64;
182592a4d85Scc 		ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size);
18325f2d433Sxy 		if (ret_val)
18425f2d433Sxy 			goto out;
18525f2d433Sxy 		size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT;
18625f2d433Sxy 		/*
18725f2d433Sxy 		 * if size != 0, it can be added to a constant and become
18825f2d433Sxy 		 * the left-shift value to set the word_size.  Otherwise,
18925f2d433Sxy 		 * word_size stays at 64.
19025f2d433Sxy 		 */
19125f2d433Sxy 		if (size) {
19225f2d433Sxy 			size += NVM_WORD_SIZE_BASE_SHIFT_82541;
19325f2d433Sxy 			nvm->word_size = 1 << size;
19425f2d433Sxy 		}
19525f2d433Sxy 	} else {
196*49b78600SRobert Mustacchi 		nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) ? 8 : 6;
197*49b78600SRobert Mustacchi 		nvm->delay_usec = 50;
198*49b78600SRobert Mustacchi 		nvm->opcode_bits = 3;
199*49b78600SRobert Mustacchi 		nvm->word_size = (eecd & E1000_EECD_ADDR_BITS) ? 256 : 64;
20025f2d433Sxy 
20125f2d433Sxy 		/* Function Pointers */
202*49b78600SRobert Mustacchi 		nvm->ops.acquire	= e1000_acquire_nvm_generic;
203*49b78600SRobert Mustacchi 		nvm->ops.read		= e1000_read_nvm_microwire;
204*49b78600SRobert Mustacchi 		nvm->ops.release	= e1000_release_nvm_generic;
205*49b78600SRobert Mustacchi 		nvm->ops.update		= e1000_update_nvm_checksum_generic;
206592a4d85Scc 		nvm->ops.valid_led_default = e1000_valid_led_default_generic;
207*49b78600SRobert Mustacchi 		nvm->ops.validate	= e1000_validate_nvm_checksum_generic;
208*49b78600SRobert Mustacchi 		nvm->ops.write		= e1000_write_nvm_microwire;
20925f2d433Sxy 	}
21025f2d433Sxy 
21125f2d433Sxy out:
21275eba5b6SRobert Mustacchi 	return ret_val;
21325f2d433Sxy }
21425f2d433Sxy 
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)
22025f2d433Sxy {
22125f2d433Sxy 	struct e1000_mac_info *mac = &hw->mac;
22225f2d433Sxy 
22325f2d433Sxy 	DEBUGFUNC("e1000_init_mac_params_82541");
22425f2d433Sxy 
22525f2d433Sxy 	/* Set media type */
226592a4d85Scc 	hw->phy.media_type = e1000_media_type_copper;
22725f2d433Sxy 	/* Set mta register count */
22825f2d433Sxy 	mac->mta_reg_count = 128;
22925f2d433Sxy 	/* Set rar entry count */
23025f2d433Sxy 	mac->rar_entry_count = E1000_RAR_ENTRIES;
23125f2d433Sxy 	/* Set if part includes ASF firmware */
23275eba5b6SRobert Mustacchi 	mac->asf_firmware_present = TRUE;
23325f2d433Sxy 
23425f2d433Sxy 	/* Function Pointers */
23525f2d433Sxy 
23625f2d433Sxy 	/* bus type/speed/width */
237592a4d85Scc 	mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
238caf05df5SMiles Xu, Sun Microsystems 	/* function id */
239caf05df5SMiles Xu, Sun Microsystems 	mac->ops.set_lan_id = e1000_set_lan_id_single_port;
24025f2d433Sxy 	/* reset */
241592a4d85Scc 	mac->ops.reset_hw = e1000_reset_hw_82541;
24225f2d433Sxy 	/* hw initialization */
243592a4d85Scc 	mac->ops.init_hw = e1000_init_hw_82541;
24425f2d433Sxy 	/* link setup */
245592a4d85Scc 	mac->ops.setup_link = e1000_setup_link_generic;
24625f2d433Sxy 	/* physical interface link setup */
247592a4d85Scc 	mac->ops.setup_physical_interface = e1000_setup_copper_link_82541;
24825f2d433Sxy 	/* check for link */
249592a4d85Scc 	mac->ops.check_for_link = e1000_check_for_link_82541;
25025f2d433Sxy 	/* link info */
251592a4d85Scc 	mac->ops.get_link_up_info = e1000_get_link_up_info_82541;
25225f2d433Sxy 	/* multicast address update */
253592a4d85Scc 	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
25425f2d433Sxy 	/* writing VFTA */
255592a4d85Scc 	mac->ops.write_vfta = e1000_write_vfta_generic;
25625f2d433Sxy 	/* clearing VFTA */
257592a4d85Scc 	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;
260caf05df5SMiles Xu, Sun Microsystems 	/* ID LED init */
261caf05df5SMiles Xu, Sun Microsystems 	mac->ops.id_led_init = e1000_id_led_init_generic;
26225f2d433Sxy 	/* setup LED */
263592a4d85Scc 	mac->ops.setup_led = e1000_setup_led_82541;
26425f2d433Sxy 	/* cleanup LED */
265592a4d85Scc 	mac->ops.cleanup_led = e1000_cleanup_led_82541;
26625f2d433Sxy 	/* turn on/off LED */
267592a4d85Scc 	mac->ops.led_on = e1000_led_on_generic;
268592a4d85Scc 	mac->ops.led_off = e1000_led_off_generic;
26925f2d433Sxy 	/* clear hardware counters */
270592a4d85Scc 	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541;
27125f2d433Sxy 
27275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
27325f2d433Sxy }
27425f2d433Sxy 
27575eba5b6SRobert Mustacchi /**
27675eba5b6SRobert Mustacchi  *  e1000_init_function_pointers_82541 - Init func ptrs.
27775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
27825f2d433Sxy  *
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)
28225f2d433Sxy {
28325f2d433Sxy 	DEBUGFUNC("e1000_init_function_pointers_82541");
28425f2d433Sxy 
285592a4d85Scc 	hw->mac.ops.init_params = e1000_init_mac_params_82541;
286592a4d85Scc 	hw->nvm.ops.init_params = e1000_init_nvm_params_82541;
287592a4d85Scc 	hw->phy.ops.init_params = e1000_init_phy_params_82541;
28825f2d433Sxy }
28925f2d433Sxy 
29075eba5b6SRobert Mustacchi /**
29175eba5b6SRobert Mustacchi  *  e1000_reset_hw_82541 - Reset hardware
29275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
29325f2d433Sxy  *
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)
29725f2d433Sxy {
298*49b78600SRobert Mustacchi 	u32 ledctl, ctrl, manc;
29925f2d433Sxy 
30025f2d433Sxy 	DEBUGFUNC("e1000_reset_hw_82541");
30125f2d433Sxy 
30225f2d433Sxy 	DEBUGOUT("Masking off all interrupts\n");
30325f2d433Sxy 	E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
30425f2d433Sxy 
30525f2d433Sxy 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
30625f2d433Sxy 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
30725f2d433Sxy 	E1000_WRITE_FLUSH(hw);
30825f2d433Sxy 
30925f2d433Sxy 	/*
31025f2d433Sxy 	 * Delay to allow any outstanding PCI transactions to complete
31125f2d433Sxy 	 * before resetting the device.
31225f2d433Sxy 	 */
31325f2d433Sxy 	msec_delay(10);
31425f2d433Sxy 
31525f2d433Sxy 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
31625f2d433Sxy 
31725f2d433Sxy 	/* Must reset the Phy before resetting the MAC */
31825f2d433Sxy 	if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
31925f2d433Sxy 		E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST));
320*49b78600SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
32125f2d433Sxy 		msec_delay(5);
32225f2d433Sxy 	}
32325f2d433Sxy 
32425f2d433Sxy 	DEBUGOUT("Issuing a global reset to 82541/82547 MAC\n");
32525f2d433Sxy 	switch (hw->mac.type) {
32625f2d433Sxy 	case e1000_82541:
32725f2d433Sxy 	case e1000_82541_rev_2:
32825f2d433Sxy 		/*
32925f2d433Sxy 		 * These controllers can't ack the 64-bit write when
33025f2d433Sxy 		 * issuing the reset, so we use IO-mapping as a
33125f2d433Sxy 		 * workaround to issue the reset.
33225f2d433Sxy 		 */
33325f2d433Sxy 		E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
33425f2d433Sxy 		break;
33525f2d433Sxy 	default:
33625f2d433Sxy 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
33725f2d433Sxy 		break;
33825f2d433Sxy 	}
33925f2d433Sxy 
34025f2d433Sxy 	/* Wait for NVM reload */
34125f2d433Sxy 	msec_delay(20);
34225f2d433Sxy 
34325f2d433Sxy 	/* Disable HW ARPs on ASF enabled adapters */
34425f2d433Sxy 	manc = E1000_READ_REG(hw, E1000_MANC);
34525f2d433Sxy 	manc &= ~E1000_MANC_ARP_EN;
34625f2d433Sxy 	E1000_WRITE_REG(hw, E1000_MANC, manc);
34725f2d433Sxy 
34825f2d433Sxy 	if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
34975eba5b6SRobert Mustacchi 		e1000_phy_init_script_82541(hw);
35025f2d433Sxy 
35125f2d433Sxy 		/* Configure activity LED after Phy reset */
35225f2d433Sxy 		ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
35325f2d433Sxy 		ledctl &= IGP_ACTIVITY_LED_MASK;
35425f2d433Sxy 		ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
35525f2d433Sxy 		E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
35625f2d433Sxy 	}
35725f2d433Sxy 
35825f2d433Sxy 	/* Once again, mask the interrupts */
35925f2d433Sxy 	DEBUGOUT("Masking off all interrupts\n");
36025f2d433Sxy 	E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
36125f2d433Sxy 
36225f2d433Sxy 	/* Clear any pending interrupt events. */
363*49b78600SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICR);
36425f2d433Sxy 
36575eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
36625f2d433Sxy }
36725f2d433Sxy 
36875eba5b6SRobert Mustacchi /**
36975eba5b6SRobert Mustacchi  *  e1000_init_hw_82541 - Initialize hardware
37075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
37125f2d433Sxy  *
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)
37525f2d433Sxy {
37625f2d433Sxy 	struct e1000_mac_info *mac = &hw->mac;
377d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
37825f2d433Sxy 	u32 i, txdctl;
37925f2d433Sxy 	s32 ret_val;
38025f2d433Sxy 
38125f2d433Sxy 	DEBUGFUNC("e1000_init_hw_82541");
38225f2d433Sxy 
38325f2d433Sxy 	/* Initialize identification LED */
384caf05df5SMiles Xu, Sun Microsystems 	ret_val = mac->ops.id_led_init(hw);
38525f2d433Sxy 	if (ret_val) {
38625f2d433Sxy 		DEBUGOUT("Error initializing identification LED\n");
387592a4d85Scc 		/* This is not fatal and we should not stop init due to this */
38825f2d433Sxy 	}
389*49b78600SRobert Mustacchi 
390caf05df5SMiles Xu, Sun Microsystems 	/* Storing the Speed Power Down  value for later use */
391*49b78600SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO,
392*49b78600SRobert Mustacchi 				       &dev_spec->spd_default);
393caf05df5SMiles Xu, Sun Microsystems 	if (ret_val)
394111c450cSMiles Xu, Sun Microsystems 		goto out;
395111c450cSMiles Xu, Sun Microsystems 
39625f2d433Sxy 	/* Disabling VLAN filtering */
39725f2d433Sxy 	DEBUGOUT("Initializing the IEEE VLAN\n");
398592a4d85Scc 	mac->ops.clear_vfta(hw);
39925f2d433Sxy 
40025f2d433Sxy 	/* Setup the receive address. */
40125f2d433Sxy 	e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
40225f2d433Sxy 
40325f2d433Sxy 	/* Zero out the Multicast HASH table */
40425f2d433Sxy 	DEBUGOUT("Zeroing the MTA\n");
40525f2d433Sxy 	for (i = 0; i < mac->mta_reg_count; i++) {
40625f2d433Sxy 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
40725f2d433Sxy 		/*
40825f2d433Sxy 		 * Avoid back to back register writes by adding the register
40925f2d433Sxy 		 * read (flush).  This is to protect against some strange
41025f2d433Sxy 		 * bridge configurations that may issue Memory Write Block
41125f2d433Sxy 		 * (MWB) to our register space.
41225f2d433Sxy 		 */
41325f2d433Sxy 		E1000_WRITE_FLUSH(hw);
41425f2d433Sxy 	}
41525f2d433Sxy 
41625f2d433Sxy 	/* Setup link and flow control */
417592a4d85Scc 	ret_val = mac->ops.setup_link(hw);
41825f2d433Sxy 
419592a4d85Scc 	txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
42025f2d433Sxy 	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
421*49b78600SRobert Mustacchi 		  E1000_TXDCTL_FULL_TX_DESC_WB;
422592a4d85Scc 	E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
42325f2d433Sxy 
42425f2d433Sxy 	/*
42525f2d433Sxy 	 * Clear all of the statistics registers (clear on read).  It is
42625f2d433Sxy 	 * important that we do this after we have tried to establish link
42725f2d433Sxy 	 * because the symbol error count will increment wildly if there
42825f2d433Sxy 	 * is no link.
42925f2d433Sxy 	 */
43025f2d433Sxy 	e1000_clear_hw_cntrs_82541(hw);
43125f2d433Sxy 
432111c450cSMiles Xu, Sun Microsystems out:
43375eba5b6SRobert Mustacchi 	return ret_val;
43425f2d433Sxy }
43525f2d433Sxy 
43675eba5b6SRobert Mustacchi /**
43725f2d433Sxy  * e1000_get_link_up_info_82541 - Report speed and duplex
43825f2d433Sxy  * @hw: pointer to the HW structure
43925f2d433Sxy  * @speed: pointer to speed buffer
44025f2d433Sxy  * @duplex: pointer to duplex buffer
44125f2d433Sxy  *
44225f2d433Sxy  * 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,
445*49b78600SRobert Mustacchi 					u16 *duplex)
44625f2d433Sxy {
44725f2d433Sxy 	struct e1000_phy_info *phy = &hw->phy;
44825f2d433Sxy 	s32 ret_val;
44925f2d433Sxy 	u16 data;
45025f2d433Sxy 
45125f2d433Sxy 	DEBUGFUNC("e1000_get_link_up_info_82541");
45225f2d433Sxy 
45325f2d433Sxy 	ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex);
45425f2d433Sxy 	if (ret_val)
45525f2d433Sxy 		goto out;
45625f2d433Sxy 
45725f2d433Sxy 	if (!phy->speed_downgraded)
45825f2d433Sxy 		goto out;
45925f2d433Sxy 
46025f2d433Sxy 	/*
46125f2d433Sxy 	 * IGP01 PHY may advertise full duplex operation after speed
46225f2d433Sxy 	 * downgrade even if it is operating at half duplex.
46325f2d433Sxy 	 * Here we set the duplex settings to match the duplex in the
46425f2d433Sxy 	 * link partner's capabilities.
46525f2d433Sxy 	 */
466592a4d85Scc 	ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data);
46725f2d433Sxy 	if (ret_val)
46825f2d433Sxy 		goto out;
46925f2d433Sxy 
47025f2d433Sxy 	if (!(data & NWAY_ER_LP_NWAY_CAPS)) {
47125f2d433Sxy 		*duplex = HALF_DUPLEX;
47225f2d433Sxy 	} else {
473592a4d85Scc 		ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data);
47425f2d433Sxy 		if (ret_val)
47525f2d433Sxy 			goto out;
47625f2d433Sxy 
47725f2d433Sxy 		if (*speed == SPEED_100) {
47825f2d433Sxy 			if (!(data & NWAY_LPAR_100TX_FD_CAPS))
47925f2d433Sxy 				*duplex = HALF_DUPLEX;
48025f2d433Sxy 		} else if (*speed == SPEED_10) {
48125f2d433Sxy 			if (!(data & NWAY_LPAR_10T_FD_CAPS))
48225f2d433Sxy 				*duplex = HALF_DUPLEX;
48325f2d433Sxy 		}
48425f2d433Sxy 	}
48525f2d433Sxy 
48625f2d433Sxy out:
48775eba5b6SRobert Mustacchi 	return ret_val;
48825f2d433Sxy }
48925f2d433Sxy 
49075eba5b6SRobert Mustacchi /**
49175eba5b6SRobert Mustacchi  *  e1000_phy_hw_reset_82541 - PHY hardware reset
49275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
49325f2d433Sxy  *
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)
50025f2d433Sxy {
50125f2d433Sxy 	s32 ret_val;
50225f2d433Sxy 	u32 ledctl;
50325f2d433Sxy 
50425f2d433Sxy 	DEBUGFUNC("e1000_phy_hw_reset_82541");
50525f2d433Sxy 
50625f2d433Sxy 	ret_val = e1000_phy_hw_reset_generic(hw);
50725f2d433Sxy 	if (ret_val)
50825f2d433Sxy 		goto out;
50925f2d433Sxy 
51075eba5b6SRobert Mustacchi 	e1000_phy_init_script_82541(hw);
51125f2d433Sxy 
51225f2d433Sxy 	if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
51325f2d433Sxy 		/* Configure activity LED after PHY reset */
51425f2d433Sxy 		ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
51525f2d433Sxy 		ledctl &= IGP_ACTIVITY_LED_MASK;
51625f2d433Sxy 		ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
51725f2d433Sxy 		E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
51825f2d433Sxy 	}
51925f2d433Sxy 
52025f2d433Sxy out:
52175eba5b6SRobert Mustacchi 	return ret_val;
52225f2d433Sxy }
52325f2d433Sxy 
52475eba5b6SRobert Mustacchi /**
52575eba5b6SRobert Mustacchi  *  e1000_setup_copper_link_82541 - Configure copper link settings
52675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
52725f2d433Sxy  *
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)
53425f2d433Sxy {
53525f2d433Sxy 	struct e1000_phy_info *phy = &hw->phy;
536d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
53775eba5b6SRobert Mustacchi 	s32  ret_val;
53825f2d433Sxy 	u32 ctrl, ledctl;
53925f2d433Sxy 
54025f2d433Sxy 	DEBUGFUNC("e1000_setup_copper_link_82541");
54125f2d433Sxy 
54225f2d433Sxy 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
54325f2d433Sxy 	ctrl |= E1000_CTRL_SLU;
54425f2d433Sxy 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
54525f2d433Sxy 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
54625f2d433Sxy 
547*49b78600SRobert Mustacchi 
54825f2d433Sxy 	/* Earlier revs of the IGP phy require us to force MDI. */
54925f2d433Sxy 	if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) {
55025f2d433Sxy 		dev_spec->dsp_config = e1000_dsp_config_disabled;
55125f2d433Sxy 		phy->mdix = 1;
55225f2d433Sxy 	} else {
55325f2d433Sxy 		dev_spec->dsp_config = e1000_dsp_config_enabled;
55425f2d433Sxy 	}
55525f2d433Sxy 
55625f2d433Sxy 	ret_val = e1000_copper_link_setup_igp(hw);
55725f2d433Sxy 	if (ret_val)
55825f2d433Sxy 		goto out;
55925f2d433Sxy 
56025f2d433Sxy 	if (hw->mac.autoneg) {
56125f2d433Sxy 		if (dev_spec->ffe_config == e1000_ffe_config_active)
56225f2d433Sxy 			dev_spec->ffe_config = e1000_ffe_config_enabled;
56325f2d433Sxy 	}
56425f2d433Sxy 
56525f2d433Sxy 	/* Configure activity LED after Phy reset */
56625f2d433Sxy 	ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
56725f2d433Sxy 	ledctl &= IGP_ACTIVITY_LED_MASK;
56825f2d433Sxy 	ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
56925f2d433Sxy 	E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
57025f2d433Sxy 
57125f2d433Sxy 	ret_val = e1000_setup_copper_link_generic(hw);
57225f2d433Sxy 
57325f2d433Sxy out:
57475eba5b6SRobert Mustacchi 	return ret_val;
57525f2d433Sxy }
57625f2d433Sxy 
57775eba5b6SRobert Mustacchi /**
57875eba5b6SRobert Mustacchi  *  e1000_check_for_link_82541 - Check/Store link connection
57975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
58025f2d433Sxy  *
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)
58525f2d433Sxy {
58625f2d433Sxy 	struct e1000_mac_info *mac = &hw->mac;
58725f2d433Sxy 	s32 ret_val;
588592a4d85Scc 	bool link;
58925f2d433Sxy 
59025f2d433Sxy 	DEBUGFUNC("e1000_check_for_link_82541");
59125f2d433Sxy 
59225f2d433Sxy 	/*
59325f2d433Sxy 	 * We only want to go out to the PHY registers to see if Auto-Neg
59425f2d433Sxy 	 * has completed and/or if our link status has changed.  The
59525f2d433Sxy 	 * get_link_status flag is set upon receiving a Link Status
59625f2d433Sxy 	 * Change or Rx Sequence Error interrupt.
59725f2d433Sxy 	 */
59825f2d433Sxy 	if (!mac->get_link_status) {
59925f2d433Sxy 		ret_val = E1000_SUCCESS;
60025f2d433Sxy 		goto out;
60125f2d433Sxy 	}
60225f2d433Sxy 
60325f2d433Sxy 	/*
60425f2d433Sxy 	 * First we want to see if the MII Status Register reports
60525f2d433Sxy 	 * link.  If so, then we want to get the current speed/duplex
60625f2d433Sxy 	 * of the PHY.
60725f2d433Sxy 	 */
60825f2d433Sxy 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
60925f2d433Sxy 	if (ret_val)
61025f2d433Sxy 		goto out;
61125f2d433Sxy 
61225f2d433Sxy 	if (!link) {
61375eba5b6SRobert Mustacchi 		ret_val = e1000_config_dsp_after_link_change_82541(hw, FALSE);
61475eba5b6SRobert Mustacchi 		goto out; /* No link detected */
61525f2d433Sxy 	}
61625f2d433Sxy 
61775eba5b6SRobert Mustacchi 	mac->get_link_status = FALSE;
61825f2d433Sxy 
61925f2d433Sxy 	/*
62025f2d433Sxy 	 * Check if there was DownShift, must be checked
62125f2d433Sxy 	 * immediately after link-up
62225f2d433Sxy 	 */
62375eba5b6SRobert Mustacchi 	e1000_check_downshift_generic(hw);
62425f2d433Sxy 
62525f2d433Sxy 	/*
62625f2d433Sxy 	 * If we are forcing speed/duplex, then we simply return since
62725f2d433Sxy 	 * we have already determined whether we have link or not.
62825f2d433Sxy 	 */
62925f2d433Sxy 	if (!mac->autoneg) {
63025f2d433Sxy 		ret_val = -E1000_ERR_CONFIG;
63125f2d433Sxy 		goto out;
63225f2d433Sxy 	}
63325f2d433Sxy 
63475eba5b6SRobert Mustacchi 	ret_val = e1000_config_dsp_after_link_change_82541(hw, TRUE);
63525f2d433Sxy 
63625f2d433Sxy 	/*
63725f2d433Sxy 	 * Auto-Neg is enabled.  Auto Speed Detection takes care
63825f2d433Sxy 	 * of MAC speed/duplex configuration.  So we only need to
63925f2d433Sxy 	 * configure Collision Distance in the MAC.
64025f2d433Sxy 	 */
64175eba5b6SRobert Mustacchi 	mac->ops.config_collision_dist(hw);
64225f2d433Sxy 
64325f2d433Sxy 	/*
64425f2d433Sxy 	 * Configure Flow Control now that Auto-Neg has completed.
64525f2d433Sxy 	 * First, we need to restore the desired flow control
64625f2d433Sxy 	 * settings because we may have had to re-autoneg with a
64725f2d433Sxy 	 * different link partner.
64825f2d433Sxy 	 */
64925f2d433Sxy 	ret_val = e1000_config_fc_after_link_up_generic(hw);
650*49b78600SRobert Mustacchi 	if (ret_val)
65125f2d433Sxy 		DEBUGOUT("Error configuring flow control\n");
65225f2d433Sxy 
65325f2d433Sxy out:
65475eba5b6SRobert Mustacchi 	return ret_val;
65525f2d433Sxy }
65625f2d433Sxy 
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
66125f2d433Sxy  *
66275eba5b6SRobert Mustacchi  *  Return E1000_ERR_PHY when failing to read/write the PHY, else E1000_SUCCESS
66375eba5b6SRobert Mustacchi  *  at any other case.
66425f2d433Sxy  *
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,
669*49b78600SRobert Mustacchi 						    bool link_up)
67025f2d433Sxy {
67125f2d433Sxy 	struct e1000_phy_info *phy = &hw->phy;
672d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
67325f2d433Sxy 	s32 ret_val;
67425f2d433Sxy 	u32 idle_errs = 0;
67525f2d433Sxy 	u16 phy_data, phy_saved_data, speed, duplex, i;
67625f2d433Sxy 	u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
677*49b78600SRobert Mustacchi 	u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
678*49b78600SRobert Mustacchi 						IGP01E1000_PHY_AGC_PARAM_A,
679*49b78600SRobert Mustacchi 						IGP01E1000_PHY_AGC_PARAM_B,
680*49b78600SRobert Mustacchi 						IGP01E1000_PHY_AGC_PARAM_C,
681*49b78600SRobert Mustacchi 						IGP01E1000_PHY_AGC_PARAM_D};
68225f2d433Sxy 
68325f2d433Sxy 	DEBUGFUNC("e1000_config_dsp_after_link_change_82541");
68425f2d433Sxy 
68525f2d433Sxy 	if (link_up) {
686592a4d85Scc 		ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
68725f2d433Sxy 		if (ret_val) {
68825f2d433Sxy 			DEBUGOUT("Error getting link speed and duplex\n");
68925f2d433Sxy 			goto out;
69025f2d433Sxy 		}
69125f2d433Sxy 
69225f2d433Sxy 		if (speed != SPEED_1000) {
69325f2d433Sxy 			ret_val = E1000_SUCCESS;
69425f2d433Sxy 			goto out;
69525f2d433Sxy 		}
69625f2d433Sxy 
697592a4d85Scc 		ret_val = phy->ops.get_cable_length(hw);
69825f2d433Sxy 		if (ret_val)
69925f2d433Sxy 			goto out;
70025f2d433Sxy 
70125f2d433Sxy 		if ((dev_spec->dsp_config == e1000_dsp_config_enabled) &&
70225f2d433Sxy 		    phy->min_cable_length >= 50) {
70325f2d433Sxy 
70425f2d433Sxy 			for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
705592a4d85Scc 				ret_val = phy->ops.read_reg(hw,
706*49b78600SRobert Mustacchi 							    dsp_reg_array[i],
707*49b78600SRobert Mustacchi 							    &phy_data);
70825f2d433Sxy 				if (ret_val)
70925f2d433Sxy 					goto out;
71025f2d433Sxy 
71125f2d433Sxy 				phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
71225f2d433Sxy 
713592a4d85Scc 				ret_val = phy->ops.write_reg(hw,
714*49b78600SRobert Mustacchi 							     dsp_reg_array[i],
715*49b78600SRobert Mustacchi 							     phy_data);
71625f2d433Sxy 				if (ret_val)
71725f2d433Sxy 					goto out;
71825f2d433Sxy 			}
71925f2d433Sxy 			dev_spec->dsp_config = e1000_dsp_config_activated;
72025f2d433Sxy 		}
72125f2d433Sxy 
72225f2d433Sxy 		if ((dev_spec->ffe_config != e1000_ffe_config_enabled) ||
72325f2d433Sxy 		    (phy->min_cable_length >= 50)) {
72425f2d433Sxy 			ret_val = E1000_SUCCESS;
72525f2d433Sxy 			goto out;
72625f2d433Sxy 		}
72725f2d433Sxy 
72825f2d433Sxy 		/* clear previous idle error counts */
729592a4d85Scc 		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
73025f2d433Sxy 		if (ret_val)
73125f2d433Sxy 			goto out;
73225f2d433Sxy 
73325f2d433Sxy 		for (i = 0; i < ffe_idle_err_timeout; i++) {
73425f2d433Sxy 			usec_delay(1000);
735*49b78600SRobert Mustacchi 			ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS,
736*49b78600SRobert Mustacchi 						    &phy_data);
73725f2d433Sxy 			if (ret_val)
73825f2d433Sxy 				goto out;
73925f2d433Sxy 
74025f2d433Sxy 			idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
74125f2d433Sxy 			if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
74225f2d433Sxy 				dev_spec->ffe_config = e1000_ffe_config_active;
74325f2d433Sxy 
744592a4d85Scc 				ret_val = phy->ops.write_reg(hw,
745*49b78600SRobert Mustacchi 						  IGP01E1000_PHY_DSP_FFE,
746*49b78600SRobert Mustacchi 						  IGP01E1000_PHY_DSP_FFE_CM_CP);
74725f2d433Sxy 				if (ret_val)
74825f2d433Sxy 					goto out;
74925f2d433Sxy 				break;
75025f2d433Sxy 			}
75125f2d433Sxy 
75225f2d433Sxy 			if (idle_errs)
75325f2d433Sxy 				ffe_idle_err_timeout =
754*49b78600SRobert Mustacchi 						 FFE_IDLE_ERR_COUNT_TIMEOUT_100;
75525f2d433Sxy 		}
75625f2d433Sxy 	} else {
75725f2d433Sxy 		if (dev_spec->dsp_config == e1000_dsp_config_activated) {
75825f2d433Sxy 			/*
75925f2d433Sxy 			 * Save off the current value of register 0x2F5B
76025f2d433Sxy 			 * to be restored at the end of the routines.
76125f2d433Sxy 			 */
762*49b78600SRobert Mustacchi 			ret_val = phy->ops.read_reg(hw, 0x2F5B,
763*49b78600SRobert Mustacchi 						    &phy_saved_data);
76425f2d433Sxy 			if (ret_val)
76525f2d433Sxy 				goto out;
76625f2d433Sxy 
76725f2d433Sxy 			/* Disable the PHY transmitter */
768592a4d85Scc 			ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
76925f2d433Sxy 			if (ret_val)
77025f2d433Sxy 				goto out;
77125f2d433Sxy 
77225f2d433Sxy 			msec_delay_irq(20);
77325f2d433Sxy 
774*49b78600SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw, 0x0000,
775*49b78600SRobert Mustacchi 						     IGP01E1000_IEEE_FORCE_GIG);
77625f2d433Sxy 			if (ret_val)
77725f2d433Sxy 				goto out;
77825f2d433Sxy 			for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
779592a4d85Scc 				ret_val = phy->ops.read_reg(hw,
780*49b78600SRobert Mustacchi 							    dsp_reg_array[i],
781*49b78600SRobert Mustacchi 							    &phy_data);
78225f2d433Sxy 				if (ret_val)
78325f2d433Sxy 					goto out;
78425f2d433Sxy 
78525f2d433Sxy 				phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
78625f2d433Sxy 				phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
78725f2d433Sxy 
788592a4d85Scc 				ret_val = phy->ops.write_reg(hw,
789*49b78600SRobert Mustacchi 							     dsp_reg_array[i],
790*49b78600SRobert Mustacchi 							     phy_data);
79125f2d433Sxy 				if (ret_val)
79225f2d433Sxy 					goto out;
79325f2d433Sxy 			}
79425f2d433Sxy 
795*49b78600SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw, 0x0000,
796*49b78600SRobert Mustacchi 					       IGP01E1000_IEEE_RESTART_AUTONEG);
79725f2d433Sxy 			if (ret_val)
79825f2d433Sxy 				goto out;
79925f2d433Sxy 
80025f2d433Sxy 			msec_delay_irq(20);
80125f2d433Sxy 
80225f2d433Sxy 			/* Now enable the transmitter */
803*49b78600SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw, 0x2F5B,
804*49b78600SRobert Mustacchi 						     phy_saved_data);
80525f2d433Sxy 			if (ret_val)
80625f2d433Sxy 				goto out;
80725f2d433Sxy 
80825f2d433Sxy 			dev_spec->dsp_config = e1000_dsp_config_enabled;
80925f2d433Sxy 		}
81025f2d433Sxy 
81125f2d433Sxy 		if (dev_spec->ffe_config != e1000_ffe_config_active) {
81225f2d433Sxy 			ret_val = E1000_SUCCESS;
81325f2d433Sxy 			goto out;
81425f2d433Sxy 		}
81525f2d433Sxy 
81625f2d433Sxy 		/*
81725f2d433Sxy 		 * Save off the current value of register 0x2F5B
81825f2d433Sxy 		 * to be restored at the end of the routines.
81925f2d433Sxy 		 */
820592a4d85Scc 		ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data);
82125f2d433Sxy 		if (ret_val)
82225f2d433Sxy 			goto out;
82325f2d433Sxy 
82425f2d433Sxy 		/* Disable the PHY transmitter */
825592a4d85Scc 		ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
82625f2d433Sxy 		if (ret_val)
82725f2d433Sxy 			goto out;
82825f2d433Sxy 
82925f2d433Sxy 		msec_delay_irq(20);
83025f2d433Sxy 
831*49b78600SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, 0x0000,
832*49b78600SRobert Mustacchi 					     IGP01E1000_IEEE_FORCE_GIG);
83325f2d433Sxy 		if (ret_val)
83425f2d433Sxy 			goto out;
83525f2d433Sxy 
836*49b78600SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_DSP_FFE,
837*49b78600SRobert Mustacchi 					     IGP01E1000_PHY_DSP_FFE_DEFAULT);
83825f2d433Sxy 		if (ret_val)
83925f2d433Sxy 			goto out;
84025f2d433Sxy 
841*49b78600SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, 0x0000,
842*49b78600SRobert Mustacchi 					     IGP01E1000_IEEE_RESTART_AUTONEG);
84325f2d433Sxy 		if (ret_val)
84425f2d433Sxy 			goto out;
84525f2d433Sxy 
84625f2d433Sxy 		msec_delay_irq(20);
84725f2d433Sxy 
84825f2d433Sxy 		/* Now enable the transmitter */
849592a4d85Scc 		ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data);
85025f2d433Sxy 
85125f2d433Sxy 		if (ret_val)
85225f2d433Sxy 			goto out;
85325f2d433Sxy 
85425f2d433Sxy 		dev_spec->ffe_config = e1000_ffe_config_enabled;
85525f2d433Sxy 	}
85625f2d433Sxy 
85725f2d433Sxy out:
85875eba5b6SRobert Mustacchi 	return ret_val;
85925f2d433Sxy }
86025f2d433Sxy 
86175eba5b6SRobert Mustacchi /**
86275eba5b6SRobert Mustacchi  *  e1000_get_cable_length_igp_82541 - Determine cable length for igp PHY
86375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
86425f2d433Sxy  *
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)
87325f2d433Sxy {
87425f2d433Sxy 	struct e1000_phy_info *phy = &hw->phy;
87525f2d433Sxy 	s32 ret_val = E1000_SUCCESS;
87625f2d433Sxy 	u16 i, data;
87725f2d433Sxy 	u16 cur_agc_value, agc_value = 0;
87825f2d433Sxy 	u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
879*49b78600SRobert Mustacchi 	u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {IGP01E1000_PHY_AGC_A,
880*49b78600SRobert Mustacchi 							 IGP01E1000_PHY_AGC_B,
881*49b78600SRobert Mustacchi 							 IGP01E1000_PHY_AGC_C,
882*49b78600SRobert Mustacchi 							 IGP01E1000_PHY_AGC_D};
88325f2d433Sxy 
88425f2d433Sxy 	DEBUGFUNC("e1000_get_cable_length_igp_82541");
88525f2d433Sxy 
88625f2d433Sxy 	/* Read the AGC registers for all channels */
88725f2d433Sxy 	for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
888592a4d85Scc 		ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data);
88925f2d433Sxy 		if (ret_val)
89025f2d433Sxy 			goto out;
89125f2d433Sxy 
89225f2d433Sxy 		cur_agc_value = data >> IGP01E1000_AGC_LENGTH_SHIFT;
89325f2d433Sxy 
89425f2d433Sxy 		/* Bounds checking */
89525f2d433Sxy 		if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
89625f2d433Sxy 		    (cur_agc_value == 0)) {
89725f2d433Sxy 			ret_val = -E1000_ERR_PHY;
89825f2d433Sxy 			goto out;
89925f2d433Sxy 		}
90025f2d433Sxy 
90125f2d433Sxy 		agc_value += cur_agc_value;
90225f2d433Sxy 
90325f2d433Sxy 		if (min_agc_value > cur_agc_value)
90425f2d433Sxy 			min_agc_value = cur_agc_value;
90525f2d433Sxy 	}
90625f2d433Sxy 
90725f2d433Sxy 	/* Remove the minimal AGC result for length < 50m */
90825f2d433Sxy 	if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * 50) {
90925f2d433Sxy 		agc_value -= min_agc_value;
91025f2d433Sxy 		/* Average the three remaining channels for the length. */
91125f2d433Sxy 		agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
91225f2d433Sxy 	} else {
91325f2d433Sxy 		/* Average the channels for the length. */
91425f2d433Sxy 		agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
91525f2d433Sxy 	}
91625f2d433Sxy 
91725f2d433Sxy 	phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] >
918*49b78600SRobert Mustacchi 				 IGP01E1000_AGC_RANGE)
919*49b78600SRobert Mustacchi 				? (e1000_igp_cable_length_table[agc_value] -
920*49b78600SRobert Mustacchi 				   IGP01E1000_AGC_RANGE)
921*49b78600SRobert Mustacchi 				: 0;
92225f2d433Sxy 	phy->max_cable_length = e1000_igp_cable_length_table[agc_value] +
923*49b78600SRobert Mustacchi 				IGP01E1000_AGC_RANGE;
92425f2d433Sxy 
92525f2d433Sxy 	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
92625f2d433Sxy 
92725f2d433Sxy out:
92875eba5b6SRobert Mustacchi 	return ret_val;
92925f2d433Sxy }
93025f2d433Sxy 
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
93525f2d433Sxy  *
93675eba5b6SRobert Mustacchi  *  Success returns 0, Failure returns 1
93725f2d433Sxy  *
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)
94625f2d433Sxy {
94725f2d433Sxy 	struct e1000_phy_info *phy = &hw->phy;
94825f2d433Sxy 	s32 ret_val;
94925f2d433Sxy 	u16 data;
95025f2d433Sxy 
95125f2d433Sxy 	DEBUGFUNC("e1000_set_d3_lplu_state_82541");
95225f2d433Sxy 
95325f2d433Sxy 	switch (hw->mac.type) {
95425f2d433Sxy 	case e1000_82541_rev_2:
95525f2d433Sxy 	case e1000_82547_rev_2:
95625f2d433Sxy 		break;
95725f2d433Sxy 	default:
95825f2d433Sxy 		ret_val = e1000_set_d3_lplu_state_generic(hw, active);
95925f2d433Sxy 		goto out;
96075eba5b6SRobert Mustacchi 		break;
96125f2d433Sxy 	}
96225f2d433Sxy 
963592a4d85Scc 	ret_val = phy->ops.read_reg(hw, IGP01E1000_GMII_FIFO, &data);
96425f2d433Sxy 	if (ret_val)
96525f2d433Sxy 		goto out;
96625f2d433Sxy 
96725f2d433Sxy 	if (!active) {
96825f2d433Sxy 		data &= ~IGP01E1000_GMII_FLEX_SPD;
969592a4d85Scc 		ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
97025f2d433Sxy 		if (ret_val)
97125f2d433Sxy 			goto out;
97225f2d433Sxy 
97325f2d433Sxy 		/*
97425f2d433Sxy 		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
97525f2d433Sxy 		 * during Dx states where the power conservation is most
97625f2d433Sxy 		 * important.  During driver activity we should enable
97725f2d433Sxy 		 * SmartSpeed, so performance is maintained.
97825f2d433Sxy 		 */
97925f2d433Sxy 		if (phy->smart_speed == e1000_smart_speed_on) {
980592a4d85Scc 			ret_val = phy->ops.read_reg(hw,
981*49b78600SRobert Mustacchi 						    IGP01E1000_PHY_PORT_CONFIG,
982*49b78600SRobert Mustacchi 						    &data);
98325f2d433Sxy 			if (ret_val)
98425f2d433Sxy 				goto out;
98525f2d433Sxy 
98625f2d433Sxy 			data |= IGP01E1000_PSCFR_SMART_SPEED;
987592a4d85Scc 			ret_val = phy->ops.write_reg(hw,
988*49b78600SRobert Mustacchi 						     IGP01E1000_PHY_PORT_CONFIG,
989*49b78600SRobert Mustacchi 						     data);
99025f2d433Sxy 			if (ret_val)
99125f2d433Sxy 				goto out;
99225f2d433Sxy 		} else if (phy->smart_speed == e1000_smart_speed_off) {
993592a4d85Scc 			ret_val = phy->ops.read_reg(hw,
994*49b78600SRobert Mustacchi 						    IGP01E1000_PHY_PORT_CONFIG,
995*49b78600SRobert Mustacchi 						    &data);
99625f2d433Sxy 			if (ret_val)
99725f2d433Sxy 				goto out;
99825f2d433Sxy 
99925f2d433Sxy 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
1000592a4d85Scc 			ret_val = phy->ops.write_reg(hw,
1001*49b78600SRobert Mustacchi 						     IGP01E1000_PHY_PORT_CONFIG,
1002*49b78600SRobert Mustacchi 						     data);
100325f2d433Sxy 			if (ret_val)
100425f2d433Sxy 				goto out;
100525f2d433Sxy 		}
100625f2d433Sxy 	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
1007*49b78600SRobert Mustacchi 		   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
1008*49b78600SRobert Mustacchi 		   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
100925f2d433Sxy 		data |= IGP01E1000_GMII_FLEX_SPD;
1010592a4d85Scc 		ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
101125f2d433Sxy 		if (ret_val)
101225f2d433Sxy 			goto out;
101325f2d433Sxy 
101425f2d433Sxy 		/* When LPLU is enabled, we should disable SmartSpeed */
1015*49b78600SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
1016*49b78600SRobert Mustacchi 					    &data);
101725f2d433Sxy 		if (ret_val)
101825f2d433Sxy 			goto out;
101925f2d433Sxy 
102025f2d433Sxy 		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
1021*49b78600SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
1022*49b78600SRobert Mustacchi 					     data);
102325f2d433Sxy 	}
102425f2d433Sxy 
102525f2d433Sxy out:
102675eba5b6SRobert Mustacchi 	return ret_val;
102725f2d433Sxy }
102825f2d433Sxy 
102975eba5b6SRobert Mustacchi /**
103075eba5b6SRobert Mustacchi  *  e1000_setup_led_82541 - Configures SW controllable LED
103175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
103225f2d433Sxy  *
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)
103725f2d433Sxy {
1038d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
103925f2d433Sxy 	s32 ret_val;
104025f2d433Sxy 
104125f2d433Sxy 	DEBUGFUNC("e1000_setup_led_82541");
104225f2d433Sxy 
1043*49b78600SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO,
1044*49b78600SRobert Mustacchi 				       &dev_spec->spd_default);
104525f2d433Sxy 	if (ret_val)
104625f2d433Sxy 		goto out;
104725f2d433Sxy 
1048*49b78600SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO,
1049*49b78600SRobert Mustacchi 					(u16)(dev_spec->spd_default &
1050*49b78600SRobert Mustacchi 					~IGP01E1000_GMII_SPD));
105125f2d433Sxy 	if (ret_val)
105225f2d433Sxy 		goto out;
105325f2d433Sxy 
105425f2d433Sxy 	E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
105525f2d433Sxy 
105625f2d433Sxy out:
105775eba5b6SRobert Mustacchi 	return ret_val;
105825f2d433Sxy }
105925f2d433Sxy 
106075eba5b6SRobert Mustacchi /**
106175eba5b6SRobert Mustacchi  *  e1000_cleanup_led_82541 - Set LED config to default operation
106275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
106325f2d433Sxy  *
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)
106825f2d433Sxy {
1069d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
107025f2d433Sxy 	s32 ret_val;
107125f2d433Sxy 
107225f2d433Sxy 	DEBUGFUNC("e1000_cleanup_led_82541");
107325f2d433Sxy 
1074*49b78600SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO,
1075*49b78600SRobert Mustacchi 					dev_spec->spd_default);
107625f2d433Sxy 	if (ret_val)
107725f2d433Sxy 		goto out;
107825f2d433Sxy 
107925f2d433Sxy 	E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default);
108025f2d433Sxy 
108125f2d433Sxy out:
108275eba5b6SRobert Mustacchi 	return ret_val;
108325f2d433Sxy }
108425f2d433Sxy 
108575eba5b6SRobert Mustacchi /**
108675eba5b6SRobert Mustacchi  *  e1000_phy_init_script_82541 - Initialize GbE PHY
108775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
108825f2d433Sxy  *
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)
109225f2d433Sxy {
1093d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
109425f2d433Sxy 	u32 ret_val;
109525f2d433Sxy 	u16 phy_saved_data;
109625f2d433Sxy 
109725f2d433Sxy 	DEBUGFUNC("e1000_phy_init_script_82541");
109825f2d433Sxy 
109925f2d433Sxy 	if (!dev_spec->phy_init_script) {
110025f2d433Sxy 		ret_val = E1000_SUCCESS;
110125f2d433Sxy 		goto out;
110225f2d433Sxy 	}
110325f2d433Sxy 
110425f2d433Sxy 	/* Delay after phy reset to enable NVM configuration to load */
110525f2d433Sxy 	msec_delay(20);
110625f2d433Sxy 
110725f2d433Sxy 	/*
110825f2d433Sxy 	 * Save off the current value of register 0x2F5B to be restored at
110925f2d433Sxy 	 * the end of this routine.
111025f2d433Sxy 	 */
1111592a4d85Scc 	ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data);
111225f2d433Sxy 
111325f2d433Sxy 	/* Disabled the PHY transmitter */
1114592a4d85Scc 	hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003);
111525f2d433Sxy 
111625f2d433Sxy 	msec_delay(20);
111725f2d433Sxy 
1118592a4d85Scc 	hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
111925f2d433Sxy 
112025f2d433Sxy 	msec_delay(5);
112125f2d433Sxy 
112225f2d433Sxy 	switch (hw->mac.type) {
112325f2d433Sxy 	case e1000_82541:
112425f2d433Sxy 	case e1000_82547:
1125592a4d85Scc 		hw->phy.ops.write_reg(hw, 0x1F95, 0x0001);
112625f2d433Sxy 
1127592a4d85Scc 		hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21);
112825f2d433Sxy 
1129592a4d85Scc 		hw->phy.ops.write_reg(hw, 0x1F79, 0x0018);
113025f2d433Sxy 
1131592a4d85Scc 		hw->phy.ops.write_reg(hw, 0x1F30, 0x1600);
113225f2d433Sxy 
1133592a4d85Scc 		hw->phy.ops.write_reg(hw, 0x1F31, 0x0014);
113425f2d433Sxy 
1135592a4d85Scc 		hw->phy.ops.write_reg(hw, 0x1F32, 0x161C);
113625f2d433Sxy 
1137592a4d85Scc 		hw->phy.ops.write_reg(hw, 0x1F94, 0x0003);
113825f2d433Sxy 
1139592a4d85Scc 		hw->phy.ops.write_reg(hw, 0x1F96, 0x003F);
114025f2d433Sxy 
1141592a4d85Scc 		hw->phy.ops.write_reg(hw, 0x2010, 0x0008);
114225f2d433Sxy 		break;
114325f2d433Sxy 	case e1000_82541_rev_2:
114425f2d433Sxy 	case e1000_82547_rev_2:
1145592a4d85Scc 		hw->phy.ops.write_reg(hw, 0x1F73, 0x0099);
114625f2d433Sxy 		break;
114725f2d433Sxy 	default:
114825f2d433Sxy 		break;
114925f2d433Sxy 	}
115025f2d433Sxy 
1151592a4d85Scc 	hw->phy.ops.write_reg(hw, 0x0000, 0x3300);
115225f2d433Sxy 
115325f2d433Sxy 	msec_delay(20);
115425f2d433Sxy 
115525f2d433Sxy 	/* Now enable the transmitter */
1156592a4d85Scc 	hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data);
115725f2d433Sxy 
115825f2d433Sxy 	if (hw->mac.type == e1000_82547) {
115925f2d433Sxy 		u16 fused, fine, coarse;
116025f2d433Sxy 
116125f2d433Sxy 		/* Move to analog registers page */
1162*49b78600SRobert Mustacchi 		hw->phy.ops.read_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
1163*49b78600SRobert Mustacchi 				     &fused);
116425f2d433Sxy 
116525f2d433Sxy 		if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
1166*49b78600SRobert Mustacchi 			hw->phy.ops.read_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS,
1167*49b78600SRobert Mustacchi 					     &fused);
116825f2d433Sxy 
116925f2d433Sxy 			fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
117025f2d433Sxy 			coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
117125f2d433Sxy 
117225f2d433Sxy 			if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
117325f2d433Sxy 				coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
117425f2d433Sxy 				fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
117525f2d433Sxy 			} else if (coarse ==
1176*49b78600SRobert Mustacchi 				   IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
117725f2d433Sxy 				fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
117825f2d433Sxy 
117925f2d433Sxy 			fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
1180*49b78600SRobert Mustacchi 				(fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
1181*49b78600SRobert Mustacchi 				(coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
118225f2d433Sxy 
1183592a4d85Scc 			hw->phy.ops.write_reg(hw,
1184*49b78600SRobert Mustacchi 					      IGP01E1000_ANALOG_FUSE_CONTROL,
1185*49b78600SRobert Mustacchi 					      fused);
1186592a4d85Scc 			hw->phy.ops.write_reg(hw,
1187*49b78600SRobert Mustacchi 				      IGP01E1000_ANALOG_FUSE_BYPASS,
1188*49b78600SRobert Mustacchi 				      IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
118925f2d433Sxy 		}
119025f2d433Sxy 	}
119125f2d433Sxy 
119225f2d433Sxy out:
119375eba5b6SRobert Mustacchi 	return ret_val;
119425f2d433Sxy }
119525f2d433Sxy 
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
120025f2d433Sxy  *
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)
120525f2d433Sxy {
1206d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
120725f2d433Sxy 
120825f2d433Sxy 	DEBUGFUNC("e1000_init_script_state_82541");
120925f2d433Sxy 
121025f2d433Sxy 	if (hw->phy.type != e1000_phy_igp) {
121125f2d433Sxy 		DEBUGOUT("Initialization script not necessary.\n");
121225f2d433Sxy 		goto out;
121325f2d433Sxy 	}
121425f2d433Sxy 
121575eba5b6SRobert Mustacchi 	dev_spec->phy_init_script = state;
121625f2d433Sxy 
121725f2d433Sxy out:
121875eba5b6SRobert Mustacchi 	return;
121925f2d433Sxy }
122025f2d433Sxy 
122175eba5b6SRobert Mustacchi /**
122275eba5b6SRobert Mustacchi  * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down
122325f2d433Sxy  * @hw: pointer to the HW structure
122425f2d433Sxy  *
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)
122925f2d433Sxy {
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);
123325f2d433Sxy 
123475eba5b6SRobert Mustacchi 	return;
123525f2d433Sxy }
123625f2d433Sxy 
123775eba5b6SRobert Mustacchi /**
123875eba5b6SRobert Mustacchi  *  e1000_clear_hw_cntrs_82541 - Clear device specific hardware counters
123975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
124025f2d433Sxy  *
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)
124425f2d433Sxy {
124575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_clear_hw_cntrs_82541");
124625f2d433Sxy 
124775eba5b6SRobert Mustacchi 	e1000_clear_hw_cntrs_base_generic(hw);
124825f2d433Sxy 
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);
127225f2d433Sxy }
127325f2d433Sxy 
127475eba5b6SRobert Mustacchi /**
127575eba5b6SRobert Mustacchi  *  e1000_read_mac_addr_82541 - Read device MAC address
127675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
127725f2d433Sxy  *
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)
128125f2d433Sxy {
128275eba5b6SRobert Mustacchi 	s32  ret_val = E1000_SUCCESS;
128375eba5b6SRobert Mustacchi 	u16 offset, nvm_data, i;
128425f2d433Sxy 
128575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_mac_addr");
128625f2d433Sxy 
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");
129225f2d433Sxy 			goto out;
129325f2d433Sxy 		}
129475eba5b6SRobert Mustacchi 		hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
129575eba5b6SRobert Mustacchi 		hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
129625f2d433Sxy 	}
129725f2d433Sxy 
129875eba5b6SRobert Mustacchi 	for (i = 0; i < ETH_ADDR_LEN; i++)
129975eba5b6SRobert Mustacchi 		hw->mac.addr[i] = hw->mac.perm_addr[i];
130025f2d433Sxy 
130125f2d433Sxy out:
130275eba5b6SRobert Mustacchi 	return ret_val;
1303592a4d85Scc }
1304592a4d85Scc 
1305