xref: /freebsd/sys/dev/e1000/e1000_82540.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 
35daf9197cSJack F Vogel /*
36daf9197cSJack F Vogel  * 82540EM Gigabit Ethernet Controller
37daf9197cSJack F Vogel  * 82540EP Gigabit Ethernet Controller
38daf9197cSJack F Vogel  * 82545EM Gigabit Ethernet Controller (Copper)
39daf9197cSJack F Vogel  * 82545EM Gigabit Ethernet Controller (Fiber)
40daf9197cSJack F Vogel  * 82545GM Gigabit Ethernet Controller
41daf9197cSJack F Vogel  * 82546EB Gigabit Ethernet Controller (Copper)
42daf9197cSJack F Vogel  * 82546EB Gigabit Ethernet Controller (Fiber)
43daf9197cSJack F Vogel  * 82546GB Gigabit Ethernet Controller
448cfa0ad2SJack F Vogel  */
458cfa0ad2SJack F Vogel 
468cfa0ad2SJack F Vogel #include "e1000_api.h"
478cfa0ad2SJack F Vogel 
488cfa0ad2SJack F Vogel static s32  e1000_init_phy_params_82540(struct e1000_hw *hw);
498cfa0ad2SJack F Vogel static s32  e1000_init_nvm_params_82540(struct e1000_hw *hw);
508cfa0ad2SJack F Vogel static s32  e1000_init_mac_params_82540(struct e1000_hw *hw);
518cfa0ad2SJack F Vogel static s32  e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw);
528cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw);
538cfa0ad2SJack F Vogel static s32  e1000_init_hw_82540(struct e1000_hw *hw);
548cfa0ad2SJack F Vogel static s32  e1000_reset_hw_82540(struct e1000_hw *hw);
558cfa0ad2SJack F Vogel static s32  e1000_set_phy_mode_82540(struct e1000_hw *hw);
568cfa0ad2SJack F Vogel static s32  e1000_set_vco_speed_82540(struct e1000_hw *hw);
578cfa0ad2SJack F Vogel static s32  e1000_setup_copper_link_82540(struct e1000_hw *hw);
588cfa0ad2SJack F Vogel static s32  e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw);
598cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw);
609d81738fSJack F Vogel static s32  e1000_read_mac_addr_82540(struct e1000_hw *hw);
618cfa0ad2SJack F Vogel 
628cfa0ad2SJack F Vogel /**
638cfa0ad2SJack F Vogel  * e1000_init_phy_params_82540 - Init PHY func ptrs.
648cfa0ad2SJack F Vogel  * @hw: pointer to the HW structure
658cfa0ad2SJack F Vogel  **/
e1000_init_phy_params_82540(struct e1000_hw * hw)668cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82540(struct e1000_hw *hw)
678cfa0ad2SJack F Vogel {
688cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
69c80429ceSEric Joyner 	s32 ret_val;
708cfa0ad2SJack F Vogel 
718cfa0ad2SJack F Vogel 	phy->addr		= 1;
728cfa0ad2SJack F Vogel 	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
738cfa0ad2SJack F Vogel 	phy->reset_delay_us	= 10000;
748cfa0ad2SJack F Vogel 	phy->type		= e1000_phy_m88;
758cfa0ad2SJack F Vogel 
768cfa0ad2SJack F Vogel 	/* Function Pointers */
778cfa0ad2SJack F Vogel 	phy->ops.check_polarity	= e1000_check_polarity_m88;
788cfa0ad2SJack F Vogel 	phy->ops.commit		= e1000_phy_sw_reset_generic;
798cfa0ad2SJack F Vogel 	phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
808cfa0ad2SJack F Vogel 	phy->ops.get_cable_length = e1000_get_cable_length_m88;
818cfa0ad2SJack F Vogel 	phy->ops.get_cfg_done	= e1000_get_cfg_done_generic;
828cfa0ad2SJack F Vogel 	phy->ops.read_reg	= e1000_read_phy_reg_m88;
838cfa0ad2SJack F Vogel 	phy->ops.reset		= e1000_phy_hw_reset_generic;
848cfa0ad2SJack F Vogel 	phy->ops.write_reg	= e1000_write_phy_reg_m88;
858cfa0ad2SJack F Vogel 	phy->ops.get_info	= e1000_get_phy_info_m88;
868cfa0ad2SJack F Vogel 	phy->ops.power_up	= e1000_power_up_phy_copper;
878cfa0ad2SJack F Vogel 	phy->ops.power_down	= e1000_power_down_phy_copper_82540;
888cfa0ad2SJack F Vogel 
898cfa0ad2SJack F Vogel 	ret_val = e1000_get_phy_id(hw);
908cfa0ad2SJack F Vogel 	if (ret_val)
918cfa0ad2SJack F Vogel 		goto out;
928cfa0ad2SJack F Vogel 
938cfa0ad2SJack F Vogel 	/* Verify phy id */
948cfa0ad2SJack F Vogel 	switch (hw->mac.type) {
958cfa0ad2SJack F Vogel 	case e1000_82540:
968cfa0ad2SJack F Vogel 	case e1000_82545:
978cfa0ad2SJack F Vogel 	case e1000_82545_rev_3:
988cfa0ad2SJack F Vogel 	case e1000_82546:
998cfa0ad2SJack F Vogel 	case e1000_82546_rev_3:
1008cfa0ad2SJack F Vogel 		if (phy->id == M88E1011_I_PHY_ID)
1018cfa0ad2SJack F Vogel 			break;
102*e05d9788SKevin Bowling 		/* FALLTHROUGH */
1038cfa0ad2SJack F Vogel 	default:
1048cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PHY;
1058cfa0ad2SJack F Vogel 		goto out;
1068cfa0ad2SJack F Vogel 		break;
1078cfa0ad2SJack F Vogel 	}
1088cfa0ad2SJack F Vogel 
1098cfa0ad2SJack F Vogel out:
1108cfa0ad2SJack F Vogel 	return ret_val;
1118cfa0ad2SJack F Vogel }
1128cfa0ad2SJack F Vogel 
1138cfa0ad2SJack F Vogel /**
1148cfa0ad2SJack F Vogel  * e1000_init_nvm_params_82540 - Init NVM func ptrs.
1158cfa0ad2SJack F Vogel  * @hw: pointer to the HW structure
1168cfa0ad2SJack F Vogel  **/
e1000_init_nvm_params_82540(struct e1000_hw * hw)1178cfa0ad2SJack F Vogel static s32 e1000_init_nvm_params_82540(struct e1000_hw *hw)
1188cfa0ad2SJack F Vogel {
1198cfa0ad2SJack F Vogel 	struct e1000_nvm_info *nvm = &hw->nvm;
1208cfa0ad2SJack F Vogel 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
1218cfa0ad2SJack F Vogel 
1228cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_nvm_params_82540");
1238cfa0ad2SJack F Vogel 
1248cfa0ad2SJack F Vogel 	nvm->type = e1000_nvm_eeprom_microwire;
1258cfa0ad2SJack F Vogel 	nvm->delay_usec = 50;
1268cfa0ad2SJack F Vogel 	nvm->opcode_bits = 3;
1278cfa0ad2SJack F Vogel 	switch (nvm->override) {
1288cfa0ad2SJack F Vogel 	case e1000_nvm_override_microwire_large:
1298cfa0ad2SJack F Vogel 		nvm->address_bits = 8;
1308cfa0ad2SJack F Vogel 		nvm->word_size = 256;
1318cfa0ad2SJack F Vogel 		break;
1328cfa0ad2SJack F Vogel 	case e1000_nvm_override_microwire_small:
1338cfa0ad2SJack F Vogel 		nvm->address_bits = 6;
1348cfa0ad2SJack F Vogel 		nvm->word_size = 64;
1358cfa0ad2SJack F Vogel 		break;
1368cfa0ad2SJack F Vogel 	default:
1378cfa0ad2SJack F Vogel 		nvm->address_bits = eecd & E1000_EECD_SIZE ? 8 : 6;
1388cfa0ad2SJack F Vogel 		nvm->word_size = eecd & E1000_EECD_SIZE ? 256 : 64;
1398cfa0ad2SJack F Vogel 		break;
1408cfa0ad2SJack F Vogel 	}
1418cfa0ad2SJack F Vogel 
1428cfa0ad2SJack F Vogel 	/* Function Pointers */
1438cfa0ad2SJack F Vogel 	nvm->ops.acquire	= e1000_acquire_nvm_generic;
1448cfa0ad2SJack F Vogel 	nvm->ops.read		= e1000_read_nvm_microwire;
1458cfa0ad2SJack F Vogel 	nvm->ops.release	= e1000_release_nvm_generic;
1468cfa0ad2SJack F Vogel 	nvm->ops.update		= e1000_update_nvm_checksum_generic;
1478cfa0ad2SJack F Vogel 	nvm->ops.valid_led_default = e1000_valid_led_default_generic;
1488cfa0ad2SJack F Vogel 	nvm->ops.validate	= e1000_validate_nvm_checksum_generic;
1498cfa0ad2SJack F Vogel 	nvm->ops.write		= e1000_write_nvm_microwire;
1508cfa0ad2SJack F Vogel 
1518cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
1528cfa0ad2SJack F Vogel }
1538cfa0ad2SJack F Vogel 
1548cfa0ad2SJack F Vogel /**
1558cfa0ad2SJack F Vogel  * e1000_init_mac_params_82540 - Init MAC func ptrs.
1568cfa0ad2SJack F Vogel  * @hw: pointer to the HW structure
1578cfa0ad2SJack F Vogel  **/
e1000_init_mac_params_82540(struct e1000_hw * hw)1588cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82540(struct e1000_hw *hw)
1598cfa0ad2SJack F Vogel {
1608cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
1618cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
1628cfa0ad2SJack F Vogel 
1638cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_mac_params_82540");
1648cfa0ad2SJack F Vogel 
1658cfa0ad2SJack F Vogel 	/* Set media type */
1668cfa0ad2SJack F Vogel 	switch (hw->device_id) {
1678cfa0ad2SJack F Vogel 	case E1000_DEV_ID_82545EM_FIBER:
1688cfa0ad2SJack F Vogel 	case E1000_DEV_ID_82545GM_FIBER:
1698cfa0ad2SJack F Vogel 	case E1000_DEV_ID_82546EB_FIBER:
1708cfa0ad2SJack F Vogel 	case E1000_DEV_ID_82546GB_FIBER:
1718cfa0ad2SJack F Vogel 		hw->phy.media_type = e1000_media_type_fiber;
1728cfa0ad2SJack F Vogel 		break;
1738cfa0ad2SJack F Vogel 	case E1000_DEV_ID_82545GM_SERDES:
1748cfa0ad2SJack F Vogel 	case E1000_DEV_ID_82546GB_SERDES:
1758cfa0ad2SJack F Vogel 		hw->phy.media_type = e1000_media_type_internal_serdes;
1768cfa0ad2SJack F Vogel 		break;
1778cfa0ad2SJack F Vogel 	default:
1788cfa0ad2SJack F Vogel 		hw->phy.media_type = e1000_media_type_copper;
1798cfa0ad2SJack F Vogel 		break;
1808cfa0ad2SJack F Vogel 	}
1818cfa0ad2SJack F Vogel 
1828cfa0ad2SJack F Vogel 	/* Set mta register count */
1838cfa0ad2SJack F Vogel 	mac->mta_reg_count = 128;
1848cfa0ad2SJack F Vogel 	/* Set rar entry count */
1858cfa0ad2SJack F Vogel 	mac->rar_entry_count = E1000_RAR_ENTRIES;
1868cfa0ad2SJack F Vogel 
1878cfa0ad2SJack F Vogel 	/* Function pointers */
1888cfa0ad2SJack F Vogel 
1898cfa0ad2SJack F Vogel 	/* bus type/speed/width */
1908cfa0ad2SJack F Vogel 	mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
191daf9197cSJack F Vogel 	/* function id */
192daf9197cSJack F Vogel 	mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
1938cfa0ad2SJack F Vogel 	/* reset */
1948cfa0ad2SJack F Vogel 	mac->ops.reset_hw = e1000_reset_hw_82540;
1958cfa0ad2SJack F Vogel 	/* hw initialization */
1968cfa0ad2SJack F Vogel 	mac->ops.init_hw = e1000_init_hw_82540;
1978cfa0ad2SJack F Vogel 	/* link setup */
1988cfa0ad2SJack F Vogel 	mac->ops.setup_link = e1000_setup_link_generic;
1998cfa0ad2SJack F Vogel 	/* physical interface setup */
2008cfa0ad2SJack F Vogel 	mac->ops.setup_physical_interface =
2018cfa0ad2SJack F Vogel 		(hw->phy.media_type == e1000_media_type_copper)
2028cfa0ad2SJack F Vogel 			? e1000_setup_copper_link_82540
2038cfa0ad2SJack F Vogel 			: e1000_setup_fiber_serdes_link_82540;
2048cfa0ad2SJack F Vogel 	/* check for link */
2058cfa0ad2SJack F Vogel 	switch (hw->phy.media_type) {
2068cfa0ad2SJack F Vogel 	case e1000_media_type_copper:
2078cfa0ad2SJack F Vogel 		mac->ops.check_for_link = e1000_check_for_copper_link_generic;
2088cfa0ad2SJack F Vogel 		break;
2098cfa0ad2SJack F Vogel 	case e1000_media_type_fiber:
2108cfa0ad2SJack F Vogel 		mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
2118cfa0ad2SJack F Vogel 		break;
2128cfa0ad2SJack F Vogel 	case e1000_media_type_internal_serdes:
2138cfa0ad2SJack F Vogel 		mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
2148cfa0ad2SJack F Vogel 		break;
2158cfa0ad2SJack F Vogel 	default:
2168cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_CONFIG;
2178cfa0ad2SJack F Vogel 		goto out;
2188cfa0ad2SJack F Vogel 		break;
2198cfa0ad2SJack F Vogel 	}
2208cfa0ad2SJack F Vogel 	/* link info */
2218cfa0ad2SJack F Vogel 	mac->ops.get_link_up_info =
2228cfa0ad2SJack F Vogel 		(hw->phy.media_type == e1000_media_type_copper)
2238cfa0ad2SJack F Vogel 			? e1000_get_speed_and_duplex_copper_generic
2248cfa0ad2SJack F Vogel 			: e1000_get_speed_and_duplex_fiber_serdes_generic;
2258cfa0ad2SJack F Vogel 	/* multicast address update */
2268cfa0ad2SJack F Vogel 	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
2278cfa0ad2SJack F Vogel 	/* writing VFTA */
2288cfa0ad2SJack F Vogel 	mac->ops.write_vfta = e1000_write_vfta_generic;
2298cfa0ad2SJack F Vogel 	/* clearing VFTA */
2308cfa0ad2SJack F Vogel 	mac->ops.clear_vfta = e1000_clear_vfta_generic;
2319d81738fSJack F Vogel 	/* read mac address */
2329d81738fSJack F Vogel 	mac->ops.read_mac_addr = e1000_read_mac_addr_82540;
233d035aa2dSJack F Vogel 	/* ID LED init */
234d035aa2dSJack F Vogel 	mac->ops.id_led_init = e1000_id_led_init_generic;
2358cfa0ad2SJack F Vogel 	/* setup LED */
2368cfa0ad2SJack F Vogel 	mac->ops.setup_led = e1000_setup_led_generic;
2378cfa0ad2SJack F Vogel 	/* cleanup LED */
2388cfa0ad2SJack F Vogel 	mac->ops.cleanup_led = e1000_cleanup_led_generic;
2398cfa0ad2SJack F Vogel 	/* turn on/off LED */
2408cfa0ad2SJack F Vogel 	mac->ops.led_on = e1000_led_on_generic;
2418cfa0ad2SJack F Vogel 	mac->ops.led_off = e1000_led_off_generic;
2428cfa0ad2SJack F Vogel 	/* clear hardware counters */
2438cfa0ad2SJack F Vogel 	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82540;
2448cfa0ad2SJack F Vogel 
2458cfa0ad2SJack F Vogel out:
2468cfa0ad2SJack F Vogel 	return ret_val;
2478cfa0ad2SJack F Vogel }
2488cfa0ad2SJack F Vogel 
2498cfa0ad2SJack F Vogel /**
2508cfa0ad2SJack F Vogel  * e1000_init_function_pointers_82540 - Init func ptrs.
2518cfa0ad2SJack F Vogel  * @hw: pointer to the HW structure
2528cfa0ad2SJack F Vogel  *
253daf9197cSJack F Vogel  * Called to initialize all function pointers and parameters.
2548cfa0ad2SJack F Vogel  **/
e1000_init_function_pointers_82540(struct e1000_hw * hw)2558cfa0ad2SJack F Vogel void e1000_init_function_pointers_82540(struct e1000_hw *hw)
2568cfa0ad2SJack F Vogel {
2578cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_function_pointers_82540");
2588cfa0ad2SJack F Vogel 
2598cfa0ad2SJack F Vogel 	hw->mac.ops.init_params = e1000_init_mac_params_82540;
2608cfa0ad2SJack F Vogel 	hw->nvm.ops.init_params = e1000_init_nvm_params_82540;
2618cfa0ad2SJack F Vogel 	hw->phy.ops.init_params = e1000_init_phy_params_82540;
2628cfa0ad2SJack F Vogel }
2638cfa0ad2SJack F Vogel 
2648cfa0ad2SJack F Vogel /**
2658cfa0ad2SJack F Vogel  *  e1000_reset_hw_82540 - Reset hardware
2668cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
2678cfa0ad2SJack F Vogel  *
268daf9197cSJack F Vogel  *  This resets the hardware into a known state.
2698cfa0ad2SJack F Vogel  **/
e1000_reset_hw_82540(struct e1000_hw * hw)2708cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82540(struct e1000_hw *hw)
2718cfa0ad2SJack F Vogel {
272730d3130SJack F Vogel 	u32 ctrl, manc;
2738cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
2748cfa0ad2SJack F Vogel 
2758cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_reset_hw_82540");
2768cfa0ad2SJack F Vogel 
2778cfa0ad2SJack F Vogel 	DEBUGOUT("Masking off all interrupts\n");
2788cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
2798cfa0ad2SJack F Vogel 
2808cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
2818cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
2828cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
2838cfa0ad2SJack F Vogel 
2848cfa0ad2SJack F Vogel 	/*
2858cfa0ad2SJack F Vogel 	 * Delay to allow any outstanding PCI transactions to complete
2868cfa0ad2SJack F Vogel 	 * before resetting the device.
2878cfa0ad2SJack F Vogel 	 */
2888cfa0ad2SJack F Vogel 	msec_delay(10);
2898cfa0ad2SJack F Vogel 
2908cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
2918cfa0ad2SJack F Vogel 
2928cfa0ad2SJack F Vogel 	DEBUGOUT("Issuing a global reset to 82540/82545/82546 MAC\n");
2938cfa0ad2SJack F Vogel 	switch (hw->mac.type) {
2948cfa0ad2SJack F Vogel 	case e1000_82545_rev_3:
2958cfa0ad2SJack F Vogel 	case e1000_82546_rev_3:
2968cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL_DUP, ctrl | E1000_CTRL_RST);
2978cfa0ad2SJack F Vogel 		break;
2988cfa0ad2SJack F Vogel 	default:
2998cfa0ad2SJack F Vogel 		/*
3008cfa0ad2SJack F Vogel 		 * These controllers can't ack the 64-bit write when
3018cfa0ad2SJack F Vogel 		 * issuing the reset, so we use IO-mapping as a
3028cfa0ad2SJack F Vogel 		 * workaround to issue the reset.
3038cfa0ad2SJack F Vogel 		 */
3048cfa0ad2SJack F Vogel 		E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
3058cfa0ad2SJack F Vogel 		break;
3068cfa0ad2SJack F Vogel 	}
3078cfa0ad2SJack F Vogel 
3088cfa0ad2SJack F Vogel 	/* Wait for EEPROM reload */
3098cfa0ad2SJack F Vogel 	msec_delay(5);
3108cfa0ad2SJack F Vogel 
3118cfa0ad2SJack F Vogel 	/* Disable HW ARPs on ASF enabled adapters */
3128cfa0ad2SJack F Vogel 	manc = E1000_READ_REG(hw, E1000_MANC);
3138cfa0ad2SJack F Vogel 	manc &= ~E1000_MANC_ARP_EN;
3148cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_MANC, manc);
3158cfa0ad2SJack F Vogel 
3168cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
317730d3130SJack F Vogel 	E1000_READ_REG(hw, E1000_ICR);
3188cfa0ad2SJack F Vogel 
3198cfa0ad2SJack F Vogel 	return ret_val;
3208cfa0ad2SJack F Vogel }
3218cfa0ad2SJack F Vogel 
3228cfa0ad2SJack F Vogel /**
3238cfa0ad2SJack F Vogel  *  e1000_init_hw_82540 - Initialize hardware
3248cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3258cfa0ad2SJack F Vogel  *
326daf9197cSJack F Vogel  *  This inits the hardware readying it for operation.
3278cfa0ad2SJack F Vogel  **/
e1000_init_hw_82540(struct e1000_hw * hw)3288cfa0ad2SJack F Vogel static s32 e1000_init_hw_82540(struct e1000_hw *hw)
3298cfa0ad2SJack F Vogel {
3308cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
3318cfa0ad2SJack F Vogel 	u32 txdctl, ctrl_ext;
332c80429ceSEric Joyner 	s32 ret_val;
3338cfa0ad2SJack F Vogel 	u16 i;
3348cfa0ad2SJack F Vogel 
3358cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_hw_82540");
3368cfa0ad2SJack F Vogel 
3378cfa0ad2SJack F Vogel 	/* Initialize identification LED */
338d035aa2dSJack F Vogel 	ret_val = mac->ops.id_led_init(hw);
3398cfa0ad2SJack F Vogel 	if (ret_val) {
3408cfa0ad2SJack F Vogel 		DEBUGOUT("Error initializing identification LED\n");
3418cfa0ad2SJack F Vogel 		/* This is not fatal and we should not stop init due to this */
3428cfa0ad2SJack F Vogel 	}
3438cfa0ad2SJack F Vogel 
3448cfa0ad2SJack F Vogel 	/* Disabling VLAN filtering */
3458cfa0ad2SJack F Vogel 	DEBUGOUT("Initializing the IEEE VLAN\n");
3468cfa0ad2SJack F Vogel 	if (mac->type < e1000_82545_rev_3)
3478cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_VET, 0);
3488cfa0ad2SJack F Vogel 
3498cfa0ad2SJack F Vogel 	mac->ops.clear_vfta(hw);
3508cfa0ad2SJack F Vogel 
3518cfa0ad2SJack F Vogel 	/* Setup the receive address. */
3528cfa0ad2SJack F Vogel 	e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
3538cfa0ad2SJack F Vogel 
3548cfa0ad2SJack F Vogel 	/* Zero out the Multicast HASH table */
3558cfa0ad2SJack F Vogel 	DEBUGOUT("Zeroing the MTA\n");
3568cfa0ad2SJack F Vogel 	for (i = 0; i < mac->mta_reg_count; i++) {
3578cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
3588cfa0ad2SJack F Vogel 		/*
3598cfa0ad2SJack F Vogel 		 * Avoid back to back register writes by adding the register
3608cfa0ad2SJack F Vogel 		 * read (flush).  This is to protect against some strange
3618cfa0ad2SJack F Vogel 		 * bridge configurations that may issue Memory Write Block
3628cfa0ad2SJack F Vogel 		 * (MWB) to our register space.  The *_rev_3 hardware at
3638cfa0ad2SJack F Vogel 		 * least doesn't respond correctly to every other dword in an
3648cfa0ad2SJack F Vogel 		 * MWB to our register space.
3658cfa0ad2SJack F Vogel 		 */
3668cfa0ad2SJack F Vogel 		E1000_WRITE_FLUSH(hw);
3678cfa0ad2SJack F Vogel 	}
3688cfa0ad2SJack F Vogel 
3698cfa0ad2SJack F Vogel 	if (mac->type < e1000_82545_rev_3)
3708cfa0ad2SJack F Vogel 		e1000_pcix_mmrbc_workaround_generic(hw);
3718cfa0ad2SJack F Vogel 
3728cfa0ad2SJack F Vogel 	/* Setup link and flow control */
3738cfa0ad2SJack F Vogel 	ret_val = mac->ops.setup_link(hw);
3748cfa0ad2SJack F Vogel 
3758cfa0ad2SJack F Vogel 	txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
3768cfa0ad2SJack F Vogel 	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
3778cfa0ad2SJack F Vogel 		  E1000_TXDCTL_FULL_TX_DESC_WB;
3788cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
3798cfa0ad2SJack F Vogel 
3808cfa0ad2SJack F Vogel 	/*
3818cfa0ad2SJack F Vogel 	 * Clear all of the statistics registers (clear on read).  It is
3828cfa0ad2SJack F Vogel 	 * important that we do this after we have tried to establish link
3838cfa0ad2SJack F Vogel 	 * because the symbol error count will increment wildly if there
3848cfa0ad2SJack F Vogel 	 * is no link.
3858cfa0ad2SJack F Vogel 	 */
3868cfa0ad2SJack F Vogel 	e1000_clear_hw_cntrs_82540(hw);
3878cfa0ad2SJack F Vogel 
3888cfa0ad2SJack F Vogel 	if ((hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER) ||
3898cfa0ad2SJack F Vogel 	    (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3)) {
3908cfa0ad2SJack F Vogel 		ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
3918cfa0ad2SJack F Vogel 		/*
3928cfa0ad2SJack F Vogel 		 * Relaxed ordering must be disabled to avoid a parity
3938cfa0ad2SJack F Vogel 		 * error crash in a PCI slot.
3948cfa0ad2SJack F Vogel 		 */
3958cfa0ad2SJack F Vogel 		ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
3968cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
3978cfa0ad2SJack F Vogel 	}
3988cfa0ad2SJack F Vogel 
3998cfa0ad2SJack F Vogel 	return ret_val;
4008cfa0ad2SJack F Vogel }
4018cfa0ad2SJack F Vogel 
4028cfa0ad2SJack F Vogel /**
4038cfa0ad2SJack F Vogel  *  e1000_setup_copper_link_82540 - Configure copper link settings
4048cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
4058cfa0ad2SJack F Vogel  *
4068cfa0ad2SJack F Vogel  *  Calls the appropriate function to configure the link for auto-neg or forced
4078cfa0ad2SJack F Vogel  *  speed and duplex.  Then we check for link, once link is established calls
4088cfa0ad2SJack F Vogel  *  to configure collision distance and flow control are called.  If link is
409daf9197cSJack F Vogel  *  not established, we return -E1000_ERR_PHY (-2).
4108cfa0ad2SJack F Vogel  **/
e1000_setup_copper_link_82540(struct e1000_hw * hw)4118cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw)
4128cfa0ad2SJack F Vogel {
4138cfa0ad2SJack F Vogel 	u32 ctrl;
414c80429ceSEric Joyner 	s32 ret_val;
4158cfa0ad2SJack F Vogel 	u16 data;
4168cfa0ad2SJack F Vogel 
4178cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_setup_copper_link_82540");
4188cfa0ad2SJack F Vogel 
4198cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
4208cfa0ad2SJack F Vogel 	ctrl |= E1000_CTRL_SLU;
4218cfa0ad2SJack F Vogel 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
4228cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
4238cfa0ad2SJack F Vogel 
4248cfa0ad2SJack F Vogel 	ret_val = e1000_set_phy_mode_82540(hw);
4258cfa0ad2SJack F Vogel 	if (ret_val)
4268cfa0ad2SJack F Vogel 		goto out;
4278cfa0ad2SJack F Vogel 
4288cfa0ad2SJack F Vogel 	if (hw->mac.type == e1000_82545_rev_3 ||
4298cfa0ad2SJack F Vogel 	    hw->mac.type == e1000_82546_rev_3) {
4304dab5c37SJack F Vogel 		ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
4314dab5c37SJack F Vogel 					       &data);
4328cfa0ad2SJack F Vogel 		if (ret_val)
4338cfa0ad2SJack F Vogel 			goto out;
4348cfa0ad2SJack F Vogel 		data |= 0x00000008;
4354dab5c37SJack F Vogel 		ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
4364dab5c37SJack F Vogel 						data);
4378cfa0ad2SJack F Vogel 		if (ret_val)
4388cfa0ad2SJack F Vogel 			goto out;
4398cfa0ad2SJack F Vogel 	}
4408cfa0ad2SJack F Vogel 
4418cfa0ad2SJack F Vogel 	ret_val = e1000_copper_link_setup_m88(hw);
4428cfa0ad2SJack F Vogel 	if (ret_val)
4438cfa0ad2SJack F Vogel 		goto out;
4448cfa0ad2SJack F Vogel 
4458cfa0ad2SJack F Vogel 	ret_val = e1000_setup_copper_link_generic(hw);
4468cfa0ad2SJack F Vogel 
4478cfa0ad2SJack F Vogel out:
4488cfa0ad2SJack F Vogel 	return ret_val;
4498cfa0ad2SJack F Vogel }
4508cfa0ad2SJack F Vogel 
4518cfa0ad2SJack F Vogel /**
4528cfa0ad2SJack F Vogel  *  e1000_setup_fiber_serdes_link_82540 - Setup link for fiber/serdes
4538cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
4548cfa0ad2SJack F Vogel  *
4558cfa0ad2SJack F Vogel  *  Set the output amplitude to the value in the EEPROM and adjust the VCO
4568cfa0ad2SJack F Vogel  *  speed to improve Bit Error Rate (BER) performance.  Configures collision
4578cfa0ad2SJack F Vogel  *  distance and flow control for fiber and serdes links.  Upon successful
458daf9197cSJack F Vogel  *  setup, poll for link.
4598cfa0ad2SJack F Vogel  **/
e1000_setup_fiber_serdes_link_82540(struct e1000_hw * hw)4608cfa0ad2SJack F Vogel static s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw)
4618cfa0ad2SJack F Vogel {
4628cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
4638cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
4648cfa0ad2SJack F Vogel 
4658cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_setup_fiber_serdes_link_82540");
4668cfa0ad2SJack F Vogel 
4678cfa0ad2SJack F Vogel 	switch (mac->type) {
4688cfa0ad2SJack F Vogel 	case e1000_82545_rev_3:
4698cfa0ad2SJack F Vogel 	case e1000_82546_rev_3:
4708cfa0ad2SJack F Vogel 		if (hw->phy.media_type == e1000_media_type_internal_serdes) {
4718cfa0ad2SJack F Vogel 			/*
4728cfa0ad2SJack F Vogel 			 * If we're on serdes media, adjust the output
4738cfa0ad2SJack F Vogel 			 * amplitude to value set in the EEPROM.
4748cfa0ad2SJack F Vogel 			 */
4758cfa0ad2SJack F Vogel 			ret_val = e1000_adjust_serdes_amplitude_82540(hw);
4768cfa0ad2SJack F Vogel 			if (ret_val)
4778cfa0ad2SJack F Vogel 				goto out;
4788cfa0ad2SJack F Vogel 		}
4798cfa0ad2SJack F Vogel 		/* Adjust VCO speed to improve BER performance */
4808cfa0ad2SJack F Vogel 		ret_val = e1000_set_vco_speed_82540(hw);
4818cfa0ad2SJack F Vogel 		if (ret_val)
4828cfa0ad2SJack F Vogel 			goto out;
4838cfa0ad2SJack F Vogel 	default:
4848cfa0ad2SJack F Vogel 		break;
4858cfa0ad2SJack F Vogel 	}
4868cfa0ad2SJack F Vogel 
4878cfa0ad2SJack F Vogel 	ret_val = e1000_setup_fiber_serdes_link_generic(hw);
4888cfa0ad2SJack F Vogel 
4898cfa0ad2SJack F Vogel out:
4908cfa0ad2SJack F Vogel 	return ret_val;
4918cfa0ad2SJack F Vogel }
4928cfa0ad2SJack F Vogel 
4938cfa0ad2SJack F Vogel /**
4948cfa0ad2SJack F Vogel  *  e1000_adjust_serdes_amplitude_82540 - Adjust amplitude based on EEPROM
4958cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
4968cfa0ad2SJack F Vogel  *
4978cfa0ad2SJack F Vogel  *  Adjust the SERDES output amplitude based on the EEPROM settings.
4988cfa0ad2SJack F Vogel  **/
e1000_adjust_serdes_amplitude_82540(struct e1000_hw * hw)4998cfa0ad2SJack F Vogel static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw)
5008cfa0ad2SJack F Vogel {
501c80429ceSEric Joyner 	s32 ret_val;
5028cfa0ad2SJack F Vogel 	u16 nvm_data;
5038cfa0ad2SJack F Vogel 
5048cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_adjust_serdes_amplitude_82540");
5058cfa0ad2SJack F Vogel 
5068cfa0ad2SJack F Vogel 	ret_val = hw->nvm.ops.read(hw, NVM_SERDES_AMPLITUDE, 1, &nvm_data);
5078cfa0ad2SJack F Vogel 	if (ret_val)
5088cfa0ad2SJack F Vogel 		goto out;
5098cfa0ad2SJack F Vogel 
5108cfa0ad2SJack F Vogel 	if (nvm_data != NVM_RESERVED_WORD) {
5118cfa0ad2SJack F Vogel 		/* Adjust serdes output amplitude only. */
5128cfa0ad2SJack F Vogel 		nvm_data &= NVM_SERDES_AMPLITUDE_MASK;
5134dab5c37SJack F Vogel 		ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_EXT_CTRL,
5148cfa0ad2SJack F Vogel 						nvm_data);
5158cfa0ad2SJack F Vogel 		if (ret_val)
5168cfa0ad2SJack F Vogel 			goto out;
5178cfa0ad2SJack F Vogel 	}
5188cfa0ad2SJack F Vogel 
5198cfa0ad2SJack F Vogel out:
5208cfa0ad2SJack F Vogel 	return ret_val;
5218cfa0ad2SJack F Vogel }
5228cfa0ad2SJack F Vogel 
5238cfa0ad2SJack F Vogel /**
5248cfa0ad2SJack F Vogel  *  e1000_set_vco_speed_82540 - Set VCO speed for better performance
5258cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5268cfa0ad2SJack F Vogel  *
5278cfa0ad2SJack F Vogel  *  Set the VCO speed to improve Bit Error Rate (BER) performance.
5288cfa0ad2SJack F Vogel  **/
e1000_set_vco_speed_82540(struct e1000_hw * hw)5298cfa0ad2SJack F Vogel static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw)
5308cfa0ad2SJack F Vogel {
531c80429ceSEric Joyner 	s32  ret_val;
5328cfa0ad2SJack F Vogel 	u16 default_page = 0;
5338cfa0ad2SJack F Vogel 	u16 phy_data;
5348cfa0ad2SJack F Vogel 
5358cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_set_vco_speed_82540");
5368cfa0ad2SJack F Vogel 
5378cfa0ad2SJack F Vogel 	/* Set PHY register 30, page 5, bit 8 to 0 */
5388cfa0ad2SJack F Vogel 
5394dab5c37SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_PAGE_SELECT,
5408cfa0ad2SJack F Vogel 				       &default_page);
5418cfa0ad2SJack F Vogel 	if (ret_val)
5428cfa0ad2SJack F Vogel 		goto out;
5438cfa0ad2SJack F Vogel 
5448cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
5458cfa0ad2SJack F Vogel 	if (ret_val)
5468cfa0ad2SJack F Vogel 		goto out;
5478cfa0ad2SJack F Vogel 
5488cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
5498cfa0ad2SJack F Vogel 	if (ret_val)
5508cfa0ad2SJack F Vogel 		goto out;
5518cfa0ad2SJack F Vogel 
5528cfa0ad2SJack F Vogel 	phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
5538cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
5548cfa0ad2SJack F Vogel 	if (ret_val)
5558cfa0ad2SJack F Vogel 		goto out;
5568cfa0ad2SJack F Vogel 
5578cfa0ad2SJack F Vogel 	/* Set PHY register 30, page 4, bit 11 to 1 */
5588cfa0ad2SJack F Vogel 
5598cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
5608cfa0ad2SJack F Vogel 	if (ret_val)
5618cfa0ad2SJack F Vogel 		goto out;
5628cfa0ad2SJack F Vogel 
5638cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
5648cfa0ad2SJack F Vogel 	if (ret_val)
5658cfa0ad2SJack F Vogel 		goto out;
5668cfa0ad2SJack F Vogel 
5678cfa0ad2SJack F Vogel 	phy_data |= M88E1000_PHY_VCO_REG_BIT11;
5688cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
5698cfa0ad2SJack F Vogel 	if (ret_val)
5708cfa0ad2SJack F Vogel 		goto out;
5718cfa0ad2SJack F Vogel 
5728cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT,
5738cfa0ad2SJack F Vogel 					default_page);
5748cfa0ad2SJack F Vogel 
5758cfa0ad2SJack F Vogel out:
5768cfa0ad2SJack F Vogel 	return ret_val;
5778cfa0ad2SJack F Vogel }
5788cfa0ad2SJack F Vogel 
5798cfa0ad2SJack F Vogel /**
5808cfa0ad2SJack F Vogel  *  e1000_set_phy_mode_82540 - Set PHY to class A mode
5818cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5828cfa0ad2SJack F Vogel  *
5838cfa0ad2SJack F Vogel  *  Sets the PHY to class A mode and assumes the following operations will
5848cfa0ad2SJack F Vogel  *  follow to enable the new class mode:
5858cfa0ad2SJack F Vogel  *    1.  Do a PHY soft reset.
5868cfa0ad2SJack F Vogel  *    2.  Restart auto-negotiation or force link.
5878cfa0ad2SJack F Vogel  **/
e1000_set_phy_mode_82540(struct e1000_hw * hw)5888cfa0ad2SJack F Vogel static s32 e1000_set_phy_mode_82540(struct e1000_hw *hw)
5898cfa0ad2SJack F Vogel {
5908cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
5918cfa0ad2SJack F Vogel 	u16 nvm_data;
5928cfa0ad2SJack F Vogel 
5938cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_set_phy_mode_82540");
5948cfa0ad2SJack F Vogel 
5958cfa0ad2SJack F Vogel 	if (hw->mac.type != e1000_82545_rev_3)
5968cfa0ad2SJack F Vogel 		goto out;
5978cfa0ad2SJack F Vogel 
5988cfa0ad2SJack F Vogel 	ret_val = hw->nvm.ops.read(hw, NVM_PHY_CLASS_WORD, 1, &nvm_data);
5998cfa0ad2SJack F Vogel 	if (ret_val) {
6008cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PHY;
6018cfa0ad2SJack F Vogel 		goto out;
6028cfa0ad2SJack F Vogel 	}
6038cfa0ad2SJack F Vogel 
6048cfa0ad2SJack F Vogel 	if ((nvm_data != NVM_RESERVED_WORD) && (nvm_data & NVM_PHY_CLASS_A)) {
6058cfa0ad2SJack F Vogel 		ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT,
6068cfa0ad2SJack F Vogel 						0x000B);
6078cfa0ad2SJack F Vogel 		if (ret_val) {
6088cfa0ad2SJack F Vogel 			ret_val = -E1000_ERR_PHY;
6098cfa0ad2SJack F Vogel 			goto out;
6108cfa0ad2SJack F Vogel 		}
6114dab5c37SJack F Vogel 		ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL,
6128cfa0ad2SJack F Vogel 						0x8104);
6138cfa0ad2SJack F Vogel 		if (ret_val) {
6148cfa0ad2SJack F Vogel 			ret_val = -E1000_ERR_PHY;
6158cfa0ad2SJack F Vogel 			goto out;
6168cfa0ad2SJack F Vogel 		}
6178cfa0ad2SJack F Vogel 
6188cfa0ad2SJack F Vogel 	}
6198cfa0ad2SJack F Vogel 
6208cfa0ad2SJack F Vogel out:
6218cfa0ad2SJack F Vogel 	return ret_val;
6228cfa0ad2SJack F Vogel }
6238cfa0ad2SJack F Vogel 
6248cfa0ad2SJack F Vogel /**
6258cfa0ad2SJack F Vogel  * e1000_power_down_phy_copper_82540 - Remove link in case of PHY power down
6268cfa0ad2SJack F Vogel  * @hw: pointer to the HW structure
6278cfa0ad2SJack F Vogel  *
6288cfa0ad2SJack F Vogel  * In the case of a PHY power down to save power, or to turn off link during a
6298cfa0ad2SJack F Vogel  * driver unload, or wake on lan is not enabled, remove the link.
6308cfa0ad2SJack F Vogel  **/
e1000_power_down_phy_copper_82540(struct e1000_hw * hw)6318cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw)
6328cfa0ad2SJack F Vogel {
6338cfa0ad2SJack F Vogel 	/* If the management interface is not enabled, then power down */
6348cfa0ad2SJack F Vogel 	if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN))
6358cfa0ad2SJack F Vogel 		e1000_power_down_phy_copper(hw);
6368cfa0ad2SJack F Vogel 
6378cfa0ad2SJack F Vogel 	return;
6388cfa0ad2SJack F Vogel }
6398cfa0ad2SJack F Vogel 
6408cfa0ad2SJack F Vogel /**
6418cfa0ad2SJack F Vogel  *  e1000_clear_hw_cntrs_82540 - Clear device specific hardware counters
6428cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
6438cfa0ad2SJack F Vogel  *
6448cfa0ad2SJack F Vogel  *  Clears the hardware counters by reading the counter registers.
6458cfa0ad2SJack F Vogel  **/
e1000_clear_hw_cntrs_82540(struct e1000_hw * hw)6468cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw)
6478cfa0ad2SJack F Vogel {
6488cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_clear_hw_cntrs_82540");
6498cfa0ad2SJack F Vogel 
6508cfa0ad2SJack F Vogel 	e1000_clear_hw_cntrs_base_generic(hw);
6518cfa0ad2SJack F Vogel 
652daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC64);
653daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC127);
654daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC255);
655daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC511);
656daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC1023);
657daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC1522);
658daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC64);
659daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC127);
660daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC255);
661daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC511);
662daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC1023);
663daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC1522);
6648cfa0ad2SJack F Vogel 
665daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ALGNERRC);
666daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_RXERRC);
667daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TNCRS);
668daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_CEXTERR);
669daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TSCTC);
670daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TSCTFC);
6718cfa0ad2SJack F Vogel 
672daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPRC);
673daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPDC);
674daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPTC);
6758cfa0ad2SJack F Vogel }
6768cfa0ad2SJack F Vogel 
6779d81738fSJack F Vogel /**
6789d81738fSJack F Vogel  *  e1000_read_mac_addr_82540 - Read device MAC address
6799d81738fSJack F Vogel  *  @hw: pointer to the HW structure
6809d81738fSJack F Vogel  *
6819d81738fSJack F Vogel  *  Reads the device MAC address from the EEPROM and stores the value.
6829d81738fSJack F Vogel  *  Since devices with two ports use the same EEPROM, we increment the
6839d81738fSJack F Vogel  *  last bit in the MAC address for the second port.
6849d81738fSJack F Vogel  *
6859d81738fSJack F Vogel  *  This version is being used over generic because of customer issues
6869d81738fSJack F Vogel  *  with VmWare and Virtual Box when using generic. It seems in
6879d81738fSJack F Vogel  *  the emulated 82545, RAR[0] does NOT have a valid address after a
6889d81738fSJack F Vogel  *  reset, this older method works and using this breaks nothing for
6899d81738fSJack F Vogel  *  these legacy adapters.
6909d81738fSJack F Vogel  **/
e1000_read_mac_addr_82540(struct e1000_hw * hw)6919d81738fSJack F Vogel s32 e1000_read_mac_addr_82540(struct e1000_hw *hw)
6929d81738fSJack F Vogel {
6939d81738fSJack F Vogel 	s32  ret_val = E1000_SUCCESS;
6949d81738fSJack F Vogel 	u16 offset, nvm_data, i;
6959d81738fSJack F Vogel 
6969d81738fSJack F Vogel 	DEBUGFUNC("e1000_read_mac_addr");
6979d81738fSJack F Vogel 
698e81998f4SEric Joyner 	for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
6999d81738fSJack F Vogel 		offset = i >> 1;
7009d81738fSJack F Vogel 		ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
7019d81738fSJack F Vogel 		if (ret_val) {
7029d81738fSJack F Vogel 			DEBUGOUT("NVM Read Error\n");
7039d81738fSJack F Vogel 			goto out;
7049d81738fSJack F Vogel 		}
7059d81738fSJack F Vogel 		hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
7069d81738fSJack F Vogel 		hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
7079d81738fSJack F Vogel 	}
7089d81738fSJack F Vogel 
7099d81738fSJack F Vogel 	/* Flip last bit of mac address if we're on second port */
7109d81738fSJack F Vogel 	if (hw->bus.func == E1000_FUNC_1)
7119d81738fSJack F Vogel 		hw->mac.perm_addr[5] ^= 1;
7129d81738fSJack F Vogel 
713e81998f4SEric Joyner 	for (i = 0; i < ETHER_ADDR_LEN; i++)
7149d81738fSJack F Vogel 		hw->mac.addr[i] = hw->mac.perm_addr[i];
7159d81738fSJack F Vogel 
7169d81738fSJack F Vogel out:
7179d81738fSJack F Vogel 	return ret_val;
7189d81738fSJack F Vogel }
719