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$*/
3475eba5b6SRobert Mustacchi 
35c124a83eSRobert Mustacchi /* 80003ES2LAN Gigabit Ethernet Controller (Copper)
3675eba5b6SRobert Mustacchi  * 80003ES2LAN Gigabit Ethernet Controller (Serdes)
3775eba5b6SRobert Mustacchi  */
3875eba5b6SRobert Mustacchi 
3975eba5b6SRobert Mustacchi #include "e1000_api.h"
4075eba5b6SRobert Mustacchi 
4175eba5b6SRobert Mustacchi static s32  e1000_acquire_phy_80003es2lan(struct e1000_hw *hw);
4275eba5b6SRobert Mustacchi static void e1000_release_phy_80003es2lan(struct e1000_hw *hw);
4375eba5b6SRobert Mustacchi static s32  e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);
4475eba5b6SRobert Mustacchi static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw);
4575eba5b6SRobert Mustacchi static s32  e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
4675eba5b6SRobert Mustacchi 						   u32 offset,
4775eba5b6SRobert Mustacchi 						   u16 *data);
4875eba5b6SRobert Mustacchi static s32  e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
4975eba5b6SRobert Mustacchi 						    u32 offset,
5075eba5b6SRobert Mustacchi 						    u16 data);
5175eba5b6SRobert Mustacchi static s32  e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
5275eba5b6SRobert Mustacchi 					u16 words, u16 *data);
5375eba5b6SRobert Mustacchi static s32  e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw);
5475eba5b6SRobert Mustacchi static s32  e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw);
5575eba5b6SRobert Mustacchi static s32  e1000_get_cable_length_80003es2lan(struct e1000_hw *hw);
5675eba5b6SRobert Mustacchi static s32  e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
5775eba5b6SRobert Mustacchi 					       u16 *duplex);
5875eba5b6SRobert Mustacchi static s32  e1000_reset_hw_80003es2lan(struct e1000_hw *hw);
5975eba5b6SRobert Mustacchi static s32  e1000_init_hw_80003es2lan(struct e1000_hw *hw);
6075eba5b6SRobert Mustacchi static s32  e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);
6175eba5b6SRobert Mustacchi static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw);
6275eba5b6SRobert Mustacchi static s32  e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
6375eba5b6SRobert Mustacchi static s32  e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex);
6475eba5b6SRobert Mustacchi static s32  e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw);
6575eba5b6SRobert Mustacchi static s32  e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw);
6675eba5b6SRobert Mustacchi static s32  e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
6775eba5b6SRobert Mustacchi 					    u16 *data);
6875eba5b6SRobert Mustacchi static s32  e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
6975eba5b6SRobert Mustacchi 					     u16 data);
7075eba5b6SRobert Mustacchi static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);
7175eba5b6SRobert Mustacchi static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
7275eba5b6SRobert Mustacchi static s32  e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw);
7375eba5b6SRobert Mustacchi static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
7475eba5b6SRobert Mustacchi 
75c124a83eSRobert Mustacchi /* A table for the GG82563 cable length where the range is defined
7675eba5b6SRobert Mustacchi  * with a lower bound at "index" and the upper bound at
7775eba5b6SRobert Mustacchi  * "index + 5".
7875eba5b6SRobert Mustacchi  */
7975eba5b6SRobert Mustacchi static const u16 e1000_gg82563_cable_length_table[] = {
8075eba5b6SRobert Mustacchi 	0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
8175eba5b6SRobert Mustacchi #define GG82563_CABLE_LENGTH_TABLE_SIZE \
8275eba5b6SRobert Mustacchi 		(sizeof(e1000_gg82563_cable_length_table) / \
8375eba5b6SRobert Mustacchi 		 sizeof(e1000_gg82563_cable_length_table[0]))
8475eba5b6SRobert Mustacchi 
8575eba5b6SRobert Mustacchi /**
8675eba5b6SRobert Mustacchi  *  e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs.
8775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
8875eba5b6SRobert Mustacchi  **/
e1000_init_phy_params_80003es2lan(struct e1000_hw * hw)8975eba5b6SRobert Mustacchi static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
9075eba5b6SRobert Mustacchi {
9175eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
92c124a83eSRobert Mustacchi 	s32 ret_val;
9375eba5b6SRobert Mustacchi 
9475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_phy_params_80003es2lan");
9575eba5b6SRobert Mustacchi 
9675eba5b6SRobert Mustacchi 	if (hw->phy.media_type != e1000_media_type_copper) {
9775eba5b6SRobert Mustacchi 		phy->type = e1000_phy_none;
98c124a83eSRobert Mustacchi 		return E1000_SUCCESS;
9975eba5b6SRobert Mustacchi 	} else {
10075eba5b6SRobert Mustacchi 		phy->ops.power_up = e1000_power_up_phy_copper;
10175eba5b6SRobert Mustacchi 		phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan;
10275eba5b6SRobert Mustacchi 	}
10375eba5b6SRobert Mustacchi 
10475eba5b6SRobert Mustacchi 	phy->addr		= 1;
10575eba5b6SRobert Mustacchi 	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
10675eba5b6SRobert Mustacchi 	phy->reset_delay_us	= 100;
10775eba5b6SRobert Mustacchi 	phy->type		= e1000_phy_gg82563;
10875eba5b6SRobert Mustacchi 
10975eba5b6SRobert Mustacchi 	phy->ops.acquire	= e1000_acquire_phy_80003es2lan;
11075eba5b6SRobert Mustacchi 	phy->ops.check_polarity	= e1000_check_polarity_m88;
11175eba5b6SRobert Mustacchi 	phy->ops.check_reset_block = e1000_check_reset_block_generic;
11275eba5b6SRobert Mustacchi 	phy->ops.commit		= e1000_phy_sw_reset_generic;
11375eba5b6SRobert Mustacchi 	phy->ops.get_cfg_done	= e1000_get_cfg_done_80003es2lan;
11475eba5b6SRobert Mustacchi 	phy->ops.get_info	= e1000_get_phy_info_m88;
11575eba5b6SRobert Mustacchi 	phy->ops.release	= e1000_release_phy_80003es2lan;
11675eba5b6SRobert Mustacchi 	phy->ops.reset		= e1000_phy_hw_reset_generic;
11775eba5b6SRobert Mustacchi 	phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
11875eba5b6SRobert Mustacchi 
11975eba5b6SRobert Mustacchi 	phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan;
12075eba5b6SRobert Mustacchi 	phy->ops.get_cable_length = e1000_get_cable_length_80003es2lan;
12175eba5b6SRobert Mustacchi 	phy->ops.read_reg	= e1000_read_phy_reg_gg82563_80003es2lan;
12275eba5b6SRobert Mustacchi 	phy->ops.write_reg	= e1000_write_phy_reg_gg82563_80003es2lan;
12375eba5b6SRobert Mustacchi 
12475eba5b6SRobert Mustacchi 	phy->ops.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan;
12575eba5b6SRobert Mustacchi 
12675eba5b6SRobert Mustacchi 	/* This can only be done after all function pointers are setup. */
12775eba5b6SRobert Mustacchi 	ret_val = e1000_get_phy_id(hw);
12875eba5b6SRobert Mustacchi 
12975eba5b6SRobert Mustacchi 	/* Verify phy id */
130c124a83eSRobert Mustacchi 	if (phy->id != GG82563_E_PHY_ID)
131c124a83eSRobert Mustacchi 		return -E1000_ERR_PHY;
13275eba5b6SRobert Mustacchi 
13375eba5b6SRobert Mustacchi 	return ret_val;
13475eba5b6SRobert Mustacchi }
13575eba5b6SRobert Mustacchi 
13675eba5b6SRobert Mustacchi /**
13775eba5b6SRobert Mustacchi  *  e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs.
13875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
13975eba5b6SRobert Mustacchi  **/
e1000_init_nvm_params_80003es2lan(struct e1000_hw * hw)14075eba5b6SRobert Mustacchi static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
14175eba5b6SRobert Mustacchi {
14275eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
14375eba5b6SRobert Mustacchi 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
14475eba5b6SRobert Mustacchi 	u16 size;
14575eba5b6SRobert Mustacchi 
14675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_nvm_params_80003es2lan");
14775eba5b6SRobert Mustacchi 
14875eba5b6SRobert Mustacchi 	nvm->opcode_bits = 8;
14975eba5b6SRobert Mustacchi 	nvm->delay_usec = 1;
15075eba5b6SRobert Mustacchi 	switch (nvm->override) {
15175eba5b6SRobert Mustacchi 	case e1000_nvm_override_spi_large:
15275eba5b6SRobert Mustacchi 		nvm->page_size = 32;
15375eba5b6SRobert Mustacchi 		nvm->address_bits = 16;
15475eba5b6SRobert Mustacchi 		break;
15575eba5b6SRobert Mustacchi 	case e1000_nvm_override_spi_small:
15675eba5b6SRobert Mustacchi 		nvm->page_size = 8;
15775eba5b6SRobert Mustacchi 		nvm->address_bits = 8;
15875eba5b6SRobert Mustacchi 		break;
15975eba5b6SRobert Mustacchi 	default:
16075eba5b6SRobert Mustacchi 		nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
16175eba5b6SRobert Mustacchi 		nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
16275eba5b6SRobert Mustacchi 		break;
16375eba5b6SRobert Mustacchi 	}
16475eba5b6SRobert Mustacchi 
16575eba5b6SRobert Mustacchi 	nvm->type = e1000_nvm_eeprom_spi;
16675eba5b6SRobert Mustacchi 
16775eba5b6SRobert Mustacchi 	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
16875eba5b6SRobert Mustacchi 		     E1000_EECD_SIZE_EX_SHIFT);
16975eba5b6SRobert Mustacchi 
170c124a83eSRobert Mustacchi 	/* Added to a constant, "size" becomes the left-shift value
17175eba5b6SRobert Mustacchi 	 * for setting word_size.
17275eba5b6SRobert Mustacchi 	 */
17375eba5b6SRobert Mustacchi 	size += NVM_WORD_SIZE_BASE_SHIFT;
17475eba5b6SRobert Mustacchi 
17575eba5b6SRobert Mustacchi 	/* EEPROM access above 16k is unsupported */
17675eba5b6SRobert Mustacchi 	if (size > 14)
17775eba5b6SRobert Mustacchi 		size = 14;
17875eba5b6SRobert Mustacchi 	nvm->word_size = 1 << size;
17975eba5b6SRobert Mustacchi 
18075eba5b6SRobert Mustacchi 	/* Function Pointers */
18175eba5b6SRobert Mustacchi 	nvm->ops.acquire	= e1000_acquire_nvm_80003es2lan;
18275eba5b6SRobert Mustacchi 	nvm->ops.read		= e1000_read_nvm_eerd;
18375eba5b6SRobert Mustacchi 	nvm->ops.release	= e1000_release_nvm_80003es2lan;
18475eba5b6SRobert Mustacchi 	nvm->ops.update		= e1000_update_nvm_checksum_generic;
18575eba5b6SRobert Mustacchi 	nvm->ops.valid_led_default = e1000_valid_led_default_generic;
18675eba5b6SRobert Mustacchi 	nvm->ops.validate	= e1000_validate_nvm_checksum_generic;
18775eba5b6SRobert Mustacchi 	nvm->ops.write		= e1000_write_nvm_80003es2lan;
18875eba5b6SRobert Mustacchi 
18975eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
19075eba5b6SRobert Mustacchi }
19175eba5b6SRobert Mustacchi 
19275eba5b6SRobert Mustacchi /**
19375eba5b6SRobert Mustacchi  *  e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs.
19475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
19575eba5b6SRobert Mustacchi  **/
e1000_init_mac_params_80003es2lan(struct e1000_hw * hw)19675eba5b6SRobert Mustacchi static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
19775eba5b6SRobert Mustacchi {
19875eba5b6SRobert Mustacchi 	struct e1000_mac_info *mac = &hw->mac;
19975eba5b6SRobert Mustacchi 
20075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_mac_params_80003es2lan");
20175eba5b6SRobert Mustacchi 
20275eba5b6SRobert Mustacchi 	/* Set media type and media-dependent function pointers */
20375eba5b6SRobert Mustacchi 	switch (hw->device_id) {
20475eba5b6SRobert Mustacchi 	case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
20575eba5b6SRobert Mustacchi 		hw->phy.media_type = e1000_media_type_internal_serdes;
20675eba5b6SRobert Mustacchi 		mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
20775eba5b6SRobert Mustacchi 		mac->ops.setup_physical_interface =
20875eba5b6SRobert Mustacchi 					e1000_setup_fiber_serdes_link_generic;
20975eba5b6SRobert Mustacchi 		break;
21075eba5b6SRobert Mustacchi 	default:
21175eba5b6SRobert Mustacchi 		hw->phy.media_type = e1000_media_type_copper;
21275eba5b6SRobert Mustacchi 		mac->ops.check_for_link = e1000_check_for_copper_link_generic;
21375eba5b6SRobert Mustacchi 		mac->ops.setup_physical_interface =
21475eba5b6SRobert Mustacchi 					e1000_setup_copper_link_80003es2lan;
21575eba5b6SRobert Mustacchi 		break;
21675eba5b6SRobert Mustacchi 	}
21775eba5b6SRobert Mustacchi 
21875eba5b6SRobert Mustacchi 	/* Set mta register count */
21975eba5b6SRobert Mustacchi 	mac->mta_reg_count = 128;
22075eba5b6SRobert Mustacchi 	/* Set rar entry count */
22175eba5b6SRobert Mustacchi 	mac->rar_entry_count = E1000_RAR_ENTRIES;
22275eba5b6SRobert Mustacchi 	/* Set if part includes ASF firmware */
22375eba5b6SRobert Mustacchi 	mac->asf_firmware_present = TRUE;
22475eba5b6SRobert Mustacchi 	/* FWSM register */
22575eba5b6SRobert Mustacchi 	mac->has_fwsm = TRUE;
22675eba5b6SRobert Mustacchi 	/* ARC supported; valid only if manageability features are enabled. */
227c124a83eSRobert Mustacchi 	mac->arc_subsystem_valid = !!(E1000_READ_REG(hw, E1000_FWSM) &
228c124a83eSRobert Mustacchi 				      E1000_FWSM_MODE_MASK);
22975eba5b6SRobert Mustacchi 	/* Adaptive IFS not supported */
23075eba5b6SRobert Mustacchi 	mac->adaptive_ifs = FALSE;
23175eba5b6SRobert Mustacchi 
23275eba5b6SRobert Mustacchi 	/* Function pointers */
23375eba5b6SRobert Mustacchi 
23475eba5b6SRobert Mustacchi 	/* bus type/speed/width */
23575eba5b6SRobert Mustacchi 	mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
23675eba5b6SRobert Mustacchi 	/* reset */
23775eba5b6SRobert Mustacchi 	mac->ops.reset_hw = e1000_reset_hw_80003es2lan;
23875eba5b6SRobert Mustacchi 	/* hw initialization */
23975eba5b6SRobert Mustacchi 	mac->ops.init_hw = e1000_init_hw_80003es2lan;
24075eba5b6SRobert Mustacchi 	/* link setup */
24175eba5b6SRobert Mustacchi 	mac->ops.setup_link = e1000_setup_link_generic;
24275eba5b6SRobert Mustacchi 	/* check management mode */
24375eba5b6SRobert Mustacchi 	mac->ops.check_mng_mode = e1000_check_mng_mode_generic;
24475eba5b6SRobert Mustacchi 	/* multicast address update */
24575eba5b6SRobert Mustacchi 	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
24675eba5b6SRobert Mustacchi 	/* writing VFTA */
24775eba5b6SRobert Mustacchi 	mac->ops.write_vfta = e1000_write_vfta_generic;
24875eba5b6SRobert Mustacchi 	/* clearing VFTA */
24975eba5b6SRobert Mustacchi 	mac->ops.clear_vfta = e1000_clear_vfta_generic;
25075eba5b6SRobert Mustacchi 	/* read mac address */
25175eba5b6SRobert Mustacchi 	mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan;
25275eba5b6SRobert Mustacchi 	/* ID LED init */
25375eba5b6SRobert Mustacchi 	mac->ops.id_led_init = e1000_id_led_init_generic;
25475eba5b6SRobert Mustacchi 	/* blink LED */
25575eba5b6SRobert Mustacchi 	mac->ops.blink_led = e1000_blink_led_generic;
25675eba5b6SRobert Mustacchi 	/* setup LED */
25775eba5b6SRobert Mustacchi 	mac->ops.setup_led = e1000_setup_led_generic;
25875eba5b6SRobert Mustacchi 	/* cleanup LED */
25975eba5b6SRobert Mustacchi 	mac->ops.cleanup_led = e1000_cleanup_led_generic;
26075eba5b6SRobert Mustacchi 	/* turn on/off LED */
26175eba5b6SRobert Mustacchi 	mac->ops.led_on = e1000_led_on_generic;
26275eba5b6SRobert Mustacchi 	mac->ops.led_off = e1000_led_off_generic;
26375eba5b6SRobert Mustacchi 	/* clear hardware counters */
26475eba5b6SRobert Mustacchi 	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan;
26575eba5b6SRobert Mustacchi 	/* link info */
26675eba5b6SRobert Mustacchi 	mac->ops.get_link_up_info = e1000_get_link_up_info_80003es2lan;
26775eba5b6SRobert Mustacchi 
26875eba5b6SRobert Mustacchi 	/* set lan id for port to determine which phy lock to use */
26975eba5b6SRobert Mustacchi 	hw->mac.ops.set_lan_id(hw);
27075eba5b6SRobert Mustacchi 
27175eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
27275eba5b6SRobert Mustacchi }
27375eba5b6SRobert Mustacchi 
27475eba5b6SRobert Mustacchi /**
27575eba5b6SRobert Mustacchi  *  e1000_init_function_pointers_80003es2lan - Init ESB2 func ptrs.
27675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
27775eba5b6SRobert Mustacchi  *
27875eba5b6SRobert Mustacchi  *  Called to initialize all function pointers and parameters.
27975eba5b6SRobert Mustacchi  **/
e1000_init_function_pointers_80003es2lan(struct e1000_hw * hw)28075eba5b6SRobert Mustacchi void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw)
28175eba5b6SRobert Mustacchi {
28275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_function_pointers_80003es2lan");
28375eba5b6SRobert Mustacchi 
28475eba5b6SRobert Mustacchi 	hw->mac.ops.init_params = e1000_init_mac_params_80003es2lan;
28575eba5b6SRobert Mustacchi 	hw->nvm.ops.init_params = e1000_init_nvm_params_80003es2lan;
28675eba5b6SRobert Mustacchi 	hw->phy.ops.init_params = e1000_init_phy_params_80003es2lan;
28775eba5b6SRobert Mustacchi }
28875eba5b6SRobert Mustacchi 
28975eba5b6SRobert Mustacchi /**
29075eba5b6SRobert Mustacchi  *  e1000_acquire_phy_80003es2lan - Acquire rights to access PHY
29175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
29275eba5b6SRobert Mustacchi  *
29375eba5b6SRobert Mustacchi  *  A wrapper to acquire access rights to the correct PHY.
29475eba5b6SRobert Mustacchi  **/
e1000_acquire_phy_80003es2lan(struct e1000_hw * hw)29575eba5b6SRobert Mustacchi static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
29675eba5b6SRobert Mustacchi {
29775eba5b6SRobert Mustacchi 	u16 mask;
29875eba5b6SRobert Mustacchi 
29975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_acquire_phy_80003es2lan");
30075eba5b6SRobert Mustacchi 
30175eba5b6SRobert Mustacchi 	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
30275eba5b6SRobert Mustacchi 	return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
30375eba5b6SRobert Mustacchi }
30475eba5b6SRobert Mustacchi 
30575eba5b6SRobert Mustacchi /**
30675eba5b6SRobert Mustacchi  *  e1000_release_phy_80003es2lan - Release rights to access PHY
30775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
30875eba5b6SRobert Mustacchi  *
30975eba5b6SRobert Mustacchi  *  A wrapper to release access rights to the correct PHY.
31075eba5b6SRobert Mustacchi  **/
e1000_release_phy_80003es2lan(struct e1000_hw * hw)31175eba5b6SRobert Mustacchi static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
31275eba5b6SRobert Mustacchi {
31375eba5b6SRobert Mustacchi 	u16 mask;
31475eba5b6SRobert Mustacchi 
31575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_release_phy_80003es2lan");
31675eba5b6SRobert Mustacchi 
31775eba5b6SRobert Mustacchi 	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
31875eba5b6SRobert Mustacchi 	e1000_release_swfw_sync_80003es2lan(hw, mask);
31975eba5b6SRobert Mustacchi }
32075eba5b6SRobert Mustacchi 
32175eba5b6SRobert Mustacchi /**
32275eba5b6SRobert Mustacchi  *  e1000_acquire_mac_csr_80003es2lan - Acquire right to access Kumeran register
32375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
32475eba5b6SRobert Mustacchi  *
32575eba5b6SRobert Mustacchi  *  Acquire the semaphore to access the Kumeran interface.
32675eba5b6SRobert Mustacchi  *
32775eba5b6SRobert Mustacchi  **/
e1000_acquire_mac_csr_80003es2lan(struct e1000_hw * hw)32875eba5b6SRobert Mustacchi static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw)
32975eba5b6SRobert Mustacchi {
33075eba5b6SRobert Mustacchi 	u16 mask;
33175eba5b6SRobert Mustacchi 
33275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_acquire_mac_csr_80003es2lan");
33375eba5b6SRobert Mustacchi 
33475eba5b6SRobert Mustacchi 	mask = E1000_SWFW_CSR_SM;
33575eba5b6SRobert Mustacchi 
33675eba5b6SRobert Mustacchi 	return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
33775eba5b6SRobert Mustacchi }
33875eba5b6SRobert Mustacchi 
33975eba5b6SRobert Mustacchi /**
34075eba5b6SRobert Mustacchi  *  e1000_release_mac_csr_80003es2lan - Release right to access Kumeran Register
34175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
34275eba5b6SRobert Mustacchi  *
34375eba5b6SRobert Mustacchi  *  Release the semaphore used to access the Kumeran interface
34475eba5b6SRobert Mustacchi  **/
e1000_release_mac_csr_80003es2lan(struct e1000_hw * hw)34575eba5b6SRobert Mustacchi static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw)
34675eba5b6SRobert Mustacchi {
34775eba5b6SRobert Mustacchi 	u16 mask;
34875eba5b6SRobert Mustacchi 
34975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_release_mac_csr_80003es2lan");
35075eba5b6SRobert Mustacchi 
35175eba5b6SRobert Mustacchi 	mask = E1000_SWFW_CSR_SM;
35275eba5b6SRobert Mustacchi 
35375eba5b6SRobert Mustacchi 	e1000_release_swfw_sync_80003es2lan(hw, mask);
35475eba5b6SRobert Mustacchi }
35575eba5b6SRobert Mustacchi 
35675eba5b6SRobert Mustacchi /**
35775eba5b6SRobert Mustacchi  *  e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM
35875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
35975eba5b6SRobert Mustacchi  *
36075eba5b6SRobert Mustacchi  *  Acquire the semaphore to access the EEPROM.
36175eba5b6SRobert Mustacchi  **/
e1000_acquire_nvm_80003es2lan(struct e1000_hw * hw)36275eba5b6SRobert Mustacchi static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw)
36375eba5b6SRobert Mustacchi {
36475eba5b6SRobert Mustacchi 	s32 ret_val;
36575eba5b6SRobert Mustacchi 
36675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_acquire_nvm_80003es2lan");
36775eba5b6SRobert Mustacchi 
36875eba5b6SRobert Mustacchi 	ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
36975eba5b6SRobert Mustacchi 	if (ret_val)
370c124a83eSRobert Mustacchi 		return ret_val;
37175eba5b6SRobert Mustacchi 
37275eba5b6SRobert Mustacchi 	ret_val = e1000_acquire_nvm_generic(hw);
37375eba5b6SRobert Mustacchi 
37475eba5b6SRobert Mustacchi 	if (ret_val)
37575eba5b6SRobert Mustacchi 		e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
37675eba5b6SRobert Mustacchi 
37775eba5b6SRobert Mustacchi 	return ret_val;
37875eba5b6SRobert Mustacchi }
37975eba5b6SRobert Mustacchi 
38075eba5b6SRobert Mustacchi /**
38175eba5b6SRobert Mustacchi  *  e1000_release_nvm_80003es2lan - Relinquish rights to access NVM
38275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
38375eba5b6SRobert Mustacchi  *
38475eba5b6SRobert Mustacchi  *  Release the semaphore used to access the EEPROM.
38575eba5b6SRobert Mustacchi  **/
e1000_release_nvm_80003es2lan(struct e1000_hw * hw)38675eba5b6SRobert Mustacchi static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw)
38775eba5b6SRobert Mustacchi {
38875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_release_nvm_80003es2lan");
38975eba5b6SRobert Mustacchi 
39075eba5b6SRobert Mustacchi 	e1000_release_nvm_generic(hw);
39175eba5b6SRobert Mustacchi 	e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
39275eba5b6SRobert Mustacchi }
39375eba5b6SRobert Mustacchi 
39475eba5b6SRobert Mustacchi /**
39575eba5b6SRobert Mustacchi  *  e1000_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore
39675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
39775eba5b6SRobert Mustacchi  *  @mask: specifies which semaphore to acquire
39875eba5b6SRobert Mustacchi  *
39975eba5b6SRobert Mustacchi  *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
40075eba5b6SRobert Mustacchi  *  will also specify which port we're acquiring the lock for.
40175eba5b6SRobert Mustacchi  **/
e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw * hw,u16 mask)40275eba5b6SRobert Mustacchi static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
40375eba5b6SRobert Mustacchi {
40475eba5b6SRobert Mustacchi 	u32 swfw_sync;
40575eba5b6SRobert Mustacchi 	u32 swmask = mask;
40675eba5b6SRobert Mustacchi 	u32 fwmask = mask << 16;
407c124a83eSRobert Mustacchi 	s32 i = 0;
408c124a83eSRobert Mustacchi 	s32 timeout = 50;
40975eba5b6SRobert Mustacchi 
41075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_acquire_swfw_sync_80003es2lan");
41175eba5b6SRobert Mustacchi 
41275eba5b6SRobert Mustacchi 	while (i < timeout) {
413c124a83eSRobert Mustacchi 		if (e1000_get_hw_semaphore_generic(hw))
414c124a83eSRobert Mustacchi 			return -E1000_ERR_SWFW_SYNC;
41575eba5b6SRobert Mustacchi 
41675eba5b6SRobert Mustacchi 		swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
41775eba5b6SRobert Mustacchi 		if (!(swfw_sync & (fwmask | swmask)))
41875eba5b6SRobert Mustacchi 			break;
41975eba5b6SRobert Mustacchi 
420c124a83eSRobert Mustacchi 		/* Firmware currently using resource (fwmask)
42175eba5b6SRobert Mustacchi 		 * or other software thread using resource (swmask)
42275eba5b6SRobert Mustacchi 		 */
42375eba5b6SRobert Mustacchi 		e1000_put_hw_semaphore_generic(hw);
42475eba5b6SRobert Mustacchi 		msec_delay_irq(5);
42575eba5b6SRobert Mustacchi 		i++;
42675eba5b6SRobert Mustacchi 	}
42775eba5b6SRobert Mustacchi 
42875eba5b6SRobert Mustacchi 	if (i == timeout) {
42975eba5b6SRobert Mustacchi 		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
430c124a83eSRobert Mustacchi 		return -E1000_ERR_SWFW_SYNC;
43175eba5b6SRobert Mustacchi 	}
43275eba5b6SRobert Mustacchi 
43375eba5b6SRobert Mustacchi 	swfw_sync |= swmask;
43475eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
43575eba5b6SRobert Mustacchi 
43675eba5b6SRobert Mustacchi 	e1000_put_hw_semaphore_generic(hw);
43775eba5b6SRobert Mustacchi 
438c124a83eSRobert Mustacchi 	return E1000_SUCCESS;
43975eba5b6SRobert Mustacchi }
44075eba5b6SRobert Mustacchi 
44175eba5b6SRobert Mustacchi /**
44275eba5b6SRobert Mustacchi  *  e1000_release_swfw_sync_80003es2lan - Release SW/FW semaphore
44375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
44475eba5b6SRobert Mustacchi  *  @mask: specifies which semaphore to acquire
44575eba5b6SRobert Mustacchi  *
44675eba5b6SRobert Mustacchi  *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
44775eba5b6SRobert Mustacchi  *  will also specify which port we're releasing the lock for.
44875eba5b6SRobert Mustacchi  **/
e1000_release_swfw_sync_80003es2lan(struct e1000_hw * hw,u16 mask)44975eba5b6SRobert Mustacchi static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
45075eba5b6SRobert Mustacchi {
45175eba5b6SRobert Mustacchi 	u32 swfw_sync;
45275eba5b6SRobert Mustacchi 
45375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_release_swfw_sync_80003es2lan");
45475eba5b6SRobert Mustacchi 
45575eba5b6SRobert Mustacchi 	while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS)
45675eba5b6SRobert Mustacchi 		; /* Empty */
45775eba5b6SRobert Mustacchi 
45875eba5b6SRobert Mustacchi 	swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
45975eba5b6SRobert Mustacchi 	swfw_sync &= ~mask;
46075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
46175eba5b6SRobert Mustacchi 
46275eba5b6SRobert Mustacchi 	e1000_put_hw_semaphore_generic(hw);
46375eba5b6SRobert Mustacchi }
46475eba5b6SRobert Mustacchi 
46575eba5b6SRobert Mustacchi /**
46675eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register
46775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
46875eba5b6SRobert Mustacchi  *  @offset: offset of the register to read
46975eba5b6SRobert Mustacchi  *  @data: pointer to the data returned from the operation
47075eba5b6SRobert Mustacchi  *
47175eba5b6SRobert Mustacchi  *  Read the GG82563 PHY register.
47275eba5b6SRobert Mustacchi  **/
e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw * hw,u32 offset,u16 * data)47375eba5b6SRobert Mustacchi static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
47475eba5b6SRobert Mustacchi 						  u32 offset, u16 *data)
47575eba5b6SRobert Mustacchi {
47675eba5b6SRobert Mustacchi 	s32 ret_val;
47775eba5b6SRobert Mustacchi 	u32 page_select;
47875eba5b6SRobert Mustacchi 	u16 temp;
47975eba5b6SRobert Mustacchi 
48075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_phy_reg_gg82563_80003es2lan");
48175eba5b6SRobert Mustacchi 
48275eba5b6SRobert Mustacchi 	ret_val = e1000_acquire_phy_80003es2lan(hw);
48375eba5b6SRobert Mustacchi 	if (ret_val)
484c124a83eSRobert Mustacchi 		return ret_val;
48575eba5b6SRobert Mustacchi 
48675eba5b6SRobert Mustacchi 	/* Select Configuration Page */
48775eba5b6SRobert Mustacchi 	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
48875eba5b6SRobert Mustacchi 		page_select = GG82563_PHY_PAGE_SELECT;
48975eba5b6SRobert Mustacchi 	} else {
490c124a83eSRobert Mustacchi 		/* Use Alternative Page Select register to access
49175eba5b6SRobert Mustacchi 		 * registers 30 and 31
49275eba5b6SRobert Mustacchi 		 */
49375eba5b6SRobert Mustacchi 		page_select = GG82563_PHY_PAGE_SELECT_ALT;
49475eba5b6SRobert Mustacchi 	}
49575eba5b6SRobert Mustacchi 
49675eba5b6SRobert Mustacchi 	temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
49775eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
49875eba5b6SRobert Mustacchi 	if (ret_val) {
49975eba5b6SRobert Mustacchi 		e1000_release_phy_80003es2lan(hw);
500c124a83eSRobert Mustacchi 		return ret_val;
50175eba5b6SRobert Mustacchi 	}
50275eba5b6SRobert Mustacchi 
503c124a83eSRobert Mustacchi 	if (hw->dev_spec._80003es2lan.mdic_wa_enable) {
504c124a83eSRobert Mustacchi 		/* The "ready" bit in the MDIC register may be incorrectly set
50575eba5b6SRobert Mustacchi 		 * before the device has completed the "Page Select" MDI
50675eba5b6SRobert Mustacchi 		 * transaction.  So we wait 200us after each MDI command...
50775eba5b6SRobert Mustacchi 		 */
50875eba5b6SRobert Mustacchi 		usec_delay(200);
50975eba5b6SRobert Mustacchi 
51075eba5b6SRobert Mustacchi 		/* ...and verify the command was successful. */
51175eba5b6SRobert Mustacchi 		ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
51275eba5b6SRobert Mustacchi 
51375eba5b6SRobert Mustacchi 		if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
51475eba5b6SRobert Mustacchi 			e1000_release_phy_80003es2lan(hw);
515c124a83eSRobert Mustacchi 			return -E1000_ERR_PHY;
51675eba5b6SRobert Mustacchi 		}
51775eba5b6SRobert Mustacchi 
51875eba5b6SRobert Mustacchi 		usec_delay(200);
51975eba5b6SRobert Mustacchi 
52075eba5b6SRobert Mustacchi 		ret_val = e1000_read_phy_reg_mdic(hw,
52175eba5b6SRobert Mustacchi 						  MAX_PHY_REG_ADDRESS & offset,
52275eba5b6SRobert Mustacchi 						  data);
52375eba5b6SRobert Mustacchi 
52475eba5b6SRobert Mustacchi 		usec_delay(200);
52575eba5b6SRobert Mustacchi 	} else {
52675eba5b6SRobert Mustacchi 		ret_val = e1000_read_phy_reg_mdic(hw,
52775eba5b6SRobert Mustacchi 						  MAX_PHY_REG_ADDRESS & offset,
52875eba5b6SRobert Mustacchi 						  data);
52975eba5b6SRobert Mustacchi 	}
53075eba5b6SRobert Mustacchi 
53175eba5b6SRobert Mustacchi 	e1000_release_phy_80003es2lan(hw);
53275eba5b6SRobert Mustacchi 
53375eba5b6SRobert Mustacchi 	return ret_val;
53475eba5b6SRobert Mustacchi }
53575eba5b6SRobert Mustacchi 
53675eba5b6SRobert Mustacchi /**
53775eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register
53875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
53975eba5b6SRobert Mustacchi  *  @offset: offset of the register to read
54075eba5b6SRobert Mustacchi  *  @data: value to write to the register
54175eba5b6SRobert Mustacchi  *
54275eba5b6SRobert Mustacchi  *  Write to the GG82563 PHY register.
54375eba5b6SRobert Mustacchi  **/
e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw * hw,u32 offset,u16 data)54475eba5b6SRobert Mustacchi static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
54575eba5b6SRobert Mustacchi 						   u32 offset, u16 data)
54675eba5b6SRobert Mustacchi {
54775eba5b6SRobert Mustacchi 	s32 ret_val;
54875eba5b6SRobert Mustacchi 	u32 page_select;
54975eba5b6SRobert Mustacchi 	u16 temp;
55075eba5b6SRobert Mustacchi 
55175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_phy_reg_gg82563_80003es2lan");
55275eba5b6SRobert Mustacchi 
55375eba5b6SRobert Mustacchi 	ret_val = e1000_acquire_phy_80003es2lan(hw);
55475eba5b6SRobert Mustacchi 	if (ret_val)
555c124a83eSRobert Mustacchi 		return ret_val;
55675eba5b6SRobert Mustacchi 
55775eba5b6SRobert Mustacchi 	/* Select Configuration Page */
55875eba5b6SRobert Mustacchi 	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
55975eba5b6SRobert Mustacchi 		page_select = GG82563_PHY_PAGE_SELECT;
56075eba5b6SRobert Mustacchi 	} else {
561c124a83eSRobert Mustacchi 		/* Use Alternative Page Select register to access
56275eba5b6SRobert Mustacchi 		 * registers 30 and 31
56375eba5b6SRobert Mustacchi 		 */
56475eba5b6SRobert Mustacchi 		page_select = GG82563_PHY_PAGE_SELECT_ALT;
56575eba5b6SRobert Mustacchi 	}
56675eba5b6SRobert Mustacchi 
56775eba5b6SRobert Mustacchi 	temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
56875eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
56975eba5b6SRobert Mustacchi 	if (ret_val) {
57075eba5b6SRobert Mustacchi 		e1000_release_phy_80003es2lan(hw);
571c124a83eSRobert Mustacchi 		return ret_val;
57275eba5b6SRobert Mustacchi 	}
57375eba5b6SRobert Mustacchi 
574c124a83eSRobert Mustacchi 	if (hw->dev_spec._80003es2lan.mdic_wa_enable) {
575c124a83eSRobert Mustacchi 		/* The "ready" bit in the MDIC register may be incorrectly set
57675eba5b6SRobert Mustacchi 		 * before the device has completed the "Page Select" MDI
57775eba5b6SRobert Mustacchi 		 * transaction.  So we wait 200us after each MDI command...
57875eba5b6SRobert Mustacchi 		 */
57975eba5b6SRobert Mustacchi 		usec_delay(200);
58075eba5b6SRobert Mustacchi 
58175eba5b6SRobert Mustacchi 		/* ...and verify the command was successful. */
58275eba5b6SRobert Mustacchi 		ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
58375eba5b6SRobert Mustacchi 
58475eba5b6SRobert Mustacchi 		if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
58575eba5b6SRobert Mustacchi 			e1000_release_phy_80003es2lan(hw);
586c124a83eSRobert Mustacchi 			return -E1000_ERR_PHY;
58775eba5b6SRobert Mustacchi 		}
58875eba5b6SRobert Mustacchi 
58975eba5b6SRobert Mustacchi 		usec_delay(200);
59075eba5b6SRobert Mustacchi 
59175eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw,
59275eba5b6SRobert Mustacchi 						  MAX_PHY_REG_ADDRESS & offset,
59375eba5b6SRobert Mustacchi 						  data);
59475eba5b6SRobert Mustacchi 
59575eba5b6SRobert Mustacchi 		usec_delay(200);
59675eba5b6SRobert Mustacchi 	} else {
59775eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw,
59875eba5b6SRobert Mustacchi 						  MAX_PHY_REG_ADDRESS & offset,
59975eba5b6SRobert Mustacchi 						  data);
60075eba5b6SRobert Mustacchi 	}
60175eba5b6SRobert Mustacchi 
60275eba5b6SRobert Mustacchi 	e1000_release_phy_80003es2lan(hw);
60375eba5b6SRobert Mustacchi 
60475eba5b6SRobert Mustacchi 	return ret_val;
60575eba5b6SRobert Mustacchi }
60675eba5b6SRobert Mustacchi 
60775eba5b6SRobert Mustacchi /**
60875eba5b6SRobert Mustacchi  *  e1000_write_nvm_80003es2lan - Write to ESB2 NVM
60975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
61075eba5b6SRobert Mustacchi  *  @offset: offset of the register to read
61175eba5b6SRobert Mustacchi  *  @words: number of words to write
61275eba5b6SRobert Mustacchi  *  @data: buffer of data to write to the NVM
61375eba5b6SRobert Mustacchi  *
61475eba5b6SRobert Mustacchi  *  Write "words" of data to the ESB2 NVM.
61575eba5b6SRobert Mustacchi  **/
e1000_write_nvm_80003es2lan(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)61675eba5b6SRobert Mustacchi static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
61775eba5b6SRobert Mustacchi 				       u16 words, u16 *data)
61875eba5b6SRobert Mustacchi {
61975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_nvm_80003es2lan");
62075eba5b6SRobert Mustacchi 
62175eba5b6SRobert Mustacchi 	return e1000_write_nvm_spi(hw, offset, words, data);
62275eba5b6SRobert Mustacchi }
62375eba5b6SRobert Mustacchi 
62475eba5b6SRobert Mustacchi /**
62575eba5b6SRobert Mustacchi  *  e1000_get_cfg_done_80003es2lan - Wait for configuration to complete
62675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
62775eba5b6SRobert Mustacchi  *
62875eba5b6SRobert Mustacchi  *  Wait a specific amount of time for manageability processes to complete.
62975eba5b6SRobert Mustacchi  *  This is a function pointer entry point called by the phy module.
63075eba5b6SRobert Mustacchi  **/
e1000_get_cfg_done_80003es2lan(struct e1000_hw * hw)63175eba5b6SRobert Mustacchi static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw)
63275eba5b6SRobert Mustacchi {
63375eba5b6SRobert Mustacchi 	s32 timeout = PHY_CFG_TIMEOUT;
63475eba5b6SRobert Mustacchi 	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
63575eba5b6SRobert Mustacchi 
63675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_cfg_done_80003es2lan");
63775eba5b6SRobert Mustacchi 
63875eba5b6SRobert Mustacchi 	if (hw->bus.func == 1)
63975eba5b6SRobert Mustacchi 		mask = E1000_NVM_CFG_DONE_PORT_1;
64075eba5b6SRobert Mustacchi 
64175eba5b6SRobert Mustacchi 	while (timeout) {
64275eba5b6SRobert Mustacchi 		if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask)
64375eba5b6SRobert Mustacchi 			break;
64475eba5b6SRobert Mustacchi 		msec_delay(1);
64575eba5b6SRobert Mustacchi 		timeout--;
64675eba5b6SRobert Mustacchi 	}
64775eba5b6SRobert Mustacchi 	if (!timeout) {
64875eba5b6SRobert Mustacchi 		DEBUGOUT("MNG configuration cycle has not completed.\n");
649c124a83eSRobert Mustacchi 		return -E1000_ERR_RESET;
65075eba5b6SRobert Mustacchi 	}
65175eba5b6SRobert Mustacchi 
652c124a83eSRobert Mustacchi 	return E1000_SUCCESS;
65375eba5b6SRobert Mustacchi }
65475eba5b6SRobert Mustacchi 
65575eba5b6SRobert Mustacchi /**
65675eba5b6SRobert Mustacchi  *  e1000_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex
65775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
65875eba5b6SRobert Mustacchi  *
65975eba5b6SRobert Mustacchi  *  Force the speed and duplex settings onto the PHY.  This is a
66075eba5b6SRobert Mustacchi  *  function pointer entry point called by the phy module.
66175eba5b6SRobert Mustacchi  **/
e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw * hw)66275eba5b6SRobert Mustacchi static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
66375eba5b6SRobert Mustacchi {
664c124a83eSRobert Mustacchi 	s32 ret_val;
66575eba5b6SRobert Mustacchi 	u16 phy_data;
66675eba5b6SRobert Mustacchi 	bool link;
66775eba5b6SRobert Mustacchi 
66875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_force_speed_duplex_80003es2lan");
66975eba5b6SRobert Mustacchi 
67075eba5b6SRobert Mustacchi 	if (!(hw->phy.ops.read_reg))
671c124a83eSRobert Mustacchi 		return E1000_SUCCESS;
67275eba5b6SRobert Mustacchi 
673c124a83eSRobert Mustacchi 	/* Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
67475eba5b6SRobert Mustacchi 	 * forced whenever speed and duplex are forced.
67575eba5b6SRobert Mustacchi 	 */
67675eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
67775eba5b6SRobert Mustacchi 	if (ret_val)
678c124a83eSRobert Mustacchi 		return ret_val;
67975eba5b6SRobert Mustacchi 
68075eba5b6SRobert Mustacchi 	phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO;
68175eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
68275eba5b6SRobert Mustacchi 	if (ret_val)
683c124a83eSRobert Mustacchi 		return ret_val;
68475eba5b6SRobert Mustacchi 
68575eba5b6SRobert Mustacchi 	DEBUGOUT1("GG82563 PSCR: %X\n", phy_data);
68675eba5b6SRobert Mustacchi 
68775eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_data);
68875eba5b6SRobert Mustacchi 	if (ret_val)
689c124a83eSRobert Mustacchi 		return ret_val;
69075eba5b6SRobert Mustacchi 
69175eba5b6SRobert Mustacchi 	e1000_phy_force_speed_duplex_setup(hw, &phy_data);
69275eba5b6SRobert Mustacchi 
69375eba5b6SRobert Mustacchi 	/* Reset the phy to commit changes. */
69475eba5b6SRobert Mustacchi 	phy_data |= MII_CR_RESET;
69575eba5b6SRobert Mustacchi 
69675eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_data);
69775eba5b6SRobert Mustacchi 	if (ret_val)
698c124a83eSRobert Mustacchi 		return ret_val;
69975eba5b6SRobert Mustacchi 
70075eba5b6SRobert Mustacchi 	usec_delay(1);
70175eba5b6SRobert Mustacchi 
70275eba5b6SRobert Mustacchi 	if (hw->phy.autoneg_wait_to_complete) {
70375eba5b6SRobert Mustacchi 		DEBUGOUT("Waiting for forced speed/duplex link on GG82563 phy.\n");
70475eba5b6SRobert Mustacchi 
70575eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
70675eba5b6SRobert Mustacchi 						     100000, &link);
70775eba5b6SRobert Mustacchi 		if (ret_val)
708c124a83eSRobert Mustacchi 			return ret_val;
70975eba5b6SRobert Mustacchi 
71075eba5b6SRobert Mustacchi 		if (!link) {
711c124a83eSRobert Mustacchi 			/* We didn't get link.
71275eba5b6SRobert Mustacchi 			 * Reset the DSP and cross our fingers.
71375eba5b6SRobert Mustacchi 			 */
71475eba5b6SRobert Mustacchi 			ret_val = e1000_phy_reset_dsp_generic(hw);
71575eba5b6SRobert Mustacchi 			if (ret_val)
716c124a83eSRobert Mustacchi 				return ret_val;
71775eba5b6SRobert Mustacchi 		}
71875eba5b6SRobert Mustacchi 
71975eba5b6SRobert Mustacchi 		/* Try once more */
72075eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
72175eba5b6SRobert Mustacchi 						     100000, &link);
72275eba5b6SRobert Mustacchi 		if (ret_val)
723c124a83eSRobert Mustacchi 			return ret_val;
72475eba5b6SRobert Mustacchi 	}
72575eba5b6SRobert Mustacchi 
72675eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
72775eba5b6SRobert Mustacchi 				       &phy_data);
72875eba5b6SRobert Mustacchi 	if (ret_val)
729c124a83eSRobert Mustacchi 		return ret_val;
73075eba5b6SRobert Mustacchi 
731c124a83eSRobert Mustacchi 	/* Resetting the phy means we need to verify the TX_CLK corresponds
73275eba5b6SRobert Mustacchi 	 * to the link speed.  10Mbps -> 2.5MHz, else 25MHz.
73375eba5b6SRobert Mustacchi 	 */
73475eba5b6SRobert Mustacchi 	phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
73575eba5b6SRobert Mustacchi 	if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED)
73675eba5b6SRobert Mustacchi 		phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5;
73775eba5b6SRobert Mustacchi 	else
73875eba5b6SRobert Mustacchi 		phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
73975eba5b6SRobert Mustacchi 
740c124a83eSRobert Mustacchi 	/* In addition, we must re-enable CRS on Tx for both half and full
74175eba5b6SRobert Mustacchi 	 * duplex.
74275eba5b6SRobert Mustacchi 	 */
74375eba5b6SRobert Mustacchi 	phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
74475eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
74575eba5b6SRobert Mustacchi 					phy_data);
74675eba5b6SRobert Mustacchi 
74775eba5b6SRobert Mustacchi 	return ret_val;
74875eba5b6SRobert Mustacchi }
74975eba5b6SRobert Mustacchi 
75075eba5b6SRobert Mustacchi /**
75175eba5b6SRobert Mustacchi  *  e1000_get_cable_length_80003es2lan - Set approximate cable length
75275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
75375eba5b6SRobert Mustacchi  *
75475eba5b6SRobert Mustacchi  *  Find the approximate cable length as measured by the GG82563 PHY.
75575eba5b6SRobert Mustacchi  *  This is a function pointer entry point called by the phy module.
75675eba5b6SRobert Mustacchi  **/
e1000_get_cable_length_80003es2lan(struct e1000_hw * hw)75775eba5b6SRobert Mustacchi static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
75875eba5b6SRobert Mustacchi {
75975eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
760c124a83eSRobert Mustacchi 	s32 ret_val;
76175eba5b6SRobert Mustacchi 	u16 phy_data, index;
76275eba5b6SRobert Mustacchi 
76375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_cable_length_80003es2lan");
76475eba5b6SRobert Mustacchi 
76575eba5b6SRobert Mustacchi 	if (!(hw->phy.ops.read_reg))
766c124a83eSRobert Mustacchi 		return E1000_SUCCESS;
76775eba5b6SRobert Mustacchi 
76875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
76975eba5b6SRobert Mustacchi 	if (ret_val)
770c124a83eSRobert Mustacchi 		return ret_val;
77175eba5b6SRobert Mustacchi 
77275eba5b6SRobert Mustacchi 	index = phy_data & GG82563_DSPD_CABLE_LENGTH;
77375eba5b6SRobert Mustacchi 
774c124a83eSRobert Mustacchi 	if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5)
775c124a83eSRobert Mustacchi 		return -E1000_ERR_PHY;
77675eba5b6SRobert Mustacchi 
77775eba5b6SRobert Mustacchi 	phy->min_cable_length = e1000_gg82563_cable_length_table[index];
77875eba5b6SRobert Mustacchi 	phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5];
77975eba5b6SRobert Mustacchi 
78075eba5b6SRobert Mustacchi 	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
78175eba5b6SRobert Mustacchi 
782c124a83eSRobert Mustacchi 	return E1000_SUCCESS;
78375eba5b6SRobert Mustacchi }
78475eba5b6SRobert Mustacchi 
78575eba5b6SRobert Mustacchi /**
78675eba5b6SRobert Mustacchi  *  e1000_get_link_up_info_80003es2lan - Report speed and duplex
78775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
78875eba5b6SRobert Mustacchi  *  @speed: pointer to speed buffer
78975eba5b6SRobert Mustacchi  *  @duplex: pointer to duplex buffer
79075eba5b6SRobert Mustacchi  *
79175eba5b6SRobert Mustacchi  *  Retrieve the current speed and duplex configuration.
79275eba5b6SRobert Mustacchi  **/
e1000_get_link_up_info_80003es2lan(struct e1000_hw * hw,u16 * speed,u16 * duplex)79375eba5b6SRobert Mustacchi static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
79475eba5b6SRobert Mustacchi 					      u16 *duplex)
79575eba5b6SRobert Mustacchi {
79675eba5b6SRobert Mustacchi 	s32 ret_val;
79775eba5b6SRobert Mustacchi 
79875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_link_up_info_80003es2lan");
79975eba5b6SRobert Mustacchi 
80075eba5b6SRobert Mustacchi 	if (hw->phy.media_type == e1000_media_type_copper) {
80175eba5b6SRobert Mustacchi 		ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
80275eba5b6SRobert Mustacchi 								    duplex);
80375eba5b6SRobert Mustacchi 		hw->phy.ops.cfg_on_link_up(hw);
80475eba5b6SRobert Mustacchi 	} else {
80575eba5b6SRobert Mustacchi 		ret_val = e1000_get_speed_and_duplex_fiber_serdes_generic(hw,
80675eba5b6SRobert Mustacchi 								  speed,
80775eba5b6SRobert Mustacchi 								  duplex);
80875eba5b6SRobert Mustacchi 	}
80975eba5b6SRobert Mustacchi 
81075eba5b6SRobert Mustacchi 	return ret_val;
81175eba5b6SRobert Mustacchi }
81275eba5b6SRobert Mustacchi 
81375eba5b6SRobert Mustacchi /**
81475eba5b6SRobert Mustacchi  *  e1000_reset_hw_80003es2lan - Reset the ESB2 controller
81575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
81675eba5b6SRobert Mustacchi  *
81775eba5b6SRobert Mustacchi  *  Perform a global reset to the ESB2 controller.
81875eba5b6SRobert Mustacchi  **/
e1000_reset_hw_80003es2lan(struct e1000_hw * hw)81975eba5b6SRobert Mustacchi static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
82075eba5b6SRobert Mustacchi {
82175eba5b6SRobert Mustacchi 	u32 ctrl;
82275eba5b6SRobert Mustacchi 	s32 ret_val;
823c124a83eSRobert Mustacchi 	u16 kum_reg_data;
82475eba5b6SRobert Mustacchi 
82575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_reset_hw_80003es2lan");
82675eba5b6SRobert Mustacchi 
827c124a83eSRobert Mustacchi 	/* Prevent the PCI-E bus from sticking if there is no TLP connection
82875eba5b6SRobert Mustacchi 	 * on the last TLP read/write transaction when MAC is reset.
82975eba5b6SRobert Mustacchi 	 */
83075eba5b6SRobert Mustacchi 	ret_val = e1000_disable_pcie_master_generic(hw);
83175eba5b6SRobert Mustacchi 	if (ret_val)
83275eba5b6SRobert Mustacchi 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
83375eba5b6SRobert Mustacchi 
83475eba5b6SRobert Mustacchi 	DEBUGOUT("Masking off all interrupts\n");
83575eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
83675eba5b6SRobert Mustacchi 
83775eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
83875eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
83975eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
84075eba5b6SRobert Mustacchi 
84175eba5b6SRobert Mustacchi 	msec_delay(10);
84275eba5b6SRobert Mustacchi 
84375eba5b6SRobert Mustacchi 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
84475eba5b6SRobert Mustacchi 
84575eba5b6SRobert Mustacchi 	ret_val = e1000_acquire_phy_80003es2lan(hw);
846c124a83eSRobert Mustacchi 	if (ret_val)
847c124a83eSRobert Mustacchi 		return ret_val;
848c124a83eSRobert Mustacchi 
84975eba5b6SRobert Mustacchi 	DEBUGOUT("Issuing a global reset to MAC\n");
85075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
85175eba5b6SRobert Mustacchi 	e1000_release_phy_80003es2lan(hw);
85275eba5b6SRobert Mustacchi 
853c124a83eSRobert Mustacchi 	/* Disable IBIST slave mode (far-end loopback) */
854*49b78600SRobert Mustacchi 	ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
855*49b78600SRobert Mustacchi 				E1000_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data);
856*49b78600SRobert Mustacchi 	if (!ret_val) {
857c124a83eSRobert Mustacchi 		kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
858*49b78600SRobert Mustacchi 		ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
859*49b78600SRobert Mustacchi 						 E1000_KMRNCTRLSTA_INBAND_PARAM,
860c124a83eSRobert Mustacchi 						 kum_reg_data);
861*49b78600SRobert Mustacchi 		if (ret_val)
862*49b78600SRobert Mustacchi 			DEBUGOUT("Error disabling far-end loopback\n");
863*49b78600SRobert Mustacchi 	} else
864*49b78600SRobert Mustacchi 		DEBUGOUT("Error disabling far-end loopback\n");
865c124a83eSRobert Mustacchi 
86675eba5b6SRobert Mustacchi 	ret_val = e1000_get_auto_rd_done_generic(hw);
86775eba5b6SRobert Mustacchi 	if (ret_val)
86875eba5b6SRobert Mustacchi 		/* We don't want to continue accessing MAC registers. */
869c124a83eSRobert Mustacchi 		return ret_val;
87075eba5b6SRobert Mustacchi 
87175eba5b6SRobert Mustacchi 	/* Clear any pending interrupt events. */
87275eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
87375eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICR);
87475eba5b6SRobert Mustacchi 
875c124a83eSRobert Mustacchi 	return e1000_check_alt_mac_addr_generic(hw);
87675eba5b6SRobert Mustacchi }
87775eba5b6SRobert Mustacchi 
87875eba5b6SRobert Mustacchi /**
87975eba5b6SRobert Mustacchi  *  e1000_init_hw_80003es2lan - Initialize the ESB2 controller
88075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
88175eba5b6SRobert Mustacchi  *
88275eba5b6SRobert Mustacchi  *  Initialize the hw bits, LED, VFTA, MTA, link and hw counters.
88375eba5b6SRobert Mustacchi  **/
e1000_init_hw_80003es2lan(struct e1000_hw * hw)88475eba5b6SRobert Mustacchi static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
88575eba5b6SRobert Mustacchi {
88675eba5b6SRobert Mustacchi 	struct e1000_mac_info *mac = &hw->mac;
88775eba5b6SRobert Mustacchi 	u32 reg_data;
88875eba5b6SRobert Mustacchi 	s32 ret_val;
88975eba5b6SRobert Mustacchi 	u16 kum_reg_data;
89075eba5b6SRobert Mustacchi 	u16 i;
89175eba5b6SRobert Mustacchi 
89275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_hw_80003es2lan");
89375eba5b6SRobert Mustacchi 
89475eba5b6SRobert Mustacchi 	e1000_initialize_hw_bits_80003es2lan(hw);
89575eba5b6SRobert Mustacchi 
89675eba5b6SRobert Mustacchi 	/* Initialize identification LED */
89775eba5b6SRobert Mustacchi 	ret_val = mac->ops.id_led_init(hw);
898c124a83eSRobert Mustacchi 	/* An error is not fatal and we should not stop init due to this */
89975eba5b6SRobert Mustacchi 	if (ret_val)
90075eba5b6SRobert Mustacchi 		DEBUGOUT("Error initializing identification LED\n");
90175eba5b6SRobert Mustacchi 
90275eba5b6SRobert Mustacchi 	/* Disabling VLAN filtering */
90375eba5b6SRobert Mustacchi 	DEBUGOUT("Initializing the IEEE VLAN\n");
90475eba5b6SRobert Mustacchi 	mac->ops.clear_vfta(hw);
90575eba5b6SRobert Mustacchi 
90675eba5b6SRobert Mustacchi 	/* Setup the receive address. */
90775eba5b6SRobert Mustacchi 	e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
90875eba5b6SRobert Mustacchi 
90975eba5b6SRobert Mustacchi 	/* Zero out the Multicast HASH table */
91075eba5b6SRobert Mustacchi 	DEBUGOUT("Zeroing the MTA\n");
91175eba5b6SRobert Mustacchi 	for (i = 0; i < mac->mta_reg_count; i++)
91275eba5b6SRobert Mustacchi 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
91375eba5b6SRobert Mustacchi 
91475eba5b6SRobert Mustacchi 	/* Setup link and flow control */
91575eba5b6SRobert Mustacchi 	ret_val = mac->ops.setup_link(hw);
916c124a83eSRobert Mustacchi 	if (ret_val)
917c124a83eSRobert Mustacchi 		return ret_val;
91875eba5b6SRobert Mustacchi 
91975eba5b6SRobert Mustacchi 	/* Disable IBIST slave mode (far-end loopback) */
920*49b78600SRobert Mustacchi 	ret_val =
92175eba5b6SRobert Mustacchi 	    e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
92275eba5b6SRobert Mustacchi 					    &kum_reg_data);
923*49b78600SRobert Mustacchi 	if (!ret_val) {
92475eba5b6SRobert Mustacchi 		kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
925*49b78600SRobert Mustacchi 		ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
926*49b78600SRobert Mustacchi 						 E1000_KMRNCTRLSTA_INBAND_PARAM,
92775eba5b6SRobert Mustacchi 						 kum_reg_data);
928*49b78600SRobert Mustacchi 		if (ret_val)
929*49b78600SRobert Mustacchi 			DEBUGOUT("Error disabling far-end loopback\n");
930*49b78600SRobert Mustacchi 	} else
931*49b78600SRobert Mustacchi 		DEBUGOUT("Error disabling far-end loopback\n");
93275eba5b6SRobert Mustacchi 
93375eba5b6SRobert Mustacchi 	/* Set the transmit descriptor write-back policy */
93475eba5b6SRobert Mustacchi 	reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
935c124a83eSRobert Mustacchi 	reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
936c124a83eSRobert Mustacchi 		    E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
93775eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
93875eba5b6SRobert Mustacchi 
93975eba5b6SRobert Mustacchi 	/* ...for both queues. */
94075eba5b6SRobert Mustacchi 	reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
941c124a83eSRobert Mustacchi 	reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
942c124a83eSRobert Mustacchi 		    E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
94375eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
94475eba5b6SRobert Mustacchi 
94575eba5b6SRobert Mustacchi 	/* Enable retransmit on late collisions */
94675eba5b6SRobert Mustacchi 	reg_data = E1000_READ_REG(hw, E1000_TCTL);
94775eba5b6SRobert Mustacchi 	reg_data |= E1000_TCTL_RTLC;
94875eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TCTL, reg_data);
94975eba5b6SRobert Mustacchi 
95075eba5b6SRobert Mustacchi 	/* Configure Gigabit Carry Extend Padding */
95175eba5b6SRobert Mustacchi 	reg_data = E1000_READ_REG(hw, E1000_TCTL_EXT);
95275eba5b6SRobert Mustacchi 	reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
95375eba5b6SRobert Mustacchi 	reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN;
95475eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TCTL_EXT, reg_data);
95575eba5b6SRobert Mustacchi 
95675eba5b6SRobert Mustacchi 	/* Configure Transmit Inter-Packet Gap */
95775eba5b6SRobert Mustacchi 	reg_data = E1000_READ_REG(hw, E1000_TIPG);
95875eba5b6SRobert Mustacchi 	reg_data &= ~E1000_TIPG_IPGT_MASK;
95975eba5b6SRobert Mustacchi 	reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
96075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TIPG, reg_data);
96175eba5b6SRobert Mustacchi 
96275eba5b6SRobert Mustacchi 	reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001);
96375eba5b6SRobert Mustacchi 	reg_data &= ~0x00100000;
96475eba5b6SRobert Mustacchi 	E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data);
96575eba5b6SRobert Mustacchi 
96675eba5b6SRobert Mustacchi 	/* default to TRUE to enable the MDIC W/A */
96775eba5b6SRobert Mustacchi 	hw->dev_spec._80003es2lan.mdic_wa_enable = TRUE;
96875eba5b6SRobert Mustacchi 
969c124a83eSRobert Mustacchi 	ret_val =
970c124a83eSRobert Mustacchi 	    e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET >>
971c124a83eSRobert Mustacchi 					    E1000_KMRNCTRLSTA_OFFSET_SHIFT, &i);
97275eba5b6SRobert Mustacchi 	if (!ret_val) {
97375eba5b6SRobert Mustacchi 		if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) ==
97475eba5b6SRobert Mustacchi 		     E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
97575eba5b6SRobert Mustacchi 			hw->dev_spec._80003es2lan.mdic_wa_enable = FALSE;
97675eba5b6SRobert Mustacchi 	}
97775eba5b6SRobert Mustacchi 
978c124a83eSRobert Mustacchi 	/* Clear all of the statistics registers (clear on read).  It is
97975eba5b6SRobert Mustacchi 	 * important that we do this after we have tried to establish link
98075eba5b6SRobert Mustacchi 	 * because the symbol error count will increment wildly if there
98175eba5b6SRobert Mustacchi 	 * is no link.
98275eba5b6SRobert Mustacchi 	 */
98375eba5b6SRobert Mustacchi 	e1000_clear_hw_cntrs_80003es2lan(hw);
98475eba5b6SRobert Mustacchi 
98575eba5b6SRobert Mustacchi 	return ret_val;
98675eba5b6SRobert Mustacchi }
98775eba5b6SRobert Mustacchi 
98875eba5b6SRobert Mustacchi /**
98975eba5b6SRobert Mustacchi  *  e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2
99075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
99175eba5b6SRobert Mustacchi  *
99275eba5b6SRobert Mustacchi  *  Initializes required hardware-dependent bits needed for normal operation.
99375eba5b6SRobert Mustacchi  **/
e1000_initialize_hw_bits_80003es2lan(struct e1000_hw * hw)99475eba5b6SRobert Mustacchi static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
99575eba5b6SRobert Mustacchi {
99675eba5b6SRobert Mustacchi 	u32 reg;
99775eba5b6SRobert Mustacchi 
99875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_initialize_hw_bits_80003es2lan");
99975eba5b6SRobert Mustacchi 
100075eba5b6SRobert Mustacchi 	/* Transmit Descriptor Control 0 */
100175eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_TXDCTL(0));
100275eba5b6SRobert Mustacchi 	reg |= (1 << 22);
100375eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg);
100475eba5b6SRobert Mustacchi 
100575eba5b6SRobert Mustacchi 	/* Transmit Descriptor Control 1 */
100675eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_TXDCTL(1));
100775eba5b6SRobert Mustacchi 	reg |= (1 << 22);
100875eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg);
100975eba5b6SRobert Mustacchi 
101075eba5b6SRobert Mustacchi 	/* Transmit Arbitration Control 0 */
101175eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_TARC(0));
101275eba5b6SRobert Mustacchi 	reg &= ~(0xF << 27); /* 30:27 */
101375eba5b6SRobert Mustacchi 	if (hw->phy.media_type != e1000_media_type_copper)
101475eba5b6SRobert Mustacchi 		reg &= ~(1 << 20);
101575eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TARC(0), reg);
101675eba5b6SRobert Mustacchi 
101775eba5b6SRobert Mustacchi 	/* Transmit Arbitration Control 1 */
101875eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_TARC(1));
101975eba5b6SRobert Mustacchi 	if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR)
102075eba5b6SRobert Mustacchi 		reg &= ~(1 << 28);
102175eba5b6SRobert Mustacchi 	else
102275eba5b6SRobert Mustacchi 		reg |= (1 << 28);
102375eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TARC(1), reg);
102475eba5b6SRobert Mustacchi 
1025c124a83eSRobert Mustacchi 	/* Disable IPv6 extension header parsing because some malformed
1026c124a83eSRobert Mustacchi 	 * IPv6 headers can hang the Rx.
1027c124a83eSRobert Mustacchi 	 */
1028c124a83eSRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_RFCTL);
1029c124a83eSRobert Mustacchi 	reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
1030c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_RFCTL, reg);
1031c124a83eSRobert Mustacchi 
103275eba5b6SRobert Mustacchi 	return;
103375eba5b6SRobert Mustacchi }
103475eba5b6SRobert Mustacchi 
103575eba5b6SRobert Mustacchi /**
103675eba5b6SRobert Mustacchi  *  e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link
103775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
103875eba5b6SRobert Mustacchi  *
103975eba5b6SRobert Mustacchi  *  Setup some GG82563 PHY registers for obtaining link
104075eba5b6SRobert Mustacchi  **/
e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw * hw)104175eba5b6SRobert Mustacchi static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
104275eba5b6SRobert Mustacchi {
104375eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
104475eba5b6SRobert Mustacchi 	s32 ret_val;
1045c124a83eSRobert Mustacchi 	u32 reg;
104675eba5b6SRobert Mustacchi 	u16 data;
104775eba5b6SRobert Mustacchi 
104875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan");
104975eba5b6SRobert Mustacchi 
105075eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
105175eba5b6SRobert Mustacchi 	if (ret_val)
1052c124a83eSRobert Mustacchi 		return ret_val;
105375eba5b6SRobert Mustacchi 
105475eba5b6SRobert Mustacchi 	data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
105575eba5b6SRobert Mustacchi 	/* Use 25MHz for both link down and 1000Base-T for Tx clock. */
105675eba5b6SRobert Mustacchi 	data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
105775eba5b6SRobert Mustacchi 
105875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
105975eba5b6SRobert Mustacchi 	if (ret_val)
1060c124a83eSRobert Mustacchi 		return ret_val;
106175eba5b6SRobert Mustacchi 
1062c124a83eSRobert Mustacchi 	/* Options:
106375eba5b6SRobert Mustacchi 	 *   MDI/MDI-X = 0 (default)
106475eba5b6SRobert Mustacchi 	 *   0 - Auto for all speeds
106575eba5b6SRobert Mustacchi 	 *   1 - MDI mode
106675eba5b6SRobert Mustacchi 	 *   2 - MDI-X mode
106775eba5b6SRobert Mustacchi 	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
106875eba5b6SRobert Mustacchi 	 */
106975eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL, &data);
107075eba5b6SRobert Mustacchi 	if (ret_val)
1071c124a83eSRobert Mustacchi 		return ret_val;
107275eba5b6SRobert Mustacchi 
107375eba5b6SRobert Mustacchi 	data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
107475eba5b6SRobert Mustacchi 
107575eba5b6SRobert Mustacchi 	switch (phy->mdix) {
107675eba5b6SRobert Mustacchi 	case 1:
107775eba5b6SRobert Mustacchi 		data |= GG82563_PSCR_CROSSOVER_MODE_MDI;
107875eba5b6SRobert Mustacchi 		break;
107975eba5b6SRobert Mustacchi 	case 2:
108075eba5b6SRobert Mustacchi 		data |= GG82563_PSCR_CROSSOVER_MODE_MDIX;
108175eba5b6SRobert Mustacchi 		break;
108275eba5b6SRobert Mustacchi 	case 0:
108375eba5b6SRobert Mustacchi 	default:
108475eba5b6SRobert Mustacchi 		data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
108575eba5b6SRobert Mustacchi 		break;
108675eba5b6SRobert Mustacchi 	}
108775eba5b6SRobert Mustacchi 
1088c124a83eSRobert Mustacchi 	/* Options:
108975eba5b6SRobert Mustacchi 	 *   disable_polarity_correction = 0 (default)
109075eba5b6SRobert Mustacchi 	 *       Automatic Correction for Reversed Cable Polarity
109175eba5b6SRobert Mustacchi 	 *   0 - Disabled
109275eba5b6SRobert Mustacchi 	 *   1 - Enabled
109375eba5b6SRobert Mustacchi 	 */
109475eba5b6SRobert Mustacchi 	data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
109575eba5b6SRobert Mustacchi 	if (phy->disable_polarity_correction)
109675eba5b6SRobert Mustacchi 		data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
109775eba5b6SRobert Mustacchi 
109875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, data);
109975eba5b6SRobert Mustacchi 	if (ret_val)
1100c124a83eSRobert Mustacchi 		return ret_val;
110175eba5b6SRobert Mustacchi 
110275eba5b6SRobert Mustacchi 	/* SW Reset the PHY so all changes take effect */
110375eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.commit(hw);
110475eba5b6SRobert Mustacchi 	if (ret_val) {
110575eba5b6SRobert Mustacchi 		DEBUGOUT("Error Resetting the PHY\n");
1106c124a83eSRobert Mustacchi 		return ret_val;
110775eba5b6SRobert Mustacchi 	}
110875eba5b6SRobert Mustacchi 
110975eba5b6SRobert Mustacchi 	/* Bypass Rx and Tx FIFO's */
1110c124a83eSRobert Mustacchi 	reg = E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL;
1111c124a83eSRobert Mustacchi 	data = (E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
111275eba5b6SRobert Mustacchi 		E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
1113c124a83eSRobert Mustacchi 	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data);
111475eba5b6SRobert Mustacchi 	if (ret_val)
1115c124a83eSRobert Mustacchi 		return ret_val;
111675eba5b6SRobert Mustacchi 
1117c124a83eSRobert Mustacchi 	reg = E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE;
1118c124a83eSRobert Mustacchi 	ret_val = e1000_read_kmrn_reg_80003es2lan(hw, reg, &data);
111975eba5b6SRobert Mustacchi 	if (ret_val)
1120c124a83eSRobert Mustacchi 		return ret_val;
112175eba5b6SRobert Mustacchi 	data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
1122c124a83eSRobert Mustacchi 	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data);
112375eba5b6SRobert Mustacchi 	if (ret_val)
1124c124a83eSRobert Mustacchi 		return ret_val;
112575eba5b6SRobert Mustacchi 
112675eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data);
112775eba5b6SRobert Mustacchi 	if (ret_val)
1128c124a83eSRobert Mustacchi 		return ret_val;
112975eba5b6SRobert Mustacchi 
113075eba5b6SRobert Mustacchi 	data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
113175eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL_2, data);
113275eba5b6SRobert Mustacchi 	if (ret_val)
1133c124a83eSRobert Mustacchi 		return ret_val;
113475eba5b6SRobert Mustacchi 
1135c124a83eSRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
1136c124a83eSRobert Mustacchi 	reg &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
1137c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
113875eba5b6SRobert Mustacchi 
113975eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data);
114075eba5b6SRobert Mustacchi 	if (ret_val)
1141c124a83eSRobert Mustacchi 		return ret_val;
114275eba5b6SRobert Mustacchi 
1143c124a83eSRobert Mustacchi 	/* Do not init these registers when the HW is in IAMT mode, since the
114475eba5b6SRobert Mustacchi 	 * firmware will have already initialized them.  We only initialize
114575eba5b6SRobert Mustacchi 	 * them if the HW is not in IAMT mode.
114675eba5b6SRobert Mustacchi 	 */
1147c124a83eSRobert Mustacchi 	if (!hw->mac.ops.check_mng_mode(hw)) {
114875eba5b6SRobert Mustacchi 		/* Enable Electrical Idle on the PHY */
114975eba5b6SRobert Mustacchi 		data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
115075eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
115175eba5b6SRobert Mustacchi 						data);
115275eba5b6SRobert Mustacchi 		if (ret_val)
1153c124a83eSRobert Mustacchi 			return ret_val;
115475eba5b6SRobert Mustacchi 
115575eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
115675eba5b6SRobert Mustacchi 					       &data);
115775eba5b6SRobert Mustacchi 		if (ret_val)
1158c124a83eSRobert Mustacchi 			return ret_val;
115975eba5b6SRobert Mustacchi 
116075eba5b6SRobert Mustacchi 		data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
116175eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
116275eba5b6SRobert Mustacchi 						data);
116375eba5b6SRobert Mustacchi 		if (ret_val)
1164c124a83eSRobert Mustacchi 			return ret_val;
116575eba5b6SRobert Mustacchi 	}
116675eba5b6SRobert Mustacchi 
1167c124a83eSRobert Mustacchi 	/* Workaround: Disable padding in Kumeran interface in the MAC
116875eba5b6SRobert Mustacchi 	 * and in the PHY to avoid CRC errors.
116975eba5b6SRobert Mustacchi 	 */
117075eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_INBAND_CTRL, &data);
117175eba5b6SRobert Mustacchi 	if (ret_val)
1172c124a83eSRobert Mustacchi 		return ret_val;
117375eba5b6SRobert Mustacchi 
117475eba5b6SRobert Mustacchi 	data |= GG82563_ICR_DIS_PADDING;
117575eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_INBAND_CTRL, data);
117675eba5b6SRobert Mustacchi 	if (ret_val)
117775eba5b6SRobert Mustacchi 		return ret_val;
1178c124a83eSRobert Mustacchi 
1179c124a83eSRobert Mustacchi 	return E1000_SUCCESS;
118075eba5b6SRobert Mustacchi }
118175eba5b6SRobert Mustacchi 
118275eba5b6SRobert Mustacchi /**
118375eba5b6SRobert Mustacchi  *  e1000_setup_copper_link_80003es2lan - Setup Copper Link for ESB2
118475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
118575eba5b6SRobert Mustacchi  *
118675eba5b6SRobert Mustacchi  *  Essentially a wrapper for setting up all things "copper" related.
118775eba5b6SRobert Mustacchi  *  This is a function pointer entry point called by the mac module.
118875eba5b6SRobert Mustacchi  **/
e1000_setup_copper_link_80003es2lan(struct e1000_hw * hw)118975eba5b6SRobert Mustacchi static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
119075eba5b6SRobert Mustacchi {
119175eba5b6SRobert Mustacchi 	u32 ctrl;
119275eba5b6SRobert Mustacchi 	s32 ret_val;
119375eba5b6SRobert Mustacchi 	u16 reg_data;
119475eba5b6SRobert Mustacchi 
119575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_setup_copper_link_80003es2lan");
119675eba5b6SRobert Mustacchi 
119775eba5b6SRobert Mustacchi 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
119875eba5b6SRobert Mustacchi 	ctrl |= E1000_CTRL_SLU;
119975eba5b6SRobert Mustacchi 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
120075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
120175eba5b6SRobert Mustacchi 
1202c124a83eSRobert Mustacchi 	/* Set the mac to wait the maximum time between each
120375eba5b6SRobert Mustacchi 	 * iteration and increase the max iterations when
120475eba5b6SRobert Mustacchi 	 * polling the phy; this fixes erroneous timeouts at 10Mbps.
120575eba5b6SRobert Mustacchi 	 */
120675eba5b6SRobert Mustacchi 	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
120775eba5b6SRobert Mustacchi 						   0xFFFF);
120875eba5b6SRobert Mustacchi 	if (ret_val)
1209c124a83eSRobert Mustacchi 		return ret_val;
121075eba5b6SRobert Mustacchi 	ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
121175eba5b6SRobert Mustacchi 						  &reg_data);
121275eba5b6SRobert Mustacchi 	if (ret_val)
1213c124a83eSRobert Mustacchi 		return ret_val;
121475eba5b6SRobert Mustacchi 	reg_data |= 0x3F;
121575eba5b6SRobert Mustacchi 	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
121675eba5b6SRobert Mustacchi 						   reg_data);
121775eba5b6SRobert Mustacchi 	if (ret_val)
1218c124a83eSRobert Mustacchi 		return ret_val;
1219c124a83eSRobert Mustacchi 	ret_val =
1220c124a83eSRobert Mustacchi 	    e1000_read_kmrn_reg_80003es2lan(hw,
1221c124a83eSRobert Mustacchi 					    E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
1222c124a83eSRobert Mustacchi 					    &reg_data);
122375eba5b6SRobert Mustacchi 	if (ret_val)
1224c124a83eSRobert Mustacchi 		return ret_val;
122575eba5b6SRobert Mustacchi 	reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
1226c124a83eSRobert Mustacchi 	ret_val =
1227c124a83eSRobert Mustacchi 	    e1000_write_kmrn_reg_80003es2lan(hw,
1228c124a83eSRobert Mustacchi 					     E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
1229c124a83eSRobert Mustacchi 					     reg_data);
123075eba5b6SRobert Mustacchi 	if (ret_val)
1231c124a83eSRobert Mustacchi 		return ret_val;
123275eba5b6SRobert Mustacchi 
123375eba5b6SRobert Mustacchi 	ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw);
123475eba5b6SRobert Mustacchi 	if (ret_val)
123575eba5b6SRobert Mustacchi 		return ret_val;
1236c124a83eSRobert Mustacchi 
1237c124a83eSRobert Mustacchi 	return e1000_setup_copper_link_generic(hw);
123875eba5b6SRobert Mustacchi }
123975eba5b6SRobert Mustacchi 
124075eba5b6SRobert Mustacchi /**
124175eba5b6SRobert Mustacchi  *  e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up
124275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
124375eba5b6SRobert Mustacchi  *  @duplex: current duplex setting
124475eba5b6SRobert Mustacchi  *
124575eba5b6SRobert Mustacchi  *  Configure the KMRN interface by applying last minute quirks for
124675eba5b6SRobert Mustacchi  *  10/100 operation.
124775eba5b6SRobert Mustacchi  **/
e1000_cfg_on_link_up_80003es2lan(struct e1000_hw * hw)124875eba5b6SRobert Mustacchi static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
124975eba5b6SRobert Mustacchi {
125075eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
125175eba5b6SRobert Mustacchi 	u16 speed;
125275eba5b6SRobert Mustacchi 	u16 duplex;
125375eba5b6SRobert Mustacchi 
125475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_configure_on_link_up");
125575eba5b6SRobert Mustacchi 
125675eba5b6SRobert Mustacchi 	if (hw->phy.media_type == e1000_media_type_copper) {
125775eba5b6SRobert Mustacchi 		ret_val = e1000_get_speed_and_duplex_copper_generic(hw, &speed,
125875eba5b6SRobert Mustacchi 								    &duplex);
125975eba5b6SRobert Mustacchi 		if (ret_val)
1260c124a83eSRobert Mustacchi 			return ret_val;
126175eba5b6SRobert Mustacchi 
126275eba5b6SRobert Mustacchi 		if (speed == SPEED_1000)
126375eba5b6SRobert Mustacchi 			ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw);
126475eba5b6SRobert Mustacchi 		else
126575eba5b6SRobert Mustacchi 			ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex);
126675eba5b6SRobert Mustacchi 	}
126775eba5b6SRobert Mustacchi 
126875eba5b6SRobert Mustacchi 	return ret_val;
126975eba5b6SRobert Mustacchi }
127075eba5b6SRobert Mustacchi 
127175eba5b6SRobert Mustacchi /**
127275eba5b6SRobert Mustacchi  *  e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation
127375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
127475eba5b6SRobert Mustacchi  *  @duplex: current duplex setting
127575eba5b6SRobert Mustacchi  *
127675eba5b6SRobert Mustacchi  *  Configure the KMRN interface by applying last minute quirks for
127775eba5b6SRobert Mustacchi  *  10/100 operation.
127875eba5b6SRobert Mustacchi  **/
e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw * hw,u16 duplex)127975eba5b6SRobert Mustacchi static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
128075eba5b6SRobert Mustacchi {
1281c124a83eSRobert Mustacchi 	s32 ret_val;
128275eba5b6SRobert Mustacchi 	u32 tipg;
128375eba5b6SRobert Mustacchi 	u32 i = 0;
128475eba5b6SRobert Mustacchi 	u16 reg_data, reg_data2;
128575eba5b6SRobert Mustacchi 
128675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_configure_kmrn_for_10_100");
128775eba5b6SRobert Mustacchi 
128875eba5b6SRobert Mustacchi 	reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
1289c124a83eSRobert Mustacchi 	ret_val =
1290c124a83eSRobert Mustacchi 	    e1000_write_kmrn_reg_80003es2lan(hw,
129175eba5b6SRobert Mustacchi 					     E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
129275eba5b6SRobert Mustacchi 					     reg_data);
129375eba5b6SRobert Mustacchi 	if (ret_val)
1294c124a83eSRobert Mustacchi 		return ret_val;
129575eba5b6SRobert Mustacchi 
129675eba5b6SRobert Mustacchi 	/* Configure Transmit Inter-Packet Gap */
129775eba5b6SRobert Mustacchi 	tipg = E1000_READ_REG(hw, E1000_TIPG);
129875eba5b6SRobert Mustacchi 	tipg &= ~E1000_TIPG_IPGT_MASK;
129975eba5b6SRobert Mustacchi 	tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN;
130075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TIPG, tipg);
130175eba5b6SRobert Mustacchi 
130275eba5b6SRobert Mustacchi 	do {
130375eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
130475eba5b6SRobert Mustacchi 					       &reg_data);
130575eba5b6SRobert Mustacchi 		if (ret_val)
1306c124a83eSRobert Mustacchi 			return ret_val;
130775eba5b6SRobert Mustacchi 
130875eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
130975eba5b6SRobert Mustacchi 					       &reg_data2);
131075eba5b6SRobert Mustacchi 		if (ret_val)
1311c124a83eSRobert Mustacchi 			return ret_val;
131275eba5b6SRobert Mustacchi 		i++;
131375eba5b6SRobert Mustacchi 	} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
131475eba5b6SRobert Mustacchi 
131575eba5b6SRobert Mustacchi 	if (duplex == HALF_DUPLEX)
131675eba5b6SRobert Mustacchi 		reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
131775eba5b6SRobert Mustacchi 	else
131875eba5b6SRobert Mustacchi 		reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
131975eba5b6SRobert Mustacchi 
1320c124a83eSRobert Mustacchi 	return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
132175eba5b6SRobert Mustacchi }
132275eba5b6SRobert Mustacchi 
132375eba5b6SRobert Mustacchi /**
132475eba5b6SRobert Mustacchi  *  e1000_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation
132575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
132675eba5b6SRobert Mustacchi  *
132775eba5b6SRobert Mustacchi  *  Configure the KMRN interface by applying last minute quirks for
132875eba5b6SRobert Mustacchi  *  gigabit operation.
132975eba5b6SRobert Mustacchi  **/
e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw * hw)133075eba5b6SRobert Mustacchi static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
133175eba5b6SRobert Mustacchi {
1332c124a83eSRobert Mustacchi 	s32 ret_val;
133375eba5b6SRobert Mustacchi 	u16 reg_data, reg_data2;
133475eba5b6SRobert Mustacchi 	u32 tipg;
133575eba5b6SRobert Mustacchi 	u32 i = 0;
133675eba5b6SRobert Mustacchi 
133775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_configure_kmrn_for_1000");
133875eba5b6SRobert Mustacchi 
133975eba5b6SRobert Mustacchi 	reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
1340c124a83eSRobert Mustacchi 	ret_val =
1341c124a83eSRobert Mustacchi 	    e1000_write_kmrn_reg_80003es2lan(hw,
1342c124a83eSRobert Mustacchi 					     E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
1343c124a83eSRobert Mustacchi 					     reg_data);
134475eba5b6SRobert Mustacchi 	if (ret_val)
1345c124a83eSRobert Mustacchi 		return ret_val;
134675eba5b6SRobert Mustacchi 
134775eba5b6SRobert Mustacchi 	/* Configure Transmit Inter-Packet Gap */
134875eba5b6SRobert Mustacchi 	tipg = E1000_READ_REG(hw, E1000_TIPG);
134975eba5b6SRobert Mustacchi 	tipg &= ~E1000_TIPG_IPGT_MASK;
135075eba5b6SRobert Mustacchi 	tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
135175eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TIPG, tipg);
135275eba5b6SRobert Mustacchi 
135375eba5b6SRobert Mustacchi 	do {
135475eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
135575eba5b6SRobert Mustacchi 					       &reg_data);
135675eba5b6SRobert Mustacchi 		if (ret_val)
1357c124a83eSRobert Mustacchi 			return ret_val;
135875eba5b6SRobert Mustacchi 
135975eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
136075eba5b6SRobert Mustacchi 					       &reg_data2);
136175eba5b6SRobert Mustacchi 		if (ret_val)
1362c124a83eSRobert Mustacchi 			return ret_val;
136375eba5b6SRobert Mustacchi 		i++;
136475eba5b6SRobert Mustacchi 	} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
136575eba5b6SRobert Mustacchi 
136675eba5b6SRobert Mustacchi 	reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
136775eba5b6SRobert Mustacchi 
1368c124a83eSRobert Mustacchi 	return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
136975eba5b6SRobert Mustacchi }
137075eba5b6SRobert Mustacchi 
137175eba5b6SRobert Mustacchi /**
137275eba5b6SRobert Mustacchi  *  e1000_read_kmrn_reg_80003es2lan - Read kumeran register
137375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
137475eba5b6SRobert Mustacchi  *  @offset: register offset to be read
137575eba5b6SRobert Mustacchi  *  @data: pointer to the read data
137675eba5b6SRobert Mustacchi  *
137775eba5b6SRobert Mustacchi  *  Acquire semaphore, then read the PHY register at offset
137875eba5b6SRobert Mustacchi  *  using the kumeran interface.  The information retrieved is stored in data.
137975eba5b6SRobert Mustacchi  *  Release the semaphore before exiting.
138075eba5b6SRobert Mustacchi  **/
e1000_read_kmrn_reg_80003es2lan(struct e1000_hw * hw,u32 offset,u16 * data)138175eba5b6SRobert Mustacchi static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
138275eba5b6SRobert Mustacchi 					   u16 *data)
138375eba5b6SRobert Mustacchi {
138475eba5b6SRobert Mustacchi 	u32 kmrnctrlsta;
1385c124a83eSRobert Mustacchi 	s32 ret_val;
138675eba5b6SRobert Mustacchi 
138775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_kmrn_reg_80003es2lan");
138875eba5b6SRobert Mustacchi 
138975eba5b6SRobert Mustacchi 	ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
139075eba5b6SRobert Mustacchi 	if (ret_val)
1391c124a83eSRobert Mustacchi 		return ret_val;
139275eba5b6SRobert Mustacchi 
139375eba5b6SRobert Mustacchi 	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
139475eba5b6SRobert Mustacchi 		       E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
139575eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
139675eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
139775eba5b6SRobert Mustacchi 
139875eba5b6SRobert Mustacchi 	usec_delay(2);
139975eba5b6SRobert Mustacchi 
140075eba5b6SRobert Mustacchi 	kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA);
140175eba5b6SRobert Mustacchi 	*data = (u16)kmrnctrlsta;
140275eba5b6SRobert Mustacchi 
140375eba5b6SRobert Mustacchi 	e1000_release_mac_csr_80003es2lan(hw);
140475eba5b6SRobert Mustacchi 
140575eba5b6SRobert Mustacchi 	return ret_val;
140675eba5b6SRobert Mustacchi }
140775eba5b6SRobert Mustacchi 
140875eba5b6SRobert Mustacchi /**
140975eba5b6SRobert Mustacchi  *  e1000_write_kmrn_reg_80003es2lan - Write kumeran register
141075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
141175eba5b6SRobert Mustacchi  *  @offset: register offset to write to
141275eba5b6SRobert Mustacchi  *  @data: data to write at register offset
141375eba5b6SRobert Mustacchi  *
141475eba5b6SRobert Mustacchi  *  Acquire semaphore, then write the data to PHY register
141575eba5b6SRobert Mustacchi  *  at the offset using the kumeran interface.  Release semaphore
141675eba5b6SRobert Mustacchi  *  before exiting.
141775eba5b6SRobert Mustacchi  **/
e1000_write_kmrn_reg_80003es2lan(struct e1000_hw * hw,u32 offset,u16 data)141875eba5b6SRobert Mustacchi static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
141975eba5b6SRobert Mustacchi 					    u16 data)
142075eba5b6SRobert Mustacchi {
142175eba5b6SRobert Mustacchi 	u32 kmrnctrlsta;
1422c124a83eSRobert Mustacchi 	s32 ret_val;
142375eba5b6SRobert Mustacchi 
142475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_kmrn_reg_80003es2lan");
142575eba5b6SRobert Mustacchi 
142675eba5b6SRobert Mustacchi 	ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
142775eba5b6SRobert Mustacchi 	if (ret_val)
1428c124a83eSRobert Mustacchi 		return ret_val;
142975eba5b6SRobert Mustacchi 
143075eba5b6SRobert Mustacchi 	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
143175eba5b6SRobert Mustacchi 		       E1000_KMRNCTRLSTA_OFFSET) | data;
143275eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
143375eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
143475eba5b6SRobert Mustacchi 
143575eba5b6SRobert Mustacchi 	usec_delay(2);
143675eba5b6SRobert Mustacchi 
143775eba5b6SRobert Mustacchi 	e1000_release_mac_csr_80003es2lan(hw);
143875eba5b6SRobert Mustacchi 
143975eba5b6SRobert Mustacchi 	return ret_val;
144075eba5b6SRobert Mustacchi }
144175eba5b6SRobert Mustacchi 
144275eba5b6SRobert Mustacchi /**
144375eba5b6SRobert Mustacchi  *  e1000_read_mac_addr_80003es2lan - Read device MAC address
144475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
144575eba5b6SRobert Mustacchi  **/
e1000_read_mac_addr_80003es2lan(struct e1000_hw * hw)144675eba5b6SRobert Mustacchi static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
144775eba5b6SRobert Mustacchi {
1448c124a83eSRobert Mustacchi 	s32 ret_val;
144975eba5b6SRobert Mustacchi 
145075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_mac_addr_80003es2lan");
145175eba5b6SRobert Mustacchi 
1452c124a83eSRobert Mustacchi 	/* If there's an alternate MAC address place it in RAR0
145375eba5b6SRobert Mustacchi 	 * so that it will override the Si installed default perm
145475eba5b6SRobert Mustacchi 	 * address.
145575eba5b6SRobert Mustacchi 	 */
145675eba5b6SRobert Mustacchi 	ret_val = e1000_check_alt_mac_addr_generic(hw);
145775eba5b6SRobert Mustacchi 	if (ret_val)
145875eba5b6SRobert Mustacchi 		return ret_val;
1459c124a83eSRobert Mustacchi 
1460c124a83eSRobert Mustacchi 	return e1000_read_mac_addr_generic(hw);
146175eba5b6SRobert Mustacchi }
146275eba5b6SRobert Mustacchi 
146375eba5b6SRobert Mustacchi /**
146475eba5b6SRobert Mustacchi  * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down
146575eba5b6SRobert Mustacchi  * @hw: pointer to the HW structure
146675eba5b6SRobert Mustacchi  *
146775eba5b6SRobert Mustacchi  * In the case of a PHY power down to save power, or to turn off link during a
146875eba5b6SRobert Mustacchi  * driver unload, or wake on lan is not enabled, remove the link.
146975eba5b6SRobert Mustacchi  **/
e1000_power_down_phy_copper_80003es2lan(struct e1000_hw * hw)147075eba5b6SRobert Mustacchi static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw)
147175eba5b6SRobert Mustacchi {
147275eba5b6SRobert Mustacchi 	/* If the management interface is not enabled, then power down */
147375eba5b6SRobert Mustacchi 	if (!(hw->mac.ops.check_mng_mode(hw) ||
147475eba5b6SRobert Mustacchi 	      hw->phy.ops.check_reset_block(hw)))
147575eba5b6SRobert Mustacchi 		e1000_power_down_phy_copper(hw);
147675eba5b6SRobert Mustacchi 
147775eba5b6SRobert Mustacchi 	return;
147875eba5b6SRobert Mustacchi }
147975eba5b6SRobert Mustacchi 
148075eba5b6SRobert Mustacchi /**
148175eba5b6SRobert Mustacchi  *  e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters
148275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
148375eba5b6SRobert Mustacchi  *
148475eba5b6SRobert Mustacchi  *  Clears the hardware counters by reading the counter registers.
148575eba5b6SRobert Mustacchi  **/
e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw * hw)148675eba5b6SRobert Mustacchi static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw)
148775eba5b6SRobert Mustacchi {
148875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_clear_hw_cntrs_80003es2lan");
148975eba5b6SRobert Mustacchi 
149075eba5b6SRobert Mustacchi 	e1000_clear_hw_cntrs_base_generic(hw);
149175eba5b6SRobert Mustacchi 
149275eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PRC64);
149375eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PRC127);
149475eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PRC255);
149575eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PRC511);
149675eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PRC1023);
149775eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PRC1522);
149875eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PTC64);
149975eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PTC127);
150075eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PTC255);
150175eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PTC511);
150275eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PTC1023);
150375eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_PTC1522);
150475eba5b6SRobert Mustacchi 
150575eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ALGNERRC);
150675eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_RXERRC);
150775eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_TNCRS);
150875eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_CEXTERR);
150975eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_TSCTC);
151075eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_TSCTFC);
151175eba5b6SRobert Mustacchi 
151275eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_MGTPRC);
151375eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_MGTPDC);
151475eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_MGTPTC);
151575eba5b6SRobert Mustacchi 
151675eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_IAC);
151775eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICRXOC);
151875eba5b6SRobert Mustacchi 
151975eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICRXPTC);
152075eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICRXATC);
152175eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICTXPTC);
152275eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICTXATC);
152375eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICTXQEC);
152475eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICTXQMTC);
152575eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICRXDMTC);
152675eba5b6SRobert Mustacchi }
1527