xref: /freebsd/sys/dev/e1000/e1000_82575.c (revision cef367e6a15b6e3e2aca88d453c74962cf1f94e7)
18cfa0ad2SJack F Vogel /******************************************************************************
28cfa0ad2SJack F Vogel 
37c669ab6SSean Bruno   Copyright (c) 2001-2015, Intel Corporation
48cfa0ad2SJack F Vogel   All rights reserved.
58cfa0ad2SJack F Vogel 
68cfa0ad2SJack F Vogel   Redistribution and use in source and binary forms, with or without
78cfa0ad2SJack F Vogel   modification, are permitted provided that the following conditions are met:
88cfa0ad2SJack F Vogel 
98cfa0ad2SJack F Vogel    1. Redistributions of source code must retain the above copyright notice,
108cfa0ad2SJack F Vogel       this list of conditions and the following disclaimer.
118cfa0ad2SJack F Vogel 
128cfa0ad2SJack F Vogel    2. Redistributions in binary form must reproduce the above copyright
138cfa0ad2SJack F Vogel       notice, this list of conditions and the following disclaimer in the
148cfa0ad2SJack F Vogel       documentation and/or other materials provided with the distribution.
158cfa0ad2SJack F Vogel 
168cfa0ad2SJack F Vogel    3. Neither the name of the Intel Corporation nor the names of its
178cfa0ad2SJack F Vogel       contributors may be used to endorse or promote products derived from
188cfa0ad2SJack F Vogel       this software without specific prior written permission.
198cfa0ad2SJack F Vogel 
208cfa0ad2SJack F Vogel   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
218cfa0ad2SJack F Vogel   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
228cfa0ad2SJack F Vogel   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238cfa0ad2SJack F Vogel   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
248cfa0ad2SJack F Vogel   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
258cfa0ad2SJack F Vogel   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268cfa0ad2SJack F Vogel   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
278cfa0ad2SJack F Vogel   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
288cfa0ad2SJack F Vogel   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
298cfa0ad2SJack F Vogel   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
308cfa0ad2SJack F Vogel   POSSIBILITY OF SUCH DAMAGE.
318cfa0ad2SJack F Vogel 
328cfa0ad2SJack F Vogel ******************************************************************************/
338cfa0ad2SJack F Vogel /*$FreeBSD$*/
348cfa0ad2SJack F Vogel 
35daf9197cSJack F Vogel /*
36daf9197cSJack F Vogel  * 82575EB Gigabit Network Connection
37daf9197cSJack F Vogel  * 82575EB Gigabit Backplane Connection
38daf9197cSJack F Vogel  * 82575GB Gigabit Network Connection
39daf9197cSJack F Vogel  * 82576 Gigabit Network Connection
409d81738fSJack F Vogel  * 82576 Quad Port Gigabit Mezzanine Adapter
41ab5d0362SJack F Vogel  * 82580 Gigabit Network Connection
42ab5d0362SJack F Vogel  * I350 Gigabit Network Connection
438cfa0ad2SJack F Vogel  */
448cfa0ad2SJack F Vogel 
458cfa0ad2SJack F Vogel #include "e1000_api.h"
46ab5d0362SJack F Vogel #include "e1000_i210.h"
478cfa0ad2SJack F Vogel 
488cfa0ad2SJack F Vogel static s32  e1000_init_phy_params_82575(struct e1000_hw *hw);
498cfa0ad2SJack F Vogel static s32  e1000_init_mac_params_82575(struct e1000_hw *hw);
508cfa0ad2SJack F Vogel static s32  e1000_acquire_phy_82575(struct e1000_hw *hw);
518cfa0ad2SJack F Vogel static void e1000_release_phy_82575(struct e1000_hw *hw);
528cfa0ad2SJack F Vogel static s32  e1000_acquire_nvm_82575(struct e1000_hw *hw);
538cfa0ad2SJack F Vogel static void e1000_release_nvm_82575(struct e1000_hw *hw);
548cfa0ad2SJack F Vogel static s32  e1000_check_for_link_82575(struct e1000_hw *hw);
557609433eSJack F Vogel static s32  e1000_check_for_link_media_swap(struct e1000_hw *hw);
568cfa0ad2SJack F Vogel static s32  e1000_get_cfg_done_82575(struct e1000_hw *hw);
578cfa0ad2SJack F Vogel static s32  e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
588cfa0ad2SJack F Vogel 					 u16 *duplex);
598cfa0ad2SJack F Vogel static s32  e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw);
608cfa0ad2SJack F Vogel static s32  e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
618cfa0ad2SJack F Vogel 					   u16 *data);
628cfa0ad2SJack F Vogel static s32  e1000_reset_hw_82575(struct e1000_hw *hw);
634edd8523SJack F Vogel static s32  e1000_reset_hw_82580(struct e1000_hw *hw);
644edd8523SJack F Vogel static s32  e1000_read_phy_reg_82580(struct e1000_hw *hw,
654edd8523SJack F Vogel 				     u32 offset, u16 *data);
664edd8523SJack F Vogel static s32  e1000_write_phy_reg_82580(struct e1000_hw *hw,
674edd8523SJack F Vogel 				      u32 offset, u16 data);
68f0ecc46dSJack F Vogel static s32  e1000_set_d0_lplu_state_82580(struct e1000_hw *hw,
69f0ecc46dSJack F Vogel 					  bool active);
70f0ecc46dSJack F Vogel static s32  e1000_set_d3_lplu_state_82580(struct e1000_hw *hw,
71f0ecc46dSJack F Vogel 					  bool active);
728cfa0ad2SJack F Vogel static s32  e1000_set_d0_lplu_state_82575(struct e1000_hw *hw,
738cfa0ad2SJack F Vogel 					  bool active);
748cfa0ad2SJack F Vogel static s32  e1000_setup_copper_link_82575(struct e1000_hw *hw);
754edd8523SJack F Vogel static s32  e1000_setup_serdes_link_82575(struct e1000_hw *hw);
764dab5c37SJack F Vogel static s32  e1000_get_media_type_82575(struct e1000_hw *hw);
774dab5c37SJack F Vogel static s32  e1000_set_sfp_media_type_82575(struct e1000_hw *hw);
788cfa0ad2SJack F Vogel static s32  e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data);
798cfa0ad2SJack F Vogel static s32  e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw,
808cfa0ad2SJack F Vogel 					    u32 offset, u16 data);
818cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw);
828cfa0ad2SJack F Vogel static s32  e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
838cfa0ad2SJack F Vogel static s32  e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
848cfa0ad2SJack F Vogel 						 u16 *speed, u16 *duplex);
858cfa0ad2SJack F Vogel static s32  e1000_get_phy_id_82575(struct e1000_hw *hw);
868cfa0ad2SJack F Vogel static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
878cfa0ad2SJack F Vogel static bool e1000_sgmii_active_82575(struct e1000_hw *hw);
888cfa0ad2SJack F Vogel static s32  e1000_reset_init_script_82575(struct e1000_hw *hw);
898cfa0ad2SJack F Vogel static s32  e1000_read_mac_addr_82575(struct e1000_hw *hw);
90a69ed8dfSJack F Vogel static void e1000_config_collision_dist_82575(struct e1000_hw *hw);
918cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw);
924edd8523SJack F Vogel static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw);
93a69ed8dfSJack F Vogel static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw);
949d81738fSJack F Vogel static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw);
957d9119bdSJack F Vogel static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw);
96f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw);
97f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw);
98f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw,
99f0ecc46dSJack F Vogel 						 u16 offset);
100f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
101f0ecc46dSJack F Vogel 						   u16 offset);
102f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw);
103f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw);
1044dab5c37SJack F Vogel static void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value);
1054dab5c37SJack F Vogel static void e1000_clear_vfta_i350(struct e1000_hw *hw);
1068cfa0ad2SJack F Vogel 
1074dab5c37SJack F Vogel static void e1000_i2c_start(struct e1000_hw *hw);
1084dab5c37SJack F Vogel static void e1000_i2c_stop(struct e1000_hw *hw);
1094dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data);
1104dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data);
1114dab5c37SJack F Vogel static s32 e1000_get_i2c_ack(struct e1000_hw *hw);
1124dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data);
1134dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data);
1144dab5c37SJack F Vogel static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl);
1154dab5c37SJack F Vogel static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl);
1164dab5c37SJack F Vogel static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data);
1174dab5c37SJack F Vogel static bool e1000_get_i2c_data(u32 *i2cctl);
1184dab5c37SJack F Vogel 
1194dab5c37SJack F Vogel static const u16 e1000_82580_rxpbs_table[] = {
1204dab5c37SJack F Vogel 	36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 };
1214edd8523SJack F Vogel #define E1000_82580_RXPBS_TABLE_SIZE \
1228cc64f1eSJack F Vogel 	(sizeof(e1000_82580_rxpbs_table) / \
1238cc64f1eSJack F Vogel 	 sizeof(e1000_82580_rxpbs_table[0]))
1244edd8523SJack F Vogel 
1257d9119bdSJack F Vogel 
1267d9119bdSJack F Vogel /**
1277d9119bdSJack F Vogel  *  e1000_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO
1287d9119bdSJack F Vogel  *  @hw: pointer to the HW structure
1297d9119bdSJack F Vogel  *
1307d9119bdSJack F Vogel  *  Called to determine if the I2C pins are being used for I2C or as an
1317d9119bdSJack F Vogel  *  external MDIO interface since the two options are mutually exclusive.
1327d9119bdSJack F Vogel  **/
1337d9119bdSJack F Vogel static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw)
1347d9119bdSJack F Vogel {
1357d9119bdSJack F Vogel 	u32 reg = 0;
1367d9119bdSJack F Vogel 	bool ext_mdio = FALSE;
1377d9119bdSJack F Vogel 
1387d9119bdSJack F Vogel 	DEBUGFUNC("e1000_sgmii_uses_mdio_82575");
1397d9119bdSJack F Vogel 
1407d9119bdSJack F Vogel 	switch (hw->mac.type) {
1417d9119bdSJack F Vogel 	case e1000_82575:
1427d9119bdSJack F Vogel 	case e1000_82576:
1437d9119bdSJack F Vogel 		reg = E1000_READ_REG(hw, E1000_MDIC);
1447d9119bdSJack F Vogel 		ext_mdio = !!(reg & E1000_MDIC_DEST);
1457d9119bdSJack F Vogel 		break;
1467d9119bdSJack F Vogel 	case e1000_82580:
147f0ecc46dSJack F Vogel 	case e1000_i350:
1487609433eSJack F Vogel 	case e1000_i354:
1496ab6bfe3SJack F Vogel 	case e1000_i210:
1506ab6bfe3SJack F Vogel 	case e1000_i211:
1517d9119bdSJack F Vogel 		reg = E1000_READ_REG(hw, E1000_MDICNFG);
1527d9119bdSJack F Vogel 		ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
1537d9119bdSJack F Vogel 		break;
1547d9119bdSJack F Vogel 	default:
1557d9119bdSJack F Vogel 		break;
1567d9119bdSJack F Vogel 	}
1577d9119bdSJack F Vogel 	return ext_mdio;
1587d9119bdSJack F Vogel }
1597d9119bdSJack F Vogel 
1608cfa0ad2SJack F Vogel /**
1618cfa0ad2SJack F Vogel  *  e1000_init_phy_params_82575 - Init PHY func ptrs.
1628cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
1638cfa0ad2SJack F Vogel  **/
1648cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
1658cfa0ad2SJack F Vogel {
1668cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
1678cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
1687d9119bdSJack F Vogel 	u32 ctrl_ext;
1698cfa0ad2SJack F Vogel 
1708cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_phy_params_82575");
1718cfa0ad2SJack F Vogel 
172ab5d0362SJack F Vogel 	phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic;
173ab5d0362SJack F Vogel 	phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic;
174ab5d0362SJack F Vogel 
1758cfa0ad2SJack F Vogel 	if (hw->phy.media_type != e1000_media_type_copper) {
1768cfa0ad2SJack F Vogel 		phy->type = e1000_phy_none;
1778cfa0ad2SJack F Vogel 		goto out;
1784edd8523SJack F Vogel 	}
1794edd8523SJack F Vogel 
1808cfa0ad2SJack F Vogel 	phy->ops.power_up   = e1000_power_up_phy_copper;
1818cfa0ad2SJack F Vogel 	phy->ops.power_down = e1000_power_down_phy_copper_82575;
1828cfa0ad2SJack F Vogel 
1838cfa0ad2SJack F Vogel 	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
1848cfa0ad2SJack F Vogel 	phy->reset_delay_us	= 100;
1858cfa0ad2SJack F Vogel 
1868cfa0ad2SJack F Vogel 	phy->ops.acquire	= e1000_acquire_phy_82575;
1878cfa0ad2SJack F Vogel 	phy->ops.check_reset_block = e1000_check_reset_block_generic;
1888cfa0ad2SJack F Vogel 	phy->ops.commit		= e1000_phy_sw_reset_generic;
1898cfa0ad2SJack F Vogel 	phy->ops.get_cfg_done	= e1000_get_cfg_done_82575;
1908cfa0ad2SJack F Vogel 	phy->ops.release	= e1000_release_phy_82575;
1918cfa0ad2SJack F Vogel 
1927d9119bdSJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
1937d9119bdSJack F Vogel 
1948cfa0ad2SJack F Vogel 	if (e1000_sgmii_active_82575(hw)) {
1958cfa0ad2SJack F Vogel 		phy->ops.reset = e1000_phy_hw_reset_sgmii_82575;
1967d9119bdSJack F Vogel 		ctrl_ext |= E1000_CTRL_I2C_ENA;
1977d9119bdSJack F Vogel 	} else {
1987d9119bdSJack F Vogel 		phy->ops.reset = e1000_phy_hw_reset_generic;
1997d9119bdSJack F Vogel 		ctrl_ext &= ~E1000_CTRL_I2C_ENA;
2007d9119bdSJack F Vogel 	}
2017d9119bdSJack F Vogel 
2027d9119bdSJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
2037d9119bdSJack F Vogel 	e1000_reset_mdicnfg_82580(hw);
2047d9119bdSJack F Vogel 
2057d9119bdSJack F Vogel 	if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) {
2068cfa0ad2SJack F Vogel 		phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575;
2078cfa0ad2SJack F Vogel 		phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575;
208ab5d0362SJack F Vogel 	} else {
209ab5d0362SJack F Vogel 		switch (hw->mac.type) {
210ab5d0362SJack F Vogel 		case e1000_82580:
211ab5d0362SJack F Vogel 		case e1000_i350:
2127609433eSJack F Vogel 		case e1000_i354:
2134edd8523SJack F Vogel 			phy->ops.read_reg = e1000_read_phy_reg_82580;
2144edd8523SJack F Vogel 			phy->ops.write_reg = e1000_write_phy_reg_82580;
215ab5d0362SJack F Vogel 			break;
216ab5d0362SJack F Vogel 		case e1000_i210:
217ab5d0362SJack F Vogel 		case e1000_i211:
218ab5d0362SJack F Vogel 			phy->ops.read_reg = e1000_read_phy_reg_gs40g;
219ab5d0362SJack F Vogel 			phy->ops.write_reg = e1000_write_phy_reg_gs40g;
220ab5d0362SJack F Vogel 			break;
221ab5d0362SJack F Vogel 		default:
2228cfa0ad2SJack F Vogel 			phy->ops.read_reg = e1000_read_phy_reg_igp;
2238cfa0ad2SJack F Vogel 			phy->ops.write_reg = e1000_write_phy_reg_igp;
2248cfa0ad2SJack F Vogel 		}
225ab5d0362SJack F Vogel 	}
2268cfa0ad2SJack F Vogel 
2278cfa0ad2SJack F Vogel 	/* Set phy->phy_addr and phy->id. */
2288cfa0ad2SJack F Vogel 	ret_val = e1000_get_phy_id_82575(hw);
2298cfa0ad2SJack F Vogel 
2308cfa0ad2SJack F Vogel 	/* Verify phy id and set remaining function pointers */
2318cfa0ad2SJack F Vogel 	switch (phy->id) {
2327609433eSJack F Vogel 	case M88E1543_E_PHY_ID:
2337609433eSJack F Vogel 	case M88E1512_E_PHY_ID:
234f0ecc46dSJack F Vogel 	case I347AT4_E_PHY_ID:
235f0ecc46dSJack F Vogel 	case M88E1112_E_PHY_ID:
2361fd3c44fSJack F Vogel 	case M88E1340M_E_PHY_ID:
2378cfa0ad2SJack F Vogel 	case M88E1111_I_PHY_ID:
2388cfa0ad2SJack F Vogel 		phy->type		= e1000_phy_m88;
2398cfa0ad2SJack F Vogel 		phy->ops.check_polarity	= e1000_check_polarity_m88;
2408cfa0ad2SJack F Vogel 		phy->ops.get_info	= e1000_get_phy_info_m88;
241f0ecc46dSJack F Vogel 		if (phy->id == I347AT4_E_PHY_ID ||
2421fd3c44fSJack F Vogel 		    phy->id == M88E1112_E_PHY_ID ||
2431fd3c44fSJack F Vogel 		    phy->id == M88E1340M_E_PHY_ID)
2444dab5c37SJack F Vogel 			phy->ops.get_cable_length =
2454dab5c37SJack F Vogel 					 e1000_get_cable_length_m88_gen2;
2467609433eSJack F Vogel 		else if (phy->id == M88E1543_E_PHY_ID ||
2477609433eSJack F Vogel 			 phy->id == M88E1512_E_PHY_ID)
2487609433eSJack F Vogel 			phy->ops.get_cable_length =
2497609433eSJack F Vogel 					 e1000_get_cable_length_m88_gen2;
250f0ecc46dSJack F Vogel 		else
2518cfa0ad2SJack F Vogel 			phy->ops.get_cable_length = e1000_get_cable_length_m88;
2528cfa0ad2SJack F Vogel 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
2537609433eSJack F Vogel 		/* Check if this PHY is confgured for media swap. */
2547609433eSJack F Vogel 		if (phy->id == M88E1112_E_PHY_ID) {
2557609433eSJack F Vogel 			u16 data;
2567609433eSJack F Vogel 
2577609433eSJack F Vogel 			ret_val = phy->ops.write_reg(hw,
2587609433eSJack F Vogel 						     E1000_M88E1112_PAGE_ADDR,
2597609433eSJack F Vogel 						     2);
2607609433eSJack F Vogel 			if (ret_val)
2617609433eSJack F Vogel 				goto out;
2627609433eSJack F Vogel 
2637609433eSJack F Vogel 			ret_val = phy->ops.read_reg(hw,
2647609433eSJack F Vogel 						    E1000_M88E1112_MAC_CTRL_1,
2657609433eSJack F Vogel 						    &data);
2667609433eSJack F Vogel 			if (ret_val)
2677609433eSJack F Vogel 				goto out;
2687609433eSJack F Vogel 
2697609433eSJack F Vogel 			data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >>
2707609433eSJack F Vogel 			       E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT;
2717609433eSJack F Vogel 			if (data == E1000_M88E1112_AUTO_COPPER_SGMII ||
2727609433eSJack F Vogel 			    data == E1000_M88E1112_AUTO_COPPER_BASEX)
2737609433eSJack F Vogel 				hw->mac.ops.check_for_link =
2747609433eSJack F Vogel 						e1000_check_for_link_media_swap;
2757609433eSJack F Vogel 		}
2768cc64f1eSJack F Vogel 		if (phy->id == M88E1512_E_PHY_ID) {
2778cc64f1eSJack F Vogel 			ret_val = e1000_initialize_M88E1512_phy(hw);
2788cc64f1eSJack F Vogel 			if (ret_val)
2798cc64f1eSJack F Vogel 				goto out;
2808cc64f1eSJack F Vogel 		}
281c80429ceSEric Joyner 		if (phy->id == M88E1543_E_PHY_ID) {
282c80429ceSEric Joyner 			ret_val = e1000_initialize_M88E1543_phy(hw);
283c80429ceSEric Joyner 			if (ret_val)
284c80429ceSEric Joyner 				goto out;
285c80429ceSEric Joyner 		}
2868cfa0ad2SJack F Vogel 		break;
2878cfa0ad2SJack F Vogel 	case IGP03E1000_E_PHY_ID:
2888cfa0ad2SJack F Vogel 	case IGP04E1000_E_PHY_ID:
2898cfa0ad2SJack F Vogel 		phy->type = e1000_phy_igp_3;
2908cfa0ad2SJack F Vogel 		phy->ops.check_polarity = e1000_check_polarity_igp;
2918cfa0ad2SJack F Vogel 		phy->ops.get_info = e1000_get_phy_info_igp;
2928cfa0ad2SJack F Vogel 		phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
2938cfa0ad2SJack F Vogel 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
2948cfa0ad2SJack F Vogel 		phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575;
2958cfa0ad2SJack F Vogel 		phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
2968cfa0ad2SJack F Vogel 		break;
2974edd8523SJack F Vogel 	case I82580_I_PHY_ID:
298f0ecc46dSJack F Vogel 	case I350_I_PHY_ID:
2994edd8523SJack F Vogel 		phy->type = e1000_phy_82580;
3004edd8523SJack F Vogel 		phy->ops.check_polarity = e1000_check_polarity_82577;
3014dab5c37SJack F Vogel 		phy->ops.force_speed_duplex =
3024dab5c37SJack F Vogel 					 e1000_phy_force_speed_duplex_82577;
3034edd8523SJack F Vogel 		phy->ops.get_cable_length = e1000_get_cable_length_82577;
3044edd8523SJack F Vogel 		phy->ops.get_info = e1000_get_phy_info_82577;
305f0ecc46dSJack F Vogel 		phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580;
306f0ecc46dSJack F Vogel 		phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580;
3074edd8523SJack F Vogel 		break;
308ab5d0362SJack F Vogel 	case I210_I_PHY_ID:
309ab5d0362SJack F Vogel 		phy->type		= e1000_phy_i210;
310ab5d0362SJack F Vogel 		phy->ops.check_polarity	= e1000_check_polarity_m88;
311ab5d0362SJack F Vogel 		phy->ops.get_info	= e1000_get_phy_info_m88;
312ab5d0362SJack F Vogel 		phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2;
313ab5d0362SJack F Vogel 		phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580;
314ab5d0362SJack F Vogel 		phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580;
315ab5d0362SJack F Vogel 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
316ab5d0362SJack F Vogel 		break;
3178cfa0ad2SJack F Vogel 	default:
3188cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PHY;
3198cfa0ad2SJack F Vogel 		goto out;
3208cfa0ad2SJack F Vogel 	}
3218cfa0ad2SJack F Vogel 
3228cfa0ad2SJack F Vogel out:
3238cfa0ad2SJack F Vogel 	return ret_val;
3248cfa0ad2SJack F Vogel }
3258cfa0ad2SJack F Vogel 
3268cfa0ad2SJack F Vogel /**
3278cfa0ad2SJack F Vogel  *  e1000_init_nvm_params_82575 - Init NVM func ptrs.
3288cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3298cfa0ad2SJack F Vogel  **/
3301fd3c44fSJack F Vogel s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
3318cfa0ad2SJack F Vogel {
3328cfa0ad2SJack F Vogel 	struct e1000_nvm_info *nvm = &hw->nvm;
3338cfa0ad2SJack F Vogel 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
3348cfa0ad2SJack F Vogel 	u16 size;
3358cfa0ad2SJack F Vogel 
3368cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_nvm_params_82575");
3378cfa0ad2SJack F Vogel 
338f0ecc46dSJack F Vogel 	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
339f0ecc46dSJack F Vogel 		     E1000_EECD_SIZE_EX_SHIFT);
340f0ecc46dSJack F Vogel 	/*
341f0ecc46dSJack F Vogel 	 * Added to a constant, "size" becomes the left-shift value
342f0ecc46dSJack F Vogel 	 * for setting word_size.
343f0ecc46dSJack F Vogel 	 */
344f0ecc46dSJack F Vogel 	size += NVM_WORD_SIZE_BASE_SHIFT;
345f0ecc46dSJack F Vogel 
3464dab5c37SJack F Vogel 	/* Just in case size is out of range, cap it to the largest
3474dab5c37SJack F Vogel 	 * EEPROM size supported
3484dab5c37SJack F Vogel 	 */
3494dab5c37SJack F Vogel 	if (size > 15)
3504dab5c37SJack F Vogel 		size = 15;
3514dab5c37SJack F Vogel 
352f0ecc46dSJack F Vogel 	nvm->word_size = 1 << size;
353ab5d0362SJack F Vogel 	if (hw->mac.type < e1000_i210) {
3548cfa0ad2SJack F Vogel 		nvm->opcode_bits = 8;
3558cfa0ad2SJack F Vogel 		nvm->delay_usec = 1;
356ab5d0362SJack F Vogel 
3578cfa0ad2SJack F Vogel 		switch (nvm->override) {
3588cfa0ad2SJack F Vogel 		case e1000_nvm_override_spi_large:
3598cfa0ad2SJack F Vogel 			nvm->page_size = 32;
3608cfa0ad2SJack F Vogel 			nvm->address_bits = 16;
3618cfa0ad2SJack F Vogel 			break;
3628cfa0ad2SJack F Vogel 		case e1000_nvm_override_spi_small:
3638cfa0ad2SJack F Vogel 			nvm->page_size = 8;
3648cfa0ad2SJack F Vogel 			nvm->address_bits = 8;
3658cfa0ad2SJack F Vogel 			break;
3668cfa0ad2SJack F Vogel 		default:
3678cfa0ad2SJack F Vogel 			nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
368ab5d0362SJack F Vogel 			nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ?
369ab5d0362SJack F Vogel 					    16 : 8;
3708cfa0ad2SJack F Vogel 			break;
3718cfa0ad2SJack F Vogel 		}
3721fd3c44fSJack F Vogel 		if (nvm->word_size == (1 << 15))
373f0ecc46dSJack F Vogel 			nvm->page_size = 128;
3748cfa0ad2SJack F Vogel 
375ab5d0362SJack F Vogel 		nvm->type = e1000_nvm_eeprom_spi;
376ab5d0362SJack F Vogel 	} else {
377ab5d0362SJack F Vogel 		nvm->type = e1000_nvm_flash_hw;
378ab5d0362SJack F Vogel 	}
3796ab6bfe3SJack F Vogel 
3808cfa0ad2SJack F Vogel 	/* Function Pointers */
3818cfa0ad2SJack F Vogel 	nvm->ops.acquire = e1000_acquire_nvm_82575;
3828cfa0ad2SJack F Vogel 	nvm->ops.release = e1000_release_nvm_82575;
3831fd3c44fSJack F Vogel 	if (nvm->word_size < (1 << 15))
3841fd3c44fSJack F Vogel 		nvm->ops.read = e1000_read_nvm_eerd;
3851fd3c44fSJack F Vogel 	else
3861fd3c44fSJack F Vogel 		nvm->ops.read = e1000_read_nvm_spi;
3871fd3c44fSJack F Vogel 
3881fd3c44fSJack F Vogel 	nvm->ops.write = e1000_write_nvm_spi;
3891fd3c44fSJack F Vogel 	nvm->ops.validate = e1000_validate_nvm_checksum_generic;
3901fd3c44fSJack F Vogel 	nvm->ops.update = e1000_update_nvm_checksum_generic;
3918cfa0ad2SJack F Vogel 	nvm->ops.valid_led_default = e1000_valid_led_default_82575;
3921fd3c44fSJack F Vogel 
393ab5d0362SJack F Vogel 	/* override generic family function pointers for specific descendants */
394f0ecc46dSJack F Vogel 	switch (hw->mac.type) {
395f0ecc46dSJack F Vogel 	case e1000_82580:
396f0ecc46dSJack F Vogel 		nvm->ops.validate = e1000_validate_nvm_checksum_82580;
397f0ecc46dSJack F Vogel 		nvm->ops.update = e1000_update_nvm_checksum_82580;
398f0ecc46dSJack F Vogel 		break;
399f0ecc46dSJack F Vogel 	case e1000_i350:
4007609433eSJack F Vogel 	case e1000_i354:
401f0ecc46dSJack F Vogel 		nvm->ops.validate = e1000_validate_nvm_checksum_i350;
402f0ecc46dSJack F Vogel 		nvm->ops.update = e1000_update_nvm_checksum_i350;
403f0ecc46dSJack F Vogel 		break;
404f0ecc46dSJack F Vogel 	default:
4051fd3c44fSJack F Vogel 		break;
406f0ecc46dSJack F Vogel 	}
4078cfa0ad2SJack F Vogel 
4088cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
4098cfa0ad2SJack F Vogel }
4108cfa0ad2SJack F Vogel 
4118cfa0ad2SJack F Vogel /**
4128cfa0ad2SJack F Vogel  *  e1000_init_mac_params_82575 - Init MAC func ptrs.
4138cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
4148cfa0ad2SJack F Vogel  **/
4158cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
4168cfa0ad2SJack F Vogel {
4178cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
418daf9197cSJack F Vogel 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
4198cfa0ad2SJack F Vogel 
4208cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_mac_params_82575");
4218cfa0ad2SJack F Vogel 
4224dab5c37SJack F Vogel 	/* Derives media type */
4234dab5c37SJack F Vogel 	e1000_get_media_type_82575(hw);
4248cfa0ad2SJack F Vogel 	/* Set mta register count */
4258cfa0ad2SJack F Vogel 	mac->mta_reg_count = 128;
4264edd8523SJack F Vogel 	/* Set uta register count */
4274edd8523SJack F Vogel 	mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128;
4288cfa0ad2SJack F Vogel 	/* Set rar entry count */
4298cfa0ad2SJack F Vogel 	mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
4308cfa0ad2SJack F Vogel 	if (mac->type == e1000_82576)
4318cfa0ad2SJack F Vogel 		mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
432a69ed8dfSJack F Vogel 	if (mac->type == e1000_82580)
4334edd8523SJack F Vogel 		mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
4347609433eSJack F Vogel 	if (mac->type == e1000_i350 || mac->type == e1000_i354)
435f0ecc46dSJack F Vogel 		mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
4366ab6bfe3SJack F Vogel 
4376ab6bfe3SJack F Vogel 	/* Enable EEE default settings for EEE supported devices */
4386ab6bfe3SJack F Vogel 	if (mac->type >= e1000_i350)
439f0ecc46dSJack F Vogel 		dev_spec->eee_disable = FALSE;
4406ab6bfe3SJack F Vogel 
4416ab6bfe3SJack F Vogel 	/* Allow a single clear of the SW semaphore on I210 and newer */
4426ab6bfe3SJack F Vogel 	if (mac->type >= e1000_i210)
4436ab6bfe3SJack F Vogel 		dev_spec->clear_semaphore_once = TRUE;
444f0ecc46dSJack F Vogel 
4458cfa0ad2SJack F Vogel 	/* Set if part includes ASF firmware */
4468cfa0ad2SJack F Vogel 	mac->asf_firmware_present = TRUE;
4478ec87fc5SJack F Vogel 	/* FWSM register */
4488ec87fc5SJack F Vogel 	mac->has_fwsm = TRUE;
4498ec87fc5SJack F Vogel 	/* ARC supported; valid only if manageability features are enabled. */
4508cfa0ad2SJack F Vogel 	mac->arc_subsystem_valid =
451ab5d0362SJack F Vogel 		!!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK);
4528cfa0ad2SJack F Vogel 
4538cfa0ad2SJack F Vogel 	/* Function pointers */
4548cfa0ad2SJack F Vogel 
4558cfa0ad2SJack F Vogel 	/* bus type/speed/width */
4568cfa0ad2SJack F Vogel 	mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
4578cfa0ad2SJack F Vogel 	/* reset */
458a69ed8dfSJack F Vogel 	if (mac->type >= e1000_82580)
4594edd8523SJack F Vogel 		mac->ops.reset_hw = e1000_reset_hw_82580;
4604edd8523SJack F Vogel 	else
4618cfa0ad2SJack F Vogel 	mac->ops.reset_hw = e1000_reset_hw_82575;
4628cfa0ad2SJack F Vogel 	/* hw initialization */
4638cc64f1eSJack F Vogel 	if ((mac->type == e1000_i210) || (mac->type == e1000_i211))
4648cc64f1eSJack F Vogel 		mac->ops.init_hw = e1000_init_hw_i210;
4658cc64f1eSJack F Vogel 	else
4668cfa0ad2SJack F Vogel 	mac->ops.init_hw = e1000_init_hw_82575;
4678cfa0ad2SJack F Vogel 	/* link setup */
4688cfa0ad2SJack F Vogel 	mac->ops.setup_link = e1000_setup_link_generic;
4698cfa0ad2SJack F Vogel 	/* physical interface link setup */
4708cfa0ad2SJack F Vogel 	mac->ops.setup_physical_interface =
4718cfa0ad2SJack F Vogel 		(hw->phy.media_type == e1000_media_type_copper)
4724dab5c37SJack F Vogel 		? e1000_setup_copper_link_82575 : e1000_setup_serdes_link_82575;
4738cfa0ad2SJack F Vogel 	/* physical interface shutdown */
4744edd8523SJack F Vogel 	mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575;
475a69ed8dfSJack F Vogel 	/* physical interface power up */
476a69ed8dfSJack F Vogel 	mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575;
4778cfa0ad2SJack F Vogel 	/* check for link */
4788cfa0ad2SJack F Vogel 	mac->ops.check_for_link = e1000_check_for_link_82575;
4798cfa0ad2SJack F Vogel 	/* read mac address */
4808cfa0ad2SJack F Vogel 	mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
481a69ed8dfSJack F Vogel 	/* configure collision distance */
482a69ed8dfSJack F Vogel 	mac->ops.config_collision_dist = e1000_config_collision_dist_82575;
4838cfa0ad2SJack F Vogel 	/* multicast address update */
484d035aa2dSJack F Vogel 	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
4857609433eSJack F Vogel 	if (hw->mac.type == e1000_i350 || mac->type == e1000_i354) {
4864dab5c37SJack F Vogel 		/* writing VFTA */
4874dab5c37SJack F Vogel 		mac->ops.write_vfta = e1000_write_vfta_i350;
4884dab5c37SJack F Vogel 		/* clearing VFTA */
4894dab5c37SJack F Vogel 		mac->ops.clear_vfta = e1000_clear_vfta_i350;
4904dab5c37SJack F Vogel 	} else {
4918cfa0ad2SJack F Vogel 		/* writing VFTA */
4928cfa0ad2SJack F Vogel 		mac->ops.write_vfta = e1000_write_vfta_generic;
4938cfa0ad2SJack F Vogel 		/* clearing VFTA */
4948cfa0ad2SJack F Vogel 		mac->ops.clear_vfta = e1000_clear_vfta_generic;
4954dab5c37SJack F Vogel 	}
4966ab6bfe3SJack F Vogel 	if (hw->mac.type >= e1000_82580)
4976ab6bfe3SJack F Vogel 		mac->ops.validate_mdi_setting =
4986ab6bfe3SJack F Vogel 				e1000_validate_mdi_setting_crossover_generic;
499d035aa2dSJack F Vogel 	/* ID LED init */
500d035aa2dSJack F Vogel 	mac->ops.id_led_init = e1000_id_led_init_generic;
5018cfa0ad2SJack F Vogel 	/* blink LED */
5028cfa0ad2SJack F Vogel 	mac->ops.blink_led = e1000_blink_led_generic;
5038cfa0ad2SJack F Vogel 	/* setup LED */
5048cfa0ad2SJack F Vogel 	mac->ops.setup_led = e1000_setup_led_generic;
5058cfa0ad2SJack F Vogel 	/* cleanup LED */
5068cfa0ad2SJack F Vogel 	mac->ops.cleanup_led = e1000_cleanup_led_generic;
5078cfa0ad2SJack F Vogel 	/* turn on/off LED */
5088cfa0ad2SJack F Vogel 	mac->ops.led_on = e1000_led_on_generic;
5098cfa0ad2SJack F Vogel 	mac->ops.led_off = e1000_led_off_generic;
5108cfa0ad2SJack F Vogel 	/* clear hardware counters */
5118cfa0ad2SJack F Vogel 	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575;
5128cfa0ad2SJack F Vogel 	/* link info */
5138cfa0ad2SJack F Vogel 	mac->ops.get_link_up_info = e1000_get_link_up_info_82575;
514ab5d0362SJack F Vogel 	/* acquire SW_FW sync */
515ab5d0362SJack F Vogel 	mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575;
516ab5d0362SJack F Vogel 	mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575;
517ab5d0362SJack F Vogel 	if (mac->type >= e1000_i210) {
518ab5d0362SJack F Vogel 		mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210;
519ab5d0362SJack F Vogel 		mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210;
520ab5d0362SJack F Vogel 	}
5218cfa0ad2SJack F Vogel 
5224edd8523SJack F Vogel 	/* set lan id for port to determine which phy lock to use */
5234edd8523SJack F Vogel 	hw->mac.ops.set_lan_id(hw);
5244edd8523SJack F Vogel 
525daf9197cSJack F Vogel 	return E1000_SUCCESS;
5268cfa0ad2SJack F Vogel }
5278cfa0ad2SJack F Vogel 
5288cfa0ad2SJack F Vogel /**
5298cfa0ad2SJack F Vogel  *  e1000_init_function_pointers_82575 - Init func ptrs.
5308cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5318cfa0ad2SJack F Vogel  *
532daf9197cSJack F Vogel  *  Called to initialize all function pointers and parameters.
5338cfa0ad2SJack F Vogel  **/
5348cfa0ad2SJack F Vogel void e1000_init_function_pointers_82575(struct e1000_hw *hw)
5358cfa0ad2SJack F Vogel {
5368cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_function_pointers_82575");
5378cfa0ad2SJack F Vogel 
5388cfa0ad2SJack F Vogel 	hw->mac.ops.init_params = e1000_init_mac_params_82575;
5398cfa0ad2SJack F Vogel 	hw->nvm.ops.init_params = e1000_init_nvm_params_82575;
5408cfa0ad2SJack F Vogel 	hw->phy.ops.init_params = e1000_init_phy_params_82575;
5417d9119bdSJack F Vogel 	hw->mbx.ops.init_params = e1000_init_mbx_params_pf;
5428cfa0ad2SJack F Vogel }
5438cfa0ad2SJack F Vogel 
5448cfa0ad2SJack F Vogel /**
5458cfa0ad2SJack F Vogel  *  e1000_acquire_phy_82575 - Acquire rights to access PHY
5468cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5478cfa0ad2SJack F Vogel  *
548daf9197cSJack F Vogel  *  Acquire access rights to the correct PHY.
5498cfa0ad2SJack F Vogel  **/
5508cfa0ad2SJack F Vogel static s32 e1000_acquire_phy_82575(struct e1000_hw *hw)
5518cfa0ad2SJack F Vogel {
5529d81738fSJack F Vogel 	u16 mask = E1000_SWFW_PHY0_SM;
5538cfa0ad2SJack F Vogel 
5548cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_acquire_phy_82575");
5558cfa0ad2SJack F Vogel 
5569d81738fSJack F Vogel 	if (hw->bus.func == E1000_FUNC_1)
5579d81738fSJack F Vogel 		mask = E1000_SWFW_PHY1_SM;
5584edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_2)
5594edd8523SJack F Vogel 		mask = E1000_SWFW_PHY2_SM;
5604edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_3)
5614edd8523SJack F Vogel 		mask = E1000_SWFW_PHY3_SM;
5628cfa0ad2SJack F Vogel 
563ab5d0362SJack F Vogel 	return hw->mac.ops.acquire_swfw_sync(hw, mask);
5648cfa0ad2SJack F Vogel }
5658cfa0ad2SJack F Vogel 
5668cfa0ad2SJack F Vogel /**
5678cfa0ad2SJack F Vogel  *  e1000_release_phy_82575 - Release rights to access PHY
5688cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5698cfa0ad2SJack F Vogel  *
570daf9197cSJack F Vogel  *  A wrapper to release access rights to the correct PHY.
5718cfa0ad2SJack F Vogel  **/
5728cfa0ad2SJack F Vogel static void e1000_release_phy_82575(struct e1000_hw *hw)
5738cfa0ad2SJack F Vogel {
5749d81738fSJack F Vogel 	u16 mask = E1000_SWFW_PHY0_SM;
5758cfa0ad2SJack F Vogel 
5768cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_release_phy_82575");
5778cfa0ad2SJack F Vogel 
5789d81738fSJack F Vogel 	if (hw->bus.func == E1000_FUNC_1)
5799d81738fSJack F Vogel 		mask = E1000_SWFW_PHY1_SM;
5804edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_2)
5814edd8523SJack F Vogel 		mask = E1000_SWFW_PHY2_SM;
5824edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_3)
5834edd8523SJack F Vogel 		mask = E1000_SWFW_PHY3_SM;
5849d81738fSJack F Vogel 
585ab5d0362SJack F Vogel 	hw->mac.ops.release_swfw_sync(hw, mask);
5868cfa0ad2SJack F Vogel }
5878cfa0ad2SJack F Vogel 
5888cfa0ad2SJack F Vogel /**
5898cfa0ad2SJack F Vogel  *  e1000_read_phy_reg_sgmii_82575 - Read PHY register using sgmii
5908cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5918cfa0ad2SJack F Vogel  *  @offset: register offset to be read
5928cfa0ad2SJack F Vogel  *  @data: pointer to the read data
5938cfa0ad2SJack F Vogel  *
5948cfa0ad2SJack F Vogel  *  Reads the PHY register at offset using the serial gigabit media independent
5958cfa0ad2SJack F Vogel  *  interface and stores the retrieved information in data.
5968cfa0ad2SJack F Vogel  **/
5978cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
5988cfa0ad2SJack F Vogel 					  u16 *data)
5998cfa0ad2SJack F Vogel {
6004edd8523SJack F Vogel 	s32 ret_val = -E1000_ERR_PARAM;
6018cfa0ad2SJack F Vogel 
6028cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_read_phy_reg_sgmii_82575");
6038cfa0ad2SJack F Vogel 
6048cfa0ad2SJack F Vogel 	if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
6058cfa0ad2SJack F Vogel 		DEBUGOUT1("PHY Address %u is out of range\n", offset);
6064edd8523SJack F Vogel 		goto out;
6078cfa0ad2SJack F Vogel 	}
6088cfa0ad2SJack F Vogel 
6094edd8523SJack F Vogel 	ret_val = hw->phy.ops.acquire(hw);
6104edd8523SJack F Vogel 	if (ret_val)
6114edd8523SJack F Vogel 		goto out;
6128cfa0ad2SJack F Vogel 
6134edd8523SJack F Vogel 	ret_val = e1000_read_phy_reg_i2c(hw, offset, data);
6148cfa0ad2SJack F Vogel 
6154edd8523SJack F Vogel 	hw->phy.ops.release(hw);
6168cfa0ad2SJack F Vogel 
6174edd8523SJack F Vogel out:
6184edd8523SJack F Vogel 	return ret_val;
6198cfa0ad2SJack F Vogel }
6208cfa0ad2SJack F Vogel 
6218cfa0ad2SJack F Vogel /**
6228cfa0ad2SJack F Vogel  *  e1000_write_phy_reg_sgmii_82575 - Write PHY register using sgmii
6238cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
6248cfa0ad2SJack F Vogel  *  @offset: register offset to write to
6258cfa0ad2SJack F Vogel  *  @data: data to write at register offset
6268cfa0ad2SJack F Vogel  *
6278cfa0ad2SJack F Vogel  *  Writes the data to PHY register at the offset using the serial gigabit
6288cfa0ad2SJack F Vogel  *  media independent interface.
6298cfa0ad2SJack F Vogel  **/
6308cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
6318cfa0ad2SJack F Vogel 					   u16 data)
6328cfa0ad2SJack F Vogel {
6334edd8523SJack F Vogel 	s32 ret_val = -E1000_ERR_PARAM;
6348cfa0ad2SJack F Vogel 
6358cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_write_phy_reg_sgmii_82575");
6368cfa0ad2SJack F Vogel 
6378cfa0ad2SJack F Vogel 	if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
6388cfa0ad2SJack F Vogel 		DEBUGOUT1("PHY Address %d is out of range\n", offset);
6394edd8523SJack F Vogel 		goto out;
6408cfa0ad2SJack F Vogel 	}
6418cfa0ad2SJack F Vogel 
6424edd8523SJack F Vogel 	ret_val = hw->phy.ops.acquire(hw);
6434edd8523SJack F Vogel 	if (ret_val)
6444edd8523SJack F Vogel 		goto out;
6458cfa0ad2SJack F Vogel 
6464edd8523SJack F Vogel 	ret_val = e1000_write_phy_reg_i2c(hw, offset, data);
6478cfa0ad2SJack F Vogel 
6484edd8523SJack F Vogel 	hw->phy.ops.release(hw);
6498cfa0ad2SJack F Vogel 
6504edd8523SJack F Vogel out:
6514edd8523SJack F Vogel 	return ret_val;
6528cfa0ad2SJack F Vogel }
6538cfa0ad2SJack F Vogel 
6548cfa0ad2SJack F Vogel /**
6558cfa0ad2SJack F Vogel  *  e1000_get_phy_id_82575 - Retrieve PHY addr and id
6568cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
6578cfa0ad2SJack F Vogel  *
6588cfa0ad2SJack F Vogel  *  Retrieves the PHY address and ID for both PHY's which do and do not use
6598cfa0ad2SJack F Vogel  *  sgmi interface.
6608cfa0ad2SJack F Vogel  **/
6618cfa0ad2SJack F Vogel static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
6628cfa0ad2SJack F Vogel {
6638cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
6648cfa0ad2SJack F Vogel 	s32  ret_val = E1000_SUCCESS;
6658cfa0ad2SJack F Vogel 	u16 phy_id;
6664edd8523SJack F Vogel 	u32 ctrl_ext;
6677d9119bdSJack F Vogel 	u32 mdic;
6688cfa0ad2SJack F Vogel 
6698cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_phy_id_82575");
6708cfa0ad2SJack F Vogel 
6717609433eSJack F Vogel 	/* some i354 devices need an extra read for phy id */
6727609433eSJack F Vogel 	if (hw->mac.type == e1000_i354)
6737609433eSJack F Vogel 		e1000_get_phy_id(hw);
6747609433eSJack F Vogel 
6758cfa0ad2SJack F Vogel 	/*
6768cfa0ad2SJack F Vogel 	 * For SGMII PHYs, we try the list of possible addresses until
6778cfa0ad2SJack F Vogel 	 * we find one that works.  For non-SGMII PHYs
6788cfa0ad2SJack F Vogel 	 * (e.g. integrated copper PHYs), an address of 1 should
6798cfa0ad2SJack F Vogel 	 * work.  The result of this function should mean phy->phy_addr
6808cfa0ad2SJack F Vogel 	 * and phy->id are set correctly.
6818cfa0ad2SJack F Vogel 	 */
6824edd8523SJack F Vogel 	if (!e1000_sgmii_active_82575(hw)) {
6838cfa0ad2SJack F Vogel 		phy->addr = 1;
6848cfa0ad2SJack F Vogel 		ret_val = e1000_get_phy_id(hw);
6858cfa0ad2SJack F Vogel 		goto out;
6868cfa0ad2SJack F Vogel 	}
6878cfa0ad2SJack F Vogel 
6887d9119bdSJack F Vogel 	if (e1000_sgmii_uses_mdio_82575(hw)) {
6897d9119bdSJack F Vogel 		switch (hw->mac.type) {
6907d9119bdSJack F Vogel 		case e1000_82575:
6917d9119bdSJack F Vogel 		case e1000_82576:
6927d9119bdSJack F Vogel 			mdic = E1000_READ_REG(hw, E1000_MDIC);
6937d9119bdSJack F Vogel 			mdic &= E1000_MDIC_PHY_MASK;
6947d9119bdSJack F Vogel 			phy->addr = mdic >> E1000_MDIC_PHY_SHIFT;
6957d9119bdSJack F Vogel 			break;
6967d9119bdSJack F Vogel 		case e1000_82580:
697f0ecc46dSJack F Vogel 		case e1000_i350:
6987609433eSJack F Vogel 		case e1000_i354:
6996ab6bfe3SJack F Vogel 		case e1000_i210:
7006ab6bfe3SJack F Vogel 		case e1000_i211:
7017d9119bdSJack F Vogel 			mdic = E1000_READ_REG(hw, E1000_MDICNFG);
7027d9119bdSJack F Vogel 			mdic &= E1000_MDICNFG_PHY_MASK;
7037d9119bdSJack F Vogel 			phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;
7047d9119bdSJack F Vogel 			break;
7057d9119bdSJack F Vogel 		default:
7067d9119bdSJack F Vogel 			ret_val = -E1000_ERR_PHY;
7077d9119bdSJack F Vogel 			goto out;
7087d9119bdSJack F Vogel 			break;
7097d9119bdSJack F Vogel 		}
7107d9119bdSJack F Vogel 		ret_val = e1000_get_phy_id(hw);
7117d9119bdSJack F Vogel 		goto out;
7127d9119bdSJack F Vogel 	}
7137d9119bdSJack F Vogel 
7144edd8523SJack F Vogel 	/* Power on sgmii phy if it is disabled */
7154edd8523SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
7164edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT,
7174edd8523SJack F Vogel 			ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA);
7184edd8523SJack F Vogel 	E1000_WRITE_FLUSH(hw);
7194edd8523SJack F Vogel 	msec_delay(300);
7204edd8523SJack F Vogel 
7218cfa0ad2SJack F Vogel 	/*
7228cfa0ad2SJack F Vogel 	 * The address field in the I2CCMD register is 3 bits and 0 is invalid.
7238cfa0ad2SJack F Vogel 	 * Therefore, we need to test 1-7
7248cfa0ad2SJack F Vogel 	 */
7258cfa0ad2SJack F Vogel 	for (phy->addr = 1; phy->addr < 8; phy->addr++) {
7268cfa0ad2SJack F Vogel 		ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id);
7278cfa0ad2SJack F Vogel 		if (ret_val == E1000_SUCCESS) {
7288cfa0ad2SJack F Vogel 			DEBUGOUT2("Vendor ID 0x%08X read at address %u\n",
7294dab5c37SJack F Vogel 				  phy_id, phy->addr);
7308cfa0ad2SJack F Vogel 			/*
7318cfa0ad2SJack F Vogel 			 * At the time of this writing, The M88 part is
7328cfa0ad2SJack F Vogel 			 * the only supported SGMII PHY product.
7338cfa0ad2SJack F Vogel 			 */
7348cfa0ad2SJack F Vogel 			if (phy_id == M88_VENDOR)
7358cfa0ad2SJack F Vogel 				break;
7368cfa0ad2SJack F Vogel 		} else {
7378cfa0ad2SJack F Vogel 			DEBUGOUT1("PHY address %u was unreadable\n",
7388cfa0ad2SJack F Vogel 				  phy->addr);
7398cfa0ad2SJack F Vogel 		}
7408cfa0ad2SJack F Vogel 	}
7418cfa0ad2SJack F Vogel 
7428cfa0ad2SJack F Vogel 	/* A valid PHY type couldn't be found. */
7438cfa0ad2SJack F Vogel 	if (phy->addr == 8) {
7448cfa0ad2SJack F Vogel 		phy->addr = 0;
7458cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PHY;
7464edd8523SJack F Vogel 	} else {
7474edd8523SJack F Vogel 		ret_val = e1000_get_phy_id(hw);
7488cfa0ad2SJack F Vogel 	}
7498cfa0ad2SJack F Vogel 
7504edd8523SJack F Vogel 	/* restore previous sfp cage power state */
7514edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
7528cfa0ad2SJack F Vogel 
7538cfa0ad2SJack F Vogel out:
7548cfa0ad2SJack F Vogel 	return ret_val;
7558cfa0ad2SJack F Vogel }
7568cfa0ad2SJack F Vogel 
7578cfa0ad2SJack F Vogel /**
7588cfa0ad2SJack F Vogel  *  e1000_phy_hw_reset_sgmii_82575 - Performs a PHY reset
7598cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
7608cfa0ad2SJack F Vogel  *
7618cfa0ad2SJack F Vogel  *  Resets the PHY using the serial gigabit media independent interface.
7628cfa0ad2SJack F Vogel  **/
7638cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw)
7648cfa0ad2SJack F Vogel {
7658cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
7668cc64f1eSJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
7678cfa0ad2SJack F Vogel 
7688cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575");
7698cfa0ad2SJack F Vogel 
7708cfa0ad2SJack F Vogel 	/*
7718cfa0ad2SJack F Vogel 	 * This isn't a TRUE "hard" reset, but is the only reset
7728cfa0ad2SJack F Vogel 	 * available to us at this time.
7738cfa0ad2SJack F Vogel 	 */
7748cfa0ad2SJack F Vogel 
7758cfa0ad2SJack F Vogel 	DEBUGOUT("Soft resetting SGMII attached PHY...\n");
7768cfa0ad2SJack F Vogel 
7778cfa0ad2SJack F Vogel 	if (!(hw->phy.ops.write_reg))
7788cfa0ad2SJack F Vogel 		goto out;
7798cfa0ad2SJack F Vogel 
7808cfa0ad2SJack F Vogel 	/*
7818cfa0ad2SJack F Vogel 	 * SFP documentation requires the following to configure the SPF module
7828cfa0ad2SJack F Vogel 	 * to work on SGMII.  No further documentation is given.
7838cfa0ad2SJack F Vogel 	 */
7848cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084);
7858cfa0ad2SJack F Vogel 	if (ret_val)
7868cfa0ad2SJack F Vogel 		goto out;
7878cfa0ad2SJack F Vogel 
7888cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.commit(hw);
7898cc64f1eSJack F Vogel 	if (ret_val)
7908cc64f1eSJack F Vogel 		goto out;
7918cfa0ad2SJack F Vogel 
7928cc64f1eSJack F Vogel 	if (phy->id == M88E1512_E_PHY_ID)
7938cc64f1eSJack F Vogel 		ret_val = e1000_initialize_M88E1512_phy(hw);
7948cfa0ad2SJack F Vogel out:
7958cfa0ad2SJack F Vogel 	return ret_val;
7968cfa0ad2SJack F Vogel }
7978cfa0ad2SJack F Vogel 
7988cfa0ad2SJack F Vogel /**
7998cfa0ad2SJack F Vogel  *  e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state
8008cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
8018cfa0ad2SJack F Vogel  *  @active: TRUE to enable LPLU, FALSE to disable
8028cfa0ad2SJack F Vogel  *
8038cfa0ad2SJack F Vogel  *  Sets the LPLU D0 state according to the active flag.  When
8048cfa0ad2SJack F Vogel  *  activating LPLU this function also disables smart speed
8058cfa0ad2SJack F Vogel  *  and vice versa.  LPLU will not be activated unless the
8068cfa0ad2SJack F Vogel  *  device autonegotiation advertisement meets standards of
8078cfa0ad2SJack F Vogel  *  either 10 or 10/100 or 10/100/1000 at all duplexes.
8088cfa0ad2SJack F Vogel  *  This is a function pointer entry point only called by
8098cfa0ad2SJack F Vogel  *  PHY setup routines.
8108cfa0ad2SJack F Vogel  **/
8118cfa0ad2SJack F Vogel static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active)
8128cfa0ad2SJack F Vogel {
8138cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
8148cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
8158cfa0ad2SJack F Vogel 	u16 data;
8168cfa0ad2SJack F Vogel 
8178cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_set_d0_lplu_state_82575");
8188cfa0ad2SJack F Vogel 
8198cfa0ad2SJack F Vogel 	if (!(hw->phy.ops.read_reg))
8208cfa0ad2SJack F Vogel 		goto out;
8218cfa0ad2SJack F Vogel 
8228cfa0ad2SJack F Vogel 	ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
8238cfa0ad2SJack F Vogel 	if (ret_val)
8248cfa0ad2SJack F Vogel 		goto out;
8258cfa0ad2SJack F Vogel 
8268cfa0ad2SJack F Vogel 	if (active) {
8278cfa0ad2SJack F Vogel 		data |= IGP02E1000_PM_D0_LPLU;
8288cfa0ad2SJack F Vogel 		ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
8298cfa0ad2SJack F Vogel 					     data);
8308cfa0ad2SJack F Vogel 		if (ret_val)
8318cfa0ad2SJack F Vogel 			goto out;
8328cfa0ad2SJack F Vogel 
8338cfa0ad2SJack F Vogel 		/* When LPLU is enabled, we should disable SmartSpeed */
8348cfa0ad2SJack F Vogel 		ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
8358cfa0ad2SJack F Vogel 					    &data);
8368cfa0ad2SJack F Vogel 		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
8378cfa0ad2SJack F Vogel 		ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
8388cfa0ad2SJack F Vogel 					     data);
8398cfa0ad2SJack F Vogel 		if (ret_val)
8408cfa0ad2SJack F Vogel 			goto out;
8418cfa0ad2SJack F Vogel 	} else {
8428cfa0ad2SJack F Vogel 		data &= ~IGP02E1000_PM_D0_LPLU;
8438cfa0ad2SJack F Vogel 		ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
8448cfa0ad2SJack F Vogel 					     data);
8458cfa0ad2SJack F Vogel 		/*
8468cfa0ad2SJack F Vogel 		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
8478cfa0ad2SJack F Vogel 		 * during Dx states where the power conservation is most
8488cfa0ad2SJack F Vogel 		 * important.  During driver activity we should enable
8498cfa0ad2SJack F Vogel 		 * SmartSpeed, so performance is maintained.
8508cfa0ad2SJack F Vogel 		 */
8518cfa0ad2SJack F Vogel 		if (phy->smart_speed == e1000_smart_speed_on) {
8528cfa0ad2SJack F Vogel 			ret_val = phy->ops.read_reg(hw,
8538cfa0ad2SJack F Vogel 						    IGP01E1000_PHY_PORT_CONFIG,
8548cfa0ad2SJack F Vogel 						    &data);
8558cfa0ad2SJack F Vogel 			if (ret_val)
8568cfa0ad2SJack F Vogel 				goto out;
8578cfa0ad2SJack F Vogel 
8588cfa0ad2SJack F Vogel 			data |= IGP01E1000_PSCFR_SMART_SPEED;
8598cfa0ad2SJack F Vogel 			ret_val = phy->ops.write_reg(hw,
8608cfa0ad2SJack F Vogel 						     IGP01E1000_PHY_PORT_CONFIG,
8618cfa0ad2SJack F Vogel 						     data);
8628cfa0ad2SJack F Vogel 			if (ret_val)
8638cfa0ad2SJack F Vogel 				goto out;
8648cfa0ad2SJack F Vogel 		} else if (phy->smart_speed == e1000_smart_speed_off) {
8658cfa0ad2SJack F Vogel 			ret_val = phy->ops.read_reg(hw,
8668cfa0ad2SJack F Vogel 						    IGP01E1000_PHY_PORT_CONFIG,
8678cfa0ad2SJack F Vogel 						    &data);
8688cfa0ad2SJack F Vogel 			if (ret_val)
8698cfa0ad2SJack F Vogel 				goto out;
8708cfa0ad2SJack F Vogel 
8718cfa0ad2SJack F Vogel 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
8728cfa0ad2SJack F Vogel 			ret_val = phy->ops.write_reg(hw,
8738cfa0ad2SJack F Vogel 						     IGP01E1000_PHY_PORT_CONFIG,
8748cfa0ad2SJack F Vogel 						     data);
8758cfa0ad2SJack F Vogel 			if (ret_val)
8768cfa0ad2SJack F Vogel 				goto out;
8778cfa0ad2SJack F Vogel 		}
8788cfa0ad2SJack F Vogel 	}
8798cfa0ad2SJack F Vogel 
8808cfa0ad2SJack F Vogel out:
8818cfa0ad2SJack F Vogel 	return ret_val;
8828cfa0ad2SJack F Vogel }
8838cfa0ad2SJack F Vogel 
8848cfa0ad2SJack F Vogel /**
885f0ecc46dSJack F Vogel  *  e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state
886f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
887f0ecc46dSJack F Vogel  *  @active: TRUE to enable LPLU, FALSE to disable
888f0ecc46dSJack F Vogel  *
889f0ecc46dSJack F Vogel  *  Sets the LPLU D0 state according to the active flag.  When
890f0ecc46dSJack F Vogel  *  activating LPLU this function also disables smart speed
891f0ecc46dSJack F Vogel  *  and vice versa.  LPLU will not be activated unless the
892f0ecc46dSJack F Vogel  *  device autonegotiation advertisement meets standards of
893f0ecc46dSJack F Vogel  *  either 10 or 10/100 or 10/100/1000 at all duplexes.
894f0ecc46dSJack F Vogel  *  This is a function pointer entry point only called by
895f0ecc46dSJack F Vogel  *  PHY setup routines.
896f0ecc46dSJack F Vogel  **/
897f0ecc46dSJack F Vogel static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active)
898f0ecc46dSJack F Vogel {
899f0ecc46dSJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
900ab5d0362SJack F Vogel 	u32 data;
901f0ecc46dSJack F Vogel 
902f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_set_d0_lplu_state_82580");
903f0ecc46dSJack F Vogel 
904f0ecc46dSJack F Vogel 	data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
905f0ecc46dSJack F Vogel 
906f0ecc46dSJack F Vogel 	if (active) {
907f0ecc46dSJack F Vogel 		data |= E1000_82580_PM_D0_LPLU;
908f0ecc46dSJack F Vogel 
909f0ecc46dSJack F Vogel 		/* When LPLU is enabled, we should disable SmartSpeed */
910f0ecc46dSJack F Vogel 		data &= ~E1000_82580_PM_SPD;
911f0ecc46dSJack F Vogel 	} else {
912f0ecc46dSJack F Vogel 		data &= ~E1000_82580_PM_D0_LPLU;
913f0ecc46dSJack F Vogel 
914f0ecc46dSJack F Vogel 		/*
915f0ecc46dSJack F Vogel 		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
916f0ecc46dSJack F Vogel 		 * during Dx states where the power conservation is most
917f0ecc46dSJack F Vogel 		 * important.  During driver activity we should enable
918f0ecc46dSJack F Vogel 		 * SmartSpeed, so performance is maintained.
919f0ecc46dSJack F Vogel 		 */
9204dab5c37SJack F Vogel 		if (phy->smart_speed == e1000_smart_speed_on)
921f0ecc46dSJack F Vogel 			data |= E1000_82580_PM_SPD;
9224dab5c37SJack F Vogel 		else if (phy->smart_speed == e1000_smart_speed_off)
923f0ecc46dSJack F Vogel 			data &= ~E1000_82580_PM_SPD;
924f0ecc46dSJack F Vogel 	}
925f0ecc46dSJack F Vogel 
926f0ecc46dSJack F Vogel 	E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
9278cc64f1eSJack F Vogel 	return E1000_SUCCESS;
928f0ecc46dSJack F Vogel }
929f0ecc46dSJack F Vogel 
930f0ecc46dSJack F Vogel /**
931f0ecc46dSJack F Vogel  *  e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3
932f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
933f0ecc46dSJack F Vogel  *  @active: boolean used to enable/disable lplu
934f0ecc46dSJack F Vogel  *
935f0ecc46dSJack F Vogel  *  Success returns 0, Failure returns 1
936f0ecc46dSJack F Vogel  *
937f0ecc46dSJack F Vogel  *  The low power link up (lplu) state is set to the power management level D3
938f0ecc46dSJack F Vogel  *  and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
939f0ecc46dSJack F Vogel  *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
940f0ecc46dSJack F Vogel  *  is used during Dx states where the power conservation is most important.
941f0ecc46dSJack F Vogel  *  During driver activity, SmartSpeed should be enabled so performance is
942f0ecc46dSJack F Vogel  *  maintained.
943f0ecc46dSJack F Vogel  **/
944f0ecc46dSJack F Vogel s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active)
945f0ecc46dSJack F Vogel {
946f0ecc46dSJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
947ab5d0362SJack F Vogel 	u32 data;
948f0ecc46dSJack F Vogel 
949f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_set_d3_lplu_state_82580");
950f0ecc46dSJack F Vogel 
951f0ecc46dSJack F Vogel 	data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
952f0ecc46dSJack F Vogel 
953f0ecc46dSJack F Vogel 	if (!active) {
954f0ecc46dSJack F Vogel 		data &= ~E1000_82580_PM_D3_LPLU;
955f0ecc46dSJack F Vogel 		/*
956f0ecc46dSJack F Vogel 		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
957f0ecc46dSJack F Vogel 		 * during Dx states where the power conservation is most
958f0ecc46dSJack F Vogel 		 * important.  During driver activity we should enable
959f0ecc46dSJack F Vogel 		 * SmartSpeed, so performance is maintained.
960f0ecc46dSJack F Vogel 		 */
9614dab5c37SJack F Vogel 		if (phy->smart_speed == e1000_smart_speed_on)
962f0ecc46dSJack F Vogel 			data |= E1000_82580_PM_SPD;
9634dab5c37SJack F Vogel 		else if (phy->smart_speed == e1000_smart_speed_off)
964f0ecc46dSJack F Vogel 			data &= ~E1000_82580_PM_SPD;
965f0ecc46dSJack F Vogel 	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
966f0ecc46dSJack F Vogel 		   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
967f0ecc46dSJack F Vogel 		   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
968f0ecc46dSJack F Vogel 		data |= E1000_82580_PM_D3_LPLU;
969f0ecc46dSJack F Vogel 		/* When LPLU is enabled, we should disable SmartSpeed */
970f0ecc46dSJack F Vogel 		data &= ~E1000_82580_PM_SPD;
971f0ecc46dSJack F Vogel 	}
972f0ecc46dSJack F Vogel 
973f0ecc46dSJack F Vogel 	E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
9748cc64f1eSJack F Vogel 	return E1000_SUCCESS;
975f0ecc46dSJack F Vogel }
976f0ecc46dSJack F Vogel 
977f0ecc46dSJack F Vogel /**
9788cfa0ad2SJack F Vogel  *  e1000_acquire_nvm_82575 - Request for access to EEPROM
9798cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
9808cfa0ad2SJack F Vogel  *
9818cfa0ad2SJack F Vogel  *  Acquire the necessary semaphores for exclusive access to the EEPROM.
9828cfa0ad2SJack F Vogel  *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
9838cfa0ad2SJack F Vogel  *  Return successful if access grant bit set, else clear the request for
9848cfa0ad2SJack F Vogel  *  EEPROM access and return -E1000_ERR_NVM (-1).
9858cfa0ad2SJack F Vogel  **/
9868cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw)
9878cfa0ad2SJack F Vogel {
9888cc64f1eSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
9898cfa0ad2SJack F Vogel 
9908cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_acquire_nvm_82575");
9918cfa0ad2SJack F Vogel 
9928cfa0ad2SJack F Vogel 	ret_val = e1000_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
9938cfa0ad2SJack F Vogel 	if (ret_val)
9948cfa0ad2SJack F Vogel 		goto out;
9954dab5c37SJack F Vogel 
9964dab5c37SJack F Vogel 	/*
9974dab5c37SJack F Vogel 	 * Check if there is some access
9984dab5c37SJack F Vogel 	 * error this access may hook on
9994dab5c37SJack F Vogel 	 */
10004dab5c37SJack F Vogel 	if (hw->mac.type == e1000_i350) {
10014dab5c37SJack F Vogel 		u32 eecd = E1000_READ_REG(hw, E1000_EECD);
10024dab5c37SJack F Vogel 		if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT |
10034dab5c37SJack F Vogel 		    E1000_EECD_TIMEOUT)) {
10044dab5c37SJack F Vogel 			/* Clear all access error flags */
10054dab5c37SJack F Vogel 			E1000_WRITE_REG(hw, E1000_EECD, eecd |
10064dab5c37SJack F Vogel 					E1000_EECD_ERROR_CLR);
10074dab5c37SJack F Vogel 			DEBUGOUT("Nvm bit banging access error detected and cleared.\n");
10084dab5c37SJack F Vogel 		}
10094dab5c37SJack F Vogel 	}
10108cc64f1eSJack F Vogel 
10114dab5c37SJack F Vogel 	if (hw->mac.type == e1000_82580) {
10124dab5c37SJack F Vogel 		u32 eecd = E1000_READ_REG(hw, E1000_EECD);
10134dab5c37SJack F Vogel 		if (eecd & E1000_EECD_BLOCKED) {
10144dab5c37SJack F Vogel 			/* Clear access error flag */
10154dab5c37SJack F Vogel 			E1000_WRITE_REG(hw, E1000_EECD, eecd |
10164dab5c37SJack F Vogel 					E1000_EECD_BLOCKED);
10174dab5c37SJack F Vogel 			DEBUGOUT("Nvm bit banging access error detected and cleared.\n");
10184dab5c37SJack F Vogel 		}
10194dab5c37SJack F Vogel 	}
10204dab5c37SJack F Vogel 
10218cfa0ad2SJack F Vogel 	ret_val = e1000_acquire_nvm_generic(hw);
10228cfa0ad2SJack F Vogel 	if (ret_val)
10238cfa0ad2SJack F Vogel 		e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
10248cfa0ad2SJack F Vogel 
10258cfa0ad2SJack F Vogel out:
10268cfa0ad2SJack F Vogel 	return ret_val;
10278cfa0ad2SJack F Vogel }
10288cfa0ad2SJack F Vogel 
10298cfa0ad2SJack F Vogel /**
10308cfa0ad2SJack F Vogel  *  e1000_release_nvm_82575 - Release exclusive access to EEPROM
10318cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
10328cfa0ad2SJack F Vogel  *
10338cfa0ad2SJack F Vogel  *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
10348cfa0ad2SJack F Vogel  *  then release the semaphores acquired.
10358cfa0ad2SJack F Vogel  **/
10368cfa0ad2SJack F Vogel static void e1000_release_nvm_82575(struct e1000_hw *hw)
10378cfa0ad2SJack F Vogel {
10388cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_release_nvm_82575");
10398cfa0ad2SJack F Vogel 
10404dab5c37SJack F Vogel 	e1000_release_nvm_generic(hw);
1041ab5d0362SJack F Vogel 
10428cfa0ad2SJack F Vogel 	e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
10438cfa0ad2SJack F Vogel }
10448cfa0ad2SJack F Vogel 
10458cfa0ad2SJack F Vogel /**
10468cfa0ad2SJack F Vogel  *  e1000_acquire_swfw_sync_82575 - Acquire SW/FW semaphore
10478cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
10488cfa0ad2SJack F Vogel  *  @mask: specifies which semaphore to acquire
10498cfa0ad2SJack F Vogel  *
10508cfa0ad2SJack F Vogel  *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
10518cfa0ad2SJack F Vogel  *  will also specify which port we're acquiring the lock for.
10528cfa0ad2SJack F Vogel  **/
10538cfa0ad2SJack F Vogel static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
10548cfa0ad2SJack F Vogel {
10558cfa0ad2SJack F Vogel 	u32 swfw_sync;
10568cfa0ad2SJack F Vogel 	u32 swmask = mask;
10578cfa0ad2SJack F Vogel 	u32 fwmask = mask << 16;
10588cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
105948600901SSean Bruno 	s32 i = 0, timeout = 200;
10608cfa0ad2SJack F Vogel 
10618cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_acquire_swfw_sync_82575");
10628cfa0ad2SJack F Vogel 
10638cfa0ad2SJack F Vogel 	while (i < timeout) {
10648cfa0ad2SJack F Vogel 		if (e1000_get_hw_semaphore_generic(hw)) {
10658cfa0ad2SJack F Vogel 			ret_val = -E1000_ERR_SWFW_SYNC;
10668cfa0ad2SJack F Vogel 			goto out;
10678cfa0ad2SJack F Vogel 		}
10688cfa0ad2SJack F Vogel 
10698cfa0ad2SJack F Vogel 		swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
10708cfa0ad2SJack F Vogel 		if (!(swfw_sync & (fwmask | swmask)))
10718cfa0ad2SJack F Vogel 			break;
10728cfa0ad2SJack F Vogel 
10738cfa0ad2SJack F Vogel 		/*
10748cfa0ad2SJack F Vogel 		 * Firmware currently using resource (fwmask)
10758cfa0ad2SJack F Vogel 		 * or other software thread using resource (swmask)
10768cfa0ad2SJack F Vogel 		 */
10778cfa0ad2SJack F Vogel 		e1000_put_hw_semaphore_generic(hw);
10788cfa0ad2SJack F Vogel 		msec_delay_irq(5);
10798cfa0ad2SJack F Vogel 		i++;
10808cfa0ad2SJack F Vogel 	}
10818cfa0ad2SJack F Vogel 
10828cfa0ad2SJack F Vogel 	if (i == timeout) {
10838cfa0ad2SJack F Vogel 		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
10848cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_SWFW_SYNC;
10858cfa0ad2SJack F Vogel 		goto out;
10868cfa0ad2SJack F Vogel 	}
10878cfa0ad2SJack F Vogel 
10888cfa0ad2SJack F Vogel 	swfw_sync |= swmask;
10898cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
10908cfa0ad2SJack F Vogel 
10918cfa0ad2SJack F Vogel 	e1000_put_hw_semaphore_generic(hw);
10928cfa0ad2SJack F Vogel 
10938cfa0ad2SJack F Vogel out:
10948cfa0ad2SJack F Vogel 	return ret_val;
10958cfa0ad2SJack F Vogel }
10968cfa0ad2SJack F Vogel 
10978cfa0ad2SJack F Vogel /**
10988cfa0ad2SJack F Vogel  *  e1000_release_swfw_sync_82575 - Release SW/FW semaphore
10998cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
11008cfa0ad2SJack F Vogel  *  @mask: specifies which semaphore to acquire
11018cfa0ad2SJack F Vogel  *
11028cfa0ad2SJack F Vogel  *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
11038cfa0ad2SJack F Vogel  *  will also specify which port we're releasing the lock for.
11048cfa0ad2SJack F Vogel  **/
11058cfa0ad2SJack F Vogel static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
11068cfa0ad2SJack F Vogel {
11078cfa0ad2SJack F Vogel 	u32 swfw_sync;
11088cfa0ad2SJack F Vogel 
11098cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_release_swfw_sync_82575");
11108cfa0ad2SJack F Vogel 
11114dab5c37SJack F Vogel 	while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS)
11124dab5c37SJack F Vogel 		; /* Empty */
11138cfa0ad2SJack F Vogel 
11148cfa0ad2SJack F Vogel 	swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
11158cfa0ad2SJack F Vogel 	swfw_sync &= ~mask;
11168cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
11178cfa0ad2SJack F Vogel 
11188cfa0ad2SJack F Vogel 	e1000_put_hw_semaphore_generic(hw);
11198cfa0ad2SJack F Vogel }
11208cfa0ad2SJack F Vogel 
11218cfa0ad2SJack F Vogel /**
11228cfa0ad2SJack F Vogel  *  e1000_get_cfg_done_82575 - Read config done bit
11238cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
11248cfa0ad2SJack F Vogel  *
11258cfa0ad2SJack F Vogel  *  Read the management control register for the config done bit for
11268cfa0ad2SJack F Vogel  *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
11278cfa0ad2SJack F Vogel  *  to read the config done bit, so an error is *ONLY* logged and returns
11288cfa0ad2SJack F Vogel  *  E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon
11298cfa0ad2SJack F Vogel  *  would not be able to be reset or change link.
11308cfa0ad2SJack F Vogel  **/
11318cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw)
11328cfa0ad2SJack F Vogel {
11338cfa0ad2SJack F Vogel 	s32 timeout = PHY_CFG_TIMEOUT;
11348cfa0ad2SJack F Vogel 	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
11358cfa0ad2SJack F Vogel 
11368cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_cfg_done_82575");
11378cfa0ad2SJack F Vogel 
11389d81738fSJack F Vogel 	if (hw->bus.func == E1000_FUNC_1)
11398cfa0ad2SJack F Vogel 		mask = E1000_NVM_CFG_DONE_PORT_1;
11404edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_2)
11414edd8523SJack F Vogel 		mask = E1000_NVM_CFG_DONE_PORT_2;
11424edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_3)
11434edd8523SJack F Vogel 		mask = E1000_NVM_CFG_DONE_PORT_3;
11448cfa0ad2SJack F Vogel 	while (timeout) {
11458cfa0ad2SJack F Vogel 		if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask)
11468cfa0ad2SJack F Vogel 			break;
11478cfa0ad2SJack F Vogel 		msec_delay(1);
11488cfa0ad2SJack F Vogel 		timeout--;
11498cfa0ad2SJack F Vogel 	}
11504edd8523SJack F Vogel 	if (!timeout)
11518cfa0ad2SJack F Vogel 		DEBUGOUT("MNG configuration cycle has not completed.\n");
11528cfa0ad2SJack F Vogel 
11538cfa0ad2SJack F Vogel 	/* If EEPROM is not marked present, init the PHY manually */
1154ab5d0362SJack F Vogel 	if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) &&
11554edd8523SJack F Vogel 	    (hw->phy.type == e1000_phy_igp_3))
11568cfa0ad2SJack F Vogel 		e1000_phy_init_script_igp3(hw);
11578cfa0ad2SJack F Vogel 
11588cc64f1eSJack F Vogel 	return E1000_SUCCESS;
11598cfa0ad2SJack F Vogel }
11608cfa0ad2SJack F Vogel 
11618cfa0ad2SJack F Vogel /**
11628cfa0ad2SJack F Vogel  *  e1000_get_link_up_info_82575 - Get link speed/duplex info
11638cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
11648cfa0ad2SJack F Vogel  *  @speed: stores the current speed
11658cfa0ad2SJack F Vogel  *  @duplex: stores the current duplex
11668cfa0ad2SJack F Vogel  *
11678cfa0ad2SJack F Vogel  *  This is a wrapper function, if using the serial gigabit media independent
11688cfa0ad2SJack F Vogel  *  interface, use PCS to retrieve the link speed and duplex information.
11698cfa0ad2SJack F Vogel  *  Otherwise, use the generic function to get the link speed and duplex info.
11708cfa0ad2SJack F Vogel  **/
11718cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
11728cfa0ad2SJack F Vogel 					u16 *duplex)
11738cfa0ad2SJack F Vogel {
11748cfa0ad2SJack F Vogel 	s32 ret_val;
11758cfa0ad2SJack F Vogel 
11768cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_link_up_info_82575");
11778cfa0ad2SJack F Vogel 
11784edd8523SJack F Vogel 	if (hw->phy.media_type != e1000_media_type_copper)
11798cfa0ad2SJack F Vogel 		ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed,
11808cfa0ad2SJack F Vogel 							       duplex);
11814edd8523SJack F Vogel 	else
11828cfa0ad2SJack F Vogel 		ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
11838cfa0ad2SJack F Vogel 								    duplex);
11848cfa0ad2SJack F Vogel 
11858cfa0ad2SJack F Vogel 	return ret_val;
11868cfa0ad2SJack F Vogel }
11878cfa0ad2SJack F Vogel 
11888cfa0ad2SJack F Vogel /**
11898cfa0ad2SJack F Vogel  *  e1000_check_for_link_82575 - Check for link
11908cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
11918cfa0ad2SJack F Vogel  *
11928cfa0ad2SJack F Vogel  *  If sgmii is enabled, then use the pcs register to determine link, otherwise
11938cfa0ad2SJack F Vogel  *  use the generic interface for determining link.
11948cfa0ad2SJack F Vogel  **/
11958cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82575(struct e1000_hw *hw)
11968cfa0ad2SJack F Vogel {
11978cfa0ad2SJack F Vogel 	s32 ret_val;
11988cfa0ad2SJack F Vogel 	u16 speed, duplex;
11998cfa0ad2SJack F Vogel 
12008cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_check_for_link_82575");
12018cfa0ad2SJack F Vogel 
12024edd8523SJack F Vogel 	if (hw->phy.media_type != e1000_media_type_copper) {
12038cfa0ad2SJack F Vogel 		ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed,
12048cfa0ad2SJack F Vogel 							       &duplex);
1205d035aa2dSJack F Vogel 		/*
1206d035aa2dSJack F Vogel 		 * Use this flag to determine if link needs to be checked or
1207d035aa2dSJack F Vogel 		 * not.  If we have link clear the flag so that we do not
1208d035aa2dSJack F Vogel 		 * continue to check for link.
1209d035aa2dSJack F Vogel 		 */
1210d035aa2dSJack F Vogel 		hw->mac.get_link_status = !hw->mac.serdes_has_link;
1211ab5d0362SJack F Vogel 
12126ab6bfe3SJack F Vogel 		/*
12136ab6bfe3SJack F Vogel 		 * Configure Flow Control now that Auto-Neg has completed.
12146ab6bfe3SJack F Vogel 		 * First, we need to restore the desired flow control
12156ab6bfe3SJack F Vogel 		 * settings because we may have had to re-autoneg with a
12166ab6bfe3SJack F Vogel 		 * different link partner.
12176ab6bfe3SJack F Vogel 		 */
12186ab6bfe3SJack F Vogel 		ret_val = e1000_config_fc_after_link_up_generic(hw);
12196ab6bfe3SJack F Vogel 		if (ret_val)
12206ab6bfe3SJack F Vogel 			DEBUGOUT("Error configuring flow control\n");
1221d035aa2dSJack F Vogel 	} else {
12228cfa0ad2SJack F Vogel 		ret_val = e1000_check_for_copper_link_generic(hw);
1223d035aa2dSJack F Vogel 	}
12248cfa0ad2SJack F Vogel 
12258cfa0ad2SJack F Vogel 	return ret_val;
12268cfa0ad2SJack F Vogel }
12278cfa0ad2SJack F Vogel 
12288cfa0ad2SJack F Vogel /**
12297609433eSJack F Vogel  *  e1000_check_for_link_media_swap - Check which M88E1112 interface linked
12307609433eSJack F Vogel  *  @hw: pointer to the HW structure
12317609433eSJack F Vogel  *
12327609433eSJack F Vogel  *  Poll the M88E1112 interfaces to see which interface achieved link.
12337609433eSJack F Vogel  */
12347609433eSJack F Vogel static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
12357609433eSJack F Vogel {
12367609433eSJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
12377609433eSJack F Vogel 	s32 ret_val;
12387609433eSJack F Vogel 	u16 data;
12397609433eSJack F Vogel 	u8 port = 0;
12407609433eSJack F Vogel 
12417609433eSJack F Vogel 	DEBUGFUNC("e1000_check_for_link_media_swap");
12427609433eSJack F Vogel 
1243c80429ceSEric Joyner 	/* Check for copper. */
12447609433eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
12457609433eSJack F Vogel 	if (ret_val)
12467609433eSJack F Vogel 		return ret_val;
12477609433eSJack F Vogel 
12487609433eSJack F Vogel 	ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data);
12497609433eSJack F Vogel 	if (ret_val)
12507609433eSJack F Vogel 		return ret_val;
12517609433eSJack F Vogel 
12527609433eSJack F Vogel 	if (data & E1000_M88E1112_STATUS_LINK)
12537609433eSJack F Vogel 		port = E1000_MEDIA_PORT_COPPER;
12547609433eSJack F Vogel 
1255c80429ceSEric Joyner 	/* Check for other. */
12567609433eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1);
12577609433eSJack F Vogel 	if (ret_val)
12587609433eSJack F Vogel 		return ret_val;
12597609433eSJack F Vogel 
12607609433eSJack F Vogel 	ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data);
12617609433eSJack F Vogel 	if (ret_val)
12627609433eSJack F Vogel 		return ret_val;
12637609433eSJack F Vogel 
12647609433eSJack F Vogel 	if (data & E1000_M88E1112_STATUS_LINK)
12657609433eSJack F Vogel 		port = E1000_MEDIA_PORT_OTHER;
12667609433eSJack F Vogel 
12677609433eSJack F Vogel 	/* Determine if a swap needs to happen. */
12687609433eSJack F Vogel 	if (port && (hw->dev_spec._82575.media_port != port)) {
12697609433eSJack F Vogel 		hw->dev_spec._82575.media_port = port;
12707609433eSJack F Vogel 		hw->dev_spec._82575.media_changed = TRUE;
1271c80429ceSEric Joyner 	}
1272c80429ceSEric Joyner 
1273c80429ceSEric Joyner 	if (port == E1000_MEDIA_PORT_COPPER) {
1274c80429ceSEric Joyner 		/* reset page to 0 */
1275c80429ceSEric Joyner 		ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
1276c80429ceSEric Joyner 		if (ret_val)
1277c80429ceSEric Joyner 			return ret_val;
1278c80429ceSEric Joyner 		e1000_check_for_link_82575(hw);
12797609433eSJack F Vogel 	} else {
1280c80429ceSEric Joyner 		e1000_check_for_link_82575(hw);
1281c80429ceSEric Joyner 		/* reset page to 0 */
1282c80429ceSEric Joyner 		ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
1283c80429ceSEric Joyner 		if (ret_val)
1284c80429ceSEric Joyner 			return ret_val;
12857609433eSJack F Vogel 	}
12867609433eSJack F Vogel 
12877609433eSJack F Vogel 	return E1000_SUCCESS;
12887609433eSJack F Vogel }
12897609433eSJack F Vogel 
12907609433eSJack F Vogel /**
1291a69ed8dfSJack F Vogel  *  e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown
1292a69ed8dfSJack F Vogel  *  @hw: pointer to the HW structure
1293a69ed8dfSJack F Vogel  **/
1294a69ed8dfSJack F Vogel static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw)
1295a69ed8dfSJack F Vogel {
1296a69ed8dfSJack F Vogel 	u32 reg;
1297a69ed8dfSJack F Vogel 
1298a69ed8dfSJack F Vogel 	DEBUGFUNC("e1000_power_up_serdes_link_82575");
1299a69ed8dfSJack F Vogel 
1300a69ed8dfSJack F Vogel 	if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
1301a69ed8dfSJack F Vogel 	    !e1000_sgmii_active_82575(hw))
1302a69ed8dfSJack F Vogel 		return;
1303a69ed8dfSJack F Vogel 
1304a69ed8dfSJack F Vogel 	/* Enable PCS to turn on link */
1305a69ed8dfSJack F Vogel 	reg = E1000_READ_REG(hw, E1000_PCS_CFG0);
1306a69ed8dfSJack F Vogel 	reg |= E1000_PCS_CFG_PCS_EN;
1307a69ed8dfSJack F Vogel 	E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg);
1308a69ed8dfSJack F Vogel 
1309a69ed8dfSJack F Vogel 	/* Power up the laser */
1310a69ed8dfSJack F Vogel 	reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
1311a69ed8dfSJack F Vogel 	reg &= ~E1000_CTRL_EXT_SDP3_DATA;
1312a69ed8dfSJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
1313a69ed8dfSJack F Vogel 
1314a69ed8dfSJack F Vogel 	/* flush the write to verify completion */
1315a69ed8dfSJack F Vogel 	E1000_WRITE_FLUSH(hw);
1316a69ed8dfSJack F Vogel 	msec_delay(1);
1317a69ed8dfSJack F Vogel }
1318a69ed8dfSJack F Vogel 
1319a69ed8dfSJack F Vogel /**
13208cfa0ad2SJack F Vogel  *  e1000_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex
13218cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
13228cfa0ad2SJack F Vogel  *  @speed: stores the current speed
13238cfa0ad2SJack F Vogel  *  @duplex: stores the current duplex
13248cfa0ad2SJack F Vogel  *
13258cfa0ad2SJack F Vogel  *  Using the physical coding sub-layer (PCS), retrieve the current speed and
13268cfa0ad2SJack F Vogel  *  duplex, then store the values in the pointers provided.
13278cfa0ad2SJack F Vogel  **/
13288cfa0ad2SJack F Vogel static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
13298cfa0ad2SJack F Vogel 						u16 *speed, u16 *duplex)
13308cfa0ad2SJack F Vogel {
13318cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
13328cfa0ad2SJack F Vogel 	u32 pcs;
13337609433eSJack F Vogel 	u32 status;
13348cfa0ad2SJack F Vogel 
13358cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575");
13368cfa0ad2SJack F Vogel 
13378cfa0ad2SJack F Vogel 	/*
13388cfa0ad2SJack F Vogel 	 * Read the PCS Status register for link state. For non-copper mode,
13398cfa0ad2SJack F Vogel 	 * the status register is not accurate. The PCS status register is
13408cfa0ad2SJack F Vogel 	 * used instead.
13418cfa0ad2SJack F Vogel 	 */
13428cfa0ad2SJack F Vogel 	pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT);
13438cfa0ad2SJack F Vogel 
13448cfa0ad2SJack F Vogel 	/*
1345ab5d0362SJack F Vogel 	 * The link up bit determines when link is up on autoneg.
13468cfa0ad2SJack F Vogel 	 */
1347ab5d0362SJack F Vogel 	if (pcs & E1000_PCS_LSTS_LINK_OK) {
13488cfa0ad2SJack F Vogel 		mac->serdes_has_link = TRUE;
13498cfa0ad2SJack F Vogel 
13508cfa0ad2SJack F Vogel 		/* Detect and store PCS speed */
13514dab5c37SJack F Vogel 		if (pcs & E1000_PCS_LSTS_SPEED_1000)
13528cfa0ad2SJack F Vogel 			*speed = SPEED_1000;
13534dab5c37SJack F Vogel 		else if (pcs & E1000_PCS_LSTS_SPEED_100)
13548cfa0ad2SJack F Vogel 			*speed = SPEED_100;
13554dab5c37SJack F Vogel 		else
13568cfa0ad2SJack F Vogel 			*speed = SPEED_10;
13578cfa0ad2SJack F Vogel 
13588cfa0ad2SJack F Vogel 		/* Detect and store PCS duplex */
13594dab5c37SJack F Vogel 		if (pcs & E1000_PCS_LSTS_DUPLEX_FULL)
13608cfa0ad2SJack F Vogel 			*duplex = FULL_DUPLEX;
13614dab5c37SJack F Vogel 		else
13628cfa0ad2SJack F Vogel 			*duplex = HALF_DUPLEX;
13636ab6bfe3SJack F Vogel 
13647609433eSJack F Vogel 		/* Check if it is an I354 2.5Gb backplane connection. */
13657609433eSJack F Vogel 		if (mac->type == e1000_i354) {
13667609433eSJack F Vogel 			status = E1000_READ_REG(hw, E1000_STATUS);
13677609433eSJack F Vogel 			if ((status & E1000_STATUS_2P5_SKU) &&
13687609433eSJack F Vogel 			    !(status & E1000_STATUS_2P5_SKU_OVER)) {
13697609433eSJack F Vogel 				*speed = SPEED_2500;
13707609433eSJack F Vogel 				*duplex = FULL_DUPLEX;
13717609433eSJack F Vogel 				DEBUGOUT("2500 Mbs, ");
13727609433eSJack F Vogel 				DEBUGOUT("Full Duplex\n");
13737609433eSJack F Vogel 			}
13747609433eSJack F Vogel 		}
13757609433eSJack F Vogel 
1376ab5d0362SJack F Vogel 	} else {
1377ab5d0362SJack F Vogel 		mac->serdes_has_link = FALSE;
1378ab5d0362SJack F Vogel 		*speed = 0;
1379ab5d0362SJack F Vogel 		*duplex = 0;
13808cfa0ad2SJack F Vogel 	}
13818cfa0ad2SJack F Vogel 
13828cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
13838cfa0ad2SJack F Vogel }
13848cfa0ad2SJack F Vogel 
13858cfa0ad2SJack F Vogel /**
13864edd8523SJack F Vogel  *  e1000_shutdown_serdes_link_82575 - Remove link during power down
13878cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
13888cfa0ad2SJack F Vogel  *
13894edd8523SJack F Vogel  *  In the case of serdes shut down sfp and PCS on driver unload
13908cfa0ad2SJack F Vogel  *  when management pass thru is not enabled.
13918cfa0ad2SJack F Vogel  **/
13924edd8523SJack F Vogel void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw)
13938cfa0ad2SJack F Vogel {
13948cfa0ad2SJack F Vogel 	u32 reg;
1395a69ed8dfSJack F Vogel 
1396a69ed8dfSJack F Vogel 	DEBUGFUNC("e1000_shutdown_serdes_link_82575");
13978cfa0ad2SJack F Vogel 
13984edd8523SJack F Vogel 	if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
13994edd8523SJack F Vogel 	    !e1000_sgmii_active_82575(hw))
14008cfa0ad2SJack F Vogel 		return;
14018cfa0ad2SJack F Vogel 
1402a69ed8dfSJack F Vogel 	if (!e1000_enable_mng_pass_thru(hw)) {
14038cfa0ad2SJack F Vogel 		/* Disable PCS to turn off link */
14048cfa0ad2SJack F Vogel 		reg = E1000_READ_REG(hw, E1000_PCS_CFG0);
14058cfa0ad2SJack F Vogel 		reg &= ~E1000_PCS_CFG_PCS_EN;
14068cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg);
14078cfa0ad2SJack F Vogel 
14088cfa0ad2SJack F Vogel 		/* shutdown the laser */
14098cfa0ad2SJack F Vogel 		reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
14104edd8523SJack F Vogel 		reg |= E1000_CTRL_EXT_SDP3_DATA;
14118cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
14128cfa0ad2SJack F Vogel 
14134edd8523SJack F Vogel 		/* flush the write to verify completion */
14148cfa0ad2SJack F Vogel 		E1000_WRITE_FLUSH(hw);
14158cfa0ad2SJack F Vogel 		msec_delay(1);
14168cfa0ad2SJack F Vogel 	}
14178cfa0ad2SJack F Vogel 
14188cfa0ad2SJack F Vogel 	return;
14198cfa0ad2SJack F Vogel }
14208cfa0ad2SJack F Vogel 
14218cfa0ad2SJack F Vogel /**
14228cfa0ad2SJack F Vogel  *  e1000_reset_hw_82575 - Reset hardware
14238cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
14248cfa0ad2SJack F Vogel  *
1425daf9197cSJack F Vogel  *  This resets the hardware into a known state.
14268cfa0ad2SJack F Vogel  **/
14278cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
14288cfa0ad2SJack F Vogel {
1429f0ecc46dSJack F Vogel 	u32 ctrl;
14308cfa0ad2SJack F Vogel 	s32 ret_val;
14318cfa0ad2SJack F Vogel 
14328cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_reset_hw_82575");
14338cfa0ad2SJack F Vogel 
14348cfa0ad2SJack F Vogel 	/*
14358cfa0ad2SJack F Vogel 	 * Prevent the PCI-E bus from sticking if there is no TLP connection
14368cfa0ad2SJack F Vogel 	 * on the last TLP read/write transaction when MAC is reset.
14378cfa0ad2SJack F Vogel 	 */
14388cfa0ad2SJack F Vogel 	ret_val = e1000_disable_pcie_master_generic(hw);
14394dab5c37SJack F Vogel 	if (ret_val)
14408cfa0ad2SJack F Vogel 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
14418cfa0ad2SJack F Vogel 
14429d81738fSJack F Vogel 	/* set the completion timeout for interface */
14439d81738fSJack F Vogel 	ret_val = e1000_set_pcie_completion_timeout(hw);
14444dab5c37SJack F Vogel 	if (ret_val)
14459d81738fSJack F Vogel 		DEBUGOUT("PCI-E Set completion timeout has failed.\n");
14469d81738fSJack F Vogel 
14478cfa0ad2SJack F Vogel 	DEBUGOUT("Masking off all interrupts\n");
14488cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
14498cfa0ad2SJack F Vogel 
14508cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
14518cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
14528cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
14538cfa0ad2SJack F Vogel 
14548cfa0ad2SJack F Vogel 	msec_delay(10);
14558cfa0ad2SJack F Vogel 
14568cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
14578cfa0ad2SJack F Vogel 
14588cfa0ad2SJack F Vogel 	DEBUGOUT("Issuing a global reset to MAC\n");
14598cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
14608cfa0ad2SJack F Vogel 
14618cfa0ad2SJack F Vogel 	ret_val = e1000_get_auto_rd_done_generic(hw);
14628cfa0ad2SJack F Vogel 	if (ret_val) {
14638cfa0ad2SJack F Vogel 		/*
14648cfa0ad2SJack F Vogel 		 * When auto config read does not complete, do not
14658cfa0ad2SJack F Vogel 		 * return with an error. This can happen in situations
14668cfa0ad2SJack F Vogel 		 * where there is no eeprom and prevents getting link.
14678cfa0ad2SJack F Vogel 		 */
14688cfa0ad2SJack F Vogel 		DEBUGOUT("Auto Read Done did not complete\n");
14698cfa0ad2SJack F Vogel 	}
14708cfa0ad2SJack F Vogel 
14718cfa0ad2SJack F Vogel 	/* If EEPROM is not present, run manual init scripts */
1472ab5d0362SJack F Vogel 	if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES))
14738cfa0ad2SJack F Vogel 		e1000_reset_init_script_82575(hw);
14748cfa0ad2SJack F Vogel 
14758cfa0ad2SJack F Vogel 	/* Clear any pending interrupt events. */
14768cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
1477f0ecc46dSJack F Vogel 	E1000_READ_REG(hw, E1000_ICR);
14788cfa0ad2SJack F Vogel 
1479d035aa2dSJack F Vogel 	/* Install any alternate MAC address into RAR0 */
1480d035aa2dSJack F Vogel 	ret_val = e1000_check_alt_mac_addr_generic(hw);
14818cfa0ad2SJack F Vogel 
14828cfa0ad2SJack F Vogel 	return ret_val;
14838cfa0ad2SJack F Vogel }
14848cfa0ad2SJack F Vogel 
14858cfa0ad2SJack F Vogel /**
14868cfa0ad2SJack F Vogel  *  e1000_init_hw_82575 - Initialize hardware
14878cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
14888cfa0ad2SJack F Vogel  *
14898cfa0ad2SJack F Vogel  *  This inits the hardware readying it for operation.
14908cfa0ad2SJack F Vogel  **/
14918cc64f1eSJack F Vogel s32 e1000_init_hw_82575(struct e1000_hw *hw)
14928cfa0ad2SJack F Vogel {
14938cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
14948cfa0ad2SJack F Vogel 	s32 ret_val;
14958cfa0ad2SJack F Vogel 	u16 i, rar_count = mac->rar_entry_count;
14968cfa0ad2SJack F Vogel 
14978cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_hw_82575");
14988cfa0ad2SJack F Vogel 
14998cfa0ad2SJack F Vogel 	/* Initialize identification LED */
1500d035aa2dSJack F Vogel 	ret_val = mac->ops.id_led_init(hw);
15018cfa0ad2SJack F Vogel 	if (ret_val) {
15028cfa0ad2SJack F Vogel 		DEBUGOUT("Error initializing identification LED\n");
15038cfa0ad2SJack F Vogel 		/* This is not fatal and we should not stop init due to this */
15048cfa0ad2SJack F Vogel 	}
15058cfa0ad2SJack F Vogel 
15068cfa0ad2SJack F Vogel 	/* Disabling VLAN filtering */
15078cfa0ad2SJack F Vogel 	DEBUGOUT("Initializing the IEEE VLAN\n");
15088cfa0ad2SJack F Vogel 	mac->ops.clear_vfta(hw);
15098cfa0ad2SJack F Vogel 
15108cfa0ad2SJack F Vogel 	/* Setup the receive address */
1511d035aa2dSJack F Vogel 	e1000_init_rx_addrs_generic(hw, rar_count);
1512d035aa2dSJack F Vogel 
15138cfa0ad2SJack F Vogel 	/* Zero out the Multicast HASH table */
15148cfa0ad2SJack F Vogel 	DEBUGOUT("Zeroing the MTA\n");
15158cfa0ad2SJack F Vogel 	for (i = 0; i < mac->mta_reg_count; i++)
15168cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
15178cfa0ad2SJack F Vogel 
15184edd8523SJack F Vogel 	/* Zero out the Unicast HASH table */
15194edd8523SJack F Vogel 	DEBUGOUT("Zeroing the UTA\n");
15204edd8523SJack F Vogel 	for (i = 0; i < mac->uta_reg_count; i++)
15214edd8523SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0);
15224edd8523SJack F Vogel 
15238cfa0ad2SJack F Vogel 	/* Setup link and flow control */
15248cfa0ad2SJack F Vogel 	ret_val = mac->ops.setup_link(hw);
15258cfa0ad2SJack F Vogel 
15264dab5c37SJack F Vogel 	/* Set the default MTU size */
15274dab5c37SJack F Vogel 	hw->dev_spec._82575.mtu = 1500;
15284dab5c37SJack F Vogel 
15298cfa0ad2SJack F Vogel 	/*
15308cfa0ad2SJack F Vogel 	 * Clear all of the statistics registers (clear on read).  It is
15318cfa0ad2SJack F Vogel 	 * important that we do this after we have tried to establish link
15328cfa0ad2SJack F Vogel 	 * because the symbol error count will increment wildly if there
15338cfa0ad2SJack F Vogel 	 * is no link.
15348cfa0ad2SJack F Vogel 	 */
15358cfa0ad2SJack F Vogel 	e1000_clear_hw_cntrs_82575(hw);
15368cfa0ad2SJack F Vogel 
15378cfa0ad2SJack F Vogel 	return ret_val;
15388cfa0ad2SJack F Vogel }
15398cfa0ad2SJack F Vogel 
15408cfa0ad2SJack F Vogel /**
15418cfa0ad2SJack F Vogel  *  e1000_setup_copper_link_82575 - Configure copper link settings
15428cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
15438cfa0ad2SJack F Vogel  *
15448cfa0ad2SJack F Vogel  *  Configures the link for auto-neg or forced speed and duplex.  Then we check
15458cfa0ad2SJack F Vogel  *  for link, once link is established calls to configure collision distance
15468cfa0ad2SJack F Vogel  *  and flow control are called.
15478cfa0ad2SJack F Vogel  **/
15488cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
15498cfa0ad2SJack F Vogel {
15509d81738fSJack F Vogel 	u32 ctrl;
15518cfa0ad2SJack F Vogel 	s32 ret_val;
15526ab6bfe3SJack F Vogel 	u32 phpm_reg;
15538cfa0ad2SJack F Vogel 
15548cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_setup_copper_link_82575");
15558cfa0ad2SJack F Vogel 
15568cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
15578cfa0ad2SJack F Vogel 	ctrl |= E1000_CTRL_SLU;
15588cfa0ad2SJack F Vogel 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
15598cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
15608cfa0ad2SJack F Vogel 
15617609433eSJack F Vogel 	/* Clear Go Link Disconnect bit on supported devices */
15627609433eSJack F Vogel 	switch (hw->mac.type) {
15637609433eSJack F Vogel 	case e1000_82580:
15647609433eSJack F Vogel 	case e1000_i350:
15657609433eSJack F Vogel 	case e1000_i210:
15667609433eSJack F Vogel 	case e1000_i211:
15676ab6bfe3SJack F Vogel 		phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
15686ab6bfe3SJack F Vogel 		phpm_reg &= ~E1000_82580_PM_GO_LINKD;
15696ab6bfe3SJack F Vogel 		E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg);
15707609433eSJack F Vogel 		break;
15717609433eSJack F Vogel 	default:
15727609433eSJack F Vogel 		break;
15736ab6bfe3SJack F Vogel 	}
15746ab6bfe3SJack F Vogel 
15754edd8523SJack F Vogel 	ret_val = e1000_setup_serdes_link_82575(hw);
15764edd8523SJack F Vogel 	if (ret_val)
15774edd8523SJack F Vogel 		goto out;
15784edd8523SJack F Vogel 
15794dab5c37SJack F Vogel 	if (e1000_sgmii_active_82575(hw)) {
15804edd8523SJack F Vogel 		/* allow time for SFP cage time to power up phy */
15814edd8523SJack F Vogel 		msec_delay(300);
15824edd8523SJack F Vogel 
15834edd8523SJack F Vogel 		ret_val = hw->phy.ops.reset(hw);
15844edd8523SJack F Vogel 		if (ret_val) {
15854edd8523SJack F Vogel 			DEBUGOUT("Error resetting the PHY.\n");
15864edd8523SJack F Vogel 			goto out;
15874edd8523SJack F Vogel 		}
15884edd8523SJack F Vogel 	}
15898cfa0ad2SJack F Vogel 	switch (hw->phy.type) {
1590ab5d0362SJack F Vogel 	case e1000_phy_i210:
15918cfa0ad2SJack F Vogel 	case e1000_phy_m88:
15926ab6bfe3SJack F Vogel 		switch (hw->phy.id) {
15936ab6bfe3SJack F Vogel 		case I347AT4_E_PHY_ID:
15946ab6bfe3SJack F Vogel 		case M88E1112_E_PHY_ID:
15956ab6bfe3SJack F Vogel 		case M88E1340M_E_PHY_ID:
15967609433eSJack F Vogel 		case M88E1543_E_PHY_ID:
15977609433eSJack F Vogel 		case M88E1512_E_PHY_ID:
15986ab6bfe3SJack F Vogel 		case I210_I_PHY_ID:
1599f0ecc46dSJack F Vogel 			ret_val = e1000_copper_link_setup_m88_gen2(hw);
16006ab6bfe3SJack F Vogel 			break;
16016ab6bfe3SJack F Vogel 		default:
16028cfa0ad2SJack F Vogel 			ret_val = e1000_copper_link_setup_m88(hw);
16038cfa0ad2SJack F Vogel 			break;
16046ab6bfe3SJack F Vogel 		}
16056ab6bfe3SJack F Vogel 		break;
16068cfa0ad2SJack F Vogel 	case e1000_phy_igp_3:
16078cfa0ad2SJack F Vogel 		ret_val = e1000_copper_link_setup_igp(hw);
16088cfa0ad2SJack F Vogel 		break;
16094edd8523SJack F Vogel 	case e1000_phy_82580:
16104edd8523SJack F Vogel 		ret_val = e1000_copper_link_setup_82577(hw);
16114edd8523SJack F Vogel 		break;
16128cfa0ad2SJack F Vogel 	default:
16138cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PHY;
16148cfa0ad2SJack F Vogel 		break;
16158cfa0ad2SJack F Vogel 	}
16168cfa0ad2SJack F Vogel 
16178cfa0ad2SJack F Vogel 	if (ret_val)
16188cfa0ad2SJack F Vogel 		goto out;
16198cfa0ad2SJack F Vogel 
16204edd8523SJack F Vogel 	ret_val = e1000_setup_copper_link_generic(hw);
16218cfa0ad2SJack F Vogel out:
16228cfa0ad2SJack F Vogel 	return ret_val;
16238cfa0ad2SJack F Vogel }
16248cfa0ad2SJack F Vogel 
16258cfa0ad2SJack F Vogel /**
16264edd8523SJack F Vogel  *  e1000_setup_serdes_link_82575 - Setup link for serdes
16278cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
16288cfa0ad2SJack F Vogel  *
16294edd8523SJack F Vogel  *  Configure the physical coding sub-layer (PCS) link.  The PCS link is
16304edd8523SJack F Vogel  *  used on copper connections where the serialized gigabit media independent
16314edd8523SJack F Vogel  *  interface (sgmii), or serdes fiber is being used.  Configures the link
16324edd8523SJack F Vogel  *  for auto-negotiation or forces speed/duplex.
16338cfa0ad2SJack F Vogel  **/
16344edd8523SJack F Vogel static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
16358cfa0ad2SJack F Vogel {
16366ab6bfe3SJack F Vogel 	u32 ctrl_ext, ctrl_reg, reg, anadv_reg;
16374edd8523SJack F Vogel 	bool pcs_autoneg;
16384dab5c37SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
16394dab5c37SJack F Vogel 	u16 data;
16408cfa0ad2SJack F Vogel 
16414edd8523SJack F Vogel 	DEBUGFUNC("e1000_setup_serdes_link_82575");
16424edd8523SJack F Vogel 
16434edd8523SJack F Vogel 	if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
16444edd8523SJack F Vogel 	    !e1000_sgmii_active_82575(hw))
16454dab5c37SJack F Vogel 		return ret_val;
16468cfa0ad2SJack F Vogel 
16478cfa0ad2SJack F Vogel 	/*
16488cfa0ad2SJack F Vogel 	 * On the 82575, SerDes loopback mode persists until it is
16498cfa0ad2SJack F Vogel 	 * explicitly turned off or a power cycle is performed.  A read to
16508cfa0ad2SJack F Vogel 	 * the register does not indicate its status.  Therefore, we ensure
16518cfa0ad2SJack F Vogel 	 * loopback mode is disabled during initialization.
16528cfa0ad2SJack F Vogel 	 */
16538cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
16548cfa0ad2SJack F Vogel 
16554edd8523SJack F Vogel 	/* power on the sfp cage if present */
16564edd8523SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
16574edd8523SJack F Vogel 	ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA;
16584edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
16594edd8523SJack F Vogel 
16604edd8523SJack F Vogel 	ctrl_reg = E1000_READ_REG(hw, E1000_CTRL);
16614edd8523SJack F Vogel 	ctrl_reg |= E1000_CTRL_SLU;
16624edd8523SJack F Vogel 
1663a69ed8dfSJack F Vogel 	/* set both sw defined pins on 82575/82576*/
1664a69ed8dfSJack F Vogel 	if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576)
16654edd8523SJack F Vogel 		ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1;
16668cfa0ad2SJack F Vogel 
16674edd8523SJack F Vogel 	reg = E1000_READ_REG(hw, E1000_PCS_LCTL);
16684edd8523SJack F Vogel 
16694edd8523SJack F Vogel 	/* default pcs_autoneg to the same setting as mac autoneg */
16704edd8523SJack F Vogel 	pcs_autoneg = hw->mac.autoneg;
16714edd8523SJack F Vogel 
16724edd8523SJack F Vogel 	switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
16734edd8523SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_SGMII:
16744edd8523SJack F Vogel 		/* sgmii mode lets the phy handle forcing speed/duplex */
16754edd8523SJack F Vogel 		pcs_autoneg = TRUE;
16764edd8523SJack F Vogel 		/* autoneg time out should be disabled for SGMII mode */
16774edd8523SJack F Vogel 		reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT);
16784edd8523SJack F Vogel 		break;
16794edd8523SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
16804edd8523SJack F Vogel 		/* disable PCS autoneg and support parallel detect only */
16814edd8523SJack F Vogel 		pcs_autoneg = FALSE;
16827d9119bdSJack F Vogel 		/* fall through to default case */
16834edd8523SJack F Vogel 	default:
16844dab5c37SJack F Vogel 		if (hw->mac.type == e1000_82575 ||
16854dab5c37SJack F Vogel 		    hw->mac.type == e1000_82576) {
16864dab5c37SJack F Vogel 			ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data);
16874dab5c37SJack F Vogel 			if (ret_val) {
16884dab5c37SJack F Vogel 				DEBUGOUT("NVM Read Error\n");
16894dab5c37SJack F Vogel 				return ret_val;
16904dab5c37SJack F Vogel 			}
16914dab5c37SJack F Vogel 
16924dab5c37SJack F Vogel 			if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT)
16934dab5c37SJack F Vogel 				pcs_autoneg = FALSE;
16944dab5c37SJack F Vogel 		}
16954dab5c37SJack F Vogel 
16964edd8523SJack F Vogel 		/*
16974edd8523SJack F Vogel 		 * non-SGMII modes only supports a speed of 1000/Full for the
16984edd8523SJack F Vogel 		 * link so it is best to just force the MAC and let the pcs
16994edd8523SJack F Vogel 		 * link either autoneg or be forced to 1000/Full
17004edd8523SJack F Vogel 		 */
17014edd8523SJack F Vogel 		ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD |
17024edd8523SJack F Vogel 			    E1000_CTRL_FD | E1000_CTRL_FRCDPX;
17034edd8523SJack F Vogel 
17044edd8523SJack F Vogel 		/* set speed of 1000/Full if speed/duplex is forced */
17054edd8523SJack F Vogel 		reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL;
17064edd8523SJack F Vogel 		break;
17074edd8523SJack F Vogel 	}
17084edd8523SJack F Vogel 
17094edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg);
17108cfa0ad2SJack F Vogel 
17118cfa0ad2SJack F Vogel 	/*
17128cfa0ad2SJack F Vogel 	 * New SerDes mode allows for forcing speed or autonegotiating speed
17138cfa0ad2SJack F Vogel 	 * at 1gb. Autoneg should be default set by most drivers. This is the
17148cfa0ad2SJack F Vogel 	 * mode that will be compatible with older link partners and switches.
17158cfa0ad2SJack F Vogel 	 * However, both are supported by the hardware and some drivers/tools.
17168cfa0ad2SJack F Vogel 	 */
17178cfa0ad2SJack F Vogel 	reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
17188cfa0ad2SJack F Vogel 		 E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
17198cfa0ad2SJack F Vogel 
17204edd8523SJack F Vogel 	if (pcs_autoneg) {
17214edd8523SJack F Vogel 		/* Set PCS register for autoneg */
17224edd8523SJack F Vogel 		reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */
17234edd8523SJack F Vogel 		       E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */
17246ab6bfe3SJack F Vogel 
17256ab6bfe3SJack F Vogel 		/* Disable force flow control for autoneg */
17266ab6bfe3SJack F Vogel 		reg &= ~E1000_PCS_LCTL_FORCE_FCTRL;
17276ab6bfe3SJack F Vogel 
17286ab6bfe3SJack F Vogel 		/* Configure flow control advertisement for autoneg */
17296ab6bfe3SJack F Vogel 		anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV);
17306ab6bfe3SJack F Vogel 		anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE);
17316ab6bfe3SJack F Vogel 
17326ab6bfe3SJack F Vogel 		switch (hw->fc.requested_mode) {
17336ab6bfe3SJack F Vogel 		case e1000_fc_full:
17346ab6bfe3SJack F Vogel 		case e1000_fc_rx_pause:
17356ab6bfe3SJack F Vogel 			anadv_reg |= E1000_TXCW_ASM_DIR;
17366ab6bfe3SJack F Vogel 			anadv_reg |= E1000_TXCW_PAUSE;
17376ab6bfe3SJack F Vogel 			break;
17386ab6bfe3SJack F Vogel 		case e1000_fc_tx_pause:
17396ab6bfe3SJack F Vogel 			anadv_reg |= E1000_TXCW_ASM_DIR;
17406ab6bfe3SJack F Vogel 			break;
17416ab6bfe3SJack F Vogel 		default:
17426ab6bfe3SJack F Vogel 			break;
17436ab6bfe3SJack F Vogel 		}
17446ab6bfe3SJack F Vogel 
17456ab6bfe3SJack F Vogel 		E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg);
17466ab6bfe3SJack F Vogel 
17474edd8523SJack F Vogel 		DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
17484edd8523SJack F Vogel 	} else {
17494edd8523SJack F Vogel 		/* Set PCS register for forced link */
1750a69ed8dfSJack F Vogel 		reg |= E1000_PCS_LCTL_FSD;	/* Force Speed */
17516ab6bfe3SJack F Vogel 
17526ab6bfe3SJack F Vogel 		/* Force flow control for forced link */
17536ab6bfe3SJack F Vogel 		reg |= E1000_PCS_LCTL_FORCE_FCTRL;
17546ab6bfe3SJack F Vogel 
17554edd8523SJack F Vogel 		DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
17568cfa0ad2SJack F Vogel 	}
17578cfa0ad2SJack F Vogel 
17588cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg);
17598cfa0ad2SJack F Vogel 
17606ab6bfe3SJack F Vogel 	if (!pcs_autoneg && !e1000_sgmii_active_82575(hw))
17614edd8523SJack F Vogel 		e1000_force_mac_fc_generic(hw);
17624edd8523SJack F Vogel 
17634dab5c37SJack F Vogel 	return ret_val;
17644dab5c37SJack F Vogel }
17654dab5c37SJack F Vogel 
17664dab5c37SJack F Vogel /**
17674dab5c37SJack F Vogel  *  e1000_get_media_type_82575 - derives current media type.
17684dab5c37SJack F Vogel  *  @hw: pointer to the HW structure
17694dab5c37SJack F Vogel  *
17704dab5c37SJack F Vogel  *  The media type is chosen reflecting few settings.
17714dab5c37SJack F Vogel  *  The following are taken into account:
17724dab5c37SJack F Vogel  *  - link mode set in the current port Init Control Word #3
17734dab5c37SJack F Vogel  *  - current link mode settings in CSR register
17744dab5c37SJack F Vogel  *  - MDIO vs. I2C PHY control interface chosen
17754dab5c37SJack F Vogel  *  - SFP module media type
17764dab5c37SJack F Vogel  **/
17774dab5c37SJack F Vogel static s32 e1000_get_media_type_82575(struct e1000_hw *hw)
17784dab5c37SJack F Vogel {
17794dab5c37SJack F Vogel 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
17806ab6bfe3SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
17814dab5c37SJack F Vogel 	u32 ctrl_ext = 0;
17826ab6bfe3SJack F Vogel 	u32 link_mode = 0;
17834dab5c37SJack F Vogel 
17844dab5c37SJack F Vogel 	/* Set internal phy as default */
17854dab5c37SJack F Vogel 	dev_spec->sgmii_active = FALSE;
17864dab5c37SJack F Vogel 	dev_spec->module_plugged = FALSE;
17874dab5c37SJack F Vogel 
17884dab5c37SJack F Vogel 	/* Get CSR setting */
17894dab5c37SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
17904dab5c37SJack F Vogel 
17916ab6bfe3SJack F Vogel 	/* extract link mode setting */
17926ab6bfe3SJack F Vogel 	link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK;
17934dab5c37SJack F Vogel 
17946ab6bfe3SJack F Vogel 	switch (link_mode) {
17954dab5c37SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
17964dab5c37SJack F Vogel 		hw->phy.media_type = e1000_media_type_internal_serdes;
17974dab5c37SJack F Vogel 		break;
17984dab5c37SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_GMII:
17994dab5c37SJack F Vogel 		hw->phy.media_type = e1000_media_type_copper;
18004dab5c37SJack F Vogel 		break;
18014dab5c37SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_SGMII:
18024dab5c37SJack F Vogel 		/* Get phy control interface type set (MDIO vs. I2C)*/
18034dab5c37SJack F Vogel 		if (e1000_sgmii_uses_mdio_82575(hw)) {
18044dab5c37SJack F Vogel 			hw->phy.media_type = e1000_media_type_copper;
18054dab5c37SJack F Vogel 			dev_spec->sgmii_active = TRUE;
18064dab5c37SJack F Vogel 			break;
18074dab5c37SJack F Vogel 		}
18086ab6bfe3SJack F Vogel 		/* fall through for I2C based SGMII */
18096ab6bfe3SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
18106ab6bfe3SJack F Vogel 		/* read media type from SFP EEPROM */
18116ab6bfe3SJack F Vogel 		ret_val = e1000_set_sfp_media_type_82575(hw);
18126ab6bfe3SJack F Vogel 		if ((ret_val != E1000_SUCCESS) ||
18136ab6bfe3SJack F Vogel 		    (hw->phy.media_type == e1000_media_type_unknown)) {
18144dab5c37SJack F Vogel 			/*
18156ab6bfe3SJack F Vogel 			 * If media type was not identified then return media
18166ab6bfe3SJack F Vogel 			 * type defined by the CTRL_EXT settings.
18174dab5c37SJack F Vogel 			 */
18186ab6bfe3SJack F Vogel 			hw->phy.media_type = e1000_media_type_internal_serdes;
18196ab6bfe3SJack F Vogel 
18206ab6bfe3SJack F Vogel 			if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) {
18216ab6bfe3SJack F Vogel 				hw->phy.media_type = e1000_media_type_copper;
18226ab6bfe3SJack F Vogel 				dev_spec->sgmii_active = TRUE;
18234dab5c37SJack F Vogel 			}
18244dab5c37SJack F Vogel 
18256ab6bfe3SJack F Vogel 			break;
18266ab6bfe3SJack F Vogel 		}
18276ab6bfe3SJack F Vogel 
18286ab6bfe3SJack F Vogel 		/* do not change link mode for 100BaseFX */
18296ab6bfe3SJack F Vogel 		if (dev_spec->eth_flags.e100_base_fx)
18306ab6bfe3SJack F Vogel 			break;
18316ab6bfe3SJack F Vogel 
18326ab6bfe3SJack F Vogel 		/* change current link mode setting */
18336ab6bfe3SJack F Vogel 		ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
18346ab6bfe3SJack F Vogel 
18356ab6bfe3SJack F Vogel 		if (hw->phy.media_type == e1000_media_type_copper)
18366ab6bfe3SJack F Vogel 			ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII;
18374dab5c37SJack F Vogel 		else
18386ab6bfe3SJack F Vogel 			ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
18396ab6bfe3SJack F Vogel 
18406ab6bfe3SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
18416ab6bfe3SJack F Vogel 
18426ab6bfe3SJack F Vogel 		break;
18434dab5c37SJack F Vogel 	}
18444dab5c37SJack F Vogel 
18454dab5c37SJack F Vogel 	return ret_val;
18464dab5c37SJack F Vogel }
18474dab5c37SJack F Vogel 
18484dab5c37SJack F Vogel /**
18494dab5c37SJack F Vogel  *  e1000_set_sfp_media_type_82575 - derives SFP module media type.
18504dab5c37SJack F Vogel  *  @hw: pointer to the HW structure
18514dab5c37SJack F Vogel  *
18524dab5c37SJack F Vogel  *  The media type is chosen based on SFP module.
18534dab5c37SJack F Vogel  *  compatibility flags retrieved from SFP ID EEPROM.
18544dab5c37SJack F Vogel  **/
18554dab5c37SJack F Vogel static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw)
18564dab5c37SJack F Vogel {
18574dab5c37SJack F Vogel 	s32 ret_val = E1000_ERR_CONFIG;
18584dab5c37SJack F Vogel 	u32 ctrl_ext = 0;
18594dab5c37SJack F Vogel 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
18606ab6bfe3SJack F Vogel 	struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags;
18614dab5c37SJack F Vogel 	u8 tranceiver_type = 0;
18626ab6bfe3SJack F Vogel 	s32 timeout = 3;
18634dab5c37SJack F Vogel 
18646ab6bfe3SJack F Vogel 	/* Turn I2C interface ON and power on sfp cage */
18654dab5c37SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
18666ab6bfe3SJack F Vogel 	ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA;
18674dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA);
18684dab5c37SJack F Vogel 
18696ab6bfe3SJack F Vogel 	E1000_WRITE_FLUSH(hw);
18706ab6bfe3SJack F Vogel 
18714dab5c37SJack F Vogel 	/* Read SFP module data */
18726ab6bfe3SJack F Vogel 	while (timeout) {
18734dab5c37SJack F Vogel 		ret_val = e1000_read_sfp_data_byte(hw,
18744dab5c37SJack F Vogel 			E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET),
18754dab5c37SJack F Vogel 			&tranceiver_type);
18766ab6bfe3SJack F Vogel 		if (ret_val == E1000_SUCCESS)
18776ab6bfe3SJack F Vogel 			break;
18786ab6bfe3SJack F Vogel 		msec_delay(100);
18796ab6bfe3SJack F Vogel 		timeout--;
18806ab6bfe3SJack F Vogel 	}
18814dab5c37SJack F Vogel 	if (ret_val != E1000_SUCCESS)
18824dab5c37SJack F Vogel 		goto out;
18836ab6bfe3SJack F Vogel 
18844dab5c37SJack F Vogel 	ret_val = e1000_read_sfp_data_byte(hw,
18854dab5c37SJack F Vogel 			E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET),
18866ab6bfe3SJack F Vogel 			(u8 *)eth_flags);
18874dab5c37SJack F Vogel 	if (ret_val != E1000_SUCCESS)
18884dab5c37SJack F Vogel 		goto out;
18896ab6bfe3SJack F Vogel 
18906ab6bfe3SJack F Vogel 	/* Check if there is some SFP module plugged and powered */
18914dab5c37SJack F Vogel 	if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) ||
18924dab5c37SJack F Vogel 	    (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) {
18934dab5c37SJack F Vogel 		dev_spec->module_plugged = TRUE;
18946ab6bfe3SJack F Vogel 		if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) {
18954dab5c37SJack F Vogel 			hw->phy.media_type = e1000_media_type_internal_serdes;
18966ab6bfe3SJack F Vogel 		} else if (eth_flags->e100_base_fx) {
18976ab6bfe3SJack F Vogel 			dev_spec->sgmii_active = TRUE;
18986ab6bfe3SJack F Vogel 			hw->phy.media_type = e1000_media_type_internal_serdes;
18996ab6bfe3SJack F Vogel 		} else if (eth_flags->e1000_base_t) {
19004dab5c37SJack F Vogel 			dev_spec->sgmii_active = TRUE;
19014dab5c37SJack F Vogel 			hw->phy.media_type = e1000_media_type_copper;
19024dab5c37SJack F Vogel 		} else {
19034dab5c37SJack F Vogel 			hw->phy.media_type = e1000_media_type_unknown;
19044dab5c37SJack F Vogel 			DEBUGOUT("PHY module has not been recognized\n");
19054dab5c37SJack F Vogel 			goto out;
19064dab5c37SJack F Vogel 		}
19074dab5c37SJack F Vogel 	} else {
19084dab5c37SJack F Vogel 		hw->phy.media_type = e1000_media_type_unknown;
19094dab5c37SJack F Vogel 	}
19104dab5c37SJack F Vogel 	ret_val = E1000_SUCCESS;
19114dab5c37SJack F Vogel out:
19124dab5c37SJack F Vogel 	/* Restore I2C interface setting */
19134dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
19144dab5c37SJack F Vogel 	return ret_val;
19158cfa0ad2SJack F Vogel }
19168cfa0ad2SJack F Vogel 
19178cfa0ad2SJack F Vogel /**
19188cfa0ad2SJack F Vogel  *  e1000_valid_led_default_82575 - Verify a valid default LED config
19198cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
19208cfa0ad2SJack F Vogel  *  @data: pointer to the NVM (EEPROM)
19218cfa0ad2SJack F Vogel  *
19228cfa0ad2SJack F Vogel  *  Read the EEPROM for the current default LED configuration.  If the
19238cfa0ad2SJack F Vogel  *  LED configuration is not valid, set to a valid LED configuration.
19248cfa0ad2SJack F Vogel  **/
19258cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data)
19268cfa0ad2SJack F Vogel {
19278cfa0ad2SJack F Vogel 	s32 ret_val;
19288cfa0ad2SJack F Vogel 
19298cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_valid_led_default_82575");
19308cfa0ad2SJack F Vogel 
19318cfa0ad2SJack F Vogel 	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
19328cfa0ad2SJack F Vogel 	if (ret_val) {
19338cfa0ad2SJack F Vogel 		DEBUGOUT("NVM Read Error\n");
19348cfa0ad2SJack F Vogel 		goto out;
19358cfa0ad2SJack F Vogel 	}
19368cfa0ad2SJack F Vogel 
19378cfa0ad2SJack F Vogel 	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
19388cfa0ad2SJack F Vogel 		switch (hw->phy.media_type) {
19398cfa0ad2SJack F Vogel 		case e1000_media_type_internal_serdes:
19408cfa0ad2SJack F Vogel 			*data = ID_LED_DEFAULT_82575_SERDES;
19418cfa0ad2SJack F Vogel 			break;
19428cfa0ad2SJack F Vogel 		case e1000_media_type_copper:
19438cfa0ad2SJack F Vogel 		default:
19448cfa0ad2SJack F Vogel 			*data = ID_LED_DEFAULT;
19458cfa0ad2SJack F Vogel 			break;
19468cfa0ad2SJack F Vogel 		}
19478cfa0ad2SJack F Vogel 	}
19488cfa0ad2SJack F Vogel out:
19498cfa0ad2SJack F Vogel 	return ret_val;
19508cfa0ad2SJack F Vogel }
19518cfa0ad2SJack F Vogel 
19528cfa0ad2SJack F Vogel /**
19538cfa0ad2SJack F Vogel  *  e1000_sgmii_active_82575 - Return sgmii state
19548cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
19558cfa0ad2SJack F Vogel  *
19568cfa0ad2SJack F Vogel  *  82575 silicon has a serialized gigabit media independent interface (sgmii)
19578cfa0ad2SJack F Vogel  *  which can be enabled for use in the embedded applications.  Simply
19588cfa0ad2SJack F Vogel  *  return the current state of the sgmii interface.
19598cfa0ad2SJack F Vogel  **/
19608cfa0ad2SJack F Vogel static bool e1000_sgmii_active_82575(struct e1000_hw *hw)
19618cfa0ad2SJack F Vogel {
1962daf9197cSJack F Vogel 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
1963daf9197cSJack F Vogel 	return dev_spec->sgmii_active;
19648cfa0ad2SJack F Vogel }
19658cfa0ad2SJack F Vogel 
19668cfa0ad2SJack F Vogel /**
19678cfa0ad2SJack F Vogel  *  e1000_reset_init_script_82575 - Inits HW defaults after reset
19688cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
19698cfa0ad2SJack F Vogel  *
19708cfa0ad2SJack F Vogel  *  Inits recommended HW defaults after a reset when there is no EEPROM
19718cfa0ad2SJack F Vogel  *  detected. This is only for the 82575.
19728cfa0ad2SJack F Vogel  **/
19738cfa0ad2SJack F Vogel static s32 e1000_reset_init_script_82575(struct e1000_hw *hw)
19748cfa0ad2SJack F Vogel {
19758cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_reset_init_script_82575");
19768cfa0ad2SJack F Vogel 
19778cfa0ad2SJack F Vogel 	if (hw->mac.type == e1000_82575) {
19788cfa0ad2SJack F Vogel 		DEBUGOUT("Running reset init script for 82575\n");
19798cfa0ad2SJack F Vogel 		/* SerDes configuration via SERDESCTRL */
19808cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C);
19818cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78);
19828cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23);
19838cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15);
19848cfa0ad2SJack F Vogel 
19858cfa0ad2SJack F Vogel 		/* CCM configuration via CCMCTL register */
19868cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00);
19878cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00);
19888cfa0ad2SJack F Vogel 
19898cfa0ad2SJack F Vogel 		/* PCIe lanes configuration */
19908cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC);
19918cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF);
19928cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05);
19938cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81);
19948cfa0ad2SJack F Vogel 
19958cfa0ad2SJack F Vogel 		/* PCIe PLL Configuration */
19968cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47);
19978cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00);
19988cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00);
19998cfa0ad2SJack F Vogel 	}
20008cfa0ad2SJack F Vogel 
20018cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
20028cfa0ad2SJack F Vogel }
20038cfa0ad2SJack F Vogel 
20048cfa0ad2SJack F Vogel /**
20058cfa0ad2SJack F Vogel  *  e1000_read_mac_addr_82575 - Read device MAC address
20068cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
20078cfa0ad2SJack F Vogel  **/
20088cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw)
20098cfa0ad2SJack F Vogel {
20108cc64f1eSJack F Vogel 	s32 ret_val;
20118cfa0ad2SJack F Vogel 
20128cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_read_mac_addr_82575");
2013d035aa2dSJack F Vogel 
2014d035aa2dSJack F Vogel 	/*
2015d035aa2dSJack F Vogel 	 * If there's an alternate MAC address place it in RAR0
2016d035aa2dSJack F Vogel 	 * so that it will override the Si installed default perm
2017d035aa2dSJack F Vogel 	 * address.
2018d035aa2dSJack F Vogel 	 */
2019d035aa2dSJack F Vogel 	ret_val = e1000_check_alt_mac_addr_generic(hw);
2020d035aa2dSJack F Vogel 	if (ret_val)
2021d035aa2dSJack F Vogel 		goto out;
2022d035aa2dSJack F Vogel 
20238cfa0ad2SJack F Vogel 	ret_val = e1000_read_mac_addr_generic(hw);
20248cfa0ad2SJack F Vogel 
2025d035aa2dSJack F Vogel out:
20268cfa0ad2SJack F Vogel 	return ret_val;
20278cfa0ad2SJack F Vogel }
20288cfa0ad2SJack F Vogel 
20298cfa0ad2SJack F Vogel /**
2030a69ed8dfSJack F Vogel  *  e1000_config_collision_dist_82575 - Configure collision distance
2031a69ed8dfSJack F Vogel  *  @hw: pointer to the HW structure
2032a69ed8dfSJack F Vogel  *
2033a69ed8dfSJack F Vogel  *  Configures the collision distance to the default value and is used
2034a69ed8dfSJack F Vogel  *  during link setup.
2035a69ed8dfSJack F Vogel  **/
2036a69ed8dfSJack F Vogel static void e1000_config_collision_dist_82575(struct e1000_hw *hw)
2037a69ed8dfSJack F Vogel {
2038a69ed8dfSJack F Vogel 	u32 tctl_ext;
2039a69ed8dfSJack F Vogel 
2040a69ed8dfSJack F Vogel 	DEBUGFUNC("e1000_config_collision_dist_82575");
2041a69ed8dfSJack F Vogel 
2042a69ed8dfSJack F Vogel 	tctl_ext = E1000_READ_REG(hw, E1000_TCTL_EXT);
2043a69ed8dfSJack F Vogel 
2044a69ed8dfSJack F Vogel 	tctl_ext &= ~E1000_TCTL_EXT_COLD;
2045a69ed8dfSJack F Vogel 	tctl_ext |= E1000_COLLISION_DISTANCE << E1000_TCTL_EXT_COLD_SHIFT;
2046a69ed8dfSJack F Vogel 
2047a69ed8dfSJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL_EXT, tctl_ext);
2048a69ed8dfSJack F Vogel 	E1000_WRITE_FLUSH(hw);
2049a69ed8dfSJack F Vogel }
2050a69ed8dfSJack F Vogel 
2051a69ed8dfSJack F Vogel /**
20528cfa0ad2SJack F Vogel  * e1000_power_down_phy_copper_82575 - Remove link during PHY power down
20538cfa0ad2SJack F Vogel  * @hw: pointer to the HW structure
20548cfa0ad2SJack F Vogel  *
20558cfa0ad2SJack F Vogel  * In the case of a PHY power down to save power, or to turn off link during a
20568cfa0ad2SJack F Vogel  * driver unload, or wake on lan is not enabled, remove the link.
20578cfa0ad2SJack F Vogel  **/
20588cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw)
20598cfa0ad2SJack F Vogel {
20608cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
20618cfa0ad2SJack F Vogel 
20628cfa0ad2SJack F Vogel 	if (!(phy->ops.check_reset_block))
20638cfa0ad2SJack F Vogel 		return;
20648cfa0ad2SJack F Vogel 
20658cfa0ad2SJack F Vogel 	/* If the management interface is not enabled, then power down */
20668ec87fc5SJack F Vogel 	if (!(e1000_enable_mng_pass_thru(hw) || phy->ops.check_reset_block(hw)))
20678cfa0ad2SJack F Vogel 		e1000_power_down_phy_copper(hw);
20688cfa0ad2SJack F Vogel 
20698cfa0ad2SJack F Vogel 	return;
20708cfa0ad2SJack F Vogel }
20718cfa0ad2SJack F Vogel 
20728cfa0ad2SJack F Vogel /**
20738cfa0ad2SJack F Vogel  *  e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters
20748cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
20758cfa0ad2SJack F Vogel  *
20768cfa0ad2SJack F Vogel  *  Clears the hardware counters by reading the counter registers.
20778cfa0ad2SJack F Vogel  **/
20788cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw)
20798cfa0ad2SJack F Vogel {
20808cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_clear_hw_cntrs_82575");
20818cfa0ad2SJack F Vogel 
20828cfa0ad2SJack F Vogel 	e1000_clear_hw_cntrs_base_generic(hw);
20838cfa0ad2SJack F Vogel 
2084daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC64);
2085daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC127);
2086daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC255);
2087daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC511);
2088daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC1023);
2089daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC1522);
2090daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC64);
2091daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC127);
2092daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC255);
2093daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC511);
2094daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC1023);
2095daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC1522);
20968cfa0ad2SJack F Vogel 
2097daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ALGNERRC);
2098daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_RXERRC);
2099daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TNCRS);
2100daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_CEXTERR);
2101daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TSCTC);
2102daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TSCTFC);
21038cfa0ad2SJack F Vogel 
2104daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPRC);
2105daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPDC);
2106daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPTC);
21078cfa0ad2SJack F Vogel 
2108daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_IAC);
2109daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXOC);
21108cfa0ad2SJack F Vogel 
2111daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXPTC);
2112daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXATC);
2113daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXPTC);
2114daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXATC);
2115daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXQEC);
2116daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXQMTC);
2117daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXDMTC);
21188cfa0ad2SJack F Vogel 
2119daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_CBTMPC);
2120daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HTDPMC);
2121daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_CBRMPC);
2122daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_RPTHC);
2123daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HGPTC);
2124daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HTCBDPC);
2125daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HGORCL);
2126daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HGORCH);
2127daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HGOTCL);
2128daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HGOTCH);
2129daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_LENERRS);
21308cfa0ad2SJack F Vogel 
21318cfa0ad2SJack F Vogel 	/* This register should not be read in copper configurations */
21324edd8523SJack F Vogel 	if ((hw->phy.media_type == e1000_media_type_internal_serdes) ||
21334edd8523SJack F Vogel 	    e1000_sgmii_active_82575(hw))
2134daf9197cSJack F Vogel 		E1000_READ_REG(hw, E1000_SCVPC);
21358cfa0ad2SJack F Vogel }
21369d81738fSJack F Vogel 
21378cfa0ad2SJack F Vogel /**
2138f0ecc46dSJack F Vogel  *  e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable
21398cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
21408cfa0ad2SJack F Vogel  *
214148600901SSean Bruno  *  After Rx enable, if manageability is enabled then there is likely some
21428cfa0ad2SJack F Vogel  *  bad data at the start of the fifo and possibly in the DMA fifo.  This
21438cfa0ad2SJack F Vogel  *  function clears the fifos and flushes any packets that came in as rx was
21448cfa0ad2SJack F Vogel  *  being enabled.
21458cfa0ad2SJack F Vogel  **/
21468cfa0ad2SJack F Vogel void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
21478cfa0ad2SJack F Vogel {
21488cfa0ad2SJack F Vogel 	u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
21498cfa0ad2SJack F Vogel 	int i, ms_wait;
21508cfa0ad2SJack F Vogel 
2151c80429ceSEric Joyner 	DEBUGFUNC("e1000_rx_fifo_flush_82575");
2152c80429ceSEric Joyner 
2153c80429ceSEric Joyner 	/* disable IPv6 options as per hardware errata */
2154c80429ceSEric Joyner 	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
2155c80429ceSEric Joyner 	rfctl |= E1000_RFCTL_IPV6_EX_DIS;
2156c80429ceSEric Joyner 	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
2157c80429ceSEric Joyner 
21588cfa0ad2SJack F Vogel 	if (hw->mac.type != e1000_82575 ||
21598cfa0ad2SJack F Vogel 	    !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN))
21608cfa0ad2SJack F Vogel 		return;
21618cfa0ad2SJack F Vogel 
2162f0ecc46dSJack F Vogel 	/* Disable all Rx queues */
21638cfa0ad2SJack F Vogel 	for (i = 0; i < 4; i++) {
21648cfa0ad2SJack F Vogel 		rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i));
21658cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_RXDCTL(i),
21668cfa0ad2SJack F Vogel 				rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE);
21678cfa0ad2SJack F Vogel 	}
21688cfa0ad2SJack F Vogel 	/* Poll all queues to verify they have shut down */
21698cfa0ad2SJack F Vogel 	for (ms_wait = 0; ms_wait < 10; ms_wait++) {
21708cfa0ad2SJack F Vogel 		msec_delay(1);
21718cfa0ad2SJack F Vogel 		rx_enabled = 0;
21728cfa0ad2SJack F Vogel 		for (i = 0; i < 4; i++)
21738cfa0ad2SJack F Vogel 			rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i));
21748cfa0ad2SJack F Vogel 		if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE))
21758cfa0ad2SJack F Vogel 			break;
21768cfa0ad2SJack F Vogel 	}
21778cfa0ad2SJack F Vogel 
21788cfa0ad2SJack F Vogel 	if (ms_wait == 10)
21798cfa0ad2SJack F Vogel 		DEBUGOUT("Queue disable timed out after 10ms\n");
21808cfa0ad2SJack F Vogel 
21818cfa0ad2SJack F Vogel 	/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
21828cfa0ad2SJack F Vogel 	 * incoming packets are rejected.  Set enable and wait 2ms so that
21838cfa0ad2SJack F Vogel 	 * any packet that was coming in as RCTL.EN was set is flushed
21848cfa0ad2SJack F Vogel 	 */
21858cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF);
21868cfa0ad2SJack F Vogel 
21878cfa0ad2SJack F Vogel 	rlpml = E1000_READ_REG(hw, E1000_RLPML);
21888cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RLPML, 0);
21898cfa0ad2SJack F Vogel 
21908cfa0ad2SJack F Vogel 	rctl = E1000_READ_REG(hw, E1000_RCTL);
21918cfa0ad2SJack F Vogel 	temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP);
21928cfa0ad2SJack F Vogel 	temp_rctl |= E1000_RCTL_LPE;
21938cfa0ad2SJack F Vogel 
21948cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl);
21958cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN);
21968cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
21978cfa0ad2SJack F Vogel 	msec_delay(2);
21988cfa0ad2SJack F Vogel 
2199f0ecc46dSJack F Vogel 	/* Enable Rx queues that were previously enabled and restore our
22008cfa0ad2SJack F Vogel 	 * previous state
22018cfa0ad2SJack F Vogel 	 */
22028cfa0ad2SJack F Vogel 	for (i = 0; i < 4; i++)
22038cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]);
22048cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, rctl);
22058cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
22068cfa0ad2SJack F Vogel 
22078cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RLPML, rlpml);
22088cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
22098cfa0ad2SJack F Vogel 
22108cfa0ad2SJack F Vogel 	/* Flush receive errors generated by workaround */
22118cfa0ad2SJack F Vogel 	E1000_READ_REG(hw, E1000_ROC);
22128cfa0ad2SJack F Vogel 	E1000_READ_REG(hw, E1000_RNBC);
22138cfa0ad2SJack F Vogel 	E1000_READ_REG(hw, E1000_MPC);
22148cfa0ad2SJack F Vogel }
2215daf9197cSJack F Vogel 
22169d81738fSJack F Vogel /**
22179d81738fSJack F Vogel  *  e1000_set_pcie_completion_timeout - set pci-e completion timeout
22189d81738fSJack F Vogel  *  @hw: pointer to the HW structure
22199d81738fSJack F Vogel  *
22209d81738fSJack F Vogel  *  The defaults for 82575 and 82576 should be in the range of 50us to 50ms,
22219d81738fSJack F Vogel  *  however the hardware default for these parts is 500us to 1ms which is less
22229d81738fSJack F Vogel  *  than the 10ms recommended by the pci-e spec.  To address this we need to
22239d81738fSJack F Vogel  *  increase the value to either 10ms to 200ms for capability version 1 config,
22249d81738fSJack F Vogel  *  or 16ms to 55ms for version 2.
22259d81738fSJack F Vogel  **/
22269d81738fSJack F Vogel static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw)
22279d81738fSJack F Vogel {
22289d81738fSJack F Vogel 	u32 gcr = E1000_READ_REG(hw, E1000_GCR);
22299d81738fSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
22309d81738fSJack F Vogel 	u16 pcie_devctl2;
22319d81738fSJack F Vogel 
22329d81738fSJack F Vogel 	/* only take action if timeout value is defaulted to 0 */
22339d81738fSJack F Vogel 	if (gcr & E1000_GCR_CMPL_TMOUT_MASK)
22349d81738fSJack F Vogel 		goto out;
22359d81738fSJack F Vogel 
22369d81738fSJack F Vogel 	/*
22379d81738fSJack F Vogel 	 * if capababilities version is type 1 we can write the
22389d81738fSJack F Vogel 	 * timeout of 10ms to 200ms through the GCR register
22399d81738fSJack F Vogel 	 */
22409d81738fSJack F Vogel 	if (!(gcr & E1000_GCR_CAP_VER2)) {
22419d81738fSJack F Vogel 		gcr |= E1000_GCR_CMPL_TMOUT_10ms;
22429d81738fSJack F Vogel 		goto out;
22439d81738fSJack F Vogel 	}
22449d81738fSJack F Vogel 
22459d81738fSJack F Vogel 	/*
22469d81738fSJack F Vogel 	 * for version 2 capabilities we need to write the config space
22479d81738fSJack F Vogel 	 * directly in order to set the completion timeout value for
22489d81738fSJack F Vogel 	 * 16ms to 55ms
22499d81738fSJack F Vogel 	 */
22509d81738fSJack F Vogel 	ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
22519d81738fSJack F Vogel 					  &pcie_devctl2);
22529d81738fSJack F Vogel 	if (ret_val)
22539d81738fSJack F Vogel 		goto out;
22549d81738fSJack F Vogel 
22559d81738fSJack F Vogel 	pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms;
22569d81738fSJack F Vogel 
22579d81738fSJack F Vogel 	ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
22589d81738fSJack F Vogel 					   &pcie_devctl2);
22599d81738fSJack F Vogel out:
22609d81738fSJack F Vogel 	/* disable completion timeout resend */
22619d81738fSJack F Vogel 	gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND;
22629d81738fSJack F Vogel 
22639d81738fSJack F Vogel 	E1000_WRITE_REG(hw, E1000_GCR, gcr);
22649d81738fSJack F Vogel 	return ret_val;
22659d81738fSJack F Vogel }
22669d81738fSJack F Vogel 
22677d9119bdSJack F Vogel /**
22687d9119bdSJack F Vogel  *  e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing
22697d9119bdSJack F Vogel  *  @hw: pointer to the hardware struct
22707d9119bdSJack F Vogel  *  @enable: state to enter, either enabled or disabled
22717d9119bdSJack F Vogel  *  @pf: Physical Function pool - do not set anti-spoofing for the PF
22727d9119bdSJack F Vogel  *
22737d9119bdSJack F Vogel  *  enables/disables L2 switch anti-spoofing functionality.
22747d9119bdSJack F Vogel  **/
22757d9119bdSJack F Vogel void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
22767d9119bdSJack F Vogel {
22777609433eSJack F Vogel 	u32 reg_val, reg_offset;
22787d9119bdSJack F Vogel 
22797d9119bdSJack F Vogel 	switch (hw->mac.type) {
22807d9119bdSJack F Vogel 	case e1000_82576:
22817609433eSJack F Vogel 		reg_offset = E1000_DTXSWC;
22827d9119bdSJack F Vogel 		break;
22834dab5c37SJack F Vogel 	case e1000_i350:
22847609433eSJack F Vogel 	case e1000_i354:
22857609433eSJack F Vogel 		reg_offset = E1000_TXSWC;
22867609433eSJack F Vogel 		break;
22877609433eSJack F Vogel 	default:
22887609433eSJack F Vogel 		return;
22897609433eSJack F Vogel 	}
22907609433eSJack F Vogel 
22917609433eSJack F Vogel 	reg_val = E1000_READ_REG(hw, reg_offset);
22924dab5c37SJack F Vogel 	if (enable) {
22937609433eSJack F Vogel 		reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK |
22944dab5c37SJack F Vogel 			     E1000_DTXSWC_VLAN_SPOOF_MASK);
22954dab5c37SJack F Vogel 		/* The PF can spoof - it has to in order to
22964dab5c37SJack F Vogel 		 * support emulation mode NICs
22974dab5c37SJack F Vogel 		 */
22987609433eSJack F Vogel 		reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
22994dab5c37SJack F Vogel 	} else {
23007609433eSJack F Vogel 		reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
23014dab5c37SJack F Vogel 			     E1000_DTXSWC_VLAN_SPOOF_MASK);
23024dab5c37SJack F Vogel 	}
23037609433eSJack F Vogel 	E1000_WRITE_REG(hw, reg_offset, reg_val);
23047d9119bdSJack F Vogel }
23057d9119bdSJack F Vogel 
23064edd8523SJack F Vogel /**
23074edd8523SJack F Vogel  *  e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback
23084edd8523SJack F Vogel  *  @hw: pointer to the hardware struct
23094edd8523SJack F Vogel  *  @enable: state to enter, either enabled or disabled
23104edd8523SJack F Vogel  *
23114edd8523SJack F Vogel  *  enables/disables L2 switch loopback functionality.
23124edd8523SJack F Vogel  **/
23134edd8523SJack F Vogel void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
23144edd8523SJack F Vogel {
23158ec87fc5SJack F Vogel 	u32 dtxswc;
23164edd8523SJack F Vogel 
23178ec87fc5SJack F Vogel 	switch (hw->mac.type) {
23188ec87fc5SJack F Vogel 	case e1000_82576:
23198ec87fc5SJack F Vogel 		dtxswc = E1000_READ_REG(hw, E1000_DTXSWC);
23204edd8523SJack F Vogel 		if (enable)
23214edd8523SJack F Vogel 			dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
23224edd8523SJack F Vogel 		else
23234edd8523SJack F Vogel 			dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
23244edd8523SJack F Vogel 		E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
23258ec87fc5SJack F Vogel 		break;
2326f0ecc46dSJack F Vogel 	case e1000_i350:
23277609433eSJack F Vogel 	case e1000_i354:
2328f0ecc46dSJack F Vogel 		dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
2329f0ecc46dSJack F Vogel 		if (enable)
2330f0ecc46dSJack F Vogel 			dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
2331f0ecc46dSJack F Vogel 		else
2332f0ecc46dSJack F Vogel 			dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
2333f0ecc46dSJack F Vogel 		E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
2334f0ecc46dSJack F Vogel 		break;
23358ec87fc5SJack F Vogel 	default:
23368ec87fc5SJack F Vogel 		/* Currently no other hardware supports loopback */
23378ec87fc5SJack F Vogel 		break;
23388ec87fc5SJack F Vogel 	}
23398ec87fc5SJack F Vogel 
23408ec87fc5SJack F Vogel 
23414edd8523SJack F Vogel }
23424edd8523SJack F Vogel 
23434edd8523SJack F Vogel /**
23444edd8523SJack F Vogel  *  e1000_vmdq_set_replication_pf - enable or disable vmdq replication
23454edd8523SJack F Vogel  *  @hw: pointer to the hardware struct
23464edd8523SJack F Vogel  *  @enable: state to enter, either enabled or disabled
23474edd8523SJack F Vogel  *
23484edd8523SJack F Vogel  *  enables/disables replication of packets across multiple pools.
23494edd8523SJack F Vogel  **/
23504edd8523SJack F Vogel void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable)
23514edd8523SJack F Vogel {
23524edd8523SJack F Vogel 	u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL);
23534edd8523SJack F Vogel 
23544edd8523SJack F Vogel 	if (enable)
23554edd8523SJack F Vogel 		vt_ctl |= E1000_VT_CTL_VM_REPL_EN;
23564edd8523SJack F Vogel 	else
23574edd8523SJack F Vogel 		vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN;
23584edd8523SJack F Vogel 
23594edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl);
23604edd8523SJack F Vogel }
23614edd8523SJack F Vogel 
23624edd8523SJack F Vogel /**
23634edd8523SJack F Vogel  *  e1000_read_phy_reg_82580 - Read 82580 MDI control register
23644edd8523SJack F Vogel  *  @hw: pointer to the HW structure
23654edd8523SJack F Vogel  *  @offset: register offset to be read
23664edd8523SJack F Vogel  *  @data: pointer to the read data
23674edd8523SJack F Vogel  *
23684edd8523SJack F Vogel  *  Reads the MDI control register in the PHY at offset and stores the
23694edd8523SJack F Vogel  *  information read to data.
23704edd8523SJack F Vogel  **/
23714edd8523SJack F Vogel static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data)
23724edd8523SJack F Vogel {
23734edd8523SJack F Vogel 	s32 ret_val;
23744edd8523SJack F Vogel 
23754edd8523SJack F Vogel 	DEBUGFUNC("e1000_read_phy_reg_82580");
23764edd8523SJack F Vogel 
23774edd8523SJack F Vogel 	ret_val = hw->phy.ops.acquire(hw);
23784edd8523SJack F Vogel 	if (ret_val)
23794edd8523SJack F Vogel 		goto out;
23804edd8523SJack F Vogel 
23814edd8523SJack F Vogel 	ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
23824edd8523SJack F Vogel 
23834edd8523SJack F Vogel 	hw->phy.ops.release(hw);
23844edd8523SJack F Vogel 
23854edd8523SJack F Vogel out:
23864edd8523SJack F Vogel 	return ret_val;
23874edd8523SJack F Vogel }
23884edd8523SJack F Vogel 
23894edd8523SJack F Vogel /**
23904edd8523SJack F Vogel  *  e1000_write_phy_reg_82580 - Write 82580 MDI control register
23914edd8523SJack F Vogel  *  @hw: pointer to the HW structure
23924edd8523SJack F Vogel  *  @offset: register offset to write to
23934edd8523SJack F Vogel  *  @data: data to write to register at offset
23944edd8523SJack F Vogel  *
23954edd8523SJack F Vogel  *  Writes data to MDI control register in the PHY at offset.
23964edd8523SJack F Vogel  **/
23974edd8523SJack F Vogel static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data)
23984edd8523SJack F Vogel {
23994edd8523SJack F Vogel 	s32 ret_val;
24004edd8523SJack F Vogel 
24014edd8523SJack F Vogel 	DEBUGFUNC("e1000_write_phy_reg_82580");
24024edd8523SJack F Vogel 
24034edd8523SJack F Vogel 	ret_val = hw->phy.ops.acquire(hw);
24044edd8523SJack F Vogel 	if (ret_val)
24054edd8523SJack F Vogel 		goto out;
24064edd8523SJack F Vogel 
24074edd8523SJack F Vogel 	ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
24084edd8523SJack F Vogel 
24094edd8523SJack F Vogel 	hw->phy.ops.release(hw);
24104edd8523SJack F Vogel 
24114edd8523SJack F Vogel out:
24124edd8523SJack F Vogel 	return ret_val;
24134edd8523SJack F Vogel }
2414a69ed8dfSJack F Vogel 
24154edd8523SJack F Vogel /**
24167d9119bdSJack F Vogel  *  e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits
24177d9119bdSJack F Vogel  *  @hw: pointer to the HW structure
24187d9119bdSJack F Vogel  *
2419*cef367e6SEitan Adler  *  This resets the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on
24207d9119bdSJack F Vogel  *  the values found in the EEPROM.  This addresses an issue in which these
24217d9119bdSJack F Vogel  *  bits are not restored from EEPROM after reset.
24227d9119bdSJack F Vogel  **/
24237d9119bdSJack F Vogel static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw)
24247d9119bdSJack F Vogel {
24257d9119bdSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
24267d9119bdSJack F Vogel 	u32 mdicnfg;
2427f0ecc46dSJack F Vogel 	u16 nvm_data = 0;
24287d9119bdSJack F Vogel 
24297d9119bdSJack F Vogel 	DEBUGFUNC("e1000_reset_mdicnfg_82580");
24307d9119bdSJack F Vogel 
24317d9119bdSJack F Vogel 	if (hw->mac.type != e1000_82580)
24327d9119bdSJack F Vogel 		goto out;
24337d9119bdSJack F Vogel 	if (!e1000_sgmii_active_82575(hw))
24347d9119bdSJack F Vogel 		goto out;
24357d9119bdSJack F Vogel 
24367d9119bdSJack F Vogel 	ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
24377d9119bdSJack F Vogel 				   NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
24387d9119bdSJack F Vogel 				   &nvm_data);
24397d9119bdSJack F Vogel 	if (ret_val) {
24407d9119bdSJack F Vogel 		DEBUGOUT("NVM Read Error\n");
24417d9119bdSJack F Vogel 		goto out;
24427d9119bdSJack F Vogel 	}
24437d9119bdSJack F Vogel 
24447d9119bdSJack F Vogel 	mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG);
24457d9119bdSJack F Vogel 	if (nvm_data & NVM_WORD24_EXT_MDIO)
24467d9119bdSJack F Vogel 		mdicnfg |= E1000_MDICNFG_EXT_MDIO;
24477d9119bdSJack F Vogel 	if (nvm_data & NVM_WORD24_COM_MDIO)
24487d9119bdSJack F Vogel 		mdicnfg |= E1000_MDICNFG_COM_MDIO;
24497d9119bdSJack F Vogel 	E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg);
24507d9119bdSJack F Vogel out:
24517d9119bdSJack F Vogel 	return ret_val;
24527d9119bdSJack F Vogel }
24537d9119bdSJack F Vogel 
24547d9119bdSJack F Vogel /**
24554edd8523SJack F Vogel  *  e1000_reset_hw_82580 - Reset hardware
24564edd8523SJack F Vogel  *  @hw: pointer to the HW structure
24574edd8523SJack F Vogel  *
24584edd8523SJack F Vogel  *  This resets function or entire device (all ports, etc.)
24594edd8523SJack F Vogel  *  to a known state.
24604edd8523SJack F Vogel  **/
24614edd8523SJack F Vogel static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
24624edd8523SJack F Vogel {
24634edd8523SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
24644edd8523SJack F Vogel 	/* BH SW mailbox bit in SW_FW_SYNC */
24654edd8523SJack F Vogel 	u16 swmbsw_mask = E1000_SW_SYNCH_MB;
2466f0ecc46dSJack F Vogel 	u32 ctrl;
24674edd8523SJack F Vogel 	bool global_device_reset = hw->dev_spec._82575.global_device_reset;
24684edd8523SJack F Vogel 
24694edd8523SJack F Vogel 	DEBUGFUNC("e1000_reset_hw_82580");
24704edd8523SJack F Vogel 
24714edd8523SJack F Vogel 	hw->dev_spec._82575.global_device_reset = FALSE;
24724edd8523SJack F Vogel 
24736ab6bfe3SJack F Vogel 	/* 82580 does not reliably do global_device_reset due to hw errata */
24746ab6bfe3SJack F Vogel 	if (hw->mac.type == e1000_82580)
24756ab6bfe3SJack F Vogel 		global_device_reset = FALSE;
24766ab6bfe3SJack F Vogel 
24774edd8523SJack F Vogel 	/* Get current control state. */
24784edd8523SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
24794edd8523SJack F Vogel 
24804edd8523SJack F Vogel 	/*
24814edd8523SJack F Vogel 	 * Prevent the PCI-E bus from sticking if there is no TLP connection
24824edd8523SJack F Vogel 	 * on the last TLP read/write transaction when MAC is reset.
24834edd8523SJack F Vogel 	 */
24844edd8523SJack F Vogel 	ret_val = e1000_disable_pcie_master_generic(hw);
24854edd8523SJack F Vogel 	if (ret_val)
24864edd8523SJack F Vogel 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
24874edd8523SJack F Vogel 
24884edd8523SJack F Vogel 	DEBUGOUT("Masking off all interrupts\n");
24894edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
24904edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
24914edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
24924edd8523SJack F Vogel 	E1000_WRITE_FLUSH(hw);
24934edd8523SJack F Vogel 
24944edd8523SJack F Vogel 	msec_delay(10);
24954edd8523SJack F Vogel 
24964edd8523SJack F Vogel 	/* Determine whether or not a global dev reset is requested */
2497ab5d0362SJack F Vogel 	if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw,
24984dab5c37SJack F Vogel 	    swmbsw_mask))
24994edd8523SJack F Vogel 			global_device_reset = FALSE;
25004edd8523SJack F Vogel 
25014dab5c37SJack F Vogel 	if (global_device_reset && !(E1000_READ_REG(hw, E1000_STATUS) &
25024dab5c37SJack F Vogel 	    E1000_STAT_DEV_RST_SET))
25034edd8523SJack F Vogel 		ctrl |= E1000_CTRL_DEV_RST;
25044edd8523SJack F Vogel 	else
25054edd8523SJack F Vogel 		ctrl |= E1000_CTRL_RST;
25064edd8523SJack F Vogel 
25074edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
25084edd8523SJack F Vogel 
25098cc64f1eSJack F Vogel 	switch (hw->device_id) {
25108cc64f1eSJack F Vogel 	case E1000_DEV_ID_DH89XXCC_SGMII:
25118cc64f1eSJack F Vogel 		break;
25128cc64f1eSJack F Vogel 	default:
25138cc64f1eSJack F Vogel 		E1000_WRITE_FLUSH(hw);
25148cc64f1eSJack F Vogel 		break;
25158cc64f1eSJack F Vogel 	}
25168cc64f1eSJack F Vogel 
25178cc64f1eSJack F Vogel 	/* Add delay to insure DEV_RST or RST has time to complete */
25184edd8523SJack F Vogel 	msec_delay(5);
25194edd8523SJack F Vogel 
25204edd8523SJack F Vogel 	ret_val = e1000_get_auto_rd_done_generic(hw);
25214edd8523SJack F Vogel 	if (ret_val) {
25224edd8523SJack F Vogel 		/*
25234edd8523SJack F Vogel 		 * When auto config read does not complete, do not
25244edd8523SJack F Vogel 		 * return with an error. This can happen in situations
25254edd8523SJack F Vogel 		 * where there is no eeprom and prevents getting link.
25264edd8523SJack F Vogel 		 */
25274edd8523SJack F Vogel 		DEBUGOUT("Auto Read Done did not complete\n");
25284edd8523SJack F Vogel 	}
25294edd8523SJack F Vogel 
25304edd8523SJack F Vogel 	/* clear global device reset status bit */
25314edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET);
25324edd8523SJack F Vogel 
25334edd8523SJack F Vogel 	/* Clear any pending interrupt events. */
25344edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
2535f0ecc46dSJack F Vogel 	E1000_READ_REG(hw, E1000_ICR);
25364edd8523SJack F Vogel 
25377d9119bdSJack F Vogel 	ret_val = e1000_reset_mdicnfg_82580(hw);
25387d9119bdSJack F Vogel 	if (ret_val)
25397d9119bdSJack F Vogel 		DEBUGOUT("Could not reset MDICNFG based on EEPROM\n");
25407d9119bdSJack F Vogel 
25414edd8523SJack F Vogel 	/* Install any alternate MAC address into RAR0 */
25424edd8523SJack F Vogel 	ret_val = e1000_check_alt_mac_addr_generic(hw);
25434edd8523SJack F Vogel 
25444edd8523SJack F Vogel 	/* Release semaphore */
25454edd8523SJack F Vogel 	if (global_device_reset)
2546ab5d0362SJack F Vogel 		hw->mac.ops.release_swfw_sync(hw, swmbsw_mask);
25474edd8523SJack F Vogel 
25484edd8523SJack F Vogel 	return ret_val;
25494edd8523SJack F Vogel }
25504edd8523SJack F Vogel 
25514edd8523SJack F Vogel /**
2552f0ecc46dSJack F Vogel  *  e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size
25534edd8523SJack F Vogel  *  @data: data received by reading RXPBS register
25544edd8523SJack F Vogel  *
25554edd8523SJack F Vogel  *  The 82580 uses a table based approach for packet buffer allocation sizes.
25564edd8523SJack F Vogel  *  This function converts the retrieved value into the correct table value
25574edd8523SJack F Vogel  *     0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7
25584edd8523SJack F Vogel  *  0x0 36  72 144   1   2   4   8  16
25594edd8523SJack F Vogel  *  0x8 35  70 140 rsv rsv rsv rsv rsv
25604edd8523SJack F Vogel  */
25614edd8523SJack F Vogel u16 e1000_rxpbs_adjust_82580(u32 data)
25624edd8523SJack F Vogel {
25634edd8523SJack F Vogel 	u16 ret_val = 0;
25644edd8523SJack F Vogel 
25654edd8523SJack F Vogel 	if (data < E1000_82580_RXPBS_TABLE_SIZE)
25664edd8523SJack F Vogel 		ret_val = e1000_82580_rxpbs_table[data];
25674edd8523SJack F Vogel 
25684edd8523SJack F Vogel 	return ret_val;
25694edd8523SJack F Vogel }
2570f0ecc46dSJack F Vogel 
2571f0ecc46dSJack F Vogel /**
2572f0ecc46dSJack F Vogel  *  e1000_validate_nvm_checksum_with_offset - Validate EEPROM
2573f0ecc46dSJack F Vogel  *  checksum
2574f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2575f0ecc46dSJack F Vogel  *  @offset: offset in words of the checksum protected region
2576f0ecc46dSJack F Vogel  *
2577f0ecc46dSJack F Vogel  *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
2578f0ecc46dSJack F Vogel  *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
2579f0ecc46dSJack F Vogel  **/
2580f0ecc46dSJack F Vogel s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
2581f0ecc46dSJack F Vogel {
2582f0ecc46dSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
2583f0ecc46dSJack F Vogel 	u16 checksum = 0;
2584f0ecc46dSJack F Vogel 	u16 i, nvm_data;
2585f0ecc46dSJack F Vogel 
2586f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_validate_nvm_checksum_with_offset");
2587f0ecc46dSJack F Vogel 
2588f0ecc46dSJack F Vogel 	for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) {
2589f0ecc46dSJack F Vogel 		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
2590f0ecc46dSJack F Vogel 		if (ret_val) {
2591f0ecc46dSJack F Vogel 			DEBUGOUT("NVM Read Error\n");
2592f0ecc46dSJack F Vogel 			goto out;
2593f0ecc46dSJack F Vogel 		}
2594f0ecc46dSJack F Vogel 		checksum += nvm_data;
2595f0ecc46dSJack F Vogel 	}
2596f0ecc46dSJack F Vogel 
2597f0ecc46dSJack F Vogel 	if (checksum != (u16) NVM_SUM) {
2598f0ecc46dSJack F Vogel 		DEBUGOUT("NVM Checksum Invalid\n");
2599f0ecc46dSJack F Vogel 		ret_val = -E1000_ERR_NVM;
2600f0ecc46dSJack F Vogel 		goto out;
2601f0ecc46dSJack F Vogel 	}
2602f0ecc46dSJack F Vogel 
2603f0ecc46dSJack F Vogel out:
2604f0ecc46dSJack F Vogel 	return ret_val;
2605f0ecc46dSJack F Vogel }
2606f0ecc46dSJack F Vogel 
2607f0ecc46dSJack F Vogel /**
2608f0ecc46dSJack F Vogel  *  e1000_update_nvm_checksum_with_offset - Update EEPROM
2609f0ecc46dSJack F Vogel  *  checksum
2610f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2611f0ecc46dSJack F Vogel  *  @offset: offset in words of the checksum protected region
2612f0ecc46dSJack F Vogel  *
2613f0ecc46dSJack F Vogel  *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
2614f0ecc46dSJack F Vogel  *  up to the checksum.  Then calculates the EEPROM checksum and writes the
2615f0ecc46dSJack F Vogel  *  value to the EEPROM.
2616f0ecc46dSJack F Vogel  **/
2617f0ecc46dSJack F Vogel s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
2618f0ecc46dSJack F Vogel {
2619f0ecc46dSJack F Vogel 	s32 ret_val;
2620f0ecc46dSJack F Vogel 	u16 checksum = 0;
2621f0ecc46dSJack F Vogel 	u16 i, nvm_data;
2622f0ecc46dSJack F Vogel 
2623f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_update_nvm_checksum_with_offset");
2624f0ecc46dSJack F Vogel 
2625f0ecc46dSJack F Vogel 	for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) {
2626f0ecc46dSJack F Vogel 		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
2627f0ecc46dSJack F Vogel 		if (ret_val) {
2628f0ecc46dSJack F Vogel 			DEBUGOUT("NVM Read Error while updating checksum.\n");
2629f0ecc46dSJack F Vogel 			goto out;
2630f0ecc46dSJack F Vogel 		}
2631f0ecc46dSJack F Vogel 		checksum += nvm_data;
2632f0ecc46dSJack F Vogel 	}
2633f0ecc46dSJack F Vogel 	checksum = (u16) NVM_SUM - checksum;
2634f0ecc46dSJack F Vogel 	ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1,
2635f0ecc46dSJack F Vogel 				    &checksum);
2636f0ecc46dSJack F Vogel 	if (ret_val)
2637f0ecc46dSJack F Vogel 		DEBUGOUT("NVM Write Error while updating checksum.\n");
2638f0ecc46dSJack F Vogel 
2639f0ecc46dSJack F Vogel out:
2640f0ecc46dSJack F Vogel 	return ret_val;
2641f0ecc46dSJack F Vogel }
2642f0ecc46dSJack F Vogel 
2643f0ecc46dSJack F Vogel /**
2644f0ecc46dSJack F Vogel  *  e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum
2645f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2646f0ecc46dSJack F Vogel  *
2647f0ecc46dSJack F Vogel  *  Calculates the EEPROM section checksum by reading/adding each word of
2648f0ecc46dSJack F Vogel  *  the EEPROM and then verifies that the sum of the EEPROM is
2649f0ecc46dSJack F Vogel  *  equal to 0xBABA.
2650f0ecc46dSJack F Vogel  **/
2651f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw)
2652f0ecc46dSJack F Vogel {
26538cc64f1eSJack F Vogel 	s32 ret_val;
2654f0ecc46dSJack F Vogel 	u16 eeprom_regions_count = 1;
2655f0ecc46dSJack F Vogel 	u16 j, nvm_data;
2656f0ecc46dSJack F Vogel 	u16 nvm_offset;
2657f0ecc46dSJack F Vogel 
2658f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_validate_nvm_checksum_82580");
2659f0ecc46dSJack F Vogel 
2660f0ecc46dSJack F Vogel 	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
2661f0ecc46dSJack F Vogel 	if (ret_val) {
2662f0ecc46dSJack F Vogel 		DEBUGOUT("NVM Read Error\n");
2663f0ecc46dSJack F Vogel 		goto out;
2664f0ecc46dSJack F Vogel 	}
2665f0ecc46dSJack F Vogel 
2666f0ecc46dSJack F Vogel 	if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) {
2667f0ecc46dSJack F Vogel 		/* if chekcsums compatibility bit is set validate checksums
2668f0ecc46dSJack F Vogel 		 * for all 4 ports. */
2669f0ecc46dSJack F Vogel 		eeprom_regions_count = 4;
2670f0ecc46dSJack F Vogel 	}
2671f0ecc46dSJack F Vogel 
2672f0ecc46dSJack F Vogel 	for (j = 0; j < eeprom_regions_count; j++) {
2673f0ecc46dSJack F Vogel 		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2674f0ecc46dSJack F Vogel 		ret_val = e1000_validate_nvm_checksum_with_offset(hw,
2675f0ecc46dSJack F Vogel 								  nvm_offset);
2676f0ecc46dSJack F Vogel 		if (ret_val != E1000_SUCCESS)
2677f0ecc46dSJack F Vogel 			goto out;
2678f0ecc46dSJack F Vogel 	}
2679f0ecc46dSJack F Vogel 
2680f0ecc46dSJack F Vogel out:
2681f0ecc46dSJack F Vogel 	return ret_val;
2682f0ecc46dSJack F Vogel }
2683f0ecc46dSJack F Vogel 
2684f0ecc46dSJack F Vogel /**
2685f0ecc46dSJack F Vogel  *  e1000_update_nvm_checksum_82580 - Update EEPROM checksum
2686f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2687f0ecc46dSJack F Vogel  *
2688f0ecc46dSJack F Vogel  *  Updates the EEPROM section checksums for all 4 ports by reading/adding
2689f0ecc46dSJack F Vogel  *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
2690f0ecc46dSJack F Vogel  *  checksum and writes the value to the EEPROM.
2691f0ecc46dSJack F Vogel  **/
2692f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw)
2693f0ecc46dSJack F Vogel {
2694f0ecc46dSJack F Vogel 	s32 ret_val;
2695f0ecc46dSJack F Vogel 	u16 j, nvm_data;
2696f0ecc46dSJack F Vogel 	u16 nvm_offset;
2697f0ecc46dSJack F Vogel 
2698f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_update_nvm_checksum_82580");
2699f0ecc46dSJack F Vogel 
2700f0ecc46dSJack F Vogel 	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
2701f0ecc46dSJack F Vogel 	if (ret_val) {
27024dab5c37SJack F Vogel 		DEBUGOUT("NVM Read Error while updating checksum compatibility bit.\n");
2703f0ecc46dSJack F Vogel 		goto out;
2704f0ecc46dSJack F Vogel 	}
2705f0ecc46dSJack F Vogel 
2706ab5d0362SJack F Vogel 	if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) {
2707f0ecc46dSJack F Vogel 		/* set compatibility bit to validate checksums appropriately */
2708f0ecc46dSJack F Vogel 		nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK;
2709f0ecc46dSJack F Vogel 		ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1,
2710f0ecc46dSJack F Vogel 					    &nvm_data);
2711f0ecc46dSJack F Vogel 		if (ret_val) {
27124dab5c37SJack F Vogel 			DEBUGOUT("NVM Write Error while updating checksum compatibility bit.\n");
2713f0ecc46dSJack F Vogel 			goto out;
2714f0ecc46dSJack F Vogel 		}
2715f0ecc46dSJack F Vogel 	}
2716f0ecc46dSJack F Vogel 
2717f0ecc46dSJack F Vogel 	for (j = 0; j < 4; j++) {
2718f0ecc46dSJack F Vogel 		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2719f0ecc46dSJack F Vogel 		ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
27204dab5c37SJack F Vogel 		if (ret_val)
2721f0ecc46dSJack F Vogel 			goto out;
2722f0ecc46dSJack F Vogel 	}
2723f0ecc46dSJack F Vogel 
2724f0ecc46dSJack F Vogel out:
2725f0ecc46dSJack F Vogel 	return ret_val;
2726f0ecc46dSJack F Vogel }
2727f0ecc46dSJack F Vogel 
2728f0ecc46dSJack F Vogel /**
2729f0ecc46dSJack F Vogel  *  e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum
2730f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2731f0ecc46dSJack F Vogel  *
2732f0ecc46dSJack F Vogel  *  Calculates the EEPROM section checksum by reading/adding each word of
2733f0ecc46dSJack F Vogel  *  the EEPROM and then verifies that the sum of the EEPROM is
2734f0ecc46dSJack F Vogel  *  equal to 0xBABA.
2735f0ecc46dSJack F Vogel  **/
2736f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw)
2737f0ecc46dSJack F Vogel {
2738f0ecc46dSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
2739f0ecc46dSJack F Vogel 	u16 j;
2740f0ecc46dSJack F Vogel 	u16 nvm_offset;
2741f0ecc46dSJack F Vogel 
2742f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_validate_nvm_checksum_i350");
2743f0ecc46dSJack F Vogel 
2744f0ecc46dSJack F Vogel 	for (j = 0; j < 4; j++) {
2745f0ecc46dSJack F Vogel 		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2746f0ecc46dSJack F Vogel 		ret_val = e1000_validate_nvm_checksum_with_offset(hw,
2747f0ecc46dSJack F Vogel 								  nvm_offset);
2748f0ecc46dSJack F Vogel 		if (ret_val != E1000_SUCCESS)
2749f0ecc46dSJack F Vogel 			goto out;
2750f0ecc46dSJack F Vogel 	}
2751f0ecc46dSJack F Vogel 
2752f0ecc46dSJack F Vogel out:
2753f0ecc46dSJack F Vogel 	return ret_val;
2754f0ecc46dSJack F Vogel }
2755f0ecc46dSJack F Vogel 
2756f0ecc46dSJack F Vogel /**
2757f0ecc46dSJack F Vogel  *  e1000_update_nvm_checksum_i350 - Update EEPROM checksum
2758f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2759f0ecc46dSJack F Vogel  *
2760f0ecc46dSJack F Vogel  *  Updates the EEPROM section checksums for all 4 ports by reading/adding
2761f0ecc46dSJack F Vogel  *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
2762f0ecc46dSJack F Vogel  *  checksum and writes the value to the EEPROM.
2763f0ecc46dSJack F Vogel  **/
2764f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw)
2765f0ecc46dSJack F Vogel {
2766f0ecc46dSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
2767f0ecc46dSJack F Vogel 	u16 j;
2768f0ecc46dSJack F Vogel 	u16 nvm_offset;
2769f0ecc46dSJack F Vogel 
2770f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_update_nvm_checksum_i350");
2771f0ecc46dSJack F Vogel 
2772f0ecc46dSJack F Vogel 	for (j = 0; j < 4; j++) {
2773f0ecc46dSJack F Vogel 		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2774f0ecc46dSJack F Vogel 		ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
2775f0ecc46dSJack F Vogel 		if (ret_val != E1000_SUCCESS)
2776f0ecc46dSJack F Vogel 			goto out;
2777f0ecc46dSJack F Vogel 	}
2778f0ecc46dSJack F Vogel 
2779f0ecc46dSJack F Vogel out:
2780f0ecc46dSJack F Vogel 	return ret_val;
2781f0ecc46dSJack F Vogel }
2782f0ecc46dSJack F Vogel 
2783f0ecc46dSJack F Vogel /**
27847609433eSJack F Vogel  *  __e1000_access_emi_reg - Read/write EMI register
27857609433eSJack F Vogel  *  @hw: pointer to the HW structure
27867609433eSJack F Vogel  *  @addr: EMI address to program
27877609433eSJack F Vogel  *  @data: pointer to value to read/write from/to the EMI address
27887609433eSJack F Vogel  *  @read: boolean flag to indicate read or write
27897609433eSJack F Vogel  **/
27907609433eSJack F Vogel static s32 __e1000_access_emi_reg(struct e1000_hw *hw, u16 address,
27917609433eSJack F Vogel 				  u16 *data, bool read)
27927609433eSJack F Vogel {
27938cc64f1eSJack F Vogel 	s32 ret_val;
27947609433eSJack F Vogel 
27957609433eSJack F Vogel 	DEBUGFUNC("__e1000_access_emi_reg");
27967609433eSJack F Vogel 
27977609433eSJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address);
27987609433eSJack F Vogel 	if (ret_val)
27997609433eSJack F Vogel 		return ret_val;
28007609433eSJack F Vogel 
28017609433eSJack F Vogel 	if (read)
28027609433eSJack F Vogel 		ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data);
28037609433eSJack F Vogel 	else
28047609433eSJack F Vogel 		ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data);
28057609433eSJack F Vogel 
28067609433eSJack F Vogel 	return ret_val;
28077609433eSJack F Vogel }
28087609433eSJack F Vogel 
28097609433eSJack F Vogel /**
28107609433eSJack F Vogel  *  e1000_read_emi_reg - Read Extended Management Interface register
28117609433eSJack F Vogel  *  @hw: pointer to the HW structure
28127609433eSJack F Vogel  *  @addr: EMI address to program
28137609433eSJack F Vogel  *  @data: value to be read from the EMI address
28147609433eSJack F Vogel  **/
28157609433eSJack F Vogel s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data)
28167609433eSJack F Vogel {
28177609433eSJack F Vogel 	DEBUGFUNC("e1000_read_emi_reg");
28187609433eSJack F Vogel 
28197609433eSJack F Vogel 	return __e1000_access_emi_reg(hw, addr, data, TRUE);
28207609433eSJack F Vogel }
28217609433eSJack F Vogel 
28227609433eSJack F Vogel /**
28238cc64f1eSJack F Vogel  *  e1000_initialize_M88E1512_phy - Initialize M88E1512 PHY
28248cc64f1eSJack F Vogel  *  @hw: pointer to the HW structure
28258cc64f1eSJack F Vogel  *
2826c80429ceSEric Joyner  *  Initialize Marvell 1512 to work correctly with Avoton.
28278cc64f1eSJack F Vogel  **/
28288cc64f1eSJack F Vogel s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw)
28298cc64f1eSJack F Vogel {
28308cc64f1eSJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
28318cc64f1eSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
28328cc64f1eSJack F Vogel 
28338cc64f1eSJack F Vogel 	DEBUGFUNC("e1000_initialize_M88E1512_phy");
28348cc64f1eSJack F Vogel 
28358cc64f1eSJack F Vogel 	/* Check if this is correct PHY. */
28368cc64f1eSJack F Vogel 	if (phy->id != M88E1512_E_PHY_ID)
28378cc64f1eSJack F Vogel 		goto out;
28388cc64f1eSJack F Vogel 
28398cc64f1eSJack F Vogel 	/* Switch to PHY page 0xFF. */
28408cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF);
28418cc64f1eSJack F Vogel 	if (ret_val)
28428cc64f1eSJack F Vogel 		goto out;
28438cc64f1eSJack F Vogel 
28448cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B);
28458cc64f1eSJack F Vogel 	if (ret_val)
28468cc64f1eSJack F Vogel 		goto out;
28478cc64f1eSJack F Vogel 
28488cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144);
28498cc64f1eSJack F Vogel 	if (ret_val)
28508cc64f1eSJack F Vogel 		goto out;
28518cc64f1eSJack F Vogel 
28528cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28);
28538cc64f1eSJack F Vogel 	if (ret_val)
28548cc64f1eSJack F Vogel 		goto out;
28558cc64f1eSJack F Vogel 
28568cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146);
28578cc64f1eSJack F Vogel 	if (ret_val)
28588cc64f1eSJack F Vogel 		goto out;
28598cc64f1eSJack F Vogel 
28608cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233);
28618cc64f1eSJack F Vogel 	if (ret_val)
28628cc64f1eSJack F Vogel 		goto out;
28638cc64f1eSJack F Vogel 
28648cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D);
28658cc64f1eSJack F Vogel 	if (ret_val)
28668cc64f1eSJack F Vogel 		goto out;
28678cc64f1eSJack F Vogel 
28688cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xCC0C);
28698cc64f1eSJack F Vogel 	if (ret_val)
28708cc64f1eSJack F Vogel 		goto out;
28718cc64f1eSJack F Vogel 
28728cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159);
28738cc64f1eSJack F Vogel 	if (ret_val)
28748cc64f1eSJack F Vogel 		goto out;
28758cc64f1eSJack F Vogel 
28768cc64f1eSJack F Vogel 	/* Switch to PHY page 0xFB. */
28778cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB);
28788cc64f1eSJack F Vogel 	if (ret_val)
28798cc64f1eSJack F Vogel 		goto out;
28808cc64f1eSJack F Vogel 
28818cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0x000D);
28828cc64f1eSJack F Vogel 	if (ret_val)
28838cc64f1eSJack F Vogel 		goto out;
28848cc64f1eSJack F Vogel 
28858cc64f1eSJack F Vogel 	/* Switch to PHY page 0x12. */
28868cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12);
28878cc64f1eSJack F Vogel 	if (ret_val)
28888cc64f1eSJack F Vogel 		goto out;
28898cc64f1eSJack F Vogel 
28908cc64f1eSJack F Vogel 	/* Change mode to SGMII-to-Copper */
28918cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001);
28928cc64f1eSJack F Vogel 	if (ret_val)
28938cc64f1eSJack F Vogel 		goto out;
28948cc64f1eSJack F Vogel 
28958cc64f1eSJack F Vogel 	/* Return the PHY to page 0. */
28968cc64f1eSJack F Vogel 	ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
28978cc64f1eSJack F Vogel 	if (ret_val)
28988cc64f1eSJack F Vogel 		goto out;
28998cc64f1eSJack F Vogel 
29008cc64f1eSJack F Vogel 	ret_val = phy->ops.commit(hw);
29018cc64f1eSJack F Vogel 	if (ret_val) {
29028cc64f1eSJack F Vogel 		DEBUGOUT("Error committing the PHY changes\n");
29038cc64f1eSJack F Vogel 		return ret_val;
29048cc64f1eSJack F Vogel 	}
29058cc64f1eSJack F Vogel 
29068cc64f1eSJack F Vogel 	msec_delay(1000);
29078cc64f1eSJack F Vogel out:
29088cc64f1eSJack F Vogel 	return ret_val;
29098cc64f1eSJack F Vogel }
29108cc64f1eSJack F Vogel 
29118cc64f1eSJack F Vogel /**
2912c80429ceSEric Joyner  *  e1000_initialize_M88E1543_phy - Initialize M88E1543 PHY
2913c80429ceSEric Joyner  *  @hw: pointer to the HW structure
2914c80429ceSEric Joyner  *
2915c80429ceSEric Joyner  *  Initialize Marvell 1543 to work correctly with Avoton.
2916c80429ceSEric Joyner  **/
2917c80429ceSEric Joyner s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw)
2918c80429ceSEric Joyner {
2919c80429ceSEric Joyner 	struct e1000_phy_info *phy = &hw->phy;
2920c80429ceSEric Joyner 	s32 ret_val = E1000_SUCCESS;
2921c80429ceSEric Joyner 
2922c80429ceSEric Joyner 	DEBUGFUNC("e1000_initialize_M88E1543_phy");
2923c80429ceSEric Joyner 
2924c80429ceSEric Joyner 	/* Check if this is correct PHY. */
2925c80429ceSEric Joyner 	if (phy->id != M88E1543_E_PHY_ID)
2926c80429ceSEric Joyner 		goto out;
2927c80429ceSEric Joyner 
2928c80429ceSEric Joyner 	/* Switch to PHY page 0xFF. */
2929c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF);
2930c80429ceSEric Joyner 	if (ret_val)
2931c80429ceSEric Joyner 		goto out;
2932c80429ceSEric Joyner 
2933c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B);
2934c80429ceSEric Joyner 	if (ret_val)
2935c80429ceSEric Joyner 		goto out;
2936c80429ceSEric Joyner 
2937c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144);
2938c80429ceSEric Joyner 	if (ret_val)
2939c80429ceSEric Joyner 		goto out;
2940c80429ceSEric Joyner 
2941c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28);
2942c80429ceSEric Joyner 	if (ret_val)
2943c80429ceSEric Joyner 		goto out;
2944c80429ceSEric Joyner 
2945c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146);
2946c80429ceSEric Joyner 	if (ret_val)
2947c80429ceSEric Joyner 		goto out;
2948c80429ceSEric Joyner 
2949c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233);
2950c80429ceSEric Joyner 	if (ret_val)
2951c80429ceSEric Joyner 		goto out;
2952c80429ceSEric Joyner 
2953c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D);
2954c80429ceSEric Joyner 	if (ret_val)
2955c80429ceSEric Joyner 		goto out;
2956c80429ceSEric Joyner 
2957c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xDC0C);
2958c80429ceSEric Joyner 	if (ret_val)
2959c80429ceSEric Joyner 		goto out;
2960c80429ceSEric Joyner 
2961c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159);
2962c80429ceSEric Joyner 	if (ret_val)
2963c80429ceSEric Joyner 		goto out;
2964c80429ceSEric Joyner 
2965c80429ceSEric Joyner 	/* Switch to PHY page 0xFB. */
2966c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB);
2967c80429ceSEric Joyner 	if (ret_val)
2968c80429ceSEric Joyner 		goto out;
2969c80429ceSEric Joyner 
2970c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0xC00D);
2971c80429ceSEric Joyner 	if (ret_val)
2972c80429ceSEric Joyner 		goto out;
2973c80429ceSEric Joyner 
2974c80429ceSEric Joyner 	/* Switch to PHY page 0x12. */
2975c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12);
2976c80429ceSEric Joyner 	if (ret_val)
2977c80429ceSEric Joyner 		goto out;
2978c80429ceSEric Joyner 
2979c80429ceSEric Joyner 	/* Change mode to SGMII-to-Copper */
2980c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001);
2981c80429ceSEric Joyner 	if (ret_val)
2982c80429ceSEric Joyner 		goto out;
2983c80429ceSEric Joyner 
2984c80429ceSEric Joyner 	/* Switch to PHY page 1. */
2985c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x1);
2986c80429ceSEric Joyner 	if (ret_val)
2987c80429ceSEric Joyner 		goto out;
2988c80429ceSEric Joyner 
2989c80429ceSEric Joyner 	/* Change mode to 1000BASE-X/SGMII and autoneg enable; reset */
2990c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1543_FIBER_CTRL, 0x9140);
2991c80429ceSEric Joyner 	if (ret_val)
2992c80429ceSEric Joyner 		goto out;
2993c80429ceSEric Joyner 
2994c80429ceSEric Joyner 	/* Return the PHY to page 0. */
2995c80429ceSEric Joyner 	ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
2996c80429ceSEric Joyner 	if (ret_val)
2997c80429ceSEric Joyner 		goto out;
2998c80429ceSEric Joyner 
2999c80429ceSEric Joyner 	ret_val = phy->ops.commit(hw);
3000c80429ceSEric Joyner 	if (ret_val) {
3001c80429ceSEric Joyner 		DEBUGOUT("Error committing the PHY changes\n");
3002c80429ceSEric Joyner 		return ret_val;
3003c80429ceSEric Joyner 	}
3004c80429ceSEric Joyner 
3005c80429ceSEric Joyner 	msec_delay(1000);
3006c80429ceSEric Joyner out:
3007c80429ceSEric Joyner 	return ret_val;
3008c80429ceSEric Joyner }
3009c80429ceSEric Joyner 
3010c80429ceSEric Joyner /**
3011f0ecc46dSJack F Vogel  *  e1000_set_eee_i350 - Enable/disable EEE support
3012f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
3013c80429ceSEric Joyner  *  @adv1g: boolean flag enabling 1G EEE advertisement
3014c80429ceSEric Joyner  *  @adv100m: boolean flag enabling 100M EEE advertisement
3015f0ecc46dSJack F Vogel  *
3016f0ecc46dSJack F Vogel  *  Enable/disable EEE based on setting in dev_spec structure.
3017f0ecc46dSJack F Vogel  *
3018f0ecc46dSJack F Vogel  **/
3019c80429ceSEric Joyner s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M)
3020f0ecc46dSJack F Vogel {
30214dab5c37SJack F Vogel 	u32 ipcnfg, eeer;
3022f0ecc46dSJack F Vogel 
3023f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_set_eee_i350");
3024f0ecc46dSJack F Vogel 
30254dab5c37SJack F Vogel 	if ((hw->mac.type < e1000_i350) ||
30264dab5c37SJack F Vogel 	    (hw->phy.media_type != e1000_media_type_copper))
3027f0ecc46dSJack F Vogel 		goto out;
3028f0ecc46dSJack F Vogel 	ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG);
3029f0ecc46dSJack F Vogel 	eeer = E1000_READ_REG(hw, E1000_EEER);
3030f0ecc46dSJack F Vogel 
3031f0ecc46dSJack F Vogel 	/* enable or disable per user setting */
3032f0ecc46dSJack F Vogel 	if (!(hw->dev_spec._82575.eee_disable)) {
30336ab6bfe3SJack F Vogel 		u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU);
30346ab6bfe3SJack F Vogel 
3035c80429ceSEric Joyner 		if (adv100M)
3036c80429ceSEric Joyner 			ipcnfg |= E1000_IPCNFG_EEE_100M_AN;
3037c80429ceSEric Joyner 		else
3038c80429ceSEric Joyner 			ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN;
3039c80429ceSEric Joyner 
3040c80429ceSEric Joyner 		if (adv1G)
3041c80429ceSEric Joyner 			ipcnfg |= E1000_IPCNFG_EEE_1G_AN;
3042c80429ceSEric Joyner 		else
3043c80429ceSEric Joyner 			ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN;
3044c80429ceSEric Joyner 
30454dab5c37SJack F Vogel 		eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
3046f0ecc46dSJack F Vogel 			 E1000_EEER_LPI_FC);
3047f0ecc46dSJack F Vogel 
30486ab6bfe3SJack F Vogel 		/* This bit should not be set in normal operation. */
30496ab6bfe3SJack F Vogel 		if (eee_su & E1000_EEE_SU_LPI_CLK_STP)
30506ab6bfe3SJack F Vogel 			DEBUGOUT("LPI Clock Stop Bit should not be set!\n");
3051f0ecc46dSJack F Vogel 	} else {
30524dab5c37SJack F Vogel 		ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
30534dab5c37SJack F Vogel 		eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
3054f0ecc46dSJack F Vogel 			  E1000_EEER_LPI_FC);
3055f0ecc46dSJack F Vogel 	}
3056f0ecc46dSJack F Vogel 	E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg);
3057f0ecc46dSJack F Vogel 	E1000_WRITE_REG(hw, E1000_EEER, eeer);
3058f0ecc46dSJack F Vogel 	E1000_READ_REG(hw, E1000_IPCNFG);
3059f0ecc46dSJack F Vogel 	E1000_READ_REG(hw, E1000_EEER);
3060f0ecc46dSJack F Vogel out:
3061f0ecc46dSJack F Vogel 
30628cc64f1eSJack F Vogel 	return E1000_SUCCESS;
3063f0ecc46dSJack F Vogel }
30644dab5c37SJack F Vogel 
30657609433eSJack F Vogel /**
30667609433eSJack F Vogel  *  e1000_set_eee_i354 - Enable/disable EEE support
30677609433eSJack F Vogel  *  @hw: pointer to the HW structure
3068c80429ceSEric Joyner  *  @adv1g: boolean flag enabling 1G EEE advertisement
3069c80429ceSEric Joyner  *  @adv100m: boolean flag enabling 100M EEE advertisement
30707609433eSJack F Vogel  *
30717609433eSJack F Vogel  *  Enable/disable EEE legacy mode based on setting in dev_spec structure.
30727609433eSJack F Vogel  *
30737609433eSJack F Vogel  **/
3074c80429ceSEric Joyner s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M)
30757609433eSJack F Vogel {
30767609433eSJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
30777609433eSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
30787609433eSJack F Vogel 	u16 phy_data;
30797609433eSJack F Vogel 
30807609433eSJack F Vogel 	DEBUGFUNC("e1000_set_eee_i354");
30817609433eSJack F Vogel 
30827609433eSJack F Vogel 	if ((hw->phy.media_type != e1000_media_type_copper) ||
30837609433eSJack F Vogel 	    ((phy->id != M88E1543_E_PHY_ID) &&
30847609433eSJack F Vogel 	    (phy->id != M88E1512_E_PHY_ID)))
30857609433eSJack F Vogel 		goto out;
30867609433eSJack F Vogel 
30877609433eSJack F Vogel 	if (!hw->dev_spec._82575.eee_disable) {
30887609433eSJack F Vogel 		/* Switch to PHY page 18. */
30897609433eSJack F Vogel 		ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18);
30907609433eSJack F Vogel 		if (ret_val)
30917609433eSJack F Vogel 			goto out;
30927609433eSJack F Vogel 
30937609433eSJack F Vogel 		ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1,
30947609433eSJack F Vogel 					    &phy_data);
30957609433eSJack F Vogel 		if (ret_val)
30967609433eSJack F Vogel 			goto out;
30977609433eSJack F Vogel 
30987609433eSJack F Vogel 		phy_data |= E1000_M88E1543_EEE_CTRL_1_MS;
30997609433eSJack F Vogel 		ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1,
31007609433eSJack F Vogel 					     phy_data);
31017609433eSJack F Vogel 		if (ret_val)
31027609433eSJack F Vogel 			goto out;
31037609433eSJack F Vogel 
31047609433eSJack F Vogel 		/* Return the PHY to page 0. */
31057609433eSJack F Vogel 		ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
31067609433eSJack F Vogel 		if (ret_val)
31077609433eSJack F Vogel 			goto out;
31087609433eSJack F Vogel 
31097609433eSJack F Vogel 		/* Turn on EEE advertisement. */
31107609433eSJack F Vogel 		ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
31117609433eSJack F Vogel 					       E1000_EEE_ADV_DEV_I354,
31127609433eSJack F Vogel 					       &phy_data);
31137609433eSJack F Vogel 		if (ret_val)
31147609433eSJack F Vogel 			goto out;
31157609433eSJack F Vogel 
3116c80429ceSEric Joyner 		if (adv100M)
3117c80429ceSEric Joyner 			phy_data |= E1000_EEE_ADV_100_SUPPORTED;
3118c80429ceSEric Joyner 		else
3119c80429ceSEric Joyner 			phy_data &= ~E1000_EEE_ADV_100_SUPPORTED;
3120c80429ceSEric Joyner 
3121c80429ceSEric Joyner 		if (adv1G)
3122c80429ceSEric Joyner 			phy_data |= E1000_EEE_ADV_1000_SUPPORTED;
3123c80429ceSEric Joyner 		else
3124c80429ceSEric Joyner 			phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED;
3125c80429ceSEric Joyner 
31267609433eSJack F Vogel 		ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
31277609433eSJack F Vogel 						E1000_EEE_ADV_DEV_I354,
31287609433eSJack F Vogel 						phy_data);
31297609433eSJack F Vogel 	} else {
31307609433eSJack F Vogel 		/* Turn off EEE advertisement. */
31317609433eSJack F Vogel 		ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
31327609433eSJack F Vogel 					       E1000_EEE_ADV_DEV_I354,
31337609433eSJack F Vogel 					       &phy_data);
31347609433eSJack F Vogel 		if (ret_val)
31357609433eSJack F Vogel 			goto out;
31367609433eSJack F Vogel 
31377609433eSJack F Vogel 		phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED |
31387609433eSJack F Vogel 			      E1000_EEE_ADV_1000_SUPPORTED);
31397609433eSJack F Vogel 		ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
31407609433eSJack F Vogel 						E1000_EEE_ADV_DEV_I354,
31417609433eSJack F Vogel 						phy_data);
31427609433eSJack F Vogel 	}
31437609433eSJack F Vogel 
31447609433eSJack F Vogel out:
31457609433eSJack F Vogel 	return ret_val;
31467609433eSJack F Vogel }
31477609433eSJack F Vogel 
31487609433eSJack F Vogel /**
31497609433eSJack F Vogel  *  e1000_get_eee_status_i354 - Get EEE status
31507609433eSJack F Vogel  *  @hw: pointer to the HW structure
31517609433eSJack F Vogel  *  @status: EEE status
31527609433eSJack F Vogel  *
31537609433eSJack F Vogel  *  Get EEE status by guessing based on whether Tx or Rx LPI indications have
31547609433eSJack F Vogel  *  been received.
31557609433eSJack F Vogel  **/
31567609433eSJack F Vogel s32 e1000_get_eee_status_i354(struct e1000_hw *hw, bool *status)
31577609433eSJack F Vogel {
31587609433eSJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
31597609433eSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
31607609433eSJack F Vogel 	u16 phy_data;
31617609433eSJack F Vogel 
31627609433eSJack F Vogel 	DEBUGFUNC("e1000_get_eee_status_i354");
31637609433eSJack F Vogel 
31647609433eSJack F Vogel 	/* Check if EEE is supported on this device. */
31657609433eSJack F Vogel 	if ((hw->phy.media_type != e1000_media_type_copper) ||
31667609433eSJack F Vogel 	    ((phy->id != M88E1543_E_PHY_ID) &&
31677609433eSJack F Vogel 	    (phy->id != M88E1512_E_PHY_ID)))
31687609433eSJack F Vogel 		goto out;
31697609433eSJack F Vogel 
31707609433eSJack F Vogel 	ret_val = e1000_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354,
31717609433eSJack F Vogel 				       E1000_PCS_STATUS_DEV_I354,
31727609433eSJack F Vogel 				       &phy_data);
31737609433eSJack F Vogel 	if (ret_val)
31747609433eSJack F Vogel 		goto out;
31757609433eSJack F Vogel 
31767609433eSJack F Vogel 	*status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD |
31777609433eSJack F Vogel 			      E1000_PCS_STATUS_RX_LPI_RCVD) ? TRUE : FALSE;
31787609433eSJack F Vogel 
31797609433eSJack F Vogel out:
31807609433eSJack F Vogel 	return ret_val;
31817609433eSJack F Vogel }
31827609433eSJack F Vogel 
31834dab5c37SJack F Vogel /* Due to a hw errata, if the host tries to  configure the VFTA register
31844dab5c37SJack F Vogel  * while performing queries from the BMC or DMA, then the VFTA in some
31854dab5c37SJack F Vogel  * cases won't be written.
31864dab5c37SJack F Vogel  */
31874dab5c37SJack F Vogel 
31884dab5c37SJack F Vogel /**
31894dab5c37SJack F Vogel  *  e1000_clear_vfta_i350 - Clear VLAN filter table
31904dab5c37SJack F Vogel  *  @hw: pointer to the HW structure
31914dab5c37SJack F Vogel  *
31924dab5c37SJack F Vogel  *  Clears the register array which contains the VLAN filter table by
31934dab5c37SJack F Vogel  *  setting all the values to 0.
31944dab5c37SJack F Vogel  **/
31954dab5c37SJack F Vogel void e1000_clear_vfta_i350(struct e1000_hw *hw)
31964dab5c37SJack F Vogel {
31974dab5c37SJack F Vogel 	u32 offset;
31984dab5c37SJack F Vogel 	int i;
31994dab5c37SJack F Vogel 
32004dab5c37SJack F Vogel 	DEBUGFUNC("e1000_clear_vfta_350");
32014dab5c37SJack F Vogel 
32024dab5c37SJack F Vogel 	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
32034dab5c37SJack F Vogel 		for (i = 0; i < 10; i++)
32044dab5c37SJack F Vogel 			E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
32054dab5c37SJack F Vogel 
32064dab5c37SJack F Vogel 		E1000_WRITE_FLUSH(hw);
32074dab5c37SJack F Vogel 	}
32084dab5c37SJack F Vogel }
32094dab5c37SJack F Vogel 
32104dab5c37SJack F Vogel /**
32114dab5c37SJack F Vogel  *  e1000_write_vfta_i350 - Write value to VLAN filter table
32124dab5c37SJack F Vogel  *  @hw: pointer to the HW structure
32134dab5c37SJack F Vogel  *  @offset: register offset in VLAN filter table
32144dab5c37SJack F Vogel  *  @value: register value written to VLAN filter table
32154dab5c37SJack F Vogel  *
32164dab5c37SJack F Vogel  *  Writes value at the given offset in the register array which stores
32174dab5c37SJack F Vogel  *  the VLAN filter table.
32184dab5c37SJack F Vogel  **/
32194dab5c37SJack F Vogel void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
32204dab5c37SJack F Vogel {
32214dab5c37SJack F Vogel 	int i;
32224dab5c37SJack F Vogel 
32234dab5c37SJack F Vogel 	DEBUGFUNC("e1000_write_vfta_350");
32244dab5c37SJack F Vogel 
32254dab5c37SJack F Vogel 	for (i = 0; i < 10; i++)
32264dab5c37SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
32274dab5c37SJack F Vogel 
32284dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
32294dab5c37SJack F Vogel }
32304dab5c37SJack F Vogel 
32314dab5c37SJack F Vogel 
32324dab5c37SJack F Vogel /**
32334dab5c37SJack F Vogel  *  e1000_set_i2c_bb - Enable I2C bit-bang
32344dab5c37SJack F Vogel  *  @hw: pointer to the HW structure
32354dab5c37SJack F Vogel  *
32364dab5c37SJack F Vogel  *  Enable I2C bit-bang interface
32374dab5c37SJack F Vogel  *
32384dab5c37SJack F Vogel  **/
32394dab5c37SJack F Vogel s32 e1000_set_i2c_bb(struct e1000_hw *hw)
32404dab5c37SJack F Vogel {
32414dab5c37SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
32424dab5c37SJack F Vogel 	u32 ctrl_ext, i2cparams;
32434dab5c37SJack F Vogel 
32444dab5c37SJack F Vogel 	DEBUGFUNC("e1000_set_i2c_bb");
32454dab5c37SJack F Vogel 
32464dab5c37SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
32474dab5c37SJack F Vogel 	ctrl_ext |= E1000_CTRL_I2C_ENA;
32484dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
32494dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
32504dab5c37SJack F Vogel 
32514dab5c37SJack F Vogel 	i2cparams = E1000_READ_REG(hw, E1000_I2CPARAMS);
32524dab5c37SJack F Vogel 	i2cparams |= E1000_I2CBB_EN;
32534dab5c37SJack F Vogel 	i2cparams |= E1000_I2C_DATA_OE_N;
32544dab5c37SJack F Vogel 	i2cparams |= E1000_I2C_CLK_OE_N;
32554dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cparams);
32564dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
32574dab5c37SJack F Vogel 
32584dab5c37SJack F Vogel 	return ret_val;
32594dab5c37SJack F Vogel }
32604dab5c37SJack F Vogel 
32614dab5c37SJack F Vogel /**
32624dab5c37SJack F Vogel  *  e1000_read_i2c_byte_generic - Reads 8 bit word over I2C
32634dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
32644dab5c37SJack F Vogel  *  @byte_offset: byte offset to read
3265ab5d0362SJack F Vogel  *  @dev_addr: device address
32664dab5c37SJack F Vogel  *  @data: value read
32674dab5c37SJack F Vogel  *
32684dab5c37SJack F Vogel  *  Performs byte read operation over I2C interface at
32694dab5c37SJack F Vogel  *  a specified device address.
32704dab5c37SJack F Vogel  **/
32714dab5c37SJack F Vogel s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
32724dab5c37SJack F Vogel 				u8 dev_addr, u8 *data)
32734dab5c37SJack F Vogel {
32744dab5c37SJack F Vogel 	s32 status = E1000_SUCCESS;
32754dab5c37SJack F Vogel 	u32 max_retry = 10;
32764dab5c37SJack F Vogel 	u32 retry = 1;
32774dab5c37SJack F Vogel 	u16 swfw_mask = 0;
32784dab5c37SJack F Vogel 
3279ab5d0362SJack F Vogel 	bool nack = TRUE;
32804dab5c37SJack F Vogel 
32814dab5c37SJack F Vogel 	DEBUGFUNC("e1000_read_i2c_byte_generic");
32824dab5c37SJack F Vogel 
32834dab5c37SJack F Vogel 	swfw_mask = E1000_SWFW_PHY0_SM;
32844dab5c37SJack F Vogel 
32854dab5c37SJack F Vogel 	do {
3286ab5d0362SJack F Vogel 		if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)
32874dab5c37SJack F Vogel 		    != E1000_SUCCESS) {
32884dab5c37SJack F Vogel 			status = E1000_ERR_SWFW_SYNC;
32894dab5c37SJack F Vogel 			goto read_byte_out;
32904dab5c37SJack F Vogel 		}
32914dab5c37SJack F Vogel 
32924dab5c37SJack F Vogel 		e1000_i2c_start(hw);
32934dab5c37SJack F Vogel 
32944dab5c37SJack F Vogel 		/* Device Address and write indication */
32954dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, dev_addr);
32964dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
32974dab5c37SJack F Vogel 			goto fail;
32984dab5c37SJack F Vogel 
32994dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
33004dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33014dab5c37SJack F Vogel 			goto fail;
33024dab5c37SJack F Vogel 
33034dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, byte_offset);
33044dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33054dab5c37SJack F Vogel 			goto fail;
33064dab5c37SJack F Vogel 
33074dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
33084dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33094dab5c37SJack F Vogel 			goto fail;
33104dab5c37SJack F Vogel 
33114dab5c37SJack F Vogel 		e1000_i2c_start(hw);
33124dab5c37SJack F Vogel 
33134dab5c37SJack F Vogel 		/* Device Address and read indication */
33144dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, (dev_addr | 0x1));
33154dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33164dab5c37SJack F Vogel 			goto fail;
33174dab5c37SJack F Vogel 
33184dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
33194dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33204dab5c37SJack F Vogel 			goto fail;
33214dab5c37SJack F Vogel 
33224dab5c37SJack F Vogel 		status = e1000_clock_in_i2c_byte(hw, data);
33234dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33244dab5c37SJack F Vogel 			goto fail;
33254dab5c37SJack F Vogel 
33264dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_bit(hw, nack);
33274dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33284dab5c37SJack F Vogel 			goto fail;
33294dab5c37SJack F Vogel 
33304dab5c37SJack F Vogel 		e1000_i2c_stop(hw);
33314dab5c37SJack F Vogel 		break;
33324dab5c37SJack F Vogel 
33334dab5c37SJack F Vogel fail:
3334ab5d0362SJack F Vogel 		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
33354dab5c37SJack F Vogel 		msec_delay(100);
33364dab5c37SJack F Vogel 		e1000_i2c_bus_clear(hw);
33374dab5c37SJack F Vogel 		retry++;
33384dab5c37SJack F Vogel 		if (retry < max_retry)
33394dab5c37SJack F Vogel 			DEBUGOUT("I2C byte read error - Retrying.\n");
33404dab5c37SJack F Vogel 		else
33414dab5c37SJack F Vogel 			DEBUGOUT("I2C byte read error.\n");
33424dab5c37SJack F Vogel 
33434dab5c37SJack F Vogel 	} while (retry < max_retry);
33444dab5c37SJack F Vogel 
3345ab5d0362SJack F Vogel 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
33464dab5c37SJack F Vogel 
33474dab5c37SJack F Vogel read_byte_out:
33484dab5c37SJack F Vogel 
33494dab5c37SJack F Vogel 	return status;
33504dab5c37SJack F Vogel }
33514dab5c37SJack F Vogel 
33524dab5c37SJack F Vogel /**
33534dab5c37SJack F Vogel  *  e1000_write_i2c_byte_generic - Writes 8 bit word over I2C
33544dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
33554dab5c37SJack F Vogel  *  @byte_offset: byte offset to write
3356ab5d0362SJack F Vogel  *  @dev_addr: device address
33574dab5c37SJack F Vogel  *  @data: value to write
33584dab5c37SJack F Vogel  *
33594dab5c37SJack F Vogel  *  Performs byte write operation over I2C interface at
33604dab5c37SJack F Vogel  *  a specified device address.
33614dab5c37SJack F Vogel  **/
33624dab5c37SJack F Vogel s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
33634dab5c37SJack F Vogel 				 u8 dev_addr, u8 data)
33644dab5c37SJack F Vogel {
33654dab5c37SJack F Vogel 	s32 status = E1000_SUCCESS;
33664dab5c37SJack F Vogel 	u32 max_retry = 1;
33674dab5c37SJack F Vogel 	u32 retry = 0;
33684dab5c37SJack F Vogel 	u16 swfw_mask = 0;
33694dab5c37SJack F Vogel 
33704dab5c37SJack F Vogel 	DEBUGFUNC("e1000_write_i2c_byte_generic");
33714dab5c37SJack F Vogel 
33724dab5c37SJack F Vogel 	swfw_mask = E1000_SWFW_PHY0_SM;
33734dab5c37SJack F Vogel 
3374ab5d0362SJack F Vogel 	if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) {
33754dab5c37SJack F Vogel 		status = E1000_ERR_SWFW_SYNC;
33764dab5c37SJack F Vogel 		goto write_byte_out;
33774dab5c37SJack F Vogel 	}
33784dab5c37SJack F Vogel 
33794dab5c37SJack F Vogel 	do {
33804dab5c37SJack F Vogel 		e1000_i2c_start(hw);
33814dab5c37SJack F Vogel 
33824dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, dev_addr);
33834dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33844dab5c37SJack F Vogel 			goto fail;
33854dab5c37SJack F Vogel 
33864dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
33874dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33884dab5c37SJack F Vogel 			goto fail;
33894dab5c37SJack F Vogel 
33904dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, byte_offset);
33914dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33924dab5c37SJack F Vogel 			goto fail;
33934dab5c37SJack F Vogel 
33944dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
33954dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
33964dab5c37SJack F Vogel 			goto fail;
33974dab5c37SJack F Vogel 
33984dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, data);
33994dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
34004dab5c37SJack F Vogel 			goto fail;
34014dab5c37SJack F Vogel 
34024dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
34034dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
34044dab5c37SJack F Vogel 			goto fail;
34054dab5c37SJack F Vogel 
34064dab5c37SJack F Vogel 		e1000_i2c_stop(hw);
34074dab5c37SJack F Vogel 		break;
34084dab5c37SJack F Vogel 
34094dab5c37SJack F Vogel fail:
34104dab5c37SJack F Vogel 		e1000_i2c_bus_clear(hw);
34114dab5c37SJack F Vogel 		retry++;
34124dab5c37SJack F Vogel 		if (retry < max_retry)
34134dab5c37SJack F Vogel 			DEBUGOUT("I2C byte write error - Retrying.\n");
34144dab5c37SJack F Vogel 		else
34154dab5c37SJack F Vogel 			DEBUGOUT("I2C byte write error.\n");
34164dab5c37SJack F Vogel 	} while (retry < max_retry);
34174dab5c37SJack F Vogel 
3418ab5d0362SJack F Vogel 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
34194dab5c37SJack F Vogel 
34204dab5c37SJack F Vogel write_byte_out:
34214dab5c37SJack F Vogel 
34224dab5c37SJack F Vogel 	return status;
34234dab5c37SJack F Vogel }
34244dab5c37SJack F Vogel 
34254dab5c37SJack F Vogel /**
34264dab5c37SJack F Vogel  *  e1000_i2c_start - Sets I2C start condition
34274dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
34284dab5c37SJack F Vogel  *
34294dab5c37SJack F Vogel  *  Sets I2C start condition (High -> Low on SDA while SCL is High)
34304dab5c37SJack F Vogel  **/
34314dab5c37SJack F Vogel static void e1000_i2c_start(struct e1000_hw *hw)
34324dab5c37SJack F Vogel {
34334dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
34344dab5c37SJack F Vogel 
34354dab5c37SJack F Vogel 	DEBUGFUNC("e1000_i2c_start");
34364dab5c37SJack F Vogel 
34374dab5c37SJack F Vogel 	/* Start condition must begin with data and clock high */
34384dab5c37SJack F Vogel 	e1000_set_i2c_data(hw, &i2cctl, 1);
34394dab5c37SJack F Vogel 	e1000_raise_i2c_clk(hw, &i2cctl);
34404dab5c37SJack F Vogel 
34414dab5c37SJack F Vogel 	/* Setup time for start condition (4.7us) */
34424dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_SU_STA);
34434dab5c37SJack F Vogel 
34444dab5c37SJack F Vogel 	e1000_set_i2c_data(hw, &i2cctl, 0);
34454dab5c37SJack F Vogel 
34464dab5c37SJack F Vogel 	/* Hold time for start condition (4us) */
34474dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_HD_STA);
34484dab5c37SJack F Vogel 
34494dab5c37SJack F Vogel 	e1000_lower_i2c_clk(hw, &i2cctl);
34504dab5c37SJack F Vogel 
34514dab5c37SJack F Vogel 	/* Minimum low period of clock is 4.7 us */
34524dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_LOW);
34534dab5c37SJack F Vogel 
34544dab5c37SJack F Vogel }
34554dab5c37SJack F Vogel 
34564dab5c37SJack F Vogel /**
34574dab5c37SJack F Vogel  *  e1000_i2c_stop - Sets I2C stop condition
34584dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
34594dab5c37SJack F Vogel  *
34604dab5c37SJack F Vogel  *  Sets I2C stop condition (Low -> High on SDA while SCL is High)
34614dab5c37SJack F Vogel  **/
34624dab5c37SJack F Vogel static void e1000_i2c_stop(struct e1000_hw *hw)
34634dab5c37SJack F Vogel {
34644dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
34654dab5c37SJack F Vogel 
34664dab5c37SJack F Vogel 	DEBUGFUNC("e1000_i2c_stop");
34674dab5c37SJack F Vogel 
34684dab5c37SJack F Vogel 	/* Stop condition must begin with data low and clock high */
34694dab5c37SJack F Vogel 	e1000_set_i2c_data(hw, &i2cctl, 0);
34704dab5c37SJack F Vogel 	e1000_raise_i2c_clk(hw, &i2cctl);
34714dab5c37SJack F Vogel 
34724dab5c37SJack F Vogel 	/* Setup time for stop condition (4us) */
34734dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_SU_STO);
34744dab5c37SJack F Vogel 
34754dab5c37SJack F Vogel 	e1000_set_i2c_data(hw, &i2cctl, 1);
34764dab5c37SJack F Vogel 
34774dab5c37SJack F Vogel 	/* bus free time between stop and start (4.7us)*/
34784dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_BUF);
34794dab5c37SJack F Vogel }
34804dab5c37SJack F Vogel 
34814dab5c37SJack F Vogel /**
34824dab5c37SJack F Vogel  *  e1000_clock_in_i2c_byte - Clocks in one byte via I2C
34834dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
34844dab5c37SJack F Vogel  *  @data: data byte to clock in
34854dab5c37SJack F Vogel  *
34864dab5c37SJack F Vogel  *  Clocks in one byte data via I2C data/clock
34874dab5c37SJack F Vogel  **/
34884dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data)
34894dab5c37SJack F Vogel {
34904dab5c37SJack F Vogel 	s32 i;
34914dab5c37SJack F Vogel 	bool bit = 0;
34924dab5c37SJack F Vogel 
34934dab5c37SJack F Vogel 	DEBUGFUNC("e1000_clock_in_i2c_byte");
34944dab5c37SJack F Vogel 
34954dab5c37SJack F Vogel 	*data = 0;
34964dab5c37SJack F Vogel 	for (i = 7; i >= 0; i--) {
34974dab5c37SJack F Vogel 		e1000_clock_in_i2c_bit(hw, &bit);
34984dab5c37SJack F Vogel 		*data |= bit << i;
34994dab5c37SJack F Vogel 	}
35004dab5c37SJack F Vogel 
35014dab5c37SJack F Vogel 	return E1000_SUCCESS;
35024dab5c37SJack F Vogel }
35034dab5c37SJack F Vogel 
35044dab5c37SJack F Vogel /**
35054dab5c37SJack F Vogel  *  e1000_clock_out_i2c_byte - Clocks out one byte via I2C
35064dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
35074dab5c37SJack F Vogel  *  @data: data byte clocked out
35084dab5c37SJack F Vogel  *
35094dab5c37SJack F Vogel  *  Clocks out one byte data via I2C data/clock
35104dab5c37SJack F Vogel  **/
35114dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data)
35124dab5c37SJack F Vogel {
35134dab5c37SJack F Vogel 	s32 status = E1000_SUCCESS;
35144dab5c37SJack F Vogel 	s32 i;
35154dab5c37SJack F Vogel 	u32 i2cctl;
35164dab5c37SJack F Vogel 	bool bit = 0;
35174dab5c37SJack F Vogel 
35184dab5c37SJack F Vogel 	DEBUGFUNC("e1000_clock_out_i2c_byte");
35194dab5c37SJack F Vogel 
35204dab5c37SJack F Vogel 	for (i = 7; i >= 0; i--) {
35214dab5c37SJack F Vogel 		bit = (data >> i) & 0x1;
35224dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_bit(hw, bit);
35234dab5c37SJack F Vogel 
35244dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
35254dab5c37SJack F Vogel 			break;
35264dab5c37SJack F Vogel 	}
35274dab5c37SJack F Vogel 
35284dab5c37SJack F Vogel 	/* Release SDA line (set high) */
35294dab5c37SJack F Vogel 	i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
35304dab5c37SJack F Vogel 
35314dab5c37SJack F Vogel 	i2cctl |= E1000_I2C_DATA_OE_N;
35324dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl);
35334dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
35344dab5c37SJack F Vogel 
35354dab5c37SJack F Vogel 	return status;
35364dab5c37SJack F Vogel }
35374dab5c37SJack F Vogel 
35384dab5c37SJack F Vogel /**
35394dab5c37SJack F Vogel  *  e1000_get_i2c_ack - Polls for I2C ACK
35404dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
35414dab5c37SJack F Vogel  *
35424dab5c37SJack F Vogel  *  Clocks in/out one bit via I2C data/clock
35434dab5c37SJack F Vogel  **/
35444dab5c37SJack F Vogel static s32 e1000_get_i2c_ack(struct e1000_hw *hw)
35454dab5c37SJack F Vogel {
35464dab5c37SJack F Vogel 	s32 status = E1000_SUCCESS;
35474dab5c37SJack F Vogel 	u32 i = 0;
35484dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
35494dab5c37SJack F Vogel 	u32 timeout = 10;
3550ab5d0362SJack F Vogel 	bool ack = TRUE;
35514dab5c37SJack F Vogel 
35524dab5c37SJack F Vogel 	DEBUGFUNC("e1000_get_i2c_ack");
35534dab5c37SJack F Vogel 
35544dab5c37SJack F Vogel 	e1000_raise_i2c_clk(hw, &i2cctl);
35554dab5c37SJack F Vogel 
35564dab5c37SJack F Vogel 	/* Minimum high period of clock is 4us */
35574dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_HIGH);
35584dab5c37SJack F Vogel 
35594dab5c37SJack F Vogel 	/* Wait until SCL returns high */
35604dab5c37SJack F Vogel 	for (i = 0; i < timeout; i++) {
35614dab5c37SJack F Vogel 		usec_delay(1);
35624dab5c37SJack F Vogel 		i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
35634dab5c37SJack F Vogel 		if (i2cctl & E1000_I2C_CLK_IN)
35644dab5c37SJack F Vogel 			break;
35654dab5c37SJack F Vogel 	}
35664dab5c37SJack F Vogel 	if (!(i2cctl & E1000_I2C_CLK_IN))
35674dab5c37SJack F Vogel 		return E1000_ERR_I2C;
35684dab5c37SJack F Vogel 
35694dab5c37SJack F Vogel 	ack = e1000_get_i2c_data(&i2cctl);
3570ab5d0362SJack F Vogel 	if (ack) {
35714dab5c37SJack F Vogel 		DEBUGOUT("I2C ack was not received.\n");
35724dab5c37SJack F Vogel 		status = E1000_ERR_I2C;
35734dab5c37SJack F Vogel 	}
35744dab5c37SJack F Vogel 
35754dab5c37SJack F Vogel 	e1000_lower_i2c_clk(hw, &i2cctl);
35764dab5c37SJack F Vogel 
35774dab5c37SJack F Vogel 	/* Minimum low period of clock is 4.7 us */
35784dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_LOW);
35794dab5c37SJack F Vogel 
35804dab5c37SJack F Vogel 	return status;
35814dab5c37SJack F Vogel }
35824dab5c37SJack F Vogel 
35834dab5c37SJack F Vogel /**
35844dab5c37SJack F Vogel  *  e1000_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
35854dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
35864dab5c37SJack F Vogel  *  @data: read data value
35874dab5c37SJack F Vogel  *
35884dab5c37SJack F Vogel  *  Clocks in one bit via I2C data/clock
35894dab5c37SJack F Vogel  **/
35904dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data)
35914dab5c37SJack F Vogel {
35924dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
35934dab5c37SJack F Vogel 
35944dab5c37SJack F Vogel 	DEBUGFUNC("e1000_clock_in_i2c_bit");
35954dab5c37SJack F Vogel 
35964dab5c37SJack F Vogel 	e1000_raise_i2c_clk(hw, &i2cctl);
35974dab5c37SJack F Vogel 
35984dab5c37SJack F Vogel 	/* Minimum high period of clock is 4us */
35994dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_HIGH);
36004dab5c37SJack F Vogel 
36014dab5c37SJack F Vogel 	i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
36024dab5c37SJack F Vogel 	*data = e1000_get_i2c_data(&i2cctl);
36034dab5c37SJack F Vogel 
36044dab5c37SJack F Vogel 	e1000_lower_i2c_clk(hw, &i2cctl);
36054dab5c37SJack F Vogel 
36064dab5c37SJack F Vogel 	/* Minimum low period of clock is 4.7 us */
36074dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_LOW);
36084dab5c37SJack F Vogel 
36094dab5c37SJack F Vogel 	return E1000_SUCCESS;
36104dab5c37SJack F Vogel }
36114dab5c37SJack F Vogel 
36124dab5c37SJack F Vogel /**
36134dab5c37SJack F Vogel  *  e1000_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
36144dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
36154dab5c37SJack F Vogel  *  @data: data value to write
36164dab5c37SJack F Vogel  *
36174dab5c37SJack F Vogel  *  Clocks out one bit via I2C data/clock
36184dab5c37SJack F Vogel  **/
36194dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data)
36204dab5c37SJack F Vogel {
36214dab5c37SJack F Vogel 	s32 status;
36224dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
36234dab5c37SJack F Vogel 
36244dab5c37SJack F Vogel 	DEBUGFUNC("e1000_clock_out_i2c_bit");
36254dab5c37SJack F Vogel 
36264dab5c37SJack F Vogel 	status = e1000_set_i2c_data(hw, &i2cctl, data);
36274dab5c37SJack F Vogel 	if (status == E1000_SUCCESS) {
36284dab5c37SJack F Vogel 		e1000_raise_i2c_clk(hw, &i2cctl);
36294dab5c37SJack F Vogel 
36304dab5c37SJack F Vogel 		/* Minimum high period of clock is 4us */
36314dab5c37SJack F Vogel 		usec_delay(E1000_I2C_T_HIGH);
36324dab5c37SJack F Vogel 
36334dab5c37SJack F Vogel 		e1000_lower_i2c_clk(hw, &i2cctl);
36344dab5c37SJack F Vogel 
36354dab5c37SJack F Vogel 		/* Minimum low period of clock is 4.7 us.
36364dab5c37SJack F Vogel 		 * This also takes care of the data hold time.
36374dab5c37SJack F Vogel 		 */
36384dab5c37SJack F Vogel 		usec_delay(E1000_I2C_T_LOW);
36394dab5c37SJack F Vogel 	} else {
36404dab5c37SJack F Vogel 		status = E1000_ERR_I2C;
36414dab5c37SJack F Vogel 		DEBUGOUT1("I2C data was not set to %X\n", data);
36424dab5c37SJack F Vogel 	}
36434dab5c37SJack F Vogel 
36444dab5c37SJack F Vogel 	return status;
36454dab5c37SJack F Vogel }
36464dab5c37SJack F Vogel /**
36474dab5c37SJack F Vogel  *  e1000_raise_i2c_clk - Raises the I2C SCL clock
36484dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
36494dab5c37SJack F Vogel  *  @i2cctl: Current value of I2CCTL register
36504dab5c37SJack F Vogel  *
36514dab5c37SJack F Vogel  *  Raises the I2C clock line '0'->'1'
36524dab5c37SJack F Vogel  **/
36534dab5c37SJack F Vogel static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
36544dab5c37SJack F Vogel {
36554dab5c37SJack F Vogel 	DEBUGFUNC("e1000_raise_i2c_clk");
36564dab5c37SJack F Vogel 
36574dab5c37SJack F Vogel 	*i2cctl |= E1000_I2C_CLK_OUT;
36584dab5c37SJack F Vogel 	*i2cctl &= ~E1000_I2C_CLK_OE_N;
36594dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
36604dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
36614dab5c37SJack F Vogel 
36624dab5c37SJack F Vogel 	/* SCL rise time (1000ns) */
36634dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_RISE);
36644dab5c37SJack F Vogel }
36654dab5c37SJack F Vogel 
36664dab5c37SJack F Vogel /**
36674dab5c37SJack F Vogel  *  e1000_lower_i2c_clk - Lowers the I2C SCL clock
36684dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
36694dab5c37SJack F Vogel  *  @i2cctl: Current value of I2CCTL register
36704dab5c37SJack F Vogel  *
36714dab5c37SJack F Vogel  *  Lowers the I2C clock line '1'->'0'
36724dab5c37SJack F Vogel  **/
36734dab5c37SJack F Vogel static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
36744dab5c37SJack F Vogel {
36754dab5c37SJack F Vogel 
36764dab5c37SJack F Vogel 	DEBUGFUNC("e1000_lower_i2c_clk");
36774dab5c37SJack F Vogel 
36784dab5c37SJack F Vogel 	*i2cctl &= ~E1000_I2C_CLK_OUT;
36794dab5c37SJack F Vogel 	*i2cctl &= ~E1000_I2C_CLK_OE_N;
36804dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
36814dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
36824dab5c37SJack F Vogel 
36834dab5c37SJack F Vogel 	/* SCL fall time (300ns) */
36844dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_FALL);
36854dab5c37SJack F Vogel }
36864dab5c37SJack F Vogel 
36874dab5c37SJack F Vogel /**
36884dab5c37SJack F Vogel  *  e1000_set_i2c_data - Sets the I2C data bit
36894dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
36904dab5c37SJack F Vogel  *  @i2cctl: Current value of I2CCTL register
36914dab5c37SJack F Vogel  *  @data: I2C data value (0 or 1) to set
36924dab5c37SJack F Vogel  *
36934dab5c37SJack F Vogel  *  Sets the I2C data bit
36944dab5c37SJack F Vogel  **/
36954dab5c37SJack F Vogel static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data)
36964dab5c37SJack F Vogel {
36974dab5c37SJack F Vogel 	s32 status = E1000_SUCCESS;
36984dab5c37SJack F Vogel 
36994dab5c37SJack F Vogel 	DEBUGFUNC("e1000_set_i2c_data");
37004dab5c37SJack F Vogel 
37014dab5c37SJack F Vogel 	if (data)
37024dab5c37SJack F Vogel 		*i2cctl |= E1000_I2C_DATA_OUT;
37034dab5c37SJack F Vogel 	else
37044dab5c37SJack F Vogel 		*i2cctl &= ~E1000_I2C_DATA_OUT;
37054dab5c37SJack F Vogel 
37064dab5c37SJack F Vogel 	*i2cctl &= ~E1000_I2C_DATA_OE_N;
37074dab5c37SJack F Vogel 	*i2cctl |= E1000_I2C_CLK_OE_N;
37084dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
37094dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
37104dab5c37SJack F Vogel 
37114dab5c37SJack F Vogel 	/* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
37124dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA);
37134dab5c37SJack F Vogel 
37144dab5c37SJack F Vogel 	*i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
37154dab5c37SJack F Vogel 	if (data != e1000_get_i2c_data(i2cctl)) {
37164dab5c37SJack F Vogel 		status = E1000_ERR_I2C;
37174dab5c37SJack F Vogel 		DEBUGOUT1("Error - I2C data was not set to %X.\n", data);
37184dab5c37SJack F Vogel 	}
37194dab5c37SJack F Vogel 
37204dab5c37SJack F Vogel 	return status;
37214dab5c37SJack F Vogel }
37224dab5c37SJack F Vogel 
37234dab5c37SJack F Vogel /**
37244dab5c37SJack F Vogel  *  e1000_get_i2c_data - Reads the I2C SDA data bit
37254dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
37264dab5c37SJack F Vogel  *  @i2cctl: Current value of I2CCTL register
37274dab5c37SJack F Vogel  *
37284dab5c37SJack F Vogel  *  Returns the I2C data bit value
37294dab5c37SJack F Vogel  **/
37304dab5c37SJack F Vogel static bool e1000_get_i2c_data(u32 *i2cctl)
37314dab5c37SJack F Vogel {
37324dab5c37SJack F Vogel 	bool data;
37334dab5c37SJack F Vogel 
37344dab5c37SJack F Vogel 	DEBUGFUNC("e1000_get_i2c_data");
37354dab5c37SJack F Vogel 
37364dab5c37SJack F Vogel 	if (*i2cctl & E1000_I2C_DATA_IN)
37374dab5c37SJack F Vogel 		data = 1;
37384dab5c37SJack F Vogel 	else
37394dab5c37SJack F Vogel 		data = 0;
37404dab5c37SJack F Vogel 
37414dab5c37SJack F Vogel 	return data;
37424dab5c37SJack F Vogel }
37434dab5c37SJack F Vogel 
37444dab5c37SJack F Vogel /**
37454dab5c37SJack F Vogel  *  e1000_i2c_bus_clear - Clears the I2C bus
37464dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
37474dab5c37SJack F Vogel  *
37484dab5c37SJack F Vogel  *  Clears the I2C bus by sending nine clock pulses.
37494dab5c37SJack F Vogel  *  Used when data line is stuck low.
37504dab5c37SJack F Vogel  **/
37514dab5c37SJack F Vogel void e1000_i2c_bus_clear(struct e1000_hw *hw)
37524dab5c37SJack F Vogel {
37534dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
37544dab5c37SJack F Vogel 	u32 i;
37554dab5c37SJack F Vogel 
37564dab5c37SJack F Vogel 	DEBUGFUNC("e1000_i2c_bus_clear");
37574dab5c37SJack F Vogel 
37584dab5c37SJack F Vogel 	e1000_i2c_start(hw);
37594dab5c37SJack F Vogel 
37604dab5c37SJack F Vogel 	e1000_set_i2c_data(hw, &i2cctl, 1);
37614dab5c37SJack F Vogel 
37624dab5c37SJack F Vogel 	for (i = 0; i < 9; i++) {
37634dab5c37SJack F Vogel 		e1000_raise_i2c_clk(hw, &i2cctl);
37644dab5c37SJack F Vogel 
37654dab5c37SJack F Vogel 		/* Min high period of clock is 4us */
37664dab5c37SJack F Vogel 		usec_delay(E1000_I2C_T_HIGH);
37674dab5c37SJack F Vogel 
37684dab5c37SJack F Vogel 		e1000_lower_i2c_clk(hw, &i2cctl);
37694dab5c37SJack F Vogel 
37704dab5c37SJack F Vogel 		/* Min low period of clock is 4.7us*/
37714dab5c37SJack F Vogel 		usec_delay(E1000_I2C_T_LOW);
37724dab5c37SJack F Vogel 	}
37734dab5c37SJack F Vogel 
37744dab5c37SJack F Vogel 	e1000_i2c_start(hw);
37754dab5c37SJack F Vogel 
37764dab5c37SJack F Vogel 	/* Put the i2c bus back to default state */
37774dab5c37SJack F Vogel 	e1000_i2c_stop(hw);
37784dab5c37SJack F Vogel }
37794dab5c37SJack F Vogel 
3780