xref: /freebsd/sys/dev/e1000/e1000_82543.c (revision 7282444b103e0b3e7c8cd053413ff6c068831cc6)
18cfa0ad2SJack F Vogel /******************************************************************************
2*7282444bSPedro F. Giffuni   SPDX-License-Identifier: BSD-3-Clause
38cfa0ad2SJack F Vogel 
47c669ab6SSean Bruno   Copyright (c) 2001-2015, 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 /*$FreeBSD$*/
358cfa0ad2SJack F Vogel 
36daf9197cSJack F Vogel /*
37daf9197cSJack F Vogel  * 82543GC Gigabit Ethernet Controller (Fiber)
38daf9197cSJack F Vogel  * 82543GC Gigabit Ethernet Controller (Copper)
39daf9197cSJack F Vogel  * 82544EI Gigabit Ethernet Controller (Copper)
40daf9197cSJack F Vogel  * 82544EI Gigabit Ethernet Controller (Fiber)
41daf9197cSJack F Vogel  * 82544GC Gigabit Ethernet Controller (Copper)
42daf9197cSJack F Vogel  * 82544GC Gigabit Ethernet Controller (LOM)
438cfa0ad2SJack F Vogel  */
448cfa0ad2SJack F Vogel 
458cfa0ad2SJack F Vogel #include "e1000_api.h"
468cfa0ad2SJack F Vogel 
478cfa0ad2SJack F Vogel static s32  e1000_init_phy_params_82543(struct e1000_hw *hw);
488cfa0ad2SJack F Vogel static s32  e1000_init_nvm_params_82543(struct e1000_hw *hw);
498cfa0ad2SJack F Vogel static s32  e1000_init_mac_params_82543(struct e1000_hw *hw);
508cfa0ad2SJack F Vogel static s32  e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset,
518cfa0ad2SJack F Vogel 				     u16 *data);
528cfa0ad2SJack F Vogel static s32  e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset,
538cfa0ad2SJack F Vogel 				      u16 data);
548cfa0ad2SJack F Vogel static s32  e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw);
558cfa0ad2SJack F Vogel static s32  e1000_phy_hw_reset_82543(struct e1000_hw *hw);
568cfa0ad2SJack F Vogel static s32  e1000_reset_hw_82543(struct e1000_hw *hw);
578cfa0ad2SJack F Vogel static s32  e1000_init_hw_82543(struct e1000_hw *hw);
588cfa0ad2SJack F Vogel static s32  e1000_setup_link_82543(struct e1000_hw *hw);
598cfa0ad2SJack F Vogel static s32  e1000_setup_copper_link_82543(struct e1000_hw *hw);
608cfa0ad2SJack F Vogel static s32  e1000_setup_fiber_link_82543(struct e1000_hw *hw);
618cfa0ad2SJack F Vogel static s32  e1000_check_for_copper_link_82543(struct e1000_hw *hw);
628cfa0ad2SJack F Vogel static s32  e1000_check_for_fiber_link_82543(struct e1000_hw *hw);
638cfa0ad2SJack F Vogel static s32  e1000_led_on_82543(struct e1000_hw *hw);
648cfa0ad2SJack F Vogel static s32  e1000_led_off_82543(struct e1000_hw *hw);
658cfa0ad2SJack F Vogel static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset,
668cfa0ad2SJack F Vogel 				   u32 value);
678cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw);
688cfa0ad2SJack F Vogel static s32  e1000_config_mac_to_phy_82543(struct e1000_hw *hw);
698cfa0ad2SJack F Vogel static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw);
708cfa0ad2SJack F Vogel static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
718cfa0ad2SJack F Vogel static s32  e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw);
728cfa0ad2SJack F Vogel static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
738cfa0ad2SJack F Vogel static u16  e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw);
748cfa0ad2SJack F Vogel static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
758cfa0ad2SJack F Vogel 					   u16 count);
768cfa0ad2SJack F Vogel static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw);
778cfa0ad2SJack F Vogel static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state);
7874dbc418SJack F Vogel static s32  e1000_read_mac_addr_82543(struct e1000_hw *hw);
7974dbc418SJack F Vogel 
808cfa0ad2SJack F Vogel 
818cfa0ad2SJack F Vogel /**
828cfa0ad2SJack F Vogel  *  e1000_init_phy_params_82543 - Init PHY func ptrs.
838cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
848cfa0ad2SJack F Vogel  **/
858cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82543(struct e1000_hw *hw)
868cfa0ad2SJack F Vogel {
878cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
888cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
898cfa0ad2SJack F Vogel 
908cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_phy_params_82543");
918cfa0ad2SJack F Vogel 
928cfa0ad2SJack F Vogel 	if (hw->phy.media_type != e1000_media_type_copper) {
938cfa0ad2SJack F Vogel 		phy->type = e1000_phy_none;
948cfa0ad2SJack F Vogel 		goto out;
958cfa0ad2SJack F Vogel 	} else {
968cfa0ad2SJack F Vogel 		phy->ops.power_up = e1000_power_up_phy_copper;
978cfa0ad2SJack F Vogel 		phy->ops.power_down = e1000_power_down_phy_copper;
988cfa0ad2SJack F Vogel 	}
998cfa0ad2SJack F Vogel 
1008cfa0ad2SJack F Vogel 	phy->addr		= 1;
1018cfa0ad2SJack F Vogel 	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
1028cfa0ad2SJack F Vogel 	phy->reset_delay_us	= 10000;
1038cfa0ad2SJack F Vogel 	phy->type		= e1000_phy_m88;
1048cfa0ad2SJack F Vogel 
1058cfa0ad2SJack F Vogel 	/* Function Pointers */
1068cfa0ad2SJack F Vogel 	phy->ops.check_polarity	= e1000_check_polarity_m88;
1078cfa0ad2SJack F Vogel 	phy->ops.commit		= e1000_phy_sw_reset_generic;
1088cfa0ad2SJack F Vogel 	phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82543;
1098cfa0ad2SJack F Vogel 	phy->ops.get_cable_length = e1000_get_cable_length_m88;
1108cfa0ad2SJack F Vogel 	phy->ops.get_cfg_done	= e1000_get_cfg_done_generic;
1118cfa0ad2SJack F Vogel 	phy->ops.read_reg	= (hw->mac.type == e1000_82543)
1128cfa0ad2SJack F Vogel 				  ? e1000_read_phy_reg_82543
1138cfa0ad2SJack F Vogel 				  : e1000_read_phy_reg_m88;
1148cfa0ad2SJack F Vogel 	phy->ops.reset		= (hw->mac.type == e1000_82543)
1158cfa0ad2SJack F Vogel 				  ? e1000_phy_hw_reset_82543
1168cfa0ad2SJack F Vogel 				  : e1000_phy_hw_reset_generic;
1178cfa0ad2SJack F Vogel 	phy->ops.write_reg	= (hw->mac.type == e1000_82543)
1188cfa0ad2SJack F Vogel 				  ? e1000_write_phy_reg_82543
1198cfa0ad2SJack F Vogel 				  : e1000_write_phy_reg_m88;
1208cfa0ad2SJack F Vogel 	phy->ops.get_info	= e1000_get_phy_info_m88;
1218cfa0ad2SJack F Vogel 
1228cfa0ad2SJack F Vogel 	/*
1238cfa0ad2SJack F Vogel 	 * The external PHY of the 82543 can be in a funky state.
1248cfa0ad2SJack F Vogel 	 * Resetting helps us read the PHY registers for acquiring
1258cfa0ad2SJack F Vogel 	 * the PHY ID.
1268cfa0ad2SJack F Vogel 	 */
1278cfa0ad2SJack F Vogel 	if (!e1000_init_phy_disabled_82543(hw)) {
1288cfa0ad2SJack F Vogel 		ret_val = phy->ops.reset(hw);
1298cfa0ad2SJack F Vogel 		if (ret_val) {
1308cfa0ad2SJack F Vogel 			DEBUGOUT("Resetting PHY during init failed.\n");
1318cfa0ad2SJack F Vogel 			goto out;
1328cfa0ad2SJack F Vogel 		}
1338cfa0ad2SJack F Vogel 		msec_delay(20);
1348cfa0ad2SJack F Vogel 	}
1358cfa0ad2SJack F Vogel 
1368cfa0ad2SJack F Vogel 	ret_val = e1000_get_phy_id(hw);
1378cfa0ad2SJack F Vogel 	if (ret_val)
1388cfa0ad2SJack F Vogel 		goto out;
1398cfa0ad2SJack F Vogel 
1408cfa0ad2SJack F Vogel 	/* Verify phy id */
1418cfa0ad2SJack F Vogel 	switch (hw->mac.type) {
1428cfa0ad2SJack F Vogel 	case e1000_82543:
1438cfa0ad2SJack F Vogel 		if (phy->id != M88E1000_E_PHY_ID) {
1448cfa0ad2SJack F Vogel 			ret_val = -E1000_ERR_PHY;
1458cfa0ad2SJack F Vogel 			goto out;
1468cfa0ad2SJack F Vogel 		}
1478cfa0ad2SJack F Vogel 		break;
1488cfa0ad2SJack F Vogel 	case e1000_82544:
1498cfa0ad2SJack F Vogel 		if (phy->id != M88E1000_I_PHY_ID) {
1508cfa0ad2SJack F Vogel 			ret_val = -E1000_ERR_PHY;
1518cfa0ad2SJack F Vogel 			goto out;
1528cfa0ad2SJack F Vogel 		}
1538cfa0ad2SJack F Vogel 		break;
1548cfa0ad2SJack F Vogel 	default:
1558cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PHY;
1568cfa0ad2SJack F Vogel 		goto out;
1578cfa0ad2SJack F Vogel 		break;
1588cfa0ad2SJack F Vogel 	}
1598cfa0ad2SJack F Vogel 
1608cfa0ad2SJack F Vogel out:
1618cfa0ad2SJack F Vogel 	return ret_val;
1628cfa0ad2SJack F Vogel }
1638cfa0ad2SJack F Vogel 
1648cfa0ad2SJack F Vogel /**
1658cfa0ad2SJack F Vogel  *  e1000_init_nvm_params_82543 - Init NVM func ptrs.
1668cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
1678cfa0ad2SJack F Vogel  **/
1688cfa0ad2SJack F Vogel static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw)
1698cfa0ad2SJack F Vogel {
1708cfa0ad2SJack F Vogel 	struct e1000_nvm_info *nvm = &hw->nvm;
1718cfa0ad2SJack F Vogel 
1728cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_nvm_params_82543");
1738cfa0ad2SJack F Vogel 
1748cfa0ad2SJack F Vogel 	nvm->type		= e1000_nvm_eeprom_microwire;
1758cfa0ad2SJack F Vogel 	nvm->word_size		= 64;
1768cfa0ad2SJack F Vogel 	nvm->delay_usec		= 50;
1778cfa0ad2SJack F Vogel 	nvm->address_bits	=  6;
1788cfa0ad2SJack F Vogel 	nvm->opcode_bits	=  3;
1798cfa0ad2SJack F Vogel 
1808cfa0ad2SJack F Vogel 	/* Function Pointers */
1818cfa0ad2SJack F Vogel 	nvm->ops.read		= e1000_read_nvm_microwire;
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_microwire;
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_82543 - Init MAC func ptrs.
1928cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
1938cfa0ad2SJack F Vogel  **/
1948cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82543(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_82543");
1998cfa0ad2SJack F Vogel 
2008cfa0ad2SJack F Vogel 	/* Set media type */
2018cfa0ad2SJack F Vogel 	switch (hw->device_id) {
2028cfa0ad2SJack F Vogel 	case E1000_DEV_ID_82543GC_FIBER:
2038cfa0ad2SJack F Vogel 	case E1000_DEV_ID_82544EI_FIBER:
2048cfa0ad2SJack F Vogel 		hw->phy.media_type = e1000_media_type_fiber;
2058cfa0ad2SJack F Vogel 		break;
2068cfa0ad2SJack F Vogel 	default:
2078cfa0ad2SJack F Vogel 		hw->phy.media_type = e1000_media_type_copper;
2088cfa0ad2SJack F Vogel 		break;
2098cfa0ad2SJack F Vogel 	}
2108cfa0ad2SJack F Vogel 
2118cfa0ad2SJack F Vogel 	/* Set mta register count */
2128cfa0ad2SJack F Vogel 	mac->mta_reg_count = 128;
2138cfa0ad2SJack F Vogel 	/* Set rar entry count */
2148cfa0ad2SJack F Vogel 	mac->rar_entry_count = E1000_RAR_ENTRIES;
2158cfa0ad2SJack F Vogel 
2168cfa0ad2SJack F Vogel 	/* Function pointers */
2178cfa0ad2SJack F Vogel 
2188cfa0ad2SJack F Vogel 	/* bus type/speed/width */
2198cfa0ad2SJack F Vogel 	mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
220daf9197cSJack F Vogel 	/* function id */
221daf9197cSJack F Vogel 	mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
2228cfa0ad2SJack F Vogel 	/* reset */
2238cfa0ad2SJack F Vogel 	mac->ops.reset_hw = e1000_reset_hw_82543;
2248cfa0ad2SJack F Vogel 	/* hw initialization */
2258cfa0ad2SJack F Vogel 	mac->ops.init_hw = e1000_init_hw_82543;
2268cfa0ad2SJack F Vogel 	/* link setup */
2278cfa0ad2SJack F Vogel 	mac->ops.setup_link = e1000_setup_link_82543;
2288cfa0ad2SJack F Vogel 	/* physical interface setup */
2298cfa0ad2SJack F Vogel 	mac->ops.setup_physical_interface =
2308cfa0ad2SJack F Vogel 		(hw->phy.media_type == e1000_media_type_copper)
23148600901SSean Bruno 		 ? e1000_setup_copper_link_82543 : e1000_setup_fiber_link_82543;
2328cfa0ad2SJack F Vogel 	/* check for link */
2338cfa0ad2SJack F Vogel 	mac->ops.check_for_link =
2348cfa0ad2SJack F Vogel 		(hw->phy.media_type == e1000_media_type_copper)
2358cfa0ad2SJack F Vogel 		 ? e1000_check_for_copper_link_82543
2368cfa0ad2SJack F Vogel 		 : e1000_check_for_fiber_link_82543;
2378cfa0ad2SJack F Vogel 	/* link info */
2388cfa0ad2SJack F Vogel 	mac->ops.get_link_up_info =
2398cfa0ad2SJack F Vogel 		(hw->phy.media_type == e1000_media_type_copper)
2408cfa0ad2SJack F Vogel 		 ? e1000_get_speed_and_duplex_copper_generic
2418cfa0ad2SJack F Vogel 		 : e1000_get_speed_and_duplex_fiber_serdes_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_82543;
2468cfa0ad2SJack F Vogel 	/* clearing VFTA */
2478cfa0ad2SJack F Vogel 	mac->ops.clear_vfta = e1000_clear_vfta_generic;
24874dbc418SJack F Vogel 	/* read mac address */
24974dbc418SJack F Vogel 	mac->ops.read_mac_addr = e1000_read_mac_addr_82543;
2508cfa0ad2SJack F Vogel 	/* turn on/off LED */
2518cfa0ad2SJack F Vogel 	mac->ops.led_on = e1000_led_on_82543;
2528cfa0ad2SJack F Vogel 	mac->ops.led_off = e1000_led_off_82543;
2538cfa0ad2SJack F Vogel 	/* clear hardware counters */
2548cfa0ad2SJack F Vogel 	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82543;
2558cfa0ad2SJack F Vogel 
2568cfa0ad2SJack F Vogel 	/* Set tbi compatibility */
2578cfa0ad2SJack F Vogel 	if ((hw->mac.type != e1000_82543) ||
2588cfa0ad2SJack F Vogel 	    (hw->phy.media_type == e1000_media_type_fiber))
2598cfa0ad2SJack F Vogel 		e1000_set_tbi_compatibility_82543(hw, FALSE);
2608cfa0ad2SJack F Vogel 
261daf9197cSJack F Vogel 	return E1000_SUCCESS;
2628cfa0ad2SJack F Vogel }
2638cfa0ad2SJack F Vogel 
2648cfa0ad2SJack F Vogel /**
2658cfa0ad2SJack F Vogel  *  e1000_init_function_pointers_82543 - Init func ptrs.
2668cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
2678cfa0ad2SJack F Vogel  *
268daf9197cSJack F Vogel  *  Called to initialize all function pointers and parameters.
2698cfa0ad2SJack F Vogel  **/
2708cfa0ad2SJack F Vogel void e1000_init_function_pointers_82543(struct e1000_hw *hw)
2718cfa0ad2SJack F Vogel {
2728cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_function_pointers_82543");
2738cfa0ad2SJack F Vogel 
2748cfa0ad2SJack F Vogel 	hw->mac.ops.init_params = e1000_init_mac_params_82543;
2758cfa0ad2SJack F Vogel 	hw->nvm.ops.init_params = e1000_init_nvm_params_82543;
2768cfa0ad2SJack F Vogel 	hw->phy.ops.init_params = e1000_init_phy_params_82543;
2778cfa0ad2SJack F Vogel }
2788cfa0ad2SJack F Vogel 
2798cfa0ad2SJack F Vogel /**
2808cfa0ad2SJack F Vogel  *  e1000_tbi_compatibility_enabled_82543 - Returns TBI compat status
2818cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
2828cfa0ad2SJack F Vogel  *
2838cfa0ad2SJack F Vogel  *  Returns the current status of 10-bit Interface (TBI) compatibility
2848cfa0ad2SJack F Vogel  *  (enabled/disabled).
2858cfa0ad2SJack F Vogel  **/
2868cfa0ad2SJack F Vogel static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw)
2878cfa0ad2SJack F Vogel {
288daf9197cSJack F Vogel 	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
2898cfa0ad2SJack F Vogel 	bool state = FALSE;
2908cfa0ad2SJack F Vogel 
2918cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_tbi_compatibility_enabled_82543");
2928cfa0ad2SJack F Vogel 
2938cfa0ad2SJack F Vogel 	if (hw->mac.type != e1000_82543) {
2948cfa0ad2SJack F Vogel 		DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
2958cfa0ad2SJack F Vogel 		goto out;
2968cfa0ad2SJack F Vogel 	}
2978cfa0ad2SJack F Vogel 
29848600901SSean Bruno 	state = !!(dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED);
2998cfa0ad2SJack F Vogel 
3008cfa0ad2SJack F Vogel out:
3018cfa0ad2SJack F Vogel 	return state;
3028cfa0ad2SJack F Vogel }
3038cfa0ad2SJack F Vogel 
3048cfa0ad2SJack F Vogel /**
3058cfa0ad2SJack F Vogel  *  e1000_set_tbi_compatibility_82543 - Set TBI compatibility
3068cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3078cfa0ad2SJack F Vogel  *  @state: enable/disable TBI compatibility
3088cfa0ad2SJack F Vogel  *
3098cfa0ad2SJack F Vogel  *  Enables or disabled 10-bit Interface (TBI) compatibility.
3108cfa0ad2SJack F Vogel  **/
3118cfa0ad2SJack F Vogel void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state)
3128cfa0ad2SJack F Vogel {
313daf9197cSJack F Vogel 	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
3148cfa0ad2SJack F Vogel 
3158cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_set_tbi_compatibility_82543");
3168cfa0ad2SJack F Vogel 
3178cfa0ad2SJack F Vogel 	if (hw->mac.type != e1000_82543) {
3188cfa0ad2SJack F Vogel 		DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
3198cfa0ad2SJack F Vogel 		goto out;
3208cfa0ad2SJack F Vogel 	}
3218cfa0ad2SJack F Vogel 
3228cfa0ad2SJack F Vogel 	if (state)
3238cfa0ad2SJack F Vogel 		dev_spec->tbi_compatibility |= TBI_COMPAT_ENABLED;
3248cfa0ad2SJack F Vogel 	else
3258cfa0ad2SJack F Vogel 		dev_spec->tbi_compatibility &= ~TBI_COMPAT_ENABLED;
3268cfa0ad2SJack F Vogel 
3278cfa0ad2SJack F Vogel out:
3288cfa0ad2SJack F Vogel 	return;
3298cfa0ad2SJack F Vogel }
3308cfa0ad2SJack F Vogel 
3318cfa0ad2SJack F Vogel /**
3328cfa0ad2SJack F Vogel  *  e1000_tbi_sbp_enabled_82543 - Returns TBI SBP status
3338cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3348cfa0ad2SJack F Vogel  *
3358cfa0ad2SJack F Vogel  *  Returns the current status of 10-bit Interface (TBI) store bad packet (SBP)
3368cfa0ad2SJack F Vogel  *  (enabled/disabled).
3378cfa0ad2SJack F Vogel  **/
3388cfa0ad2SJack F Vogel bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw)
3398cfa0ad2SJack F Vogel {
340daf9197cSJack F Vogel 	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
3418cfa0ad2SJack F Vogel 	bool state = FALSE;
3428cfa0ad2SJack F Vogel 
3438cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_tbi_sbp_enabled_82543");
3448cfa0ad2SJack F Vogel 
3458cfa0ad2SJack F Vogel 	if (hw->mac.type != e1000_82543) {
3468cfa0ad2SJack F Vogel 		DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
3478cfa0ad2SJack F Vogel 		goto out;
3488cfa0ad2SJack F Vogel 	}
3498cfa0ad2SJack F Vogel 
35048600901SSean Bruno 	state = !!(dev_spec->tbi_compatibility & TBI_SBP_ENABLED);
3518cfa0ad2SJack F Vogel 
3528cfa0ad2SJack F Vogel out:
3538cfa0ad2SJack F Vogel 	return state;
3548cfa0ad2SJack F Vogel }
3558cfa0ad2SJack F Vogel 
3568cfa0ad2SJack F Vogel /**
3578cfa0ad2SJack F Vogel  *  e1000_set_tbi_sbp_82543 - Set TBI SBP
3588cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3598cfa0ad2SJack F Vogel  *  @state: enable/disable TBI store bad packet
3608cfa0ad2SJack F Vogel  *
3618cfa0ad2SJack F Vogel  *  Enables or disabled 10-bit Interface (TBI) store bad packet (SBP).
3628cfa0ad2SJack F Vogel  **/
3638cfa0ad2SJack F Vogel static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state)
3648cfa0ad2SJack F Vogel {
365daf9197cSJack F Vogel 	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
3668cfa0ad2SJack F Vogel 
3678cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_set_tbi_sbp_82543");
3688cfa0ad2SJack F Vogel 
3698cfa0ad2SJack F Vogel 	if (state && e1000_tbi_compatibility_enabled_82543(hw))
3708cfa0ad2SJack F Vogel 		dev_spec->tbi_compatibility |= TBI_SBP_ENABLED;
3718cfa0ad2SJack F Vogel 	else
3728cfa0ad2SJack F Vogel 		dev_spec->tbi_compatibility &= ~TBI_SBP_ENABLED;
3738cfa0ad2SJack F Vogel 
3748cfa0ad2SJack F Vogel 	return;
3758cfa0ad2SJack F Vogel }
3768cfa0ad2SJack F Vogel 
3778cfa0ad2SJack F Vogel /**
3788cfa0ad2SJack F Vogel  *  e1000_init_phy_disabled_82543 - Returns init PHY status
3798cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3808cfa0ad2SJack F Vogel  *
3818cfa0ad2SJack F Vogel  *  Returns the current status of whether PHY initialization is disabled.
3828cfa0ad2SJack F Vogel  *  True if PHY initialization is disabled else FALSE.
3838cfa0ad2SJack F Vogel  **/
3848cfa0ad2SJack F Vogel static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw)
3858cfa0ad2SJack F Vogel {
386daf9197cSJack F Vogel 	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
3878cfa0ad2SJack F Vogel 	bool ret_val;
3888cfa0ad2SJack F Vogel 
3898cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_phy_disabled_82543");
3908cfa0ad2SJack F Vogel 
3918cfa0ad2SJack F Vogel 	if (hw->mac.type != e1000_82543) {
3928cfa0ad2SJack F Vogel 		ret_val = FALSE;
3938cfa0ad2SJack F Vogel 		goto out;
3948cfa0ad2SJack F Vogel 	}
3958cfa0ad2SJack F Vogel 
3968cfa0ad2SJack F Vogel 	ret_val = dev_spec->init_phy_disabled;
3978cfa0ad2SJack F Vogel 
3988cfa0ad2SJack F Vogel out:
3998cfa0ad2SJack F Vogel 	return ret_val;
4008cfa0ad2SJack F Vogel }
4018cfa0ad2SJack F Vogel 
4028cfa0ad2SJack F Vogel /**
4038cfa0ad2SJack F Vogel  *  e1000_tbi_adjust_stats_82543 - Adjust stats when TBI enabled
4048cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
4058cfa0ad2SJack F Vogel  *  @stats: Struct containing statistic register values
4068cfa0ad2SJack F Vogel  *  @frame_len: The length of the frame in question
4078cfa0ad2SJack F Vogel  *  @mac_addr: The Ethernet destination address of the frame in question
4088cfa0ad2SJack F Vogel  *  @max_frame_size: The maximum frame size
4098cfa0ad2SJack F Vogel  *
4108cfa0ad2SJack F Vogel  *  Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
4118cfa0ad2SJack F Vogel  **/
4128cfa0ad2SJack F Vogel void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw,
4138cfa0ad2SJack F Vogel 				  struct e1000_hw_stats *stats, u32 frame_len,
4148cfa0ad2SJack F Vogel 				  u8 *mac_addr, u32 max_frame_size)
4158cfa0ad2SJack F Vogel {
4168cfa0ad2SJack F Vogel 	if (!(e1000_tbi_sbp_enabled_82543(hw)))
4178cfa0ad2SJack F Vogel 		goto out;
4188cfa0ad2SJack F Vogel 
4198cfa0ad2SJack F Vogel 	/* First adjust the frame length. */
4208cfa0ad2SJack F Vogel 	frame_len--;
4218cfa0ad2SJack F Vogel 	/*
4228cfa0ad2SJack F Vogel 	 * We need to adjust the statistics counters, since the hardware
4238cfa0ad2SJack F Vogel 	 * counters overcount this packet as a CRC error and undercount
4248cfa0ad2SJack F Vogel 	 * the packet as a good packet
4258cfa0ad2SJack F Vogel 	 */
4268cfa0ad2SJack F Vogel 	/* This packet should not be counted as a CRC error. */
4278cfa0ad2SJack F Vogel 	stats->crcerrs--;
4288cfa0ad2SJack F Vogel 	/* This packet does count as a Good Packet Received. */
4298cfa0ad2SJack F Vogel 	stats->gprc++;
4308cfa0ad2SJack F Vogel 
4318cfa0ad2SJack F Vogel 	/* Adjust the Good Octets received counters */
4328cfa0ad2SJack F Vogel 	stats->gorc += frame_len;
4338cfa0ad2SJack F Vogel 
4348cfa0ad2SJack F Vogel 	/*
4358cfa0ad2SJack F Vogel 	 * Is this a broadcast or multicast?  Check broadcast first,
4368cfa0ad2SJack F Vogel 	 * since the test for a multicast frame will test positive on
4378cfa0ad2SJack F Vogel 	 * a broadcast frame.
4388cfa0ad2SJack F Vogel 	 */
4398cfa0ad2SJack F Vogel 	if ((mac_addr[0] == 0xff) && (mac_addr[1] == 0xff))
4408cfa0ad2SJack F Vogel 		/* Broadcast packet */
4418cfa0ad2SJack F Vogel 		stats->bprc++;
4428cfa0ad2SJack F Vogel 	else if (*mac_addr & 0x01)
4438cfa0ad2SJack F Vogel 		/* Multicast packet */
4448cfa0ad2SJack F Vogel 		stats->mprc++;
4458cfa0ad2SJack F Vogel 
4468cfa0ad2SJack F Vogel 	/*
4478cfa0ad2SJack F Vogel 	 * In this case, the hardware has over counted the number of
4488cfa0ad2SJack F Vogel 	 * oversize frames.
4498cfa0ad2SJack F Vogel 	 */
4508cfa0ad2SJack F Vogel 	if ((frame_len == max_frame_size) && (stats->roc > 0))
4518cfa0ad2SJack F Vogel 		stats->roc--;
4528cfa0ad2SJack F Vogel 
4538cfa0ad2SJack F Vogel 	/*
4548cfa0ad2SJack F Vogel 	 * Adjust the bin counters when the extra byte put the frame in the
4558cfa0ad2SJack F Vogel 	 * wrong bin. Remember that the frame_len was adjusted above.
4568cfa0ad2SJack F Vogel 	 */
4578cfa0ad2SJack F Vogel 	if (frame_len == 64) {
4588cfa0ad2SJack F Vogel 		stats->prc64++;
4598cfa0ad2SJack F Vogel 		stats->prc127--;
4608cfa0ad2SJack F Vogel 	} else if (frame_len == 127) {
4618cfa0ad2SJack F Vogel 		stats->prc127++;
4628cfa0ad2SJack F Vogel 		stats->prc255--;
4638cfa0ad2SJack F Vogel 	} else if (frame_len == 255) {
4648cfa0ad2SJack F Vogel 		stats->prc255++;
4658cfa0ad2SJack F Vogel 		stats->prc511--;
4668cfa0ad2SJack F Vogel 	} else if (frame_len == 511) {
4678cfa0ad2SJack F Vogel 		stats->prc511++;
4688cfa0ad2SJack F Vogel 		stats->prc1023--;
4698cfa0ad2SJack F Vogel 	} else if (frame_len == 1023) {
4708cfa0ad2SJack F Vogel 		stats->prc1023++;
4718cfa0ad2SJack F Vogel 		stats->prc1522--;
4728cfa0ad2SJack F Vogel 	} else if (frame_len == 1522) {
4738cfa0ad2SJack F Vogel 		stats->prc1522++;
4748cfa0ad2SJack F Vogel 	}
4758cfa0ad2SJack F Vogel 
4768cfa0ad2SJack F Vogel out:
4778cfa0ad2SJack F Vogel 	return;
4788cfa0ad2SJack F Vogel }
4798cfa0ad2SJack F Vogel 
4808cfa0ad2SJack F Vogel /**
4818cfa0ad2SJack F Vogel  *  e1000_read_phy_reg_82543 - Read PHY register
4828cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
4838cfa0ad2SJack F Vogel  *  @offset: register offset to be read
4848cfa0ad2SJack F Vogel  *  @data: pointer to the read data
4858cfa0ad2SJack F Vogel  *
4868cfa0ad2SJack F Vogel  *  Reads the PHY at offset and stores the information read to data.
4878cfa0ad2SJack F Vogel  **/
4888cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data)
4898cfa0ad2SJack F Vogel {
4908cfa0ad2SJack F Vogel 	u32 mdic;
4918cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
4928cfa0ad2SJack F Vogel 
4938cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_read_phy_reg_82543");
4948cfa0ad2SJack F Vogel 
4958cfa0ad2SJack F Vogel 	if (offset > MAX_PHY_REG_ADDRESS) {
4968cfa0ad2SJack F Vogel 		DEBUGOUT1("PHY Address %d is out of range\n", offset);
4978cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PARAM;
4988cfa0ad2SJack F Vogel 		goto out;
4998cfa0ad2SJack F Vogel 	}
5008cfa0ad2SJack F Vogel 
5018cfa0ad2SJack F Vogel 	/*
5028cfa0ad2SJack F Vogel 	 * We must first send a preamble through the MDIO pin to signal the
5038cfa0ad2SJack F Vogel 	 * beginning of an MII instruction.  This is done by sending 32
5048cfa0ad2SJack F Vogel 	 * consecutive "1" bits.
5058cfa0ad2SJack F Vogel 	 */
5068cfa0ad2SJack F Vogel 	e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
5078cfa0ad2SJack F Vogel 
5088cfa0ad2SJack F Vogel 	/*
5098cfa0ad2SJack F Vogel 	 * Now combine the next few fields that are required for a read
5108cfa0ad2SJack F Vogel 	 * operation.  We use this method instead of calling the
5118cfa0ad2SJack F Vogel 	 * e1000_shift_out_mdi_bits routine five different times.  The format
5128cfa0ad2SJack F Vogel 	 * of an MII read instruction consists of a shift out of 14 bits and
5138cfa0ad2SJack F Vogel 	 * is defined as follows:
5148cfa0ad2SJack F Vogel 	 *         <Preamble><SOF><Op Code><Phy Addr><Offset>
5158cfa0ad2SJack F Vogel 	 * followed by a shift in of 18 bits.  This first two bits shifted in
5168cfa0ad2SJack F Vogel 	 * are TurnAround bits used to avoid contention on the MDIO pin when a
5178cfa0ad2SJack F Vogel 	 * READ operation is performed.  These two bits are thrown away
5188cfa0ad2SJack F Vogel 	 * followed by a shift in of 16 bits which contains the desired data.
5198cfa0ad2SJack F Vogel 	 */
5208cfa0ad2SJack F Vogel 	mdic = (offset | (hw->phy.addr << 5) |
5218cfa0ad2SJack F Vogel 		(PHY_OP_READ << 10) | (PHY_SOF << 12));
5228cfa0ad2SJack F Vogel 
5238cfa0ad2SJack F Vogel 	e1000_shift_out_mdi_bits_82543(hw, mdic, 14);
5248cfa0ad2SJack F Vogel 
5258cfa0ad2SJack F Vogel 	/*
5268cfa0ad2SJack F Vogel 	 * Now that we've shifted out the read command to the MII, we need to
5278cfa0ad2SJack F Vogel 	 * "shift in" the 16-bit value (18 total bits) of the requested PHY
5288cfa0ad2SJack F Vogel 	 * register address.
5298cfa0ad2SJack F Vogel 	 */
5308cfa0ad2SJack F Vogel 	*data = e1000_shift_in_mdi_bits_82543(hw);
5318cfa0ad2SJack F Vogel 
5328cfa0ad2SJack F Vogel out:
5338cfa0ad2SJack F Vogel 	return ret_val;
5348cfa0ad2SJack F Vogel }
5358cfa0ad2SJack F Vogel 
5368cfa0ad2SJack F Vogel /**
5378cfa0ad2SJack F Vogel  *  e1000_write_phy_reg_82543 - Write PHY register
5388cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5398cfa0ad2SJack F Vogel  *  @offset: register offset to be written
5408cfa0ad2SJack F Vogel  *  @data: pointer to the data to be written at offset
5418cfa0ad2SJack F Vogel  *
5428cfa0ad2SJack F Vogel  *  Writes data to the PHY at offset.
5438cfa0ad2SJack F Vogel  **/
5448cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data)
5458cfa0ad2SJack F Vogel {
5468cfa0ad2SJack F Vogel 	u32 mdic;
5478cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
5488cfa0ad2SJack F Vogel 
5498cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_write_phy_reg_82543");
5508cfa0ad2SJack F Vogel 
5518cfa0ad2SJack F Vogel 	if (offset > MAX_PHY_REG_ADDRESS) {
5528cfa0ad2SJack F Vogel 		DEBUGOUT1("PHY Address %d is out of range\n", offset);
5538cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PARAM;
5548cfa0ad2SJack F Vogel 		goto out;
5558cfa0ad2SJack F Vogel 	}
5568cfa0ad2SJack F Vogel 
5578cfa0ad2SJack F Vogel 	/*
5588cfa0ad2SJack F Vogel 	 * We'll need to use the SW defined pins to shift the write command
5598cfa0ad2SJack F Vogel 	 * out to the PHY. We first send a preamble to the PHY to signal the
5608cfa0ad2SJack F Vogel 	 * beginning of the MII instruction.  This is done by sending 32
5618cfa0ad2SJack F Vogel 	 * consecutive "1" bits.
5628cfa0ad2SJack F Vogel 	 */
5638cfa0ad2SJack F Vogel 	e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
5648cfa0ad2SJack F Vogel 
5658cfa0ad2SJack F Vogel 	/*
5668cfa0ad2SJack F Vogel 	 * Now combine the remaining required fields that will indicate a
5678cfa0ad2SJack F Vogel 	 * write operation. We use this method instead of calling the
5688cfa0ad2SJack F Vogel 	 * e1000_shift_out_mdi_bits routine for each field in the command. The
5698cfa0ad2SJack F Vogel 	 * format of a MII write instruction is as follows:
5708cfa0ad2SJack F Vogel 	 * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
5718cfa0ad2SJack F Vogel 	 */
5728cfa0ad2SJack F Vogel 	mdic = ((PHY_TURNAROUND) | (offset << 2) | (hw->phy.addr << 7) |
5738cfa0ad2SJack F Vogel 		(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
5748cfa0ad2SJack F Vogel 	mdic <<= 16;
5758cfa0ad2SJack F Vogel 	mdic |= (u32)data;
5768cfa0ad2SJack F Vogel 
5778cfa0ad2SJack F Vogel 	e1000_shift_out_mdi_bits_82543(hw, mdic, 32);
5788cfa0ad2SJack F Vogel 
5798cfa0ad2SJack F Vogel out:
5808cfa0ad2SJack F Vogel 	return ret_val;
5818cfa0ad2SJack F Vogel }
5828cfa0ad2SJack F Vogel 
5838cfa0ad2SJack F Vogel /**
5848cfa0ad2SJack F Vogel  *  e1000_raise_mdi_clk_82543 - Raise Management Data Input clock
5858cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5868cfa0ad2SJack F Vogel  *  @ctrl: pointer to the control register
5878cfa0ad2SJack F Vogel  *
5888cfa0ad2SJack F Vogel  *  Raise the management data input clock by setting the MDC bit in the control
5898cfa0ad2SJack F Vogel  *  register.
5908cfa0ad2SJack F Vogel  **/
5918cfa0ad2SJack F Vogel static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
5928cfa0ad2SJack F Vogel {
5938cfa0ad2SJack F Vogel 	/*
5948cfa0ad2SJack F Vogel 	 * Raise the clock input to the Management Data Clock (by setting the
5958cfa0ad2SJack F Vogel 	 * MDC bit), and then delay a sufficient amount of time.
5968cfa0ad2SJack F Vogel 	 */
5978cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl | E1000_CTRL_MDC));
5988cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
5998cfa0ad2SJack F Vogel 	usec_delay(10);
6008cfa0ad2SJack F Vogel }
6018cfa0ad2SJack F Vogel 
6028cfa0ad2SJack F Vogel /**
6038cfa0ad2SJack F Vogel  *  e1000_lower_mdi_clk_82543 - Lower Management Data Input clock
6048cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
6058cfa0ad2SJack F Vogel  *  @ctrl: pointer to the control register
6068cfa0ad2SJack F Vogel  *
6078cfa0ad2SJack F Vogel  *  Lower the management data input clock by clearing the MDC bit in the
6088cfa0ad2SJack F Vogel  *  control register.
6098cfa0ad2SJack F Vogel  **/
6108cfa0ad2SJack F Vogel static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
6118cfa0ad2SJack F Vogel {
6128cfa0ad2SJack F Vogel 	/*
6138cfa0ad2SJack F Vogel 	 * Lower the clock input to the Management Data Clock (by clearing the
6148cfa0ad2SJack F Vogel 	 * MDC bit), and then delay a sufficient amount of time.
6158cfa0ad2SJack F Vogel 	 */
6168cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl & ~E1000_CTRL_MDC));
6178cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
6188cfa0ad2SJack F Vogel 	usec_delay(10);
6198cfa0ad2SJack F Vogel }
6208cfa0ad2SJack F Vogel 
6218cfa0ad2SJack F Vogel /**
6228cfa0ad2SJack F Vogel  *  e1000_shift_out_mdi_bits_82543 - Shift data bits our to the PHY
6238cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
6248cfa0ad2SJack F Vogel  *  @data: data to send to the PHY
6258cfa0ad2SJack F Vogel  *  @count: number of bits to shift out
6268cfa0ad2SJack F Vogel  *
6278cfa0ad2SJack F Vogel  *  We need to shift 'count' bits out to the PHY.  So, the value in the
6288cfa0ad2SJack F Vogel  *  "data" parameter will be shifted out to the PHY one bit at a time.
6298cfa0ad2SJack F Vogel  *  In order to do this, "data" must be broken down into bits.
6308cfa0ad2SJack F Vogel  **/
6318cfa0ad2SJack F Vogel static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
6328cfa0ad2SJack F Vogel 					   u16 count)
6338cfa0ad2SJack F Vogel {
6348cfa0ad2SJack F Vogel 	u32 ctrl, mask;
6358cfa0ad2SJack F Vogel 
6368cfa0ad2SJack F Vogel 	/*
6378cfa0ad2SJack F Vogel 	 * We need to shift "count" number of bits out to the PHY.  So, the
6388cfa0ad2SJack F Vogel 	 * value in the "data" parameter will be shifted out to the PHY one
6398cfa0ad2SJack F Vogel 	 * bit at a time.  In order to do this, "data" must be broken down
6408cfa0ad2SJack F Vogel 	 * into bits.
6418cfa0ad2SJack F Vogel 	 */
6428cfa0ad2SJack F Vogel 	mask = 0x01;
6438cfa0ad2SJack F Vogel 	mask <<= (count - 1);
6448cfa0ad2SJack F Vogel 
6458cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
6468cfa0ad2SJack F Vogel 
6478cfa0ad2SJack F Vogel 	/* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
6488cfa0ad2SJack F Vogel 	ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
6498cfa0ad2SJack F Vogel 
6508cfa0ad2SJack F Vogel 	while (mask) {
6518cfa0ad2SJack F Vogel 		/*
6528cfa0ad2SJack F Vogel 		 * A "1" is shifted out to the PHY by setting the MDIO bit to
6538cfa0ad2SJack F Vogel 		 * "1" and then raising and lowering the Management Data Clock.
6548cfa0ad2SJack F Vogel 		 * A "0" is shifted out to the PHY by setting the MDIO bit to
6558cfa0ad2SJack F Vogel 		 * "0" and then raising and lowering the clock.
6568cfa0ad2SJack F Vogel 		 */
65748600901SSean Bruno 		if (data & mask)
65848600901SSean Bruno 			ctrl |= E1000_CTRL_MDIO;
65948600901SSean Bruno 		else
66048600901SSean Bruno 			ctrl &= ~E1000_CTRL_MDIO;
6618cfa0ad2SJack F Vogel 
6628cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
6638cfa0ad2SJack F Vogel 		E1000_WRITE_FLUSH(hw);
6648cfa0ad2SJack F Vogel 
6658cfa0ad2SJack F Vogel 		usec_delay(10);
6668cfa0ad2SJack F Vogel 
6678cfa0ad2SJack F Vogel 		e1000_raise_mdi_clk_82543(hw, &ctrl);
6688cfa0ad2SJack F Vogel 		e1000_lower_mdi_clk_82543(hw, &ctrl);
6698cfa0ad2SJack F Vogel 
6708cfa0ad2SJack F Vogel 		mask >>= 1;
6718cfa0ad2SJack F Vogel 	}
6728cfa0ad2SJack F Vogel }
6738cfa0ad2SJack F Vogel 
6748cfa0ad2SJack F Vogel /**
6758cfa0ad2SJack F Vogel  *  e1000_shift_in_mdi_bits_82543 - Shift data bits in from the PHY
6768cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
6778cfa0ad2SJack F Vogel  *
6788cfa0ad2SJack F Vogel  *  In order to read a register from the PHY, we need to shift 18 bits
6798cfa0ad2SJack F Vogel  *  in from the PHY.  Bits are "shifted in" by raising the clock input to
6808cfa0ad2SJack F Vogel  *  the PHY (setting the MDC bit), and then reading the value of the data out
6818cfa0ad2SJack F Vogel  *  MDIO bit.
6828cfa0ad2SJack F Vogel  **/
6838cfa0ad2SJack F Vogel static u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw)
6848cfa0ad2SJack F Vogel {
6858cfa0ad2SJack F Vogel 	u32 ctrl;
6868cfa0ad2SJack F Vogel 	u16 data = 0;
6878cfa0ad2SJack F Vogel 	u8 i;
6888cfa0ad2SJack F Vogel 
6898cfa0ad2SJack F Vogel 	/*
6908cfa0ad2SJack F Vogel 	 * In order to read a register from the PHY, we need to shift in a
6918cfa0ad2SJack F Vogel 	 * total of 18 bits from the PHY.  The first two bit (turnaround)
6928cfa0ad2SJack F Vogel 	 * times are used to avoid contention on the MDIO pin when a read
6938cfa0ad2SJack F Vogel 	 * operation is performed.  These two bits are ignored by us and
6948cfa0ad2SJack F Vogel 	 * thrown away.  Bits are "shifted in" by raising the input to the
6958cfa0ad2SJack F Vogel 	 * Management Data Clock (setting the MDC bit) and then reading the
6968cfa0ad2SJack F Vogel 	 * value of the MDIO bit.
6978cfa0ad2SJack F Vogel 	 */
6988cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
6998cfa0ad2SJack F Vogel 
7008cfa0ad2SJack F Vogel 	/*
7018cfa0ad2SJack F Vogel 	 * Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
7028cfa0ad2SJack F Vogel 	 * input.
7038cfa0ad2SJack F Vogel 	 */
7048cfa0ad2SJack F Vogel 	ctrl &= ~E1000_CTRL_MDIO_DIR;
7058cfa0ad2SJack F Vogel 	ctrl &= ~E1000_CTRL_MDIO;
7068cfa0ad2SJack F Vogel 
7078cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
7088cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
7098cfa0ad2SJack F Vogel 
7108cfa0ad2SJack F Vogel 	/*
7118cfa0ad2SJack F Vogel 	 * Raise and lower the clock before reading in the data.  This accounts
7128cfa0ad2SJack F Vogel 	 * for the turnaround bits.  The first clock occurred when we clocked
7138cfa0ad2SJack F Vogel 	 * out the last bit of the Register Address.
7148cfa0ad2SJack F Vogel 	 */
7158cfa0ad2SJack F Vogel 	e1000_raise_mdi_clk_82543(hw, &ctrl);
7168cfa0ad2SJack F Vogel 	e1000_lower_mdi_clk_82543(hw, &ctrl);
7178cfa0ad2SJack F Vogel 
7188cfa0ad2SJack F Vogel 	for (data = 0, i = 0; i < 16; i++) {
7198cfa0ad2SJack F Vogel 		data <<= 1;
7208cfa0ad2SJack F Vogel 		e1000_raise_mdi_clk_82543(hw, &ctrl);
7218cfa0ad2SJack F Vogel 		ctrl = E1000_READ_REG(hw, E1000_CTRL);
7228cfa0ad2SJack F Vogel 		/* Check to see if we shifted in a "1". */
7238cfa0ad2SJack F Vogel 		if (ctrl & E1000_CTRL_MDIO)
7248cfa0ad2SJack F Vogel 			data |= 1;
7258cfa0ad2SJack F Vogel 		e1000_lower_mdi_clk_82543(hw, &ctrl);
7268cfa0ad2SJack F Vogel 	}
7278cfa0ad2SJack F Vogel 
7288cfa0ad2SJack F Vogel 	e1000_raise_mdi_clk_82543(hw, &ctrl);
7298cfa0ad2SJack F Vogel 	e1000_lower_mdi_clk_82543(hw, &ctrl);
7308cfa0ad2SJack F Vogel 
7318cfa0ad2SJack F Vogel 	return data;
7328cfa0ad2SJack F Vogel }
7338cfa0ad2SJack F Vogel 
7348cfa0ad2SJack F Vogel /**
7358cfa0ad2SJack F Vogel  *  e1000_phy_force_speed_duplex_82543 - Force speed/duplex for PHY
7368cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
7378cfa0ad2SJack F Vogel  *
7388cfa0ad2SJack F Vogel  *  Calls the function to force speed and duplex for the m88 PHY, and
7398cfa0ad2SJack F Vogel  *  if the PHY is not auto-negotiating and the speed is forced to 10Mbit,
7408cfa0ad2SJack F Vogel  *  then call the function for polarity reversal workaround.
7418cfa0ad2SJack F Vogel  **/
7428cfa0ad2SJack F Vogel static s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw)
7438cfa0ad2SJack F Vogel {
7448cfa0ad2SJack F Vogel 	s32 ret_val;
7458cfa0ad2SJack F Vogel 
7468cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_phy_force_speed_duplex_82543");
7478cfa0ad2SJack F Vogel 
7488cfa0ad2SJack F Vogel 	ret_val = e1000_phy_force_speed_duplex_m88(hw);
7498cfa0ad2SJack F Vogel 	if (ret_val)
7508cfa0ad2SJack F Vogel 		goto out;
7518cfa0ad2SJack F Vogel 
75248600901SSean Bruno 	if (!hw->mac.autoneg && (hw->mac.forced_speed_duplex &
75348600901SSean Bruno 	    E1000_ALL_10_SPEED))
7548cfa0ad2SJack F Vogel 		ret_val = e1000_polarity_reversal_workaround_82543(hw);
7558cfa0ad2SJack F Vogel 
7568cfa0ad2SJack F Vogel out:
7578cfa0ad2SJack F Vogel 	return ret_val;
7588cfa0ad2SJack F Vogel }
7598cfa0ad2SJack F Vogel 
7608cfa0ad2SJack F Vogel /**
7618cfa0ad2SJack F Vogel  *  e1000_polarity_reversal_workaround_82543 - Workaround polarity reversal
7628cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
7638cfa0ad2SJack F Vogel  *
7648cfa0ad2SJack F Vogel  *  When forcing link to 10 Full or 10 Half, the PHY can reverse the polarity
7658cfa0ad2SJack F Vogel  *  inadvertently.  To workaround the issue, we disable the transmitter on
7668cfa0ad2SJack F Vogel  *  the PHY until we have established the link partner's link parameters.
7678cfa0ad2SJack F Vogel  **/
7688cfa0ad2SJack F Vogel static s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw)
7698cfa0ad2SJack F Vogel {
7708cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
7718cfa0ad2SJack F Vogel 	u16 mii_status_reg;
7728cfa0ad2SJack F Vogel 	u16 i;
7738cfa0ad2SJack F Vogel 	bool link;
7748cfa0ad2SJack F Vogel 
7758cfa0ad2SJack F Vogel 	if (!(hw->phy.ops.write_reg))
7768cfa0ad2SJack F Vogel 		goto out;
7778cfa0ad2SJack F Vogel 
7788cfa0ad2SJack F Vogel 	/* Polarity reversal workaround for forced 10F/10H links. */
7798cfa0ad2SJack F Vogel 
7808cfa0ad2SJack F Vogel 	/* Disable the transmitter on the PHY */
7818cfa0ad2SJack F Vogel 
7828cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
7838cfa0ad2SJack F Vogel 	if (ret_val)
7848cfa0ad2SJack F Vogel 		goto out;
7858cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
7868cfa0ad2SJack F Vogel 	if (ret_val)
7878cfa0ad2SJack F Vogel 		goto out;
7888cfa0ad2SJack F Vogel 
7898cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
7908cfa0ad2SJack F Vogel 	if (ret_val)
7918cfa0ad2SJack F Vogel 		goto out;
7928cfa0ad2SJack F Vogel 
7938cfa0ad2SJack F Vogel 	/*
7948cfa0ad2SJack F Vogel 	 * This loop will early-out if the NO link condition has been met.
7958cfa0ad2SJack F Vogel 	 * In other words, DO NOT use e1000_phy_has_link_generic() here.
7968cfa0ad2SJack F Vogel 	 */
7978cfa0ad2SJack F Vogel 	for (i = PHY_FORCE_TIME; i > 0; i--) {
7988cfa0ad2SJack F Vogel 		/*
7998cfa0ad2SJack F Vogel 		 * Read the MII Status Register and wait for Link Status bit
8008cfa0ad2SJack F Vogel 		 * to be clear.
8018cfa0ad2SJack F Vogel 		 */
8028cfa0ad2SJack F Vogel 
8038cfa0ad2SJack F Vogel 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
8048cfa0ad2SJack F Vogel 		if (ret_val)
8058cfa0ad2SJack F Vogel 			goto out;
8068cfa0ad2SJack F Vogel 
8078cfa0ad2SJack F Vogel 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
8088cfa0ad2SJack F Vogel 		if (ret_val)
8098cfa0ad2SJack F Vogel 			goto out;
8108cfa0ad2SJack F Vogel 
81148600901SSean Bruno 		if (!(mii_status_reg & ~MII_SR_LINK_STATUS))
8128cfa0ad2SJack F Vogel 			break;
8138cfa0ad2SJack F Vogel 		msec_delay_irq(100);
8148cfa0ad2SJack F Vogel 	}
8158cfa0ad2SJack F Vogel 
8168cfa0ad2SJack F Vogel 	/* Recommended delay time after link has been lost */
8178cfa0ad2SJack F Vogel 	msec_delay_irq(1000);
8188cfa0ad2SJack F Vogel 
8198cfa0ad2SJack F Vogel 	/* Now we will re-enable the transmitter on the PHY */
8208cfa0ad2SJack F Vogel 
8218cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
8228cfa0ad2SJack F Vogel 	if (ret_val)
8238cfa0ad2SJack F Vogel 		goto out;
8248cfa0ad2SJack F Vogel 	msec_delay_irq(50);
8258cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
8268cfa0ad2SJack F Vogel 	if (ret_val)
8278cfa0ad2SJack F Vogel 		goto out;
8288cfa0ad2SJack F Vogel 	msec_delay_irq(50);
8298cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
8308cfa0ad2SJack F Vogel 	if (ret_val)
8318cfa0ad2SJack F Vogel 		goto out;
8328cfa0ad2SJack F Vogel 	msec_delay_irq(50);
8338cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
8348cfa0ad2SJack F Vogel 	if (ret_val)
8358cfa0ad2SJack F Vogel 		goto out;
8368cfa0ad2SJack F Vogel 
8378cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
8388cfa0ad2SJack F Vogel 	if (ret_val)
8398cfa0ad2SJack F Vogel 		goto out;
8408cfa0ad2SJack F Vogel 
8418cfa0ad2SJack F Vogel 	/*
8428cfa0ad2SJack F Vogel 	 * Read the MII Status Register and wait for Link Status bit
8438cfa0ad2SJack F Vogel 	 * to be set.
8448cfa0ad2SJack F Vogel 	 */
8458cfa0ad2SJack F Vogel 	ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_TIME, 100000, &link);
8468cfa0ad2SJack F Vogel 	if (ret_val)
8478cfa0ad2SJack F Vogel 		goto out;
8488cfa0ad2SJack F Vogel 
8498cfa0ad2SJack F Vogel out:
8508cfa0ad2SJack F Vogel 	return ret_val;
8518cfa0ad2SJack F Vogel }
8528cfa0ad2SJack F Vogel 
8538cfa0ad2SJack F Vogel /**
8548cfa0ad2SJack F Vogel  *  e1000_phy_hw_reset_82543 - PHY hardware reset
8558cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
8568cfa0ad2SJack F Vogel  *
8578cfa0ad2SJack F Vogel  *  Sets the PHY_RESET_DIR bit in the extended device control register
8588cfa0ad2SJack F Vogel  *  to put the PHY into a reset and waits for completion.  Once the reset
8598cfa0ad2SJack F Vogel  *  has been accomplished, clear the PHY_RESET_DIR bit to take the PHY out
860daf9197cSJack F Vogel  *  of reset.
8618cfa0ad2SJack F Vogel  **/
8628cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw)
8638cfa0ad2SJack F Vogel {
8648cfa0ad2SJack F Vogel 	u32 ctrl_ext;
8658cfa0ad2SJack F Vogel 	s32 ret_val;
8668cfa0ad2SJack F Vogel 
8678cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_phy_hw_reset_82543");
8688cfa0ad2SJack F Vogel 
8698cfa0ad2SJack F Vogel 	/*
8708cfa0ad2SJack F Vogel 	 * Read the Extended Device Control Register, assert the PHY_RESET_DIR
8718cfa0ad2SJack F Vogel 	 * bit to put the PHY into reset...
8728cfa0ad2SJack F Vogel 	 */
8738cfa0ad2SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
8748cfa0ad2SJack F Vogel 	ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
8758cfa0ad2SJack F Vogel 	ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
8768cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
8778cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
8788cfa0ad2SJack F Vogel 
8798cfa0ad2SJack F Vogel 	msec_delay(10);
8808cfa0ad2SJack F Vogel 
8818cfa0ad2SJack F Vogel 	/* ...then take it out of reset. */
8828cfa0ad2SJack F Vogel 	ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
8838cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
8848cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
8858cfa0ad2SJack F Vogel 
8868cfa0ad2SJack F Vogel 	usec_delay(150);
8878cfa0ad2SJack F Vogel 
8888cfa0ad2SJack F Vogel 	if (!(hw->phy.ops.get_cfg_done))
8898cfa0ad2SJack F Vogel 		return E1000_SUCCESS;
8908cfa0ad2SJack F Vogel 
8918cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.get_cfg_done(hw);
8928cfa0ad2SJack F Vogel 
8938cfa0ad2SJack F Vogel 	return ret_val;
8948cfa0ad2SJack F Vogel }
8958cfa0ad2SJack F Vogel 
8968cfa0ad2SJack F Vogel /**
8978cfa0ad2SJack F Vogel  *  e1000_reset_hw_82543 - Reset hardware
8988cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
8998cfa0ad2SJack F Vogel  *
900daf9197cSJack F Vogel  *  This resets the hardware into a known state.
9018cfa0ad2SJack F Vogel  **/
9028cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82543(struct e1000_hw *hw)
9038cfa0ad2SJack F Vogel {
904c80429ceSEric Joyner 	u32 ctrl;
9058cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
9068cfa0ad2SJack F Vogel 
9078cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_reset_hw_82543");
9088cfa0ad2SJack F Vogel 
9098cfa0ad2SJack F Vogel 	DEBUGOUT("Masking off all interrupts\n");
9108cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
9118cfa0ad2SJack F Vogel 
9128cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
9138cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
9148cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
9158cfa0ad2SJack F Vogel 
9168cfa0ad2SJack F Vogel 	e1000_set_tbi_sbp_82543(hw, FALSE);
9178cfa0ad2SJack F Vogel 
9188cfa0ad2SJack F Vogel 	/*
9198cfa0ad2SJack F Vogel 	 * Delay to allow any outstanding PCI transactions to complete before
9208cfa0ad2SJack F Vogel 	 * resetting the device
9218cfa0ad2SJack F Vogel 	 */
9228cfa0ad2SJack F Vogel 	msec_delay(10);
9238cfa0ad2SJack F Vogel 
9248cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
9258cfa0ad2SJack F Vogel 
9268cfa0ad2SJack F Vogel 	DEBUGOUT("Issuing a global reset to 82543/82544 MAC\n");
9278cfa0ad2SJack F Vogel 	if (hw->mac.type == e1000_82543) {
9288cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
9298cfa0ad2SJack F Vogel 	} else {
9308cfa0ad2SJack F Vogel 		/*
9318cfa0ad2SJack F Vogel 		 * The 82544 can't ACK the 64-bit write when issuing the
9328cfa0ad2SJack F Vogel 		 * reset, so use IO-mapping as a workaround.
9338cfa0ad2SJack F Vogel 		 */
9348cfa0ad2SJack F Vogel 		E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
9358cfa0ad2SJack F Vogel 	}
9368cfa0ad2SJack F Vogel 
9378cfa0ad2SJack F Vogel 	/*
9388cfa0ad2SJack F Vogel 	 * After MAC reset, force reload of NVM to restore power-on
9398cfa0ad2SJack F Vogel 	 * settings to device.
9408cfa0ad2SJack F Vogel 	 */
9418cfa0ad2SJack F Vogel 	hw->nvm.ops.reload(hw);
9428cfa0ad2SJack F Vogel 	msec_delay(2);
9438cfa0ad2SJack F Vogel 
9448cfa0ad2SJack F Vogel 	/* Masking off and clearing any pending interrupts */
9458cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
946c80429ceSEric Joyner 	E1000_READ_REG(hw, E1000_ICR);
9478cfa0ad2SJack F Vogel 
9488cfa0ad2SJack F Vogel 	return ret_val;
9498cfa0ad2SJack F Vogel }
9508cfa0ad2SJack F Vogel 
9518cfa0ad2SJack F Vogel /**
9528cfa0ad2SJack F Vogel  *  e1000_init_hw_82543 - Initialize hardware
9538cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
9548cfa0ad2SJack F Vogel  *
9558cfa0ad2SJack F Vogel  *  This inits the hardware readying it for operation.
9568cfa0ad2SJack F Vogel  **/
9578cfa0ad2SJack F Vogel static s32 e1000_init_hw_82543(struct e1000_hw *hw)
9588cfa0ad2SJack F Vogel {
9598cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
960daf9197cSJack F Vogel 	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
9618cfa0ad2SJack F Vogel 	u32 ctrl;
9628cfa0ad2SJack F Vogel 	s32 ret_val;
9638cfa0ad2SJack F Vogel 	u16 i;
9648cfa0ad2SJack F Vogel 
9658cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_hw_82543");
9668cfa0ad2SJack F Vogel 
9678cfa0ad2SJack F Vogel 	/* Disabling VLAN filtering */
9688cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_VET, 0);
9698cfa0ad2SJack F Vogel 	mac->ops.clear_vfta(hw);
9708cfa0ad2SJack F Vogel 
9718cfa0ad2SJack F Vogel 	/* Setup the receive address. */
9728cfa0ad2SJack F Vogel 	e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
9738cfa0ad2SJack F Vogel 
9748cfa0ad2SJack F Vogel 	/* Zero out the Multicast HASH table */
9758cfa0ad2SJack F Vogel 	DEBUGOUT("Zeroing the MTA\n");
9768cfa0ad2SJack F Vogel 	for (i = 0; i < mac->mta_reg_count; i++) {
9778cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
9788cfa0ad2SJack F Vogel 		E1000_WRITE_FLUSH(hw);
9798cfa0ad2SJack F Vogel 	}
9808cfa0ad2SJack F Vogel 
9818cfa0ad2SJack F Vogel 	/*
9828cfa0ad2SJack F Vogel 	 * Set the PCI priority bit correctly in the CTRL register.  This
9838cfa0ad2SJack F Vogel 	 * determines if the adapter gives priority to receives, or if it
9848cfa0ad2SJack F Vogel 	 * gives equal priority to transmits and receives.
9858cfa0ad2SJack F Vogel 	 */
9868cfa0ad2SJack F Vogel 	if (hw->mac.type == e1000_82543 && dev_spec->dma_fairness) {
9878cfa0ad2SJack F Vogel 		ctrl = E1000_READ_REG(hw, E1000_CTRL);
9888cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR);
9898cfa0ad2SJack F Vogel 	}
9908cfa0ad2SJack F Vogel 
9918cfa0ad2SJack F Vogel 	e1000_pcix_mmrbc_workaround_generic(hw);
9928cfa0ad2SJack F Vogel 
9938cfa0ad2SJack F Vogel 	/* Setup link and flow control */
9948cfa0ad2SJack F Vogel 	ret_val = mac->ops.setup_link(hw);
9958cfa0ad2SJack F Vogel 
9968cfa0ad2SJack F Vogel 	/*
9978cfa0ad2SJack F Vogel 	 * Clear all of the statistics registers (clear on read).  It is
9988cfa0ad2SJack F Vogel 	 * important that we do this after we have tried to establish link
9998cfa0ad2SJack F Vogel 	 * because the symbol error count will increment wildly if there
10008cfa0ad2SJack F Vogel 	 * is no link.
10018cfa0ad2SJack F Vogel 	 */
10028cfa0ad2SJack F Vogel 	e1000_clear_hw_cntrs_82543(hw);
10038cfa0ad2SJack F Vogel 
10048cfa0ad2SJack F Vogel 	return ret_val;
10058cfa0ad2SJack F Vogel }
10068cfa0ad2SJack F Vogel 
10078cfa0ad2SJack F Vogel /**
10088cfa0ad2SJack F Vogel  *  e1000_setup_link_82543 - Setup flow control and link settings
10098cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
10108cfa0ad2SJack F Vogel  *
10118cfa0ad2SJack F Vogel  *  Read the EEPROM to determine the initial polarity value and write the
10128cfa0ad2SJack F Vogel  *  extended device control register with the information before calling
10138cfa0ad2SJack F Vogel  *  the generic setup link function, which does the following:
10148cfa0ad2SJack F Vogel  *  Determines which flow control settings to use, then configures flow
10158cfa0ad2SJack F Vogel  *  control.  Calls the appropriate media-specific link configuration
10168cfa0ad2SJack F Vogel  *  function.  Assuming the adapter has a valid link partner, a valid link
10178cfa0ad2SJack F Vogel  *  should be established.  Assumes the hardware has previously been reset
10188cfa0ad2SJack F Vogel  *  and the transmitter and receiver are not enabled.
10198cfa0ad2SJack F Vogel  **/
10208cfa0ad2SJack F Vogel static s32 e1000_setup_link_82543(struct e1000_hw *hw)
10218cfa0ad2SJack F Vogel {
10228cfa0ad2SJack F Vogel 	u32 ctrl_ext;
10238cfa0ad2SJack F Vogel 	s32  ret_val;
10248cfa0ad2SJack F Vogel 	u16 data;
10258cfa0ad2SJack F Vogel 
10268cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_setup_link_82543");
10278cfa0ad2SJack F Vogel 
10288cfa0ad2SJack F Vogel 	/*
10298cfa0ad2SJack F Vogel 	 * Take the 4 bits from NVM word 0xF that determine the initial
10308cfa0ad2SJack F Vogel 	 * polarity value for the SW controlled pins, and setup the
10318cfa0ad2SJack F Vogel 	 * Extended Device Control reg with that info.
10328cfa0ad2SJack F Vogel 	 * This is needed because one of the SW controlled pins is used for
10338cfa0ad2SJack F Vogel 	 * signal detection.  So this should be done before phy setup.
10348cfa0ad2SJack F Vogel 	 */
10358cfa0ad2SJack F Vogel 	if (hw->mac.type == e1000_82543) {
10368cfa0ad2SJack F Vogel 		ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data);
10378cfa0ad2SJack F Vogel 		if (ret_val) {
10388cfa0ad2SJack F Vogel 			DEBUGOUT("NVM Read Error\n");
10398cfa0ad2SJack F Vogel 			ret_val = -E1000_ERR_NVM;
10408cfa0ad2SJack F Vogel 			goto out;
10418cfa0ad2SJack F Vogel 		}
10428cfa0ad2SJack F Vogel 		ctrl_ext = ((data & NVM_WORD0F_SWPDIO_EXT_MASK) <<
10438cfa0ad2SJack F Vogel 			    NVM_SWDPIO_EXT_SHIFT);
10448cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
10458cfa0ad2SJack F Vogel 	}
10468cfa0ad2SJack F Vogel 
10478cfa0ad2SJack F Vogel 	ret_val = e1000_setup_link_generic(hw);
10488cfa0ad2SJack F Vogel 
10498cfa0ad2SJack F Vogel out:
10508cfa0ad2SJack F Vogel 	return ret_val;
10518cfa0ad2SJack F Vogel }
10528cfa0ad2SJack F Vogel 
10538cfa0ad2SJack F Vogel /**
10548cfa0ad2SJack F Vogel  *  e1000_setup_copper_link_82543 - Configure copper link settings
10558cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
10568cfa0ad2SJack F Vogel  *
10578cfa0ad2SJack F Vogel  *  Configures the link for auto-neg or forced speed and duplex.  Then we check
10588cfa0ad2SJack F Vogel  *  for link, once link is established calls to configure collision distance
10598cfa0ad2SJack F Vogel  *  and flow control are called.
10608cfa0ad2SJack F Vogel  **/
10618cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw)
10628cfa0ad2SJack F Vogel {
10638cfa0ad2SJack F Vogel 	u32 ctrl;
10648cfa0ad2SJack F Vogel 	s32 ret_val;
10658cfa0ad2SJack F Vogel 	bool link;
10668cfa0ad2SJack F Vogel 
10678cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_setup_copper_link_82543");
10688cfa0ad2SJack F Vogel 
10698cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL) | E1000_CTRL_SLU;
10708cfa0ad2SJack F Vogel 	/*
10718cfa0ad2SJack F Vogel 	 * With 82543, we need to force speed and duplex on the MAC
10728cfa0ad2SJack F Vogel 	 * equal to what the PHY speed and duplex configuration is.
10738cfa0ad2SJack F Vogel 	 * In addition, we need to perform a hardware reset on the
10748cfa0ad2SJack F Vogel 	 * PHY to take it out of reset.
10758cfa0ad2SJack F Vogel 	 */
10768cfa0ad2SJack F Vogel 	if (hw->mac.type == e1000_82543) {
10778cfa0ad2SJack F Vogel 		ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
10788cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
10798cfa0ad2SJack F Vogel 		ret_val = hw->phy.ops.reset(hw);
10808cfa0ad2SJack F Vogel 		if (ret_val)
10818cfa0ad2SJack F Vogel 			goto out;
10828cfa0ad2SJack F Vogel 	} else {
10838cfa0ad2SJack F Vogel 		ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
10848cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
10858cfa0ad2SJack F Vogel 	}
10868cfa0ad2SJack F Vogel 
10878cfa0ad2SJack F Vogel 	/* Set MDI/MDI-X, Polarity Reversal, and downshift settings */
10888cfa0ad2SJack F Vogel 	ret_val = e1000_copper_link_setup_m88(hw);
10898cfa0ad2SJack F Vogel 	if (ret_val)
10908cfa0ad2SJack F Vogel 		goto out;
10918cfa0ad2SJack F Vogel 
10928cfa0ad2SJack F Vogel 	if (hw->mac.autoneg) {
10938cfa0ad2SJack F Vogel 		/*
10948cfa0ad2SJack F Vogel 		 * Setup autoneg and flow control advertisement and perform
10958cfa0ad2SJack F Vogel 		 * autonegotiation.
10968cfa0ad2SJack F Vogel 		 */
10978cfa0ad2SJack F Vogel 		ret_val = e1000_copper_link_autoneg(hw);
10988cfa0ad2SJack F Vogel 		if (ret_val)
10998cfa0ad2SJack F Vogel 			goto out;
11008cfa0ad2SJack F Vogel 	} else {
11018cfa0ad2SJack F Vogel 		/*
11028cfa0ad2SJack F Vogel 		 * PHY will be set to 10H, 10F, 100H or 100F
11038cfa0ad2SJack F Vogel 		 * depending on user settings.
11048cfa0ad2SJack F Vogel 		 */
11058cfa0ad2SJack F Vogel 		DEBUGOUT("Forcing Speed and Duplex\n");
11068cfa0ad2SJack F Vogel 		ret_val = e1000_phy_force_speed_duplex_82543(hw);
11078cfa0ad2SJack F Vogel 		if (ret_val) {
11088cfa0ad2SJack F Vogel 			DEBUGOUT("Error Forcing Speed and Duplex\n");
11098cfa0ad2SJack F Vogel 			goto out;
11108cfa0ad2SJack F Vogel 		}
11118cfa0ad2SJack F Vogel 	}
11128cfa0ad2SJack F Vogel 
11138cfa0ad2SJack F Vogel 	/*
11148cfa0ad2SJack F Vogel 	 * Check link status. Wait up to 100 microseconds for link to become
11158cfa0ad2SJack F Vogel 	 * valid.
11168cfa0ad2SJack F Vogel 	 */
111748600901SSean Bruno 	ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
11188cfa0ad2SJack F Vogel 					     &link);
11198cfa0ad2SJack F Vogel 	if (ret_val)
11208cfa0ad2SJack F Vogel 		goto out;
11218cfa0ad2SJack F Vogel 
11228cfa0ad2SJack F Vogel 
11238cfa0ad2SJack F Vogel 	if (link) {
11248cfa0ad2SJack F Vogel 		DEBUGOUT("Valid link established!!!\n");
11258cfa0ad2SJack F Vogel 		/* Config the MAC and PHY after link is up */
11268cfa0ad2SJack F Vogel 		if (hw->mac.type == e1000_82544) {
1127ab5d0362SJack F Vogel 			hw->mac.ops.config_collision_dist(hw);
11288cfa0ad2SJack F Vogel 		} else {
11298cfa0ad2SJack F Vogel 			ret_val = e1000_config_mac_to_phy_82543(hw);
11308cfa0ad2SJack F Vogel 			if (ret_val)
11318cfa0ad2SJack F Vogel 				goto out;
11328cfa0ad2SJack F Vogel 		}
11338cfa0ad2SJack F Vogel 		ret_val = e1000_config_fc_after_link_up_generic(hw);
11348cfa0ad2SJack F Vogel 	} else {
11358cfa0ad2SJack F Vogel 		DEBUGOUT("Unable to establish link!!!\n");
11368cfa0ad2SJack F Vogel 	}
11378cfa0ad2SJack F Vogel 
11388cfa0ad2SJack F Vogel out:
11398cfa0ad2SJack F Vogel 	return ret_val;
11408cfa0ad2SJack F Vogel }
11418cfa0ad2SJack F Vogel 
11428cfa0ad2SJack F Vogel /**
11438cfa0ad2SJack F Vogel  *  e1000_setup_fiber_link_82543 - Setup link for fiber
11448cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
11458cfa0ad2SJack F Vogel  *
11468cfa0ad2SJack F Vogel  *  Configures collision distance and flow control for fiber links.  Upon
11478cfa0ad2SJack F Vogel  *  successful setup, poll for link.
11488cfa0ad2SJack F Vogel  **/
11498cfa0ad2SJack F Vogel static s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw)
11508cfa0ad2SJack F Vogel {
11518cfa0ad2SJack F Vogel 	u32 ctrl;
11528cfa0ad2SJack F Vogel 	s32 ret_val;
11538cfa0ad2SJack F Vogel 
11548cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_setup_fiber_link_82543");
11558cfa0ad2SJack F Vogel 
11568cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
11578cfa0ad2SJack F Vogel 
11588cfa0ad2SJack F Vogel 	/* Take the link out of reset */
11598cfa0ad2SJack F Vogel 	ctrl &= ~E1000_CTRL_LRST;
11608cfa0ad2SJack F Vogel 
1161ab5d0362SJack F Vogel 	hw->mac.ops.config_collision_dist(hw);
11628cfa0ad2SJack F Vogel 
11638cfa0ad2SJack F Vogel 	ret_val = e1000_commit_fc_settings_generic(hw);
11648cfa0ad2SJack F Vogel 	if (ret_val)
11658cfa0ad2SJack F Vogel 		goto out;
11668cfa0ad2SJack F Vogel 
11678cfa0ad2SJack F Vogel 	DEBUGOUT("Auto-negotiation enabled\n");
11688cfa0ad2SJack F Vogel 
11698cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
11708cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
11718cfa0ad2SJack F Vogel 	msec_delay(1);
11728cfa0ad2SJack F Vogel 
11738cfa0ad2SJack F Vogel 	/*
11748cfa0ad2SJack F Vogel 	 * For these adapters, the SW definable pin 1 is cleared when the
11758cfa0ad2SJack F Vogel 	 * optics detect a signal.  If we have a signal, then poll for a
11768cfa0ad2SJack F Vogel 	 * "Link-Up" indication.
11778cfa0ad2SJack F Vogel 	 */
117848600901SSean Bruno 	if (!(E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1))
11798cfa0ad2SJack F Vogel 		ret_val = e1000_poll_fiber_serdes_link_generic(hw);
118048600901SSean Bruno 	else
11818cfa0ad2SJack F Vogel 		DEBUGOUT("No signal detected\n");
11828cfa0ad2SJack F Vogel 
11838cfa0ad2SJack F Vogel out:
11848cfa0ad2SJack F Vogel 	return ret_val;
11858cfa0ad2SJack F Vogel }
11868cfa0ad2SJack F Vogel 
11878cfa0ad2SJack F Vogel /**
11888cfa0ad2SJack F Vogel  *  e1000_check_for_copper_link_82543 - Check for link (Copper)
11898cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
11908cfa0ad2SJack F Vogel  *
11918cfa0ad2SJack F Vogel  *  Checks the phy for link, if link exists, do the following:
11928cfa0ad2SJack F Vogel  *   - check for downshift
11938cfa0ad2SJack F Vogel  *   - do polarity workaround (if necessary)
11948cfa0ad2SJack F Vogel  *   - configure collision distance
11958cfa0ad2SJack F Vogel  *   - configure flow control after link up
11968cfa0ad2SJack F Vogel  *   - configure tbi compatibility
11978cfa0ad2SJack F Vogel  **/
11988cfa0ad2SJack F Vogel static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw)
11998cfa0ad2SJack F Vogel {
12008cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
12018cfa0ad2SJack F Vogel 	u32 icr, rctl;
12028cfa0ad2SJack F Vogel 	s32 ret_val;
12038cfa0ad2SJack F Vogel 	u16 speed, duplex;
12048cfa0ad2SJack F Vogel 	bool link;
12058cfa0ad2SJack F Vogel 
12068cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_check_for_copper_link_82543");
12078cfa0ad2SJack F Vogel 
12088cfa0ad2SJack F Vogel 	if (!mac->get_link_status) {
12098cfa0ad2SJack F Vogel 		ret_val = E1000_SUCCESS;
12108cfa0ad2SJack F Vogel 		goto out;
12118cfa0ad2SJack F Vogel 	}
12128cfa0ad2SJack F Vogel 
12138cfa0ad2SJack F Vogel 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
12148cfa0ad2SJack F Vogel 	if (ret_val)
12158cfa0ad2SJack F Vogel 		goto out;
12168cfa0ad2SJack F Vogel 
12178cfa0ad2SJack F Vogel 	if (!link)
12188cfa0ad2SJack F Vogel 		goto out; /* No link detected */
12198cfa0ad2SJack F Vogel 
12208cfa0ad2SJack F Vogel 	mac->get_link_status = FALSE;
12218cfa0ad2SJack F Vogel 
12228cfa0ad2SJack F Vogel 	e1000_check_downshift_generic(hw);
12238cfa0ad2SJack F Vogel 
12248cfa0ad2SJack F Vogel 	/*
12258cfa0ad2SJack F Vogel 	 * If we are forcing speed/duplex, then we can return since
12268cfa0ad2SJack F Vogel 	 * we have already determined whether we have link or not.
12278cfa0ad2SJack F Vogel 	 */
12288cfa0ad2SJack F Vogel 	if (!mac->autoneg) {
12298cfa0ad2SJack F Vogel 		/*
12308cfa0ad2SJack F Vogel 		 * If speed and duplex are forced to 10H or 10F, then we will
12318cfa0ad2SJack F Vogel 		 * implement the polarity reversal workaround.  We disable
12328cfa0ad2SJack F Vogel 		 * interrupts first, and upon returning, place the devices
12338cfa0ad2SJack F Vogel 		 * interrupt state to its previous value except for the link
12348cfa0ad2SJack F Vogel 		 * status change interrupt which will happened due to the
12358cfa0ad2SJack F Vogel 		 * execution of this workaround.
12368cfa0ad2SJack F Vogel 		 */
12378cfa0ad2SJack F Vogel 		if (mac->forced_speed_duplex & E1000_ALL_10_SPEED) {
12388cfa0ad2SJack F Vogel 			E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
12398cfa0ad2SJack F Vogel 			ret_val = e1000_polarity_reversal_workaround_82543(hw);
12408cfa0ad2SJack F Vogel 			icr = E1000_READ_REG(hw, E1000_ICR);
12418cfa0ad2SJack F Vogel 			E1000_WRITE_REG(hw, E1000_ICS, (icr & ~E1000_ICS_LSC));
12428cfa0ad2SJack F Vogel 			E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK);
12438cfa0ad2SJack F Vogel 		}
12448cfa0ad2SJack F Vogel 
12458cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_CONFIG;
12468cfa0ad2SJack F Vogel 		goto out;
12478cfa0ad2SJack F Vogel 	}
12488cfa0ad2SJack F Vogel 
12498cfa0ad2SJack F Vogel 	/*
12508cfa0ad2SJack F Vogel 	 * We have a M88E1000 PHY and Auto-Neg is enabled.  If we
12518cfa0ad2SJack F Vogel 	 * have Si on board that is 82544 or newer, Auto
12528cfa0ad2SJack F Vogel 	 * Speed Detection takes care of MAC speed/duplex
12538cfa0ad2SJack F Vogel 	 * configuration.  So we only need to configure Collision
12548cfa0ad2SJack F Vogel 	 * Distance in the MAC.  Otherwise, we need to force
12558cfa0ad2SJack F Vogel 	 * speed/duplex on the MAC to the current PHY speed/duplex
12568cfa0ad2SJack F Vogel 	 * settings.
12578cfa0ad2SJack F Vogel 	 */
12588cfa0ad2SJack F Vogel 	if (mac->type == e1000_82544)
1259ab5d0362SJack F Vogel 		hw->mac.ops.config_collision_dist(hw);
12608cfa0ad2SJack F Vogel 	else {
12618cfa0ad2SJack F Vogel 		ret_val = e1000_config_mac_to_phy_82543(hw);
12628cfa0ad2SJack F Vogel 		if (ret_val) {
12638cfa0ad2SJack F Vogel 			DEBUGOUT("Error configuring MAC to PHY settings\n");
12648cfa0ad2SJack F Vogel 			goto out;
12658cfa0ad2SJack F Vogel 		}
12668cfa0ad2SJack F Vogel 	}
12678cfa0ad2SJack F Vogel 
12688cfa0ad2SJack F Vogel 	/*
12698cfa0ad2SJack F Vogel 	 * Configure Flow Control now that Auto-Neg has completed.
12708cfa0ad2SJack F Vogel 	 * First, we need to restore the desired flow control
12718cfa0ad2SJack F Vogel 	 * settings because we may have had to re-autoneg with a
12728cfa0ad2SJack F Vogel 	 * different link partner.
12738cfa0ad2SJack F Vogel 	 */
12748cfa0ad2SJack F Vogel 	ret_val = e1000_config_fc_after_link_up_generic(hw);
127548600901SSean Bruno 	if (ret_val)
12768cfa0ad2SJack F Vogel 		DEBUGOUT("Error configuring flow control\n");
12778cfa0ad2SJack F Vogel 
12788cfa0ad2SJack F Vogel 	/*
12798cfa0ad2SJack F Vogel 	 * At this point we know that we are on copper and we have
12808cfa0ad2SJack F Vogel 	 * auto-negotiated link.  These are conditions for checking the link
12818cfa0ad2SJack F Vogel 	 * partner capability register.  We use the link speed to determine if
12828cfa0ad2SJack F Vogel 	 * TBI compatibility needs to be turned on or off.  If the link is not
12838cfa0ad2SJack F Vogel 	 * at gigabit speed, then TBI compatibility is not needed.  If we are
12848cfa0ad2SJack F Vogel 	 * at gigabit speed, we turn on TBI compatibility.
12858cfa0ad2SJack F Vogel 	 */
12868cfa0ad2SJack F Vogel 	if (e1000_tbi_compatibility_enabled_82543(hw)) {
12878cfa0ad2SJack F Vogel 		ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
12888cfa0ad2SJack F Vogel 		if (ret_val) {
12898cfa0ad2SJack F Vogel 			DEBUGOUT("Error getting link speed and duplex\n");
12908cfa0ad2SJack F Vogel 			return ret_val;
12918cfa0ad2SJack F Vogel 		}
12928cfa0ad2SJack F Vogel 		if (speed != SPEED_1000) {
12938cfa0ad2SJack F Vogel 			/*
12948cfa0ad2SJack F Vogel 			 * If link speed is not set to gigabit speed,
12958cfa0ad2SJack F Vogel 			 * we do not need to enable TBI compatibility.
12968cfa0ad2SJack F Vogel 			 */
12978cfa0ad2SJack F Vogel 			if (e1000_tbi_sbp_enabled_82543(hw)) {
12988cfa0ad2SJack F Vogel 				/*
12998cfa0ad2SJack F Vogel 				 * If we previously were in the mode,
13008cfa0ad2SJack F Vogel 				 * turn it off.
13018cfa0ad2SJack F Vogel 				 */
13028cfa0ad2SJack F Vogel 				e1000_set_tbi_sbp_82543(hw, FALSE);
13038cfa0ad2SJack F Vogel 				rctl = E1000_READ_REG(hw, E1000_RCTL);
13048cfa0ad2SJack F Vogel 				rctl &= ~E1000_RCTL_SBP;
13058cfa0ad2SJack F Vogel 				E1000_WRITE_REG(hw, E1000_RCTL, rctl);
13068cfa0ad2SJack F Vogel 			}
13078cfa0ad2SJack F Vogel 		} else {
13088cfa0ad2SJack F Vogel 			/*
13098cfa0ad2SJack F Vogel 			 * If TBI compatibility is was previously off,
13108cfa0ad2SJack F Vogel 			 * turn it on. For compatibility with a TBI link
13118cfa0ad2SJack F Vogel 			 * partner, we will store bad packets. Some
13128cfa0ad2SJack F Vogel 			 * frames have an additional byte on the end and
13138cfa0ad2SJack F Vogel 			 * will look like CRC errors to to the hardware.
13148cfa0ad2SJack F Vogel 			 */
13158cfa0ad2SJack F Vogel 			if (!e1000_tbi_sbp_enabled_82543(hw)) {
13168cfa0ad2SJack F Vogel 				e1000_set_tbi_sbp_82543(hw, TRUE);
13178cfa0ad2SJack F Vogel 				rctl = E1000_READ_REG(hw, E1000_RCTL);
13188cfa0ad2SJack F Vogel 				rctl |= E1000_RCTL_SBP;
13198cfa0ad2SJack F Vogel 				E1000_WRITE_REG(hw, E1000_RCTL, rctl);
13208cfa0ad2SJack F Vogel 			}
13218cfa0ad2SJack F Vogel 		}
13228cfa0ad2SJack F Vogel 	}
13238cfa0ad2SJack F Vogel out:
13248cfa0ad2SJack F Vogel 	return ret_val;
13258cfa0ad2SJack F Vogel }
13268cfa0ad2SJack F Vogel 
13278cfa0ad2SJack F Vogel /**
13288cfa0ad2SJack F Vogel  *  e1000_check_for_fiber_link_82543 - Check for link (Fiber)
13298cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
13308cfa0ad2SJack F Vogel  *
13318cfa0ad2SJack F Vogel  *  Checks for link up on the hardware.  If link is not up and we have
13328cfa0ad2SJack F Vogel  *  a signal, then we need to force link up.
13338cfa0ad2SJack F Vogel  **/
13348cfa0ad2SJack F Vogel static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw)
13358cfa0ad2SJack F Vogel {
13368cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
13378cfa0ad2SJack F Vogel 	u32 rxcw, ctrl, status;
13388cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
13398cfa0ad2SJack F Vogel 
13408cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_check_for_fiber_link_82543");
13418cfa0ad2SJack F Vogel 
13428cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
13438cfa0ad2SJack F Vogel 	status = E1000_READ_REG(hw, E1000_STATUS);
13448cfa0ad2SJack F Vogel 	rxcw = E1000_READ_REG(hw, E1000_RXCW);
13458cfa0ad2SJack F Vogel 
13468cfa0ad2SJack F Vogel 	/*
13478cfa0ad2SJack F Vogel 	 * If we don't have link (auto-negotiation failed or link partner
13488cfa0ad2SJack F Vogel 	 * cannot auto-negotiate), the cable is plugged in (we have signal),
13498cfa0ad2SJack F Vogel 	 * and our link partner is not trying to auto-negotiate with us (we
13508cfa0ad2SJack F Vogel 	 * are receiving idles or data), we need to force link up. We also
13518cfa0ad2SJack F Vogel 	 * need to give auto-negotiation time to complete, in case the cable
13528cfa0ad2SJack F Vogel 	 * was just plugged in. The autoneg_failed flag does this.
13538cfa0ad2SJack F Vogel 	 */
13548cfa0ad2SJack F Vogel 	/* (ctrl & E1000_CTRL_SWDPIN1) == 0 == have signal */
13558cfa0ad2SJack F Vogel 	if ((!(ctrl & E1000_CTRL_SWDPIN1)) &&
13568cfa0ad2SJack F Vogel 	    (!(status & E1000_STATUS_LU)) &&
13578cfa0ad2SJack F Vogel 	    (!(rxcw & E1000_RXCW_C))) {
135848600901SSean Bruno 		if (!mac->autoneg_failed) {
135948600901SSean Bruno 			mac->autoneg_failed = TRUE;
13608cfa0ad2SJack F Vogel 			ret_val = 0;
13618cfa0ad2SJack F Vogel 			goto out;
13628cfa0ad2SJack F Vogel 		}
13638cfa0ad2SJack F Vogel 		DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
13648cfa0ad2SJack F Vogel 
13658cfa0ad2SJack F Vogel 		/* Disable auto-negotiation in the TXCW register */
13668cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
13678cfa0ad2SJack F Vogel 
13688cfa0ad2SJack F Vogel 		/* Force link-up and also force full-duplex. */
13698cfa0ad2SJack F Vogel 		ctrl = E1000_READ_REG(hw, E1000_CTRL);
13708cfa0ad2SJack F Vogel 		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
13718cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
13728cfa0ad2SJack F Vogel 
13738cfa0ad2SJack F Vogel 		/* Configure Flow Control after forcing link up. */
13748cfa0ad2SJack F Vogel 		ret_val = e1000_config_fc_after_link_up_generic(hw);
13758cfa0ad2SJack F Vogel 		if (ret_val) {
13768cfa0ad2SJack F Vogel 			DEBUGOUT("Error configuring flow control\n");
13778cfa0ad2SJack F Vogel 			goto out;
13788cfa0ad2SJack F Vogel 		}
13798cfa0ad2SJack F Vogel 	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
13808cfa0ad2SJack F Vogel 		/*
13818cfa0ad2SJack F Vogel 		 * If we are forcing link and we are receiving /C/ ordered
13828cfa0ad2SJack F Vogel 		 * sets, re-enable auto-negotiation in the TXCW register
13838cfa0ad2SJack F Vogel 		 * and disable forced link in the Device Control register
13848cfa0ad2SJack F Vogel 		 * in an attempt to auto-negotiate with our link partner.
13858cfa0ad2SJack F Vogel 		 */
13868cfa0ad2SJack F Vogel 		DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
13878cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
13888cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
13898cfa0ad2SJack F Vogel 
13908cfa0ad2SJack F Vogel 		mac->serdes_has_link = TRUE;
13918cfa0ad2SJack F Vogel 	}
13928cfa0ad2SJack F Vogel 
13938cfa0ad2SJack F Vogel out:
13948cfa0ad2SJack F Vogel 	return ret_val;
13958cfa0ad2SJack F Vogel }
13968cfa0ad2SJack F Vogel 
13978cfa0ad2SJack F Vogel /**
13988cfa0ad2SJack F Vogel  *  e1000_config_mac_to_phy_82543 - Configure MAC to PHY settings
13998cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
14008cfa0ad2SJack F Vogel  *
14018cfa0ad2SJack F Vogel  *  For the 82543 silicon, we need to set the MAC to match the settings
14028cfa0ad2SJack F Vogel  *  of the PHY, even if the PHY is auto-negotiating.
14038cfa0ad2SJack F Vogel  **/
14048cfa0ad2SJack F Vogel static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw)
14058cfa0ad2SJack F Vogel {
14068cfa0ad2SJack F Vogel 	u32 ctrl;
14078cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
14088cfa0ad2SJack F Vogel 	u16 phy_data;
14098cfa0ad2SJack F Vogel 
14108cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_config_mac_to_phy_82543");
14118cfa0ad2SJack F Vogel 
14128cfa0ad2SJack F Vogel 	if (!(hw->phy.ops.read_reg))
14138cfa0ad2SJack F Vogel 		goto out;
14148cfa0ad2SJack F Vogel 
14158cfa0ad2SJack F Vogel 	/* Set the bits to force speed and duplex */
14168cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
14178cfa0ad2SJack F Vogel 	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
14188cfa0ad2SJack F Vogel 	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
14198cfa0ad2SJack F Vogel 
14208cfa0ad2SJack F Vogel 	/*
14218cfa0ad2SJack F Vogel 	 * Set up duplex in the Device Control and Transmit Control
14228cfa0ad2SJack F Vogel 	 * registers depending on negotiated values.
14238cfa0ad2SJack F Vogel 	 */
14248cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
14258cfa0ad2SJack F Vogel 	if (ret_val)
14268cfa0ad2SJack F Vogel 		goto out;
14278cfa0ad2SJack F Vogel 
14288cfa0ad2SJack F Vogel 	ctrl &= ~E1000_CTRL_FD;
14298cfa0ad2SJack F Vogel 	if (phy_data & M88E1000_PSSR_DPLX)
14308cfa0ad2SJack F Vogel 		ctrl |= E1000_CTRL_FD;
14318cfa0ad2SJack F Vogel 
1432ab5d0362SJack F Vogel 	hw->mac.ops.config_collision_dist(hw);
14338cfa0ad2SJack F Vogel 
14348cfa0ad2SJack F Vogel 	/*
14358cfa0ad2SJack F Vogel 	 * Set up speed in the Device Control register depending on
14368cfa0ad2SJack F Vogel 	 * negotiated values.
14378cfa0ad2SJack F Vogel 	 */
14388cfa0ad2SJack F Vogel 	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
14398cfa0ad2SJack F Vogel 		ctrl |= E1000_CTRL_SPD_1000;
14408cfa0ad2SJack F Vogel 	else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
14418cfa0ad2SJack F Vogel 		ctrl |= E1000_CTRL_SPD_100;
14428cfa0ad2SJack F Vogel 
14438cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
14448cfa0ad2SJack F Vogel 
14458cfa0ad2SJack F Vogel out:
14468cfa0ad2SJack F Vogel 	return ret_val;
14478cfa0ad2SJack F Vogel }
14488cfa0ad2SJack F Vogel 
14498cfa0ad2SJack F Vogel /**
14508cfa0ad2SJack F Vogel  *  e1000_write_vfta_82543 - Write value to VLAN filter table
14518cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
14528cfa0ad2SJack F Vogel  *  @offset: the 32-bit offset in which to write the value to.
14538cfa0ad2SJack F Vogel  *  @value: the 32-bit value to write at location offset.
14548cfa0ad2SJack F Vogel  *
14558cfa0ad2SJack F Vogel  *  This writes a 32-bit value to a 32-bit offset in the VLAN filter
14568cfa0ad2SJack F Vogel  *  table.
14578cfa0ad2SJack F Vogel  **/
14588cfa0ad2SJack F Vogel static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value)
14598cfa0ad2SJack F Vogel {
14608cfa0ad2SJack F Vogel 	u32 temp;
14618cfa0ad2SJack F Vogel 
14628cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_write_vfta_82543");
14638cfa0ad2SJack F Vogel 
14648cfa0ad2SJack F Vogel 	if ((hw->mac.type == e1000_82544) && (offset & 1)) {
14658cfa0ad2SJack F Vogel 		temp = E1000_READ_REG_ARRAY(hw, E1000_VFTA, offset - 1);
14668cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
14678cfa0ad2SJack F Vogel 		E1000_WRITE_FLUSH(hw);
14688cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset - 1, temp);
14698cfa0ad2SJack F Vogel 		E1000_WRITE_FLUSH(hw);
14708cfa0ad2SJack F Vogel 	} else {
14718cfa0ad2SJack F Vogel 		e1000_write_vfta_generic(hw, offset, value);
14728cfa0ad2SJack F Vogel 	}
14738cfa0ad2SJack F Vogel }
14748cfa0ad2SJack F Vogel 
14758cfa0ad2SJack F Vogel /**
14768cfa0ad2SJack F Vogel  *  e1000_led_on_82543 - Turn on SW controllable LED
14778cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
14788cfa0ad2SJack F Vogel  *
1479daf9197cSJack F Vogel  *  Turns the SW defined LED on.
14808cfa0ad2SJack F Vogel  **/
14818cfa0ad2SJack F Vogel static s32 e1000_led_on_82543(struct e1000_hw *hw)
14828cfa0ad2SJack F Vogel {
14838cfa0ad2SJack F Vogel 	u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
14848cfa0ad2SJack F Vogel 
14858cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_led_on_82543");
14868cfa0ad2SJack F Vogel 
14878cfa0ad2SJack F Vogel 	if (hw->mac.type == e1000_82544 &&
14888cfa0ad2SJack F Vogel 	    hw->phy.media_type == e1000_media_type_copper) {
14898cfa0ad2SJack F Vogel 		/* Clear SW-definable Pin 0 to turn on the LED */
14908cfa0ad2SJack F Vogel 		ctrl &= ~E1000_CTRL_SWDPIN0;
14918cfa0ad2SJack F Vogel 		ctrl |= E1000_CTRL_SWDPIO0;
14928cfa0ad2SJack F Vogel 	} else {
14938cfa0ad2SJack F Vogel 		/* Fiber 82544 and all 82543 use this method */
14948cfa0ad2SJack F Vogel 		ctrl |= E1000_CTRL_SWDPIN0;
14958cfa0ad2SJack F Vogel 		ctrl |= E1000_CTRL_SWDPIO0;
14968cfa0ad2SJack F Vogel 	}
14978cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
14988cfa0ad2SJack F Vogel 
14998cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
15008cfa0ad2SJack F Vogel }
15018cfa0ad2SJack F Vogel 
15028cfa0ad2SJack F Vogel /**
15038cfa0ad2SJack F Vogel  *  e1000_led_off_82543 - Turn off SW controllable LED
15048cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
15058cfa0ad2SJack F Vogel  *
1506daf9197cSJack F Vogel  *  Turns the SW defined LED off.
15078cfa0ad2SJack F Vogel  **/
15088cfa0ad2SJack F Vogel static s32 e1000_led_off_82543(struct e1000_hw *hw)
15098cfa0ad2SJack F Vogel {
15108cfa0ad2SJack F Vogel 	u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
15118cfa0ad2SJack F Vogel 
15128cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_led_off_82543");
15138cfa0ad2SJack F Vogel 
15148cfa0ad2SJack F Vogel 	if (hw->mac.type == e1000_82544 &&
15158cfa0ad2SJack F Vogel 	    hw->phy.media_type == e1000_media_type_copper) {
15168cfa0ad2SJack F Vogel 		/* Set SW-definable Pin 0 to turn off the LED */
15178cfa0ad2SJack F Vogel 		ctrl |= E1000_CTRL_SWDPIN0;
15188cfa0ad2SJack F Vogel 		ctrl |= E1000_CTRL_SWDPIO0;
15198cfa0ad2SJack F Vogel 	} else {
15208cfa0ad2SJack F Vogel 		ctrl &= ~E1000_CTRL_SWDPIN0;
15218cfa0ad2SJack F Vogel 		ctrl |= E1000_CTRL_SWDPIO0;
15228cfa0ad2SJack F Vogel 	}
15238cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
15248cfa0ad2SJack F Vogel 
15258cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
15268cfa0ad2SJack F Vogel }
15278cfa0ad2SJack F Vogel 
15288cfa0ad2SJack F Vogel /**
15298cfa0ad2SJack F Vogel  *  e1000_clear_hw_cntrs_82543 - Clear device specific hardware counters
15308cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
15318cfa0ad2SJack F Vogel  *
15328cfa0ad2SJack F Vogel  *  Clears the hardware counters by reading the counter registers.
15338cfa0ad2SJack F Vogel  **/
15348cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw)
15358cfa0ad2SJack F Vogel {
15368cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_clear_hw_cntrs_82543");
15378cfa0ad2SJack F Vogel 
15388cfa0ad2SJack F Vogel 	e1000_clear_hw_cntrs_base_generic(hw);
15398cfa0ad2SJack F Vogel 
1540daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC64);
1541daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC127);
1542daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC255);
1543daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC511);
1544daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC1023);
1545daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC1522);
1546daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC64);
1547daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC127);
1548daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC255);
1549daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC511);
1550daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC1023);
1551daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC1522);
15528cfa0ad2SJack F Vogel 
1553daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ALGNERRC);
1554daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_RXERRC);
1555daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TNCRS);
1556daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_CEXTERR);
1557daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TSCTC);
1558daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TSCTFC);
15598cfa0ad2SJack F Vogel }
156074dbc418SJack F Vogel 
156174dbc418SJack F Vogel /**
156274dbc418SJack F Vogel  *  e1000_read_mac_addr_82543 - Read device MAC address
156374dbc418SJack F Vogel  *  @hw: pointer to the HW structure
156474dbc418SJack F Vogel  *
156574dbc418SJack F Vogel  *  Reads the device MAC address from the EEPROM and stores the value.
156674dbc418SJack F Vogel  *  Since devices with two ports use the same EEPROM, we increment the
156774dbc418SJack F Vogel  *  last bit in the MAC address for the second port.
156874dbc418SJack F Vogel  *
156974dbc418SJack F Vogel  **/
157074dbc418SJack F Vogel s32 e1000_read_mac_addr_82543(struct e1000_hw *hw)
157174dbc418SJack F Vogel {
157274dbc418SJack F Vogel 	s32  ret_val = E1000_SUCCESS;
157374dbc418SJack F Vogel 	u16 offset, nvm_data, i;
157474dbc418SJack F Vogel 
157574dbc418SJack F Vogel 	DEBUGFUNC("e1000_read_mac_addr");
157674dbc418SJack F Vogel 
157774dbc418SJack F Vogel 	for (i = 0; i < ETH_ADDR_LEN; i += 2) {
157874dbc418SJack F Vogel 		offset = i >> 1;
157974dbc418SJack F Vogel 		ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
158074dbc418SJack F Vogel 		if (ret_val) {
158174dbc418SJack F Vogel 			DEBUGOUT("NVM Read Error\n");
158274dbc418SJack F Vogel 			goto out;
158374dbc418SJack F Vogel 		}
158474dbc418SJack F Vogel 		hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
158574dbc418SJack F Vogel 		hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
158674dbc418SJack F Vogel 	}
158774dbc418SJack F Vogel 
158874dbc418SJack F Vogel 	/* Flip last bit of mac address if we're on second port */
158974dbc418SJack F Vogel 	if (hw->bus.func == E1000_FUNC_1)
159074dbc418SJack F Vogel 		hw->mac.perm_addr[5] ^= 1;
159174dbc418SJack F Vogel 
159274dbc418SJack F Vogel 	for (i = 0; i < ETH_ADDR_LEN; i++)
159374dbc418SJack F Vogel 		hw->mac.addr[i] = hw->mac.perm_addr[i];
159474dbc418SJack F Vogel 
159574dbc418SJack F Vogel out:
159674dbc418SJack F Vogel 	return ret_val;
159774dbc418SJack F Vogel }
1598