xref: /freebsd/sys/dev/e1000/e1000_82575.c (revision ab5d036272b634fcf04a3ef30be1fecd86435f7f)
18cfa0ad2SJack F Vogel /******************************************************************************
28cfa0ad2SJack F Vogel 
3*ab5d0362SJack F Vogel   Copyright (c) 2001-2012, 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
41*ab5d0362SJack F Vogel  * 82580 Gigabit Network Connection
42*ab5d0362SJack F Vogel  * I350 Gigabit Network Connection
438cfa0ad2SJack F Vogel  */
448cfa0ad2SJack F Vogel 
458cfa0ad2SJack F Vogel #include "e1000_api.h"
46*ab5d0362SJack 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);
558cfa0ad2SJack F Vogel static s32  e1000_get_cfg_done_82575(struct e1000_hw *hw);
568cfa0ad2SJack F Vogel static s32  e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
578cfa0ad2SJack F Vogel 					 u16 *duplex);
588cfa0ad2SJack F Vogel static s32  e1000_init_hw_82575(struct e1000_hw *hw);
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 \
1224edd8523SJack F Vogel 	(sizeof(e1000_82580_rxpbs_table)/sizeof(u16))
1234edd8523SJack F Vogel 
1247d9119bdSJack F Vogel 
1257d9119bdSJack F Vogel /**
1267d9119bdSJack F Vogel  *  e1000_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO
1277d9119bdSJack F Vogel  *  @hw: pointer to the HW structure
1287d9119bdSJack F Vogel  *
1297d9119bdSJack F Vogel  *  Called to determine if the I2C pins are being used for I2C or as an
1307d9119bdSJack F Vogel  *  external MDIO interface since the two options are mutually exclusive.
1317d9119bdSJack F Vogel  **/
1327d9119bdSJack F Vogel static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw)
1337d9119bdSJack F Vogel {
1347d9119bdSJack F Vogel 	u32 reg = 0;
1357d9119bdSJack F Vogel 	bool ext_mdio = FALSE;
1367d9119bdSJack F Vogel 
1377d9119bdSJack F Vogel 	DEBUGFUNC("e1000_sgmii_uses_mdio_82575");
1387d9119bdSJack F Vogel 
1397d9119bdSJack F Vogel 	switch (hw->mac.type) {
1407d9119bdSJack F Vogel 	case e1000_82575:
1417d9119bdSJack F Vogel 	case e1000_82576:
1427d9119bdSJack F Vogel 		reg = E1000_READ_REG(hw, E1000_MDIC);
1437d9119bdSJack F Vogel 		ext_mdio = !!(reg & E1000_MDIC_DEST);
1447d9119bdSJack F Vogel 		break;
1457d9119bdSJack F Vogel 	case e1000_82580:
146f0ecc46dSJack F Vogel 	case e1000_i350:
1477d9119bdSJack F Vogel 		reg = E1000_READ_REG(hw, E1000_MDICNFG);
1487d9119bdSJack F Vogel 		ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
1497d9119bdSJack F Vogel 		break;
1507d9119bdSJack F Vogel 	default:
1517d9119bdSJack F Vogel 		break;
1527d9119bdSJack F Vogel 	}
1537d9119bdSJack F Vogel 	return ext_mdio;
1547d9119bdSJack F Vogel }
1557d9119bdSJack F Vogel 
1568cfa0ad2SJack F Vogel /**
1578cfa0ad2SJack F Vogel  *  e1000_init_phy_params_82575 - Init PHY func ptrs.
1588cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
1598cfa0ad2SJack F Vogel  **/
1608cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
1618cfa0ad2SJack F Vogel {
1628cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
1638cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
1647d9119bdSJack F Vogel 	u32 ctrl_ext;
1658cfa0ad2SJack F Vogel 
1668cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_phy_params_82575");
1678cfa0ad2SJack F Vogel 
168*ab5d0362SJack F Vogel 	phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic;
169*ab5d0362SJack F Vogel 	phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic;
170*ab5d0362SJack F Vogel 
1718cfa0ad2SJack F Vogel 	if (hw->phy.media_type != e1000_media_type_copper) {
1728cfa0ad2SJack F Vogel 		phy->type = e1000_phy_none;
1738cfa0ad2SJack F Vogel 		goto out;
1744edd8523SJack F Vogel 	}
1754edd8523SJack F Vogel 
1768cfa0ad2SJack F Vogel 	phy->ops.power_up   = e1000_power_up_phy_copper;
1778cfa0ad2SJack F Vogel 	phy->ops.power_down = e1000_power_down_phy_copper_82575;
1788cfa0ad2SJack F Vogel 
1798cfa0ad2SJack F Vogel 	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
1808cfa0ad2SJack F Vogel 	phy->reset_delay_us	= 100;
1818cfa0ad2SJack F Vogel 
1828cfa0ad2SJack F Vogel 	phy->ops.acquire	= e1000_acquire_phy_82575;
1838cfa0ad2SJack F Vogel 	phy->ops.check_reset_block = e1000_check_reset_block_generic;
1848cfa0ad2SJack F Vogel 	phy->ops.commit		= e1000_phy_sw_reset_generic;
1858cfa0ad2SJack F Vogel 	phy->ops.get_cfg_done	= e1000_get_cfg_done_82575;
1868cfa0ad2SJack F Vogel 	phy->ops.release	= e1000_release_phy_82575;
1878cfa0ad2SJack F Vogel 
1887d9119bdSJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
1897d9119bdSJack F Vogel 
1908cfa0ad2SJack F Vogel 	if (e1000_sgmii_active_82575(hw)) {
1918cfa0ad2SJack F Vogel 		phy->ops.reset = e1000_phy_hw_reset_sgmii_82575;
1927d9119bdSJack F Vogel 		ctrl_ext |= E1000_CTRL_I2C_ENA;
1937d9119bdSJack F Vogel 	} else {
1947d9119bdSJack F Vogel 		phy->ops.reset = e1000_phy_hw_reset_generic;
1957d9119bdSJack F Vogel 		ctrl_ext &= ~E1000_CTRL_I2C_ENA;
1967d9119bdSJack F Vogel 	}
1977d9119bdSJack F Vogel 
1987d9119bdSJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
1997d9119bdSJack F Vogel 	e1000_reset_mdicnfg_82580(hw);
2007d9119bdSJack F Vogel 
2017d9119bdSJack F Vogel 	if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) {
2028cfa0ad2SJack F Vogel 		phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575;
2038cfa0ad2SJack F Vogel 		phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575;
204*ab5d0362SJack F Vogel 	} else {
205*ab5d0362SJack F Vogel 		switch (hw->mac.type) {
206*ab5d0362SJack F Vogel 		case e1000_82580:
207*ab5d0362SJack F Vogel 		case e1000_i350:
2084edd8523SJack F Vogel 			phy->ops.read_reg = e1000_read_phy_reg_82580;
2094edd8523SJack F Vogel 			phy->ops.write_reg = e1000_write_phy_reg_82580;
210*ab5d0362SJack F Vogel 			break;
211*ab5d0362SJack F Vogel 		case e1000_i210:
212*ab5d0362SJack F Vogel 		case e1000_i211:
213*ab5d0362SJack F Vogel 			phy->ops.read_reg = e1000_read_phy_reg_gs40g;
214*ab5d0362SJack F Vogel 			phy->ops.write_reg = e1000_write_phy_reg_gs40g;
215*ab5d0362SJack F Vogel 			break;
216*ab5d0362SJack F Vogel 		default:
2178cfa0ad2SJack F Vogel 			phy->ops.read_reg = e1000_read_phy_reg_igp;
2188cfa0ad2SJack F Vogel 			phy->ops.write_reg = e1000_write_phy_reg_igp;
2198cfa0ad2SJack F Vogel 		}
220*ab5d0362SJack F Vogel 	}
2218cfa0ad2SJack F Vogel 
2228cfa0ad2SJack F Vogel 	/* Set phy->phy_addr and phy->id. */
2238cfa0ad2SJack F Vogel 	ret_val = e1000_get_phy_id_82575(hw);
2248cfa0ad2SJack F Vogel 
2258cfa0ad2SJack F Vogel 	/* Verify phy id and set remaining function pointers */
2268cfa0ad2SJack F Vogel 	switch (phy->id) {
227f0ecc46dSJack F Vogel 	case I347AT4_E_PHY_ID:
228f0ecc46dSJack F Vogel 	case M88E1112_E_PHY_ID:
2291fd3c44fSJack F Vogel 	case M88E1340M_E_PHY_ID:
2308cfa0ad2SJack F Vogel 	case M88E1111_I_PHY_ID:
2318cfa0ad2SJack F Vogel 		phy->type		= e1000_phy_m88;
2328cfa0ad2SJack F Vogel 		phy->ops.check_polarity	= e1000_check_polarity_m88;
2338cfa0ad2SJack F Vogel 		phy->ops.get_info	= e1000_get_phy_info_m88;
234f0ecc46dSJack F Vogel 		if (phy->id == I347AT4_E_PHY_ID ||
2351fd3c44fSJack F Vogel 		    phy->id == M88E1112_E_PHY_ID ||
2361fd3c44fSJack F Vogel 		    phy->id == M88E1340M_E_PHY_ID)
2374dab5c37SJack F Vogel 			phy->ops.get_cable_length =
2384dab5c37SJack F Vogel 					 e1000_get_cable_length_m88_gen2;
239f0ecc46dSJack F Vogel 		else
2408cfa0ad2SJack F Vogel 			phy->ops.get_cable_length = e1000_get_cable_length_m88;
2418cfa0ad2SJack F Vogel 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
2428cfa0ad2SJack F Vogel 		break;
2438cfa0ad2SJack F Vogel 	case IGP03E1000_E_PHY_ID:
2448cfa0ad2SJack F Vogel 	case IGP04E1000_E_PHY_ID:
2458cfa0ad2SJack F Vogel 		phy->type = e1000_phy_igp_3;
2468cfa0ad2SJack F Vogel 		phy->ops.check_polarity = e1000_check_polarity_igp;
2478cfa0ad2SJack F Vogel 		phy->ops.get_info = e1000_get_phy_info_igp;
2488cfa0ad2SJack F Vogel 		phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
2498cfa0ad2SJack F Vogel 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
2508cfa0ad2SJack F Vogel 		phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575;
2518cfa0ad2SJack F Vogel 		phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
2528cfa0ad2SJack F Vogel 		break;
2534edd8523SJack F Vogel 	case I82580_I_PHY_ID:
254f0ecc46dSJack F Vogel 	case I350_I_PHY_ID:
2554edd8523SJack F Vogel 		phy->type = e1000_phy_82580;
2564edd8523SJack F Vogel 		phy->ops.check_polarity = e1000_check_polarity_82577;
2574dab5c37SJack F Vogel 		phy->ops.force_speed_duplex =
2584dab5c37SJack F Vogel 					 e1000_phy_force_speed_duplex_82577;
2594edd8523SJack F Vogel 		phy->ops.get_cable_length = e1000_get_cable_length_82577;
2604edd8523SJack F Vogel 		phy->ops.get_info = e1000_get_phy_info_82577;
261f0ecc46dSJack F Vogel 		phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580;
262f0ecc46dSJack F Vogel 		phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580;
2634edd8523SJack F Vogel 		break;
264*ab5d0362SJack F Vogel 	case I210_I_PHY_ID:
265*ab5d0362SJack F Vogel 		phy->type		= e1000_phy_i210;
266*ab5d0362SJack F Vogel 		phy->ops.check_polarity	= e1000_check_polarity_m88;
267*ab5d0362SJack F Vogel 		phy->ops.get_info	= e1000_get_phy_info_m88;
268*ab5d0362SJack F Vogel 		phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2;
269*ab5d0362SJack F Vogel 		phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580;
270*ab5d0362SJack F Vogel 		phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580;
271*ab5d0362SJack F Vogel 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
272*ab5d0362SJack F Vogel 		break;
2738cfa0ad2SJack F Vogel 	default:
2748cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PHY;
2758cfa0ad2SJack F Vogel 		goto out;
2768cfa0ad2SJack F Vogel 	}
2778cfa0ad2SJack F Vogel 
2788cfa0ad2SJack F Vogel out:
2798cfa0ad2SJack F Vogel 	return ret_val;
2808cfa0ad2SJack F Vogel }
2818cfa0ad2SJack F Vogel 
2828cfa0ad2SJack F Vogel /**
2838cfa0ad2SJack F Vogel  *  e1000_init_nvm_params_82575 - Init NVM func ptrs.
2848cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
2858cfa0ad2SJack F Vogel  **/
2861fd3c44fSJack F Vogel s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
2878cfa0ad2SJack F Vogel {
2888cfa0ad2SJack F Vogel 	struct e1000_nvm_info *nvm = &hw->nvm;
2898cfa0ad2SJack F Vogel 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
2908cfa0ad2SJack F Vogel 	u16 size;
2918cfa0ad2SJack F Vogel 
2928cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_nvm_params_82575");
2938cfa0ad2SJack F Vogel 
294f0ecc46dSJack F Vogel 	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
295f0ecc46dSJack F Vogel 		     E1000_EECD_SIZE_EX_SHIFT);
296f0ecc46dSJack F Vogel 	/*
297f0ecc46dSJack F Vogel 	 * Added to a constant, "size" becomes the left-shift value
298f0ecc46dSJack F Vogel 	 * for setting word_size.
299f0ecc46dSJack F Vogel 	 */
300f0ecc46dSJack F Vogel 	size += NVM_WORD_SIZE_BASE_SHIFT;
301f0ecc46dSJack F Vogel 
3024dab5c37SJack F Vogel 	/* Just in case size is out of range, cap it to the largest
3034dab5c37SJack F Vogel 	 * EEPROM size supported
3044dab5c37SJack F Vogel 	 */
3054dab5c37SJack F Vogel 	if (size > 15)
3064dab5c37SJack F Vogel 		size = 15;
3074dab5c37SJack F Vogel 
308f0ecc46dSJack F Vogel 	nvm->word_size = 1 << size;
309*ab5d0362SJack F Vogel 	if (hw->mac.type < e1000_i210) {
3108cfa0ad2SJack F Vogel 		nvm->opcode_bits = 8;
3118cfa0ad2SJack F Vogel 		nvm->delay_usec = 1;
312*ab5d0362SJack F Vogel 
3138cfa0ad2SJack F Vogel 		switch (nvm->override) {
3148cfa0ad2SJack F Vogel 		case e1000_nvm_override_spi_large:
3158cfa0ad2SJack F Vogel 			nvm->page_size = 32;
3168cfa0ad2SJack F Vogel 			nvm->address_bits = 16;
3178cfa0ad2SJack F Vogel 			break;
3188cfa0ad2SJack F Vogel 		case e1000_nvm_override_spi_small:
3198cfa0ad2SJack F Vogel 			nvm->page_size = 8;
3208cfa0ad2SJack F Vogel 			nvm->address_bits = 8;
3218cfa0ad2SJack F Vogel 			break;
3228cfa0ad2SJack F Vogel 		default:
3238cfa0ad2SJack F Vogel 			nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
324*ab5d0362SJack F Vogel 			nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ?
325*ab5d0362SJack F Vogel 					    16 : 8;
3268cfa0ad2SJack F Vogel 			break;
3278cfa0ad2SJack F Vogel 		}
3281fd3c44fSJack F Vogel 		if (nvm->word_size == (1 << 15))
329f0ecc46dSJack F Vogel 			nvm->page_size = 128;
3308cfa0ad2SJack F Vogel 
331*ab5d0362SJack F Vogel 		nvm->type = e1000_nvm_eeprom_spi;
332*ab5d0362SJack F Vogel 	} else {
333*ab5d0362SJack F Vogel 		nvm->type = e1000_nvm_flash_hw;
334*ab5d0362SJack F Vogel 	}
3358cfa0ad2SJack F Vogel 	/* Function Pointers */
3368cfa0ad2SJack F Vogel 	nvm->ops.acquire = e1000_acquire_nvm_82575;
3378cfa0ad2SJack F Vogel 	nvm->ops.release = e1000_release_nvm_82575;
3381fd3c44fSJack F Vogel 	if (nvm->word_size < (1 << 15))
3391fd3c44fSJack F Vogel 		nvm->ops.read = e1000_read_nvm_eerd;
3401fd3c44fSJack F Vogel 	else
3411fd3c44fSJack F Vogel 		nvm->ops.read = e1000_read_nvm_spi;
3421fd3c44fSJack F Vogel 
3431fd3c44fSJack F Vogel 	nvm->ops.write = e1000_write_nvm_spi;
3441fd3c44fSJack F Vogel 	nvm->ops.validate = e1000_validate_nvm_checksum_generic;
3451fd3c44fSJack F Vogel 	nvm->ops.update = e1000_update_nvm_checksum_generic;
3468cfa0ad2SJack F Vogel 	nvm->ops.valid_led_default = e1000_valid_led_default_82575;
3471fd3c44fSJack F Vogel 
348*ab5d0362SJack F Vogel 	/* override generic family function pointers for specific descendants */
349f0ecc46dSJack F Vogel 	switch (hw->mac.type) {
350f0ecc46dSJack F Vogel 	case e1000_82580:
351f0ecc46dSJack F Vogel 		nvm->ops.validate = e1000_validate_nvm_checksum_82580;
352f0ecc46dSJack F Vogel 		nvm->ops.update = e1000_update_nvm_checksum_82580;
353f0ecc46dSJack F Vogel 		break;
354f0ecc46dSJack F Vogel 	case e1000_i350:
355f0ecc46dSJack F Vogel 		nvm->ops.validate = e1000_validate_nvm_checksum_i350;
356f0ecc46dSJack F Vogel 		nvm->ops.update = e1000_update_nvm_checksum_i350;
357f0ecc46dSJack F Vogel 		break;
358f0ecc46dSJack F Vogel 	default:
3591fd3c44fSJack F Vogel 		break;
360f0ecc46dSJack F Vogel 	}
3618cfa0ad2SJack F Vogel 
3628cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
3638cfa0ad2SJack F Vogel }
3648cfa0ad2SJack F Vogel 
3658cfa0ad2SJack F Vogel /**
3668cfa0ad2SJack F Vogel  *  e1000_init_mac_params_82575 - Init MAC func ptrs.
3678cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3688cfa0ad2SJack F Vogel  **/
3698cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
3708cfa0ad2SJack F Vogel {
3718cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
372daf9197cSJack F Vogel 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
3738cfa0ad2SJack F Vogel 
3748cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_mac_params_82575");
3758cfa0ad2SJack F Vogel 
3764dab5c37SJack F Vogel 	/* Derives media type */
3774dab5c37SJack F Vogel 	e1000_get_media_type_82575(hw);
3788cfa0ad2SJack F Vogel 	/* Set mta register count */
3798cfa0ad2SJack F Vogel 	mac->mta_reg_count = 128;
3804edd8523SJack F Vogel 	/* Set uta register count */
3814edd8523SJack F Vogel 	mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128;
3828cfa0ad2SJack F Vogel 	/* Set rar entry count */
3838cfa0ad2SJack F Vogel 	mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
3848cfa0ad2SJack F Vogel 	if (mac->type == e1000_82576)
3858cfa0ad2SJack F Vogel 		mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
386a69ed8dfSJack F Vogel 	if (mac->type == e1000_82580)
3874edd8523SJack F Vogel 		mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
388f0ecc46dSJack F Vogel 	if (mac->type == e1000_i350) {
389f0ecc46dSJack F Vogel 		mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
390f0ecc46dSJack F Vogel 		/* Enable EEE default settings for i350 */
391f0ecc46dSJack F Vogel 		dev_spec->eee_disable = FALSE;
392f0ecc46dSJack F Vogel 	}
393f0ecc46dSJack F Vogel 
3948cfa0ad2SJack F Vogel 	/* Set if part includes ASF firmware */
3958cfa0ad2SJack F Vogel 	mac->asf_firmware_present = TRUE;
3968ec87fc5SJack F Vogel 	/* FWSM register */
3978ec87fc5SJack F Vogel 	mac->has_fwsm = TRUE;
3988ec87fc5SJack F Vogel 	/* ARC supported; valid only if manageability features are enabled. */
3998cfa0ad2SJack F Vogel 	mac->arc_subsystem_valid =
400*ab5d0362SJack F Vogel 		!!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK);
4018cfa0ad2SJack F Vogel 
4028cfa0ad2SJack F Vogel 	/* Function pointers */
4038cfa0ad2SJack F Vogel 
4048cfa0ad2SJack F Vogel 	/* bus type/speed/width */
4058cfa0ad2SJack F Vogel 	mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
4068cfa0ad2SJack F Vogel 	/* reset */
407a69ed8dfSJack F Vogel 	if (mac->type >= e1000_82580)
4084edd8523SJack F Vogel 		mac->ops.reset_hw = e1000_reset_hw_82580;
4094edd8523SJack F Vogel 	else
4108cfa0ad2SJack F Vogel 	mac->ops.reset_hw = e1000_reset_hw_82575;
4118cfa0ad2SJack F Vogel 	/* hw initialization */
4128cfa0ad2SJack F Vogel 	mac->ops.init_hw = e1000_init_hw_82575;
4138cfa0ad2SJack F Vogel 	/* link setup */
4148cfa0ad2SJack F Vogel 	mac->ops.setup_link = e1000_setup_link_generic;
4158cfa0ad2SJack F Vogel 	/* physical interface link setup */
4168cfa0ad2SJack F Vogel 	mac->ops.setup_physical_interface =
4178cfa0ad2SJack F Vogel 		(hw->phy.media_type == e1000_media_type_copper)
4184dab5c37SJack F Vogel 		? e1000_setup_copper_link_82575 : e1000_setup_serdes_link_82575;
4198cfa0ad2SJack F Vogel 	/* physical interface shutdown */
4204edd8523SJack F Vogel 	mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575;
421a69ed8dfSJack F Vogel 	/* physical interface power up */
422a69ed8dfSJack F Vogel 	mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575;
4238cfa0ad2SJack F Vogel 	/* check for link */
4248cfa0ad2SJack F Vogel 	mac->ops.check_for_link = e1000_check_for_link_82575;
4258cfa0ad2SJack F Vogel 	/* read mac address */
4268cfa0ad2SJack F Vogel 	mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
427a69ed8dfSJack F Vogel 	/* configure collision distance */
428a69ed8dfSJack F Vogel 	mac->ops.config_collision_dist = e1000_config_collision_dist_82575;
4298cfa0ad2SJack F Vogel 	/* multicast address update */
430d035aa2dSJack F Vogel 	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
4314dab5c37SJack F Vogel 	if (hw->mac.type == e1000_i350) {
4324dab5c37SJack F Vogel 		/* writing VFTA */
4334dab5c37SJack F Vogel 		mac->ops.write_vfta = e1000_write_vfta_i350;
4344dab5c37SJack F Vogel 		/* clearing VFTA */
4354dab5c37SJack F Vogel 		mac->ops.clear_vfta = e1000_clear_vfta_i350;
4364dab5c37SJack F Vogel 	} else {
4378cfa0ad2SJack F Vogel 		/* writing VFTA */
4388cfa0ad2SJack F Vogel 		mac->ops.write_vfta = e1000_write_vfta_generic;
4398cfa0ad2SJack F Vogel 		/* clearing VFTA */
4408cfa0ad2SJack F Vogel 		mac->ops.clear_vfta = e1000_clear_vfta_generic;
4414dab5c37SJack F Vogel 	}
442d035aa2dSJack F Vogel 	/* ID LED init */
443d035aa2dSJack F Vogel 	mac->ops.id_led_init = e1000_id_led_init_generic;
4448cfa0ad2SJack F Vogel 	/* blink LED */
4458cfa0ad2SJack F Vogel 	mac->ops.blink_led = e1000_blink_led_generic;
4468cfa0ad2SJack F Vogel 	/* setup LED */
4478cfa0ad2SJack F Vogel 	mac->ops.setup_led = e1000_setup_led_generic;
4488cfa0ad2SJack F Vogel 	/* cleanup LED */
4498cfa0ad2SJack F Vogel 	mac->ops.cleanup_led = e1000_cleanup_led_generic;
4508cfa0ad2SJack F Vogel 	/* turn on/off LED */
4518cfa0ad2SJack F Vogel 	mac->ops.led_on = e1000_led_on_generic;
4528cfa0ad2SJack F Vogel 	mac->ops.led_off = e1000_led_off_generic;
4538cfa0ad2SJack F Vogel 	/* clear hardware counters */
4548cfa0ad2SJack F Vogel 	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575;
4558cfa0ad2SJack F Vogel 	/* link info */
4568cfa0ad2SJack F Vogel 	mac->ops.get_link_up_info = e1000_get_link_up_info_82575;
457*ab5d0362SJack F Vogel 	/* acquire SW_FW sync */
458*ab5d0362SJack F Vogel 	mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575;
459*ab5d0362SJack F Vogel 	mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575;
460*ab5d0362SJack F Vogel 	if (mac->type >= e1000_i210) {
461*ab5d0362SJack F Vogel 		mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210;
462*ab5d0362SJack F Vogel 		mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210;
463*ab5d0362SJack F Vogel 	}
4648cfa0ad2SJack F Vogel 
4654edd8523SJack F Vogel 	/* set lan id for port to determine which phy lock to use */
4664edd8523SJack F Vogel 	hw->mac.ops.set_lan_id(hw);
4674edd8523SJack F Vogel 
468daf9197cSJack F Vogel 	return E1000_SUCCESS;
4698cfa0ad2SJack F Vogel }
4708cfa0ad2SJack F Vogel 
4718cfa0ad2SJack F Vogel /**
4728cfa0ad2SJack F Vogel  *  e1000_init_function_pointers_82575 - Init func ptrs.
4738cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
4748cfa0ad2SJack F Vogel  *
475daf9197cSJack F Vogel  *  Called to initialize all function pointers and parameters.
4768cfa0ad2SJack F Vogel  **/
4778cfa0ad2SJack F Vogel void e1000_init_function_pointers_82575(struct e1000_hw *hw)
4788cfa0ad2SJack F Vogel {
4798cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_function_pointers_82575");
4808cfa0ad2SJack F Vogel 
4818cfa0ad2SJack F Vogel 	hw->mac.ops.init_params = e1000_init_mac_params_82575;
4828cfa0ad2SJack F Vogel 	hw->nvm.ops.init_params = e1000_init_nvm_params_82575;
4838cfa0ad2SJack F Vogel 	hw->phy.ops.init_params = e1000_init_phy_params_82575;
4847d9119bdSJack F Vogel 	hw->mbx.ops.init_params = e1000_init_mbx_params_pf;
4858cfa0ad2SJack F Vogel }
4868cfa0ad2SJack F Vogel 
4878cfa0ad2SJack F Vogel /**
4888cfa0ad2SJack F Vogel  *  e1000_acquire_phy_82575 - Acquire rights to access PHY
4898cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
4908cfa0ad2SJack F Vogel  *
491daf9197cSJack F Vogel  *  Acquire access rights to the correct PHY.
4928cfa0ad2SJack F Vogel  **/
4938cfa0ad2SJack F Vogel static s32 e1000_acquire_phy_82575(struct e1000_hw *hw)
4948cfa0ad2SJack F Vogel {
4959d81738fSJack F Vogel 	u16 mask = E1000_SWFW_PHY0_SM;
4968cfa0ad2SJack F Vogel 
4978cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_acquire_phy_82575");
4988cfa0ad2SJack F Vogel 
4999d81738fSJack F Vogel 	if (hw->bus.func == E1000_FUNC_1)
5009d81738fSJack F Vogel 		mask = E1000_SWFW_PHY1_SM;
5014edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_2)
5024edd8523SJack F Vogel 		mask = E1000_SWFW_PHY2_SM;
5034edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_3)
5044edd8523SJack F Vogel 		mask = E1000_SWFW_PHY3_SM;
5058cfa0ad2SJack F Vogel 
506*ab5d0362SJack F Vogel 	return hw->mac.ops.acquire_swfw_sync(hw, mask);
5078cfa0ad2SJack F Vogel }
5088cfa0ad2SJack F Vogel 
5098cfa0ad2SJack F Vogel /**
5108cfa0ad2SJack F Vogel  *  e1000_release_phy_82575 - Release rights to access PHY
5118cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5128cfa0ad2SJack F Vogel  *
513daf9197cSJack F Vogel  *  A wrapper to release access rights to the correct PHY.
5148cfa0ad2SJack F Vogel  **/
5158cfa0ad2SJack F Vogel static void e1000_release_phy_82575(struct e1000_hw *hw)
5168cfa0ad2SJack F Vogel {
5179d81738fSJack F Vogel 	u16 mask = E1000_SWFW_PHY0_SM;
5188cfa0ad2SJack F Vogel 
5198cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_release_phy_82575");
5208cfa0ad2SJack F Vogel 
5219d81738fSJack F Vogel 	if (hw->bus.func == E1000_FUNC_1)
5229d81738fSJack F Vogel 		mask = E1000_SWFW_PHY1_SM;
5234edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_2)
5244edd8523SJack F Vogel 		mask = E1000_SWFW_PHY2_SM;
5254edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_3)
5264edd8523SJack F Vogel 		mask = E1000_SWFW_PHY3_SM;
5279d81738fSJack F Vogel 
528*ab5d0362SJack F Vogel 	hw->mac.ops.release_swfw_sync(hw, mask);
5298cfa0ad2SJack F Vogel }
5308cfa0ad2SJack F Vogel 
5318cfa0ad2SJack F Vogel /**
5328cfa0ad2SJack F Vogel  *  e1000_read_phy_reg_sgmii_82575 - Read PHY register using sgmii
5338cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5348cfa0ad2SJack F Vogel  *  @offset: register offset to be read
5358cfa0ad2SJack F Vogel  *  @data: pointer to the read data
5368cfa0ad2SJack F Vogel  *
5378cfa0ad2SJack F Vogel  *  Reads the PHY register at offset using the serial gigabit media independent
5388cfa0ad2SJack F Vogel  *  interface and stores the retrieved information in data.
5398cfa0ad2SJack F Vogel  **/
5408cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
5418cfa0ad2SJack F Vogel 					  u16 *data)
5428cfa0ad2SJack F Vogel {
5434edd8523SJack F Vogel 	s32 ret_val = -E1000_ERR_PARAM;
5448cfa0ad2SJack F Vogel 
5458cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_read_phy_reg_sgmii_82575");
5468cfa0ad2SJack F Vogel 
5478cfa0ad2SJack F Vogel 	if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
5488cfa0ad2SJack F Vogel 		DEBUGOUT1("PHY Address %u is out of range\n", offset);
5494edd8523SJack F Vogel 		goto out;
5508cfa0ad2SJack F Vogel 	}
5518cfa0ad2SJack F Vogel 
5524edd8523SJack F Vogel 	ret_val = hw->phy.ops.acquire(hw);
5534edd8523SJack F Vogel 	if (ret_val)
5544edd8523SJack F Vogel 		goto out;
5558cfa0ad2SJack F Vogel 
5564edd8523SJack F Vogel 	ret_val = e1000_read_phy_reg_i2c(hw, offset, data);
5578cfa0ad2SJack F Vogel 
5584edd8523SJack F Vogel 	hw->phy.ops.release(hw);
5598cfa0ad2SJack F Vogel 
5604edd8523SJack F Vogel out:
5614edd8523SJack F Vogel 	return ret_val;
5628cfa0ad2SJack F Vogel }
5638cfa0ad2SJack F Vogel 
5648cfa0ad2SJack F Vogel /**
5658cfa0ad2SJack F Vogel  *  e1000_write_phy_reg_sgmii_82575 - Write PHY register using sgmii
5668cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
5678cfa0ad2SJack F Vogel  *  @offset: register offset to write to
5688cfa0ad2SJack F Vogel  *  @data: data to write at register offset
5698cfa0ad2SJack F Vogel  *
5708cfa0ad2SJack F Vogel  *  Writes the data to PHY register at the offset using the serial gigabit
5718cfa0ad2SJack F Vogel  *  media independent interface.
5728cfa0ad2SJack F Vogel  **/
5738cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
5748cfa0ad2SJack F Vogel 					   u16 data)
5758cfa0ad2SJack F Vogel {
5764edd8523SJack F Vogel 	s32 ret_val = -E1000_ERR_PARAM;
5778cfa0ad2SJack F Vogel 
5788cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_write_phy_reg_sgmii_82575");
5798cfa0ad2SJack F Vogel 
5808cfa0ad2SJack F Vogel 	if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
5818cfa0ad2SJack F Vogel 		DEBUGOUT1("PHY Address %d is out of range\n", offset);
5824edd8523SJack F Vogel 		goto out;
5838cfa0ad2SJack F Vogel 	}
5848cfa0ad2SJack F Vogel 
5854edd8523SJack F Vogel 	ret_val = hw->phy.ops.acquire(hw);
5864edd8523SJack F Vogel 	if (ret_val)
5874edd8523SJack F Vogel 		goto out;
5888cfa0ad2SJack F Vogel 
5894edd8523SJack F Vogel 	ret_val = e1000_write_phy_reg_i2c(hw, offset, data);
5908cfa0ad2SJack F Vogel 
5914edd8523SJack F Vogel 	hw->phy.ops.release(hw);
5928cfa0ad2SJack F Vogel 
5934edd8523SJack F Vogel out:
5944edd8523SJack F Vogel 	return ret_val;
5958cfa0ad2SJack F Vogel }
5968cfa0ad2SJack F Vogel 
5978cfa0ad2SJack F Vogel /**
5988cfa0ad2SJack F Vogel  *  e1000_get_phy_id_82575 - Retrieve PHY addr and id
5998cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
6008cfa0ad2SJack F Vogel  *
6018cfa0ad2SJack F Vogel  *  Retrieves the PHY address and ID for both PHY's which do and do not use
6028cfa0ad2SJack F Vogel  *  sgmi interface.
6038cfa0ad2SJack F Vogel  **/
6048cfa0ad2SJack F Vogel static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
6058cfa0ad2SJack F Vogel {
6068cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
6078cfa0ad2SJack F Vogel 	s32  ret_val = E1000_SUCCESS;
6088cfa0ad2SJack F Vogel 	u16 phy_id;
6094edd8523SJack F Vogel 	u32 ctrl_ext;
6107d9119bdSJack F Vogel 	u32 mdic;
6118cfa0ad2SJack F Vogel 
6128cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_phy_id_82575");
6138cfa0ad2SJack F Vogel 
6148cfa0ad2SJack F Vogel 	/*
6158cfa0ad2SJack F Vogel 	 * For SGMII PHYs, we try the list of possible addresses until
6168cfa0ad2SJack F Vogel 	 * we find one that works.  For non-SGMII PHYs
6178cfa0ad2SJack F Vogel 	 * (e.g. integrated copper PHYs), an address of 1 should
6188cfa0ad2SJack F Vogel 	 * work.  The result of this function should mean phy->phy_addr
6198cfa0ad2SJack F Vogel 	 * and phy->id are set correctly.
6208cfa0ad2SJack F Vogel 	 */
6214edd8523SJack F Vogel 	if (!e1000_sgmii_active_82575(hw)) {
6228cfa0ad2SJack F Vogel 		phy->addr = 1;
6238cfa0ad2SJack F Vogel 		ret_val = e1000_get_phy_id(hw);
6248cfa0ad2SJack F Vogel 		goto out;
6258cfa0ad2SJack F Vogel 	}
6268cfa0ad2SJack F Vogel 
6277d9119bdSJack F Vogel 	if (e1000_sgmii_uses_mdio_82575(hw)) {
6287d9119bdSJack F Vogel 		switch (hw->mac.type) {
6297d9119bdSJack F Vogel 		case e1000_82575:
6307d9119bdSJack F Vogel 		case e1000_82576:
6317d9119bdSJack F Vogel 			mdic = E1000_READ_REG(hw, E1000_MDIC);
6327d9119bdSJack F Vogel 			mdic &= E1000_MDIC_PHY_MASK;
6337d9119bdSJack F Vogel 			phy->addr = mdic >> E1000_MDIC_PHY_SHIFT;
6347d9119bdSJack F Vogel 			break;
6357d9119bdSJack F Vogel 		case e1000_82580:
636f0ecc46dSJack F Vogel 		case e1000_i350:
6377d9119bdSJack F Vogel 			mdic = E1000_READ_REG(hw, E1000_MDICNFG);
6387d9119bdSJack F Vogel 			mdic &= E1000_MDICNFG_PHY_MASK;
6397d9119bdSJack F Vogel 			phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;
6407d9119bdSJack F Vogel 			break;
6417d9119bdSJack F Vogel 		default:
6427d9119bdSJack F Vogel 			ret_val = -E1000_ERR_PHY;
6437d9119bdSJack F Vogel 			goto out;
6447d9119bdSJack F Vogel 			break;
6457d9119bdSJack F Vogel 		}
6467d9119bdSJack F Vogel 		ret_val = e1000_get_phy_id(hw);
6477d9119bdSJack F Vogel 		goto out;
6487d9119bdSJack F Vogel 	}
6497d9119bdSJack F Vogel 
6504edd8523SJack F Vogel 	/* Power on sgmii phy if it is disabled */
6514edd8523SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
6524edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT,
6534edd8523SJack F Vogel 			ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA);
6544edd8523SJack F Vogel 	E1000_WRITE_FLUSH(hw);
6554edd8523SJack F Vogel 	msec_delay(300);
6564edd8523SJack F Vogel 
6578cfa0ad2SJack F Vogel 	/*
6588cfa0ad2SJack F Vogel 	 * The address field in the I2CCMD register is 3 bits and 0 is invalid.
6598cfa0ad2SJack F Vogel 	 * Therefore, we need to test 1-7
6608cfa0ad2SJack F Vogel 	 */
6618cfa0ad2SJack F Vogel 	for (phy->addr = 1; phy->addr < 8; phy->addr++) {
6628cfa0ad2SJack F Vogel 		ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id);
6638cfa0ad2SJack F Vogel 		if (ret_val == E1000_SUCCESS) {
6648cfa0ad2SJack F Vogel 			DEBUGOUT2("Vendor ID 0x%08X read at address %u\n",
6654dab5c37SJack F Vogel 				  phy_id, phy->addr);
6668cfa0ad2SJack F Vogel 			/*
6678cfa0ad2SJack F Vogel 			 * At the time of this writing, The M88 part is
6688cfa0ad2SJack F Vogel 			 * the only supported SGMII PHY product.
6698cfa0ad2SJack F Vogel 			 */
6708cfa0ad2SJack F Vogel 			if (phy_id == M88_VENDOR)
6718cfa0ad2SJack F Vogel 				break;
6728cfa0ad2SJack F Vogel 		} else {
6738cfa0ad2SJack F Vogel 			DEBUGOUT1("PHY address %u was unreadable\n",
6748cfa0ad2SJack F Vogel 				  phy->addr);
6758cfa0ad2SJack F Vogel 		}
6768cfa0ad2SJack F Vogel 	}
6778cfa0ad2SJack F Vogel 
6788cfa0ad2SJack F Vogel 	/* A valid PHY type couldn't be found. */
6798cfa0ad2SJack F Vogel 	if (phy->addr == 8) {
6808cfa0ad2SJack F Vogel 		phy->addr = 0;
6818cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PHY;
6824edd8523SJack F Vogel 	} else {
6834edd8523SJack F Vogel 		ret_val = e1000_get_phy_id(hw);
6848cfa0ad2SJack F Vogel 	}
6858cfa0ad2SJack F Vogel 
6864edd8523SJack F Vogel 	/* restore previous sfp cage power state */
6874edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
6888cfa0ad2SJack F Vogel 
6898cfa0ad2SJack F Vogel out:
6908cfa0ad2SJack F Vogel 	return ret_val;
6918cfa0ad2SJack F Vogel }
6928cfa0ad2SJack F Vogel 
6938cfa0ad2SJack F Vogel /**
6948cfa0ad2SJack F Vogel  *  e1000_phy_hw_reset_sgmii_82575 - Performs a PHY reset
6958cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
6968cfa0ad2SJack F Vogel  *
6978cfa0ad2SJack F Vogel  *  Resets the PHY using the serial gigabit media independent interface.
6988cfa0ad2SJack F Vogel  **/
6998cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw)
7008cfa0ad2SJack F Vogel {
7018cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
7028cfa0ad2SJack F Vogel 
7038cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575");
7048cfa0ad2SJack F Vogel 
7058cfa0ad2SJack F Vogel 	/*
7068cfa0ad2SJack F Vogel 	 * This isn't a TRUE "hard" reset, but is the only reset
7078cfa0ad2SJack F Vogel 	 * available to us at this time.
7088cfa0ad2SJack F Vogel 	 */
7098cfa0ad2SJack F Vogel 
7108cfa0ad2SJack F Vogel 	DEBUGOUT("Soft resetting SGMII attached PHY...\n");
7118cfa0ad2SJack F Vogel 
7128cfa0ad2SJack F Vogel 	if (!(hw->phy.ops.write_reg))
7138cfa0ad2SJack F Vogel 		goto out;
7148cfa0ad2SJack F Vogel 
7158cfa0ad2SJack F Vogel 	/*
7168cfa0ad2SJack F Vogel 	 * SFP documentation requires the following to configure the SPF module
7178cfa0ad2SJack F Vogel 	 * to work on SGMII.  No further documentation is given.
7188cfa0ad2SJack F Vogel 	 */
7198cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084);
7208cfa0ad2SJack F Vogel 	if (ret_val)
7218cfa0ad2SJack F Vogel 		goto out;
7228cfa0ad2SJack F Vogel 
7238cfa0ad2SJack F Vogel 	ret_val = hw->phy.ops.commit(hw);
7248cfa0ad2SJack F Vogel 
7258cfa0ad2SJack F Vogel out:
7268cfa0ad2SJack F Vogel 	return ret_val;
7278cfa0ad2SJack F Vogel }
7288cfa0ad2SJack F Vogel 
7298cfa0ad2SJack F Vogel /**
7308cfa0ad2SJack F Vogel  *  e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state
7318cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
7328cfa0ad2SJack F Vogel  *  @active: TRUE to enable LPLU, FALSE to disable
7338cfa0ad2SJack F Vogel  *
7348cfa0ad2SJack F Vogel  *  Sets the LPLU D0 state according to the active flag.  When
7358cfa0ad2SJack F Vogel  *  activating LPLU this function also disables smart speed
7368cfa0ad2SJack F Vogel  *  and vice versa.  LPLU will not be activated unless the
7378cfa0ad2SJack F Vogel  *  device autonegotiation advertisement meets standards of
7388cfa0ad2SJack F Vogel  *  either 10 or 10/100 or 10/100/1000 at all duplexes.
7398cfa0ad2SJack F Vogel  *  This is a function pointer entry point only called by
7408cfa0ad2SJack F Vogel  *  PHY setup routines.
7418cfa0ad2SJack F Vogel  **/
7428cfa0ad2SJack F Vogel static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active)
7438cfa0ad2SJack F Vogel {
7448cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
7458cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
7468cfa0ad2SJack F Vogel 	u16 data;
7478cfa0ad2SJack F Vogel 
7488cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_set_d0_lplu_state_82575");
7498cfa0ad2SJack F Vogel 
7508cfa0ad2SJack F Vogel 	if (!(hw->phy.ops.read_reg))
7518cfa0ad2SJack F Vogel 		goto out;
7528cfa0ad2SJack F Vogel 
7538cfa0ad2SJack F Vogel 	ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
7548cfa0ad2SJack F Vogel 	if (ret_val)
7558cfa0ad2SJack F Vogel 		goto out;
7568cfa0ad2SJack F Vogel 
7578cfa0ad2SJack F Vogel 	if (active) {
7588cfa0ad2SJack F Vogel 		data |= IGP02E1000_PM_D0_LPLU;
7598cfa0ad2SJack F Vogel 		ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
7608cfa0ad2SJack F Vogel 					     data);
7618cfa0ad2SJack F Vogel 		if (ret_val)
7628cfa0ad2SJack F Vogel 			goto out;
7638cfa0ad2SJack F Vogel 
7648cfa0ad2SJack F Vogel 		/* When LPLU is enabled, we should disable SmartSpeed */
7658cfa0ad2SJack F Vogel 		ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
7668cfa0ad2SJack F Vogel 					    &data);
7678cfa0ad2SJack F Vogel 		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
7688cfa0ad2SJack F Vogel 		ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
7698cfa0ad2SJack F Vogel 					     data);
7708cfa0ad2SJack F Vogel 		if (ret_val)
7718cfa0ad2SJack F Vogel 			goto out;
7728cfa0ad2SJack F Vogel 	} else {
7738cfa0ad2SJack F Vogel 		data &= ~IGP02E1000_PM_D0_LPLU;
7748cfa0ad2SJack F Vogel 		ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
7758cfa0ad2SJack F Vogel 					     data);
7768cfa0ad2SJack F Vogel 		/*
7778cfa0ad2SJack F Vogel 		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
7788cfa0ad2SJack F Vogel 		 * during Dx states where the power conservation is most
7798cfa0ad2SJack F Vogel 		 * important.  During driver activity we should enable
7808cfa0ad2SJack F Vogel 		 * SmartSpeed, so performance is maintained.
7818cfa0ad2SJack F Vogel 		 */
7828cfa0ad2SJack F Vogel 		if (phy->smart_speed == e1000_smart_speed_on) {
7838cfa0ad2SJack F Vogel 			ret_val = phy->ops.read_reg(hw,
7848cfa0ad2SJack F Vogel 						    IGP01E1000_PHY_PORT_CONFIG,
7858cfa0ad2SJack F Vogel 						    &data);
7868cfa0ad2SJack F Vogel 			if (ret_val)
7878cfa0ad2SJack F Vogel 				goto out;
7888cfa0ad2SJack F Vogel 
7898cfa0ad2SJack F Vogel 			data |= IGP01E1000_PSCFR_SMART_SPEED;
7908cfa0ad2SJack F Vogel 			ret_val = phy->ops.write_reg(hw,
7918cfa0ad2SJack F Vogel 						     IGP01E1000_PHY_PORT_CONFIG,
7928cfa0ad2SJack F Vogel 						     data);
7938cfa0ad2SJack F Vogel 			if (ret_val)
7948cfa0ad2SJack F Vogel 				goto out;
7958cfa0ad2SJack F Vogel 		} else if (phy->smart_speed == e1000_smart_speed_off) {
7968cfa0ad2SJack F Vogel 			ret_val = phy->ops.read_reg(hw,
7978cfa0ad2SJack F Vogel 						    IGP01E1000_PHY_PORT_CONFIG,
7988cfa0ad2SJack F Vogel 						    &data);
7998cfa0ad2SJack F Vogel 			if (ret_val)
8008cfa0ad2SJack F Vogel 				goto out;
8018cfa0ad2SJack F Vogel 
8028cfa0ad2SJack F Vogel 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
8038cfa0ad2SJack F Vogel 			ret_val = phy->ops.write_reg(hw,
8048cfa0ad2SJack F Vogel 						     IGP01E1000_PHY_PORT_CONFIG,
8058cfa0ad2SJack F Vogel 						     data);
8068cfa0ad2SJack F Vogel 			if (ret_val)
8078cfa0ad2SJack F Vogel 				goto out;
8088cfa0ad2SJack F Vogel 		}
8098cfa0ad2SJack F Vogel 	}
8108cfa0ad2SJack F Vogel 
8118cfa0ad2SJack F Vogel out:
8128cfa0ad2SJack F Vogel 	return ret_val;
8138cfa0ad2SJack F Vogel }
8148cfa0ad2SJack F Vogel 
8158cfa0ad2SJack F Vogel /**
816f0ecc46dSJack F Vogel  *  e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state
817f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
818f0ecc46dSJack F Vogel  *  @active: TRUE to enable LPLU, FALSE to disable
819f0ecc46dSJack F Vogel  *
820f0ecc46dSJack F Vogel  *  Sets the LPLU D0 state according to the active flag.  When
821f0ecc46dSJack F Vogel  *  activating LPLU this function also disables smart speed
822f0ecc46dSJack F Vogel  *  and vice versa.  LPLU will not be activated unless the
823f0ecc46dSJack F Vogel  *  device autonegotiation advertisement meets standards of
824f0ecc46dSJack F Vogel  *  either 10 or 10/100 or 10/100/1000 at all duplexes.
825f0ecc46dSJack F Vogel  *  This is a function pointer entry point only called by
826f0ecc46dSJack F Vogel  *  PHY setup routines.
827f0ecc46dSJack F Vogel  **/
828f0ecc46dSJack F Vogel static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active)
829f0ecc46dSJack F Vogel {
830f0ecc46dSJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
831f0ecc46dSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
832*ab5d0362SJack F Vogel 	u32 data;
833f0ecc46dSJack F Vogel 
834f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_set_d0_lplu_state_82580");
835f0ecc46dSJack F Vogel 
836f0ecc46dSJack F Vogel 	data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
837f0ecc46dSJack F Vogel 
838f0ecc46dSJack F Vogel 	if (active) {
839f0ecc46dSJack F Vogel 		data |= E1000_82580_PM_D0_LPLU;
840f0ecc46dSJack F Vogel 
841f0ecc46dSJack F Vogel 		/* When LPLU is enabled, we should disable SmartSpeed */
842f0ecc46dSJack F Vogel 		data &= ~E1000_82580_PM_SPD;
843f0ecc46dSJack F Vogel 	} else {
844f0ecc46dSJack F Vogel 		data &= ~E1000_82580_PM_D0_LPLU;
845f0ecc46dSJack F Vogel 
846f0ecc46dSJack F Vogel 		/*
847f0ecc46dSJack F Vogel 		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
848f0ecc46dSJack F Vogel 		 * during Dx states where the power conservation is most
849f0ecc46dSJack F Vogel 		 * important.  During driver activity we should enable
850f0ecc46dSJack F Vogel 		 * SmartSpeed, so performance is maintained.
851f0ecc46dSJack F Vogel 		 */
8524dab5c37SJack F Vogel 		if (phy->smart_speed == e1000_smart_speed_on)
853f0ecc46dSJack F Vogel 			data |= E1000_82580_PM_SPD;
8544dab5c37SJack F Vogel 		else if (phy->smart_speed == e1000_smart_speed_off)
855f0ecc46dSJack F Vogel 			data &= ~E1000_82580_PM_SPD;
856f0ecc46dSJack F Vogel 	}
857f0ecc46dSJack F Vogel 
858f0ecc46dSJack F Vogel 	E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
859f0ecc46dSJack F Vogel 	return ret_val;
860f0ecc46dSJack F Vogel }
861f0ecc46dSJack F Vogel 
862f0ecc46dSJack F Vogel /**
863f0ecc46dSJack F Vogel  *  e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3
864f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
865f0ecc46dSJack F Vogel  *  @active: boolean used to enable/disable lplu
866f0ecc46dSJack F Vogel  *
867f0ecc46dSJack F Vogel  *  Success returns 0, Failure returns 1
868f0ecc46dSJack F Vogel  *
869f0ecc46dSJack F Vogel  *  The low power link up (lplu) state is set to the power management level D3
870f0ecc46dSJack F Vogel  *  and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
871f0ecc46dSJack F Vogel  *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
872f0ecc46dSJack F Vogel  *  is used during Dx states where the power conservation is most important.
873f0ecc46dSJack F Vogel  *  During driver activity, SmartSpeed should be enabled so performance is
874f0ecc46dSJack F Vogel  *  maintained.
875f0ecc46dSJack F Vogel  **/
876f0ecc46dSJack F Vogel s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active)
877f0ecc46dSJack F Vogel {
878f0ecc46dSJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
879f0ecc46dSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
880*ab5d0362SJack F Vogel 	u32 data;
881f0ecc46dSJack F Vogel 
882f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_set_d3_lplu_state_82580");
883f0ecc46dSJack F Vogel 
884f0ecc46dSJack F Vogel 	data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
885f0ecc46dSJack F Vogel 
886f0ecc46dSJack F Vogel 	if (!active) {
887f0ecc46dSJack F Vogel 		data &= ~E1000_82580_PM_D3_LPLU;
888f0ecc46dSJack F Vogel 		/*
889f0ecc46dSJack F Vogel 		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
890f0ecc46dSJack F Vogel 		 * during Dx states where the power conservation is most
891f0ecc46dSJack F Vogel 		 * important.  During driver activity we should enable
892f0ecc46dSJack F Vogel 		 * SmartSpeed, so performance is maintained.
893f0ecc46dSJack F Vogel 		 */
8944dab5c37SJack F Vogel 		if (phy->smart_speed == e1000_smart_speed_on)
895f0ecc46dSJack F Vogel 			data |= E1000_82580_PM_SPD;
8964dab5c37SJack F Vogel 		else if (phy->smart_speed == e1000_smart_speed_off)
897f0ecc46dSJack F Vogel 			data &= ~E1000_82580_PM_SPD;
898f0ecc46dSJack F Vogel 	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
899f0ecc46dSJack F Vogel 		   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
900f0ecc46dSJack F Vogel 		   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
901f0ecc46dSJack F Vogel 		data |= E1000_82580_PM_D3_LPLU;
902f0ecc46dSJack F Vogel 		/* When LPLU is enabled, we should disable SmartSpeed */
903f0ecc46dSJack F Vogel 		data &= ~E1000_82580_PM_SPD;
904f0ecc46dSJack F Vogel 	}
905f0ecc46dSJack F Vogel 
906f0ecc46dSJack F Vogel 	E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
907f0ecc46dSJack F Vogel 	return ret_val;
908f0ecc46dSJack F Vogel }
909f0ecc46dSJack F Vogel 
910f0ecc46dSJack F Vogel /**
9118cfa0ad2SJack F Vogel  *  e1000_acquire_nvm_82575 - Request for access to EEPROM
9128cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
9138cfa0ad2SJack F Vogel  *
9148cfa0ad2SJack F Vogel  *  Acquire the necessary semaphores for exclusive access to the EEPROM.
9158cfa0ad2SJack F Vogel  *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
9168cfa0ad2SJack F Vogel  *  Return successful if access grant bit set, else clear the request for
9178cfa0ad2SJack F Vogel  *  EEPROM access and return -E1000_ERR_NVM (-1).
9188cfa0ad2SJack F Vogel  **/
9198cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw)
9208cfa0ad2SJack F Vogel {
9218cfa0ad2SJack F Vogel 	s32 ret_val;
9228cfa0ad2SJack F Vogel 
9238cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_acquire_nvm_82575");
9248cfa0ad2SJack F Vogel 
9258cfa0ad2SJack F Vogel 	ret_val = e1000_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
9268cfa0ad2SJack F Vogel 	if (ret_val)
9278cfa0ad2SJack F Vogel 		goto out;
9284dab5c37SJack F Vogel 
9294dab5c37SJack F Vogel 	/*
9304dab5c37SJack F Vogel 	 * Check if there is some access
9314dab5c37SJack F Vogel 	 * error this access may hook on
9324dab5c37SJack F Vogel 	 */
9334dab5c37SJack F Vogel 	if (hw->mac.type == e1000_i350) {
9344dab5c37SJack F Vogel 		u32 eecd = E1000_READ_REG(hw, E1000_EECD);
9354dab5c37SJack F Vogel 		if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT |
9364dab5c37SJack F Vogel 		    E1000_EECD_TIMEOUT)) {
9374dab5c37SJack F Vogel 			/* Clear all access error flags */
9384dab5c37SJack F Vogel 			E1000_WRITE_REG(hw, E1000_EECD, eecd |
9394dab5c37SJack F Vogel 					E1000_EECD_ERROR_CLR);
9404dab5c37SJack F Vogel 			DEBUGOUT("Nvm bit banging access error detected and cleared.\n");
9414dab5c37SJack F Vogel 		}
9424dab5c37SJack F Vogel 	}
9434dab5c37SJack F Vogel 	if (hw->mac.type == e1000_82580) {
9444dab5c37SJack F Vogel 		u32 eecd = E1000_READ_REG(hw, E1000_EECD);
9454dab5c37SJack F Vogel 		if (eecd & E1000_EECD_BLOCKED) {
9464dab5c37SJack F Vogel 			/* Clear access error flag */
9474dab5c37SJack F Vogel 			E1000_WRITE_REG(hw, E1000_EECD, eecd |
9484dab5c37SJack F Vogel 					E1000_EECD_BLOCKED);
9494dab5c37SJack F Vogel 			DEBUGOUT("Nvm bit banging access error detected and cleared.\n");
9504dab5c37SJack F Vogel 		}
9514dab5c37SJack F Vogel 	}
9524dab5c37SJack F Vogel 
9534dab5c37SJack F Vogel 
9548cfa0ad2SJack F Vogel 	ret_val = e1000_acquire_nvm_generic(hw);
9558cfa0ad2SJack F Vogel 	if (ret_val)
9568cfa0ad2SJack F Vogel 		e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
9578cfa0ad2SJack F Vogel 
9588cfa0ad2SJack F Vogel out:
9598cfa0ad2SJack F Vogel 	return ret_val;
9608cfa0ad2SJack F Vogel }
9618cfa0ad2SJack F Vogel 
9628cfa0ad2SJack F Vogel /**
9638cfa0ad2SJack F Vogel  *  e1000_release_nvm_82575 - Release exclusive access to EEPROM
9648cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
9658cfa0ad2SJack F Vogel  *
9668cfa0ad2SJack F Vogel  *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
9678cfa0ad2SJack F Vogel  *  then release the semaphores acquired.
9688cfa0ad2SJack F Vogel  **/
9698cfa0ad2SJack F Vogel static void e1000_release_nvm_82575(struct e1000_hw *hw)
9708cfa0ad2SJack F Vogel {
9718cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_release_nvm_82575");
9728cfa0ad2SJack F Vogel 
9734dab5c37SJack F Vogel 	e1000_release_nvm_generic(hw);
974*ab5d0362SJack F Vogel 
9758cfa0ad2SJack F Vogel 	e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
9768cfa0ad2SJack F Vogel }
9778cfa0ad2SJack F Vogel 
9788cfa0ad2SJack F Vogel /**
9798cfa0ad2SJack F Vogel  *  e1000_acquire_swfw_sync_82575 - Acquire SW/FW semaphore
9808cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
9818cfa0ad2SJack F Vogel  *  @mask: specifies which semaphore to acquire
9828cfa0ad2SJack F Vogel  *
9838cfa0ad2SJack F Vogel  *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
9848cfa0ad2SJack F Vogel  *  will also specify which port we're acquiring the lock for.
9858cfa0ad2SJack F Vogel  **/
9868cfa0ad2SJack F Vogel static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
9878cfa0ad2SJack F Vogel {
9888cfa0ad2SJack F Vogel 	u32 swfw_sync;
9898cfa0ad2SJack F Vogel 	u32 swmask = mask;
9908cfa0ad2SJack F Vogel 	u32 fwmask = mask << 16;
9918cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
9928cfa0ad2SJack F Vogel 	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
9938cfa0ad2SJack F Vogel 
9948cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_acquire_swfw_sync_82575");
9958cfa0ad2SJack F Vogel 
9968cfa0ad2SJack F Vogel 	while (i < timeout) {
9978cfa0ad2SJack F Vogel 		if (e1000_get_hw_semaphore_generic(hw)) {
9988cfa0ad2SJack F Vogel 			ret_val = -E1000_ERR_SWFW_SYNC;
9998cfa0ad2SJack F Vogel 			goto out;
10008cfa0ad2SJack F Vogel 		}
10018cfa0ad2SJack F Vogel 
10028cfa0ad2SJack F Vogel 		swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
10038cfa0ad2SJack F Vogel 		if (!(swfw_sync & (fwmask | swmask)))
10048cfa0ad2SJack F Vogel 			break;
10058cfa0ad2SJack F Vogel 
10068cfa0ad2SJack F Vogel 		/*
10078cfa0ad2SJack F Vogel 		 * Firmware currently using resource (fwmask)
10088cfa0ad2SJack F Vogel 		 * or other software thread using resource (swmask)
10098cfa0ad2SJack F Vogel 		 */
10108cfa0ad2SJack F Vogel 		e1000_put_hw_semaphore_generic(hw);
10118cfa0ad2SJack F Vogel 		msec_delay_irq(5);
10128cfa0ad2SJack F Vogel 		i++;
10138cfa0ad2SJack F Vogel 	}
10148cfa0ad2SJack F Vogel 
10158cfa0ad2SJack F Vogel 	if (i == timeout) {
10168cfa0ad2SJack F Vogel 		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
10178cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_SWFW_SYNC;
10188cfa0ad2SJack F Vogel 		goto out;
10198cfa0ad2SJack F Vogel 	}
10208cfa0ad2SJack F Vogel 
10218cfa0ad2SJack F Vogel 	swfw_sync |= swmask;
10228cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
10238cfa0ad2SJack F Vogel 
10248cfa0ad2SJack F Vogel 	e1000_put_hw_semaphore_generic(hw);
10258cfa0ad2SJack F Vogel 
10268cfa0ad2SJack F Vogel out:
10278cfa0ad2SJack F Vogel 	return ret_val;
10288cfa0ad2SJack F Vogel }
10298cfa0ad2SJack F Vogel 
10308cfa0ad2SJack F Vogel /**
10318cfa0ad2SJack F Vogel  *  e1000_release_swfw_sync_82575 - Release SW/FW semaphore
10328cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
10338cfa0ad2SJack F Vogel  *  @mask: specifies which semaphore to acquire
10348cfa0ad2SJack F Vogel  *
10358cfa0ad2SJack F Vogel  *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
10368cfa0ad2SJack F Vogel  *  will also specify which port we're releasing the lock for.
10378cfa0ad2SJack F Vogel  **/
10388cfa0ad2SJack F Vogel static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
10398cfa0ad2SJack F Vogel {
10408cfa0ad2SJack F Vogel 	u32 swfw_sync;
10418cfa0ad2SJack F Vogel 
10428cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_release_swfw_sync_82575");
10438cfa0ad2SJack F Vogel 
10444dab5c37SJack F Vogel 	while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS)
10454dab5c37SJack F Vogel 		; /* Empty */
10468cfa0ad2SJack F Vogel 
10478cfa0ad2SJack F Vogel 	swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
10488cfa0ad2SJack F Vogel 	swfw_sync &= ~mask;
10498cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
10508cfa0ad2SJack F Vogel 
10518cfa0ad2SJack F Vogel 	e1000_put_hw_semaphore_generic(hw);
10528cfa0ad2SJack F Vogel }
10538cfa0ad2SJack F Vogel 
10548cfa0ad2SJack F Vogel /**
10558cfa0ad2SJack F Vogel  *  e1000_get_cfg_done_82575 - Read config done bit
10568cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
10578cfa0ad2SJack F Vogel  *
10588cfa0ad2SJack F Vogel  *  Read the management control register for the config done bit for
10598cfa0ad2SJack F Vogel  *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
10608cfa0ad2SJack F Vogel  *  to read the config done bit, so an error is *ONLY* logged and returns
10618cfa0ad2SJack F Vogel  *  E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon
10628cfa0ad2SJack F Vogel  *  would not be able to be reset or change link.
10638cfa0ad2SJack F Vogel  **/
10648cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw)
10658cfa0ad2SJack F Vogel {
10668cfa0ad2SJack F Vogel 	s32 timeout = PHY_CFG_TIMEOUT;
10678cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
10688cfa0ad2SJack F Vogel 	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
10698cfa0ad2SJack F Vogel 
10708cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_cfg_done_82575");
10718cfa0ad2SJack F Vogel 
10729d81738fSJack F Vogel 	if (hw->bus.func == E1000_FUNC_1)
10738cfa0ad2SJack F Vogel 		mask = E1000_NVM_CFG_DONE_PORT_1;
10744edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_2)
10754edd8523SJack F Vogel 		mask = E1000_NVM_CFG_DONE_PORT_2;
10764edd8523SJack F Vogel 	else if (hw->bus.func == E1000_FUNC_3)
10774edd8523SJack F Vogel 		mask = E1000_NVM_CFG_DONE_PORT_3;
10788cfa0ad2SJack F Vogel 	while (timeout) {
10798cfa0ad2SJack F Vogel 		if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask)
10808cfa0ad2SJack F Vogel 			break;
10818cfa0ad2SJack F Vogel 		msec_delay(1);
10828cfa0ad2SJack F Vogel 		timeout--;
10838cfa0ad2SJack F Vogel 	}
10844edd8523SJack F Vogel 	if (!timeout)
10858cfa0ad2SJack F Vogel 		DEBUGOUT("MNG configuration cycle has not completed.\n");
10868cfa0ad2SJack F Vogel 
10878cfa0ad2SJack F Vogel 	/* If EEPROM is not marked present, init the PHY manually */
1088*ab5d0362SJack F Vogel 	if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) &&
10894edd8523SJack F Vogel 	    (hw->phy.type == e1000_phy_igp_3))
10908cfa0ad2SJack F Vogel 		e1000_phy_init_script_igp3(hw);
10918cfa0ad2SJack F Vogel 
10928cfa0ad2SJack F Vogel 	return ret_val;
10938cfa0ad2SJack F Vogel }
10948cfa0ad2SJack F Vogel 
10958cfa0ad2SJack F Vogel /**
10968cfa0ad2SJack F Vogel  *  e1000_get_link_up_info_82575 - Get link speed/duplex info
10978cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
10988cfa0ad2SJack F Vogel  *  @speed: stores the current speed
10998cfa0ad2SJack F Vogel  *  @duplex: stores the current duplex
11008cfa0ad2SJack F Vogel  *
11018cfa0ad2SJack F Vogel  *  This is a wrapper function, if using the serial gigabit media independent
11028cfa0ad2SJack F Vogel  *  interface, use PCS to retrieve the link speed and duplex information.
11038cfa0ad2SJack F Vogel  *  Otherwise, use the generic function to get the link speed and duplex info.
11048cfa0ad2SJack F Vogel  **/
11058cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
11068cfa0ad2SJack F Vogel 					u16 *duplex)
11078cfa0ad2SJack F Vogel {
11088cfa0ad2SJack F Vogel 	s32 ret_val;
11098cfa0ad2SJack F Vogel 
11108cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_link_up_info_82575");
11118cfa0ad2SJack F Vogel 
11124edd8523SJack F Vogel 	if (hw->phy.media_type != e1000_media_type_copper)
11138cfa0ad2SJack F Vogel 		ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed,
11148cfa0ad2SJack F Vogel 							       duplex);
11154edd8523SJack F Vogel 	else
11168cfa0ad2SJack F Vogel 		ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
11178cfa0ad2SJack F Vogel 								    duplex);
11188cfa0ad2SJack F Vogel 
11198cfa0ad2SJack F Vogel 	return ret_val;
11208cfa0ad2SJack F Vogel }
11218cfa0ad2SJack F Vogel 
11228cfa0ad2SJack F Vogel /**
11238cfa0ad2SJack F Vogel  *  e1000_check_for_link_82575 - Check for link
11248cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
11258cfa0ad2SJack F Vogel  *
11268cfa0ad2SJack F Vogel  *  If sgmii is enabled, then use the pcs register to determine link, otherwise
11278cfa0ad2SJack F Vogel  *  use the generic interface for determining link.
11288cfa0ad2SJack F Vogel  **/
11298cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82575(struct e1000_hw *hw)
11308cfa0ad2SJack F Vogel {
11318cfa0ad2SJack F Vogel 	s32 ret_val;
11328cfa0ad2SJack F Vogel 	u16 speed, duplex;
11338cfa0ad2SJack F Vogel 
11348cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_check_for_link_82575");
11358cfa0ad2SJack F Vogel 
11364edd8523SJack F Vogel 	if (hw->phy.media_type != e1000_media_type_copper) {
11378cfa0ad2SJack F Vogel 		ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed,
11388cfa0ad2SJack F Vogel 							       &duplex);
1139d035aa2dSJack F Vogel 		/*
1140d035aa2dSJack F Vogel 		 * Use this flag to determine if link needs to be checked or
1141d035aa2dSJack F Vogel 		 * not.  If we have link clear the flag so that we do not
1142d035aa2dSJack F Vogel 		 * continue to check for link.
1143d035aa2dSJack F Vogel 		 */
1144d035aa2dSJack F Vogel 		hw->mac.get_link_status = !hw->mac.serdes_has_link;
1145*ab5d0362SJack F Vogel 
1146d035aa2dSJack F Vogel 	} else {
11478cfa0ad2SJack F Vogel 		ret_val = e1000_check_for_copper_link_generic(hw);
1148d035aa2dSJack F Vogel 	}
11498cfa0ad2SJack F Vogel 
11508cfa0ad2SJack F Vogel 	return ret_val;
11518cfa0ad2SJack F Vogel }
11528cfa0ad2SJack F Vogel 
11538cfa0ad2SJack F Vogel /**
1154a69ed8dfSJack F Vogel  *  e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown
1155a69ed8dfSJack F Vogel  *  @hw: pointer to the HW structure
1156a69ed8dfSJack F Vogel  **/
1157a69ed8dfSJack F Vogel static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw)
1158a69ed8dfSJack F Vogel {
1159a69ed8dfSJack F Vogel 	u32 reg;
1160a69ed8dfSJack F Vogel 
1161a69ed8dfSJack F Vogel 	DEBUGFUNC("e1000_power_up_serdes_link_82575");
1162a69ed8dfSJack F Vogel 
1163a69ed8dfSJack F Vogel 	if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
1164a69ed8dfSJack F Vogel 	    !e1000_sgmii_active_82575(hw))
1165a69ed8dfSJack F Vogel 		return;
1166a69ed8dfSJack F Vogel 
1167a69ed8dfSJack F Vogel 	/* Enable PCS to turn on link */
1168a69ed8dfSJack F Vogel 	reg = E1000_READ_REG(hw, E1000_PCS_CFG0);
1169a69ed8dfSJack F Vogel 	reg |= E1000_PCS_CFG_PCS_EN;
1170a69ed8dfSJack F Vogel 	E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg);
1171a69ed8dfSJack F Vogel 
1172a69ed8dfSJack F Vogel 	/* Power up the laser */
1173a69ed8dfSJack F Vogel 	reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
1174a69ed8dfSJack F Vogel 	reg &= ~E1000_CTRL_EXT_SDP3_DATA;
1175a69ed8dfSJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
1176a69ed8dfSJack F Vogel 
1177a69ed8dfSJack F Vogel 	/* flush the write to verify completion */
1178a69ed8dfSJack F Vogel 	E1000_WRITE_FLUSH(hw);
1179a69ed8dfSJack F Vogel 	msec_delay(1);
1180a69ed8dfSJack F Vogel }
1181a69ed8dfSJack F Vogel 
1182a69ed8dfSJack F Vogel /**
11838cfa0ad2SJack F Vogel  *  e1000_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex
11848cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
11858cfa0ad2SJack F Vogel  *  @speed: stores the current speed
11868cfa0ad2SJack F Vogel  *  @duplex: stores the current duplex
11878cfa0ad2SJack F Vogel  *
11888cfa0ad2SJack F Vogel  *  Using the physical coding sub-layer (PCS), retrieve the current speed and
11898cfa0ad2SJack F Vogel  *  duplex, then store the values in the pointers provided.
11908cfa0ad2SJack F Vogel  **/
11918cfa0ad2SJack F Vogel static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
11928cfa0ad2SJack F Vogel 						u16 *speed, u16 *duplex)
11938cfa0ad2SJack F Vogel {
11948cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
11958cfa0ad2SJack F Vogel 	u32 pcs;
11968cfa0ad2SJack F Vogel 
11978cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575");
11988cfa0ad2SJack F Vogel 
11998cfa0ad2SJack F Vogel 	/*
12008cfa0ad2SJack F Vogel 	 * Read the PCS Status register for link state. For non-copper mode,
12018cfa0ad2SJack F Vogel 	 * the status register is not accurate. The PCS status register is
12028cfa0ad2SJack F Vogel 	 * used instead.
12038cfa0ad2SJack F Vogel 	 */
12048cfa0ad2SJack F Vogel 	pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT);
12058cfa0ad2SJack F Vogel 
12068cfa0ad2SJack F Vogel 	/*
1207*ab5d0362SJack F Vogel 	 * The link up bit determines when link is up on autoneg.
12088cfa0ad2SJack F Vogel 	 */
1209*ab5d0362SJack F Vogel 	if (pcs & E1000_PCS_LSTS_LINK_OK) {
12108cfa0ad2SJack F Vogel 		mac->serdes_has_link = TRUE;
12118cfa0ad2SJack F Vogel 
12128cfa0ad2SJack F Vogel 		/* Detect and store PCS speed */
12134dab5c37SJack F Vogel 		if (pcs & E1000_PCS_LSTS_SPEED_1000)
12148cfa0ad2SJack F Vogel 			*speed = SPEED_1000;
12154dab5c37SJack F Vogel 		else if (pcs & E1000_PCS_LSTS_SPEED_100)
12168cfa0ad2SJack F Vogel 			*speed = SPEED_100;
12174dab5c37SJack F Vogel 		else
12188cfa0ad2SJack F Vogel 			*speed = SPEED_10;
12198cfa0ad2SJack F Vogel 
12208cfa0ad2SJack F Vogel 		/* Detect and store PCS duplex */
12214dab5c37SJack F Vogel 		if (pcs & E1000_PCS_LSTS_DUPLEX_FULL)
12228cfa0ad2SJack F Vogel 			*duplex = FULL_DUPLEX;
12234dab5c37SJack F Vogel 		else
12248cfa0ad2SJack F Vogel 			*duplex = HALF_DUPLEX;
1225*ab5d0362SJack F Vogel 	} else {
1226*ab5d0362SJack F Vogel 		mac->serdes_has_link = FALSE;
1227*ab5d0362SJack F Vogel 		*speed = 0;
1228*ab5d0362SJack F Vogel 		*duplex = 0;
12298cfa0ad2SJack F Vogel 	}
12308cfa0ad2SJack F Vogel 
12318cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
12328cfa0ad2SJack F Vogel }
12338cfa0ad2SJack F Vogel 
12348cfa0ad2SJack F Vogel /**
12354edd8523SJack F Vogel  *  e1000_shutdown_serdes_link_82575 - Remove link during power down
12368cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
12378cfa0ad2SJack F Vogel  *
12384edd8523SJack F Vogel  *  In the case of serdes shut down sfp and PCS on driver unload
12398cfa0ad2SJack F Vogel  *  when management pass thru is not enabled.
12408cfa0ad2SJack F Vogel  **/
12414edd8523SJack F Vogel void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw)
12428cfa0ad2SJack F Vogel {
12438cfa0ad2SJack F Vogel 	u32 reg;
1244a69ed8dfSJack F Vogel 
1245a69ed8dfSJack F Vogel 	DEBUGFUNC("e1000_shutdown_serdes_link_82575");
12468cfa0ad2SJack F Vogel 
12474edd8523SJack F Vogel 	if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
12484edd8523SJack F Vogel 	    !e1000_sgmii_active_82575(hw))
12498cfa0ad2SJack F Vogel 		return;
12508cfa0ad2SJack F Vogel 
1251a69ed8dfSJack F Vogel 	if (!e1000_enable_mng_pass_thru(hw)) {
12528cfa0ad2SJack F Vogel 		/* Disable PCS to turn off link */
12538cfa0ad2SJack F Vogel 		reg = E1000_READ_REG(hw, E1000_PCS_CFG0);
12548cfa0ad2SJack F Vogel 		reg &= ~E1000_PCS_CFG_PCS_EN;
12558cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg);
12568cfa0ad2SJack F Vogel 
12578cfa0ad2SJack F Vogel 		/* shutdown the laser */
12588cfa0ad2SJack F Vogel 		reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
12594edd8523SJack F Vogel 		reg |= E1000_CTRL_EXT_SDP3_DATA;
12608cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
12618cfa0ad2SJack F Vogel 
12624edd8523SJack F Vogel 		/* flush the write to verify completion */
12638cfa0ad2SJack F Vogel 		E1000_WRITE_FLUSH(hw);
12648cfa0ad2SJack F Vogel 		msec_delay(1);
12658cfa0ad2SJack F Vogel 	}
12668cfa0ad2SJack F Vogel 
12678cfa0ad2SJack F Vogel 	return;
12688cfa0ad2SJack F Vogel }
12698cfa0ad2SJack F Vogel 
12708cfa0ad2SJack F Vogel /**
12718cfa0ad2SJack F Vogel  *  e1000_reset_hw_82575 - Reset hardware
12728cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
12738cfa0ad2SJack F Vogel  *
1274daf9197cSJack F Vogel  *  This resets the hardware into a known state.
12758cfa0ad2SJack F Vogel  **/
12768cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
12778cfa0ad2SJack F Vogel {
1278f0ecc46dSJack F Vogel 	u32 ctrl;
12798cfa0ad2SJack F Vogel 	s32 ret_val;
12808cfa0ad2SJack F Vogel 
12818cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_reset_hw_82575");
12828cfa0ad2SJack F Vogel 
12838cfa0ad2SJack F Vogel 	/*
12848cfa0ad2SJack F Vogel 	 * Prevent the PCI-E bus from sticking if there is no TLP connection
12858cfa0ad2SJack F Vogel 	 * on the last TLP read/write transaction when MAC is reset.
12868cfa0ad2SJack F Vogel 	 */
12878cfa0ad2SJack F Vogel 	ret_val = e1000_disable_pcie_master_generic(hw);
12884dab5c37SJack F Vogel 	if (ret_val)
12898cfa0ad2SJack F Vogel 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
12908cfa0ad2SJack F Vogel 
12919d81738fSJack F Vogel 	/* set the completion timeout for interface */
12929d81738fSJack F Vogel 	ret_val = e1000_set_pcie_completion_timeout(hw);
12934dab5c37SJack F Vogel 	if (ret_val)
12949d81738fSJack F Vogel 		DEBUGOUT("PCI-E Set completion timeout has failed.\n");
12959d81738fSJack F Vogel 
12968cfa0ad2SJack F Vogel 	DEBUGOUT("Masking off all interrupts\n");
12978cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
12988cfa0ad2SJack F Vogel 
12998cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
13008cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
13018cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
13028cfa0ad2SJack F Vogel 
13038cfa0ad2SJack F Vogel 	msec_delay(10);
13048cfa0ad2SJack F Vogel 
13058cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
13068cfa0ad2SJack F Vogel 
13078cfa0ad2SJack F Vogel 	DEBUGOUT("Issuing a global reset to MAC\n");
13088cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
13098cfa0ad2SJack F Vogel 
13108cfa0ad2SJack F Vogel 	ret_val = e1000_get_auto_rd_done_generic(hw);
13118cfa0ad2SJack F Vogel 	if (ret_val) {
13128cfa0ad2SJack F Vogel 		/*
13138cfa0ad2SJack F Vogel 		 * When auto config read does not complete, do not
13148cfa0ad2SJack F Vogel 		 * return with an error. This can happen in situations
13158cfa0ad2SJack F Vogel 		 * where there is no eeprom and prevents getting link.
13168cfa0ad2SJack F Vogel 		 */
13178cfa0ad2SJack F Vogel 		DEBUGOUT("Auto Read Done did not complete\n");
13188cfa0ad2SJack F Vogel 	}
13198cfa0ad2SJack F Vogel 
13208cfa0ad2SJack F Vogel 	/* If EEPROM is not present, run manual init scripts */
1321*ab5d0362SJack F Vogel 	if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES))
13228cfa0ad2SJack F Vogel 		e1000_reset_init_script_82575(hw);
13238cfa0ad2SJack F Vogel 
13248cfa0ad2SJack F Vogel 	/* Clear any pending interrupt events. */
13258cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
1326f0ecc46dSJack F Vogel 	E1000_READ_REG(hw, E1000_ICR);
13278cfa0ad2SJack F Vogel 
1328d035aa2dSJack F Vogel 	/* Install any alternate MAC address into RAR0 */
1329d035aa2dSJack F Vogel 	ret_val = e1000_check_alt_mac_addr_generic(hw);
13308cfa0ad2SJack F Vogel 
13318cfa0ad2SJack F Vogel 	return ret_val;
13328cfa0ad2SJack F Vogel }
13338cfa0ad2SJack F Vogel 
13348cfa0ad2SJack F Vogel /**
13358cfa0ad2SJack F Vogel  *  e1000_init_hw_82575 - Initialize hardware
13368cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
13378cfa0ad2SJack F Vogel  *
13388cfa0ad2SJack F Vogel  *  This inits the hardware readying it for operation.
13398cfa0ad2SJack F Vogel  **/
13408cfa0ad2SJack F Vogel static s32 e1000_init_hw_82575(struct e1000_hw *hw)
13418cfa0ad2SJack F Vogel {
13428cfa0ad2SJack F Vogel 	struct e1000_mac_info *mac = &hw->mac;
13438cfa0ad2SJack F Vogel 	s32 ret_val;
13448cfa0ad2SJack F Vogel 	u16 i, rar_count = mac->rar_entry_count;
13458cfa0ad2SJack F Vogel 
13468cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_init_hw_82575");
13478cfa0ad2SJack F Vogel 
13488cfa0ad2SJack F Vogel 	/* Initialize identification LED */
1349d035aa2dSJack F Vogel 	ret_val = mac->ops.id_led_init(hw);
13508cfa0ad2SJack F Vogel 	if (ret_val) {
13518cfa0ad2SJack F Vogel 		DEBUGOUT("Error initializing identification LED\n");
13528cfa0ad2SJack F Vogel 		/* This is not fatal and we should not stop init due to this */
13538cfa0ad2SJack F Vogel 	}
13548cfa0ad2SJack F Vogel 
13558cfa0ad2SJack F Vogel 	/* Disabling VLAN filtering */
13568cfa0ad2SJack F Vogel 	DEBUGOUT("Initializing the IEEE VLAN\n");
13578cfa0ad2SJack F Vogel 	mac->ops.clear_vfta(hw);
13588cfa0ad2SJack F Vogel 
13598cfa0ad2SJack F Vogel 	/* Setup the receive address */
1360d035aa2dSJack F Vogel 	e1000_init_rx_addrs_generic(hw, rar_count);
1361d035aa2dSJack F Vogel 
13628cfa0ad2SJack F Vogel 	/* Zero out the Multicast HASH table */
13638cfa0ad2SJack F Vogel 	DEBUGOUT("Zeroing the MTA\n");
13648cfa0ad2SJack F Vogel 	for (i = 0; i < mac->mta_reg_count; i++)
13658cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
13668cfa0ad2SJack F Vogel 
13674edd8523SJack F Vogel 	/* Zero out the Unicast HASH table */
13684edd8523SJack F Vogel 	DEBUGOUT("Zeroing the UTA\n");
13694edd8523SJack F Vogel 	for (i = 0; i < mac->uta_reg_count; i++)
13704edd8523SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0);
13714edd8523SJack F Vogel 
13728cfa0ad2SJack F Vogel 	/* Setup link and flow control */
13738cfa0ad2SJack F Vogel 	ret_val = mac->ops.setup_link(hw);
13748cfa0ad2SJack F Vogel 
13754dab5c37SJack F Vogel 	/* Set the default MTU size */
13764dab5c37SJack F Vogel 	hw->dev_spec._82575.mtu = 1500;
13774dab5c37SJack F Vogel 
13788cfa0ad2SJack F Vogel 	/*
13798cfa0ad2SJack F Vogel 	 * Clear all of the statistics registers (clear on read).  It is
13808cfa0ad2SJack F Vogel 	 * important that we do this after we have tried to establish link
13818cfa0ad2SJack F Vogel 	 * because the symbol error count will increment wildly if there
13828cfa0ad2SJack F Vogel 	 * is no link.
13838cfa0ad2SJack F Vogel 	 */
13848cfa0ad2SJack F Vogel 	e1000_clear_hw_cntrs_82575(hw);
13858cfa0ad2SJack F Vogel 
13868cfa0ad2SJack F Vogel 	return ret_val;
13878cfa0ad2SJack F Vogel }
13888cfa0ad2SJack F Vogel 
13898cfa0ad2SJack F Vogel /**
13908cfa0ad2SJack F Vogel  *  e1000_setup_copper_link_82575 - Configure copper link settings
13918cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
13928cfa0ad2SJack F Vogel  *
13938cfa0ad2SJack F Vogel  *  Configures the link for auto-neg or forced speed and duplex.  Then we check
13948cfa0ad2SJack F Vogel  *  for link, once link is established calls to configure collision distance
13958cfa0ad2SJack F Vogel  *  and flow control are called.
13968cfa0ad2SJack F Vogel  **/
13978cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
13988cfa0ad2SJack F Vogel {
13999d81738fSJack F Vogel 	u32 ctrl;
14008cfa0ad2SJack F Vogel 	s32  ret_val;
14018cfa0ad2SJack F Vogel 
14028cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_setup_copper_link_82575");
14038cfa0ad2SJack F Vogel 
14048cfa0ad2SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
14058cfa0ad2SJack F Vogel 	ctrl |= E1000_CTRL_SLU;
14068cfa0ad2SJack F Vogel 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
14078cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
14088cfa0ad2SJack F Vogel 
14094edd8523SJack F Vogel 	ret_val = e1000_setup_serdes_link_82575(hw);
14104edd8523SJack F Vogel 	if (ret_val)
14114edd8523SJack F Vogel 		goto out;
14124edd8523SJack F Vogel 
14134dab5c37SJack F Vogel 	if (e1000_sgmii_active_82575(hw)) {
14144edd8523SJack F Vogel 		/* allow time for SFP cage time to power up phy */
14154edd8523SJack F Vogel 		msec_delay(300);
14164edd8523SJack F Vogel 
14174edd8523SJack F Vogel 		ret_val = hw->phy.ops.reset(hw);
14184edd8523SJack F Vogel 		if (ret_val) {
14194edd8523SJack F Vogel 			DEBUGOUT("Error resetting the PHY.\n");
14204edd8523SJack F Vogel 			goto out;
14214edd8523SJack F Vogel 		}
14224edd8523SJack F Vogel 	}
14238cfa0ad2SJack F Vogel 	switch (hw->phy.type) {
1424*ab5d0362SJack F Vogel 	case e1000_phy_i210:
14258cfa0ad2SJack F Vogel 	case e1000_phy_m88:
1426f0ecc46dSJack F Vogel 		if (hw->phy.id == I347AT4_E_PHY_ID ||
14271fd3c44fSJack F Vogel 		    hw->phy.id == M88E1112_E_PHY_ID ||
14281fd3c44fSJack F Vogel 		    hw->phy.id == M88E1340M_E_PHY_ID)
1429f0ecc46dSJack F Vogel 			ret_val = e1000_copper_link_setup_m88_gen2(hw);
1430f0ecc46dSJack F Vogel 		else
14318cfa0ad2SJack F Vogel 			ret_val = e1000_copper_link_setup_m88(hw);
14328cfa0ad2SJack F Vogel 		break;
14338cfa0ad2SJack F Vogel 	case e1000_phy_igp_3:
14348cfa0ad2SJack F Vogel 		ret_val = e1000_copper_link_setup_igp(hw);
14358cfa0ad2SJack F Vogel 		break;
14364edd8523SJack F Vogel 	case e1000_phy_82580:
14374edd8523SJack F Vogel 		ret_val = e1000_copper_link_setup_82577(hw);
14384edd8523SJack F Vogel 		break;
14398cfa0ad2SJack F Vogel 	default:
14408cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PHY;
14418cfa0ad2SJack F Vogel 		break;
14428cfa0ad2SJack F Vogel 	}
14438cfa0ad2SJack F Vogel 
14448cfa0ad2SJack F Vogel 	if (ret_val)
14458cfa0ad2SJack F Vogel 		goto out;
14468cfa0ad2SJack F Vogel 
14474edd8523SJack F Vogel 	ret_val = e1000_setup_copper_link_generic(hw);
14488cfa0ad2SJack F Vogel out:
14498cfa0ad2SJack F Vogel 	return ret_val;
14508cfa0ad2SJack F Vogel }
14518cfa0ad2SJack F Vogel 
14528cfa0ad2SJack F Vogel /**
14534edd8523SJack F Vogel  *  e1000_setup_serdes_link_82575 - Setup link for serdes
14548cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
14558cfa0ad2SJack F Vogel  *
14564edd8523SJack F Vogel  *  Configure the physical coding sub-layer (PCS) link.  The PCS link is
14574edd8523SJack F Vogel  *  used on copper connections where the serialized gigabit media independent
14584edd8523SJack F Vogel  *  interface (sgmii), or serdes fiber is being used.  Configures the link
14594edd8523SJack F Vogel  *  for auto-negotiation or forces speed/duplex.
14608cfa0ad2SJack F Vogel  **/
14614edd8523SJack F Vogel static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
14628cfa0ad2SJack F Vogel {
14634edd8523SJack F Vogel 	u32 ctrl_ext, ctrl_reg, reg;
14644edd8523SJack F Vogel 	bool pcs_autoneg;
14654dab5c37SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
14664dab5c37SJack F Vogel 	u16 data;
14678cfa0ad2SJack F Vogel 
14684edd8523SJack F Vogel 	DEBUGFUNC("e1000_setup_serdes_link_82575");
14694edd8523SJack F Vogel 
14704edd8523SJack F Vogel 	if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
14714edd8523SJack F Vogel 	    !e1000_sgmii_active_82575(hw))
14724dab5c37SJack F Vogel 		return ret_val;
14738cfa0ad2SJack F Vogel 
14748cfa0ad2SJack F Vogel 	/*
14758cfa0ad2SJack F Vogel 	 * On the 82575, SerDes loopback mode persists until it is
14768cfa0ad2SJack F Vogel 	 * explicitly turned off or a power cycle is performed.  A read to
14778cfa0ad2SJack F Vogel 	 * the register does not indicate its status.  Therefore, we ensure
14788cfa0ad2SJack F Vogel 	 * loopback mode is disabled during initialization.
14798cfa0ad2SJack F Vogel 	 */
14808cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
14818cfa0ad2SJack F Vogel 
14824edd8523SJack F Vogel 	/* power on the sfp cage if present */
14834edd8523SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
14844edd8523SJack F Vogel 	ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA;
14854edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
14864edd8523SJack F Vogel 
14874edd8523SJack F Vogel 	ctrl_reg = E1000_READ_REG(hw, E1000_CTRL);
14884edd8523SJack F Vogel 	ctrl_reg |= E1000_CTRL_SLU;
14894edd8523SJack F Vogel 
1490a69ed8dfSJack F Vogel 	/* set both sw defined pins on 82575/82576*/
1491a69ed8dfSJack F Vogel 	if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576)
14924edd8523SJack F Vogel 		ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1;
14938cfa0ad2SJack F Vogel 
14944edd8523SJack F Vogel 	reg = E1000_READ_REG(hw, E1000_PCS_LCTL);
14954edd8523SJack F Vogel 
14964edd8523SJack F Vogel 	/* default pcs_autoneg to the same setting as mac autoneg */
14974edd8523SJack F Vogel 	pcs_autoneg = hw->mac.autoneg;
14984edd8523SJack F Vogel 
14994edd8523SJack F Vogel 	switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
15004edd8523SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_SGMII:
15014edd8523SJack F Vogel 		/* sgmii mode lets the phy handle forcing speed/duplex */
15024edd8523SJack F Vogel 		pcs_autoneg = TRUE;
15034edd8523SJack F Vogel 		/* autoneg time out should be disabled for SGMII mode */
15044edd8523SJack F Vogel 		reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT);
15054edd8523SJack F Vogel 		break;
15064edd8523SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
15074edd8523SJack F Vogel 		/* disable PCS autoneg and support parallel detect only */
15084edd8523SJack F Vogel 		pcs_autoneg = FALSE;
15097d9119bdSJack F Vogel 		/* fall through to default case */
15104edd8523SJack F Vogel 	default:
15114dab5c37SJack F Vogel 		if (hw->mac.type == e1000_82575 ||
15124dab5c37SJack F Vogel 		    hw->mac.type == e1000_82576) {
15134dab5c37SJack F Vogel 			ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data);
15144dab5c37SJack F Vogel 			if (ret_val) {
15154dab5c37SJack F Vogel 				DEBUGOUT("NVM Read Error\n");
15164dab5c37SJack F Vogel 				return ret_val;
15174dab5c37SJack F Vogel 			}
15184dab5c37SJack F Vogel 
15194dab5c37SJack F Vogel 			if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT)
15204dab5c37SJack F Vogel 				pcs_autoneg = FALSE;
15214dab5c37SJack F Vogel 		}
15224dab5c37SJack F Vogel 
15234edd8523SJack F Vogel 		/*
15244edd8523SJack F Vogel 		 * non-SGMII modes only supports a speed of 1000/Full for the
15254edd8523SJack F Vogel 		 * link so it is best to just force the MAC and let the pcs
15264edd8523SJack F Vogel 		 * link either autoneg or be forced to 1000/Full
15274edd8523SJack F Vogel 		 */
15284edd8523SJack F Vogel 		ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD |
15294edd8523SJack F Vogel 			    E1000_CTRL_FD | E1000_CTRL_FRCDPX;
15304edd8523SJack F Vogel 
15314edd8523SJack F Vogel 		/* set speed of 1000/Full if speed/duplex is forced */
15324edd8523SJack F Vogel 		reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL;
15334edd8523SJack F Vogel 		break;
15344edd8523SJack F Vogel 	}
15354edd8523SJack F Vogel 
15364edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg);
15378cfa0ad2SJack F Vogel 
15388cfa0ad2SJack F Vogel 	/*
15398cfa0ad2SJack F Vogel 	 * New SerDes mode allows for forcing speed or autonegotiating speed
15408cfa0ad2SJack F Vogel 	 * at 1gb. Autoneg should be default set by most drivers. This is the
15418cfa0ad2SJack F Vogel 	 * mode that will be compatible with older link partners and switches.
15428cfa0ad2SJack F Vogel 	 * However, both are supported by the hardware and some drivers/tools.
15438cfa0ad2SJack F Vogel 	 */
15448cfa0ad2SJack F Vogel 	reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
15458cfa0ad2SJack F Vogel 		 E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
15468cfa0ad2SJack F Vogel 
15474edd8523SJack F Vogel 	/*
15484edd8523SJack F Vogel 	 * We force flow control to prevent the CTRL register values from being
15494edd8523SJack F Vogel 	 * overwritten by the autonegotiated flow control values
15504edd8523SJack F Vogel 	 */
15518cfa0ad2SJack F Vogel 	reg |= E1000_PCS_LCTL_FORCE_FCTRL;
15524edd8523SJack F Vogel 
15534edd8523SJack F Vogel 	if (pcs_autoneg) {
15544edd8523SJack F Vogel 		/* Set PCS register for autoneg */
15554edd8523SJack F Vogel 		reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */
15564edd8523SJack F Vogel 		       E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */
15574edd8523SJack F Vogel 		DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
15584edd8523SJack F Vogel 	} else {
15594edd8523SJack F Vogel 		/* Set PCS register for forced link */
1560a69ed8dfSJack F Vogel 		reg |= E1000_PCS_LCTL_FSD;	/* Force Speed */
15614edd8523SJack F Vogel 		DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
15628cfa0ad2SJack F Vogel 	}
15638cfa0ad2SJack F Vogel 
15648cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg);
15658cfa0ad2SJack F Vogel 
15664edd8523SJack F Vogel 	if (!e1000_sgmii_active_82575(hw))
15674edd8523SJack F Vogel 		e1000_force_mac_fc_generic(hw);
15684edd8523SJack F Vogel 
15694dab5c37SJack F Vogel 	return ret_val;
15704dab5c37SJack F Vogel }
15714dab5c37SJack F Vogel 
15724dab5c37SJack F Vogel /**
15734dab5c37SJack F Vogel  *  e1000_get_media_type_82575 - derives current media type.
15744dab5c37SJack F Vogel  *  @hw: pointer to the HW structure
15754dab5c37SJack F Vogel  *
15764dab5c37SJack F Vogel  *  The media type is chosen reflecting few settings.
15774dab5c37SJack F Vogel  *  The following are taken into account:
15784dab5c37SJack F Vogel  *  - link mode set in the current port Init Control Word #3
15794dab5c37SJack F Vogel  *  - current link mode settings in CSR register
15804dab5c37SJack F Vogel  *  - MDIO vs. I2C PHY control interface chosen
15814dab5c37SJack F Vogel  *  - SFP module media type
15824dab5c37SJack F Vogel  **/
15834dab5c37SJack F Vogel static s32 e1000_get_media_type_82575(struct e1000_hw *hw)
15844dab5c37SJack F Vogel {
15854dab5c37SJack F Vogel 	u32 lan_id = 0;
15864dab5c37SJack F Vogel 	s32 ret_val = E1000_ERR_CONFIG;
15874dab5c37SJack F Vogel 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
15884dab5c37SJack F Vogel 	u32 ctrl_ext = 0;
15894dab5c37SJack F Vogel 	u32 current_link_mode = 0;
15904dab5c37SJack F Vogel 	u16 init_ctrl_wd_3 = 0;
15914dab5c37SJack F Vogel 	u8 init_ctrl_wd_3_offset = 0;
15924dab5c37SJack F Vogel 	u8 init_ctrl_wd_3_bit_offset = 0;
15934dab5c37SJack F Vogel 
15944dab5c37SJack F Vogel 	/* Set internal phy as default */
15954dab5c37SJack F Vogel 	dev_spec->sgmii_active = FALSE;
15964dab5c37SJack F Vogel 	dev_spec->module_plugged = FALSE;
15974dab5c37SJack F Vogel 
15984dab5c37SJack F Vogel 	/*
15994dab5c37SJack F Vogel 	 * Check if NVM access method is attached already.
16004dab5c37SJack F Vogel 	 * If it is then Init Control Word #3 is considered
16014dab5c37SJack F Vogel 	 * otherwise runtime CSR register content is taken.
16024dab5c37SJack F Vogel 	 */
16034dab5c37SJack F Vogel 
16044dab5c37SJack F Vogel 	/* Get CSR setting */
16054dab5c37SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
16064dab5c37SJack F Vogel 
16074dab5c37SJack F Vogel 	/* Get link mode setting */
16084dab5c37SJack F Vogel 	if ((hw->nvm.ops.read) && (hw->nvm.ops.read != e1000_null_read_nvm)) {
16094dab5c37SJack F Vogel 		/* Take link mode from EEPROM */
16104dab5c37SJack F Vogel 
16114dab5c37SJack F Vogel 		/*
16124dab5c37SJack F Vogel 		 * Get LAN port ID to derive its
16134dab5c37SJack F Vogel 		 * adequate Init Control Word #3
16144dab5c37SJack F Vogel 		 */
16154dab5c37SJack F Vogel 		lan_id = ((E1000_READ_REG(hw, E1000_STATUS) &
16164dab5c37SJack F Vogel 		      E1000_STATUS_LAN_ID_MASK) >> E1000_STATUS_LAN_ID_OFFSET);
16174dab5c37SJack F Vogel 		/*
16184dab5c37SJack F Vogel 		 * Derive Init Control Word #3 offset
16194dab5c37SJack F Vogel 		 * and mask to pick up link mode setting.
16204dab5c37SJack F Vogel 		 */
16214dab5c37SJack F Vogel 		if (hw->mac.type < e1000_82580) {
16224dab5c37SJack F Vogel 			init_ctrl_wd_3_offset = lan_id ?
16234dab5c37SJack F Vogel 			   NVM_INIT_CONTROL3_PORT_A : NVM_INIT_CONTROL3_PORT_B;
16244dab5c37SJack F Vogel 			init_ctrl_wd_3_bit_offset = NVM_WORD24_LNK_MODE_OFFSET;
16254dab5c37SJack F Vogel 		} else {
16264dab5c37SJack F Vogel 			init_ctrl_wd_3_offset =
16274dab5c37SJack F Vogel 					    NVM_82580_LAN_FUNC_OFFSET(lan_id) +
16284dab5c37SJack F Vogel 					    NVM_INIT_CONTROL3_PORT_A;
16294dab5c37SJack F Vogel 			init_ctrl_wd_3_bit_offset =
16304dab5c37SJack F Vogel 					      NVM_WORD24_82580_LNK_MODE_OFFSET;
16314dab5c37SJack F Vogel 		}
16324dab5c37SJack F Vogel 		/* Read Init Control Word #3*/
16334dab5c37SJack F Vogel 		hw->nvm.ops.read(hw, init_ctrl_wd_3_offset, 1, &init_ctrl_wd_3);
16344dab5c37SJack F Vogel 
16354dab5c37SJack F Vogel 		/*
16364dab5c37SJack F Vogel 		 * Align link mode bits to
16374dab5c37SJack F Vogel 		 * their CTRL_EXT location.
16384dab5c37SJack F Vogel 		 */
1639*ab5d0362SJack F Vogel 		current_link_mode = init_ctrl_wd_3;
16404dab5c37SJack F Vogel 		current_link_mode <<= (E1000_CTRL_EXT_LINK_MODE_OFFSET -
16414dab5c37SJack F Vogel 				       init_ctrl_wd_3_bit_offset);
16424dab5c37SJack F Vogel 		current_link_mode &= E1000_CTRL_EXT_LINK_MODE_MASK;
16434dab5c37SJack F Vogel 
1644*ab5d0362SJack F Vogel 		/*
1645*ab5d0362SJack F Vogel 		 * Switch to CSR for all but internal PHY.
1646*ab5d0362SJack F Vogel 		 */
1647*ab5d0362SJack F Vogel 		if (current_link_mode != E1000_CTRL_EXT_LINK_MODE_GMII)
1648*ab5d0362SJack F Vogel 			/* Take link mode from CSR */
1649*ab5d0362SJack F Vogel 			current_link_mode = ctrl_ext &
1650*ab5d0362SJack F Vogel 					    E1000_CTRL_EXT_LINK_MODE_MASK;
1651*ab5d0362SJack F Vogel 	} else {
1652*ab5d0362SJack F Vogel 		/* Take link mode from CSR */
1653*ab5d0362SJack F Vogel 		current_link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK;
1654*ab5d0362SJack F Vogel 	}
1655*ab5d0362SJack F Vogel 
16564dab5c37SJack F Vogel 	switch (current_link_mode) {
16574dab5c37SJack F Vogel 
16584dab5c37SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
16594dab5c37SJack F Vogel 		hw->phy.media_type = e1000_media_type_internal_serdes;
16604dab5c37SJack F Vogel 		current_link_mode = E1000_CTRL_EXT_LINK_MODE_1000BASE_KX;
16614dab5c37SJack F Vogel 		break;
16624dab5c37SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_GMII:
16634dab5c37SJack F Vogel 		hw->phy.media_type = e1000_media_type_copper;
16644dab5c37SJack F Vogel 		current_link_mode = E1000_CTRL_EXT_LINK_MODE_GMII;
16654dab5c37SJack F Vogel 		break;
16664dab5c37SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_SGMII:
16674dab5c37SJack F Vogel 	case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
16684dab5c37SJack F Vogel 		/* Get phy control interface type set (MDIO vs. I2C)*/
16694dab5c37SJack F Vogel 		if (e1000_sgmii_uses_mdio_82575(hw)) {
16704dab5c37SJack F Vogel 			hw->phy.media_type = e1000_media_type_copper;
16714dab5c37SJack F Vogel 			dev_spec->sgmii_active = TRUE;
16724dab5c37SJack F Vogel 			current_link_mode = E1000_CTRL_EXT_LINK_MODE_SGMII;
16734dab5c37SJack F Vogel 		} else {
16744dab5c37SJack F Vogel 			ret_val = e1000_set_sfp_media_type_82575(hw);
16754dab5c37SJack F Vogel 			if (ret_val != E1000_SUCCESS)
16764dab5c37SJack F Vogel 				goto out;
16774dab5c37SJack F Vogel 			if (hw->phy.media_type ==
16784dab5c37SJack F Vogel 				e1000_media_type_internal_serdes) {
16794dab5c37SJack F Vogel 				current_link_mode =
16804dab5c37SJack F Vogel 					 E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
16814dab5c37SJack F Vogel 			} else if (hw->phy.media_type ==
16824dab5c37SJack F Vogel 				e1000_media_type_copper) {
16834dab5c37SJack F Vogel 				current_link_mode =
16844dab5c37SJack F Vogel 					       E1000_CTRL_EXT_LINK_MODE_SGMII;
16854dab5c37SJack F Vogel 			}
16864dab5c37SJack F Vogel 		}
16874dab5c37SJack F Vogel 		break;
16884dab5c37SJack F Vogel 	default:
16894dab5c37SJack F Vogel 		DEBUGOUT("Link mode mask doesn't fit bit field size\n");
16904dab5c37SJack F Vogel 		goto out;
16914dab5c37SJack F Vogel 	}
16924dab5c37SJack F Vogel 	/*
16934dab5c37SJack F Vogel 	 * Do not change current link mode setting
16944dab5c37SJack F Vogel 	 * if media type is fibre or has not been
16954dab5c37SJack F Vogel 	 * recognized.
16964dab5c37SJack F Vogel 	 */
16974dab5c37SJack F Vogel 	if ((hw->phy.media_type != e1000_media_type_unknown) &&
16984dab5c37SJack F Vogel 	    (hw->phy.media_type != e1000_media_type_fiber)) {
16994dab5c37SJack F Vogel 		/* Update link mode */
17004dab5c37SJack F Vogel 		ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
17014dab5c37SJack F Vogel 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext |
17024dab5c37SJack F Vogel 				current_link_mode);
17034dab5c37SJack F Vogel 	}
17044dab5c37SJack F Vogel 
17054dab5c37SJack F Vogel 	ret_val = E1000_SUCCESS;
17064dab5c37SJack F Vogel out:
17074dab5c37SJack F Vogel 	/*
17084dab5c37SJack F Vogel 	 * If media type was not identified then return media type
17094dab5c37SJack F Vogel 	 * defined by the CTRL_EXT settings.
17104dab5c37SJack F Vogel 	 */
17114dab5c37SJack F Vogel 	if (hw->phy.media_type == e1000_media_type_unknown) {
17124dab5c37SJack F Vogel 		if (current_link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII)
17134dab5c37SJack F Vogel 			hw->phy.media_type = e1000_media_type_copper;
17144dab5c37SJack F Vogel 		else
17154dab5c37SJack F Vogel 			hw->phy.media_type = e1000_media_type_internal_serdes;
17164dab5c37SJack F Vogel 	}
17174dab5c37SJack F Vogel 
17184dab5c37SJack F Vogel 	return ret_val;
17194dab5c37SJack F Vogel }
17204dab5c37SJack F Vogel 
17214dab5c37SJack F Vogel /**
17224dab5c37SJack F Vogel  *  e1000_set_sfp_media_type_82575 - derives SFP module media type.
17234dab5c37SJack F Vogel  *  @hw: pointer to the HW structure
17244dab5c37SJack F Vogel  *
17254dab5c37SJack F Vogel  *  The media type is chosen based on SFP module.
17264dab5c37SJack F Vogel  *  compatibility flags retrieved from SFP ID EEPROM.
17274dab5c37SJack F Vogel  **/
17284dab5c37SJack F Vogel static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw)
17294dab5c37SJack F Vogel {
17304dab5c37SJack F Vogel 	s32 ret_val = E1000_ERR_CONFIG;
17314dab5c37SJack F Vogel 	u32 ctrl_ext = 0;
17324dab5c37SJack F Vogel 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
17334dab5c37SJack F Vogel 	struct sfp_e1000_flags eth_flags = {0};
17344dab5c37SJack F Vogel 	u8 tranceiver_type = 0;
17354dab5c37SJack F Vogel 
17364dab5c37SJack F Vogel 	/* Turn I2C interface ON */
17374dab5c37SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
17384dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA);
17394dab5c37SJack F Vogel 
17404dab5c37SJack F Vogel 	/* Read SFP module data */
17414dab5c37SJack F Vogel 	ret_val = e1000_read_sfp_data_byte(hw,
17424dab5c37SJack F Vogel 			E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET),
17434dab5c37SJack F Vogel 			&tranceiver_type);
17444dab5c37SJack F Vogel 	if (ret_val != E1000_SUCCESS)
17454dab5c37SJack F Vogel 		goto out;
17464dab5c37SJack F Vogel 	ret_val = e1000_read_sfp_data_byte(hw,
17474dab5c37SJack F Vogel 			E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET),
17484dab5c37SJack F Vogel 			(u8 *)&eth_flags);
17494dab5c37SJack F Vogel 	if (ret_val != E1000_SUCCESS)
17504dab5c37SJack F Vogel 		goto out;
17514dab5c37SJack F Vogel 	/*
17524dab5c37SJack F Vogel 	 * Check if there is some SFP
17534dab5c37SJack F Vogel 	 * module plugged and powered
17544dab5c37SJack F Vogel 	 */
17554dab5c37SJack F Vogel 	if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) ||
17564dab5c37SJack F Vogel 	    (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) {
17574dab5c37SJack F Vogel 		dev_spec->module_plugged = TRUE;
17584dab5c37SJack F Vogel 		if (eth_flags.e1000_base_lx || eth_flags.e1000_base_sx) {
17594dab5c37SJack F Vogel 			hw->phy.media_type = e1000_media_type_internal_serdes;
17604dab5c37SJack F Vogel 		} else if (eth_flags.e1000_base_t) {
17614dab5c37SJack F Vogel 			dev_spec->sgmii_active = TRUE;
17624dab5c37SJack F Vogel 			hw->phy.media_type = e1000_media_type_copper;
17634dab5c37SJack F Vogel 		} else {
17644dab5c37SJack F Vogel 				hw->phy.media_type = e1000_media_type_unknown;
17654dab5c37SJack F Vogel 				DEBUGOUT("PHY module has not been recognized\n");
17664dab5c37SJack F Vogel 				goto out;
17674dab5c37SJack F Vogel 		}
17684dab5c37SJack F Vogel 	} else {
17694dab5c37SJack F Vogel 		hw->phy.media_type = e1000_media_type_unknown;
17704dab5c37SJack F Vogel 	}
17714dab5c37SJack F Vogel 	ret_val = E1000_SUCCESS;
17724dab5c37SJack F Vogel out:
17734dab5c37SJack F Vogel 	/* Restore I2C interface setting */
17744dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
17754dab5c37SJack F Vogel 	return ret_val;
17768cfa0ad2SJack F Vogel }
17778cfa0ad2SJack F Vogel 
17788cfa0ad2SJack F Vogel /**
17798cfa0ad2SJack F Vogel  *  e1000_valid_led_default_82575 - Verify a valid default LED config
17808cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
17818cfa0ad2SJack F Vogel  *  @data: pointer to the NVM (EEPROM)
17828cfa0ad2SJack F Vogel  *
17838cfa0ad2SJack F Vogel  *  Read the EEPROM for the current default LED configuration.  If the
17848cfa0ad2SJack F Vogel  *  LED configuration is not valid, set to a valid LED configuration.
17858cfa0ad2SJack F Vogel  **/
17868cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data)
17878cfa0ad2SJack F Vogel {
17888cfa0ad2SJack F Vogel 	s32 ret_val;
17898cfa0ad2SJack F Vogel 
17908cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_valid_led_default_82575");
17918cfa0ad2SJack F Vogel 
17928cfa0ad2SJack F Vogel 	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
17938cfa0ad2SJack F Vogel 	if (ret_val) {
17948cfa0ad2SJack F Vogel 		DEBUGOUT("NVM Read Error\n");
17958cfa0ad2SJack F Vogel 		goto out;
17968cfa0ad2SJack F Vogel 	}
17978cfa0ad2SJack F Vogel 
17988cfa0ad2SJack F Vogel 	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
17998cfa0ad2SJack F Vogel 		switch (hw->phy.media_type) {
18008cfa0ad2SJack F Vogel 		case e1000_media_type_internal_serdes:
18018cfa0ad2SJack F Vogel 			*data = ID_LED_DEFAULT_82575_SERDES;
18028cfa0ad2SJack F Vogel 			break;
18038cfa0ad2SJack F Vogel 		case e1000_media_type_copper:
18048cfa0ad2SJack F Vogel 		default:
18058cfa0ad2SJack F Vogel 			*data = ID_LED_DEFAULT;
18068cfa0ad2SJack F Vogel 			break;
18078cfa0ad2SJack F Vogel 		}
18088cfa0ad2SJack F Vogel 	}
18098cfa0ad2SJack F Vogel out:
18108cfa0ad2SJack F Vogel 	return ret_val;
18118cfa0ad2SJack F Vogel }
18128cfa0ad2SJack F Vogel 
18138cfa0ad2SJack F Vogel /**
18148cfa0ad2SJack F Vogel  *  e1000_sgmii_active_82575 - Return sgmii state
18158cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
18168cfa0ad2SJack F Vogel  *
18178cfa0ad2SJack F Vogel  *  82575 silicon has a serialized gigabit media independent interface (sgmii)
18188cfa0ad2SJack F Vogel  *  which can be enabled for use in the embedded applications.  Simply
18198cfa0ad2SJack F Vogel  *  return the current state of the sgmii interface.
18208cfa0ad2SJack F Vogel  **/
18218cfa0ad2SJack F Vogel static bool e1000_sgmii_active_82575(struct e1000_hw *hw)
18228cfa0ad2SJack F Vogel {
1823daf9197cSJack F Vogel 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
1824daf9197cSJack F Vogel 	return dev_spec->sgmii_active;
18258cfa0ad2SJack F Vogel }
18268cfa0ad2SJack F Vogel 
18278cfa0ad2SJack F Vogel /**
18288cfa0ad2SJack F Vogel  *  e1000_reset_init_script_82575 - Inits HW defaults after reset
18298cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
18308cfa0ad2SJack F Vogel  *
18318cfa0ad2SJack F Vogel  *  Inits recommended HW defaults after a reset when there is no EEPROM
18328cfa0ad2SJack F Vogel  *  detected. This is only for the 82575.
18338cfa0ad2SJack F Vogel  **/
18348cfa0ad2SJack F Vogel static s32 e1000_reset_init_script_82575(struct e1000_hw *hw)
18358cfa0ad2SJack F Vogel {
18368cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_reset_init_script_82575");
18378cfa0ad2SJack F Vogel 
18388cfa0ad2SJack F Vogel 	if (hw->mac.type == e1000_82575) {
18398cfa0ad2SJack F Vogel 		DEBUGOUT("Running reset init script for 82575\n");
18408cfa0ad2SJack F Vogel 		/* SerDes configuration via SERDESCTRL */
18418cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C);
18428cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78);
18438cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23);
18448cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15);
18458cfa0ad2SJack F Vogel 
18468cfa0ad2SJack F Vogel 		/* CCM configuration via CCMCTL register */
18478cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00);
18488cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00);
18498cfa0ad2SJack F Vogel 
18508cfa0ad2SJack F Vogel 		/* PCIe lanes configuration */
18518cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC);
18528cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF);
18538cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05);
18548cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81);
18558cfa0ad2SJack F Vogel 
18568cfa0ad2SJack F Vogel 		/* PCIe PLL Configuration */
18578cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47);
18588cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00);
18598cfa0ad2SJack F Vogel 		e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00);
18608cfa0ad2SJack F Vogel 	}
18618cfa0ad2SJack F Vogel 
18628cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
18638cfa0ad2SJack F Vogel }
18648cfa0ad2SJack F Vogel 
18658cfa0ad2SJack F Vogel /**
18668cfa0ad2SJack F Vogel  *  e1000_read_mac_addr_82575 - Read device MAC address
18678cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
18688cfa0ad2SJack F Vogel  **/
18698cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw)
18708cfa0ad2SJack F Vogel {
18718cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
18728cfa0ad2SJack F Vogel 
18738cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_read_mac_addr_82575");
1874d035aa2dSJack F Vogel 
1875d035aa2dSJack F Vogel 	/*
1876d035aa2dSJack F Vogel 	 * If there's an alternate MAC address place it in RAR0
1877d035aa2dSJack F Vogel 	 * so that it will override the Si installed default perm
1878d035aa2dSJack F Vogel 	 * address.
1879d035aa2dSJack F Vogel 	 */
1880d035aa2dSJack F Vogel 	ret_val = e1000_check_alt_mac_addr_generic(hw);
1881d035aa2dSJack F Vogel 	if (ret_val)
1882d035aa2dSJack F Vogel 		goto out;
1883d035aa2dSJack F Vogel 
18848cfa0ad2SJack F Vogel 	ret_val = e1000_read_mac_addr_generic(hw);
18858cfa0ad2SJack F Vogel 
1886d035aa2dSJack F Vogel out:
18878cfa0ad2SJack F Vogel 	return ret_val;
18888cfa0ad2SJack F Vogel }
18898cfa0ad2SJack F Vogel 
18908cfa0ad2SJack F Vogel /**
1891a69ed8dfSJack F Vogel  *  e1000_config_collision_dist_82575 - Configure collision distance
1892a69ed8dfSJack F Vogel  *  @hw: pointer to the HW structure
1893a69ed8dfSJack F Vogel  *
1894a69ed8dfSJack F Vogel  *  Configures the collision distance to the default value and is used
1895a69ed8dfSJack F Vogel  *  during link setup.
1896a69ed8dfSJack F Vogel  **/
1897a69ed8dfSJack F Vogel static void e1000_config_collision_dist_82575(struct e1000_hw *hw)
1898a69ed8dfSJack F Vogel {
1899a69ed8dfSJack F Vogel 	u32 tctl_ext;
1900a69ed8dfSJack F Vogel 
1901a69ed8dfSJack F Vogel 	DEBUGFUNC("e1000_config_collision_dist_82575");
1902a69ed8dfSJack F Vogel 
1903a69ed8dfSJack F Vogel 	tctl_ext = E1000_READ_REG(hw, E1000_TCTL_EXT);
1904a69ed8dfSJack F Vogel 
1905a69ed8dfSJack F Vogel 	tctl_ext &= ~E1000_TCTL_EXT_COLD;
1906a69ed8dfSJack F Vogel 	tctl_ext |= E1000_COLLISION_DISTANCE << E1000_TCTL_EXT_COLD_SHIFT;
1907a69ed8dfSJack F Vogel 
1908a69ed8dfSJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL_EXT, tctl_ext);
1909a69ed8dfSJack F Vogel 	E1000_WRITE_FLUSH(hw);
1910a69ed8dfSJack F Vogel }
1911a69ed8dfSJack F Vogel 
1912a69ed8dfSJack F Vogel /**
19138cfa0ad2SJack F Vogel  * e1000_power_down_phy_copper_82575 - Remove link during PHY power down
19148cfa0ad2SJack F Vogel  * @hw: pointer to the HW structure
19158cfa0ad2SJack F Vogel  *
19168cfa0ad2SJack F Vogel  * In the case of a PHY power down to save power, or to turn off link during a
19178cfa0ad2SJack F Vogel  * driver unload, or wake on lan is not enabled, remove the link.
19188cfa0ad2SJack F Vogel  **/
19198cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw)
19208cfa0ad2SJack F Vogel {
19218cfa0ad2SJack F Vogel 	struct e1000_phy_info *phy = &hw->phy;
19228cfa0ad2SJack F Vogel 
19238cfa0ad2SJack F Vogel 	if (!(phy->ops.check_reset_block))
19248cfa0ad2SJack F Vogel 		return;
19258cfa0ad2SJack F Vogel 
19268cfa0ad2SJack F Vogel 	/* If the management interface is not enabled, then power down */
19278ec87fc5SJack F Vogel 	if (!(e1000_enable_mng_pass_thru(hw) || phy->ops.check_reset_block(hw)))
19288cfa0ad2SJack F Vogel 		e1000_power_down_phy_copper(hw);
19298cfa0ad2SJack F Vogel 
19308cfa0ad2SJack F Vogel 	return;
19318cfa0ad2SJack F Vogel }
19328cfa0ad2SJack F Vogel 
19338cfa0ad2SJack F Vogel /**
19348cfa0ad2SJack F Vogel  *  e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters
19358cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
19368cfa0ad2SJack F Vogel  *
19378cfa0ad2SJack F Vogel  *  Clears the hardware counters by reading the counter registers.
19388cfa0ad2SJack F Vogel  **/
19398cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw)
19408cfa0ad2SJack F Vogel {
19418cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_clear_hw_cntrs_82575");
19428cfa0ad2SJack F Vogel 
19438cfa0ad2SJack F Vogel 	e1000_clear_hw_cntrs_base_generic(hw);
19448cfa0ad2SJack F Vogel 
1945daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC64);
1946daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC127);
1947daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC255);
1948daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC511);
1949daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC1023);
1950daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PRC1522);
1951daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC64);
1952daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC127);
1953daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC255);
1954daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC511);
1955daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC1023);
1956daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_PTC1522);
19578cfa0ad2SJack F Vogel 
1958daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ALGNERRC);
1959daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_RXERRC);
1960daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TNCRS);
1961daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_CEXTERR);
1962daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TSCTC);
1963daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_TSCTFC);
19648cfa0ad2SJack F Vogel 
1965daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPRC);
1966daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPDC);
1967daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_MGTPTC);
19688cfa0ad2SJack F Vogel 
1969daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_IAC);
1970daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXOC);
19718cfa0ad2SJack F Vogel 
1972daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXPTC);
1973daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXATC);
1974daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXPTC);
1975daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXATC);
1976daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXQEC);
1977daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICTXQMTC);
1978daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_ICRXDMTC);
19798cfa0ad2SJack F Vogel 
1980daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_CBTMPC);
1981daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HTDPMC);
1982daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_CBRMPC);
1983daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_RPTHC);
1984daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HGPTC);
1985daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HTCBDPC);
1986daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HGORCL);
1987daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HGORCH);
1988daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HGOTCL);
1989daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_HGOTCH);
1990daf9197cSJack F Vogel 	E1000_READ_REG(hw, E1000_LENERRS);
19918cfa0ad2SJack F Vogel 
19928cfa0ad2SJack F Vogel 	/* This register should not be read in copper configurations */
19934edd8523SJack F Vogel 	if ((hw->phy.media_type == e1000_media_type_internal_serdes) ||
19944edd8523SJack F Vogel 	    e1000_sgmii_active_82575(hw))
1995daf9197cSJack F Vogel 		E1000_READ_REG(hw, E1000_SCVPC);
19968cfa0ad2SJack F Vogel }
19979d81738fSJack F Vogel 
19988cfa0ad2SJack F Vogel /**
1999f0ecc46dSJack F Vogel  *  e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable
20008cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
20018cfa0ad2SJack F Vogel  *
20028cfa0ad2SJack F Vogel  *  After rx enable if managability is enabled then there is likely some
20038cfa0ad2SJack F Vogel  *  bad data at the start of the fifo and possibly in the DMA fifo.  This
20048cfa0ad2SJack F Vogel  *  function clears the fifos and flushes any packets that came in as rx was
20058cfa0ad2SJack F Vogel  *  being enabled.
20068cfa0ad2SJack F Vogel  **/
20078cfa0ad2SJack F Vogel void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
20088cfa0ad2SJack F Vogel {
20098cfa0ad2SJack F Vogel 	u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
20108cfa0ad2SJack F Vogel 	int i, ms_wait;
20118cfa0ad2SJack F Vogel 
20128cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_rx_fifo_workaround_82575");
20138cfa0ad2SJack F Vogel 	if (hw->mac.type != e1000_82575 ||
20148cfa0ad2SJack F Vogel 	    !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN))
20158cfa0ad2SJack F Vogel 		return;
20168cfa0ad2SJack F Vogel 
2017f0ecc46dSJack F Vogel 	/* Disable all Rx queues */
20188cfa0ad2SJack F Vogel 	for (i = 0; i < 4; i++) {
20198cfa0ad2SJack F Vogel 		rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i));
20208cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_RXDCTL(i),
20218cfa0ad2SJack F Vogel 				rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE);
20228cfa0ad2SJack F Vogel 	}
20238cfa0ad2SJack F Vogel 	/* Poll all queues to verify they have shut down */
20248cfa0ad2SJack F Vogel 	for (ms_wait = 0; ms_wait < 10; ms_wait++) {
20258cfa0ad2SJack F Vogel 		msec_delay(1);
20268cfa0ad2SJack F Vogel 		rx_enabled = 0;
20278cfa0ad2SJack F Vogel 		for (i = 0; i < 4; i++)
20288cfa0ad2SJack F Vogel 			rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i));
20298cfa0ad2SJack F Vogel 		if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE))
20308cfa0ad2SJack F Vogel 			break;
20318cfa0ad2SJack F Vogel 	}
20328cfa0ad2SJack F Vogel 
20338cfa0ad2SJack F Vogel 	if (ms_wait == 10)
20348cfa0ad2SJack F Vogel 		DEBUGOUT("Queue disable timed out after 10ms\n");
20358cfa0ad2SJack F Vogel 
20368cfa0ad2SJack F Vogel 	/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
20378cfa0ad2SJack F Vogel 	 * incoming packets are rejected.  Set enable and wait 2ms so that
20388cfa0ad2SJack F Vogel 	 * any packet that was coming in as RCTL.EN was set is flushed
20398cfa0ad2SJack F Vogel 	 */
20408cfa0ad2SJack F Vogel 	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
20418cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF);
20428cfa0ad2SJack F Vogel 
20438cfa0ad2SJack F Vogel 	rlpml = E1000_READ_REG(hw, E1000_RLPML);
20448cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RLPML, 0);
20458cfa0ad2SJack F Vogel 
20468cfa0ad2SJack F Vogel 	rctl = E1000_READ_REG(hw, E1000_RCTL);
20478cfa0ad2SJack F Vogel 	temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP);
20488cfa0ad2SJack F Vogel 	temp_rctl |= E1000_RCTL_LPE;
20498cfa0ad2SJack F Vogel 
20508cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl);
20518cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN);
20528cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
20538cfa0ad2SJack F Vogel 	msec_delay(2);
20548cfa0ad2SJack F Vogel 
2055f0ecc46dSJack F Vogel 	/* Enable Rx queues that were previously enabled and restore our
20568cfa0ad2SJack F Vogel 	 * previous state
20578cfa0ad2SJack F Vogel 	 */
20588cfa0ad2SJack F Vogel 	for (i = 0; i < 4; i++)
20598cfa0ad2SJack F Vogel 		E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]);
20608cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, rctl);
20618cfa0ad2SJack F Vogel 	E1000_WRITE_FLUSH(hw);
20628cfa0ad2SJack F Vogel 
20638cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RLPML, rlpml);
20648cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
20658cfa0ad2SJack F Vogel 
20668cfa0ad2SJack F Vogel 	/* Flush receive errors generated by workaround */
20678cfa0ad2SJack F Vogel 	E1000_READ_REG(hw, E1000_ROC);
20688cfa0ad2SJack F Vogel 	E1000_READ_REG(hw, E1000_RNBC);
20698cfa0ad2SJack F Vogel 	E1000_READ_REG(hw, E1000_MPC);
20708cfa0ad2SJack F Vogel }
2071daf9197cSJack F Vogel 
20729d81738fSJack F Vogel /**
20739d81738fSJack F Vogel  *  e1000_set_pcie_completion_timeout - set pci-e completion timeout
20749d81738fSJack F Vogel  *  @hw: pointer to the HW structure
20759d81738fSJack F Vogel  *
20769d81738fSJack F Vogel  *  The defaults for 82575 and 82576 should be in the range of 50us to 50ms,
20779d81738fSJack F Vogel  *  however the hardware default for these parts is 500us to 1ms which is less
20789d81738fSJack F Vogel  *  than the 10ms recommended by the pci-e spec.  To address this we need to
20799d81738fSJack F Vogel  *  increase the value to either 10ms to 200ms for capability version 1 config,
20809d81738fSJack F Vogel  *  or 16ms to 55ms for version 2.
20819d81738fSJack F Vogel  **/
20829d81738fSJack F Vogel static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw)
20839d81738fSJack F Vogel {
20849d81738fSJack F Vogel 	u32 gcr = E1000_READ_REG(hw, E1000_GCR);
20859d81738fSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
20869d81738fSJack F Vogel 	u16 pcie_devctl2;
20879d81738fSJack F Vogel 
20889d81738fSJack F Vogel 	/* only take action if timeout value is defaulted to 0 */
20899d81738fSJack F Vogel 	if (gcr & E1000_GCR_CMPL_TMOUT_MASK)
20909d81738fSJack F Vogel 		goto out;
20919d81738fSJack F Vogel 
20929d81738fSJack F Vogel 	/*
20939d81738fSJack F Vogel 	 * if capababilities version is type 1 we can write the
20949d81738fSJack F Vogel 	 * timeout of 10ms to 200ms through the GCR register
20959d81738fSJack F Vogel 	 */
20969d81738fSJack F Vogel 	if (!(gcr & E1000_GCR_CAP_VER2)) {
20979d81738fSJack F Vogel 		gcr |= E1000_GCR_CMPL_TMOUT_10ms;
20989d81738fSJack F Vogel 		goto out;
20999d81738fSJack F Vogel 	}
21009d81738fSJack F Vogel 
21019d81738fSJack F Vogel 	/*
21029d81738fSJack F Vogel 	 * for version 2 capabilities we need to write the config space
21039d81738fSJack F Vogel 	 * directly in order to set the completion timeout value for
21049d81738fSJack F Vogel 	 * 16ms to 55ms
21059d81738fSJack F Vogel 	 */
21069d81738fSJack F Vogel 	ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
21079d81738fSJack F Vogel 					  &pcie_devctl2);
21089d81738fSJack F Vogel 	if (ret_val)
21099d81738fSJack F Vogel 		goto out;
21109d81738fSJack F Vogel 
21119d81738fSJack F Vogel 	pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms;
21129d81738fSJack F Vogel 
21139d81738fSJack F Vogel 	ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
21149d81738fSJack F Vogel 					   &pcie_devctl2);
21159d81738fSJack F Vogel out:
21169d81738fSJack F Vogel 	/* disable completion timeout resend */
21179d81738fSJack F Vogel 	gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND;
21189d81738fSJack F Vogel 
21199d81738fSJack F Vogel 	E1000_WRITE_REG(hw, E1000_GCR, gcr);
21209d81738fSJack F Vogel 	return ret_val;
21219d81738fSJack F Vogel }
21229d81738fSJack F Vogel 
21237d9119bdSJack F Vogel /**
21247d9119bdSJack F Vogel  *  e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing
21257d9119bdSJack F Vogel  *  @hw: pointer to the hardware struct
21267d9119bdSJack F Vogel  *  @enable: state to enter, either enabled or disabled
21277d9119bdSJack F Vogel  *  @pf: Physical Function pool - do not set anti-spoofing for the PF
21287d9119bdSJack F Vogel  *
21297d9119bdSJack F Vogel  *  enables/disables L2 switch anti-spoofing functionality.
21307d9119bdSJack F Vogel  **/
21317d9119bdSJack F Vogel void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
21327d9119bdSJack F Vogel {
21337d9119bdSJack F Vogel 	u32 dtxswc;
21347d9119bdSJack F Vogel 
21357d9119bdSJack F Vogel 	switch (hw->mac.type) {
21367d9119bdSJack F Vogel 	case e1000_82576:
21377d9119bdSJack F Vogel 		dtxswc = E1000_READ_REG(hw, E1000_DTXSWC);
21387d9119bdSJack F Vogel 		if (enable) {
21397d9119bdSJack F Vogel 			dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
21407d9119bdSJack F Vogel 				   E1000_DTXSWC_VLAN_SPOOF_MASK);
21417d9119bdSJack F Vogel 			/* The PF can spoof - it has to in order to
21427d9119bdSJack F Vogel 			 * support emulation mode NICs */
21434dab5c37SJack F Vogel 			dtxswc ^= (1 << pf | 1 << (pf +
21444dab5c37SJack F Vogel 				   E1000_DTXSWC_VLAN_SPOOF_SHIFT));
21457d9119bdSJack F Vogel 		} else {
21467d9119bdSJack F Vogel 			dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
21477d9119bdSJack F Vogel 				    E1000_DTXSWC_VLAN_SPOOF_MASK);
21487d9119bdSJack F Vogel 		}
21497d9119bdSJack F Vogel 		E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
21507d9119bdSJack F Vogel 		break;
21514dab5c37SJack F Vogel 	case e1000_i350:
21524dab5c37SJack F Vogel 		dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
21534dab5c37SJack F Vogel 		if (enable) {
21544dab5c37SJack F Vogel 			dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
21554dab5c37SJack F Vogel 				   E1000_DTXSWC_VLAN_SPOOF_MASK);
21564dab5c37SJack F Vogel 			/* The PF can spoof - it has to in order to
21574dab5c37SJack F Vogel 			 * support emulation mode NICs
21584dab5c37SJack F Vogel 			 */
21594dab5c37SJack F Vogel 			dtxswc ^= (1 << pf | 1 << (pf +
21604dab5c37SJack F Vogel 				   E1000_DTXSWC_VLAN_SPOOF_SHIFT));
21614dab5c37SJack F Vogel 		} else {
21624dab5c37SJack F Vogel 			dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
21634dab5c37SJack F Vogel 				    E1000_DTXSWC_VLAN_SPOOF_MASK);
21644dab5c37SJack F Vogel 		}
21654dab5c37SJack F Vogel 		E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
21667d9119bdSJack F Vogel 	default:
21677d9119bdSJack F Vogel 		break;
21687d9119bdSJack F Vogel 	}
21697d9119bdSJack F Vogel }
21707d9119bdSJack F Vogel 
21714edd8523SJack F Vogel /**
21724edd8523SJack F Vogel  *  e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback
21734edd8523SJack F Vogel  *  @hw: pointer to the hardware struct
21744edd8523SJack F Vogel  *  @enable: state to enter, either enabled or disabled
21754edd8523SJack F Vogel  *
21764edd8523SJack F Vogel  *  enables/disables L2 switch loopback functionality.
21774edd8523SJack F Vogel  **/
21784edd8523SJack F Vogel void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
21794edd8523SJack F Vogel {
21808ec87fc5SJack F Vogel 	u32 dtxswc;
21814edd8523SJack F Vogel 
21828ec87fc5SJack F Vogel 	switch (hw->mac.type) {
21838ec87fc5SJack F Vogel 	case e1000_82576:
21848ec87fc5SJack F Vogel 		dtxswc = E1000_READ_REG(hw, E1000_DTXSWC);
21854edd8523SJack F Vogel 		if (enable)
21864edd8523SJack F Vogel 			dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
21874edd8523SJack F Vogel 		else
21884edd8523SJack F Vogel 			dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
21894edd8523SJack F Vogel 		E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
21908ec87fc5SJack F Vogel 		break;
2191f0ecc46dSJack F Vogel 	case e1000_i350:
2192f0ecc46dSJack F Vogel 		dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
2193f0ecc46dSJack F Vogel 		if (enable)
2194f0ecc46dSJack F Vogel 			dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
2195f0ecc46dSJack F Vogel 		else
2196f0ecc46dSJack F Vogel 			dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
2197f0ecc46dSJack F Vogel 		E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
2198f0ecc46dSJack F Vogel 		break;
21998ec87fc5SJack F Vogel 	default:
22008ec87fc5SJack F Vogel 		/* Currently no other hardware supports loopback */
22018ec87fc5SJack F Vogel 		break;
22028ec87fc5SJack F Vogel 	}
22038ec87fc5SJack F Vogel 
22048ec87fc5SJack F Vogel 
22054edd8523SJack F Vogel }
22064edd8523SJack F Vogel 
22074edd8523SJack F Vogel /**
22084edd8523SJack F Vogel  *  e1000_vmdq_set_replication_pf - enable or disable vmdq replication
22094edd8523SJack F Vogel  *  @hw: pointer to the hardware struct
22104edd8523SJack F Vogel  *  @enable: state to enter, either enabled or disabled
22114edd8523SJack F Vogel  *
22124edd8523SJack F Vogel  *  enables/disables replication of packets across multiple pools.
22134edd8523SJack F Vogel  **/
22144edd8523SJack F Vogel void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable)
22154edd8523SJack F Vogel {
22164edd8523SJack F Vogel 	u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL);
22174edd8523SJack F Vogel 
22184edd8523SJack F Vogel 	if (enable)
22194edd8523SJack F Vogel 		vt_ctl |= E1000_VT_CTL_VM_REPL_EN;
22204edd8523SJack F Vogel 	else
22214edd8523SJack F Vogel 		vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN;
22224edd8523SJack F Vogel 
22234edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl);
22244edd8523SJack F Vogel }
22254edd8523SJack F Vogel 
22264edd8523SJack F Vogel /**
22274edd8523SJack F Vogel  *  e1000_read_phy_reg_82580 - Read 82580 MDI control register
22284edd8523SJack F Vogel  *  @hw: pointer to the HW structure
22294edd8523SJack F Vogel  *  @offset: register offset to be read
22304edd8523SJack F Vogel  *  @data: pointer to the read data
22314edd8523SJack F Vogel  *
22324edd8523SJack F Vogel  *  Reads the MDI control register in the PHY at offset and stores the
22334edd8523SJack F Vogel  *  information read to data.
22344edd8523SJack F Vogel  **/
22354edd8523SJack F Vogel static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data)
22364edd8523SJack F Vogel {
22374edd8523SJack F Vogel 	s32 ret_val;
22384edd8523SJack F Vogel 
22394edd8523SJack F Vogel 	DEBUGFUNC("e1000_read_phy_reg_82580");
22404edd8523SJack F Vogel 
22414edd8523SJack F Vogel 	ret_val = hw->phy.ops.acquire(hw);
22424edd8523SJack F Vogel 	if (ret_val)
22434edd8523SJack F Vogel 		goto out;
22444edd8523SJack F Vogel 
22454edd8523SJack F Vogel 	ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
22464edd8523SJack F Vogel 
22474edd8523SJack F Vogel 	hw->phy.ops.release(hw);
22484edd8523SJack F Vogel 
22494edd8523SJack F Vogel out:
22504edd8523SJack F Vogel 	return ret_val;
22514edd8523SJack F Vogel }
22524edd8523SJack F Vogel 
22534edd8523SJack F Vogel /**
22544edd8523SJack F Vogel  *  e1000_write_phy_reg_82580 - Write 82580 MDI control register
22554edd8523SJack F Vogel  *  @hw: pointer to the HW structure
22564edd8523SJack F Vogel  *  @offset: register offset to write to
22574edd8523SJack F Vogel  *  @data: data to write to register at offset
22584edd8523SJack F Vogel  *
22594edd8523SJack F Vogel  *  Writes data to MDI control register in the PHY at offset.
22604edd8523SJack F Vogel  **/
22614edd8523SJack F Vogel static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data)
22624edd8523SJack F Vogel {
22634edd8523SJack F Vogel 	s32 ret_val;
22644edd8523SJack F Vogel 
22654edd8523SJack F Vogel 	DEBUGFUNC("e1000_write_phy_reg_82580");
22664edd8523SJack F Vogel 
22674edd8523SJack F Vogel 	ret_val = hw->phy.ops.acquire(hw);
22684edd8523SJack F Vogel 	if (ret_val)
22694edd8523SJack F Vogel 		goto out;
22704edd8523SJack F Vogel 
22714edd8523SJack F Vogel 	ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
22724edd8523SJack F Vogel 
22734edd8523SJack F Vogel 	hw->phy.ops.release(hw);
22744edd8523SJack F Vogel 
22754edd8523SJack F Vogel out:
22764edd8523SJack F Vogel 	return ret_val;
22774edd8523SJack F Vogel }
2278a69ed8dfSJack F Vogel 
22794edd8523SJack F Vogel /**
22807d9119bdSJack F Vogel  *  e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits
22817d9119bdSJack F Vogel  *  @hw: pointer to the HW structure
22827d9119bdSJack F Vogel  *
22834dab5c37SJack F Vogel  *  This resets the the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on
22847d9119bdSJack F Vogel  *  the values found in the EEPROM.  This addresses an issue in which these
22857d9119bdSJack F Vogel  *  bits are not restored from EEPROM after reset.
22867d9119bdSJack F Vogel  **/
22877d9119bdSJack F Vogel static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw)
22887d9119bdSJack F Vogel {
22897d9119bdSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
22907d9119bdSJack F Vogel 	u32 mdicnfg;
2291f0ecc46dSJack F Vogel 	u16 nvm_data = 0;
22927d9119bdSJack F Vogel 
22937d9119bdSJack F Vogel 	DEBUGFUNC("e1000_reset_mdicnfg_82580");
22947d9119bdSJack F Vogel 
22957d9119bdSJack F Vogel 	if (hw->mac.type != e1000_82580)
22967d9119bdSJack F Vogel 		goto out;
22977d9119bdSJack F Vogel 	if (!e1000_sgmii_active_82575(hw))
22987d9119bdSJack F Vogel 		goto out;
22997d9119bdSJack F Vogel 
23007d9119bdSJack F Vogel 	ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
23017d9119bdSJack F Vogel 				   NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
23027d9119bdSJack F Vogel 				   &nvm_data);
23037d9119bdSJack F Vogel 	if (ret_val) {
23047d9119bdSJack F Vogel 		DEBUGOUT("NVM Read Error\n");
23057d9119bdSJack F Vogel 		goto out;
23067d9119bdSJack F Vogel 	}
23077d9119bdSJack F Vogel 
23087d9119bdSJack F Vogel 	mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG);
23097d9119bdSJack F Vogel 	if (nvm_data & NVM_WORD24_EXT_MDIO)
23107d9119bdSJack F Vogel 		mdicnfg |= E1000_MDICNFG_EXT_MDIO;
23117d9119bdSJack F Vogel 	if (nvm_data & NVM_WORD24_COM_MDIO)
23127d9119bdSJack F Vogel 		mdicnfg |= E1000_MDICNFG_COM_MDIO;
23137d9119bdSJack F Vogel 	E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg);
23147d9119bdSJack F Vogel out:
23157d9119bdSJack F Vogel 	return ret_val;
23167d9119bdSJack F Vogel }
23177d9119bdSJack F Vogel 
23187d9119bdSJack F Vogel /**
23194edd8523SJack F Vogel  *  e1000_reset_hw_82580 - Reset hardware
23204edd8523SJack F Vogel  *  @hw: pointer to the HW structure
23214edd8523SJack F Vogel  *
23224edd8523SJack F Vogel  *  This resets function or entire device (all ports, etc.)
23234edd8523SJack F Vogel  *  to a known state.
23244edd8523SJack F Vogel  **/
23254edd8523SJack F Vogel static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
23264edd8523SJack F Vogel {
23274edd8523SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
23284edd8523SJack F Vogel 	/* BH SW mailbox bit in SW_FW_SYNC */
23294edd8523SJack F Vogel 	u16 swmbsw_mask = E1000_SW_SYNCH_MB;
2330f0ecc46dSJack F Vogel 	u32 ctrl;
23314edd8523SJack F Vogel 	bool global_device_reset = hw->dev_spec._82575.global_device_reset;
23324edd8523SJack F Vogel 
23334edd8523SJack F Vogel 	DEBUGFUNC("e1000_reset_hw_82580");
23344edd8523SJack F Vogel 
23354edd8523SJack F Vogel 	hw->dev_spec._82575.global_device_reset = FALSE;
23364edd8523SJack F Vogel 
23374edd8523SJack F Vogel 	/* Get current control state. */
23384edd8523SJack F Vogel 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
23394edd8523SJack F Vogel 
23404edd8523SJack F Vogel 	/*
23414edd8523SJack F Vogel 	 * Prevent the PCI-E bus from sticking if there is no TLP connection
23424edd8523SJack F Vogel 	 * on the last TLP read/write transaction when MAC is reset.
23434edd8523SJack F Vogel 	 */
23444edd8523SJack F Vogel 	ret_val = e1000_disable_pcie_master_generic(hw);
23454edd8523SJack F Vogel 	if (ret_val)
23464edd8523SJack F Vogel 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
23474edd8523SJack F Vogel 
23484edd8523SJack F Vogel 	DEBUGOUT("Masking off all interrupts\n");
23494edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
23504edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
23514edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
23524edd8523SJack F Vogel 	E1000_WRITE_FLUSH(hw);
23534edd8523SJack F Vogel 
23544edd8523SJack F Vogel 	msec_delay(10);
23554edd8523SJack F Vogel 
23564edd8523SJack F Vogel 	/* Determine whether or not a global dev reset is requested */
2357*ab5d0362SJack F Vogel 	if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw,
23584dab5c37SJack F Vogel 	    swmbsw_mask))
23594edd8523SJack F Vogel 			global_device_reset = FALSE;
23604edd8523SJack F Vogel 
23614dab5c37SJack F Vogel 	if (global_device_reset && !(E1000_READ_REG(hw, E1000_STATUS) &
23624dab5c37SJack F Vogel 	    E1000_STAT_DEV_RST_SET))
23634edd8523SJack F Vogel 		ctrl |= E1000_CTRL_DEV_RST;
23644edd8523SJack F Vogel 	else
23654edd8523SJack F Vogel 		ctrl |= E1000_CTRL_RST;
23664edd8523SJack F Vogel 
23674edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
23684dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
23694edd8523SJack F Vogel 
23704edd8523SJack F Vogel 	/* Add delay to insure DEV_RST has time to complete */
23714edd8523SJack F Vogel 	if (global_device_reset)
23724edd8523SJack F Vogel 		msec_delay(5);
23734edd8523SJack F Vogel 
23744edd8523SJack F Vogel 	ret_val = e1000_get_auto_rd_done_generic(hw);
23754edd8523SJack F Vogel 	if (ret_val) {
23764edd8523SJack F Vogel 		/*
23774edd8523SJack F Vogel 		 * When auto config read does not complete, do not
23784edd8523SJack F Vogel 		 * return with an error. This can happen in situations
23794edd8523SJack F Vogel 		 * where there is no eeprom and prevents getting link.
23804edd8523SJack F Vogel 		 */
23814edd8523SJack F Vogel 		DEBUGOUT("Auto Read Done did not complete\n");
23824edd8523SJack F Vogel 	}
23834edd8523SJack F Vogel 
23844edd8523SJack F Vogel 	/* If EEPROM is not present, run manual init scripts */
2385*ab5d0362SJack F Vogel 	if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES))
23864edd8523SJack F Vogel 		e1000_reset_init_script_82575(hw);
23874edd8523SJack F Vogel 
23884edd8523SJack F Vogel 	/* clear global device reset status bit */
23894edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET);
23904edd8523SJack F Vogel 
23914edd8523SJack F Vogel 	/* Clear any pending interrupt events. */
23924edd8523SJack F Vogel 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
2393f0ecc46dSJack F Vogel 	E1000_READ_REG(hw, E1000_ICR);
23944edd8523SJack F Vogel 
23957d9119bdSJack F Vogel 	ret_val = e1000_reset_mdicnfg_82580(hw);
23967d9119bdSJack F Vogel 	if (ret_val)
23977d9119bdSJack F Vogel 		DEBUGOUT("Could not reset MDICNFG based on EEPROM\n");
23987d9119bdSJack F Vogel 
23994edd8523SJack F Vogel 	/* Install any alternate MAC address into RAR0 */
24004edd8523SJack F Vogel 	ret_val = e1000_check_alt_mac_addr_generic(hw);
24014edd8523SJack F Vogel 
24024edd8523SJack F Vogel 	/* Release semaphore */
24034edd8523SJack F Vogel 	if (global_device_reset)
2404*ab5d0362SJack F Vogel 		hw->mac.ops.release_swfw_sync(hw, swmbsw_mask);
24054edd8523SJack F Vogel 
24064edd8523SJack F Vogel 	return ret_val;
24074edd8523SJack F Vogel }
24084edd8523SJack F Vogel 
24094edd8523SJack F Vogel /**
2410f0ecc46dSJack F Vogel  *  e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size
24114edd8523SJack F Vogel  *  @data: data received by reading RXPBS register
24124edd8523SJack F Vogel  *
24134edd8523SJack F Vogel  *  The 82580 uses a table based approach for packet buffer allocation sizes.
24144edd8523SJack F Vogel  *  This function converts the retrieved value into the correct table value
24154edd8523SJack F Vogel  *     0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7
24164edd8523SJack F Vogel  *  0x0 36  72 144   1   2   4   8  16
24174edd8523SJack F Vogel  *  0x8 35  70 140 rsv rsv rsv rsv rsv
24184edd8523SJack F Vogel  */
24194edd8523SJack F Vogel u16 e1000_rxpbs_adjust_82580(u32 data)
24204edd8523SJack F Vogel {
24214edd8523SJack F Vogel 	u16 ret_val = 0;
24224edd8523SJack F Vogel 
24234edd8523SJack F Vogel 	if (data < E1000_82580_RXPBS_TABLE_SIZE)
24244edd8523SJack F Vogel 		ret_val = e1000_82580_rxpbs_table[data];
24254edd8523SJack F Vogel 
24264edd8523SJack F Vogel 	return ret_val;
24274edd8523SJack F Vogel }
2428f0ecc46dSJack F Vogel 
2429f0ecc46dSJack F Vogel /**
2430f0ecc46dSJack F Vogel  *  e1000_validate_nvm_checksum_with_offset - Validate EEPROM
2431f0ecc46dSJack F Vogel  *  checksum
2432f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2433f0ecc46dSJack F Vogel  *  @offset: offset in words of the checksum protected region
2434f0ecc46dSJack F Vogel  *
2435f0ecc46dSJack F Vogel  *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
2436f0ecc46dSJack F Vogel  *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
2437f0ecc46dSJack F Vogel  **/
2438f0ecc46dSJack F Vogel s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
2439f0ecc46dSJack F Vogel {
2440f0ecc46dSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
2441f0ecc46dSJack F Vogel 	u16 checksum = 0;
2442f0ecc46dSJack F Vogel 	u16 i, nvm_data;
2443f0ecc46dSJack F Vogel 
2444f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_validate_nvm_checksum_with_offset");
2445f0ecc46dSJack F Vogel 
2446f0ecc46dSJack F Vogel 	for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) {
2447f0ecc46dSJack F Vogel 		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
2448f0ecc46dSJack F Vogel 		if (ret_val) {
2449f0ecc46dSJack F Vogel 			DEBUGOUT("NVM Read Error\n");
2450f0ecc46dSJack F Vogel 			goto out;
2451f0ecc46dSJack F Vogel 		}
2452f0ecc46dSJack F Vogel 		checksum += nvm_data;
2453f0ecc46dSJack F Vogel 	}
2454f0ecc46dSJack F Vogel 
2455f0ecc46dSJack F Vogel 	if (checksum != (u16) NVM_SUM) {
2456f0ecc46dSJack F Vogel 		DEBUGOUT("NVM Checksum Invalid\n");
2457f0ecc46dSJack F Vogel 		ret_val = -E1000_ERR_NVM;
2458f0ecc46dSJack F Vogel 		goto out;
2459f0ecc46dSJack F Vogel 	}
2460f0ecc46dSJack F Vogel 
2461f0ecc46dSJack F Vogel out:
2462f0ecc46dSJack F Vogel 	return ret_val;
2463f0ecc46dSJack F Vogel }
2464f0ecc46dSJack F Vogel 
2465f0ecc46dSJack F Vogel /**
2466f0ecc46dSJack F Vogel  *  e1000_update_nvm_checksum_with_offset - Update EEPROM
2467f0ecc46dSJack F Vogel  *  checksum
2468f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2469f0ecc46dSJack F Vogel  *  @offset: offset in words of the checksum protected region
2470f0ecc46dSJack F Vogel  *
2471f0ecc46dSJack F Vogel  *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
2472f0ecc46dSJack F Vogel  *  up to the checksum.  Then calculates the EEPROM checksum and writes the
2473f0ecc46dSJack F Vogel  *  value to the EEPROM.
2474f0ecc46dSJack F Vogel  **/
2475f0ecc46dSJack F Vogel s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
2476f0ecc46dSJack F Vogel {
2477f0ecc46dSJack F Vogel 	s32 ret_val;
2478f0ecc46dSJack F Vogel 	u16 checksum = 0;
2479f0ecc46dSJack F Vogel 	u16 i, nvm_data;
2480f0ecc46dSJack F Vogel 
2481f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_update_nvm_checksum_with_offset");
2482f0ecc46dSJack F Vogel 
2483f0ecc46dSJack F Vogel 	for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) {
2484f0ecc46dSJack F Vogel 		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
2485f0ecc46dSJack F Vogel 		if (ret_val) {
2486f0ecc46dSJack F Vogel 			DEBUGOUT("NVM Read Error while updating checksum.\n");
2487f0ecc46dSJack F Vogel 			goto out;
2488f0ecc46dSJack F Vogel 		}
2489f0ecc46dSJack F Vogel 		checksum += nvm_data;
2490f0ecc46dSJack F Vogel 	}
2491f0ecc46dSJack F Vogel 	checksum = (u16) NVM_SUM - checksum;
2492f0ecc46dSJack F Vogel 	ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1,
2493f0ecc46dSJack F Vogel 				    &checksum);
2494f0ecc46dSJack F Vogel 	if (ret_val)
2495f0ecc46dSJack F Vogel 		DEBUGOUT("NVM Write Error while updating checksum.\n");
2496f0ecc46dSJack F Vogel 
2497f0ecc46dSJack F Vogel out:
2498f0ecc46dSJack F Vogel 	return ret_val;
2499f0ecc46dSJack F Vogel }
2500f0ecc46dSJack F Vogel 
2501f0ecc46dSJack F Vogel /**
2502f0ecc46dSJack F Vogel  *  e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum
2503f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2504f0ecc46dSJack F Vogel  *
2505f0ecc46dSJack F Vogel  *  Calculates the EEPROM section checksum by reading/adding each word of
2506f0ecc46dSJack F Vogel  *  the EEPROM and then verifies that the sum of the EEPROM is
2507f0ecc46dSJack F Vogel  *  equal to 0xBABA.
2508f0ecc46dSJack F Vogel  **/
2509f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw)
2510f0ecc46dSJack F Vogel {
2511f0ecc46dSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
2512f0ecc46dSJack F Vogel 	u16 eeprom_regions_count = 1;
2513f0ecc46dSJack F Vogel 	u16 j, nvm_data;
2514f0ecc46dSJack F Vogel 	u16 nvm_offset;
2515f0ecc46dSJack F Vogel 
2516f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_validate_nvm_checksum_82580");
2517f0ecc46dSJack F Vogel 
2518f0ecc46dSJack F Vogel 	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
2519f0ecc46dSJack F Vogel 	if (ret_val) {
2520f0ecc46dSJack F Vogel 		DEBUGOUT("NVM Read Error\n");
2521f0ecc46dSJack F Vogel 		goto out;
2522f0ecc46dSJack F Vogel 	}
2523f0ecc46dSJack F Vogel 
2524f0ecc46dSJack F Vogel 	if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) {
2525f0ecc46dSJack F Vogel 		/* if chekcsums compatibility bit is set validate checksums
2526f0ecc46dSJack F Vogel 		 * for all 4 ports. */
2527f0ecc46dSJack F Vogel 		eeprom_regions_count = 4;
2528f0ecc46dSJack F Vogel 	}
2529f0ecc46dSJack F Vogel 
2530f0ecc46dSJack F Vogel 	for (j = 0; j < eeprom_regions_count; j++) {
2531f0ecc46dSJack F Vogel 		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2532f0ecc46dSJack F Vogel 		ret_val = e1000_validate_nvm_checksum_with_offset(hw,
2533f0ecc46dSJack F Vogel 								  nvm_offset);
2534f0ecc46dSJack F Vogel 		if (ret_val != E1000_SUCCESS)
2535f0ecc46dSJack F Vogel 			goto out;
2536f0ecc46dSJack F Vogel 	}
2537f0ecc46dSJack F Vogel 
2538f0ecc46dSJack F Vogel out:
2539f0ecc46dSJack F Vogel 	return ret_val;
2540f0ecc46dSJack F Vogel }
2541f0ecc46dSJack F Vogel 
2542f0ecc46dSJack F Vogel /**
2543f0ecc46dSJack F Vogel  *  e1000_update_nvm_checksum_82580 - Update EEPROM checksum
2544f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2545f0ecc46dSJack F Vogel  *
2546f0ecc46dSJack F Vogel  *  Updates the EEPROM section checksums for all 4 ports by reading/adding
2547f0ecc46dSJack F Vogel  *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
2548f0ecc46dSJack F Vogel  *  checksum and writes the value to the EEPROM.
2549f0ecc46dSJack F Vogel  **/
2550f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw)
2551f0ecc46dSJack F Vogel {
2552f0ecc46dSJack F Vogel 	s32 ret_val;
2553f0ecc46dSJack F Vogel 	u16 j, nvm_data;
2554f0ecc46dSJack F Vogel 	u16 nvm_offset;
2555f0ecc46dSJack F Vogel 
2556f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_update_nvm_checksum_82580");
2557f0ecc46dSJack F Vogel 
2558f0ecc46dSJack F Vogel 	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
2559f0ecc46dSJack F Vogel 	if (ret_val) {
25604dab5c37SJack F Vogel 		DEBUGOUT("NVM Read Error while updating checksum compatibility bit.\n");
2561f0ecc46dSJack F Vogel 		goto out;
2562f0ecc46dSJack F Vogel 	}
2563f0ecc46dSJack F Vogel 
2564*ab5d0362SJack F Vogel 	if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) {
2565f0ecc46dSJack F Vogel 		/* set compatibility bit to validate checksums appropriately */
2566f0ecc46dSJack F Vogel 		nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK;
2567f0ecc46dSJack F Vogel 		ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1,
2568f0ecc46dSJack F Vogel 					    &nvm_data);
2569f0ecc46dSJack F Vogel 		if (ret_val) {
25704dab5c37SJack F Vogel 			DEBUGOUT("NVM Write Error while updating checksum compatibility bit.\n");
2571f0ecc46dSJack F Vogel 			goto out;
2572f0ecc46dSJack F Vogel 		}
2573f0ecc46dSJack F Vogel 	}
2574f0ecc46dSJack F Vogel 
2575f0ecc46dSJack F Vogel 	for (j = 0; j < 4; j++) {
2576f0ecc46dSJack F Vogel 		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2577f0ecc46dSJack F Vogel 		ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
25784dab5c37SJack F Vogel 		if (ret_val)
2579f0ecc46dSJack F Vogel 			goto out;
2580f0ecc46dSJack F Vogel 	}
2581f0ecc46dSJack F Vogel 
2582f0ecc46dSJack F Vogel out:
2583f0ecc46dSJack F Vogel 	return ret_val;
2584f0ecc46dSJack F Vogel }
2585f0ecc46dSJack F Vogel 
2586f0ecc46dSJack F Vogel /**
2587f0ecc46dSJack F Vogel  *  e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum
2588f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2589f0ecc46dSJack F Vogel  *
2590f0ecc46dSJack F Vogel  *  Calculates the EEPROM section checksum by reading/adding each word of
2591f0ecc46dSJack F Vogel  *  the EEPROM and then verifies that the sum of the EEPROM is
2592f0ecc46dSJack F Vogel  *  equal to 0xBABA.
2593f0ecc46dSJack F Vogel  **/
2594f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw)
2595f0ecc46dSJack F Vogel {
2596f0ecc46dSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
2597f0ecc46dSJack F Vogel 	u16 j;
2598f0ecc46dSJack F Vogel 	u16 nvm_offset;
2599f0ecc46dSJack F Vogel 
2600f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_validate_nvm_checksum_i350");
2601f0ecc46dSJack F Vogel 
2602f0ecc46dSJack F Vogel 	for (j = 0; j < 4; j++) {
2603f0ecc46dSJack F Vogel 		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2604f0ecc46dSJack F Vogel 		ret_val = e1000_validate_nvm_checksum_with_offset(hw,
2605f0ecc46dSJack F Vogel 								  nvm_offset);
2606f0ecc46dSJack F Vogel 		if (ret_val != E1000_SUCCESS)
2607f0ecc46dSJack F Vogel 			goto out;
2608f0ecc46dSJack F Vogel 	}
2609f0ecc46dSJack F Vogel 
2610f0ecc46dSJack F Vogel out:
2611f0ecc46dSJack F Vogel 	return ret_val;
2612f0ecc46dSJack F Vogel }
2613f0ecc46dSJack F Vogel 
2614f0ecc46dSJack F Vogel /**
2615f0ecc46dSJack F Vogel  *  e1000_update_nvm_checksum_i350 - Update EEPROM checksum
2616f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2617f0ecc46dSJack F Vogel  *
2618f0ecc46dSJack F Vogel  *  Updates the EEPROM section checksums for all 4 ports by reading/adding
2619f0ecc46dSJack F Vogel  *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
2620f0ecc46dSJack F Vogel  *  checksum and writes the value to the EEPROM.
2621f0ecc46dSJack F Vogel  **/
2622f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw)
2623f0ecc46dSJack F Vogel {
2624f0ecc46dSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
2625f0ecc46dSJack F Vogel 	u16 j;
2626f0ecc46dSJack F Vogel 	u16 nvm_offset;
2627f0ecc46dSJack F Vogel 
2628f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_update_nvm_checksum_i350");
2629f0ecc46dSJack F Vogel 
2630f0ecc46dSJack F Vogel 	for (j = 0; j < 4; j++) {
2631f0ecc46dSJack F Vogel 		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2632f0ecc46dSJack F Vogel 		ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
2633f0ecc46dSJack F Vogel 		if (ret_val != E1000_SUCCESS)
2634f0ecc46dSJack F Vogel 			goto out;
2635f0ecc46dSJack F Vogel 	}
2636f0ecc46dSJack F Vogel 
2637f0ecc46dSJack F Vogel out:
2638f0ecc46dSJack F Vogel 	return ret_val;
2639f0ecc46dSJack F Vogel }
2640f0ecc46dSJack F Vogel 
2641f0ecc46dSJack F Vogel /**
2642f0ecc46dSJack F Vogel  *  e1000_set_eee_i350 - Enable/disable EEE support
2643f0ecc46dSJack F Vogel  *  @hw: pointer to the HW structure
2644f0ecc46dSJack F Vogel  *
2645f0ecc46dSJack F Vogel  *  Enable/disable EEE based on setting in dev_spec structure.
2646f0ecc46dSJack F Vogel  *
2647f0ecc46dSJack F Vogel  **/
2648f0ecc46dSJack F Vogel s32 e1000_set_eee_i350(struct e1000_hw *hw)
2649f0ecc46dSJack F Vogel {
2650f0ecc46dSJack F Vogel 	s32 ret_val = E1000_SUCCESS;
26514dab5c37SJack F Vogel 	u32 ipcnfg, eeer;
2652f0ecc46dSJack F Vogel 
2653f0ecc46dSJack F Vogel 	DEBUGFUNC("e1000_set_eee_i350");
2654f0ecc46dSJack F Vogel 
26554dab5c37SJack F Vogel 	if ((hw->mac.type < e1000_i350) ||
26564dab5c37SJack F Vogel 	    (hw->phy.media_type != e1000_media_type_copper))
2657f0ecc46dSJack F Vogel 		goto out;
2658f0ecc46dSJack F Vogel 	ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG);
2659f0ecc46dSJack F Vogel 	eeer = E1000_READ_REG(hw, E1000_EEER);
2660f0ecc46dSJack F Vogel 
2661f0ecc46dSJack F Vogel 	/* enable or disable per user setting */
2662f0ecc46dSJack F Vogel 	if (!(hw->dev_spec._82575.eee_disable)) {
26634dab5c37SJack F Vogel 		ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
26644dab5c37SJack F Vogel 		eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
2665f0ecc46dSJack F Vogel 			 E1000_EEER_LPI_FC);
2666f0ecc46dSJack F Vogel 
2667f0ecc46dSJack F Vogel 	} else {
26684dab5c37SJack F Vogel 		ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
26694dab5c37SJack F Vogel 		eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
2670f0ecc46dSJack F Vogel 			  E1000_EEER_LPI_FC);
2671f0ecc46dSJack F Vogel 	}
2672f0ecc46dSJack F Vogel 	E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg);
2673f0ecc46dSJack F Vogel 	E1000_WRITE_REG(hw, E1000_EEER, eeer);
2674f0ecc46dSJack F Vogel 	E1000_READ_REG(hw, E1000_IPCNFG);
2675f0ecc46dSJack F Vogel 	E1000_READ_REG(hw, E1000_EEER);
2676f0ecc46dSJack F Vogel out:
2677f0ecc46dSJack F Vogel 
2678f0ecc46dSJack F Vogel 	return ret_val;
2679f0ecc46dSJack F Vogel }
26804dab5c37SJack F Vogel 
26814dab5c37SJack F Vogel /* Due to a hw errata, if the host tries to  configure the VFTA register
26824dab5c37SJack F Vogel  * while performing queries from the BMC or DMA, then the VFTA in some
26834dab5c37SJack F Vogel  * cases won't be written.
26844dab5c37SJack F Vogel  */
26854dab5c37SJack F Vogel 
26864dab5c37SJack F Vogel /**
26874dab5c37SJack F Vogel  *  e1000_clear_vfta_i350 - Clear VLAN filter table
26884dab5c37SJack F Vogel  *  @hw: pointer to the HW structure
26894dab5c37SJack F Vogel  *
26904dab5c37SJack F Vogel  *  Clears the register array which contains the VLAN filter table by
26914dab5c37SJack F Vogel  *  setting all the values to 0.
26924dab5c37SJack F Vogel  **/
26934dab5c37SJack F Vogel void e1000_clear_vfta_i350(struct e1000_hw *hw)
26944dab5c37SJack F Vogel {
26954dab5c37SJack F Vogel 	u32 offset;
26964dab5c37SJack F Vogel 	int i;
26974dab5c37SJack F Vogel 
26984dab5c37SJack F Vogel 	DEBUGFUNC("e1000_clear_vfta_350");
26994dab5c37SJack F Vogel 
27004dab5c37SJack F Vogel 	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
27014dab5c37SJack F Vogel 		for (i = 0; i < 10; i++)
27024dab5c37SJack F Vogel 			E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
27034dab5c37SJack F Vogel 
27044dab5c37SJack F Vogel 		E1000_WRITE_FLUSH(hw);
27054dab5c37SJack F Vogel 	}
27064dab5c37SJack F Vogel }
27074dab5c37SJack F Vogel 
27084dab5c37SJack F Vogel /**
27094dab5c37SJack F Vogel  *  e1000_write_vfta_i350 - Write value to VLAN filter table
27104dab5c37SJack F Vogel  *  @hw: pointer to the HW structure
27114dab5c37SJack F Vogel  *  @offset: register offset in VLAN filter table
27124dab5c37SJack F Vogel  *  @value: register value written to VLAN filter table
27134dab5c37SJack F Vogel  *
27144dab5c37SJack F Vogel  *  Writes value at the given offset in the register array which stores
27154dab5c37SJack F Vogel  *  the VLAN filter table.
27164dab5c37SJack F Vogel  **/
27174dab5c37SJack F Vogel void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
27184dab5c37SJack F Vogel {
27194dab5c37SJack F Vogel 	int i;
27204dab5c37SJack F Vogel 
27214dab5c37SJack F Vogel 	DEBUGFUNC("e1000_write_vfta_350");
27224dab5c37SJack F Vogel 
27234dab5c37SJack F Vogel 	for (i = 0; i < 10; i++)
27244dab5c37SJack F Vogel 		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
27254dab5c37SJack F Vogel 
27264dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
27274dab5c37SJack F Vogel }
27284dab5c37SJack F Vogel 
27294dab5c37SJack F Vogel 
27304dab5c37SJack F Vogel /**
27314dab5c37SJack F Vogel  *  e1000_set_i2c_bb - Enable I2C bit-bang
27324dab5c37SJack F Vogel  *  @hw: pointer to the HW structure
27334dab5c37SJack F Vogel  *
27344dab5c37SJack F Vogel  *  Enable I2C bit-bang interface
27354dab5c37SJack F Vogel  *
27364dab5c37SJack F Vogel  **/
27374dab5c37SJack F Vogel s32 e1000_set_i2c_bb(struct e1000_hw *hw)
27384dab5c37SJack F Vogel {
27394dab5c37SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
27404dab5c37SJack F Vogel 	u32 ctrl_ext, i2cparams;
27414dab5c37SJack F Vogel 
27424dab5c37SJack F Vogel 	DEBUGFUNC("e1000_set_i2c_bb");
27434dab5c37SJack F Vogel 
27444dab5c37SJack F Vogel 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
27454dab5c37SJack F Vogel 	ctrl_ext |= E1000_CTRL_I2C_ENA;
27464dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
27474dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
27484dab5c37SJack F Vogel 
27494dab5c37SJack F Vogel 	i2cparams = E1000_READ_REG(hw, E1000_I2CPARAMS);
27504dab5c37SJack F Vogel 	i2cparams |= E1000_I2CBB_EN;
27514dab5c37SJack F Vogel 	i2cparams |= E1000_I2C_DATA_OE_N;
27524dab5c37SJack F Vogel 	i2cparams |= E1000_I2C_CLK_OE_N;
27534dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cparams);
27544dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
27554dab5c37SJack F Vogel 
27564dab5c37SJack F Vogel 	return ret_val;
27574dab5c37SJack F Vogel }
27584dab5c37SJack F Vogel 
27594dab5c37SJack F Vogel /**
27604dab5c37SJack F Vogel  *  e1000_read_i2c_byte_generic - Reads 8 bit word over I2C
27614dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
27624dab5c37SJack F Vogel  *  @byte_offset: byte offset to read
2763*ab5d0362SJack F Vogel  *  @dev_addr: device address
27644dab5c37SJack F Vogel  *  @data: value read
27654dab5c37SJack F Vogel  *
27664dab5c37SJack F Vogel  *  Performs byte read operation over I2C interface at
27674dab5c37SJack F Vogel  *  a specified device address.
27684dab5c37SJack F Vogel  **/
27694dab5c37SJack F Vogel s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
27704dab5c37SJack F Vogel 				u8 dev_addr, u8 *data)
27714dab5c37SJack F Vogel {
27724dab5c37SJack F Vogel 	s32 status = E1000_SUCCESS;
27734dab5c37SJack F Vogel 	u32 max_retry = 10;
27744dab5c37SJack F Vogel 	u32 retry = 1;
27754dab5c37SJack F Vogel 	u16 swfw_mask = 0;
27764dab5c37SJack F Vogel 
2777*ab5d0362SJack F Vogel 	bool nack = TRUE;
27784dab5c37SJack F Vogel 
27794dab5c37SJack F Vogel 	DEBUGFUNC("e1000_read_i2c_byte_generic");
27804dab5c37SJack F Vogel 
27814dab5c37SJack F Vogel 	swfw_mask = E1000_SWFW_PHY0_SM;
27824dab5c37SJack F Vogel 
27834dab5c37SJack F Vogel 	do {
2784*ab5d0362SJack F Vogel 		if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)
27854dab5c37SJack F Vogel 		    != E1000_SUCCESS) {
27864dab5c37SJack F Vogel 			status = E1000_ERR_SWFW_SYNC;
27874dab5c37SJack F Vogel 			goto read_byte_out;
27884dab5c37SJack F Vogel 		}
27894dab5c37SJack F Vogel 
27904dab5c37SJack F Vogel 		e1000_i2c_start(hw);
27914dab5c37SJack F Vogel 
27924dab5c37SJack F Vogel 		/* Device Address and write indication */
27934dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, dev_addr);
27944dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
27954dab5c37SJack F Vogel 			goto fail;
27964dab5c37SJack F Vogel 
27974dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
27984dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
27994dab5c37SJack F Vogel 			goto fail;
28004dab5c37SJack F Vogel 
28014dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, byte_offset);
28024dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28034dab5c37SJack F Vogel 			goto fail;
28044dab5c37SJack F Vogel 
28054dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
28064dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28074dab5c37SJack F Vogel 			goto fail;
28084dab5c37SJack F Vogel 
28094dab5c37SJack F Vogel 		e1000_i2c_start(hw);
28104dab5c37SJack F Vogel 
28114dab5c37SJack F Vogel 		/* Device Address and read indication */
28124dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, (dev_addr | 0x1));
28134dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28144dab5c37SJack F Vogel 			goto fail;
28154dab5c37SJack F Vogel 
28164dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
28174dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28184dab5c37SJack F Vogel 			goto fail;
28194dab5c37SJack F Vogel 
28204dab5c37SJack F Vogel 		status = e1000_clock_in_i2c_byte(hw, data);
28214dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28224dab5c37SJack F Vogel 			goto fail;
28234dab5c37SJack F Vogel 
28244dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_bit(hw, nack);
28254dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28264dab5c37SJack F Vogel 			goto fail;
28274dab5c37SJack F Vogel 
28284dab5c37SJack F Vogel 		e1000_i2c_stop(hw);
28294dab5c37SJack F Vogel 		break;
28304dab5c37SJack F Vogel 
28314dab5c37SJack F Vogel fail:
2832*ab5d0362SJack F Vogel 		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
28334dab5c37SJack F Vogel 		msec_delay(100);
28344dab5c37SJack F Vogel 		e1000_i2c_bus_clear(hw);
28354dab5c37SJack F Vogel 		retry++;
28364dab5c37SJack F Vogel 		if (retry < max_retry)
28374dab5c37SJack F Vogel 			DEBUGOUT("I2C byte read error - Retrying.\n");
28384dab5c37SJack F Vogel 		else
28394dab5c37SJack F Vogel 			DEBUGOUT("I2C byte read error.\n");
28404dab5c37SJack F Vogel 
28414dab5c37SJack F Vogel 	} while (retry < max_retry);
28424dab5c37SJack F Vogel 
2843*ab5d0362SJack F Vogel 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
28444dab5c37SJack F Vogel 
28454dab5c37SJack F Vogel read_byte_out:
28464dab5c37SJack F Vogel 
28474dab5c37SJack F Vogel 	return status;
28484dab5c37SJack F Vogel }
28494dab5c37SJack F Vogel 
28504dab5c37SJack F Vogel /**
28514dab5c37SJack F Vogel  *  e1000_write_i2c_byte_generic - Writes 8 bit word over I2C
28524dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
28534dab5c37SJack F Vogel  *  @byte_offset: byte offset to write
2854*ab5d0362SJack F Vogel  *  @dev_addr: device address
28554dab5c37SJack F Vogel  *  @data: value to write
28564dab5c37SJack F Vogel  *
28574dab5c37SJack F Vogel  *  Performs byte write operation over I2C interface at
28584dab5c37SJack F Vogel  *  a specified device address.
28594dab5c37SJack F Vogel  **/
28604dab5c37SJack F Vogel s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
28614dab5c37SJack F Vogel 				 u8 dev_addr, u8 data)
28624dab5c37SJack F Vogel {
28634dab5c37SJack F Vogel 	s32 status = E1000_SUCCESS;
28644dab5c37SJack F Vogel 	u32 max_retry = 1;
28654dab5c37SJack F Vogel 	u32 retry = 0;
28664dab5c37SJack F Vogel 	u16 swfw_mask = 0;
28674dab5c37SJack F Vogel 
28684dab5c37SJack F Vogel 	DEBUGFUNC("e1000_write_i2c_byte_generic");
28694dab5c37SJack F Vogel 
28704dab5c37SJack F Vogel 	swfw_mask = E1000_SWFW_PHY0_SM;
28714dab5c37SJack F Vogel 
2872*ab5d0362SJack F Vogel 	if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) {
28734dab5c37SJack F Vogel 		status = E1000_ERR_SWFW_SYNC;
28744dab5c37SJack F Vogel 		goto write_byte_out;
28754dab5c37SJack F Vogel 	}
28764dab5c37SJack F Vogel 
28774dab5c37SJack F Vogel 	do {
28784dab5c37SJack F Vogel 		e1000_i2c_start(hw);
28794dab5c37SJack F Vogel 
28804dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, dev_addr);
28814dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28824dab5c37SJack F Vogel 			goto fail;
28834dab5c37SJack F Vogel 
28844dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
28854dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28864dab5c37SJack F Vogel 			goto fail;
28874dab5c37SJack F Vogel 
28884dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, byte_offset);
28894dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28904dab5c37SJack F Vogel 			goto fail;
28914dab5c37SJack F Vogel 
28924dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
28934dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28944dab5c37SJack F Vogel 			goto fail;
28954dab5c37SJack F Vogel 
28964dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_byte(hw, data);
28974dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
28984dab5c37SJack F Vogel 			goto fail;
28994dab5c37SJack F Vogel 
29004dab5c37SJack F Vogel 		status = e1000_get_i2c_ack(hw);
29014dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
29024dab5c37SJack F Vogel 			goto fail;
29034dab5c37SJack F Vogel 
29044dab5c37SJack F Vogel 		e1000_i2c_stop(hw);
29054dab5c37SJack F Vogel 		break;
29064dab5c37SJack F Vogel 
29074dab5c37SJack F Vogel fail:
29084dab5c37SJack F Vogel 		e1000_i2c_bus_clear(hw);
29094dab5c37SJack F Vogel 		retry++;
29104dab5c37SJack F Vogel 		if (retry < max_retry)
29114dab5c37SJack F Vogel 			DEBUGOUT("I2C byte write error - Retrying.\n");
29124dab5c37SJack F Vogel 		else
29134dab5c37SJack F Vogel 			DEBUGOUT("I2C byte write error.\n");
29144dab5c37SJack F Vogel 	} while (retry < max_retry);
29154dab5c37SJack F Vogel 
2916*ab5d0362SJack F Vogel 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
29174dab5c37SJack F Vogel 
29184dab5c37SJack F Vogel write_byte_out:
29194dab5c37SJack F Vogel 
29204dab5c37SJack F Vogel 	return status;
29214dab5c37SJack F Vogel }
29224dab5c37SJack F Vogel 
29234dab5c37SJack F Vogel /**
29244dab5c37SJack F Vogel  *  e1000_i2c_start - Sets I2C start condition
29254dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
29264dab5c37SJack F Vogel  *
29274dab5c37SJack F Vogel  *  Sets I2C start condition (High -> Low on SDA while SCL is High)
29284dab5c37SJack F Vogel  **/
29294dab5c37SJack F Vogel static void e1000_i2c_start(struct e1000_hw *hw)
29304dab5c37SJack F Vogel {
29314dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
29324dab5c37SJack F Vogel 
29334dab5c37SJack F Vogel 	DEBUGFUNC("e1000_i2c_start");
29344dab5c37SJack F Vogel 
29354dab5c37SJack F Vogel 	/* Start condition must begin with data and clock high */
29364dab5c37SJack F Vogel 	e1000_set_i2c_data(hw, &i2cctl, 1);
29374dab5c37SJack F Vogel 	e1000_raise_i2c_clk(hw, &i2cctl);
29384dab5c37SJack F Vogel 
29394dab5c37SJack F Vogel 	/* Setup time for start condition (4.7us) */
29404dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_SU_STA);
29414dab5c37SJack F Vogel 
29424dab5c37SJack F Vogel 	e1000_set_i2c_data(hw, &i2cctl, 0);
29434dab5c37SJack F Vogel 
29444dab5c37SJack F Vogel 	/* Hold time for start condition (4us) */
29454dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_HD_STA);
29464dab5c37SJack F Vogel 
29474dab5c37SJack F Vogel 	e1000_lower_i2c_clk(hw, &i2cctl);
29484dab5c37SJack F Vogel 
29494dab5c37SJack F Vogel 	/* Minimum low period of clock is 4.7 us */
29504dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_LOW);
29514dab5c37SJack F Vogel 
29524dab5c37SJack F Vogel }
29534dab5c37SJack F Vogel 
29544dab5c37SJack F Vogel /**
29554dab5c37SJack F Vogel  *  e1000_i2c_stop - Sets I2C stop condition
29564dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
29574dab5c37SJack F Vogel  *
29584dab5c37SJack F Vogel  *  Sets I2C stop condition (Low -> High on SDA while SCL is High)
29594dab5c37SJack F Vogel  **/
29604dab5c37SJack F Vogel static void e1000_i2c_stop(struct e1000_hw *hw)
29614dab5c37SJack F Vogel {
29624dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
29634dab5c37SJack F Vogel 
29644dab5c37SJack F Vogel 	DEBUGFUNC("e1000_i2c_stop");
29654dab5c37SJack F Vogel 
29664dab5c37SJack F Vogel 	/* Stop condition must begin with data low and clock high */
29674dab5c37SJack F Vogel 	e1000_set_i2c_data(hw, &i2cctl, 0);
29684dab5c37SJack F Vogel 	e1000_raise_i2c_clk(hw, &i2cctl);
29694dab5c37SJack F Vogel 
29704dab5c37SJack F Vogel 	/* Setup time for stop condition (4us) */
29714dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_SU_STO);
29724dab5c37SJack F Vogel 
29734dab5c37SJack F Vogel 	e1000_set_i2c_data(hw, &i2cctl, 1);
29744dab5c37SJack F Vogel 
29754dab5c37SJack F Vogel 	/* bus free time between stop and start (4.7us)*/
29764dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_BUF);
29774dab5c37SJack F Vogel }
29784dab5c37SJack F Vogel 
29794dab5c37SJack F Vogel /**
29804dab5c37SJack F Vogel  *  e1000_clock_in_i2c_byte - Clocks in one byte via I2C
29814dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
29824dab5c37SJack F Vogel  *  @data: data byte to clock in
29834dab5c37SJack F Vogel  *
29844dab5c37SJack F Vogel  *  Clocks in one byte data via I2C data/clock
29854dab5c37SJack F Vogel  **/
29864dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data)
29874dab5c37SJack F Vogel {
29884dab5c37SJack F Vogel 	s32 i;
29894dab5c37SJack F Vogel 	bool bit = 0;
29904dab5c37SJack F Vogel 
29914dab5c37SJack F Vogel 	DEBUGFUNC("e1000_clock_in_i2c_byte");
29924dab5c37SJack F Vogel 
29934dab5c37SJack F Vogel 	*data = 0;
29944dab5c37SJack F Vogel 	for (i = 7; i >= 0; i--) {
29954dab5c37SJack F Vogel 		e1000_clock_in_i2c_bit(hw, &bit);
29964dab5c37SJack F Vogel 		*data |= bit << i;
29974dab5c37SJack F Vogel 	}
29984dab5c37SJack F Vogel 
29994dab5c37SJack F Vogel 	return E1000_SUCCESS;
30004dab5c37SJack F Vogel }
30014dab5c37SJack F Vogel 
30024dab5c37SJack F Vogel /**
30034dab5c37SJack F Vogel  *  e1000_clock_out_i2c_byte - Clocks out one byte via I2C
30044dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
30054dab5c37SJack F Vogel  *  @data: data byte clocked out
30064dab5c37SJack F Vogel  *
30074dab5c37SJack F Vogel  *  Clocks out one byte data via I2C data/clock
30084dab5c37SJack F Vogel  **/
30094dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data)
30104dab5c37SJack F Vogel {
30114dab5c37SJack F Vogel 	s32 status = E1000_SUCCESS;
30124dab5c37SJack F Vogel 	s32 i;
30134dab5c37SJack F Vogel 	u32 i2cctl;
30144dab5c37SJack F Vogel 	bool bit = 0;
30154dab5c37SJack F Vogel 
30164dab5c37SJack F Vogel 	DEBUGFUNC("e1000_clock_out_i2c_byte");
30174dab5c37SJack F Vogel 
30184dab5c37SJack F Vogel 	for (i = 7; i >= 0; i--) {
30194dab5c37SJack F Vogel 		bit = (data >> i) & 0x1;
30204dab5c37SJack F Vogel 		status = e1000_clock_out_i2c_bit(hw, bit);
30214dab5c37SJack F Vogel 
30224dab5c37SJack F Vogel 		if (status != E1000_SUCCESS)
30234dab5c37SJack F Vogel 			break;
30244dab5c37SJack F Vogel 	}
30254dab5c37SJack F Vogel 
30264dab5c37SJack F Vogel 	/* Release SDA line (set high) */
30274dab5c37SJack F Vogel 	i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
30284dab5c37SJack F Vogel 
30294dab5c37SJack F Vogel 	i2cctl |= E1000_I2C_DATA_OE_N;
30304dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl);
30314dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
30324dab5c37SJack F Vogel 
30334dab5c37SJack F Vogel 	return status;
30344dab5c37SJack F Vogel }
30354dab5c37SJack F Vogel 
30364dab5c37SJack F Vogel /**
30374dab5c37SJack F Vogel  *  e1000_get_i2c_ack - Polls for I2C ACK
30384dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
30394dab5c37SJack F Vogel  *
30404dab5c37SJack F Vogel  *  Clocks in/out one bit via I2C data/clock
30414dab5c37SJack F Vogel  **/
30424dab5c37SJack F Vogel static s32 e1000_get_i2c_ack(struct e1000_hw *hw)
30434dab5c37SJack F Vogel {
30444dab5c37SJack F Vogel 	s32 status = E1000_SUCCESS;
30454dab5c37SJack F Vogel 	u32 i = 0;
30464dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
30474dab5c37SJack F Vogel 	u32 timeout = 10;
3048*ab5d0362SJack F Vogel 	bool ack = TRUE;
30494dab5c37SJack F Vogel 
30504dab5c37SJack F Vogel 	DEBUGFUNC("e1000_get_i2c_ack");
30514dab5c37SJack F Vogel 
30524dab5c37SJack F Vogel 	e1000_raise_i2c_clk(hw, &i2cctl);
30534dab5c37SJack F Vogel 
30544dab5c37SJack F Vogel 	/* Minimum high period of clock is 4us */
30554dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_HIGH);
30564dab5c37SJack F Vogel 
30574dab5c37SJack F Vogel 	/* Wait until SCL returns high */
30584dab5c37SJack F Vogel 	for (i = 0; i < timeout; i++) {
30594dab5c37SJack F Vogel 		usec_delay(1);
30604dab5c37SJack F Vogel 		i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
30614dab5c37SJack F Vogel 		if (i2cctl & E1000_I2C_CLK_IN)
30624dab5c37SJack F Vogel 			break;
30634dab5c37SJack F Vogel 	}
30644dab5c37SJack F Vogel 	if (!(i2cctl & E1000_I2C_CLK_IN))
30654dab5c37SJack F Vogel 		return E1000_ERR_I2C;
30664dab5c37SJack F Vogel 
30674dab5c37SJack F Vogel 	ack = e1000_get_i2c_data(&i2cctl);
3068*ab5d0362SJack F Vogel 	if (ack) {
30694dab5c37SJack F Vogel 		DEBUGOUT("I2C ack was not received.\n");
30704dab5c37SJack F Vogel 		status = E1000_ERR_I2C;
30714dab5c37SJack F Vogel 	}
30724dab5c37SJack F Vogel 
30734dab5c37SJack F Vogel 	e1000_lower_i2c_clk(hw, &i2cctl);
30744dab5c37SJack F Vogel 
30754dab5c37SJack F Vogel 	/* Minimum low period of clock is 4.7 us */
30764dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_LOW);
30774dab5c37SJack F Vogel 
30784dab5c37SJack F Vogel 	return status;
30794dab5c37SJack F Vogel }
30804dab5c37SJack F Vogel 
30814dab5c37SJack F Vogel /**
30824dab5c37SJack F Vogel  *  e1000_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
30834dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
30844dab5c37SJack F Vogel  *  @data: read data value
30854dab5c37SJack F Vogel  *
30864dab5c37SJack F Vogel  *  Clocks in one bit via I2C data/clock
30874dab5c37SJack F Vogel  **/
30884dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data)
30894dab5c37SJack F Vogel {
30904dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
30914dab5c37SJack F Vogel 
30924dab5c37SJack F Vogel 	DEBUGFUNC("e1000_clock_in_i2c_bit");
30934dab5c37SJack F Vogel 
30944dab5c37SJack F Vogel 	e1000_raise_i2c_clk(hw, &i2cctl);
30954dab5c37SJack F Vogel 
30964dab5c37SJack F Vogel 	/* Minimum high period of clock is 4us */
30974dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_HIGH);
30984dab5c37SJack F Vogel 
30994dab5c37SJack F Vogel 	i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
31004dab5c37SJack F Vogel 	*data = e1000_get_i2c_data(&i2cctl);
31014dab5c37SJack F Vogel 
31024dab5c37SJack F Vogel 	e1000_lower_i2c_clk(hw, &i2cctl);
31034dab5c37SJack F Vogel 
31044dab5c37SJack F Vogel 	/* Minimum low period of clock is 4.7 us */
31054dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_LOW);
31064dab5c37SJack F Vogel 
31074dab5c37SJack F Vogel 	return E1000_SUCCESS;
31084dab5c37SJack F Vogel }
31094dab5c37SJack F Vogel 
31104dab5c37SJack F Vogel /**
31114dab5c37SJack F Vogel  *  e1000_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
31124dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
31134dab5c37SJack F Vogel  *  @data: data value to write
31144dab5c37SJack F Vogel  *
31154dab5c37SJack F Vogel  *  Clocks out one bit via I2C data/clock
31164dab5c37SJack F Vogel  **/
31174dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data)
31184dab5c37SJack F Vogel {
31194dab5c37SJack F Vogel 	s32 status;
31204dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
31214dab5c37SJack F Vogel 
31224dab5c37SJack F Vogel 	DEBUGFUNC("e1000_clock_out_i2c_bit");
31234dab5c37SJack F Vogel 
31244dab5c37SJack F Vogel 	status = e1000_set_i2c_data(hw, &i2cctl, data);
31254dab5c37SJack F Vogel 	if (status == E1000_SUCCESS) {
31264dab5c37SJack F Vogel 		e1000_raise_i2c_clk(hw, &i2cctl);
31274dab5c37SJack F Vogel 
31284dab5c37SJack F Vogel 		/* Minimum high period of clock is 4us */
31294dab5c37SJack F Vogel 		usec_delay(E1000_I2C_T_HIGH);
31304dab5c37SJack F Vogel 
31314dab5c37SJack F Vogel 		e1000_lower_i2c_clk(hw, &i2cctl);
31324dab5c37SJack F Vogel 
31334dab5c37SJack F Vogel 		/* Minimum low period of clock is 4.7 us.
31344dab5c37SJack F Vogel 		 * This also takes care of the data hold time.
31354dab5c37SJack F Vogel 		 */
31364dab5c37SJack F Vogel 		usec_delay(E1000_I2C_T_LOW);
31374dab5c37SJack F Vogel 	} else {
31384dab5c37SJack F Vogel 		status = E1000_ERR_I2C;
31394dab5c37SJack F Vogel 		DEBUGOUT1("I2C data was not set to %X\n", data);
31404dab5c37SJack F Vogel 	}
31414dab5c37SJack F Vogel 
31424dab5c37SJack F Vogel 	return status;
31434dab5c37SJack F Vogel }
31444dab5c37SJack F Vogel /**
31454dab5c37SJack F Vogel  *  e1000_raise_i2c_clk - Raises the I2C SCL clock
31464dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
31474dab5c37SJack F Vogel  *  @i2cctl: Current value of I2CCTL register
31484dab5c37SJack F Vogel  *
31494dab5c37SJack F Vogel  *  Raises the I2C clock line '0'->'1'
31504dab5c37SJack F Vogel  **/
31514dab5c37SJack F Vogel static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
31524dab5c37SJack F Vogel {
31534dab5c37SJack F Vogel 	DEBUGFUNC("e1000_raise_i2c_clk");
31544dab5c37SJack F Vogel 
31554dab5c37SJack F Vogel 	*i2cctl |= E1000_I2C_CLK_OUT;
31564dab5c37SJack F Vogel 	*i2cctl &= ~E1000_I2C_CLK_OE_N;
31574dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
31584dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
31594dab5c37SJack F Vogel 
31604dab5c37SJack F Vogel 	/* SCL rise time (1000ns) */
31614dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_RISE);
31624dab5c37SJack F Vogel }
31634dab5c37SJack F Vogel 
31644dab5c37SJack F Vogel /**
31654dab5c37SJack F Vogel  *  e1000_lower_i2c_clk - Lowers the I2C SCL clock
31664dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
31674dab5c37SJack F Vogel  *  @i2cctl: Current value of I2CCTL register
31684dab5c37SJack F Vogel  *
31694dab5c37SJack F Vogel  *  Lowers the I2C clock line '1'->'0'
31704dab5c37SJack F Vogel  **/
31714dab5c37SJack F Vogel static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
31724dab5c37SJack F Vogel {
31734dab5c37SJack F Vogel 
31744dab5c37SJack F Vogel 	DEBUGFUNC("e1000_lower_i2c_clk");
31754dab5c37SJack F Vogel 
31764dab5c37SJack F Vogel 	*i2cctl &= ~E1000_I2C_CLK_OUT;
31774dab5c37SJack F Vogel 	*i2cctl &= ~E1000_I2C_CLK_OE_N;
31784dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
31794dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
31804dab5c37SJack F Vogel 
31814dab5c37SJack F Vogel 	/* SCL fall time (300ns) */
31824dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_FALL);
31834dab5c37SJack F Vogel }
31844dab5c37SJack F Vogel 
31854dab5c37SJack F Vogel /**
31864dab5c37SJack F Vogel  *  e1000_set_i2c_data - Sets the I2C data bit
31874dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
31884dab5c37SJack F Vogel  *  @i2cctl: Current value of I2CCTL register
31894dab5c37SJack F Vogel  *  @data: I2C data value (0 or 1) to set
31904dab5c37SJack F Vogel  *
31914dab5c37SJack F Vogel  *  Sets the I2C data bit
31924dab5c37SJack F Vogel  **/
31934dab5c37SJack F Vogel static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data)
31944dab5c37SJack F Vogel {
31954dab5c37SJack F Vogel 	s32 status = E1000_SUCCESS;
31964dab5c37SJack F Vogel 
31974dab5c37SJack F Vogel 	DEBUGFUNC("e1000_set_i2c_data");
31984dab5c37SJack F Vogel 
31994dab5c37SJack F Vogel 	if (data)
32004dab5c37SJack F Vogel 		*i2cctl |= E1000_I2C_DATA_OUT;
32014dab5c37SJack F Vogel 	else
32024dab5c37SJack F Vogel 		*i2cctl &= ~E1000_I2C_DATA_OUT;
32034dab5c37SJack F Vogel 
32044dab5c37SJack F Vogel 	*i2cctl &= ~E1000_I2C_DATA_OE_N;
32054dab5c37SJack F Vogel 	*i2cctl |= E1000_I2C_CLK_OE_N;
32064dab5c37SJack F Vogel 	E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
32074dab5c37SJack F Vogel 	E1000_WRITE_FLUSH(hw);
32084dab5c37SJack F Vogel 
32094dab5c37SJack F Vogel 	/* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
32104dab5c37SJack F Vogel 	usec_delay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA);
32114dab5c37SJack F Vogel 
32124dab5c37SJack F Vogel 	*i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
32134dab5c37SJack F Vogel 	if (data != e1000_get_i2c_data(i2cctl)) {
32144dab5c37SJack F Vogel 		status = E1000_ERR_I2C;
32154dab5c37SJack F Vogel 		DEBUGOUT1("Error - I2C data was not set to %X.\n", data);
32164dab5c37SJack F Vogel 	}
32174dab5c37SJack F Vogel 
32184dab5c37SJack F Vogel 	return status;
32194dab5c37SJack F Vogel }
32204dab5c37SJack F Vogel 
32214dab5c37SJack F Vogel /**
32224dab5c37SJack F Vogel  *  e1000_get_i2c_data - Reads the I2C SDA data bit
32234dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
32244dab5c37SJack F Vogel  *  @i2cctl: Current value of I2CCTL register
32254dab5c37SJack F Vogel  *
32264dab5c37SJack F Vogel  *  Returns the I2C data bit value
32274dab5c37SJack F Vogel  **/
32284dab5c37SJack F Vogel static bool e1000_get_i2c_data(u32 *i2cctl)
32294dab5c37SJack F Vogel {
32304dab5c37SJack F Vogel 	bool data;
32314dab5c37SJack F Vogel 
32324dab5c37SJack F Vogel 	DEBUGFUNC("e1000_get_i2c_data");
32334dab5c37SJack F Vogel 
32344dab5c37SJack F Vogel 	if (*i2cctl & E1000_I2C_DATA_IN)
32354dab5c37SJack F Vogel 		data = 1;
32364dab5c37SJack F Vogel 	else
32374dab5c37SJack F Vogel 		data = 0;
32384dab5c37SJack F Vogel 
32394dab5c37SJack F Vogel 	return data;
32404dab5c37SJack F Vogel }
32414dab5c37SJack F Vogel 
32424dab5c37SJack F Vogel /**
32434dab5c37SJack F Vogel  *  e1000_i2c_bus_clear - Clears the I2C bus
32444dab5c37SJack F Vogel  *  @hw: pointer to hardware structure
32454dab5c37SJack F Vogel  *
32464dab5c37SJack F Vogel  *  Clears the I2C bus by sending nine clock pulses.
32474dab5c37SJack F Vogel  *  Used when data line is stuck low.
32484dab5c37SJack F Vogel  **/
32494dab5c37SJack F Vogel void e1000_i2c_bus_clear(struct e1000_hw *hw)
32504dab5c37SJack F Vogel {
32514dab5c37SJack F Vogel 	u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
32524dab5c37SJack F Vogel 	u32 i;
32534dab5c37SJack F Vogel 
32544dab5c37SJack F Vogel 	DEBUGFUNC("e1000_i2c_bus_clear");
32554dab5c37SJack F Vogel 
32564dab5c37SJack F Vogel 	e1000_i2c_start(hw);
32574dab5c37SJack F Vogel 
32584dab5c37SJack F Vogel 	e1000_set_i2c_data(hw, &i2cctl, 1);
32594dab5c37SJack F Vogel 
32604dab5c37SJack F Vogel 	for (i = 0; i < 9; i++) {
32614dab5c37SJack F Vogel 		e1000_raise_i2c_clk(hw, &i2cctl);
32624dab5c37SJack F Vogel 
32634dab5c37SJack F Vogel 		/* Min high period of clock is 4us */
32644dab5c37SJack F Vogel 		usec_delay(E1000_I2C_T_HIGH);
32654dab5c37SJack F Vogel 
32664dab5c37SJack F Vogel 		e1000_lower_i2c_clk(hw, &i2cctl);
32674dab5c37SJack F Vogel 
32684dab5c37SJack F Vogel 		/* Min low period of clock is 4.7us*/
32694dab5c37SJack F Vogel 		usec_delay(E1000_I2C_T_LOW);
32704dab5c37SJack F Vogel 	}
32714dab5c37SJack F Vogel 
32724dab5c37SJack F Vogel 	e1000_i2c_start(hw);
32734dab5c37SJack F Vogel 
32744dab5c37SJack F Vogel 	/* Put the i2c bus back to default state */
32754dab5c37SJack F Vogel 	e1000_i2c_stop(hw);
32764dab5c37SJack F Vogel }
32774dab5c37SJack F Vogel 
3278