xref: /freebsd/sys/dev/e1000/e1000_80003es2lan.c (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
18cfa0ad2SJack F Vogel /******************************************************************************
27282444bSPedro F. Giffuni   SPDX-License-Identifier: BSD-3-Clause
38cfa0ad2SJack F Vogel 
4702cac6cSKevin Bowling   Copyright (c) 2001-2020, Intel Corporation
58cfa0ad2SJack F Vogel   All rights reserved.
68cfa0ad2SJack F Vogel 
78cfa0ad2SJack F Vogel   Redistribution and use in source and binary forms, with or without
88cfa0ad2SJack F Vogel   modification, are permitted provided that the following conditions are met:
98cfa0ad2SJack F Vogel 
108cfa0ad2SJack F Vogel    1. Redistributions of source code must retain the above copyright notice,
118cfa0ad2SJack F Vogel       this list of conditions and the following disclaimer.
128cfa0ad2SJack F Vogel 
138cfa0ad2SJack F Vogel    2. Redistributions in binary form must reproduce the above copyright
148cfa0ad2SJack F Vogel       notice, this list of conditions and the following disclaimer in the
158cfa0ad2SJack F Vogel       documentation and/or other materials provided with the distribution.
168cfa0ad2SJack F Vogel 
178cfa0ad2SJack F Vogel    3. Neither the name of the Intel Corporation nor the names of its
188cfa0ad2SJack F Vogel       contributors may be used to endorse or promote products derived from
198cfa0ad2SJack F Vogel       this software without specific prior written permission.
208cfa0ad2SJack F Vogel 
218cfa0ad2SJack F Vogel   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
228cfa0ad2SJack F Vogel   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
238cfa0ad2SJack F Vogel   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
248cfa0ad2SJack F Vogel   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
258cfa0ad2SJack F Vogel   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
268cfa0ad2SJack F Vogel   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
278cfa0ad2SJack F Vogel   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
288cfa0ad2SJack F Vogel   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
298cfa0ad2SJack F Vogel   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
308cfa0ad2SJack F Vogel   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
318cfa0ad2SJack F Vogel   POSSIBILITY OF SUCH DAMAGE.
328cfa0ad2SJack F Vogel 
338cfa0ad2SJack F Vogel ******************************************************************************/
348cfa0ad2SJack F Vogel 
357609433eSJack F Vogel /* 80003ES2LAN Gigabit Ethernet Controller (Copper)
36daf9197cSJack F Vogel  * 80003ES2LAN Gigabit Ethernet Controller (Serdes)
378cfa0ad2SJack F Vogel  */
388cfa0ad2SJack F Vogel 
398cfa0ad2SJack F Vogel #include "e1000_api.h"
408cfa0ad2SJack F Vogel 
418cfa0ad2SJack F Vogel static s32  e1000_acquire_phy_80003es2lan(struct e1000_hw *hw);
428cfa0ad2SJack F Vogel static void e1000_release_phy_80003es2lan(struct e1000_hw *hw);
438cfa0ad2SJack F Vogel static s32  e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);
448cfa0ad2SJack F Vogel static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw);
458cfa0ad2SJack F Vogel static s32  e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
468cfa0ad2SJack F Vogel 						   u32 offset,
478cfa0ad2SJack F Vogel 						   u16 *data);
488cfa0ad2SJack F Vogel static s32  e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
498cfa0ad2SJack F Vogel 						    u32 offset,
508cfa0ad2SJack F Vogel 						    u16 data);
518cfa0ad2SJack F Vogel static s32  e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
528cfa0ad2SJack F Vogel 					u16 words, u16 *data);
538cfa0ad2SJack F Vogel static s32  e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw);
548cfa0ad2SJack F Vogel static s32  e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw);
558cfa0ad2SJack F Vogel static s32  e1000_get_cable_length_80003es2lan(struct e1000_hw *hw);
568cfa0ad2SJack F Vogel static s32  e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
578cfa0ad2SJack F Vogel 					       u16 *duplex);
588cfa0ad2SJack F Vogel static s32  e1000_reset_hw_80003es2lan(struct e1000_hw *hw);
598cfa0ad2SJack F Vogel static s32  e1000_init_hw_80003es2lan(struct e1000_hw *hw);
608cfa0ad2SJack F Vogel static s32  e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);
618cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw);
628cfa0ad2SJack F Vogel static s32  e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex);
638cfa0ad2SJack F Vogel static s32  e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw);
64daf9197cSJack F Vogel static s32  e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw);
65daf9197cSJack F Vogel static s32  e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
66daf9197cSJack F Vogel 					    u16 *data);
67daf9197cSJack F Vogel static s32  e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
68daf9197cSJack F Vogel 					     u16 data);
698cfa0ad2SJack F Vogel static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);
708cfa0ad2SJack F Vogel static s32  e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw);
718cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
728cfa0ad2SJack F Vogel 
737609433eSJack F Vogel /* A table for the GG82563 cable length where the range is defined
748cfa0ad2SJack F Vogel  * with a lower bound at "index" and the upper bound at
758cfa0ad2SJack F Vogel  * "index + 5".
768cfa0ad2SJack F Vogel  */
77730d3130SJack F Vogel static const u16 e1000_gg82563_cable_length_table[] = {
78730d3130SJack F Vogel 	0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
798cfa0ad2SJack F Vogel #define GG82563_CABLE_LENGTH_TABLE_SIZE \
808cfa0ad2SJack F Vogel 		(sizeof(e1000_gg82563_cable_length_table) / \
818cfa0ad2SJack F Vogel 		 sizeof(e1000_gg82563_cable_length_table[0]))
828cfa0ad2SJack F Vogel 
838cfa0ad2SJack F Vogel /**
848cfa0ad2SJack F Vogel  *  e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs.
858cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
868cfa0ad2SJack F Vogel  **/
e1000_init_phy_params_80003es2lan(struct e1000_hw * hw)878cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
888cfa0ad2SJack F Vogel {
898cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
907609433eSJack F Vogel 	s32 ret_val;
918cfa0ad2SJack F Vogel 
928cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_phy_params_80003es2lan");
938cfa0ad2SJack F Vogel 
948cfa0ad2SJack F Vogel 	if (hw->phy.media_type != e1000_media_type_copper) {
958cfa0ad2SJack F Vogel 		phy->type = e1000_phy_none;
967609433eSJack F Vogel 		return E1000_SUCCESS;
978cfa0ad2SJack F Vogel 	} else {
988cfa0ad2SJack F Vogel 		phy->ops.power_up = e1000_power_up_phy_copper;
998cfa0ad2SJack F Vogel 		phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan;
1008cfa0ad2SJack F Vogel 	}
1018cfa0ad2SJack F Vogel 
1028cfa0ad2SJack F Vogel 	phy->addr		= 1;
1038cfa0ad2SJack F Vogel 	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
1048cfa0ad2SJack F Vogel 	phy->reset_delay_us	= 100;
1058cfa0ad2SJack F Vogel 	phy->type		= e1000_phy_gg82563;
1068cfa0ad2SJack F Vogel 
1078cfa0ad2SJack F Vogel 	phy->ops.acquire	= e1000_acquire_phy_80003es2lan;
1088cfa0ad2SJack F Vogel 	phy->ops.check_polarity	= e1000_check_polarity_m88;
1098cfa0ad2SJack F Vogel 	phy->ops.check_reset_block = e1000_check_reset_block_generic;
1108cfa0ad2SJack F Vogel 	phy->ops.commit		= e1000_phy_sw_reset_generic;
1118cfa0ad2SJack F Vogel 	phy->ops.get_cfg_done	= e1000_get_cfg_done_80003es2lan;
1128cfa0ad2SJack F Vogel 	phy->ops.get_info	= e1000_get_phy_info_m88;
1138cfa0ad2SJack F Vogel 	phy->ops.release	= e1000_release_phy_80003es2lan;
1148cfa0ad2SJack F Vogel 	phy->ops.reset		= e1000_phy_hw_reset_generic;
1158cfa0ad2SJack F Vogel 	phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
1168cfa0ad2SJack F Vogel 
1178cfa0ad2SJack F Vogel 	phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan;
1188cfa0ad2SJack F Vogel 	phy->ops.get_cable_length = e1000_get_cable_length_80003es2lan;
1198cfa0ad2SJack F Vogel 	phy->ops.read_reg	= e1000_read_phy_reg_gg82563_80003es2lan;
1208cfa0ad2SJack F Vogel 	phy->ops.write_reg	= e1000_write_phy_reg_gg82563_80003es2lan;
1218cfa0ad2SJack F Vogel 
122daf9197cSJack F Vogel 	phy->ops.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan;
123daf9197cSJack F Vogel 
1248cfa0ad2SJack F Vogel 	/* This can only be done after all function pointers are setup. */
1258cfa0ad2SJack F Vogel 	ret_val = e1000_get_phy_id(hw);
1268cfa0ad2SJack F Vogel 
1278cfa0ad2SJack F Vogel 	/* Verify phy id */
1287609433eSJack F Vogel 	if (phy->id != GG82563_E_PHY_ID)
1297609433eSJack F Vogel 		return -E1000_ERR_PHY;
1308cfa0ad2SJack F Vogel 
1318cfa0ad2SJack F Vogel 	return ret_val;
1328cfa0ad2SJack F Vogel }
1338cfa0ad2SJack F Vogel 
1348cfa0ad2SJack F Vogel /**
1358cfa0ad2SJack F Vogel  *  e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs.
1368cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
1378cfa0ad2SJack F Vogel  **/
e1000_init_nvm_params_80003es2lan(struct e1000_hw * hw)1388cfa0ad2SJack F Vogel static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
1398cfa0ad2SJack F Vogel {
1408cfa0ad2SJack F Vogel 	struct e1000_nvm_info *nvm = &hw->nvm;
1418cfa0ad2SJack F Vogel 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
1428cfa0ad2SJack F Vogel 	u16 size;
1438cfa0ad2SJack F Vogel 
1448cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_nvm_params_80003es2lan");
1458cfa0ad2SJack F Vogel 
1468cfa0ad2SJack F Vogel 	nvm->opcode_bits = 8;
1478cfa0ad2SJack F Vogel 	nvm->delay_usec = 1;
1488cfa0ad2SJack F Vogel 	switch (nvm->override) {
1498cfa0ad2SJack F Vogel 	case e1000_nvm_override_spi_large:
1508cfa0ad2SJack F Vogel 		nvm->page_size = 32;
1518cfa0ad2SJack F Vogel 		nvm->address_bits = 16;
1528cfa0ad2SJack F Vogel 		break;
1538cfa0ad2SJack F Vogel 	case e1000_nvm_override_spi_small:
1548cfa0ad2SJack F Vogel 		nvm->page_size = 8;
1558cfa0ad2SJack F Vogel 		nvm->address_bits = 8;
1568cfa0ad2SJack F Vogel 		break;
1578cfa0ad2SJack F Vogel 	default:
1588cfa0ad2SJack F Vogel 		nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
1598cfa0ad2SJack F Vogel 		nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
1608cfa0ad2SJack F Vogel 		break;
1618cfa0ad2SJack F Vogel 	}
1628cfa0ad2SJack F Vogel 
1638cfa0ad2SJack F Vogel 	nvm->type = e1000_nvm_eeprom_spi;
1648cfa0ad2SJack F Vogel 
1658cfa0ad2SJack F Vogel 	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
1668cfa0ad2SJack F Vogel 		     E1000_EECD_SIZE_EX_SHIFT);
1678cfa0ad2SJack F Vogel 
1687609433eSJack F Vogel 	/* Added to a constant, "size" becomes the left-shift value
1698cfa0ad2SJack F Vogel 	 * for setting word_size.
1708cfa0ad2SJack F Vogel 	 */
1718cfa0ad2SJack F Vogel 	size += NVM_WORD_SIZE_BASE_SHIFT;
1728cfa0ad2SJack F Vogel 
1738cfa0ad2SJack F Vogel 	/* EEPROM access above 16k is unsupported */
1748cfa0ad2SJack F Vogel 	if (size > 14)
1758cfa0ad2SJack F Vogel 		size = 14;
1768cfa0ad2SJack F Vogel 	nvm->word_size = 1 << size;
1778cfa0ad2SJack F Vogel 
1788cfa0ad2SJack F Vogel 	/* Function Pointers */
1798cfa0ad2SJack F Vogel 	nvm->ops.acquire	= e1000_acquire_nvm_80003es2lan;
1808cfa0ad2SJack F Vogel 	nvm->ops.read		= e1000_read_nvm_eerd;
1818cfa0ad2SJack F Vogel 	nvm->ops.release	= e1000_release_nvm_80003es2lan;
1828cfa0ad2SJack F Vogel 	nvm->ops.update		= e1000_update_nvm_checksum_generic;
1838cfa0ad2SJack F Vogel 	nvm->ops.valid_led_default = e1000_valid_led_default_generic;
1848cfa0ad2SJack F Vogel 	nvm->ops.validate	= e1000_validate_nvm_checksum_generic;
1858cfa0ad2SJack F Vogel 	nvm->ops.write		= e1000_write_nvm_80003es2lan;
1868cfa0ad2SJack F Vogel 
1878cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
1888cfa0ad2SJack F Vogel }
1898cfa0ad2SJack F Vogel 
1908cfa0ad2SJack F Vogel /**
1918cfa0ad2SJack F Vogel  *  e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs.
1928cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
1938cfa0ad2SJack F Vogel  **/
e1000_init_mac_params_80003es2lan(struct e1000_hw * hw)1948cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
1958cfa0ad2SJack F Vogel {
1968cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
1978cfa0ad2SJack F Vogel 
1988cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_mac_params_80003es2lan");
1998cfa0ad2SJack F Vogel 
2004edd8523SJack F Vogel 	/* Set media type and media-dependent function pointers */
2018cfa0ad2SJack F Vogel 	switch (hw->device_id) {
2028cfa0ad2SJack F Vogel 	case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
2038cfa0ad2SJack F Vogel 		hw->phy.media_type = e1000_media_type_internal_serdes;
2044edd8523SJack F Vogel 		mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
2054edd8523SJack F Vogel 		mac->ops.setup_physical_interface =
2064edd8523SJack F Vogel 					e1000_setup_fiber_serdes_link_generic;
2078cfa0ad2SJack F Vogel 		break;
2088cfa0ad2SJack F Vogel 	default:
2098cfa0ad2SJack F Vogel 		hw->phy.media_type = e1000_media_type_copper;
2104edd8523SJack F Vogel 		mac->ops.check_for_link = e1000_check_for_copper_link_generic;
2114edd8523SJack F Vogel 		mac->ops.setup_physical_interface =
2124edd8523SJack F Vogel 					e1000_setup_copper_link_80003es2lan;
2138cfa0ad2SJack F Vogel 		break;
2148cfa0ad2SJack F Vogel 	}
2158cfa0ad2SJack F Vogel 
2168cfa0ad2SJack F Vogel 	/* Set mta register count */
2178cfa0ad2SJack F Vogel 	mac->mta_reg_count = 128;
2188cfa0ad2SJack F Vogel 	/* Set rar entry count */
2198cfa0ad2SJack F Vogel 	mac->rar_entry_count = E1000_RAR_ENTRIES;
2208cfa0ad2SJack F Vogel 	/* Set if part includes ASF firmware */
221*1bbdc25fSKevin Bowling 	mac->asf_firmware_present = true;
2228ec87fc5SJack F Vogel 	/* FWSM register */
223*1bbdc25fSKevin Bowling 	mac->has_fwsm = true;
2248ec87fc5SJack F Vogel 	/* ARC supported; valid only if manageability features are enabled. */
2257609433eSJack F Vogel 	mac->arc_subsystem_valid = !!(E1000_READ_REG(hw, E1000_FWSM) &
2267609433eSJack F Vogel 				      E1000_FWSM_MODE_MASK);
2274edd8523SJack F Vogel 	/* Adaptive IFS not supported */
228*1bbdc25fSKevin Bowling 	mac->adaptive_ifs = false;
2298cfa0ad2SJack F Vogel 
2308cfa0ad2SJack F Vogel 	/* Function pointers */
2318cfa0ad2SJack F Vogel 
2328cfa0ad2SJack F Vogel 	/* bus type/speed/width */
2338cfa0ad2SJack F Vogel 	mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
2348cfa0ad2SJack F Vogel 	/* reset */
2358cfa0ad2SJack F Vogel 	mac->ops.reset_hw = e1000_reset_hw_80003es2lan;
2368cfa0ad2SJack F Vogel 	/* hw initialization */
2378cfa0ad2SJack F Vogel 	mac->ops.init_hw = e1000_init_hw_80003es2lan;
2388cfa0ad2SJack F Vogel 	/* link setup */
2398cfa0ad2SJack F Vogel 	mac->ops.setup_link = e1000_setup_link_generic;
2408cfa0ad2SJack F Vogel 	/* check management mode */
2418cfa0ad2SJack F Vogel 	mac->ops.check_mng_mode = e1000_check_mng_mode_generic;
2428cfa0ad2SJack F Vogel 	/* multicast address update */
2438cfa0ad2SJack F Vogel 	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
2448cfa0ad2SJack F Vogel 	/* writing VFTA */
2458cfa0ad2SJack F Vogel 	mac->ops.write_vfta = e1000_write_vfta_generic;
2468cfa0ad2SJack F Vogel 	/* clearing VFTA */
2478cfa0ad2SJack F Vogel 	mac->ops.clear_vfta = e1000_clear_vfta_generic;
2488cfa0ad2SJack F Vogel 	/* read mac address */
2498cfa0ad2SJack F Vogel 	mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan;
250d035aa2dSJack F Vogel 	/* ID LED init */
251d035aa2dSJack F Vogel 	mac->ops.id_led_init = e1000_id_led_init_generic;
2528cfa0ad2SJack F Vogel 	/* blink LED */
2538cfa0ad2SJack F Vogel 	mac->ops.blink_led = e1000_blink_led_generic;
2548cfa0ad2SJack F Vogel 	/* setup LED */
2558cfa0ad2SJack F Vogel 	mac->ops.setup_led = e1000_setup_led_generic;
2568cfa0ad2SJack F Vogel 	/* cleanup LED */
2578cfa0ad2SJack F Vogel 	mac->ops.cleanup_led = e1000_cleanup_led_generic;
2588cfa0ad2SJack F Vogel 	/* turn on/off LED */
2598cfa0ad2SJack F Vogel 	mac->ops.led_on = e1000_led_on_generic;
2608cfa0ad2SJack F Vogel 	mac->ops.led_off = e1000_led_off_generic;
2618cfa0ad2SJack F Vogel 	/* clear hardware counters */
2628cfa0ad2SJack F Vogel 	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan;
2638cfa0ad2SJack F Vogel 	/* link info */
2648cfa0ad2SJack F Vogel 	mac->ops.get_link_up_info = e1000_get_link_up_info_80003es2lan;
2658cfa0ad2SJack F Vogel 
2664edd8523SJack F Vogel 	/* set lan id for port to determine which phy lock to use */
2674edd8523SJack F Vogel 	hw->mac.ops.set_lan_id(hw);
2684edd8523SJack F Vogel 
2694edd8523SJack F Vogel 	return E1000_SUCCESS;
2708cfa0ad2SJack F Vogel }
2718cfa0ad2SJack F Vogel 
2728cfa0ad2SJack F Vogel /**
2738cfa0ad2SJack F Vogel  *  e1000_init_function_pointers_80003es2lan - Init ESB2 func ptrs.
2748cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
2758cfa0ad2SJack F Vogel  *
276daf9197cSJack F Vogel  *  Called to initialize all function pointers and parameters.
2778cfa0ad2SJack F Vogel  **/
e1000_init_function_pointers_80003es2lan(struct e1000_hw * hw)2788cfa0ad2SJack F Vogel void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw)
2798cfa0ad2SJack F Vogel {
2808cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_function_pointers_80003es2lan");
2818cfa0ad2SJack F Vogel 
2828cfa0ad2SJack F Vogel 	hw->mac.ops.init_params = e1000_init_mac_params_80003es2lan;
2838cfa0ad2SJack F Vogel 	hw->nvm.ops.init_params = e1000_init_nvm_params_80003es2lan;
2848cfa0ad2SJack F Vogel 	hw->phy.ops.init_params = e1000_init_phy_params_80003es2lan;
2858cfa0ad2SJack F Vogel }
2868cfa0ad2SJack F Vogel 
2878cfa0ad2SJack F Vogel /**
2888cfa0ad2SJack F Vogel  *  e1000_acquire_phy_80003es2lan - Acquire rights to access PHY
2898cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
2908cfa0ad2SJack F Vogel  *
291daf9197cSJack F Vogel  *  A wrapper to acquire access rights to the correct PHY.
2928cfa0ad2SJack F Vogel  **/
e1000_acquire_phy_80003es2lan(struct e1000_hw * hw)2938cfa0ad2SJack F Vogel static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
2948cfa0ad2SJack F Vogel {
2958cfa0ad2SJack F Vogel 	u16 mask;
2968cfa0ad2SJack F Vogel 
2978cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_acquire_phy_80003es2lan");
2988cfa0ad2SJack F Vogel 
2998cfa0ad2SJack F Vogel 	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
300d5210708SMatt Macy 	return e1000_acquire_swfw_sync(hw, mask);
3018cfa0ad2SJack F Vogel }
3028cfa0ad2SJack F Vogel 
3038cfa0ad2SJack F Vogel /**
3048cfa0ad2SJack F Vogel  *  e1000_release_phy_80003es2lan - Release rights to access PHY
3058cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3068cfa0ad2SJack F Vogel  *
307daf9197cSJack F Vogel  *  A wrapper to release access rights to the correct PHY.
3088cfa0ad2SJack F Vogel  **/
e1000_release_phy_80003es2lan(struct e1000_hw * hw)3098cfa0ad2SJack F Vogel static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
3108cfa0ad2SJack F Vogel {
3118cfa0ad2SJack F Vogel 	u16 mask;
3128cfa0ad2SJack F Vogel 
3138cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_release_phy_80003es2lan");
3148cfa0ad2SJack F Vogel 
3158cfa0ad2SJack F Vogel 	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
316d5210708SMatt Macy 	e1000_release_swfw_sync(hw, mask);
317daf9197cSJack F Vogel }
318daf9197cSJack F Vogel 
319daf9197cSJack F Vogel /**
3204dab5c37SJack F Vogel  *  e1000_acquire_mac_csr_80003es2lan - Acquire right to access Kumeran register
321daf9197cSJack F Vogel  *  @hw: pointer to the HW structure
322daf9197cSJack F Vogel  *
323daf9197cSJack F Vogel  *  Acquire the semaphore to access the Kumeran interface.
324daf9197cSJack F Vogel  *
325daf9197cSJack F Vogel  **/
e1000_acquire_mac_csr_80003es2lan(struct e1000_hw * hw)326daf9197cSJack F Vogel static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw)
327daf9197cSJack F Vogel {
328daf9197cSJack F Vogel 	u16 mask;
329daf9197cSJack F Vogel 
330daf9197cSJack F Vogel 	DEBUGFUNC("e1000_acquire_mac_csr_80003es2lan");
331daf9197cSJack F Vogel 
332daf9197cSJack F Vogel 	mask = E1000_SWFW_CSR_SM;
333daf9197cSJack F Vogel 
334d5210708SMatt Macy 	return e1000_acquire_swfw_sync(hw, mask);
335daf9197cSJack F Vogel }
336daf9197cSJack F Vogel 
337daf9197cSJack F Vogel /**
3384dab5c37SJack F Vogel  *  e1000_release_mac_csr_80003es2lan - Release right to access Kumeran Register
339daf9197cSJack F Vogel  *  @hw: pointer to the HW structure
340daf9197cSJack F Vogel  *
341daf9197cSJack F Vogel  *  Release the semaphore used to access the Kumeran interface
342daf9197cSJack F Vogel  **/
e1000_release_mac_csr_80003es2lan(struct e1000_hw * hw)343daf9197cSJack F Vogel static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw)
344daf9197cSJack F Vogel {
345daf9197cSJack F Vogel 	u16 mask;
346daf9197cSJack F Vogel 
347daf9197cSJack F Vogel 	DEBUGFUNC("e1000_release_mac_csr_80003es2lan");
348daf9197cSJack F Vogel 
349daf9197cSJack F Vogel 	mask = E1000_SWFW_CSR_SM;
3508cfa0ad2SJack F Vogel 
351d5210708SMatt Macy 	e1000_release_swfw_sync(hw, mask);
3528cfa0ad2SJack F Vogel }
3538cfa0ad2SJack F Vogel 
3548cfa0ad2SJack F Vogel /**
3558cfa0ad2SJack F Vogel  *  e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM
3568cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3578cfa0ad2SJack F Vogel  *
358daf9197cSJack F Vogel  *  Acquire the semaphore to access the EEPROM.
3598cfa0ad2SJack F Vogel  **/
e1000_acquire_nvm_80003es2lan(struct e1000_hw * hw)3608cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw)
3618cfa0ad2SJack F Vogel {
3628cfa0ad2SJack F Vogel 	s32 ret_val;
3638cfa0ad2SJack F Vogel 
3648cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_acquire_nvm_80003es2lan");
3658cfa0ad2SJack F Vogel 
366d5210708SMatt Macy 	ret_val = e1000_acquire_swfw_sync(hw, E1000_SWFW_EEP_SM);
3678cfa0ad2SJack F Vogel 	if (ret_val)
3687609433eSJack F Vogel 		return ret_val;
3698cfa0ad2SJack F Vogel 
3708cfa0ad2SJack F Vogel 	ret_val = e1000_acquire_nvm_generic(hw);
3718cfa0ad2SJack F Vogel 
3728cfa0ad2SJack F Vogel 	if (ret_val)
373d5210708SMatt Macy 		e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
3748cfa0ad2SJack F Vogel 
3758cfa0ad2SJack F Vogel 	return ret_val;
3768cfa0ad2SJack F Vogel }
3778cfa0ad2SJack F Vogel 
3788cfa0ad2SJack F Vogel /**
3798cfa0ad2SJack F Vogel  *  e1000_release_nvm_80003es2lan - Relinquish rights to access NVM
3808cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3818cfa0ad2SJack F Vogel  *
382daf9197cSJack F Vogel  *  Release the semaphore used to access the EEPROM.
3838cfa0ad2SJack F Vogel  **/
e1000_release_nvm_80003es2lan(struct e1000_hw * hw)3848cfa0ad2SJack F Vogel static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw)
3858cfa0ad2SJack F Vogel {
3868cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_release_nvm_80003es2lan");
3878cfa0ad2SJack F Vogel 
3888cfa0ad2SJack F Vogel 	e1000_release_nvm_generic(hw);
389d5210708SMatt Macy 	e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
3908cfa0ad2SJack F Vogel }
3918cfa0ad2SJack F Vogel 
3928cfa0ad2SJack F Vogel /**
3938cfa0ad2SJack F Vogel  *  e1000_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register
3948cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3958cfa0ad2SJack F Vogel  *  @offset: offset of the register to read
3968cfa0ad2SJack F Vogel  *  @data: pointer to the data returned from the operation
3978cfa0ad2SJack F Vogel  *
398daf9197cSJack F Vogel  *  Read the GG82563 PHY register.
3998cfa0ad2SJack F Vogel  **/
e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw * hw,u32 offset,u16 * data)4008cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
4018cfa0ad2SJack F Vogel 						  u32 offset, u16 *data)
4028cfa0ad2SJack F Vogel {
4038cfa0ad2SJack F Vogel 	s32 ret_val;
4048cfa0ad2SJack F Vogel 	u32 page_select;
4058cfa0ad2SJack F Vogel 	u16 temp;
4068cfa0ad2SJack F Vogel 
4078cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_read_phy_reg_gg82563_80003es2lan");
4088cfa0ad2SJack F Vogel 
4098cfa0ad2SJack F Vogel 	ret_val = e1000_acquire_phy_80003es2lan(hw);
4108cfa0ad2SJack F Vogel 	if (ret_val)
4117609433eSJack F Vogel 		return ret_val;
4128cfa0ad2SJack F Vogel 
4138cfa0ad2SJack F Vogel 	/* Select Configuration Page */
4148cfa0ad2SJack F Vogel 	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
4158cfa0ad2SJack F Vogel 		page_select = GG82563_PHY_PAGE_SELECT;
4168cfa0ad2SJack F Vogel 	} else {
4177609433eSJack F Vogel 		/* Use Alternative Page Select register to access
4188cfa0ad2SJack F Vogel 		 * registers 30 and 31
4198cfa0ad2SJack F Vogel 		 */
4208cfa0ad2SJack F Vogel 		page_select = GG82563_PHY_PAGE_SELECT_ALT;
4218cfa0ad2SJack F Vogel 	}
4228cfa0ad2SJack F Vogel 
4238cfa0ad2SJack F Vogel 	temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
4248cfa0ad2SJack F Vogel 	ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
4258cfa0ad2SJack F Vogel 	if (ret_val) {
4268cfa0ad2SJack F Vogel 		e1000_release_phy_80003es2lan(hw);
4277609433eSJack F Vogel 		return ret_val;
4288cfa0ad2SJack F Vogel 	}
4298cfa0ad2SJack F Vogel 
4307609433eSJack F Vogel 	if (hw->dev_spec._80003es2lan.mdic_wa_enable) {
4317609433eSJack F Vogel 		/* The "ready" bit in the MDIC register may be incorrectly set
4328cfa0ad2SJack F Vogel 		 * before the device has completed the "Page Select" MDI
4338cfa0ad2SJack F Vogel 		 * transaction.  So we wait 200us after each MDI command...
4348cfa0ad2SJack F Vogel 		 */
4358cfa0ad2SJack F Vogel 		usec_delay(200);
4368cfa0ad2SJack F Vogel 
4378cfa0ad2SJack F Vogel 		/* ...and verify the command was successful. */
4388cfa0ad2SJack F Vogel 		ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
4398cfa0ad2SJack F Vogel 
4408cfa0ad2SJack F Vogel 		if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
4418cfa0ad2SJack F Vogel 			e1000_release_phy_80003es2lan(hw);
4427609433eSJack F Vogel 			return -E1000_ERR_PHY;
4438cfa0ad2SJack F Vogel 		}
4448cfa0ad2SJack F Vogel 
4458cfa0ad2SJack F Vogel 		usec_delay(200);
4468cfa0ad2SJack F Vogel 
4474edd8523SJack F Vogel 		ret_val = e1000_read_phy_reg_mdic(hw,
4484edd8523SJack F Vogel 						  MAX_PHY_REG_ADDRESS & offset,
4498cfa0ad2SJack F Vogel 						  data);
4508cfa0ad2SJack F Vogel 
4518cfa0ad2SJack F Vogel 		usec_delay(200);
4524edd8523SJack F Vogel 	} else {
4534edd8523SJack F Vogel 		ret_val = e1000_read_phy_reg_mdic(hw,
4544edd8523SJack F Vogel 						  MAX_PHY_REG_ADDRESS & offset,
4554edd8523SJack F Vogel 						  data);
4564edd8523SJack F Vogel 	}
4574edd8523SJack F Vogel 
4588cfa0ad2SJack F Vogel 	e1000_release_phy_80003es2lan(hw);
4598cfa0ad2SJack F Vogel 
4608cfa0ad2SJack F Vogel 	return ret_val;
4618cfa0ad2SJack F Vogel }
4628cfa0ad2SJack F Vogel 
4638cfa0ad2SJack F Vogel /**
4648cfa0ad2SJack F Vogel  *  e1000_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register
4658cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
4668cfa0ad2SJack F Vogel  *  @offset: offset of the register to read
4678cfa0ad2SJack F Vogel  *  @data: value to write to the register
4688cfa0ad2SJack F Vogel  *
469daf9197cSJack F Vogel  *  Write to the GG82563 PHY register.
4708cfa0ad2SJack F Vogel  **/
e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw * hw,u32 offset,u16 data)4718cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
4728cfa0ad2SJack F Vogel 						   u32 offset, u16 data)
4738cfa0ad2SJack F Vogel {
4748cfa0ad2SJack F Vogel 	s32 ret_val;
4758cfa0ad2SJack F Vogel 	u32 page_select;
4768cfa0ad2SJack F Vogel 	u16 temp;
4778cfa0ad2SJack F Vogel 
4788cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_write_phy_reg_gg82563_80003es2lan");
4798cfa0ad2SJack F Vogel 
4808cfa0ad2SJack F Vogel 	ret_val = e1000_acquire_phy_80003es2lan(hw);
4818cfa0ad2SJack F Vogel 	if (ret_val)
4827609433eSJack F Vogel 		return ret_val;
4838cfa0ad2SJack F Vogel 
4848cfa0ad2SJack F Vogel 	/* Select Configuration Page */
4858cfa0ad2SJack F Vogel 	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
4868cfa0ad2SJack F Vogel 		page_select = GG82563_PHY_PAGE_SELECT;
4878cfa0ad2SJack F Vogel 	} else {
4887609433eSJack F Vogel 		/* Use Alternative Page Select register to access
4898cfa0ad2SJack F Vogel 		 * registers 30 and 31
4908cfa0ad2SJack F Vogel 		 */
4918cfa0ad2SJack F Vogel 		page_select = GG82563_PHY_PAGE_SELECT_ALT;
4928cfa0ad2SJack F Vogel 	}
4938cfa0ad2SJack F Vogel 
4948cfa0ad2SJack F Vogel 	temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
4958cfa0ad2SJack F Vogel 	ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
4968cfa0ad2SJack F Vogel 	if (ret_val) {
4978cfa0ad2SJack F Vogel 		e1000_release_phy_80003es2lan(hw);
4987609433eSJack F Vogel 		return ret_val;
4998cfa0ad2SJack F Vogel 	}
5008cfa0ad2SJack F Vogel 
5017609433eSJack F Vogel 	if (hw->dev_spec._80003es2lan.mdic_wa_enable) {
5027609433eSJack F Vogel 		/* The "ready" bit in the MDIC register may be incorrectly set
5038cfa0ad2SJack F Vogel 		 * before the device has completed the "Page Select" MDI
5048cfa0ad2SJack F Vogel 		 * transaction.  So we wait 200us after each MDI command...
5058cfa0ad2SJack F Vogel 		 */
5068cfa0ad2SJack F Vogel 		usec_delay(200);
5078cfa0ad2SJack F Vogel 
5088cfa0ad2SJack F Vogel 		/* ...and verify the command was successful. */
5098cfa0ad2SJack F Vogel 		ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
5108cfa0ad2SJack F Vogel 
5118cfa0ad2SJack F Vogel 		if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
5128cfa0ad2SJack F Vogel 			e1000_release_phy_80003es2lan(hw);
5137609433eSJack F Vogel 			return -E1000_ERR_PHY;
5148cfa0ad2SJack F Vogel 		}
5158cfa0ad2SJack F Vogel 
5168cfa0ad2SJack F Vogel 		usec_delay(200);
5178cfa0ad2SJack F Vogel 
5184edd8523SJack F Vogel 		ret_val = e1000_write_phy_reg_mdic(hw,
5194edd8523SJack F Vogel 						  MAX_PHY_REG_ADDRESS & offset,
5208cfa0ad2SJack F Vogel 						  data);
5218cfa0ad2SJack F Vogel 
5228cfa0ad2SJack F Vogel 		usec_delay(200);
5234edd8523SJack F Vogel 	} else {
5244edd8523SJack F Vogel 		ret_val = e1000_write_phy_reg_mdic(hw,
5254edd8523SJack F Vogel 						  MAX_PHY_REG_ADDRESS & offset,
5264edd8523SJack F Vogel 						  data);
5274edd8523SJack F Vogel 	}
5284edd8523SJack F Vogel 
5298cfa0ad2SJack F Vogel 	e1000_release_phy_80003es2lan(hw);
5308cfa0ad2SJack F Vogel 
5318cfa0ad2SJack F Vogel 	return ret_val;
5328cfa0ad2SJack F Vogel }
5338cfa0ad2SJack F Vogel 
5348cfa0ad2SJack F Vogel /**
5358cfa0ad2SJack F Vogel  *  e1000_write_nvm_80003es2lan - Write to ESB2 NVM
5368cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5378cfa0ad2SJack F Vogel  *  @offset: offset of the register to read
5388cfa0ad2SJack F Vogel  *  @words: number of words to write
5398cfa0ad2SJack F Vogel  *  @data: buffer of data to write to the NVM
5408cfa0ad2SJack F Vogel  *
541daf9197cSJack F Vogel  *  Write "words" of data to the ESB2 NVM.
5428cfa0ad2SJack F Vogel  **/
e1000_write_nvm_80003es2lan(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)5438cfa0ad2SJack F Vogel static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
5448cfa0ad2SJack F Vogel 				       u16 words, u16 *data)
5458cfa0ad2SJack F Vogel {
5468cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_write_nvm_80003es2lan");
5478cfa0ad2SJack F Vogel 
5488cfa0ad2SJack F Vogel 	return e1000_write_nvm_spi(hw, offset, words, data);
5498cfa0ad2SJack F Vogel }
5508cfa0ad2SJack F Vogel 
5518cfa0ad2SJack F Vogel /**
5528cfa0ad2SJack F Vogel  *  e1000_get_cfg_done_80003es2lan - Wait for configuration to complete
5538cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5548cfa0ad2SJack F Vogel  *
5558cfa0ad2SJack F Vogel  *  Wait a specific amount of time for manageability processes to complete.
5568cfa0ad2SJack F Vogel  *  This is a function pointer entry point called by the phy module.
5578cfa0ad2SJack F Vogel  **/
e1000_get_cfg_done_80003es2lan(struct e1000_hw * hw)5588cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw)
5598cfa0ad2SJack F Vogel {
5608cfa0ad2SJack F Vogel 	s32 timeout = PHY_CFG_TIMEOUT;
5618cfa0ad2SJack F Vogel 	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
5628cfa0ad2SJack F Vogel 
5638cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_cfg_done_80003es2lan");
5648cfa0ad2SJack F Vogel 
5658cfa0ad2SJack F Vogel 	if (hw->bus.func == 1)
5668cfa0ad2SJack F Vogel 		mask = E1000_NVM_CFG_DONE_PORT_1;
5678cfa0ad2SJack F Vogel 
5688cfa0ad2SJack F Vogel 	while (timeout) {
5698cfa0ad2SJack F Vogel 		if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask)
5708cfa0ad2SJack F Vogel 			break;
5718cfa0ad2SJack F Vogel 		msec_delay(1);
5728cfa0ad2SJack F Vogel 		timeout--;
5738cfa0ad2SJack F Vogel 	}
5748cfa0ad2SJack F Vogel 	if (!timeout) {
5758cfa0ad2SJack F Vogel 		DEBUGOUT("MNG configuration cycle has not completed.\n");
5767609433eSJack F Vogel 		return -E1000_ERR_RESET;
5778cfa0ad2SJack F Vogel 	}
5788cfa0ad2SJack F Vogel 
5797609433eSJack F Vogel 	return E1000_SUCCESS;
5808cfa0ad2SJack F Vogel }
5818cfa0ad2SJack F Vogel 
5828cfa0ad2SJack F Vogel /**
5838cfa0ad2SJack F Vogel  *  e1000_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex
5848cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5858cfa0ad2SJack F Vogel  *
5868cfa0ad2SJack F Vogel  *  Force the speed and duplex settings onto the PHY.  This is a
5878cfa0ad2SJack F Vogel  *  function pointer entry point called by the phy module.
5888cfa0ad2SJack F Vogel  **/
e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw * hw)5898cfa0ad2SJack F Vogel static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
5908cfa0ad2SJack F Vogel {
5917609433eSJack F Vogel 	s32 ret_val;
5928cfa0ad2SJack F Vogel 	u16 phy_data;
5938cfa0ad2SJack F Vogel 	bool link;
5948cfa0ad2SJack F Vogel 
5958cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_phy_force_speed_duplex_80003es2lan");
5968cfa0ad2SJack F Vogel 
5978cfa0ad2SJack F Vogel 	if (!(hw->phy.ops.read_reg))
5987609433eSJack F Vogel 		return E1000_SUCCESS;
5998cfa0ad2SJack F Vogel 
6007609433eSJack F Vogel 	/* Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
6018cfa0ad2SJack F Vogel 	 * forced whenever speed and duplex are forced.
6028cfa0ad2SJack F Vogel 	 */
6038cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
6048cfa0ad2SJack F Vogel 	if (ret_val)
6057609433eSJack F Vogel 		return ret_val;
6068cfa0ad2SJack F Vogel 
6078cfa0ad2SJack F Vogel 	phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO;
6088cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
6098cfa0ad2SJack F Vogel 	if (ret_val)
6107609433eSJack F Vogel 		return ret_val;
6118cfa0ad2SJack F Vogel 
6128cfa0ad2SJack F Vogel 	DEBUGOUT1("GG82563 PSCR: %X\n", phy_data);
6138cfa0ad2SJack F Vogel 
6148cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_data);
6158cfa0ad2SJack F Vogel 	if (ret_val)
6167609433eSJack F Vogel 		return ret_val;
6178cfa0ad2SJack F Vogel 
6188cfa0ad2SJack F Vogel 	e1000_phy_force_speed_duplex_setup(hw, &phy_data);
6198cfa0ad2SJack F Vogel 
6208cfa0ad2SJack F Vogel 	/* Reset the phy to commit changes. */
6218cfa0ad2SJack F Vogel 	phy_data |= MII_CR_RESET;
6228cfa0ad2SJack F Vogel 
6238cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_data);
6248cfa0ad2SJack F Vogel 	if (ret_val)
6257609433eSJack F Vogel 		return ret_val;
6268cfa0ad2SJack F Vogel 
6278cfa0ad2SJack F Vogel 	usec_delay(1);
6288cfa0ad2SJack F Vogel 
6298cfa0ad2SJack F Vogel 	if (hw->phy.autoneg_wait_to_complete) {
6304dab5c37SJack F Vogel 		DEBUGOUT("Waiting for forced speed/duplex link on GG82563 phy.\n");
6318cfa0ad2SJack F Vogel 
6328cfa0ad2SJack F Vogel 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
6338cfa0ad2SJack F Vogel 						     100000, &link);
6348cfa0ad2SJack F Vogel 		if (ret_val)
6357609433eSJack F Vogel 			return ret_val;
6368cfa0ad2SJack F Vogel 
6378cfa0ad2SJack F Vogel 		if (!link) {
6387609433eSJack F Vogel 			/* We didn't get link.
6398cfa0ad2SJack F Vogel 			 * Reset the DSP and cross our fingers.
6408cfa0ad2SJack F Vogel 			 */
6418cfa0ad2SJack F Vogel 			ret_val = e1000_phy_reset_dsp_generic(hw);
6428cfa0ad2SJack F Vogel 			if (ret_val)
6437609433eSJack F Vogel 				return ret_val;
6448cfa0ad2SJack F Vogel 		}
6458cfa0ad2SJack F Vogel 
6468cfa0ad2SJack F Vogel 		/* Try once more */
6478cfa0ad2SJack F Vogel 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
6488cfa0ad2SJack F Vogel 						     100000, &link);
6498cfa0ad2SJack F Vogel 		if (ret_val)
6507609433eSJack F Vogel 			return ret_val;
6518cfa0ad2SJack F Vogel 	}
6528cfa0ad2SJack F Vogel 
6534dab5c37SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
6544dab5c37SJack F Vogel 				       &phy_data);
6558cfa0ad2SJack F Vogel 	if (ret_val)
6567609433eSJack F Vogel 		return ret_val;
6578cfa0ad2SJack F Vogel 
6587609433eSJack F Vogel 	/* Resetting the phy means we need to verify the TX_CLK corresponds
6598cfa0ad2SJack F Vogel 	 * to the link speed.  10Mbps -> 2.5MHz, else 25MHz.
6608cfa0ad2SJack F Vogel 	 */
6618cfa0ad2SJack F Vogel 	phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
6628cfa0ad2SJack F Vogel 	if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED)
6638cfa0ad2SJack F Vogel 		phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5;
6648cfa0ad2SJack F Vogel 	else
6658cfa0ad2SJack F Vogel 		phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
6668cfa0ad2SJack F Vogel 
6677609433eSJack F Vogel 	/* In addition, we must re-enable CRS on Tx for both half and full
6688cfa0ad2SJack F Vogel 	 * duplex.
6698cfa0ad2SJack F Vogel 	 */
6708cfa0ad2SJack F Vogel 	phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
6714dab5c37SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
6724dab5c37SJack F Vogel 					phy_data);
6738cfa0ad2SJack F Vogel 
6748cfa0ad2SJack F Vogel 	return ret_val;
6758cfa0ad2SJack F Vogel }
6768cfa0ad2SJack F Vogel 
6778cfa0ad2SJack F Vogel /**
6788cfa0ad2SJack F Vogel  *  e1000_get_cable_length_80003es2lan - Set approximate cable length
6798cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
6808cfa0ad2SJack F Vogel  *
6818cfa0ad2SJack F Vogel  *  Find the approximate cable length as measured by the GG82563 PHY.
6828cfa0ad2SJack F Vogel  *  This is a function pointer entry point called by the phy module.
6838cfa0ad2SJack F Vogel  **/
e1000_get_cable_length_80003es2lan(struct e1000_hw * hw)6848cfa0ad2SJack F Vogel static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
6858cfa0ad2SJack F Vogel {
6868cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
6877609433eSJack F Vogel 	s32 ret_val;
6888cfa0ad2SJack F Vogel 	u16 phy_data, index;
6898cfa0ad2SJack F Vogel 
6908cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_cable_length_80003es2lan");
6918cfa0ad2SJack F Vogel 
6928cfa0ad2SJack F Vogel 	if (!(hw->phy.ops.read_reg))
6937609433eSJack F Vogel 		return E1000_SUCCESS;
6948cfa0ad2SJack F Vogel 
6958cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
6968cfa0ad2SJack F Vogel 	if (ret_val)
6977609433eSJack F Vogel 		return ret_val;
6988cfa0ad2SJack F Vogel 
6998cfa0ad2SJack F Vogel 	index = phy_data & GG82563_DSPD_CABLE_LENGTH;
7008cfa0ad2SJack F Vogel 
7017609433eSJack F Vogel 	if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5)
7027609433eSJack F Vogel 		return -E1000_ERR_PHY;
7038cfa0ad2SJack F Vogel 
704d035aa2dSJack F Vogel 	phy->min_cable_length = e1000_gg82563_cable_length_table[index];
705d035aa2dSJack F Vogel 	phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5];
706d035aa2dSJack F Vogel 
707d035aa2dSJack F Vogel 	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
708d035aa2dSJack F Vogel 
7097609433eSJack F Vogel 	return E1000_SUCCESS;
7108cfa0ad2SJack F Vogel }
7118cfa0ad2SJack F Vogel 
7128cfa0ad2SJack F Vogel /**
7138cfa0ad2SJack F Vogel  *  e1000_get_link_up_info_80003es2lan - Report speed and duplex
7148cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
7158cfa0ad2SJack F Vogel  *  @speed: pointer to speed buffer
7168cfa0ad2SJack F Vogel  *  @duplex: pointer to duplex buffer
7178cfa0ad2SJack F Vogel  *
7188cfa0ad2SJack F Vogel  *  Retrieve the current speed and duplex configuration.
7198cfa0ad2SJack F Vogel  **/
e1000_get_link_up_info_80003es2lan(struct e1000_hw * hw,u16 * speed,u16 * duplex)7208cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
7218cfa0ad2SJack F Vogel 					      u16 *duplex)
7228cfa0ad2SJack F Vogel {
7238cfa0ad2SJack F Vogel 	s32 ret_val;
7248cfa0ad2SJack F Vogel 
7258cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_link_up_info_80003es2lan");
7268cfa0ad2SJack F Vogel 
7278cfa0ad2SJack F Vogel 	if (hw->phy.media_type == e1000_media_type_copper) {
7284dab5c37SJack F Vogel 		ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
7298cfa0ad2SJack F Vogel 								    duplex);
730daf9197cSJack F Vogel 		hw->phy.ops.cfg_on_link_up(hw);
7318cfa0ad2SJack F Vogel 	} else {
7328cfa0ad2SJack F Vogel 		ret_val = e1000_get_speed_and_duplex_fiber_serdes_generic(hw,
7338cfa0ad2SJack F Vogel 								  speed,
7348cfa0ad2SJack F Vogel 								  duplex);
7358cfa0ad2SJack F Vogel 	}
7368cfa0ad2SJack F Vogel 
7378cfa0ad2SJack F Vogel 	return ret_val;
7388cfa0ad2SJack F Vogel }
7398cfa0ad2SJack F Vogel 
7408cfa0ad2SJack F Vogel /**
7418cfa0ad2SJack F Vogel  *  e1000_reset_hw_80003es2lan - Reset the ESB2 controller
7428cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
7438cfa0ad2SJack F Vogel  *
7448cfa0ad2SJack F Vogel  *  Perform a global reset to the ESB2 controller.
7458cfa0ad2SJack F Vogel  **/
e1000_reset_hw_80003es2lan(struct e1000_hw * hw)7468cfa0ad2SJack F Vogel static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
7478cfa0ad2SJack F Vogel {
748730d3130SJack F Vogel 	u32 ctrl;
7498cfa0ad2SJack F Vogel 	s32 ret_val;
7507609433eSJack F Vogel 	u16 kum_reg_data;
7518cfa0ad2SJack F Vogel 
7528cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_reset_hw_80003es2lan");
7538cfa0ad2SJack F Vogel 
7547609433eSJack F Vogel 	/* Prevent the PCI-E bus from sticking if there is no TLP connection
7558cfa0ad2SJack F Vogel 	 * on the last TLP read/write transaction when MAC is reset.
7568cfa0ad2SJack F Vogel 	 */
7578cfa0ad2SJack F Vogel 	ret_val = e1000_disable_pcie_master_generic(hw);
758daf9197cSJack F Vogel 	if (ret_val)
7598cfa0ad2SJack F Vogel 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
7608cfa0ad2SJack F Vogel 
7618cfa0ad2SJack F Vogel 	DEBUGOUT("Masking off all interrupts\n");
7628cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
7638cfa0ad2SJack F Vogel 
7648cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
7658cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
7668cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
7678cfa0ad2SJack F Vogel 
7688cfa0ad2SJack F Vogel 	msec_delay(10);
7698cfa0ad2SJack F Vogel 
7708cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
7718cfa0ad2SJack F Vogel 
772daf9197cSJack F Vogel 	ret_val = e1000_acquire_phy_80003es2lan(hw);
7737609433eSJack F Vogel 	if (ret_val)
7747609433eSJack F Vogel 		return ret_val;
7757609433eSJack F Vogel 
7768cfa0ad2SJack F Vogel 	DEBUGOUT("Issuing a global reset to MAC\n");
7778cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
778daf9197cSJack F Vogel 	e1000_release_phy_80003es2lan(hw);
7798cfa0ad2SJack F Vogel 
7807609433eSJack F Vogel 	/* Disable IBIST slave mode (far-end loopback) */
781c80429ceSEric Joyner 	ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
782c80429ceSEric Joyner 				E1000_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data);
783c80429ceSEric Joyner 	if (!ret_val) {
7847609433eSJack F Vogel 		kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
785c80429ceSEric Joyner 		ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
786c80429ceSEric Joyner 						 E1000_KMRNCTRLSTA_INBAND_PARAM,
7877609433eSJack F Vogel 						 kum_reg_data);
788c80429ceSEric Joyner 		if (ret_val)
789c80429ceSEric Joyner 			DEBUGOUT("Error disabling far-end loopback\n");
790c80429ceSEric Joyner 	} else
791c80429ceSEric Joyner 		DEBUGOUT("Error disabling far-end loopback\n");
7927609433eSJack F Vogel 
7938cfa0ad2SJack F Vogel 	ret_val = e1000_get_auto_rd_done_generic(hw);
7948cfa0ad2SJack F Vogel 	if (ret_val)
7958cfa0ad2SJack F Vogel 		/* We don't want to continue accessing MAC registers. */
7967609433eSJack F Vogel 		return ret_val;
7978cfa0ad2SJack F Vogel 
7988cfa0ad2SJack F Vogel 	/* Clear any pending interrupt events. */
7998cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
800730d3130SJack F Vogel 	E1000_READ_REG(hw, E1000_ICR);
8018cfa0ad2SJack F Vogel 
8027609433eSJack F Vogel 	return e1000_check_alt_mac_addr_generic(hw);
8038cfa0ad2SJack F Vogel }
8048cfa0ad2SJack F Vogel 
8058cfa0ad2SJack F Vogel /**
8068cfa0ad2SJack F Vogel  *  e1000_init_hw_80003es2lan - Initialize the ESB2 controller
8078cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
8088cfa0ad2SJack F Vogel  *
8098cfa0ad2SJack F Vogel  *  Initialize the hw bits, LED, VFTA, MTA, link and hw counters.
8108cfa0ad2SJack F Vogel  **/
e1000_init_hw_80003es2lan(struct e1000_hw * hw)8118cfa0ad2SJack F Vogel static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
8128cfa0ad2SJack F Vogel {
8138cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
8148cfa0ad2SJack F Vogel 	u32 reg_data;
8158cfa0ad2SJack F Vogel 	s32 ret_val;
816730d3130SJack F Vogel 	u16 kum_reg_data;
8178cfa0ad2SJack F Vogel 	u16 i;
8188cfa0ad2SJack F Vogel 
8198cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_hw_80003es2lan");
8208cfa0ad2SJack F Vogel 
8218cfa0ad2SJack F Vogel 	e1000_initialize_hw_bits_80003es2lan(hw);
8228cfa0ad2SJack F Vogel 
8238cfa0ad2SJack F Vogel 	/* Initialize identification LED */
824d035aa2dSJack F Vogel 	ret_val = mac->ops.id_led_init(hw);
8257609433eSJack F Vogel 	/* An error is not fatal and we should not stop init due to this */
8264edd8523SJack F Vogel 	if (ret_val)
8278cfa0ad2SJack F Vogel 		DEBUGOUT("Error initializing identification LED\n");
8288cfa0ad2SJack F Vogel 
8298cfa0ad2SJack F Vogel 	/* Disabling VLAN filtering */
8308cfa0ad2SJack F Vogel 	DEBUGOUT("Initializing the IEEE VLAN\n");
8318cfa0ad2SJack F Vogel 	mac->ops.clear_vfta(hw);
8328cfa0ad2SJack F Vogel 
8338cfa0ad2SJack F Vogel 	/* Setup the receive address. */
8348cfa0ad2SJack F Vogel 	e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
8358cfa0ad2SJack F Vogel 
8368cfa0ad2SJack F Vogel 	/* Zero out the Multicast HASH table */
8378cfa0ad2SJack F Vogel 	DEBUGOUT("Zeroing the MTA\n");
8388cfa0ad2SJack F Vogel 	for (i = 0; i < mac->mta_reg_count; i++)
8398cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
8408cfa0ad2SJack F Vogel 
8418cfa0ad2SJack F Vogel 	/* Setup link and flow control */
8428cfa0ad2SJack F Vogel 	ret_val = mac->ops.setup_link(hw);
8437609433eSJack F Vogel 	if (ret_val)
8447609433eSJack F Vogel 		return ret_val;
8458cfa0ad2SJack F Vogel 
846730d3130SJack F Vogel 	/* Disable IBIST slave mode (far-end loopback) */
847c80429ceSEric Joyner 	ret_val =
848730d3130SJack F Vogel 	    e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
849730d3130SJack F Vogel 					    &kum_reg_data);
850c80429ceSEric Joyner 	if (!ret_val) {
851730d3130SJack F Vogel 		kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
852c80429ceSEric Joyner 		ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
853c80429ceSEric Joyner 						 E1000_KMRNCTRLSTA_INBAND_PARAM,
854730d3130SJack F Vogel 						 kum_reg_data);
855c80429ceSEric Joyner 		if (ret_val)
856c80429ceSEric Joyner 			DEBUGOUT("Error disabling far-end loopback\n");
857c80429ceSEric Joyner 	} else
858c80429ceSEric Joyner 		DEBUGOUT("Error disabling far-end loopback\n");
859730d3130SJack F Vogel 
8608cfa0ad2SJack F Vogel 	/* Set the transmit descriptor write-back policy */
8618cfa0ad2SJack F Vogel 	reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
8627609433eSJack F Vogel 	reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
8637609433eSJack F Vogel 		    E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
8648cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
8658cfa0ad2SJack F Vogel 
8668cfa0ad2SJack F Vogel 	/* ...for both queues. */
8678cfa0ad2SJack F Vogel 	reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
8687609433eSJack F Vogel 	reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
8697609433eSJack F Vogel 		    E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
8708cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
8718cfa0ad2SJack F Vogel 
8728cfa0ad2SJack F Vogel 	/* Enable retransmit on late collisions */
8738cfa0ad2SJack F Vogel 	reg_data = E1000_READ_REG(hw, E1000_TCTL);
8748cfa0ad2SJack F Vogel 	reg_data |= E1000_TCTL_RTLC;
8758cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL, reg_data);
8768cfa0ad2SJack F Vogel 
8778cfa0ad2SJack F Vogel 	/* Configure Gigabit Carry Extend Padding */
8788cfa0ad2SJack F Vogel 	reg_data = E1000_READ_REG(hw, E1000_TCTL_EXT);
8798cfa0ad2SJack F Vogel 	reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
8808cfa0ad2SJack F Vogel 	reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN;
8818cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL_EXT, reg_data);
8828cfa0ad2SJack F Vogel 
8838cfa0ad2SJack F Vogel 	/* Configure Transmit Inter-Packet Gap */
8848cfa0ad2SJack F Vogel 	reg_data = E1000_READ_REG(hw, E1000_TIPG);
8858cfa0ad2SJack F Vogel 	reg_data &= ~E1000_TIPG_IPGT_MASK;
8868cfa0ad2SJack F Vogel 	reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
8878cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TIPG, reg_data);
8888cfa0ad2SJack F Vogel 
8898cfa0ad2SJack F Vogel 	reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001);
8908cfa0ad2SJack F Vogel 	reg_data &= ~0x00100000;
8918cfa0ad2SJack F Vogel 	E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data);
8928cfa0ad2SJack F Vogel 
893*1bbdc25fSKevin Bowling 	/* default to true to enable the MDIC W/A */
894*1bbdc25fSKevin Bowling 	hw->dev_spec._80003es2lan.mdic_wa_enable = true;
8954edd8523SJack F Vogel 
8967609433eSJack F Vogel 	ret_val =
8977609433eSJack F Vogel 	    e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET >>
8987609433eSJack F Vogel 					    E1000_KMRNCTRLSTA_OFFSET_SHIFT, &i);
8994edd8523SJack F Vogel 	if (!ret_val) {
9004edd8523SJack F Vogel 		if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) ==
9014edd8523SJack F Vogel 		     E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
902*1bbdc25fSKevin Bowling 			hw->dev_spec._80003es2lan.mdic_wa_enable = false;
9034edd8523SJack F Vogel 	}
9044edd8523SJack F Vogel 
9057609433eSJack F Vogel 	/* Clear all of the statistics registers (clear on read).  It is
9068cfa0ad2SJack F Vogel 	 * important that we do this after we have tried to establish link
9078cfa0ad2SJack F Vogel 	 * because the symbol error count will increment wildly if there
9088cfa0ad2SJack F Vogel 	 * is no link.
9098cfa0ad2SJack F Vogel 	 */
9108cfa0ad2SJack F Vogel 	e1000_clear_hw_cntrs_80003es2lan(hw);
9118cfa0ad2SJack F Vogel 
9128cfa0ad2SJack F Vogel 	return ret_val;
9138cfa0ad2SJack F Vogel }
9148cfa0ad2SJack F Vogel 
9158cfa0ad2SJack F Vogel /**
9168cfa0ad2SJack F Vogel  *  e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2
9178cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
9188cfa0ad2SJack F Vogel  *
9198cfa0ad2SJack F Vogel  *  Initializes required hardware-dependent bits needed for normal operation.
9208cfa0ad2SJack F Vogel  **/
e1000_initialize_hw_bits_80003es2lan(struct e1000_hw * hw)9218cfa0ad2SJack F Vogel static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
9228cfa0ad2SJack F Vogel {
9238cfa0ad2SJack F Vogel 	u32 reg;
9248cfa0ad2SJack F Vogel 
9258cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_initialize_hw_bits_80003es2lan");
9268cfa0ad2SJack F Vogel 
9278cfa0ad2SJack F Vogel 	/* Transmit Descriptor Control 0 */
9288cfa0ad2SJack F Vogel 	reg = E1000_READ_REG(hw, E1000_TXDCTL(0));
9298cfa0ad2SJack F Vogel 	reg |= (1 << 22);
9308cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg);
9318cfa0ad2SJack F Vogel 
9328cfa0ad2SJack F Vogel 	/* Transmit Descriptor Control 1 */
9338cfa0ad2SJack F Vogel 	reg = E1000_READ_REG(hw, E1000_TXDCTL(1));
9348cfa0ad2SJack F Vogel 	reg |= (1 << 22);
9358cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg);
9368cfa0ad2SJack F Vogel 
9378cfa0ad2SJack F Vogel 	/* Transmit Arbitration Control 0 */
9388cfa0ad2SJack F Vogel 	reg = E1000_READ_REG(hw, E1000_TARC(0));
9398cfa0ad2SJack F Vogel 	reg &= ~(0xF << 27); /* 30:27 */
9408cfa0ad2SJack F Vogel 	if (hw->phy.media_type != e1000_media_type_copper)
9418cfa0ad2SJack F Vogel 		reg &= ~(1 << 20);
9428cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TARC(0), reg);
9438cfa0ad2SJack F Vogel 
9448cfa0ad2SJack F Vogel 	/* Transmit Arbitration Control 1 */
9458cfa0ad2SJack F Vogel 	reg = E1000_READ_REG(hw, E1000_TARC(1));
9468cfa0ad2SJack F Vogel 	if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR)
9478cfa0ad2SJack F Vogel 		reg &= ~(1 << 28);
9488cfa0ad2SJack F Vogel 	else
9498cfa0ad2SJack F Vogel 		reg |= (1 << 28);
9508cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TARC(1), reg);
9518cfa0ad2SJack F Vogel 
9527609433eSJack F Vogel 	/* Disable IPv6 extension header parsing because some malformed
9537609433eSJack F Vogel 	 * IPv6 headers can hang the Rx.
9547609433eSJack F Vogel 	 */
9557609433eSJack F Vogel 	reg = E1000_READ_REG(hw, E1000_RFCTL);
9567609433eSJack F Vogel 	reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
9577609433eSJack F Vogel 	E1000_WRITE_REG(hw, E1000_RFCTL, reg);
9587609433eSJack F Vogel 
9598cfa0ad2SJack F Vogel 	return;
9608cfa0ad2SJack F Vogel }
9618cfa0ad2SJack F Vogel 
9628cfa0ad2SJack F Vogel /**
9638cfa0ad2SJack F Vogel  *  e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link
9648cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
9658cfa0ad2SJack F Vogel  *
9668cfa0ad2SJack F Vogel  *  Setup some GG82563 PHY registers for obtaining link
9678cfa0ad2SJack F Vogel  **/
e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw * hw)9688cfa0ad2SJack F Vogel static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
9698cfa0ad2SJack F Vogel {
9708cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
9718cfa0ad2SJack F Vogel 	s32 ret_val;
9727609433eSJack F Vogel 	u32 reg;
973daf9197cSJack F Vogel 	u16 data;
9748cfa0ad2SJack F Vogel 
9758cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan");
9768cfa0ad2SJack F Vogel 
9774dab5c37SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
9788cfa0ad2SJack F Vogel 	if (ret_val)
9797609433eSJack F Vogel 		return ret_val;
9808cfa0ad2SJack F Vogel 
9818cfa0ad2SJack F Vogel 	data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
9828cfa0ad2SJack F Vogel 	/* Use 25MHz for both link down and 1000Base-T for Tx clock. */
9838cfa0ad2SJack F Vogel 	data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
9848cfa0ad2SJack F Vogel 
9854dab5c37SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
9868cfa0ad2SJack F Vogel 	if (ret_val)
9877609433eSJack F Vogel 		return ret_val;
9888cfa0ad2SJack F Vogel 
9897609433eSJack F Vogel 	/* Options:
9908cfa0ad2SJack F Vogel 	 *   MDI/MDI-X = 0 (default)
9918cfa0ad2SJack F Vogel 	 *   0 - Auto for all speeds
9928cfa0ad2SJack F Vogel 	 *   1 - MDI mode
9938cfa0ad2SJack F Vogel 	 *   2 - MDI-X mode
9948cfa0ad2SJack F Vogel 	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
9958cfa0ad2SJack F Vogel 	 */
9968cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL, &data);
9978cfa0ad2SJack F Vogel 	if (ret_val)
9987609433eSJack F Vogel 		return ret_val;
9998cfa0ad2SJack F Vogel 
10008cfa0ad2SJack F Vogel 	data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
10018cfa0ad2SJack F Vogel 
10028cfa0ad2SJack F Vogel 	switch (phy->mdix) {
10038cfa0ad2SJack F Vogel 	case 1:
10048cfa0ad2SJack F Vogel 		data |= GG82563_PSCR_CROSSOVER_MODE_MDI;
10058cfa0ad2SJack F Vogel 		break;
10068cfa0ad2SJack F Vogel 	case 2:
10078cfa0ad2SJack F Vogel 		data |= GG82563_PSCR_CROSSOVER_MODE_MDIX;
10088cfa0ad2SJack F Vogel 		break;
10098cfa0ad2SJack F Vogel 	case 0:
10108cfa0ad2SJack F Vogel 	default:
10118cfa0ad2SJack F Vogel 		data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
10128cfa0ad2SJack F Vogel 		break;
10138cfa0ad2SJack F Vogel 	}
10148cfa0ad2SJack F Vogel 
10157609433eSJack F Vogel 	/* Options:
10168cfa0ad2SJack F Vogel 	 *   disable_polarity_correction = 0 (default)
10178cfa0ad2SJack F Vogel 	 *       Automatic Correction for Reversed Cable Polarity
10188cfa0ad2SJack F Vogel 	 *   0 - Disabled
10198cfa0ad2SJack F Vogel 	 *   1 - Enabled
10208cfa0ad2SJack F Vogel 	 */
10218cfa0ad2SJack F Vogel 	data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
10228cfa0ad2SJack F Vogel 	if (phy->disable_polarity_correction)
10238cfa0ad2SJack F Vogel 		data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
10248cfa0ad2SJack F Vogel 
10258cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, data);
10268cfa0ad2SJack F Vogel 	if (ret_val)
10277609433eSJack F Vogel 		return ret_val;
10288cfa0ad2SJack F Vogel 
10298cfa0ad2SJack F Vogel 	/* SW Reset the PHY so all changes take effect */
10308cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.commit(hw);
10318cfa0ad2SJack F Vogel 	if (ret_val) {
10328cfa0ad2SJack F Vogel 		DEBUGOUT("Error Resetting the PHY\n");
10337609433eSJack F Vogel 		return ret_val;
10348cfa0ad2SJack F Vogel 	}
10358cfa0ad2SJack F Vogel 
10368cfa0ad2SJack F Vogel 	/* Bypass Rx and Tx FIFO's */
10377609433eSJack F Vogel 	reg = E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL;
10387609433eSJack F Vogel 	data = (E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
10398cfa0ad2SJack F Vogel 		E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
10407609433eSJack F Vogel 	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data);
10418cfa0ad2SJack F Vogel 	if (ret_val)
10427609433eSJack F Vogel 		return ret_val;
10438cfa0ad2SJack F Vogel 
10447609433eSJack F Vogel 	reg = E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE;
10457609433eSJack F Vogel 	ret_val = e1000_read_kmrn_reg_80003es2lan(hw, reg, &data);
10468cfa0ad2SJack F Vogel 	if (ret_val)
10477609433eSJack F Vogel 		return ret_val;
10488cfa0ad2SJack F Vogel 	data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
10497609433eSJack F Vogel 	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data);
10508cfa0ad2SJack F Vogel 	if (ret_val)
10517609433eSJack F Vogel 		return ret_val;
10528cfa0ad2SJack F Vogel 
10538cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data);
10548cfa0ad2SJack F Vogel 	if (ret_val)
10557609433eSJack F Vogel 		return ret_val;
10568cfa0ad2SJack F Vogel 
10578cfa0ad2SJack F Vogel 	data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
10588cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL_2, data);
10598cfa0ad2SJack F Vogel 	if (ret_val)
10607609433eSJack F Vogel 		return ret_val;
10618cfa0ad2SJack F Vogel 
10627609433eSJack F Vogel 	reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
10637609433eSJack F Vogel 	reg &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
10647609433eSJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
10658cfa0ad2SJack F Vogel 
10668cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data);
10678cfa0ad2SJack F Vogel 	if (ret_val)
10687609433eSJack F Vogel 		return ret_val;
10698cfa0ad2SJack F Vogel 
10707609433eSJack F Vogel 	/* Do not init these registers when the HW is in IAMT mode, since the
10718cfa0ad2SJack F Vogel 	 * firmware will have already initialized them.  We only initialize
10728cfa0ad2SJack F Vogel 	 * them if the HW is not in IAMT mode.
10738cfa0ad2SJack F Vogel 	 */
10747609433eSJack F Vogel 	if (!hw->mac.ops.check_mng_mode(hw)) {
10758cfa0ad2SJack F Vogel 		/* Enable Electrical Idle on the PHY */
10768cfa0ad2SJack F Vogel 		data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
1077d035aa2dSJack F Vogel 		ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
10788cfa0ad2SJack F Vogel 						data);
10798cfa0ad2SJack F Vogel 		if (ret_val)
10807609433eSJack F Vogel 			return ret_val;
1081d035aa2dSJack F Vogel 
1082d035aa2dSJack F Vogel 		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
10838cfa0ad2SJack F Vogel 					       &data);
10848cfa0ad2SJack F Vogel 		if (ret_val)
10857609433eSJack F Vogel 			return ret_val;
10868cfa0ad2SJack F Vogel 
10878cfa0ad2SJack F Vogel 		data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
1088d035aa2dSJack F Vogel 		ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
10898cfa0ad2SJack F Vogel 						data);
10908cfa0ad2SJack F Vogel 		if (ret_val)
10917609433eSJack F Vogel 			return ret_val;
10928cfa0ad2SJack F Vogel 	}
10938cfa0ad2SJack F Vogel 
10947609433eSJack F Vogel 	/* Workaround: Disable padding in Kumeran interface in the MAC
10958cfa0ad2SJack F Vogel 	 * and in the PHY to avoid CRC errors.
10968cfa0ad2SJack F Vogel 	 */
10978cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_INBAND_CTRL, &data);
10988cfa0ad2SJack F Vogel 	if (ret_val)
10997609433eSJack F Vogel 		return ret_val;
11008cfa0ad2SJack F Vogel 
11018cfa0ad2SJack F Vogel 	data |= GG82563_ICR_DIS_PADDING;
11028cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_INBAND_CTRL, data);
11038cfa0ad2SJack F Vogel 	if (ret_val)
11048cfa0ad2SJack F Vogel 		return ret_val;
11057609433eSJack F Vogel 
11067609433eSJack F Vogel 	return E1000_SUCCESS;
11078cfa0ad2SJack F Vogel }
11088cfa0ad2SJack F Vogel 
11098cfa0ad2SJack F Vogel /**
11108cfa0ad2SJack F Vogel  *  e1000_setup_copper_link_80003es2lan - Setup Copper Link for ESB2
11118cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
11128cfa0ad2SJack F Vogel  *
11138cfa0ad2SJack F Vogel  *  Essentially a wrapper for setting up all things "copper" related.
11148cfa0ad2SJack F Vogel  *  This is a function pointer entry point called by the mac module.
11158cfa0ad2SJack F Vogel  **/
e1000_setup_copper_link_80003es2lan(struct e1000_hw * hw)11168cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
11178cfa0ad2SJack F Vogel {
11188cfa0ad2SJack F Vogel 	u32 ctrl;
11198cfa0ad2SJack F Vogel 	s32 ret_val;
11208cfa0ad2SJack F Vogel 	u16 reg_data;
11218cfa0ad2SJack F Vogel 
11228cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_setup_copper_link_80003es2lan");
11238cfa0ad2SJack F Vogel 
11248cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
11258cfa0ad2SJack F Vogel 	ctrl |= E1000_CTRL_SLU;
11268cfa0ad2SJack F Vogel 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
11278cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
11288cfa0ad2SJack F Vogel 
11297609433eSJack F Vogel 	/* Set the mac to wait the maximum time between each
11308cfa0ad2SJack F Vogel 	 * iteration and increase the max iterations when
11318cfa0ad2SJack F Vogel 	 * polling the phy; this fixes erroneous timeouts at 10Mbps.
11328cfa0ad2SJack F Vogel 	 */
1133daf9197cSJack F Vogel 	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
11348cfa0ad2SJack F Vogel 						   0xFFFF);
11358cfa0ad2SJack F Vogel 	if (ret_val)
11367609433eSJack F Vogel 		return ret_val;
1137daf9197cSJack F Vogel 	ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
11388cfa0ad2SJack F Vogel 						  &reg_data);
11398cfa0ad2SJack F Vogel 	if (ret_val)
11407609433eSJack F Vogel 		return ret_val;
11418cfa0ad2SJack F Vogel 	reg_data |= 0x3F;
1142daf9197cSJack F Vogel 	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
11438cfa0ad2SJack F Vogel 						   reg_data);
11448cfa0ad2SJack F Vogel 	if (ret_val)
11457609433eSJack F Vogel 		return ret_val;
11467609433eSJack F Vogel 	ret_val =
11477609433eSJack F Vogel 	    e1000_read_kmrn_reg_80003es2lan(hw,
11487609433eSJack F Vogel 					    E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
11497609433eSJack F Vogel 					    &reg_data);
11508cfa0ad2SJack F Vogel 	if (ret_val)
11517609433eSJack F Vogel 		return ret_val;
11528cfa0ad2SJack F Vogel 	reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
11537609433eSJack F Vogel 	ret_val =
11547609433eSJack F Vogel 	    e1000_write_kmrn_reg_80003es2lan(hw,
11557609433eSJack F Vogel 					     E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
11567609433eSJack F Vogel 					     reg_data);
11578cfa0ad2SJack F Vogel 	if (ret_val)
11587609433eSJack F Vogel 		return ret_val;
11598cfa0ad2SJack F Vogel 
11608cfa0ad2SJack F Vogel 	ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw);
11618cfa0ad2SJack F Vogel 	if (ret_val)
11628cfa0ad2SJack F Vogel 		return ret_val;
11637609433eSJack F Vogel 
11647609433eSJack F Vogel 	return e1000_setup_copper_link_generic(hw);
11658cfa0ad2SJack F Vogel }
11668cfa0ad2SJack F Vogel 
11678cfa0ad2SJack F Vogel /**
1168daf9197cSJack F Vogel  *  e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up
1169daf9197cSJack F Vogel  *  @hw: pointer to the HW structure
1170daf9197cSJack F Vogel  *
1171daf9197cSJack F Vogel  *  Configure the KMRN interface by applying last minute quirks for
1172daf9197cSJack F Vogel  *  10/100 operation.
1173daf9197cSJack F Vogel  **/
e1000_cfg_on_link_up_80003es2lan(struct e1000_hw * hw)1174daf9197cSJack F Vogel static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
1175daf9197cSJack F Vogel {
1176daf9197cSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
1177daf9197cSJack F Vogel 	u16 speed;
1178daf9197cSJack F Vogel 	u16 duplex;
1179daf9197cSJack F Vogel 
1180daf9197cSJack F Vogel 	DEBUGFUNC("e1000_configure_on_link_up");
1181daf9197cSJack F Vogel 
1182daf9197cSJack F Vogel 	if (hw->phy.media_type == e1000_media_type_copper) {
11834dab5c37SJack F Vogel 		ret_val = e1000_get_speed_and_duplex_copper_generic(hw, &speed,
1184daf9197cSJack F Vogel 								    &duplex);
1185daf9197cSJack F Vogel 		if (ret_val)
11867609433eSJack F Vogel 			return ret_val;
1187daf9197cSJack F Vogel 
1188daf9197cSJack F Vogel 		if (speed == SPEED_1000)
1189daf9197cSJack F Vogel 			ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw);
1190daf9197cSJack F Vogel 		else
1191daf9197cSJack F Vogel 			ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex);
1192daf9197cSJack F Vogel 	}
1193daf9197cSJack F Vogel 
1194daf9197cSJack F Vogel 	return ret_val;
1195daf9197cSJack F Vogel }
1196daf9197cSJack F Vogel 
1197daf9197cSJack F Vogel /**
11988cfa0ad2SJack F Vogel  *  e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation
11998cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
12008cfa0ad2SJack F Vogel  *  @duplex: current duplex setting
12018cfa0ad2SJack F Vogel  *
12028cfa0ad2SJack F Vogel  *  Configure the KMRN interface by applying last minute quirks for
12038cfa0ad2SJack F Vogel  *  10/100 operation.
12048cfa0ad2SJack F Vogel  **/
e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw * hw,u16 duplex)12058cfa0ad2SJack F Vogel static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
12068cfa0ad2SJack F Vogel {
12077609433eSJack F Vogel 	s32 ret_val;
12088cfa0ad2SJack F Vogel 	u32 tipg;
12098cfa0ad2SJack F Vogel 	u32 i = 0;
12108cfa0ad2SJack F Vogel 	u16 reg_data, reg_data2;
12118cfa0ad2SJack F Vogel 
12128cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_configure_kmrn_for_10_100");
12138cfa0ad2SJack F Vogel 
12148cfa0ad2SJack F Vogel 	reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
12157609433eSJack F Vogel 	ret_val =
12167609433eSJack F Vogel 	    e1000_write_kmrn_reg_80003es2lan(hw,
12178cfa0ad2SJack F Vogel 					     E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
12188cfa0ad2SJack F Vogel 					     reg_data);
12198cfa0ad2SJack F Vogel 	if (ret_val)
12207609433eSJack F Vogel 		return ret_val;
12218cfa0ad2SJack F Vogel 
12228cfa0ad2SJack F Vogel 	/* Configure Transmit Inter-Packet Gap */
12238cfa0ad2SJack F Vogel 	tipg = E1000_READ_REG(hw, E1000_TIPG);
12248cfa0ad2SJack F Vogel 	tipg &= ~E1000_TIPG_IPGT_MASK;
12258cfa0ad2SJack F Vogel 	tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN;
12268cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TIPG, tipg);
12278cfa0ad2SJack F Vogel 
12288cfa0ad2SJack F Vogel 	do {
12298cfa0ad2SJack F Vogel 		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
12308cfa0ad2SJack F Vogel 					       &reg_data);
12318cfa0ad2SJack F Vogel 		if (ret_val)
12327609433eSJack F Vogel 			return ret_val;
12338cfa0ad2SJack F Vogel 
12348cfa0ad2SJack F Vogel 		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
12358cfa0ad2SJack F Vogel 					       &reg_data2);
12368cfa0ad2SJack F Vogel 		if (ret_val)
12377609433eSJack F Vogel 			return ret_val;
12388cfa0ad2SJack F Vogel 		i++;
12398cfa0ad2SJack F Vogel 	} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
12408cfa0ad2SJack F Vogel 
12418cfa0ad2SJack F Vogel 	if (duplex == HALF_DUPLEX)
12428cfa0ad2SJack F Vogel 		reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
12438cfa0ad2SJack F Vogel 	else
12448cfa0ad2SJack F Vogel 		reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
12458cfa0ad2SJack F Vogel 
12467609433eSJack F Vogel 	return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
12478cfa0ad2SJack F Vogel }
12488cfa0ad2SJack F Vogel 
12498cfa0ad2SJack F Vogel /**
12508cfa0ad2SJack F Vogel  *  e1000_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation
12518cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
12528cfa0ad2SJack F Vogel  *
12538cfa0ad2SJack F Vogel  *  Configure the KMRN interface by applying last minute quirks for
12548cfa0ad2SJack F Vogel  *  gigabit operation.
12558cfa0ad2SJack F Vogel  **/
e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw * hw)12568cfa0ad2SJack F Vogel static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
12578cfa0ad2SJack F Vogel {
12587609433eSJack F Vogel 	s32 ret_val;
12598cfa0ad2SJack F Vogel 	u16 reg_data, reg_data2;
12608cfa0ad2SJack F Vogel 	u32 tipg;
12618cfa0ad2SJack F Vogel 	u32 i = 0;
12628cfa0ad2SJack F Vogel 
12638cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_configure_kmrn_for_1000");
12648cfa0ad2SJack F Vogel 
12658cfa0ad2SJack F Vogel 	reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
12667609433eSJack F Vogel 	ret_val =
12677609433eSJack F Vogel 	    e1000_write_kmrn_reg_80003es2lan(hw,
12687609433eSJack F Vogel 					     E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
12697609433eSJack F Vogel 					     reg_data);
12708cfa0ad2SJack F Vogel 	if (ret_val)
12717609433eSJack F Vogel 		return ret_val;
12728cfa0ad2SJack F Vogel 
12738cfa0ad2SJack F Vogel 	/* Configure Transmit Inter-Packet Gap */
12748cfa0ad2SJack F Vogel 	tipg = E1000_READ_REG(hw, E1000_TIPG);
12758cfa0ad2SJack F Vogel 	tipg &= ~E1000_TIPG_IPGT_MASK;
12768cfa0ad2SJack F Vogel 	tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
12778cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TIPG, tipg);
12788cfa0ad2SJack F Vogel 
12798cfa0ad2SJack F Vogel 	do {
12808cfa0ad2SJack F Vogel 		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
12818cfa0ad2SJack F Vogel 					       &reg_data);
12828cfa0ad2SJack F Vogel 		if (ret_val)
12837609433eSJack F Vogel 			return ret_val;
12848cfa0ad2SJack F Vogel 
12858cfa0ad2SJack F Vogel 		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
12868cfa0ad2SJack F Vogel 					       &reg_data2);
12878cfa0ad2SJack F Vogel 		if (ret_val)
12887609433eSJack F Vogel 			return ret_val;
12898cfa0ad2SJack F Vogel 		i++;
12908cfa0ad2SJack F Vogel 	} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
12918cfa0ad2SJack F Vogel 
12928cfa0ad2SJack F Vogel 	reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
12938cfa0ad2SJack F Vogel 
12947609433eSJack F Vogel 	return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
12958cfa0ad2SJack F Vogel }
12968cfa0ad2SJack F Vogel 
12978cfa0ad2SJack F Vogel /**
1298daf9197cSJack F Vogel  *  e1000_read_kmrn_reg_80003es2lan - Read kumeran register
1299daf9197cSJack F Vogel  *  @hw: pointer to the HW structure
1300daf9197cSJack F Vogel  *  @offset: register offset to be read
1301daf9197cSJack F Vogel  *  @data: pointer to the read data
1302daf9197cSJack F Vogel  *
1303daf9197cSJack F Vogel  *  Acquire semaphore, then read the PHY register at offset
1304daf9197cSJack F Vogel  *  using the kumeran interface.  The information retrieved is stored in data.
1305daf9197cSJack F Vogel  *  Release the semaphore before exiting.
1306daf9197cSJack F Vogel  **/
e1000_read_kmrn_reg_80003es2lan(struct e1000_hw * hw,u32 offset,u16 * data)1307d035aa2dSJack F Vogel static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
1308d035aa2dSJack F Vogel 					   u16 *data)
1309daf9197cSJack F Vogel {
1310daf9197cSJack F Vogel 	u32 kmrnctrlsta;
13117609433eSJack F Vogel 	s32 ret_val;
1312daf9197cSJack F Vogel 
1313daf9197cSJack F Vogel 	DEBUGFUNC("e1000_read_kmrn_reg_80003es2lan");
1314daf9197cSJack F Vogel 
1315daf9197cSJack F Vogel 	ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
1316daf9197cSJack F Vogel 	if (ret_val)
13177609433eSJack F Vogel 		return ret_val;
1318daf9197cSJack F Vogel 
1319daf9197cSJack F Vogel 	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
1320daf9197cSJack F Vogel 		       E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
1321daf9197cSJack F Vogel 	E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
13224dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
1323daf9197cSJack F Vogel 
1324daf9197cSJack F Vogel 	usec_delay(2);
1325daf9197cSJack F Vogel 
1326daf9197cSJack F Vogel 	kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA);
1327daf9197cSJack F Vogel 	*data = (u16)kmrnctrlsta;
1328daf9197cSJack F Vogel 
1329daf9197cSJack F Vogel 	e1000_release_mac_csr_80003es2lan(hw);
1330daf9197cSJack F Vogel 
1331daf9197cSJack F Vogel 	return ret_val;
1332daf9197cSJack F Vogel }
1333daf9197cSJack F Vogel 
1334daf9197cSJack F Vogel /**
1335daf9197cSJack F Vogel  *  e1000_write_kmrn_reg_80003es2lan - Write kumeran register
1336daf9197cSJack F Vogel  *  @hw: pointer to the HW structure
1337daf9197cSJack F Vogel  *  @offset: register offset to write to
1338daf9197cSJack F Vogel  *  @data: data to write at register offset
1339daf9197cSJack F Vogel  *
1340daf9197cSJack F Vogel  *  Acquire semaphore, then write the data to PHY register
1341daf9197cSJack F Vogel  *  at the offset using the kumeran interface.  Release semaphore
1342daf9197cSJack F Vogel  *  before exiting.
1343daf9197cSJack F Vogel  **/
e1000_write_kmrn_reg_80003es2lan(struct e1000_hw * hw,u32 offset,u16 data)1344d035aa2dSJack F Vogel static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
1345d035aa2dSJack F Vogel 					    u16 data)
1346daf9197cSJack F Vogel {
1347daf9197cSJack F Vogel 	u32 kmrnctrlsta;
13487609433eSJack F Vogel 	s32 ret_val;
1349daf9197cSJack F Vogel 
1350daf9197cSJack F Vogel 	DEBUGFUNC("e1000_write_kmrn_reg_80003es2lan");
1351daf9197cSJack F Vogel 
1352daf9197cSJack F Vogel 	ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
1353daf9197cSJack F Vogel 	if (ret_val)
13547609433eSJack F Vogel 		return ret_val;
1355daf9197cSJack F Vogel 
1356daf9197cSJack F Vogel 	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
1357daf9197cSJack F Vogel 		       E1000_KMRNCTRLSTA_OFFSET) | data;
1358daf9197cSJack F Vogel 	E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
13594dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
1360daf9197cSJack F Vogel 
1361daf9197cSJack F Vogel 	usec_delay(2);
1362daf9197cSJack F Vogel 
1363daf9197cSJack F Vogel 	e1000_release_mac_csr_80003es2lan(hw);
1364daf9197cSJack F Vogel 
1365daf9197cSJack F Vogel 	return ret_val;
1366daf9197cSJack F Vogel }
1367daf9197cSJack F Vogel 
1368daf9197cSJack F Vogel /**
13698cfa0ad2SJack F Vogel  *  e1000_read_mac_addr_80003es2lan - Read device MAC address
13708cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
13718cfa0ad2SJack F Vogel  **/
e1000_read_mac_addr_80003es2lan(struct e1000_hw * hw)13728cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
13738cfa0ad2SJack F Vogel {
13747609433eSJack F Vogel 	s32 ret_val;
13758cfa0ad2SJack F Vogel 
13768cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_read_mac_addr_80003es2lan");
1377d035aa2dSJack F Vogel 
13787609433eSJack F Vogel 	/* If there's an alternate MAC address place it in RAR0
1379d035aa2dSJack F Vogel 	 * so that it will override the Si installed default perm
1380d035aa2dSJack F Vogel 	 * address.
1381d035aa2dSJack F Vogel 	 */
1382d035aa2dSJack F Vogel 	ret_val = e1000_check_alt_mac_addr_generic(hw);
1383d035aa2dSJack F Vogel 	if (ret_val)
13848cfa0ad2SJack F Vogel 		return ret_val;
13857609433eSJack F Vogel 
13867609433eSJack F Vogel 	return e1000_read_mac_addr_generic(hw);
13878cfa0ad2SJack F Vogel }
13888cfa0ad2SJack F Vogel 
13898cfa0ad2SJack F Vogel /**
13908cfa0ad2SJack F Vogel  * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down
13918cfa0ad2SJack F Vogel  * @hw: pointer to the HW structure
13928cfa0ad2SJack F Vogel  *
13938cfa0ad2SJack F Vogel  * In the case of a PHY power down to save power, or to turn off link during a
13948cfa0ad2SJack F Vogel  * driver unload, or wake on lan is not enabled, remove the link.
13958cfa0ad2SJack F Vogel  **/
e1000_power_down_phy_copper_80003es2lan(struct e1000_hw * hw)13968cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw)
13978cfa0ad2SJack F Vogel {
13988cfa0ad2SJack F Vogel 	/* If the management interface is not enabled, then power down */
13998cfa0ad2SJack F Vogel 	if (!(hw->mac.ops.check_mng_mode(hw) ||
14008cfa0ad2SJack F Vogel 	      hw->phy.ops.check_reset_block(hw)))
14018cfa0ad2SJack F Vogel 		e1000_power_down_phy_copper(hw);
14028cfa0ad2SJack F Vogel 
14038cfa0ad2SJack F Vogel 	return;
14048cfa0ad2SJack F Vogel }
14058cfa0ad2SJack F Vogel 
14068cfa0ad2SJack F Vogel /**
14078cfa0ad2SJack F Vogel  *  e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters
14088cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
14098cfa0ad2SJack F Vogel  *
14108cfa0ad2SJack F Vogel  *  Clears the hardware counters by reading the counter registers.
14118cfa0ad2SJack F Vogel  **/
e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw * hw)14128cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw)
14138cfa0ad2SJack F Vogel {
14148cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_clear_hw_cntrs_80003es2lan");
14158cfa0ad2SJack F Vogel 
14168cfa0ad2SJack F Vogel 	e1000_clear_hw_cntrs_base_generic(hw);
14178cfa0ad2SJack F Vogel 
1418daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC64);
1419daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC127);
1420daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC255);
1421daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC511);
1422daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC1023);
1423daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC1522);
1424daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC64);
1425daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC127);
1426daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC255);
1427daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC511);
1428daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC1023);
1429daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC1522);
14308cfa0ad2SJack F Vogel 
1431daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ALGNERRC);
1432daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_RXERRC);
1433daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TNCRS);
1434daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_CEXTERR);
1435daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TSCTC);
1436daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TSCTFC);
14378cfa0ad2SJack F Vogel 
1438daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPRC);
1439daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPDC);
1440daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPTC);
14418cfa0ad2SJack F Vogel 
1442daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_IAC);
1443daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXOC);
14448cfa0ad2SJack F Vogel 
1445daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXPTC);
1446daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXATC);
1447daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXPTC);
1448daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXATC);
1449daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXQEC);
1450daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXQMTC);
1451daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXDMTC);
14528cfa0ad2SJack F Vogel }
1453