xref: /onnv-gate/usr/src/uts/common/io/igb/igb_82575.c (revision 12111:a462ebfcbf99)
15779Sxy150489 /*
25779Sxy150489  * CDDL HEADER START
35779Sxy150489  *
45779Sxy150489  * The contents of this file are subject to the terms of the
55779Sxy150489  * Common Development and Distribution License (the "License").
65779Sxy150489  * You may not use this file except in compliance with the License.
75779Sxy150489  *
8*12111SGuoqing.Zhu@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12111SGuoqing.Zhu@Sun.COM  * or http://www.opensolaris.org/os/licensing.
105779Sxy150489  * See the License for the specific language governing permissions
115779Sxy150489  * and limitations under the License.
125779Sxy150489  *
13*12111SGuoqing.Zhu@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*12111SGuoqing.Zhu@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155779Sxy150489  * If applicable, add the following below this CDDL HEADER, with the
165779Sxy150489  * fields enclosed by brackets "[]" replaced with your own identifying
175779Sxy150489  * information: Portions Copyright [yyyy] [name of copyright owner]
185779Sxy150489  *
195779Sxy150489  * CDDL HEADER END
205779Sxy150489  */
215779Sxy150489 
225779Sxy150489 /*
23*12111SGuoqing.Zhu@Sun.COM  * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
245779Sxy150489  */
255779Sxy150489 
26*12111SGuoqing.Zhu@Sun.COM /*
27*12111SGuoqing.Zhu@Sun.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28*12111SGuoqing.Zhu@Sun.COM  */
29*12111SGuoqing.Zhu@Sun.COM 
30*12111SGuoqing.Zhu@Sun.COM /* IntelVersion: 1.146.2.2 v3_3_14_3_BHSW1 */
315779Sxy150489 
325779Sxy150489 /*
338571SChenlu.Chen@Sun.COM  * 82575EB Gigabit Network Connection
348571SChenlu.Chen@Sun.COM  * 82575EB Gigabit Backplane Connection
358571SChenlu.Chen@Sun.COM  * 82575GB Gigabit Network Connection
368571SChenlu.Chen@Sun.COM  * 82576 Gigabit Network Connection
3710319SJason.Xu@Sun.COM  * 82576 Quad Port Gigabit Mezzanine Adapter
385779Sxy150489  */
395779Sxy150489 
405779Sxy150489 #include "igb_api.h"
415779Sxy150489 
425779Sxy150489 static s32 e1000_init_phy_params_82575(struct e1000_hw *hw);
435779Sxy150489 static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw);
445779Sxy150489 static s32 e1000_init_mac_params_82575(struct e1000_hw *hw);
455779Sxy150489 static s32 e1000_acquire_phy_82575(struct e1000_hw *hw);
465779Sxy150489 static void e1000_release_phy_82575(struct e1000_hw *hw);
475779Sxy150489 static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw);
485779Sxy150489 static void e1000_release_nvm_82575(struct e1000_hw *hw);
495779Sxy150489 static s32 e1000_check_for_link_82575(struct e1000_hw *hw);
505779Sxy150489 static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw);
515779Sxy150489 static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
525779Sxy150489     u16 *duplex);
535779Sxy150489 static s32 e1000_init_hw_82575(struct e1000_hw *hw);
545779Sxy150489 static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw);
555779Sxy150489 static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
565779Sxy150489     u16 *data);
575779Sxy150489 static s32 e1000_reset_hw_82575(struct e1000_hw *hw);
5811155SJason.Xu@Sun.COM static s32 e1000_reset_hw_82580(struct e1000_hw *hw);
5911155SJason.Xu@Sun.COM static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset,
6011155SJason.Xu@Sun.COM     u16 *data);
6111155SJason.Xu@Sun.COM static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset,
6211155SJason.Xu@Sun.COM     u16 data);
635779Sxy150489 static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw,
645779Sxy150489     bool active);
655779Sxy150489 static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw);
6611155SJason.Xu@Sun.COM static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw);
678571SChenlu.Chen@Sun.COM static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data);
685779Sxy150489 static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw,
695779Sxy150489     u32 offset, u16 data);
705779Sxy150489 static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw);
715779Sxy150489 static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
725779Sxy150489 static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
735779Sxy150489     u16 *speed, u16 *duplex);
745779Sxy150489 static s32 e1000_get_phy_id_82575(struct e1000_hw *hw);
755779Sxy150489 static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
765779Sxy150489 static bool e1000_sgmii_active_82575(struct e1000_hw *hw);
775779Sxy150489 static s32 e1000_reset_init_script_82575(struct e1000_hw *hw);
785779Sxy150489 static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw);
795779Sxy150489 static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw);
8011155SJason.Xu@Sun.COM static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw);
8110319SJason.Xu@Sun.COM static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw);
825779Sxy150489 
8311155SJason.Xu@Sun.COM static const u16 e1000_82580_rxpbs_table[] =
8411155SJason.Xu@Sun.COM 	{36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140};
8511155SJason.Xu@Sun.COM #define	E1000_82580_RXPBS_TABLE_SIZE \
8611155SJason.Xu@Sun.COM 	(sizeof (e1000_82580_rxpbs_table)/sizeof (u16))
8711155SJason.Xu@Sun.COM 
885779Sxy150489 /*
895779Sxy150489  * e1000_init_phy_params_82575 - Init PHY func ptrs.
905779Sxy150489  * @hw: pointer to the HW structure
915779Sxy150489  */
925779Sxy150489 static s32
e1000_init_phy_params_82575(struct e1000_hw * hw)935779Sxy150489 e1000_init_phy_params_82575(struct e1000_hw *hw)
945779Sxy150489 {
955779Sxy150489 	struct e1000_phy_info *phy = &hw->phy;
965779Sxy150489 	s32 ret_val = E1000_SUCCESS;
975779Sxy150489 
985779Sxy150489 	DEBUGFUNC("e1000_init_phy_params_82575");
995779Sxy150489 
1005779Sxy150489 	if (hw->phy.media_type != e1000_media_type_copper) {
1015779Sxy150489 		phy->type = e1000_phy_none;
1025779Sxy150489 		goto out;
1035779Sxy150489 	}
1045779Sxy150489 
10511155SJason.Xu@Sun.COM 	phy->ops.power_up = e1000_power_up_phy_copper;
10611155SJason.Xu@Sun.COM 	phy->ops.power_down = e1000_power_down_phy_copper_82575;
10711155SJason.Xu@Sun.COM 
1085779Sxy150489 	phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
1095779Sxy150489 	phy->reset_delay_us = 100;
1105779Sxy150489 
1118571SChenlu.Chen@Sun.COM 	phy->ops.acquire = e1000_acquire_phy_82575;
1128571SChenlu.Chen@Sun.COM 	phy->ops.check_reset_block = e1000_check_reset_block_generic;
1138571SChenlu.Chen@Sun.COM 	phy->ops.commit = e1000_phy_sw_reset_generic;
1148571SChenlu.Chen@Sun.COM 	phy->ops.get_cfg_done = e1000_get_cfg_done_82575;
1158571SChenlu.Chen@Sun.COM 	phy->ops.release = e1000_release_phy_82575;
1165779Sxy150489 
1175779Sxy150489 	if (e1000_sgmii_active_82575(hw)) {
1188571SChenlu.Chen@Sun.COM 		phy->ops.reset = e1000_phy_hw_reset_sgmii_82575;
1198571SChenlu.Chen@Sun.COM 		phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575;
1208571SChenlu.Chen@Sun.COM 		phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575;
12111155SJason.Xu@Sun.COM 	} else if (hw->mac.type == e1000_82580) {
12211155SJason.Xu@Sun.COM 		phy->ops.reset = e1000_phy_hw_reset_generic;
12311155SJason.Xu@Sun.COM 		phy->ops.read_reg = e1000_read_phy_reg_82580;
12411155SJason.Xu@Sun.COM 		phy->ops.write_reg = e1000_write_phy_reg_82580;
1255779Sxy150489 	} else {
1268571SChenlu.Chen@Sun.COM 		phy->ops.reset = e1000_phy_hw_reset_generic;
1278571SChenlu.Chen@Sun.COM 		phy->ops.read_reg = e1000_read_phy_reg_igp;
1288571SChenlu.Chen@Sun.COM 		phy->ops.write_reg = e1000_write_phy_reg_igp;
1295779Sxy150489 	}
1305779Sxy150489 
1315779Sxy150489 	/* Set phy->phy_addr and phy->id. */
1325779Sxy150489 	ret_val = e1000_get_phy_id_82575(hw);
1335779Sxy150489 
1345779Sxy150489 	/* Verify phy id and set remaining function pointers */
1355779Sxy150489 	switch (phy->id) {
1365779Sxy150489 	case M88E1111_I_PHY_ID:
1375779Sxy150489 		phy->type = e1000_phy_m88;
1388571SChenlu.Chen@Sun.COM 		phy->ops.check_polarity = e1000_check_polarity_m88;
1398571SChenlu.Chen@Sun.COM 		phy->ops.get_info = e1000_get_phy_info_m88;
1408571SChenlu.Chen@Sun.COM 		phy->ops.get_cable_length = e1000_get_cable_length_m88;
1418571SChenlu.Chen@Sun.COM 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
1425779Sxy150489 		break;
1435779Sxy150489 	case IGP03E1000_E_PHY_ID:
1448571SChenlu.Chen@Sun.COM 	case IGP04E1000_E_PHY_ID:
1455779Sxy150489 		phy->type = e1000_phy_igp_3;
1468571SChenlu.Chen@Sun.COM 		phy->ops.check_polarity = e1000_check_polarity_igp;
1478571SChenlu.Chen@Sun.COM 		phy->ops.get_info = e1000_get_phy_info_igp;
1488571SChenlu.Chen@Sun.COM 		phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
1498571SChenlu.Chen@Sun.COM 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
1508571SChenlu.Chen@Sun.COM 		phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575;
1518571SChenlu.Chen@Sun.COM 		phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
1525779Sxy150489 		break;
15311155SJason.Xu@Sun.COM 	case I82580_I_PHY_ID:
15411155SJason.Xu@Sun.COM 		phy->type = e1000_phy_82580;
15511155SJason.Xu@Sun.COM 		phy->ops.check_polarity = e1000_check_polarity_82577;
15611155SJason.Xu@Sun.COM 		phy->ops.force_speed_duplex =
15711155SJason.Xu@Sun.COM 		    e1000_phy_force_speed_duplex_82577;
15811155SJason.Xu@Sun.COM 		phy->ops.get_cable_length = e1000_get_cable_length_82577;
15911155SJason.Xu@Sun.COM 		phy->ops.get_info = e1000_get_phy_info_82577;
16011155SJason.Xu@Sun.COM 		break;
1615779Sxy150489 	default:
1625779Sxy150489 		ret_val = -E1000_ERR_PHY;
1635779Sxy150489 		goto out;
1645779Sxy150489 	}
1655779Sxy150489 
1665779Sxy150489 out:
1675779Sxy150489 	return (ret_val);
1685779Sxy150489 }
1695779Sxy150489 
1705779Sxy150489 /*
1715779Sxy150489  * e1000_init_nvm_params_82575 - Init NVM func ptrs.
1725779Sxy150489  * @hw: pointer to the HW structure
1735779Sxy150489  */
1745779Sxy150489 static s32
e1000_init_nvm_params_82575(struct e1000_hw * hw)1755779Sxy150489 e1000_init_nvm_params_82575(struct e1000_hw *hw)
1765779Sxy150489 {
1775779Sxy150489 	struct e1000_nvm_info *nvm = &hw->nvm;
1785779Sxy150489 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
1795779Sxy150489 	u16 size;
1805779Sxy150489 
1815779Sxy150489 	DEBUGFUNC("e1000_init_nvm_params_82575");
1825779Sxy150489 
1835779Sxy150489 	nvm->opcode_bits = 8;
1845779Sxy150489 	nvm->delay_usec = 1;
1855779Sxy150489 	switch (nvm->override) {
1865779Sxy150489 	case e1000_nvm_override_spi_large:
1875779Sxy150489 		nvm->page_size = 32;
1885779Sxy150489 		nvm->address_bits = 16;
1895779Sxy150489 		break;
1905779Sxy150489 	case e1000_nvm_override_spi_small:
1915779Sxy150489 		nvm->page_size = 8;
1925779Sxy150489 		nvm->address_bits = 8;
1935779Sxy150489 		break;
1945779Sxy150489 	default:
1955779Sxy150489 		nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
1965779Sxy150489 		nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
1975779Sxy150489 		break;
1985779Sxy150489 	}
1995779Sxy150489 
2005779Sxy150489 	nvm->type = e1000_nvm_eeprom_spi;
2015779Sxy150489 
2025779Sxy150489 	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
2035779Sxy150489 	    E1000_EECD_SIZE_EX_SHIFT);
2045779Sxy150489 
2055779Sxy150489 	/*
2065779Sxy150489 	 * Added to a constant, "size" becomes the left-shift value
2075779Sxy150489 	 * for setting word_size.
2085779Sxy150489 	 */
2095779Sxy150489 	size += NVM_WORD_SIZE_BASE_SHIFT;
2105779Sxy150489 
2115779Sxy150489 	/* EEPROM access above 16k is unsupported */
2125779Sxy150489 	if (size > 14)
2135779Sxy150489 		size = 14;
2145779Sxy150489 	nvm->word_size = 1 << size;
2155779Sxy150489 
2165779Sxy150489 	/* Function Pointers */
2178571SChenlu.Chen@Sun.COM 	nvm->ops.acquire = e1000_acquire_nvm_82575;
2188571SChenlu.Chen@Sun.COM 	nvm->ops.read = e1000_read_nvm_eerd;
2198571SChenlu.Chen@Sun.COM 	nvm->ops.release = e1000_release_nvm_82575;
2208571SChenlu.Chen@Sun.COM 	nvm->ops.update = e1000_update_nvm_checksum_generic;
2218571SChenlu.Chen@Sun.COM 	nvm->ops.valid_led_default = e1000_valid_led_default_82575;
2228571SChenlu.Chen@Sun.COM 	nvm->ops.validate = e1000_validate_nvm_checksum_generic;
2238571SChenlu.Chen@Sun.COM 	nvm->ops.write = e1000_write_nvm_spi;
2245779Sxy150489 
2255779Sxy150489 	return (E1000_SUCCESS);
2265779Sxy150489 }
2275779Sxy150489 
2285779Sxy150489 /*
2295779Sxy150489  * e1000_init_mac_params_82575 - Init MAC func ptrs.
2305779Sxy150489  * @hw: pointer to the HW structure
2315779Sxy150489  */
2325779Sxy150489 static s32
e1000_init_mac_params_82575(struct e1000_hw * hw)2335779Sxy150489 e1000_init_mac_params_82575(struct e1000_hw *hw)
2345779Sxy150489 {
2355779Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
2368571SChenlu.Chen@Sun.COM 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
2375779Sxy150489 	u32 ctrl_ext = 0;
2385779Sxy150489 
2395779Sxy150489 	DEBUGFUNC("e1000_init_mac_params_82575");
2405779Sxy150489 
2415779Sxy150489 	/* Set media type */
2425779Sxy150489 	/*
2435779Sxy150489 	 * The 82575 uses bits 22:23 for link mode. The mode can be changed
2445779Sxy150489 	 * based on the EEPROM. We cannot rely upon device ID. There
2455779Sxy150489 	 * is no distinguishable difference between fiber and internal
2465779Sxy150489 	 * SerDes mode on the 82575. There can be an external PHY attached
2478571SChenlu.Chen@Sun.COM 	 * on the SGMII interface. For this, we'll set sgmii_active to true.
2485779Sxy150489 	 */
2495779Sxy150489 	hw->phy.media_type = e1000_media_type_copper;
2508571SChenlu.Chen@Sun.COM 	dev_spec->sgmii_active = false;
2515779Sxy150489 
2525779Sxy150489 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
25311155SJason.Xu@Sun.COM 	switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
25411155SJason.Xu@Sun.COM 	case E1000_CTRL_EXT_LINK_MODE_SGMII:
25511155SJason.Xu@Sun.COM 		dev_spec->sgmii_active = true;
25611155SJason.Xu@Sun.COM 		ctrl_ext |= E1000_CTRL_I2C_ENA;
25711155SJason.Xu@Sun.COM 		break;
25811155SJason.Xu@Sun.COM 	case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
25911155SJason.Xu@Sun.COM 	case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
2605779Sxy150489 		hw->phy.media_type = e1000_media_type_internal_serdes;
2615779Sxy150489 		ctrl_ext |= E1000_CTRL_I2C_ENA;
26211155SJason.Xu@Sun.COM 		break;
26311155SJason.Xu@Sun.COM 	default:
2645779Sxy150489 		ctrl_ext &= ~E1000_CTRL_I2C_ENA;
26511155SJason.Xu@Sun.COM 		break;
2665779Sxy150489 	}
26711155SJason.Xu@Sun.COM 
2685779Sxy150489 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
2695779Sxy150489 
270*12111SGuoqing.Zhu@Sun.COM 	/*
271*12111SGuoqing.Zhu@Sun.COM 	 * if using i2c make certain the MDICNFG register is cleared to prevent
272*12111SGuoqing.Zhu@Sun.COM 	 * communications from being misrouted to the mdic registers
273*12111SGuoqing.Zhu@Sun.COM 	 */
274*12111SGuoqing.Zhu@Sun.COM 	if ((ctrl_ext & E1000_CTRL_I2C_ENA) && (hw->mac.type == e1000_82580))
275*12111SGuoqing.Zhu@Sun.COM 		E1000_WRITE_REG(hw, E1000_MDICNFG, 0);
276*12111SGuoqing.Zhu@Sun.COM 
2775779Sxy150489 	/* Set mta register count */
2785779Sxy150489 	mac->mta_reg_count = 128;
27911155SJason.Xu@Sun.COM 	/* Set uta register count */
28011155SJason.Xu@Sun.COM 	mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128;
2815779Sxy150489 	/* Set rar entry count */
2825779Sxy150489 	mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
2838571SChenlu.Chen@Sun.COM 	if (mac->type == e1000_82576)
2848571SChenlu.Chen@Sun.COM 		mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
28511155SJason.Xu@Sun.COM 	if (mac->type == e1000_82580)
28611155SJason.Xu@Sun.COM 		mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
2875779Sxy150489 	/* Set if part includes ASF firmware */
2888571SChenlu.Chen@Sun.COM 	mac->asf_firmware_present = true;
2895779Sxy150489 	/* Set if manageability features are enabled. */
2905779Sxy150489 	mac->arc_subsystem_valid =
2915779Sxy150489 	    (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK)
2928571SChenlu.Chen@Sun.COM 	    ? true : false;
2935779Sxy150489 
2945779Sxy150489 	/* Function pointers */
2955779Sxy150489 
2965779Sxy150489 	/* bus type/speed/width */
2978571SChenlu.Chen@Sun.COM 	mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
2985779Sxy150489 	/* reset */
29911155SJason.Xu@Sun.COM 	if (mac->type == e1000_82580)
30011155SJason.Xu@Sun.COM 		mac->ops.reset_hw = e1000_reset_hw_82580;
30111155SJason.Xu@Sun.COM 	else
30211155SJason.Xu@Sun.COM 		mac->ops.reset_hw = e1000_reset_hw_82575;
3035779Sxy150489 	/* hw initialization */
3048571SChenlu.Chen@Sun.COM 	mac->ops.init_hw = e1000_init_hw_82575;
3055779Sxy150489 	/* link setup */
3068571SChenlu.Chen@Sun.COM 	mac->ops.setup_link = e1000_setup_link_generic;
3075779Sxy150489 	/* physical interface link setup */
3088571SChenlu.Chen@Sun.COM 	mac->ops.setup_physical_interface =
3095779Sxy150489 	    (hw->phy.media_type == e1000_media_type_copper)
3105779Sxy150489 	    ? e1000_setup_copper_link_82575
31111155SJason.Xu@Sun.COM 	    : e1000_setup_serdes_link_82575;
3128571SChenlu.Chen@Sun.COM 	/* physical interface shutdown */
31311155SJason.Xu@Sun.COM 	mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575;
3145779Sxy150489 	/* check for link */
3158571SChenlu.Chen@Sun.COM 	mac->ops.check_for_link = e1000_check_for_link_82575;
3165779Sxy150489 	/* receive address register setting */
3178571SChenlu.Chen@Sun.COM 	mac->ops.rar_set = e1000_rar_set_generic;
3185779Sxy150489 	/* read mac address */
3198571SChenlu.Chen@Sun.COM 	mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
3205779Sxy150489 	/* multicast address update */
32110319SJason.Xu@Sun.COM 	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
3225779Sxy150489 	/* writing VFTA */
3238571SChenlu.Chen@Sun.COM 	mac->ops.write_vfta = e1000_write_vfta_generic;
3245779Sxy150489 	/* clearing VFTA */
3258571SChenlu.Chen@Sun.COM 	mac->ops.clear_vfta = e1000_clear_vfta_generic;
3265779Sxy150489 	/* setting MTA */
3278571SChenlu.Chen@Sun.COM 	mac->ops.mta_set = e1000_mta_set_generic;
32810319SJason.Xu@Sun.COM 	/* ID LED init */
32910319SJason.Xu@Sun.COM 	mac->ops.id_led_init = e1000_id_led_init_generic;
3305779Sxy150489 	/* blink LED */
3318571SChenlu.Chen@Sun.COM 	mac->ops.blink_led = e1000_blink_led_generic;
3325779Sxy150489 	/* setup LED */
3338571SChenlu.Chen@Sun.COM 	mac->ops.setup_led = e1000_setup_led_generic;
3345779Sxy150489 	/* cleanup LED */
3358571SChenlu.Chen@Sun.COM 	mac->ops.cleanup_led = e1000_cleanup_led_generic;
3365779Sxy150489 	/* turn on/off LED */
3378571SChenlu.Chen@Sun.COM 	mac->ops.led_on = e1000_led_on_generic;
3388571SChenlu.Chen@Sun.COM 	mac->ops.led_off = e1000_led_off_generic;
3395779Sxy150489 	/* clear hardware counters */
3408571SChenlu.Chen@Sun.COM 	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575;
3415779Sxy150489 	/* link info */
3428571SChenlu.Chen@Sun.COM 	mac->ops.get_link_up_info = e1000_get_link_up_info_82575;
3435779Sxy150489 
34411155SJason.Xu@Sun.COM 	/* set lan id for port to determine which phy lock to use */
34511155SJason.Xu@Sun.COM 	hw->mac.ops.set_lan_id(hw);
34611155SJason.Xu@Sun.COM 
3478571SChenlu.Chen@Sun.COM 	return (E1000_SUCCESS);
3485779Sxy150489 }
3495779Sxy150489 
3505779Sxy150489 /*
3515779Sxy150489  * e1000_init_function_pointers_82575 - Init func ptrs.
3525779Sxy150489  * @hw: pointer to the HW structure
3535779Sxy150489  *
3548571SChenlu.Chen@Sun.COM  * Called to initialize all function pointers and parameters.
3555779Sxy150489  */
3565779Sxy150489 void
e1000_init_function_pointers_82575(struct e1000_hw * hw)3575779Sxy150489 e1000_init_function_pointers_82575(struct e1000_hw *hw)
3585779Sxy150489 {
3595779Sxy150489 	DEBUGFUNC("e1000_init_function_pointers_82575");
3605779Sxy150489 
3618571SChenlu.Chen@Sun.COM 	hw->mac.ops.init_params = e1000_init_mac_params_82575;
3628571SChenlu.Chen@Sun.COM 	hw->nvm.ops.init_params = e1000_init_nvm_params_82575;
3638571SChenlu.Chen@Sun.COM 	hw->phy.ops.init_params = e1000_init_phy_params_82575;
3645779Sxy150489 }
3655779Sxy150489 
3665779Sxy150489 /*
3675779Sxy150489  * e1000_acquire_phy_82575 - Acquire rights to access PHY
3685779Sxy150489  * @hw: pointer to the HW structure
3695779Sxy150489  *
3708571SChenlu.Chen@Sun.COM  * Acquire access rights to the correct PHY.
3715779Sxy150489  */
3725779Sxy150489 static s32
e1000_acquire_phy_82575(struct e1000_hw * hw)3735779Sxy150489 e1000_acquire_phy_82575(struct e1000_hw *hw)
3745779Sxy150489 {
37510319SJason.Xu@Sun.COM 	u16 mask = E1000_SWFW_PHY0_SM;
3765779Sxy150489 
3775779Sxy150489 	DEBUGFUNC("e1000_acquire_phy_82575");
3785779Sxy150489 
37910319SJason.Xu@Sun.COM 	if (hw->bus.func == E1000_FUNC_1)
38010319SJason.Xu@Sun.COM 		mask = E1000_SWFW_PHY1_SM;
38111155SJason.Xu@Sun.COM 	else if (hw->bus.func == E1000_FUNC_2)
38211155SJason.Xu@Sun.COM 		mask = E1000_SWFW_PHY2_SM;
38311155SJason.Xu@Sun.COM 	else if (hw->bus.func == E1000_FUNC_3)
38411155SJason.Xu@Sun.COM 		mask = E1000_SWFW_PHY3_SM;
3855779Sxy150489 
3865779Sxy150489 	return (e1000_acquire_swfw_sync_82575(hw, mask));
3875779Sxy150489 }
3885779Sxy150489 
3895779Sxy150489 /*
3905779Sxy150489  * e1000_release_phy_82575 - Release rights to access PHY
3915779Sxy150489  * @hw: pointer to the HW structure
3925779Sxy150489  *
3938571SChenlu.Chen@Sun.COM  * A wrapper to release access rights to the correct PHY.
3945779Sxy150489  */
3955779Sxy150489 static void
e1000_release_phy_82575(struct e1000_hw * hw)3965779Sxy150489 e1000_release_phy_82575(struct e1000_hw *hw)
3975779Sxy150489 {
39810319SJason.Xu@Sun.COM 	u16 mask = E1000_SWFW_PHY0_SM;
3995779Sxy150489 
4005779Sxy150489 	DEBUGFUNC("e1000_release_phy_82575");
4015779Sxy150489 
40210319SJason.Xu@Sun.COM 	if (hw->bus.func == E1000_FUNC_1)
40310319SJason.Xu@Sun.COM 		mask = E1000_SWFW_PHY1_SM;
40411155SJason.Xu@Sun.COM 	else if (hw->bus.func == E1000_FUNC_2)
40511155SJason.Xu@Sun.COM 		mask = E1000_SWFW_PHY2_SM;
40611155SJason.Xu@Sun.COM 	else if (hw->bus.func == E1000_FUNC_3)
40711155SJason.Xu@Sun.COM 		mask = E1000_SWFW_PHY3_SM;
40810319SJason.Xu@Sun.COM 
4095779Sxy150489 	e1000_release_swfw_sync_82575(hw, mask);
4105779Sxy150489 }
4115779Sxy150489 
4125779Sxy150489 /*
4135779Sxy150489  * e1000_read_phy_reg_sgmii_82575 - Read PHY register using sgmii
4145779Sxy150489  * @hw: pointer to the HW structure
4155779Sxy150489  * @offset: register offset to be read
4165779Sxy150489  * @data: pointer to the read data
4175779Sxy150489  *
4185779Sxy150489  * Reads the PHY register at offset using the serial gigabit media independent
4195779Sxy150489  * interface and stores the retrieved information in data.
4205779Sxy150489  */
4215779Sxy150489 static s32
e1000_read_phy_reg_sgmii_82575(struct e1000_hw * hw,u32 offset,u16 * data)4225779Sxy150489 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 *data)
4235779Sxy150489 {
42411155SJason.Xu@Sun.COM 	s32 ret_val = -E1000_ERR_PARAM;
4255779Sxy150489 
4265779Sxy150489 	DEBUGFUNC("e1000_read_phy_reg_sgmii_82575");
4275779Sxy150489 
4285779Sxy150489 	if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
4295779Sxy150489 		DEBUGOUT1("PHY Address %u is out of range\n", offset);
43011155SJason.Xu@Sun.COM 		goto out;
4315779Sxy150489 	}
4325779Sxy150489 
43311155SJason.Xu@Sun.COM 	ret_val = hw->phy.ops.acquire(hw);
43411155SJason.Xu@Sun.COM 	if (ret_val)
43511155SJason.Xu@Sun.COM 		goto out;
4365779Sxy150489 
43711155SJason.Xu@Sun.COM 	ret_val = e1000_read_phy_reg_i2c(hw, offset, data);
4385779Sxy150489 
43911155SJason.Xu@Sun.COM 	hw->phy.ops.release(hw);
4405779Sxy150489 
44111155SJason.Xu@Sun.COM out:
44211155SJason.Xu@Sun.COM 	return (ret_val);
4435779Sxy150489 }
4445779Sxy150489 
4455779Sxy150489 /*
4465779Sxy150489  * e1000_write_phy_reg_sgmii_82575 - Write PHY register using sgmii
4475779Sxy150489  * @hw: pointer to the HW structure
4485779Sxy150489  * @offset: register offset to write to
4495779Sxy150489  * @data: data to write at register offset
4505779Sxy150489  *
4515779Sxy150489  * Writes the data to PHY register at the offset using the serial gigabit
4525779Sxy150489  * media independent interface.
4535779Sxy150489  */
4545779Sxy150489 static s32
e1000_write_phy_reg_sgmii_82575(struct e1000_hw * hw,u32 offset,u16 data)4555779Sxy150489 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 data)
4565779Sxy150489 {
45711155SJason.Xu@Sun.COM 	s32 ret_val = -E1000_ERR_PARAM;
4585779Sxy150489 
4595779Sxy150489 	DEBUGFUNC("e1000_write_phy_reg_sgmii_82575");
4605779Sxy150489 
4615779Sxy150489 	if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
4625779Sxy150489 		DEBUGOUT1("PHY Address %d is out of range\n", offset);
46311155SJason.Xu@Sun.COM 		goto out;
4645779Sxy150489 	}
4655779Sxy150489 
46611155SJason.Xu@Sun.COM 	ret_val = hw->phy.ops.acquire(hw);
46711155SJason.Xu@Sun.COM 	if (ret_val)
46811155SJason.Xu@Sun.COM 		goto out;
4695779Sxy150489 
47011155SJason.Xu@Sun.COM 	ret_val = e1000_write_phy_reg_i2c(hw, offset, data);
4715779Sxy150489 
47211155SJason.Xu@Sun.COM 	hw->phy.ops.release(hw);
47311155SJason.Xu@Sun.COM 
47411155SJason.Xu@Sun.COM out:
47511155SJason.Xu@Sun.COM 	return (ret_val);
4765779Sxy150489 }
4775779Sxy150489 
4785779Sxy150489 /*
4798571SChenlu.Chen@Sun.COM  * e1000_get_phy_id_82575 - Retrieve PHY addr and id
4805779Sxy150489  * @hw: pointer to the HW structure
4815779Sxy150489  *
4828571SChenlu.Chen@Sun.COM  * Retrieves the PHY address and ID for both PHY's which do and do not use
4835779Sxy150489  * sgmi interface.
4845779Sxy150489  */
4855779Sxy150489 static s32
e1000_get_phy_id_82575(struct e1000_hw * hw)4865779Sxy150489 e1000_get_phy_id_82575(struct e1000_hw *hw)
4875779Sxy150489 {
4885779Sxy150489 	struct e1000_phy_info *phy = &hw->phy;
4895779Sxy150489 	s32 ret_val = E1000_SUCCESS;
4905779Sxy150489 	u16 phy_id;
49111155SJason.Xu@Sun.COM 	u32 ctrl_ext;
4925779Sxy150489 
4935779Sxy150489 	DEBUGFUNC("e1000_get_phy_id_82575");
4945779Sxy150489 
4955779Sxy150489 	/*
4965779Sxy150489 	 * For SGMII PHYs, we try the list of possible addresses until
4975779Sxy150489 	 * we find one that works.  For non-SGMII PHYs
4985779Sxy150489 	 * (e.g. integrated copper PHYs), an address of 1 should
4995779Sxy150489 	 * work.  The result of this function should mean phy->phy_addr
5005779Sxy150489 	 * and phy->id are set correctly.
5015779Sxy150489 	 */
50211155SJason.Xu@Sun.COM 	if (!e1000_sgmii_active_82575(hw)) {
5035779Sxy150489 		phy->addr = 1;
5045779Sxy150489 		ret_val = e1000_get_phy_id(hw);
5055779Sxy150489 		goto out;
5065779Sxy150489 	}
5075779Sxy150489 
50811155SJason.Xu@Sun.COM 	/* Power on sgmii phy if it is disabled */
50911155SJason.Xu@Sun.COM 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
51011155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_CTRL_EXT,
51111155SJason.Xu@Sun.COM 	    ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA);
51211155SJason.Xu@Sun.COM 	E1000_WRITE_FLUSH(hw);
51311155SJason.Xu@Sun.COM 	msec_delay(300);
51411155SJason.Xu@Sun.COM 
5155779Sxy150489 	/*
5165779Sxy150489 	 * The address field in the I2CCMD register is 3 bits and 0 is invalid.
5175779Sxy150489 	 * Therefore, we need to test 1-7
5185779Sxy150489 	 */
5195779Sxy150489 	for (phy->addr = 1; phy->addr < 8; phy->addr++) {
5205779Sxy150489 		ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id);
5215779Sxy150489 		if (ret_val == E1000_SUCCESS) {
5225779Sxy150489 			DEBUGOUT2("Vendor ID 0x%08X read at address %u\n",
5235779Sxy150489 			    phy_id,
5245779Sxy150489 			    phy->addr);
5255779Sxy150489 			/*
5265779Sxy150489 			 * At the time of this writing, The M88 part is
5275779Sxy150489 			 * the only supported SGMII PHY product.
5285779Sxy150489 			 */
5295779Sxy150489 			if (phy_id == M88_VENDOR)
5305779Sxy150489 				break;
5315779Sxy150489 		} else {
5325779Sxy150489 			DEBUGOUT1("PHY address %u was unreadable\n",
5335779Sxy150489 			    phy->addr);
5345779Sxy150489 		}
5355779Sxy150489 	}
5365779Sxy150489 
5375779Sxy150489 	/* A valid PHY type couldn't be found. */
5385779Sxy150489 	if (phy->addr == 8) {
5395779Sxy150489 		phy->addr = 0;
5405779Sxy150489 		ret_val = -E1000_ERR_PHY;
54111155SJason.Xu@Sun.COM 	} else {
54211155SJason.Xu@Sun.COM 		ret_val = e1000_get_phy_id(hw);
5435779Sxy150489 	}
5445779Sxy150489 
54511155SJason.Xu@Sun.COM 	/* restore previous sfp cage power state */
54611155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
5475779Sxy150489 
5485779Sxy150489 out:
5495779Sxy150489 	return (ret_val);
5505779Sxy150489 }
5515779Sxy150489 
5525779Sxy150489 /*
5535779Sxy150489  * e1000_phy_hw_reset_sgmii_82575 - Performs a PHY reset
5545779Sxy150489  * @hw: pointer to the HW structure
5555779Sxy150489  *
5565779Sxy150489  * Resets the PHY using the serial gigabit media independent interface.
5575779Sxy150489  */
5585779Sxy150489 static s32
e1000_phy_hw_reset_sgmii_82575(struct e1000_hw * hw)5595779Sxy150489 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw)
5605779Sxy150489 {
5618571SChenlu.Chen@Sun.COM 	s32 ret_val = E1000_SUCCESS;
5625779Sxy150489 
5635779Sxy150489 	DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575");
5645779Sxy150489 
5655779Sxy150489 	/*
5665779Sxy150489 	 * This isn't a true "hard" reset, but is the only reset
5675779Sxy150489 	 * available to us at this time.
5685779Sxy150489 	 */
5695779Sxy150489 
5705779Sxy150489 	DEBUGOUT("Soft resetting SGMII attached PHY...\n");
5715779Sxy150489 
5728571SChenlu.Chen@Sun.COM 	if (!(hw->phy.ops.write_reg))
5738571SChenlu.Chen@Sun.COM 		goto out;
5748571SChenlu.Chen@Sun.COM 
5755779Sxy150489 	/*
5765779Sxy150489 	 * SFP documentation requires the following to configure the SPF module
5775779Sxy150489 	 * to work on SGMII.  No further documentation is given.
5785779Sxy150489 	 */
5798571SChenlu.Chen@Sun.COM 	ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084);
5805779Sxy150489 	if (ret_val)
5815779Sxy150489 		goto out;
5825779Sxy150489 
5838571SChenlu.Chen@Sun.COM 	ret_val = hw->phy.ops.commit(hw);
5845779Sxy150489 
5855779Sxy150489 out:
5865779Sxy150489 	return (ret_val);
5875779Sxy150489 }
5885779Sxy150489 
5895779Sxy150489 /*
5905779Sxy150489  * e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state
5915779Sxy150489  * @hw: pointer to the HW structure
5928571SChenlu.Chen@Sun.COM  * @active: true to enable LPLU, false to disable
5935779Sxy150489  *
5945779Sxy150489  * Sets the LPLU D0 state according to the active flag.  When
5955779Sxy150489  * activating LPLU this function also disables smart speed
5965779Sxy150489  * and vice versa.  LPLU will not be activated unless the
5975779Sxy150489  * device autonegotiation advertisement meets standards of
5985779Sxy150489  * either 10 or 10/100 or 10/100/1000 at all duplexes.
5995779Sxy150489  * This is a function pointer entry point only called by
6005779Sxy150489  * PHY setup routines.
6015779Sxy150489  */
6025779Sxy150489 static s32
e1000_set_d0_lplu_state_82575(struct e1000_hw * hw,bool active)6035779Sxy150489 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active)
6045779Sxy150489 {
6055779Sxy150489 	struct e1000_phy_info *phy = &hw->phy;
6068571SChenlu.Chen@Sun.COM 	s32 ret_val = E1000_SUCCESS;
6075779Sxy150489 	u16 data;
6085779Sxy150489 
6095779Sxy150489 	DEBUGFUNC("e1000_set_d0_lplu_state_82575");
6105779Sxy150489 
6118571SChenlu.Chen@Sun.COM 	if (!(hw->phy.ops.read_reg))
6128571SChenlu.Chen@Sun.COM 		goto out;
6138571SChenlu.Chen@Sun.COM 
6148571SChenlu.Chen@Sun.COM 	ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
6155779Sxy150489 	if (ret_val)
6165779Sxy150489 		goto out;
6175779Sxy150489 
6185779Sxy150489 	if (active) {
6195779Sxy150489 		data |= IGP02E1000_PM_D0_LPLU;
6208571SChenlu.Chen@Sun.COM 		ret_val = phy->ops.write_reg(hw,
6215779Sxy150489 		    IGP02E1000_PHY_POWER_MGMT,
6225779Sxy150489 		    data);
6235779Sxy150489 		if (ret_val)
6245779Sxy150489 			goto out;
6255779Sxy150489 
6265779Sxy150489 		/* When LPLU is enabled, we should disable SmartSpeed */
6278571SChenlu.Chen@Sun.COM 		ret_val = phy->ops.read_reg(hw,
6285779Sxy150489 		    IGP01E1000_PHY_PORT_CONFIG,
6295779Sxy150489 		    &data);
6305779Sxy150489 		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
6318571SChenlu.Chen@Sun.COM 		ret_val = phy->ops.write_reg(hw,
6325779Sxy150489 		    IGP01E1000_PHY_PORT_CONFIG,
6335779Sxy150489 		    data);
6345779Sxy150489 		if (ret_val)
6355779Sxy150489 			goto out;
6365779Sxy150489 	} else {
6375779Sxy150489 		data &= ~IGP02E1000_PM_D0_LPLU;
6388571SChenlu.Chen@Sun.COM 		ret_val = phy->ops.write_reg(hw,
6395779Sxy150489 		    IGP02E1000_PHY_POWER_MGMT,
6405779Sxy150489 		    data);
6415779Sxy150489 		/*
6425779Sxy150489 		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
6435779Sxy150489 		 * during Dx states where the power conservation is most
6445779Sxy150489 		 * important.  During driver activity we should enable
6455779Sxy150489 		 * SmartSpeed, so performance is maintained.
6465779Sxy150489 		 */
6475779Sxy150489 		if (phy->smart_speed == e1000_smart_speed_on) {
6488571SChenlu.Chen@Sun.COM 			ret_val = phy->ops.read_reg(hw,
6495779Sxy150489 			    IGP01E1000_PHY_PORT_CONFIG,
6505779Sxy150489 			    &data);
6515779Sxy150489 			if (ret_val)
6525779Sxy150489 				goto out;
6535779Sxy150489 
6545779Sxy150489 			data |= IGP01E1000_PSCFR_SMART_SPEED;
6558571SChenlu.Chen@Sun.COM 			ret_val = phy->ops.write_reg(hw,
6565779Sxy150489 			    IGP01E1000_PHY_PORT_CONFIG,
6575779Sxy150489 			    data);
6585779Sxy150489 			if (ret_val)
6595779Sxy150489 				goto out;
6605779Sxy150489 		} else if (phy->smart_speed == e1000_smart_speed_off) {
6618571SChenlu.Chen@Sun.COM 			ret_val = phy->ops.read_reg(hw,
6625779Sxy150489 			    IGP01E1000_PHY_PORT_CONFIG,
6635779Sxy150489 			    &data);
6645779Sxy150489 			if (ret_val)
6655779Sxy150489 				goto out;
6665779Sxy150489 
6675779Sxy150489 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
6688571SChenlu.Chen@Sun.COM 			ret_val = phy->ops.write_reg(hw,
6695779Sxy150489 			    IGP01E1000_PHY_PORT_CONFIG,
6705779Sxy150489 			    data);
6715779Sxy150489 			if (ret_val)
6725779Sxy150489 				goto out;
6735779Sxy150489 		}
6745779Sxy150489 	}
6755779Sxy150489 
6765779Sxy150489 out:
6775779Sxy150489 	return (ret_val);
6785779Sxy150489 }
6795779Sxy150489 
6805779Sxy150489 /*
6815779Sxy150489  * e1000_acquire_nvm_82575 - Request for access to EEPROM
6825779Sxy150489  * @hw: pointer to the HW structure
6835779Sxy150489  *
6848571SChenlu.Chen@Sun.COM  * Acquire the necessary semaphores for exclusive access to the EEPROM.
6855779Sxy150489  * Set the EEPROM access request bit and wait for EEPROM access grant bit.
6865779Sxy150489  * Return successful if access grant bit set, else clear the request for
6875779Sxy150489  * EEPROM access and return -E1000_ERR_NVM (-1).
6885779Sxy150489  */
6895779Sxy150489 static s32
e1000_acquire_nvm_82575(struct e1000_hw * hw)6905779Sxy150489 e1000_acquire_nvm_82575(struct e1000_hw *hw)
6915779Sxy150489 {
6925779Sxy150489 	s32 ret_val;
6935779Sxy150489 
6945779Sxy150489 	DEBUGFUNC("e1000_acquire_nvm_82575");
6955779Sxy150489 
6965779Sxy150489 	ret_val = e1000_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
6975779Sxy150489 	if (ret_val)
6985779Sxy150489 		goto out;
6995779Sxy150489 
7005779Sxy150489 	ret_val = e1000_acquire_nvm_generic(hw);
7015779Sxy150489 
7025779Sxy150489 	if (ret_val)
7035779Sxy150489 		e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
7045779Sxy150489 
7055779Sxy150489 out:
7065779Sxy150489 	return (ret_val);
7075779Sxy150489 }
7085779Sxy150489 
7095779Sxy150489 /*
7105779Sxy150489  * e1000_release_nvm_82575 - Release exclusive access to EEPROM
7115779Sxy150489  * @hw: pointer to the HW structure
7125779Sxy150489  *
7135779Sxy150489  * Stop any current commands to the EEPROM and clear the EEPROM request bit,
7145779Sxy150489  * then release the semaphores acquired.
7155779Sxy150489  */
7165779Sxy150489 static void
e1000_release_nvm_82575(struct e1000_hw * hw)7175779Sxy150489 e1000_release_nvm_82575(struct e1000_hw *hw)
7185779Sxy150489 {
7195779Sxy150489 	DEBUGFUNC("e1000_release_nvm_82575");
7205779Sxy150489 
7215779Sxy150489 	e1000_release_nvm_generic(hw);
7225779Sxy150489 	e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
7235779Sxy150489 }
7245779Sxy150489 
7255779Sxy150489 /*
7265779Sxy150489  * e1000_acquire_swfw_sync_82575 - Acquire SW/FW semaphore
7275779Sxy150489  * @hw: pointer to the HW structure
7285779Sxy150489  * @mask: specifies which semaphore to acquire
7295779Sxy150489  *
7305779Sxy150489  * Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
7315779Sxy150489  * will also specify which port we're acquiring the lock for.
7325779Sxy150489  */
7335779Sxy150489 static s32
e1000_acquire_swfw_sync_82575(struct e1000_hw * hw,u16 mask)7345779Sxy150489 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
7355779Sxy150489 {
7365779Sxy150489 	u32 swfw_sync;
7375779Sxy150489 	u32 swmask = mask;
7385779Sxy150489 	u32 fwmask = mask << 16;
7395779Sxy150489 	s32 ret_val = E1000_SUCCESS;
7405779Sxy150489 	s32 i = 0, timeout = 200;	/* FIXME: find real value to use here */
7415779Sxy150489 
7425779Sxy150489 	DEBUGFUNC("e1000_acquire_swfw_sync_82575");
7435779Sxy150489 
7445779Sxy150489 	while (i < timeout) {
7455779Sxy150489 		if (e1000_get_hw_semaphore_generic(hw)) {
7465779Sxy150489 			ret_val = -E1000_ERR_SWFW_SYNC;
7475779Sxy150489 			goto out;
7485779Sxy150489 		}
7495779Sxy150489 
7505779Sxy150489 		swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
7515779Sxy150489 		if (!(swfw_sync & (fwmask | swmask)))
7525779Sxy150489 			break;
7535779Sxy150489 
7545779Sxy150489 		/*
7555779Sxy150489 		 * Firmware currently using resource (fwmask)
7565779Sxy150489 		 * or other software thread using resource (swmask)
7575779Sxy150489 		 */
7585779Sxy150489 		e1000_put_hw_semaphore_generic(hw);
7595779Sxy150489 		msec_delay_irq(5);
7605779Sxy150489 		i++;
7615779Sxy150489 	}
7625779Sxy150489 
7635779Sxy150489 	if (i == timeout) {
7645779Sxy150489 		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
7655779Sxy150489 		ret_val = -E1000_ERR_SWFW_SYNC;
7665779Sxy150489 		goto out;
7675779Sxy150489 	}
7685779Sxy150489 
7695779Sxy150489 	swfw_sync |= swmask;
7705779Sxy150489 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
7715779Sxy150489 
7725779Sxy150489 	e1000_put_hw_semaphore_generic(hw);
7735779Sxy150489 
7745779Sxy150489 out:
7755779Sxy150489 	return (ret_val);
7765779Sxy150489 }
7775779Sxy150489 
7785779Sxy150489 /*
7795779Sxy150489  * e1000_release_swfw_sync_82575 - Release SW/FW semaphore
7805779Sxy150489  * @hw: pointer to the HW structure
7815779Sxy150489  * @mask: specifies which semaphore to acquire
7825779Sxy150489  *
7835779Sxy150489  * Release the SW/FW semaphore used to access the PHY or NVM.  The mask
7845779Sxy150489  * will also specify which port we're releasing the lock for.
7855779Sxy150489  */
7865779Sxy150489 static void
e1000_release_swfw_sync_82575(struct e1000_hw * hw,u16 mask)7875779Sxy150489 e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
7885779Sxy150489 {
7895779Sxy150489 	u32 swfw_sync;
7905779Sxy150489 
7915779Sxy150489 	DEBUGFUNC("e1000_release_swfw_sync_82575");
7925779Sxy150489 
7935779Sxy150489 	while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) {
7945779Sxy150489 		/* Empty */
7955779Sxy150489 	}
7965779Sxy150489 
7975779Sxy150489 	swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
7985779Sxy150489 	swfw_sync &= ~mask;
7995779Sxy150489 	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
8005779Sxy150489 
8015779Sxy150489 	e1000_put_hw_semaphore_generic(hw);
8025779Sxy150489 }
8035779Sxy150489 
8045779Sxy150489 /*
8055779Sxy150489  * e1000_get_cfg_done_82575 - Read config done bit
8065779Sxy150489  * @hw: pointer to the HW structure
8075779Sxy150489  *
8085779Sxy150489  * Read the management control register for the config done bit for
8095779Sxy150489  * completion status.  NOTE: silicon which is EEPROM-less will fail trying
8105779Sxy150489  * to read the config done bit, so an error is *ONLY* logged and returns
8115779Sxy150489  * E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon
8125779Sxy150489  * would not be able to be reset or change link.
8135779Sxy150489  */
8145779Sxy150489 static s32
e1000_get_cfg_done_82575(struct e1000_hw * hw)8155779Sxy150489 e1000_get_cfg_done_82575(struct e1000_hw *hw)
8165779Sxy150489 {
8175779Sxy150489 	s32 timeout = PHY_CFG_TIMEOUT;
8185779Sxy150489 	s32 ret_val = E1000_SUCCESS;
8195779Sxy150489 	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
8205779Sxy150489 
8215779Sxy150489 	DEBUGFUNC("e1000_get_cfg_done_82575");
8225779Sxy150489 
82310319SJason.Xu@Sun.COM 	if (hw->bus.func == E1000_FUNC_1)
8245779Sxy150489 		mask = E1000_NVM_CFG_DONE_PORT_1;
82511155SJason.Xu@Sun.COM 	else if (hw->bus.func == E1000_FUNC_2)
82611155SJason.Xu@Sun.COM 		mask = E1000_NVM_CFG_DONE_PORT_2;
82711155SJason.Xu@Sun.COM 	else if (hw->bus.func == E1000_FUNC_3)
82811155SJason.Xu@Sun.COM 		mask = E1000_NVM_CFG_DONE_PORT_3;
8295779Sxy150489 
8305779Sxy150489 	while (timeout) {
8315779Sxy150489 		if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask)
8325779Sxy150489 			break;
8335779Sxy150489 		msec_delay(1);
8345779Sxy150489 		timeout--;
8355779Sxy150489 	}
83611155SJason.Xu@Sun.COM 	if (!timeout)
8375779Sxy150489 		DEBUGOUT("MNG configuration cycle has not completed.\n");
8385779Sxy150489 
8395779Sxy150489 	/* If EEPROM is not marked present, init the PHY manually */
8405779Sxy150489 	if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) &&
84111155SJason.Xu@Sun.COM 	    (hw->phy.type == e1000_phy_igp_3))
8425779Sxy150489 		(void) e1000_phy_init_script_igp3(hw);
84311155SJason.Xu@Sun.COM 
8445779Sxy150489 	return (ret_val);
8455779Sxy150489 }
8465779Sxy150489 
8475779Sxy150489 /*
8485779Sxy150489  * e1000_get_link_up_info_82575 - Get link speed/duplex info
8495779Sxy150489  * @hw: pointer to the HW structure
8505779Sxy150489  * @speed: stores the current speed
8515779Sxy150489  * @duplex: stores the current duplex
8525779Sxy150489  *
8535779Sxy150489  * This is a wrapper function, if using the serial gigabit media independent
8548571SChenlu.Chen@Sun.COM  * interface, use PCS to retrieve the link speed and duplex information.
8555779Sxy150489  * Otherwise, use the generic function to get the link speed and duplex info.
8565779Sxy150489  */
8575779Sxy150489 static s32
e1000_get_link_up_info_82575(struct e1000_hw * hw,u16 * speed,u16 * duplex)8585779Sxy150489 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex)
8595779Sxy150489 {
8605779Sxy150489 	s32 ret_val;
8615779Sxy150489 
8625779Sxy150489 	DEBUGFUNC("e1000_get_link_up_info_82575");
8635779Sxy150489 
86411155SJason.Xu@Sun.COM 	if (hw->phy.media_type != e1000_media_type_copper)
8655779Sxy150489 		ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed,
8665779Sxy150489 		    duplex);
86711155SJason.Xu@Sun.COM 	else
8685779Sxy150489 		ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
8695779Sxy150489 		    duplex);
8705779Sxy150489 
8715779Sxy150489 	return (ret_val);
8725779Sxy150489 }
8735779Sxy150489 
8745779Sxy150489 /*
8755779Sxy150489  * e1000_check_for_link_82575 - Check for link
8765779Sxy150489  * @hw: pointer to the HW structure
8775779Sxy150489  *
8785779Sxy150489  * If sgmii is enabled, then use the pcs register to determine link, otherwise
8795779Sxy150489  * use the generic interface for determining link.
8805779Sxy150489  */
8815779Sxy150489 static s32
e1000_check_for_link_82575(struct e1000_hw * hw)8825779Sxy150489 e1000_check_for_link_82575(struct e1000_hw *hw)
8835779Sxy150489 {
8845779Sxy150489 	s32 ret_val;
8855779Sxy150489 	u16 speed, duplex;
8865779Sxy150489 
8875779Sxy150489 	DEBUGFUNC("e1000_check_for_link_82575");
8885779Sxy150489 
8895779Sxy150489 	/* SGMII link check is done through the PCS register. */
89011155SJason.Xu@Sun.COM 	if (hw->phy.media_type != e1000_media_type_copper) {
8915779Sxy150489 		ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed,
8925779Sxy150489 		    &duplex);
89310319SJason.Xu@Sun.COM 		/*
89410319SJason.Xu@Sun.COM 		 * Use this flag to determine if link needs to be checked or
89510319SJason.Xu@Sun.COM 		 * not.  If we have link clear the flag so that we do not
89610319SJason.Xu@Sun.COM 		 * continue to check for link.
89710319SJason.Xu@Sun.COM 		 */
89810319SJason.Xu@Sun.COM 		hw->mac.get_link_status = !hw->mac.serdes_has_link;
89910319SJason.Xu@Sun.COM 	} else {
9005779Sxy150489 		ret_val = e1000_check_for_copper_link_generic(hw);
90110319SJason.Xu@Sun.COM 	}
9025779Sxy150489 
9035779Sxy150489 	return (ret_val);
9045779Sxy150489 }
9055779Sxy150489 
9065779Sxy150489 /*
9075779Sxy150489  * e1000_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex
9085779Sxy150489  * @hw: pointer to the HW structure
9095779Sxy150489  * @speed: stores the current speed
9105779Sxy150489  * @duplex: stores the current duplex
9115779Sxy150489  *
9128571SChenlu.Chen@Sun.COM  * Using the physical coding sub-layer (PCS), retrieve the current speed and
9135779Sxy150489  * duplex, then store the values in the pointers provided.
9145779Sxy150489  */
9155779Sxy150489 static s32
e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw * hw,u16 * speed,u16 * duplex)9165779Sxy150489 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
9175779Sxy150489     u16 *speed, u16 *duplex)
9185779Sxy150489 {
9195779Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
9205779Sxy150489 	u32 pcs;
9215779Sxy150489 
9225779Sxy150489 	DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575");
9235779Sxy150489 
9245779Sxy150489 	/* Set up defaults for the return values of this function */
9258571SChenlu.Chen@Sun.COM 	mac->serdes_has_link = false;
9265779Sxy150489 	*speed = 0;
9275779Sxy150489 	*duplex = 0;
9285779Sxy150489 
9295779Sxy150489 	/*
9305779Sxy150489 	 * Read the PCS Status register for link state. For non-copper mode,
9315779Sxy150489 	 * the status register is not accurate. The PCS status register is
9325779Sxy150489 	 * used instead.
9335779Sxy150489 	 */
9345779Sxy150489 	pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT);
9355779Sxy150489 
9365779Sxy150489 	/*
9375779Sxy150489 	 * The link up bit determines when link is up on autoneg. The sync ok
9385779Sxy150489 	 * gets set once both sides sync up and agree upon link. Stable link
9395779Sxy150489 	 * can be determined by checking for both link up and link sync ok
9405779Sxy150489 	 */
9415779Sxy150489 	if ((pcs & E1000_PCS_LSTS_LINK_OK) && (pcs & E1000_PCS_LSTS_SYNK_OK)) {
9428571SChenlu.Chen@Sun.COM 		mac->serdes_has_link = true;
9435779Sxy150489 
9445779Sxy150489 		/* Detect and store PCS speed */
9455779Sxy150489 		if (pcs & E1000_PCS_LSTS_SPEED_1000) {
9465779Sxy150489 			*speed = SPEED_1000;
9475779Sxy150489 		} else if (pcs & E1000_PCS_LSTS_SPEED_100) {
9485779Sxy150489 			*speed = SPEED_100;
9495779Sxy150489 		} else {
9505779Sxy150489 			*speed = SPEED_10;
9515779Sxy150489 		}
9525779Sxy150489 
9535779Sxy150489 		/* Detect and store PCS duplex */
9545779Sxy150489 		if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) {
9555779Sxy150489 			*duplex = FULL_DUPLEX;
9565779Sxy150489 		} else {
9575779Sxy150489 			*duplex = HALF_DUPLEX;
9585779Sxy150489 		}
9595779Sxy150489 	}
9608571SChenlu.Chen@Sun.COM 
9615779Sxy150489 	return (E1000_SUCCESS);
9625779Sxy150489 }
9635779Sxy150489 
9645779Sxy150489 /*
96511155SJason.Xu@Sun.COM  * e1000_shutdown_serdes_link_82575 - Remove link during power down
9668571SChenlu.Chen@Sun.COM  * @hw: pointer to the HW structure
9678571SChenlu.Chen@Sun.COM  *
96811155SJason.Xu@Sun.COM  * In the case of serdes shut down sfp and PCS on driver unload
9698571SChenlu.Chen@Sun.COM  * when management pass thru is not enabled.
9708571SChenlu.Chen@Sun.COM  */
9718571SChenlu.Chen@Sun.COM void
e1000_shutdown_serdes_link_82575(struct e1000_hw * hw)97211155SJason.Xu@Sun.COM e1000_shutdown_serdes_link_82575(struct e1000_hw *hw)
9738571SChenlu.Chen@Sun.COM {
9748571SChenlu.Chen@Sun.COM 	u32 reg;
9758571SChenlu.Chen@Sun.COM 	u16 eeprom_data = 0;
9768571SChenlu.Chen@Sun.COM 
97711155SJason.Xu@Sun.COM 	if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
97811155SJason.Xu@Sun.COM 	    !e1000_sgmii_active_82575(hw))
9798571SChenlu.Chen@Sun.COM 		return;
9808571SChenlu.Chen@Sun.COM 
98110319SJason.Xu@Sun.COM 	if (hw->bus.func == E1000_FUNC_0)
9828571SChenlu.Chen@Sun.COM 		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
98311155SJason.Xu@Sun.COM 	else if (hw->mac.type == e1000_82580)
98411155SJason.Xu@Sun.COM 		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
98511155SJason.Xu@Sun.COM 		    NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
98611155SJason.Xu@Sun.COM 		    &eeprom_data);
98710319SJason.Xu@Sun.COM 	else if (hw->bus.func == E1000_FUNC_1)
98810319SJason.Xu@Sun.COM 		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
9898571SChenlu.Chen@Sun.COM 
9908571SChenlu.Chen@Sun.COM 	/*
9918571SChenlu.Chen@Sun.COM 	 * If APM is not enabled in the EEPROM and management interface is
9928571SChenlu.Chen@Sun.COM 	 * not enabled, then power down.
9938571SChenlu.Chen@Sun.COM 	 */
9948571SChenlu.Chen@Sun.COM 	if (!(eeprom_data & E1000_NVM_APME_82575) &&
9958571SChenlu.Chen@Sun.COM 	    !e1000_enable_mng_pass_thru(hw)) {
9968571SChenlu.Chen@Sun.COM 		/* Disable PCS to turn off link */
9978571SChenlu.Chen@Sun.COM 		reg = E1000_READ_REG(hw, E1000_PCS_CFG0);
9988571SChenlu.Chen@Sun.COM 		reg &= ~E1000_PCS_CFG_PCS_EN;
9998571SChenlu.Chen@Sun.COM 		E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg);
10008571SChenlu.Chen@Sun.COM 
10018571SChenlu.Chen@Sun.COM 		/* shutdown the laser */
10028571SChenlu.Chen@Sun.COM 		reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
100311155SJason.Xu@Sun.COM 		reg |= E1000_CTRL_EXT_SDP3_DATA;
10048571SChenlu.Chen@Sun.COM 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
10058571SChenlu.Chen@Sun.COM 
100611155SJason.Xu@Sun.COM 		/* flush the write to verify completion */
10078571SChenlu.Chen@Sun.COM 		E1000_WRITE_FLUSH(hw);
10088571SChenlu.Chen@Sun.COM 		msec_delay(1);
10095779Sxy150489 	}
10105779Sxy150489 }
10115779Sxy150489 
10125779Sxy150489 /*
10135779Sxy150489  * e1000_reset_hw_82575 - Reset hardware
10145779Sxy150489  * @hw: pointer to the HW structure
10155779Sxy150489  *
10168571SChenlu.Chen@Sun.COM  * This resets the hardware into a known state.
10175779Sxy150489  */
10185779Sxy150489 static s32
e1000_reset_hw_82575(struct e1000_hw * hw)10195779Sxy150489 e1000_reset_hw_82575(struct e1000_hw *hw)
10205779Sxy150489 {
10215779Sxy150489 	u32 ctrl;
10225779Sxy150489 	s32 ret_val;
10235779Sxy150489 
10245779Sxy150489 	DEBUGFUNC("e1000_reset_hw_82575");
10255779Sxy150489 
10265779Sxy150489 	/*
10275779Sxy150489 	 * Prevent the PCI-E bus from sticking if there is no TLP connection
10285779Sxy150489 	 * on the last TLP read/write transaction when MAC is reset.
10295779Sxy150489 	 */
10305779Sxy150489 	ret_val = e1000_disable_pcie_master_generic(hw);
10315779Sxy150489 	if (ret_val) {
10325779Sxy150489 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
10335779Sxy150489 	}
10345779Sxy150489 
103510319SJason.Xu@Sun.COM 	/* set the completion timeout for interface */
103610319SJason.Xu@Sun.COM 	ret_val = e1000_set_pcie_completion_timeout(hw);
103710319SJason.Xu@Sun.COM 	if (ret_val) {
103810319SJason.Xu@Sun.COM 		DEBUGOUT("PCI-E Set completion timeout has failed.\n");
103910319SJason.Xu@Sun.COM 	}
104010319SJason.Xu@Sun.COM 
10415779Sxy150489 	DEBUGOUT("Masking off all interrupts\n");
10425779Sxy150489 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
10435779Sxy150489 
10445779Sxy150489 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
10455779Sxy150489 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
10465779Sxy150489 	E1000_WRITE_FLUSH(hw);
10475779Sxy150489 
10485779Sxy150489 	msec_delay(10);
10495779Sxy150489 
10505779Sxy150489 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
10515779Sxy150489 
10525779Sxy150489 	DEBUGOUT("Issuing a global reset to MAC\n");
10535779Sxy150489 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
10545779Sxy150489 
10555779Sxy150489 	ret_val = e1000_get_auto_rd_done_generic(hw);
10565779Sxy150489 	if (ret_val) {
10575779Sxy150489 		/*
10585779Sxy150489 		 * When auto config read does not complete, do not
10595779Sxy150489 		 * return with an error. This can happen in situations
10605779Sxy150489 		 * where there is no eeprom and prevents getting link.
10615779Sxy150489 		 */
10625779Sxy150489 		DEBUGOUT("Auto Read Done did not complete\n");
10635779Sxy150489 	}
10645779Sxy150489 
10655779Sxy150489 	/* If EEPROM is not present, run manual init scripts */
10665779Sxy150489 	if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0)
10675779Sxy150489 		(void) e1000_reset_init_script_82575(hw);
10685779Sxy150489 
10695779Sxy150489 	/* Clear any pending interrupt events. */
10705779Sxy150489 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
10715779Sxy150489 	(void) E1000_READ_REG(hw, E1000_ICR);
10725779Sxy150489 
107310319SJason.Xu@Sun.COM 	/* Install any alternate MAC address into RAR0 */
107410319SJason.Xu@Sun.COM 	ret_val = e1000_check_alt_mac_addr_generic(hw);
10755779Sxy150489 
10765779Sxy150489 	return (ret_val);
10775779Sxy150489 }
10785779Sxy150489 
10795779Sxy150489 /*
10805779Sxy150489  * e1000_init_hw_82575 - Initialize hardware
10815779Sxy150489  * @hw: pointer to the HW structure
10825779Sxy150489  *
10835779Sxy150489  * This inits the hardware readying it for operation.
10845779Sxy150489  */
10855779Sxy150489 static s32
e1000_init_hw_82575(struct e1000_hw * hw)10865779Sxy150489 e1000_init_hw_82575(struct e1000_hw *hw)
10875779Sxy150489 {
10885779Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
10895779Sxy150489 	s32 ret_val;
10905779Sxy150489 	u16 i, rar_count = mac->rar_entry_count;
10915779Sxy150489 
10925779Sxy150489 	DEBUGFUNC("e1000_init_hw_82575");
10935779Sxy150489 
10945779Sxy150489 	/* Initialize identification LED */
109510319SJason.Xu@Sun.COM 	ret_val = mac->ops.id_led_init(hw);
10965779Sxy150489 	if (ret_val) {
10975779Sxy150489 		DEBUGOUT("Error initializing identification LED\n");
10985779Sxy150489 		/* This is not fatal and we should not stop init due to this */
10995779Sxy150489 	}
11005779Sxy150489 
11015779Sxy150489 	/* Disabling VLAN filtering */
11025779Sxy150489 	DEBUGOUT("Initializing the IEEE VLAN\n");
11038571SChenlu.Chen@Sun.COM 	mac->ops.clear_vfta(hw);
11045779Sxy150489 
11055779Sxy150489 	/* Setup the receive address */
110610319SJason.Xu@Sun.COM 	e1000_init_rx_addrs_generic(hw, rar_count);
11075779Sxy150489 	/* Zero out the Multicast HASH table */
11085779Sxy150489 	DEBUGOUT("Zeroing the MTA\n");
11095779Sxy150489 	for (i = 0; i < mac->mta_reg_count; i++)
11105779Sxy150489 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
11115779Sxy150489 
111211155SJason.Xu@Sun.COM 	/* Zero out the Unicast HASH table */
111311155SJason.Xu@Sun.COM 	DEBUGOUT("Zeroing the UTA\n");
111411155SJason.Xu@Sun.COM 	for (i = 0; i < mac->uta_reg_count; i++)
111511155SJason.Xu@Sun.COM 		E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0);
111611155SJason.Xu@Sun.COM 
11175779Sxy150489 	/* Setup link and flow control */
11188571SChenlu.Chen@Sun.COM 	ret_val = mac->ops.setup_link(hw);
11195779Sxy150489 
11205779Sxy150489 	/*
11215779Sxy150489 	 * Clear all of the statistics registers (clear on read).  It is
11225779Sxy150489 	 * important that we do this after we have tried to establish link
11235779Sxy150489 	 * because the symbol error count will increment wildly if there
11245779Sxy150489 	 * is no link.
11255779Sxy150489 	 */
11265779Sxy150489 	e1000_clear_hw_cntrs_82575(hw);
11275779Sxy150489 
11285779Sxy150489 	return (ret_val);
11295779Sxy150489 }
11305779Sxy150489 
11315779Sxy150489 /*
11325779Sxy150489  * e1000_setup_copper_link_82575 - Configure copper link settings
11335779Sxy150489  * @hw: pointer to the HW structure
11345779Sxy150489  *
11355779Sxy150489  * Configures the link for auto-neg or forced speed and duplex.  Then we check
11365779Sxy150489  * for link, once link is established calls to configure collision distance
11375779Sxy150489  * and flow control are called.
11385779Sxy150489  */
11395779Sxy150489 static s32
e1000_setup_copper_link_82575(struct e1000_hw * hw)11405779Sxy150489 e1000_setup_copper_link_82575(struct e1000_hw *hw)
11415779Sxy150489 {
114210319SJason.Xu@Sun.COM 	u32 ctrl;
11435779Sxy150489 	s32 ret_val;
11445779Sxy150489 
11455779Sxy150489 	DEBUGFUNC("e1000_setup_copper_link_82575");
11465779Sxy150489 
11475779Sxy150489 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
11485779Sxy150489 	ctrl |= E1000_CTRL_SLU;
11495779Sxy150489 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
11505779Sxy150489 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
11515779Sxy150489 
115211155SJason.Xu@Sun.COM 	ret_val = e1000_setup_serdes_link_82575(hw);
115311155SJason.Xu@Sun.COM 	if (ret_val)
115411155SJason.Xu@Sun.COM 		goto out;
115511155SJason.Xu@Sun.COM 
115611155SJason.Xu@Sun.COM 	if (e1000_sgmii_active_82575(hw) && !hw->phy.reset_disable) {
1157*12111SGuoqing.Zhu@Sun.COM 		/* allow time for SFP cage time to power up phy */
1158*12111SGuoqing.Zhu@Sun.COM 		msec_delay(300);
1159*12111SGuoqing.Zhu@Sun.COM 
116011155SJason.Xu@Sun.COM 		ret_val = hw->phy.ops.reset(hw);
116111155SJason.Xu@Sun.COM 		if (ret_val) {
116211155SJason.Xu@Sun.COM 			DEBUGOUT("Error resetting the PHY.\n");
116311155SJason.Xu@Sun.COM 			goto out;
116411155SJason.Xu@Sun.COM 		}
116511155SJason.Xu@Sun.COM 	}
11665779Sxy150489 	switch (hw->phy.type) {
11675779Sxy150489 	case e1000_phy_m88:
11685779Sxy150489 		ret_val = e1000_copper_link_setup_m88(hw);
11695779Sxy150489 		break;
11705779Sxy150489 	case e1000_phy_igp_3:
11715779Sxy150489 		ret_val = e1000_copper_link_setup_igp(hw);
11725779Sxy150489 		break;
117311155SJason.Xu@Sun.COM 	case e1000_phy_82580:
117411155SJason.Xu@Sun.COM 		ret_val = e1000_copper_link_setup_82577(hw);
117511155SJason.Xu@Sun.COM 		break;
11765779Sxy150489 	default:
11775779Sxy150489 		ret_val = -E1000_ERR_PHY;
11785779Sxy150489 		break;
11795779Sxy150489 	}
11805779Sxy150489 
11815779Sxy150489 	if (ret_val)
11825779Sxy150489 		goto out;
11835779Sxy150489 
118411155SJason.Xu@Sun.COM 	ret_val = e1000_setup_copper_link_generic(hw);
11855779Sxy150489 out:
11865779Sxy150489 	return (ret_val);
11875779Sxy150489 }
11885779Sxy150489 
11895779Sxy150489 /*
119011155SJason.Xu@Sun.COM  * e1000_setup_serdes_link_82575 - Setup link for serdes
11915779Sxy150489  * @hw: pointer to the HW structure
11925779Sxy150489  *
119311155SJason.Xu@Sun.COM  * Configure the physical coding sub-layer (PCS) link.  The PCS link is
119411155SJason.Xu@Sun.COM  * used on copper connections where the serialized gigabit media independent
119511155SJason.Xu@Sun.COM  * interface (sgmii), or serdes fiber is being used.  Configures the link
119611155SJason.Xu@Sun.COM  * for auto-negotiation or forces speed/duplex.
11975779Sxy150489  */
11985779Sxy150489 static s32
e1000_setup_serdes_link_82575(struct e1000_hw * hw)119911155SJason.Xu@Sun.COM e1000_setup_serdes_link_82575(struct e1000_hw *hw)
12005779Sxy150489 {
1201*12111SGuoqing.Zhu@Sun.COM 	u32 ctrl_ext, ctrl_reg, reg;
1202*12111SGuoqing.Zhu@Sun.COM 	bool pcs_autoneg;
120311155SJason.Xu@Sun.COM 
120411155SJason.Xu@Sun.COM 	DEBUGFUNC("e1000_setup_serdes_link_82575");
12055779Sxy150489 
120611155SJason.Xu@Sun.COM 	if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
120711155SJason.Xu@Sun.COM 	    !e1000_sgmii_active_82575(hw))
120811155SJason.Xu@Sun.COM 		return (E1000_SUCCESS);
12095779Sxy150489 
12105779Sxy150489 	/*
12115779Sxy150489 	 * On the 82575, SerDes loopback mode persists until it is
12125779Sxy150489 	 * explicitly turned off or a power cycle is performed.  A read to
12135779Sxy150489 	 * the register does not indicate its status.  Therefore, we ensure
12145779Sxy150489 	 * loopback mode is disabled during initialization.
12155779Sxy150489 	 */
12165779Sxy150489 	E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
12175779Sxy150489 
121811155SJason.Xu@Sun.COM 	/* power on the sfp cage if present */
1219*12111SGuoqing.Zhu@Sun.COM 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
1220*12111SGuoqing.Zhu@Sun.COM 	ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA;
1221*12111SGuoqing.Zhu@Sun.COM 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
122211155SJason.Xu@Sun.COM 
122311155SJason.Xu@Sun.COM 	ctrl_reg = E1000_READ_REG(hw, E1000_CTRL);
122411155SJason.Xu@Sun.COM 	ctrl_reg |= E1000_CTRL_SLU;
122511155SJason.Xu@Sun.COM 
122610319SJason.Xu@Sun.COM 	if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) {
122710319SJason.Xu@Sun.COM 		/* set both sw defined pins */
122811155SJason.Xu@Sun.COM 		ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1;
12295779Sxy150489 
123011155SJason.Xu@Sun.COM 		/* Set switch control to serdes energy detect */
123111155SJason.Xu@Sun.COM 		reg = E1000_READ_REG(hw, E1000_CONNSW);
123211155SJason.Xu@Sun.COM 		reg |= E1000_CONNSW_ENRGSRC;
123311155SJason.Xu@Sun.COM 		E1000_WRITE_REG(hw, E1000_CONNSW, reg);
12348571SChenlu.Chen@Sun.COM 	}
12358571SChenlu.Chen@Sun.COM 
123611155SJason.Xu@Sun.COM 	reg = E1000_READ_REG(hw, E1000_PCS_LCTL);
123711155SJason.Xu@Sun.COM 
1238*12111SGuoqing.Zhu@Sun.COM 	/* default pcs_autoneg to the same setting as mac autoneg */
1239*12111SGuoqing.Zhu@Sun.COM 	pcs_autoneg = hw->mac.autoneg;
124011155SJason.Xu@Sun.COM 
1241*12111SGuoqing.Zhu@Sun.COM 	switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
1242*12111SGuoqing.Zhu@Sun.COM 	case E1000_CTRL_EXT_LINK_MODE_SGMII:
1243*12111SGuoqing.Zhu@Sun.COM 		/* sgmii mode lets the phy handle forcing speed/duplex */
1244*12111SGuoqing.Zhu@Sun.COM 		pcs_autoneg = true;
1245*12111SGuoqing.Zhu@Sun.COM 		/* autoneg time out should be disabled for SGMII mode */
124611155SJason.Xu@Sun.COM 		reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT);
1247*12111SGuoqing.Zhu@Sun.COM 		break;
1248*12111SGuoqing.Zhu@Sun.COM 	case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
1249*12111SGuoqing.Zhu@Sun.COM 		/* disable PCS autoneg and support parallel detect only */
1250*12111SGuoqing.Zhu@Sun.COM 		pcs_autoneg = false;
1251*12111SGuoqing.Zhu@Sun.COM 	default:
1252*12111SGuoqing.Zhu@Sun.COM 		/*
1253*12111SGuoqing.Zhu@Sun.COM 		 * non-SGMII modes only supports a speed of 1000/Full for the
1254*12111SGuoqing.Zhu@Sun.COM 		 * link so it is best to just force the MAC and let the pcs
1255*12111SGuoqing.Zhu@Sun.COM 		 * link either autoneg or be forced to 1000/Full
1256*12111SGuoqing.Zhu@Sun.COM 		 */
125711155SJason.Xu@Sun.COM 		ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD |
125811155SJason.Xu@Sun.COM 		    E1000_CTRL_FD | E1000_CTRL_FRCDPX;
1259*12111SGuoqing.Zhu@Sun.COM 
1260*12111SGuoqing.Zhu@Sun.COM 		/* set speed of 1000/Full if speed/duplex is forced */
1261*12111SGuoqing.Zhu@Sun.COM 		reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL;
1262*12111SGuoqing.Zhu@Sun.COM 		break;
126311155SJason.Xu@Sun.COM 	}
126411155SJason.Xu@Sun.COM 
126511155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg);
12665779Sxy150489 
12675779Sxy150489 	/*
12685779Sxy150489 	 * New SerDes mode allows for forcing speed or autonegotiating speed
12695779Sxy150489 	 * at 1gb. Autoneg should be default set by most drivers. This is the
12705779Sxy150489 	 * mode that will be compatible with older link partners and switches.
12715779Sxy150489 	 * However, both are supported by the hardware and some drivers/tools.
12725779Sxy150489 	 */
12735779Sxy150489 
12745779Sxy150489 	reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
12755779Sxy150489 	    E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
12765779Sxy150489 
127711155SJason.Xu@Sun.COM 	/*
127811155SJason.Xu@Sun.COM 	 * We force flow control to prevent the CTRL register values from being
127911155SJason.Xu@Sun.COM 	 * overwritten by the autonegotiated flow control values
128011155SJason.Xu@Sun.COM 	 */
128111155SJason.Xu@Sun.COM 	reg |= E1000_PCS_LCTL_FORCE_FCTRL;
128211155SJason.Xu@Sun.COM 
1283*12111SGuoqing.Zhu@Sun.COM 	if (pcs_autoneg) {
12845779Sxy150489 		/* Set PCS register for autoneg */
1285*12111SGuoqing.Zhu@Sun.COM 		reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */
1286*12111SGuoqing.Zhu@Sun.COM 		    E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */
128711155SJason.Xu@Sun.COM 		DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
12885779Sxy150489 	} else {
1289*12111SGuoqing.Zhu@Sun.COM 		/* Set PCS register for forced link */
1290*12111SGuoqing.Zhu@Sun.COM 		reg |= E1000_PCS_LCTL_FSD;	/* Force Speed */
129111155SJason.Xu@Sun.COM 		DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
12928571SChenlu.Chen@Sun.COM 	}
12938571SChenlu.Chen@Sun.COM 
12945779Sxy150489 	E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg);
12955779Sxy150489 
129611155SJason.Xu@Sun.COM 	if (!e1000_sgmii_active_82575(hw))
129711155SJason.Xu@Sun.COM 		(void) e1000_force_mac_fc_generic(hw);
129811155SJason.Xu@Sun.COM 
12995779Sxy150489 	return (E1000_SUCCESS);
13005779Sxy150489 }
13015779Sxy150489 
13025779Sxy150489 /*
13038571SChenlu.Chen@Sun.COM  * e1000_valid_led_default_82575 - Verify a valid default LED config
13048571SChenlu.Chen@Sun.COM  * @hw: pointer to the HW structure
13058571SChenlu.Chen@Sun.COM  * @data: pointer to the NVM (EEPROM)
13068571SChenlu.Chen@Sun.COM  *
13078571SChenlu.Chen@Sun.COM  * Read the EEPROM for the current default LED configuration.  If the
13088571SChenlu.Chen@Sun.COM  * LED configuration is not valid, set to a valid LED configuration.
13098571SChenlu.Chen@Sun.COM  */
13108571SChenlu.Chen@Sun.COM static s32
e1000_valid_led_default_82575(struct e1000_hw * hw,u16 * data)13118571SChenlu.Chen@Sun.COM e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data)
13128571SChenlu.Chen@Sun.COM {
13138571SChenlu.Chen@Sun.COM 	s32 ret_val;
13148571SChenlu.Chen@Sun.COM 
13158571SChenlu.Chen@Sun.COM 	DEBUGFUNC("e1000_valid_led_default_82575");
13168571SChenlu.Chen@Sun.COM 
13178571SChenlu.Chen@Sun.COM 	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
13188571SChenlu.Chen@Sun.COM 	if (ret_val) {
13198571SChenlu.Chen@Sun.COM 		DEBUGOUT("NVM Read Error\n");
13208571SChenlu.Chen@Sun.COM 		goto out;
13218571SChenlu.Chen@Sun.COM 	}
13228571SChenlu.Chen@Sun.COM 
13238571SChenlu.Chen@Sun.COM 	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
13248571SChenlu.Chen@Sun.COM 		switch (hw->phy.media_type) {
13258571SChenlu.Chen@Sun.COM 		case e1000_media_type_internal_serdes:
13268571SChenlu.Chen@Sun.COM 			*data = ID_LED_DEFAULT_82575_SERDES;
13278571SChenlu.Chen@Sun.COM 			break;
13288571SChenlu.Chen@Sun.COM 		case e1000_media_type_copper:
13298571SChenlu.Chen@Sun.COM 		default:
13308571SChenlu.Chen@Sun.COM 			*data = ID_LED_DEFAULT;
13318571SChenlu.Chen@Sun.COM 			break;
13328571SChenlu.Chen@Sun.COM 		}
13338571SChenlu.Chen@Sun.COM 	}
13348571SChenlu.Chen@Sun.COM out:
13358571SChenlu.Chen@Sun.COM 	return (ret_val);
13368571SChenlu.Chen@Sun.COM }
13378571SChenlu.Chen@Sun.COM 
13388571SChenlu.Chen@Sun.COM /*
13395779Sxy150489  * e1000_sgmii_active_82575 - Return sgmii state
13405779Sxy150489  * @hw: pointer to the HW structure
13415779Sxy150489  *
13425779Sxy150489  * 82575 silicon has a serialized gigabit media independent interface (sgmii)
13435779Sxy150489  * which can be enabled for use in the embedded applications.  Simply
13445779Sxy150489  * return the current state of the sgmii interface.
13455779Sxy150489  */
13465779Sxy150489 static bool
e1000_sgmii_active_82575(struct e1000_hw * hw)13475779Sxy150489 e1000_sgmii_active_82575(struct e1000_hw *hw)
13485779Sxy150489 {
13498571SChenlu.Chen@Sun.COM 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
13508571SChenlu.Chen@Sun.COM 	return (dev_spec->sgmii_active);
13515779Sxy150489 }
13525779Sxy150489 
13535779Sxy150489 /*
13545779Sxy150489  * e1000_reset_init_script_82575 - Inits HW defaults after reset
13555779Sxy150489  * @hw: pointer to the HW structure
13565779Sxy150489  *
13575779Sxy150489  * Inits recommended HW defaults after a reset when there is no EEPROM
13585779Sxy150489  * detected. This is only for the 82575.
13595779Sxy150489  */
13605779Sxy150489 static s32
e1000_reset_init_script_82575(struct e1000_hw * hw)13615779Sxy150489 e1000_reset_init_script_82575(struct e1000_hw *hw)
13625779Sxy150489 {
13635779Sxy150489 	DEBUGFUNC("e1000_reset_init_script_82575");
13645779Sxy150489 
13655779Sxy150489 	if (hw->mac.type == e1000_82575) {
13665779Sxy150489 		DEBUGOUT("Running reset init script for 82575\n");
13675779Sxy150489 		/* SerDes configuration via SERDESCTRL */
13688571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL,
13698571SChenlu.Chen@Sun.COM 		    0x00, 0x0C);
13708571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL,
13718571SChenlu.Chen@Sun.COM 		    0x01, 0x78);
13728571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL,
13738571SChenlu.Chen@Sun.COM 		    0x1B, 0x23);
13748571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL,
13758571SChenlu.Chen@Sun.COM 		    0x23, 0x15);
13765779Sxy150489 
13775779Sxy150489 		/* CCM configuration via CCMCTL register */
13788571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL,
13798571SChenlu.Chen@Sun.COM 		    0x14, 0x00);
13808571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL,
13818571SChenlu.Chen@Sun.COM 		    0x10, 0x00);
13825779Sxy150489 
13835779Sxy150489 		/* PCIe lanes configuration */
13848571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL,
13858571SChenlu.Chen@Sun.COM 		    0x00, 0xEC);
13868571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL,
13878571SChenlu.Chen@Sun.COM 		    0x61, 0xDF);
13888571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL,
13898571SChenlu.Chen@Sun.COM 		    0x34, 0x05);
13908571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL,
13918571SChenlu.Chen@Sun.COM 		    0x2F, 0x81);
13925779Sxy150489 
13935779Sxy150489 		/* PCIe PLL Configuration */
13948571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL,
13958571SChenlu.Chen@Sun.COM 		    0x02, 0x47);
13968571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL,
13978571SChenlu.Chen@Sun.COM 		    0x14, 0x00);
13988571SChenlu.Chen@Sun.COM 		(void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL,
13998571SChenlu.Chen@Sun.COM 		    0x10, 0x00);
14005779Sxy150489 	}
14015779Sxy150489 
14025779Sxy150489 	return (E1000_SUCCESS);
14035779Sxy150489 }
14045779Sxy150489 
14055779Sxy150489 /*
14065779Sxy150489  * e1000_read_mac_addr_82575 - Read device MAC address
14075779Sxy150489  * @hw: pointer to the HW structure
14085779Sxy150489  */
14095779Sxy150489 static s32
e1000_read_mac_addr_82575(struct e1000_hw * hw)14105779Sxy150489 e1000_read_mac_addr_82575(struct e1000_hw *hw)
14115779Sxy150489 {
14125779Sxy150489 	s32 ret_val = E1000_SUCCESS;
14135779Sxy150489 
14145779Sxy150489 	DEBUGFUNC("e1000_read_mac_addr_82575");
14155779Sxy150489 
141610319SJason.Xu@Sun.COM 	/*
141710319SJason.Xu@Sun.COM 	 * If there's an alternate MAC address place it in RAR0
141810319SJason.Xu@Sun.COM 	 * so that it will override the Si installed default perm
141910319SJason.Xu@Sun.COM 	 * address.
142010319SJason.Xu@Sun.COM 	 */
142110319SJason.Xu@Sun.COM 	ret_val = e1000_check_alt_mac_addr_generic(hw);
142210319SJason.Xu@Sun.COM 	if (ret_val)
142310319SJason.Xu@Sun.COM 		goto out;
142410319SJason.Xu@Sun.COM 
142510319SJason.Xu@Sun.COM 	ret_val = e1000_read_mac_addr_generic(hw);
142610319SJason.Xu@Sun.COM 
142710319SJason.Xu@Sun.COM out:
14285779Sxy150489 	return (ret_val);
14295779Sxy150489 }
14305779Sxy150489 
14315779Sxy150489 /*
14325779Sxy150489  * e1000_power_down_phy_copper_82575 - Remove link during PHY power down
14335779Sxy150489  * @hw: pointer to the HW structure
14345779Sxy150489  *
14355779Sxy150489  * In the case of a PHY power down to save power, or to turn off link during a
14365779Sxy150489  * driver unload, or wake on lan is not enabled, remove the link.
14375779Sxy150489  */
14385779Sxy150489 static void
e1000_power_down_phy_copper_82575(struct e1000_hw * hw)14395779Sxy150489 e1000_power_down_phy_copper_82575(struct e1000_hw *hw)
14405779Sxy150489 {
14418571SChenlu.Chen@Sun.COM 	struct e1000_phy_info *phy = &hw->phy;
14428571SChenlu.Chen@Sun.COM 	struct e1000_mac_info *mac = &hw->mac;
14438571SChenlu.Chen@Sun.COM 
14448571SChenlu.Chen@Sun.COM 	if (!(phy->ops.check_reset_block))
14458571SChenlu.Chen@Sun.COM 		return;
14468571SChenlu.Chen@Sun.COM 
14475779Sxy150489 	/* If the management interface is not enabled, then power down */
14488571SChenlu.Chen@Sun.COM 	if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw)))
14495779Sxy150489 		e1000_power_down_phy_copper(hw);
14505779Sxy150489 }
14515779Sxy150489 
14525779Sxy150489 /*
14535779Sxy150489  * e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters
14545779Sxy150489  * @hw: pointer to the HW structure
14555779Sxy150489  *
14565779Sxy150489  * Clears the hardware counters by reading the counter registers.
14575779Sxy150489  */
14585779Sxy150489 static void
e1000_clear_hw_cntrs_82575(struct e1000_hw * hw)14595779Sxy150489 e1000_clear_hw_cntrs_82575(struct e1000_hw *hw)
14605779Sxy150489 {
14615779Sxy150489 	DEBUGFUNC("e1000_clear_hw_cntrs_82575");
14625779Sxy150489 
14635779Sxy150489 	e1000_clear_hw_cntrs_base_generic(hw);
14645779Sxy150489 
14655779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PRC64);
14665779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PRC127);
14675779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PRC255);
14685779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PRC511);
14695779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PRC1023);
14705779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PRC1522);
14715779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PTC64);
14725779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PTC127);
14735779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PTC255);
14745779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PTC511);
14755779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PTC1023);
14765779Sxy150489 	(void) E1000_READ_REG(hw, E1000_PTC1522);
14775779Sxy150489 
14785779Sxy150489 	(void) E1000_READ_REG(hw, E1000_ALGNERRC);
14795779Sxy150489 	(void) E1000_READ_REG(hw, E1000_RXERRC);
14805779Sxy150489 	(void) E1000_READ_REG(hw, E1000_TNCRS);
14815779Sxy150489 	(void) E1000_READ_REG(hw, E1000_CEXTERR);
14825779Sxy150489 	(void) E1000_READ_REG(hw, E1000_TSCTC);
14835779Sxy150489 	(void) E1000_READ_REG(hw, E1000_TSCTFC);
14845779Sxy150489 
14855779Sxy150489 	(void) E1000_READ_REG(hw, E1000_MGTPRC);
14865779Sxy150489 	(void) E1000_READ_REG(hw, E1000_MGTPDC);
14875779Sxy150489 	(void) E1000_READ_REG(hw, E1000_MGTPTC);
14885779Sxy150489 
14895779Sxy150489 	(void) E1000_READ_REG(hw, E1000_IAC);
14905779Sxy150489 	(void) E1000_READ_REG(hw, E1000_ICRXOC);
14915779Sxy150489 
14925779Sxy150489 	(void) E1000_READ_REG(hw, E1000_ICRXPTC);
14935779Sxy150489 	(void) E1000_READ_REG(hw, E1000_ICRXATC);
14945779Sxy150489 	(void) E1000_READ_REG(hw, E1000_ICTXPTC);
14955779Sxy150489 	(void) E1000_READ_REG(hw, E1000_ICTXATC);
14965779Sxy150489 	(void) E1000_READ_REG(hw, E1000_ICTXQEC);
14975779Sxy150489 	(void) E1000_READ_REG(hw, E1000_ICTXQMTC);
14985779Sxy150489 	(void) E1000_READ_REG(hw, E1000_ICRXDMTC);
14995779Sxy150489 
15005779Sxy150489 	(void) E1000_READ_REG(hw, E1000_CBTMPC);
15015779Sxy150489 	(void) E1000_READ_REG(hw, E1000_HTDPMC);
15025779Sxy150489 	(void) E1000_READ_REG(hw, E1000_CBRMPC);
15035779Sxy150489 	(void) E1000_READ_REG(hw, E1000_RPTHC);
15045779Sxy150489 	(void) E1000_READ_REG(hw, E1000_HGPTC);
15055779Sxy150489 	(void) E1000_READ_REG(hw, E1000_HTCBDPC);
15065779Sxy150489 	(void) E1000_READ_REG(hw, E1000_HGORCL);
15075779Sxy150489 	(void) E1000_READ_REG(hw, E1000_HGORCH);
15085779Sxy150489 	(void) E1000_READ_REG(hw, E1000_HGOTCL);
15095779Sxy150489 	(void) E1000_READ_REG(hw, E1000_HGOTCH);
15105779Sxy150489 	(void) E1000_READ_REG(hw, E1000_LENERRS);
15115779Sxy150489 
15125779Sxy150489 	/* This register should not be read in copper configurations */
151311155SJason.Xu@Sun.COM 	if ((hw->phy.media_type == e1000_media_type_internal_serdes) ||
151411155SJason.Xu@Sun.COM 	    e1000_sgmii_active_82575(hw))
15155779Sxy150489 		(void) E1000_READ_REG(hw, E1000_SCVPC);
15165779Sxy150489 }
15178571SChenlu.Chen@Sun.COM 
15188571SChenlu.Chen@Sun.COM /*
15198571SChenlu.Chen@Sun.COM  * e1000_rx_fifo_flush_82575 - Clean rx fifo after RX enable
15208571SChenlu.Chen@Sun.COM  * @hw: pointer to the HW structure
15218571SChenlu.Chen@Sun.COM  *
15228571SChenlu.Chen@Sun.COM  * After rx enable if managability is enabled then there is likely some
15238571SChenlu.Chen@Sun.COM  * bad data at the start of the fifo and possibly in the DMA fifo.  This
15248571SChenlu.Chen@Sun.COM  * function clears the fifos and flushes any packets that came in as rx was
15258571SChenlu.Chen@Sun.COM  * being enabled.
15268571SChenlu.Chen@Sun.COM  */
15278571SChenlu.Chen@Sun.COM void
e1000_rx_fifo_flush_82575(struct e1000_hw * hw)15288571SChenlu.Chen@Sun.COM e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
15298571SChenlu.Chen@Sun.COM {
15308571SChenlu.Chen@Sun.COM 	u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
15318571SChenlu.Chen@Sun.COM 	int i, ms_wait;
15328571SChenlu.Chen@Sun.COM 
15338571SChenlu.Chen@Sun.COM 	DEBUGFUNC("e1000_rx_fifo_workaround_82575");
15348571SChenlu.Chen@Sun.COM 	if (hw->mac.type != e1000_82575 ||
15358571SChenlu.Chen@Sun.COM 	    !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN))
15368571SChenlu.Chen@Sun.COM 		return;
15378571SChenlu.Chen@Sun.COM 
15388571SChenlu.Chen@Sun.COM 	/* Disable all RX queues */
15398571SChenlu.Chen@Sun.COM 	for (i = 0; i < 4; i++) {
15408571SChenlu.Chen@Sun.COM 		rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i));
15418571SChenlu.Chen@Sun.COM 		E1000_WRITE_REG(hw, E1000_RXDCTL(i),
15428571SChenlu.Chen@Sun.COM 		    rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE);
15438571SChenlu.Chen@Sun.COM 	}
15448571SChenlu.Chen@Sun.COM 	/* Poll all queues to verify they have shut down */
15458571SChenlu.Chen@Sun.COM 	for (ms_wait = 0; ms_wait < 10; ms_wait++) {
15468571SChenlu.Chen@Sun.COM 		msec_delay(1);
15478571SChenlu.Chen@Sun.COM 		rx_enabled = 0;
15488571SChenlu.Chen@Sun.COM 		for (i = 0; i < 4; i++)
15498571SChenlu.Chen@Sun.COM 			rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i));
15508571SChenlu.Chen@Sun.COM 		if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE))
15518571SChenlu.Chen@Sun.COM 			break;
15528571SChenlu.Chen@Sun.COM 	}
15538571SChenlu.Chen@Sun.COM 
15548571SChenlu.Chen@Sun.COM 	if (ms_wait == 10)
15558571SChenlu.Chen@Sun.COM 		DEBUGOUT("Queue disable timed out after 10ms\n");
15568571SChenlu.Chen@Sun.COM 
15578571SChenlu.Chen@Sun.COM 	/*
15588571SChenlu.Chen@Sun.COM 	 * Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
15598571SChenlu.Chen@Sun.COM 	 * incoming packets are rejected.  Set enable and wait 2ms so that
15608571SChenlu.Chen@Sun.COM 	 * any packet that was coming in as RCTL.EN was set is flushed
15618571SChenlu.Chen@Sun.COM 	 */
15628571SChenlu.Chen@Sun.COM 	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
15638571SChenlu.Chen@Sun.COM 	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF);
15648571SChenlu.Chen@Sun.COM 
15658571SChenlu.Chen@Sun.COM 	rlpml = E1000_READ_REG(hw, E1000_RLPML);
15668571SChenlu.Chen@Sun.COM 	E1000_WRITE_REG(hw, E1000_RLPML, 0);
15678571SChenlu.Chen@Sun.COM 
15688571SChenlu.Chen@Sun.COM 	rctl = E1000_READ_REG(hw, E1000_RCTL);
15698571SChenlu.Chen@Sun.COM 	temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP);
15708571SChenlu.Chen@Sun.COM 	temp_rctl |= E1000_RCTL_LPE;
15718571SChenlu.Chen@Sun.COM 
15728571SChenlu.Chen@Sun.COM 	E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl);
15738571SChenlu.Chen@Sun.COM 	E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN);
15748571SChenlu.Chen@Sun.COM 	E1000_WRITE_FLUSH(hw);
15758571SChenlu.Chen@Sun.COM 	msec_delay(2);
15768571SChenlu.Chen@Sun.COM 
15778571SChenlu.Chen@Sun.COM 	/*
15788571SChenlu.Chen@Sun.COM 	 * Enable RX queues that were previously enabled and restore our
15798571SChenlu.Chen@Sun.COM 	 * previous state
15808571SChenlu.Chen@Sun.COM 	 */
15818571SChenlu.Chen@Sun.COM 	for (i = 0; i < 4; i++)
15828571SChenlu.Chen@Sun.COM 		E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]);
15838571SChenlu.Chen@Sun.COM 	E1000_WRITE_REG(hw, E1000_RCTL, rctl);
15848571SChenlu.Chen@Sun.COM 	E1000_WRITE_FLUSH(hw);
15858571SChenlu.Chen@Sun.COM 
15868571SChenlu.Chen@Sun.COM 	E1000_WRITE_REG(hw, E1000_RLPML, rlpml);
15878571SChenlu.Chen@Sun.COM 	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
15888571SChenlu.Chen@Sun.COM 
15898571SChenlu.Chen@Sun.COM 	/* Flush receive errors generated by workaround */
15908571SChenlu.Chen@Sun.COM 	(void) E1000_READ_REG(hw, E1000_ROC);
15918571SChenlu.Chen@Sun.COM 	(void) E1000_READ_REG(hw, E1000_RNBC);
15928571SChenlu.Chen@Sun.COM 	(void) E1000_READ_REG(hw, E1000_MPC);
15938571SChenlu.Chen@Sun.COM }
159410319SJason.Xu@Sun.COM 
159510319SJason.Xu@Sun.COM /*
159610319SJason.Xu@Sun.COM  * e1000_set_pcie_completion_timeout - set pci-e completion timeout
159710319SJason.Xu@Sun.COM  * @hw: pointer to the HW structure
159810319SJason.Xu@Sun.COM  *
159910319SJason.Xu@Sun.COM  * The defaults for 82575 and 82576 should be in the range of 50us to 50ms,
160010319SJason.Xu@Sun.COM  * however the hardware default for these parts is 500us to 1ms which is less
160110319SJason.Xu@Sun.COM  * than the 10ms recommended by the pci-e spec.  To address this we need to
160210319SJason.Xu@Sun.COM  * increase the value to either 10ms to 200ms for capability version 1 config,
160310319SJason.Xu@Sun.COM  * or 16ms to 55ms for version 2.
160410319SJason.Xu@Sun.COM  */
160510319SJason.Xu@Sun.COM static s32
e1000_set_pcie_completion_timeout(struct e1000_hw * hw)160610319SJason.Xu@Sun.COM e1000_set_pcie_completion_timeout(struct e1000_hw *hw)
160710319SJason.Xu@Sun.COM {
160810319SJason.Xu@Sun.COM 	u32 gcr = E1000_READ_REG(hw, E1000_GCR);
160910319SJason.Xu@Sun.COM 	s32 ret_val = E1000_SUCCESS;
161010319SJason.Xu@Sun.COM 	u16 pcie_devctl2;
161110319SJason.Xu@Sun.COM 
161210319SJason.Xu@Sun.COM 	/* only take action if timeout value is defaulted to 0 */
161310319SJason.Xu@Sun.COM 	if (gcr & E1000_GCR_CMPL_TMOUT_MASK)
161410319SJason.Xu@Sun.COM 		goto out;
161510319SJason.Xu@Sun.COM 
161610319SJason.Xu@Sun.COM 	/*
161710319SJason.Xu@Sun.COM 	 * if capababilities version is type 1 we can write the
161810319SJason.Xu@Sun.COM 	 * timeout of 10ms to 200ms through the GCR register
161910319SJason.Xu@Sun.COM 	 */
162010319SJason.Xu@Sun.COM 	if (!(gcr & E1000_GCR_CAP_VER2)) {
162110319SJason.Xu@Sun.COM 		gcr |= E1000_GCR_CMPL_TMOUT_10ms;
162210319SJason.Xu@Sun.COM 		goto out;
162310319SJason.Xu@Sun.COM 	}
162410319SJason.Xu@Sun.COM 
162510319SJason.Xu@Sun.COM 	/*
162610319SJason.Xu@Sun.COM 	 * for version 2 capabilities we need to write the config space
162710319SJason.Xu@Sun.COM 	 * directly in order to set the completion timeout value for
162810319SJason.Xu@Sun.COM 	 * 16ms to 55ms
162910319SJason.Xu@Sun.COM 	 */
163010319SJason.Xu@Sun.COM 	ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
163110319SJason.Xu@Sun.COM 	    &pcie_devctl2);
163210319SJason.Xu@Sun.COM 	if (ret_val)
163310319SJason.Xu@Sun.COM 		goto out;
163410319SJason.Xu@Sun.COM 
163510319SJason.Xu@Sun.COM 	pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms;
163610319SJason.Xu@Sun.COM 
163710319SJason.Xu@Sun.COM 	ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
163810319SJason.Xu@Sun.COM 	    &pcie_devctl2);
163910319SJason.Xu@Sun.COM out:
164010319SJason.Xu@Sun.COM 	/* disable completion timeout resend */
164110319SJason.Xu@Sun.COM 	gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND;
164210319SJason.Xu@Sun.COM 
164310319SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_GCR, gcr);
164410319SJason.Xu@Sun.COM 	return (ret_val);
164510319SJason.Xu@Sun.COM }
164611155SJason.Xu@Sun.COM 
164711155SJason.Xu@Sun.COM /*
164811155SJason.Xu@Sun.COM  * e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback
164911155SJason.Xu@Sun.COM  * @hw: pointer to the hardware struct
165011155SJason.Xu@Sun.COM  * @enable: state to enter, either enabled or disabled
165111155SJason.Xu@Sun.COM  *
165211155SJason.Xu@Sun.COM  * enables/disables L2 switch loopback functionality.
165311155SJason.Xu@Sun.COM  */
165411155SJason.Xu@Sun.COM void
e1000_vmdq_set_loopback_pf(struct e1000_hw * hw,bool enable)165511155SJason.Xu@Sun.COM e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
165611155SJason.Xu@Sun.COM {
165711155SJason.Xu@Sun.COM 	u32 dtxswc = E1000_READ_REG(hw, E1000_DTXSWC);
165811155SJason.Xu@Sun.COM 
165911155SJason.Xu@Sun.COM 	if (enable)
166011155SJason.Xu@Sun.COM 		dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
166111155SJason.Xu@Sun.COM 	else
166211155SJason.Xu@Sun.COM 		dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
166311155SJason.Xu@Sun.COM 
166411155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
166511155SJason.Xu@Sun.COM }
166611155SJason.Xu@Sun.COM 
166711155SJason.Xu@Sun.COM /*
166811155SJason.Xu@Sun.COM  * e1000_vmdq_set_replication_pf - enable or disable vmdq replication
166911155SJason.Xu@Sun.COM  * @hw: pointer to the hardware struct
167011155SJason.Xu@Sun.COM  * @enable: state to enter, either enabled or disabled
167111155SJason.Xu@Sun.COM  *
167211155SJason.Xu@Sun.COM  * enables/disables replication of packets across multiple pools.
167311155SJason.Xu@Sun.COM  */
167411155SJason.Xu@Sun.COM void
e1000_vmdq_set_replication_pf(struct e1000_hw * hw,bool enable)167511155SJason.Xu@Sun.COM e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable)
167611155SJason.Xu@Sun.COM {
167711155SJason.Xu@Sun.COM 	u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL);
167811155SJason.Xu@Sun.COM 
167911155SJason.Xu@Sun.COM 	if (enable)
168011155SJason.Xu@Sun.COM 		vt_ctl |= E1000_VT_CTL_VM_REPL_EN;
168111155SJason.Xu@Sun.COM 	else
168211155SJason.Xu@Sun.COM 		vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN;
168311155SJason.Xu@Sun.COM 
168411155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl);
168511155SJason.Xu@Sun.COM }
168611155SJason.Xu@Sun.COM 
168711155SJason.Xu@Sun.COM /*
168811155SJason.Xu@Sun.COM  * e1000_read_phy_reg_82580 - Read 82580 MDI control register
168911155SJason.Xu@Sun.COM  * @hw: pointer to the HW structure
169011155SJason.Xu@Sun.COM  * @offset: register offset to be read
169111155SJason.Xu@Sun.COM  * @data: pointer to the read data
169211155SJason.Xu@Sun.COM  *
169311155SJason.Xu@Sun.COM  * Reads the MDI control register in the PHY at offset and stores the
169411155SJason.Xu@Sun.COM  * information read to data.
169511155SJason.Xu@Sun.COM  */
169611155SJason.Xu@Sun.COM static s32
e1000_read_phy_reg_82580(struct e1000_hw * hw,u32 offset,u16 * data)169711155SJason.Xu@Sun.COM e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data)
169811155SJason.Xu@Sun.COM {
169911155SJason.Xu@Sun.COM 	u32 mdicnfg = 0;
170011155SJason.Xu@Sun.COM 	s32 ret_val;
170111155SJason.Xu@Sun.COM 
170211155SJason.Xu@Sun.COM 	DEBUGFUNC("e1000_read_phy_reg_82580");
170311155SJason.Xu@Sun.COM 
170411155SJason.Xu@Sun.COM 	ret_val = hw->phy.ops.acquire(hw);
170511155SJason.Xu@Sun.COM 	if (ret_val)
170611155SJason.Xu@Sun.COM 		goto out;
170711155SJason.Xu@Sun.COM 
170811155SJason.Xu@Sun.COM 	/*
170911155SJason.Xu@Sun.COM 	 * We config the phy address in MDICNFG register now. Same bits
171011155SJason.Xu@Sun.COM 	 * as before. The values in MDIC can be written but will be
171111155SJason.Xu@Sun.COM 	 * ignored. This allows us to call the old function after
171211155SJason.Xu@Sun.COM 	 * configuring the PHY address in the new register
171311155SJason.Xu@Sun.COM 	 */
171411155SJason.Xu@Sun.COM 	mdicnfg = (hw->phy.addr << E1000_MDIC_PHY_SHIFT);
171511155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg);
171611155SJason.Xu@Sun.COM 
171711155SJason.Xu@Sun.COM 	ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
171811155SJason.Xu@Sun.COM 
171911155SJason.Xu@Sun.COM 	hw->phy.ops.release(hw);
172011155SJason.Xu@Sun.COM 
172111155SJason.Xu@Sun.COM out:
172211155SJason.Xu@Sun.COM 	return (ret_val);
172311155SJason.Xu@Sun.COM }
172411155SJason.Xu@Sun.COM 
172511155SJason.Xu@Sun.COM /*
172611155SJason.Xu@Sun.COM  * e1000_write_phy_reg_82580 - Write 82580 MDI control register
172711155SJason.Xu@Sun.COM  * @hw: pointer to the HW structure
172811155SJason.Xu@Sun.COM  * @offset: register offset to write to
172911155SJason.Xu@Sun.COM  * @data: data to write to register at offset
173011155SJason.Xu@Sun.COM  *
173111155SJason.Xu@Sun.COM  * Writes data to MDI control register in the PHY at offset.
173211155SJason.Xu@Sun.COM  */
173311155SJason.Xu@Sun.COM static s32
e1000_write_phy_reg_82580(struct e1000_hw * hw,u32 offset,u16 data)173411155SJason.Xu@Sun.COM e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data)
173511155SJason.Xu@Sun.COM {
173611155SJason.Xu@Sun.COM 	u32 mdicnfg = 0;
173711155SJason.Xu@Sun.COM 	s32 ret_val;
173811155SJason.Xu@Sun.COM 
173911155SJason.Xu@Sun.COM 	DEBUGFUNC("e1000_write_phy_reg_82580");
174011155SJason.Xu@Sun.COM 
174111155SJason.Xu@Sun.COM 	ret_val = hw->phy.ops.acquire(hw);
174211155SJason.Xu@Sun.COM 	if (ret_val)
174311155SJason.Xu@Sun.COM 		goto out;
174411155SJason.Xu@Sun.COM 
174511155SJason.Xu@Sun.COM 	/*
174611155SJason.Xu@Sun.COM 	 * We config the phy address in MDICNFG register now. Same bits
174711155SJason.Xu@Sun.COM 	 * as before. The values in MDIC can be written but will be
174811155SJason.Xu@Sun.COM 	 * ignored. This allows us to call the old function after
174911155SJason.Xu@Sun.COM 	 * configuring the PHY address in the new register
175011155SJason.Xu@Sun.COM 	 */
175111155SJason.Xu@Sun.COM 	mdicnfg = (hw->phy.addr << E1000_MDIC_PHY_SHIFT);
175211155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg);
175311155SJason.Xu@Sun.COM 
175411155SJason.Xu@Sun.COM 	ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
175511155SJason.Xu@Sun.COM 
175611155SJason.Xu@Sun.COM 	hw->phy.ops.release(hw);
175711155SJason.Xu@Sun.COM 
175811155SJason.Xu@Sun.COM out:
175911155SJason.Xu@Sun.COM 	return (ret_val);
176011155SJason.Xu@Sun.COM }
176111155SJason.Xu@Sun.COM 
176211155SJason.Xu@Sun.COM /*
176311155SJason.Xu@Sun.COM  * e1000_reset_hw_82580 - Reset hardware
176411155SJason.Xu@Sun.COM  * @hw: pointer to the HW structure
176511155SJason.Xu@Sun.COM  *
176611155SJason.Xu@Sun.COM  * This resets function or entire device (all ports, etc.)
176711155SJason.Xu@Sun.COM  * to a known state.
176811155SJason.Xu@Sun.COM  */
176911155SJason.Xu@Sun.COM static s32
e1000_reset_hw_82580(struct e1000_hw * hw)177011155SJason.Xu@Sun.COM e1000_reset_hw_82580(struct e1000_hw *hw)
177111155SJason.Xu@Sun.COM {
177211155SJason.Xu@Sun.COM 	s32 ret_val = E1000_SUCCESS;
177311155SJason.Xu@Sun.COM 	/* BH SW mailbox bit in SW_FW_SYNC */
177411155SJason.Xu@Sun.COM 	u16 swmbsw_mask = E1000_SW_SYNCH_MB;
177511155SJason.Xu@Sun.COM 	u32 ctrl;
177611155SJason.Xu@Sun.COM 	bool global_device_reset = hw->dev_spec._82575.global_device_reset;
177711155SJason.Xu@Sun.COM 
177811155SJason.Xu@Sun.COM 	DEBUGFUNC("e1000_reset_hw_82580");
177911155SJason.Xu@Sun.COM 
178011155SJason.Xu@Sun.COM 	hw->dev_spec._82575.global_device_reset = false;
178111155SJason.Xu@Sun.COM 
178211155SJason.Xu@Sun.COM 	/* Get current control state. */
178311155SJason.Xu@Sun.COM 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
178411155SJason.Xu@Sun.COM 
178511155SJason.Xu@Sun.COM 	/*
178611155SJason.Xu@Sun.COM 	 * Prevent the PCI-E bus from sticking if there is no TLP connection
178711155SJason.Xu@Sun.COM 	 * on the last TLP read/write transaction when MAC is reset.
178811155SJason.Xu@Sun.COM 	 */
178911155SJason.Xu@Sun.COM 	ret_val = e1000_disable_pcie_master_generic(hw);
179011155SJason.Xu@Sun.COM 	if (ret_val)
179111155SJason.Xu@Sun.COM 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
179211155SJason.Xu@Sun.COM 
179311155SJason.Xu@Sun.COM 	DEBUGOUT("Masking off all interrupts\n");
179411155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
179511155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
179611155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
179711155SJason.Xu@Sun.COM 	E1000_WRITE_FLUSH(hw);
179811155SJason.Xu@Sun.COM 
179911155SJason.Xu@Sun.COM 	msec_delay(10);
180011155SJason.Xu@Sun.COM 
180111155SJason.Xu@Sun.COM 	/* Determine whether or not a global dev reset is requested */
180211155SJason.Xu@Sun.COM 	if (global_device_reset &&
180311155SJason.Xu@Sun.COM 	    e1000_acquire_swfw_sync_82575(hw, swmbsw_mask))
180411155SJason.Xu@Sun.COM 		global_device_reset = false;
180511155SJason.Xu@Sun.COM 
180611155SJason.Xu@Sun.COM 	if (global_device_reset &&
180711155SJason.Xu@Sun.COM 	    !(E1000_READ_REG(hw, E1000_STATUS) & E1000_STAT_DEV_RST_SET))
180811155SJason.Xu@Sun.COM 		ctrl |= E1000_CTRL_DEV_RST;
180911155SJason.Xu@Sun.COM 	else
181011155SJason.Xu@Sun.COM 		ctrl |= E1000_CTRL_RST;
181111155SJason.Xu@Sun.COM 
181211155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
181311155SJason.Xu@Sun.COM 
181411155SJason.Xu@Sun.COM 	/* Add delay to insure DEV_RST has time to complete */
181511155SJason.Xu@Sun.COM 	if (global_device_reset)
181611155SJason.Xu@Sun.COM 		msec_delay(5);
181711155SJason.Xu@Sun.COM 
181811155SJason.Xu@Sun.COM 	ret_val = e1000_get_auto_rd_done_generic(hw);
181911155SJason.Xu@Sun.COM 	if (ret_val) {
182011155SJason.Xu@Sun.COM 		/*
182111155SJason.Xu@Sun.COM 		 * When auto config read does not complete, do not
182211155SJason.Xu@Sun.COM 		 * return with an error. This can happen in situations
182311155SJason.Xu@Sun.COM 		 * where there is no eeprom and prevents getting link.
182411155SJason.Xu@Sun.COM 		 */
182511155SJason.Xu@Sun.COM 		DEBUGOUT("Auto Read Done did not complete\n");
182611155SJason.Xu@Sun.COM 	}
182711155SJason.Xu@Sun.COM 
182811155SJason.Xu@Sun.COM 	/* If EEPROM is not present, run manual init scripts */
182911155SJason.Xu@Sun.COM 	if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0)
183011387SSurya.Prakki@Sun.COM 		(void) e1000_reset_init_script_82575(hw);
183111155SJason.Xu@Sun.COM 
183211155SJason.Xu@Sun.COM 	/* clear global device reset status bit */
183311155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET);
183411155SJason.Xu@Sun.COM 
183511155SJason.Xu@Sun.COM 	/* Clear any pending interrupt events. */
183611155SJason.Xu@Sun.COM 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
183711155SJason.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_ICR);
183811155SJason.Xu@Sun.COM 
183911155SJason.Xu@Sun.COM 	/* Install any alternate MAC address into RAR0 */
184011155SJason.Xu@Sun.COM 	ret_val = e1000_check_alt_mac_addr_generic(hw);
184111155SJason.Xu@Sun.COM 
184211155SJason.Xu@Sun.COM 	/* Release semaphore */
184311155SJason.Xu@Sun.COM 	if (global_device_reset)
184411155SJason.Xu@Sun.COM 		e1000_release_swfw_sync_82575(hw, swmbsw_mask);
184511155SJason.Xu@Sun.COM 
184611155SJason.Xu@Sun.COM 	return (ret_val);
184711155SJason.Xu@Sun.COM }
184811155SJason.Xu@Sun.COM 
184911155SJason.Xu@Sun.COM /*
185011155SJason.Xu@Sun.COM  * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual RX PBA size
185111155SJason.Xu@Sun.COM  * @data: data received by reading RXPBS register
185211155SJason.Xu@Sun.COM  *
185311155SJason.Xu@Sun.COM  * The 82580 uses a table based approach for packet buffer allocation sizes.
185411155SJason.Xu@Sun.COM  * This function converts the retrieved value into the correct table value
185511155SJason.Xu@Sun.COM  *    0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7
185611155SJason.Xu@Sun.COM  * 0x0 36  72 144   1   2   4   8  16
185711155SJason.Xu@Sun.COM  * 0x8 35  70 140 rsv rsv rsv rsv rsv
185811155SJason.Xu@Sun.COM  */
185911155SJason.Xu@Sun.COM u16
e1000_rxpbs_adjust_82580(u32 data)186011155SJason.Xu@Sun.COM e1000_rxpbs_adjust_82580(u32 data)
186111155SJason.Xu@Sun.COM {
186211155SJason.Xu@Sun.COM 	u16 ret_val = 0;
186311155SJason.Xu@Sun.COM 
186411155SJason.Xu@Sun.COM 	if (data < E1000_82580_RXPBS_TABLE_SIZE)
186511155SJason.Xu@Sun.COM 		ret_val = e1000_82580_rxpbs_table[data];
186611155SJason.Xu@Sun.COM 
186711155SJason.Xu@Sun.COM 	return (ret_val);
186811155SJason.Xu@Sun.COM }
1869