18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci/* 82571EB Gigabit Ethernet Controller
58c2ecf20Sopenharmony_ci * 82571EB Gigabit Ethernet Controller (Copper)
68c2ecf20Sopenharmony_ci * 82571EB Gigabit Ethernet Controller (Fiber)
78c2ecf20Sopenharmony_ci * 82571EB Dual Port Gigabit Mezzanine Adapter
88c2ecf20Sopenharmony_ci * 82571EB Quad Port Gigabit Mezzanine Adapter
98c2ecf20Sopenharmony_ci * 82571PT Gigabit PT Quad Port Server ExpressModule
108c2ecf20Sopenharmony_ci * 82572EI Gigabit Ethernet Controller (Copper)
118c2ecf20Sopenharmony_ci * 82572EI Gigabit Ethernet Controller (Fiber)
128c2ecf20Sopenharmony_ci * 82572EI Gigabit Ethernet Controller
138c2ecf20Sopenharmony_ci * 82573V Gigabit Ethernet Controller (Copper)
148c2ecf20Sopenharmony_ci * 82573E Gigabit Ethernet Controller (Copper)
158c2ecf20Sopenharmony_ci * 82573L Gigabit Ethernet Controller
168c2ecf20Sopenharmony_ci * 82574L Gigabit Network Connection
178c2ecf20Sopenharmony_ci * 82583V Gigabit Network Connection
188c2ecf20Sopenharmony_ci */
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include "e1000.h"
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic s32 e1000_get_phy_id_82571(struct e1000_hw *hw);
238c2ecf20Sopenharmony_cistatic s32 e1000_setup_copper_link_82571(struct e1000_hw *hw);
248c2ecf20Sopenharmony_cistatic s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);
258c2ecf20Sopenharmony_cistatic s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw);
268c2ecf20Sopenharmony_cistatic s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
278c2ecf20Sopenharmony_ci				      u16 words, u16 *data);
288c2ecf20Sopenharmony_cistatic s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw);
298c2ecf20Sopenharmony_cistatic void e1000_initialize_hw_bits_82571(struct e1000_hw *hw);
308c2ecf20Sopenharmony_cistatic void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
318c2ecf20Sopenharmony_cistatic bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
328c2ecf20Sopenharmony_cistatic s32 e1000_led_on_82574(struct e1000_hw *hw);
338c2ecf20Sopenharmony_cistatic void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);
348c2ecf20Sopenharmony_cistatic void e1000_power_down_phy_copper_82571(struct e1000_hw *hw);
358c2ecf20Sopenharmony_cistatic void e1000_put_hw_semaphore_82573(struct e1000_hw *hw);
368c2ecf20Sopenharmony_cistatic s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw);
378c2ecf20Sopenharmony_cistatic void e1000_put_hw_semaphore_82574(struct e1000_hw *hw);
388c2ecf20Sopenharmony_cistatic s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active);
398c2ecf20Sopenharmony_cistatic s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/**
428c2ecf20Sopenharmony_ci *  e1000_init_phy_params_82571 - Init PHY func ptrs.
438c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
448c2ecf20Sopenharmony_ci **/
458c2ecf20Sopenharmony_cistatic s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	struct e1000_phy_info *phy = &hw->phy;
488c2ecf20Sopenharmony_ci	s32 ret_val;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	if (hw->phy.media_type != e1000_media_type_copper) {
518c2ecf20Sopenharmony_ci		phy->type = e1000_phy_none;
528c2ecf20Sopenharmony_ci		return 0;
538c2ecf20Sopenharmony_ci	}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	phy->addr = 1;
568c2ecf20Sopenharmony_ci	phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
578c2ecf20Sopenharmony_ci	phy->reset_delay_us = 100;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	phy->ops.power_up = e1000_power_up_phy_copper;
608c2ecf20Sopenharmony_ci	phy->ops.power_down = e1000_power_down_phy_copper_82571;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
638c2ecf20Sopenharmony_ci	case e1000_82571:
648c2ecf20Sopenharmony_ci	case e1000_82572:
658c2ecf20Sopenharmony_ci		phy->type = e1000_phy_igp_2;
668c2ecf20Sopenharmony_ci		break;
678c2ecf20Sopenharmony_ci	case e1000_82573:
688c2ecf20Sopenharmony_ci		phy->type = e1000_phy_m88;
698c2ecf20Sopenharmony_ci		break;
708c2ecf20Sopenharmony_ci	case e1000_82574:
718c2ecf20Sopenharmony_ci	case e1000_82583:
728c2ecf20Sopenharmony_ci		phy->type = e1000_phy_bm;
738c2ecf20Sopenharmony_ci		phy->ops.acquire = e1000_get_hw_semaphore_82574;
748c2ecf20Sopenharmony_ci		phy->ops.release = e1000_put_hw_semaphore_82574;
758c2ecf20Sopenharmony_ci		phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574;
768c2ecf20Sopenharmony_ci		phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82574;
778c2ecf20Sopenharmony_ci		break;
788c2ecf20Sopenharmony_ci	default:
798c2ecf20Sopenharmony_ci		return -E1000_ERR_PHY;
808c2ecf20Sopenharmony_ci	}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	/* This can only be done after all function pointers are setup. */
838c2ecf20Sopenharmony_ci	ret_val = e1000_get_phy_id_82571(hw);
848c2ecf20Sopenharmony_ci	if (ret_val) {
858c2ecf20Sopenharmony_ci		e_dbg("Error getting PHY ID\n");
868c2ecf20Sopenharmony_ci		return ret_val;
878c2ecf20Sopenharmony_ci	}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	/* Verify phy id */
908c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
918c2ecf20Sopenharmony_ci	case e1000_82571:
928c2ecf20Sopenharmony_ci	case e1000_82572:
938c2ecf20Sopenharmony_ci		if (phy->id != IGP01E1000_I_PHY_ID)
948c2ecf20Sopenharmony_ci			ret_val = -E1000_ERR_PHY;
958c2ecf20Sopenharmony_ci		break;
968c2ecf20Sopenharmony_ci	case e1000_82573:
978c2ecf20Sopenharmony_ci		if (phy->id != M88E1111_I_PHY_ID)
988c2ecf20Sopenharmony_ci			ret_val = -E1000_ERR_PHY;
998c2ecf20Sopenharmony_ci		break;
1008c2ecf20Sopenharmony_ci	case e1000_82574:
1018c2ecf20Sopenharmony_ci	case e1000_82583:
1028c2ecf20Sopenharmony_ci		if (phy->id != BME1000_E_PHY_ID_R2)
1038c2ecf20Sopenharmony_ci			ret_val = -E1000_ERR_PHY;
1048c2ecf20Sopenharmony_ci		break;
1058c2ecf20Sopenharmony_ci	default:
1068c2ecf20Sopenharmony_ci		ret_val = -E1000_ERR_PHY;
1078c2ecf20Sopenharmony_ci		break;
1088c2ecf20Sopenharmony_ci	}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	if (ret_val)
1118c2ecf20Sopenharmony_ci		e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	return ret_val;
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci/**
1178c2ecf20Sopenharmony_ci *  e1000_init_nvm_params_82571 - Init NVM func ptrs.
1188c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
1198c2ecf20Sopenharmony_ci **/
1208c2ecf20Sopenharmony_cistatic s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
1218c2ecf20Sopenharmony_ci{
1228c2ecf20Sopenharmony_ci	struct e1000_nvm_info *nvm = &hw->nvm;
1238c2ecf20Sopenharmony_ci	u32 eecd = er32(EECD);
1248c2ecf20Sopenharmony_ci	u16 size;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	nvm->opcode_bits = 8;
1278c2ecf20Sopenharmony_ci	nvm->delay_usec = 1;
1288c2ecf20Sopenharmony_ci	switch (nvm->override) {
1298c2ecf20Sopenharmony_ci	case e1000_nvm_override_spi_large:
1308c2ecf20Sopenharmony_ci		nvm->page_size = 32;
1318c2ecf20Sopenharmony_ci		nvm->address_bits = 16;
1328c2ecf20Sopenharmony_ci		break;
1338c2ecf20Sopenharmony_ci	case e1000_nvm_override_spi_small:
1348c2ecf20Sopenharmony_ci		nvm->page_size = 8;
1358c2ecf20Sopenharmony_ci		nvm->address_bits = 8;
1368c2ecf20Sopenharmony_ci		break;
1378c2ecf20Sopenharmony_ci	default:
1388c2ecf20Sopenharmony_ci		nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
1398c2ecf20Sopenharmony_ci		nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
1408c2ecf20Sopenharmony_ci		break;
1418c2ecf20Sopenharmony_ci	}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
1448c2ecf20Sopenharmony_ci	case e1000_82573:
1458c2ecf20Sopenharmony_ci	case e1000_82574:
1468c2ecf20Sopenharmony_ci	case e1000_82583:
1478c2ecf20Sopenharmony_ci		if (((eecd >> 15) & 0x3) == 0x3) {
1488c2ecf20Sopenharmony_ci			nvm->type = e1000_nvm_flash_hw;
1498c2ecf20Sopenharmony_ci			nvm->word_size = 2048;
1508c2ecf20Sopenharmony_ci			/* Autonomous Flash update bit must be cleared due
1518c2ecf20Sopenharmony_ci			 * to Flash update issue.
1528c2ecf20Sopenharmony_ci			 */
1538c2ecf20Sopenharmony_ci			eecd &= ~E1000_EECD_AUPDEN;
1548c2ecf20Sopenharmony_ci			ew32(EECD, eecd);
1558c2ecf20Sopenharmony_ci			break;
1568c2ecf20Sopenharmony_ci		}
1578c2ecf20Sopenharmony_ci		fallthrough;
1588c2ecf20Sopenharmony_ci	default:
1598c2ecf20Sopenharmony_ci		nvm->type = e1000_nvm_eeprom_spi;
1608c2ecf20Sopenharmony_ci		size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
1618c2ecf20Sopenharmony_ci			     E1000_EECD_SIZE_EX_SHIFT);
1628c2ecf20Sopenharmony_ci		/* Added to a constant, "size" becomes the left-shift value
1638c2ecf20Sopenharmony_ci		 * for setting word_size.
1648c2ecf20Sopenharmony_ci		 */
1658c2ecf20Sopenharmony_ci		size += NVM_WORD_SIZE_BASE_SHIFT;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci		/* EEPROM access above 16k is unsupported */
1688c2ecf20Sopenharmony_ci		if (size > 14)
1698c2ecf20Sopenharmony_ci			size = 14;
1708c2ecf20Sopenharmony_ci		nvm->word_size = BIT(size);
1718c2ecf20Sopenharmony_ci		break;
1728c2ecf20Sopenharmony_ci	}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	/* Function Pointers */
1758c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
1768c2ecf20Sopenharmony_ci	case e1000_82574:
1778c2ecf20Sopenharmony_ci	case e1000_82583:
1788c2ecf20Sopenharmony_ci		nvm->ops.acquire = e1000_get_hw_semaphore_82574;
1798c2ecf20Sopenharmony_ci		nvm->ops.release = e1000_put_hw_semaphore_82574;
1808c2ecf20Sopenharmony_ci		break;
1818c2ecf20Sopenharmony_ci	default:
1828c2ecf20Sopenharmony_ci		break;
1838c2ecf20Sopenharmony_ci	}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	return 0;
1868c2ecf20Sopenharmony_ci}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci/**
1898c2ecf20Sopenharmony_ci *  e1000_init_mac_params_82571 - Init MAC func ptrs.
1908c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
1918c2ecf20Sopenharmony_ci **/
1928c2ecf20Sopenharmony_cistatic s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	struct e1000_mac_info *mac = &hw->mac;
1958c2ecf20Sopenharmony_ci	u32 swsm = 0;
1968c2ecf20Sopenharmony_ci	u32 swsm2 = 0;
1978c2ecf20Sopenharmony_ci	bool force_clear_smbi = false;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	/* Set media type and media-dependent function pointers */
2008c2ecf20Sopenharmony_ci	switch (hw->adapter->pdev->device) {
2018c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82571EB_FIBER:
2028c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82572EI_FIBER:
2038c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82571EB_QUAD_FIBER:
2048c2ecf20Sopenharmony_ci		hw->phy.media_type = e1000_media_type_fiber;
2058c2ecf20Sopenharmony_ci		mac->ops.setup_physical_interface =
2068c2ecf20Sopenharmony_ci		    e1000_setup_fiber_serdes_link_82571;
2078c2ecf20Sopenharmony_ci		mac->ops.check_for_link = e1000e_check_for_fiber_link;
2088c2ecf20Sopenharmony_ci		mac->ops.get_link_up_info =
2098c2ecf20Sopenharmony_ci		    e1000e_get_speed_and_duplex_fiber_serdes;
2108c2ecf20Sopenharmony_ci		break;
2118c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82571EB_SERDES:
2128c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82571EB_SERDES_DUAL:
2138c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82571EB_SERDES_QUAD:
2148c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82572EI_SERDES:
2158c2ecf20Sopenharmony_ci		hw->phy.media_type = e1000_media_type_internal_serdes;
2168c2ecf20Sopenharmony_ci		mac->ops.setup_physical_interface =
2178c2ecf20Sopenharmony_ci		    e1000_setup_fiber_serdes_link_82571;
2188c2ecf20Sopenharmony_ci		mac->ops.check_for_link = e1000_check_for_serdes_link_82571;
2198c2ecf20Sopenharmony_ci		mac->ops.get_link_up_info =
2208c2ecf20Sopenharmony_ci		    e1000e_get_speed_and_duplex_fiber_serdes;
2218c2ecf20Sopenharmony_ci		break;
2228c2ecf20Sopenharmony_ci	default:
2238c2ecf20Sopenharmony_ci		hw->phy.media_type = e1000_media_type_copper;
2248c2ecf20Sopenharmony_ci		mac->ops.setup_physical_interface =
2258c2ecf20Sopenharmony_ci		    e1000_setup_copper_link_82571;
2268c2ecf20Sopenharmony_ci		mac->ops.check_for_link = e1000e_check_for_copper_link;
2278c2ecf20Sopenharmony_ci		mac->ops.get_link_up_info = e1000e_get_speed_and_duplex_copper;
2288c2ecf20Sopenharmony_ci		break;
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* Set mta register count */
2328c2ecf20Sopenharmony_ci	mac->mta_reg_count = 128;
2338c2ecf20Sopenharmony_ci	/* Set rar entry count */
2348c2ecf20Sopenharmony_ci	mac->rar_entry_count = E1000_RAR_ENTRIES;
2358c2ecf20Sopenharmony_ci	/* Adaptive IFS supported */
2368c2ecf20Sopenharmony_ci	mac->adaptive_ifs = true;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	/* MAC-specific function pointers */
2398c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
2408c2ecf20Sopenharmony_ci	case e1000_82573:
2418c2ecf20Sopenharmony_ci		mac->ops.set_lan_id = e1000_set_lan_id_single_port;
2428c2ecf20Sopenharmony_ci		mac->ops.check_mng_mode = e1000e_check_mng_mode_generic;
2438c2ecf20Sopenharmony_ci		mac->ops.led_on = e1000e_led_on_generic;
2448c2ecf20Sopenharmony_ci		mac->ops.blink_led = e1000e_blink_led_generic;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci		/* FWSM register */
2478c2ecf20Sopenharmony_ci		mac->has_fwsm = true;
2488c2ecf20Sopenharmony_ci		/* ARC supported; valid only if manageability features are
2498c2ecf20Sopenharmony_ci		 * enabled.
2508c2ecf20Sopenharmony_ci		 */
2518c2ecf20Sopenharmony_ci		mac->arc_subsystem_valid = !!(er32(FWSM) &
2528c2ecf20Sopenharmony_ci					      E1000_FWSM_MODE_MASK);
2538c2ecf20Sopenharmony_ci		break;
2548c2ecf20Sopenharmony_ci	case e1000_82574:
2558c2ecf20Sopenharmony_ci	case e1000_82583:
2568c2ecf20Sopenharmony_ci		mac->ops.set_lan_id = e1000_set_lan_id_single_port;
2578c2ecf20Sopenharmony_ci		mac->ops.check_mng_mode = e1000_check_mng_mode_82574;
2588c2ecf20Sopenharmony_ci		mac->ops.led_on = e1000_led_on_82574;
2598c2ecf20Sopenharmony_ci		break;
2608c2ecf20Sopenharmony_ci	default:
2618c2ecf20Sopenharmony_ci		mac->ops.check_mng_mode = e1000e_check_mng_mode_generic;
2628c2ecf20Sopenharmony_ci		mac->ops.led_on = e1000e_led_on_generic;
2638c2ecf20Sopenharmony_ci		mac->ops.blink_led = e1000e_blink_led_generic;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci		/* FWSM register */
2668c2ecf20Sopenharmony_ci		mac->has_fwsm = true;
2678c2ecf20Sopenharmony_ci		break;
2688c2ecf20Sopenharmony_ci	}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	/* Ensure that the inter-port SWSM.SMBI lock bit is clear before
2718c2ecf20Sopenharmony_ci	 * first NVM or PHY access. This should be done for single-port
2728c2ecf20Sopenharmony_ci	 * devices, and for one port only on dual-port devices so that
2738c2ecf20Sopenharmony_ci	 * for those devices we can still use the SMBI lock to synchronize
2748c2ecf20Sopenharmony_ci	 * inter-port accesses to the PHY & NVM.
2758c2ecf20Sopenharmony_ci	 */
2768c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
2778c2ecf20Sopenharmony_ci	case e1000_82571:
2788c2ecf20Sopenharmony_ci	case e1000_82572:
2798c2ecf20Sopenharmony_ci		swsm2 = er32(SWSM2);
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci		if (!(swsm2 & E1000_SWSM2_LOCK)) {
2828c2ecf20Sopenharmony_ci			/* Only do this for the first interface on this card */
2838c2ecf20Sopenharmony_ci			ew32(SWSM2, swsm2 | E1000_SWSM2_LOCK);
2848c2ecf20Sopenharmony_ci			force_clear_smbi = true;
2858c2ecf20Sopenharmony_ci		} else {
2868c2ecf20Sopenharmony_ci			force_clear_smbi = false;
2878c2ecf20Sopenharmony_ci		}
2888c2ecf20Sopenharmony_ci		break;
2898c2ecf20Sopenharmony_ci	default:
2908c2ecf20Sopenharmony_ci		force_clear_smbi = true;
2918c2ecf20Sopenharmony_ci		break;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (force_clear_smbi) {
2958c2ecf20Sopenharmony_ci		/* Make sure SWSM.SMBI is clear */
2968c2ecf20Sopenharmony_ci		swsm = er32(SWSM);
2978c2ecf20Sopenharmony_ci		if (swsm & E1000_SWSM_SMBI) {
2988c2ecf20Sopenharmony_ci			/* This bit should not be set on a first interface, and
2998c2ecf20Sopenharmony_ci			 * indicates that the bootagent or EFI code has
3008c2ecf20Sopenharmony_ci			 * improperly left this bit enabled
3018c2ecf20Sopenharmony_ci			 */
3028c2ecf20Sopenharmony_ci			e_dbg("Please update your 82571 Bootagent\n");
3038c2ecf20Sopenharmony_ci		}
3048c2ecf20Sopenharmony_ci		ew32(SWSM, swsm & ~E1000_SWSM_SMBI);
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	/* Initialize device specific counter of SMBI acquisition timeouts. */
3088c2ecf20Sopenharmony_ci	hw->dev_spec.e82571.smb_counter = 0;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	return 0;
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_cistatic s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
3168c2ecf20Sopenharmony_ci	static int global_quad_port_a;	/* global port a indication */
3178c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
3188c2ecf20Sopenharmony_ci	int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1;
3198c2ecf20Sopenharmony_ci	s32 rc;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	rc = e1000_init_mac_params_82571(hw);
3228c2ecf20Sopenharmony_ci	if (rc)
3238c2ecf20Sopenharmony_ci		return rc;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	rc = e1000_init_nvm_params_82571(hw);
3268c2ecf20Sopenharmony_ci	if (rc)
3278c2ecf20Sopenharmony_ci		return rc;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	rc = e1000_init_phy_params_82571(hw);
3308c2ecf20Sopenharmony_ci	if (rc)
3318c2ecf20Sopenharmony_ci		return rc;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	/* tag quad port adapters first, it's used below */
3348c2ecf20Sopenharmony_ci	switch (pdev->device) {
3358c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82571EB_QUAD_COPPER:
3368c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82571EB_QUAD_FIBER:
3378c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82571EB_QUAD_COPPER_LP:
3388c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82571PT_QUAD_COPPER:
3398c2ecf20Sopenharmony_ci		adapter->flags |= FLAG_IS_QUAD_PORT;
3408c2ecf20Sopenharmony_ci		/* mark the first port */
3418c2ecf20Sopenharmony_ci		if (global_quad_port_a == 0)
3428c2ecf20Sopenharmony_ci			adapter->flags |= FLAG_IS_QUAD_PORT_A;
3438c2ecf20Sopenharmony_ci		/* Reset for multiple quad port adapters */
3448c2ecf20Sopenharmony_ci		global_quad_port_a++;
3458c2ecf20Sopenharmony_ci		if (global_quad_port_a == 4)
3468c2ecf20Sopenharmony_ci			global_quad_port_a = 0;
3478c2ecf20Sopenharmony_ci		break;
3488c2ecf20Sopenharmony_ci	default:
3498c2ecf20Sopenharmony_ci		break;
3508c2ecf20Sopenharmony_ci	}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	switch (adapter->hw.mac.type) {
3538c2ecf20Sopenharmony_ci	case e1000_82571:
3548c2ecf20Sopenharmony_ci		/* these dual ports don't have WoL on port B at all */
3558c2ecf20Sopenharmony_ci		if (((pdev->device == E1000_DEV_ID_82571EB_FIBER) ||
3568c2ecf20Sopenharmony_ci		     (pdev->device == E1000_DEV_ID_82571EB_SERDES) ||
3578c2ecf20Sopenharmony_ci		     (pdev->device == E1000_DEV_ID_82571EB_COPPER)) &&
3588c2ecf20Sopenharmony_ci		    (is_port_b))
3598c2ecf20Sopenharmony_ci			adapter->flags &= ~FLAG_HAS_WOL;
3608c2ecf20Sopenharmony_ci		/* quad ports only support WoL on port A */
3618c2ecf20Sopenharmony_ci		if (adapter->flags & FLAG_IS_QUAD_PORT &&
3628c2ecf20Sopenharmony_ci		    (!(adapter->flags & FLAG_IS_QUAD_PORT_A)))
3638c2ecf20Sopenharmony_ci			adapter->flags &= ~FLAG_HAS_WOL;
3648c2ecf20Sopenharmony_ci		/* Does not support WoL on any port */
3658c2ecf20Sopenharmony_ci		if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD)
3668c2ecf20Sopenharmony_ci			adapter->flags &= ~FLAG_HAS_WOL;
3678c2ecf20Sopenharmony_ci		break;
3688c2ecf20Sopenharmony_ci	case e1000_82573:
3698c2ecf20Sopenharmony_ci		if (pdev->device == E1000_DEV_ID_82573L) {
3708c2ecf20Sopenharmony_ci			adapter->flags |= FLAG_HAS_JUMBO_FRAMES;
3718c2ecf20Sopenharmony_ci			adapter->max_hw_frame_size = DEFAULT_JUMBO;
3728c2ecf20Sopenharmony_ci		}
3738c2ecf20Sopenharmony_ci		break;
3748c2ecf20Sopenharmony_ci	default:
3758c2ecf20Sopenharmony_ci		break;
3768c2ecf20Sopenharmony_ci	}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	return 0;
3798c2ecf20Sopenharmony_ci}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci/**
3828c2ecf20Sopenharmony_ci *  e1000_get_phy_id_82571 - Retrieve the PHY ID and revision
3838c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
3848c2ecf20Sopenharmony_ci *
3858c2ecf20Sopenharmony_ci *  Reads the PHY registers and stores the PHY ID and possibly the PHY
3868c2ecf20Sopenharmony_ci *  revision in the hardware structure.
3878c2ecf20Sopenharmony_ci **/
3888c2ecf20Sopenharmony_cistatic s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	struct e1000_phy_info *phy = &hw->phy;
3918c2ecf20Sopenharmony_ci	s32 ret_val;
3928c2ecf20Sopenharmony_ci	u16 phy_id = 0;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
3958c2ecf20Sopenharmony_ci	case e1000_82571:
3968c2ecf20Sopenharmony_ci	case e1000_82572:
3978c2ecf20Sopenharmony_ci		/* The 82571 firmware may still be configuring the PHY.
3988c2ecf20Sopenharmony_ci		 * In this case, we cannot access the PHY until the
3998c2ecf20Sopenharmony_ci		 * configuration is done.  So we explicitly set the
4008c2ecf20Sopenharmony_ci		 * PHY ID.
4018c2ecf20Sopenharmony_ci		 */
4028c2ecf20Sopenharmony_ci		phy->id = IGP01E1000_I_PHY_ID;
4038c2ecf20Sopenharmony_ci		break;
4048c2ecf20Sopenharmony_ci	case e1000_82573:
4058c2ecf20Sopenharmony_ci		return e1000e_get_phy_id(hw);
4068c2ecf20Sopenharmony_ci	case e1000_82574:
4078c2ecf20Sopenharmony_ci	case e1000_82583:
4088c2ecf20Sopenharmony_ci		ret_val = e1e_rphy(hw, MII_PHYSID1, &phy_id);
4098c2ecf20Sopenharmony_ci		if (ret_val)
4108c2ecf20Sopenharmony_ci			return ret_val;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci		phy->id = (u32)(phy_id << 16);
4138c2ecf20Sopenharmony_ci		usleep_range(20, 40);
4148c2ecf20Sopenharmony_ci		ret_val = e1e_rphy(hw, MII_PHYSID2, &phy_id);
4158c2ecf20Sopenharmony_ci		if (ret_val)
4168c2ecf20Sopenharmony_ci			return ret_val;
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci		phy->id |= (u32)(phy_id);
4198c2ecf20Sopenharmony_ci		phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
4208c2ecf20Sopenharmony_ci		break;
4218c2ecf20Sopenharmony_ci	default:
4228c2ecf20Sopenharmony_ci		return -E1000_ERR_PHY;
4238c2ecf20Sopenharmony_ci	}
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	return 0;
4268c2ecf20Sopenharmony_ci}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci/**
4298c2ecf20Sopenharmony_ci *  e1000_get_hw_semaphore_82571 - Acquire hardware semaphore
4308c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
4318c2ecf20Sopenharmony_ci *
4328c2ecf20Sopenharmony_ci *  Acquire the HW semaphore to access the PHY or NVM
4338c2ecf20Sopenharmony_ci **/
4348c2ecf20Sopenharmony_cistatic s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
4358c2ecf20Sopenharmony_ci{
4368c2ecf20Sopenharmony_ci	u32 swsm;
4378c2ecf20Sopenharmony_ci	s32 sw_timeout = hw->nvm.word_size + 1;
4388c2ecf20Sopenharmony_ci	s32 fw_timeout = hw->nvm.word_size + 1;
4398c2ecf20Sopenharmony_ci	s32 i = 0;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	/* If we have timedout 3 times on trying to acquire
4428c2ecf20Sopenharmony_ci	 * the inter-port SMBI semaphore, there is old code
4438c2ecf20Sopenharmony_ci	 * operating on the other port, and it is not
4448c2ecf20Sopenharmony_ci	 * releasing SMBI. Modify the number of times that
4458c2ecf20Sopenharmony_ci	 * we try for the semaphore to interwork with this
4468c2ecf20Sopenharmony_ci	 * older code.
4478c2ecf20Sopenharmony_ci	 */
4488c2ecf20Sopenharmony_ci	if (hw->dev_spec.e82571.smb_counter > 2)
4498c2ecf20Sopenharmony_ci		sw_timeout = 1;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	/* Get the SW semaphore */
4528c2ecf20Sopenharmony_ci	while (i < sw_timeout) {
4538c2ecf20Sopenharmony_ci		swsm = er32(SWSM);
4548c2ecf20Sopenharmony_ci		if (!(swsm & E1000_SWSM_SMBI))
4558c2ecf20Sopenharmony_ci			break;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci		usleep_range(50, 100);
4588c2ecf20Sopenharmony_ci		i++;
4598c2ecf20Sopenharmony_ci	}
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	if (i == sw_timeout) {
4628c2ecf20Sopenharmony_ci		e_dbg("Driver can't access device - SMBI bit is set.\n");
4638c2ecf20Sopenharmony_ci		hw->dev_spec.e82571.smb_counter++;
4648c2ecf20Sopenharmony_ci	}
4658c2ecf20Sopenharmony_ci	/* Get the FW semaphore. */
4668c2ecf20Sopenharmony_ci	for (i = 0; i < fw_timeout; i++) {
4678c2ecf20Sopenharmony_ci		swsm = er32(SWSM);
4688c2ecf20Sopenharmony_ci		ew32(SWSM, swsm | E1000_SWSM_SWESMBI);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci		/* Semaphore acquired if bit latched */
4718c2ecf20Sopenharmony_ci		if (er32(SWSM) & E1000_SWSM_SWESMBI)
4728c2ecf20Sopenharmony_ci			break;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci		usleep_range(50, 100);
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	if (i == fw_timeout) {
4788c2ecf20Sopenharmony_ci		/* Release semaphores */
4798c2ecf20Sopenharmony_ci		e1000_put_hw_semaphore_82571(hw);
4808c2ecf20Sopenharmony_ci		e_dbg("Driver can't access the NVM\n");
4818c2ecf20Sopenharmony_ci		return -E1000_ERR_NVM;
4828c2ecf20Sopenharmony_ci	}
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	return 0;
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci/**
4888c2ecf20Sopenharmony_ci *  e1000_put_hw_semaphore_82571 - Release hardware semaphore
4898c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
4908c2ecf20Sopenharmony_ci *
4918c2ecf20Sopenharmony_ci *  Release hardware semaphore used to access the PHY or NVM
4928c2ecf20Sopenharmony_ci **/
4938c2ecf20Sopenharmony_cistatic void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
4948c2ecf20Sopenharmony_ci{
4958c2ecf20Sopenharmony_ci	u32 swsm;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	swsm = er32(SWSM);
4988c2ecf20Sopenharmony_ci	swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
4998c2ecf20Sopenharmony_ci	ew32(SWSM, swsm);
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci/**
5038c2ecf20Sopenharmony_ci *  e1000_get_hw_semaphore_82573 - Acquire hardware semaphore
5048c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
5058c2ecf20Sopenharmony_ci *
5068c2ecf20Sopenharmony_ci *  Acquire the HW semaphore during reset.
5078c2ecf20Sopenharmony_ci *
5088c2ecf20Sopenharmony_ci **/
5098c2ecf20Sopenharmony_cistatic s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
5108c2ecf20Sopenharmony_ci{
5118c2ecf20Sopenharmony_ci	u32 extcnf_ctrl;
5128c2ecf20Sopenharmony_ci	s32 i = 0;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	extcnf_ctrl = er32(EXTCNF_CTRL);
5158c2ecf20Sopenharmony_ci	do {
5168c2ecf20Sopenharmony_ci		extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
5178c2ecf20Sopenharmony_ci		ew32(EXTCNF_CTRL, extcnf_ctrl);
5188c2ecf20Sopenharmony_ci		extcnf_ctrl = er32(EXTCNF_CTRL);
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci		if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
5218c2ecf20Sopenharmony_ci			break;
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci		usleep_range(2000, 4000);
5248c2ecf20Sopenharmony_ci		i++;
5258c2ecf20Sopenharmony_ci	} while (i < MDIO_OWNERSHIP_TIMEOUT);
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	if (i == MDIO_OWNERSHIP_TIMEOUT) {
5288c2ecf20Sopenharmony_ci		/* Release semaphores */
5298c2ecf20Sopenharmony_ci		e1000_put_hw_semaphore_82573(hw);
5308c2ecf20Sopenharmony_ci		e_dbg("Driver can't access the PHY\n");
5318c2ecf20Sopenharmony_ci		return -E1000_ERR_PHY;
5328c2ecf20Sopenharmony_ci	}
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	return 0;
5358c2ecf20Sopenharmony_ci}
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci/**
5388c2ecf20Sopenharmony_ci *  e1000_put_hw_semaphore_82573 - Release hardware semaphore
5398c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
5408c2ecf20Sopenharmony_ci *
5418c2ecf20Sopenharmony_ci *  Release hardware semaphore used during reset.
5428c2ecf20Sopenharmony_ci *
5438c2ecf20Sopenharmony_ci **/
5448c2ecf20Sopenharmony_cistatic void e1000_put_hw_semaphore_82573(struct e1000_hw *hw)
5458c2ecf20Sopenharmony_ci{
5468c2ecf20Sopenharmony_ci	u32 extcnf_ctrl;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	extcnf_ctrl = er32(EXTCNF_CTRL);
5498c2ecf20Sopenharmony_ci	extcnf_ctrl &= ~E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
5508c2ecf20Sopenharmony_ci	ew32(EXTCNF_CTRL, extcnf_ctrl);
5518c2ecf20Sopenharmony_ci}
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(swflag_mutex);
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci/**
5568c2ecf20Sopenharmony_ci *  e1000_get_hw_semaphore_82574 - Acquire hardware semaphore
5578c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
5588c2ecf20Sopenharmony_ci *
5598c2ecf20Sopenharmony_ci *  Acquire the HW semaphore to access the PHY or NVM.
5608c2ecf20Sopenharmony_ci *
5618c2ecf20Sopenharmony_ci **/
5628c2ecf20Sopenharmony_cistatic s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	s32 ret_val;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	mutex_lock(&swflag_mutex);
5678c2ecf20Sopenharmony_ci	ret_val = e1000_get_hw_semaphore_82573(hw);
5688c2ecf20Sopenharmony_ci	if (ret_val)
5698c2ecf20Sopenharmony_ci		mutex_unlock(&swflag_mutex);
5708c2ecf20Sopenharmony_ci	return ret_val;
5718c2ecf20Sopenharmony_ci}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci/**
5748c2ecf20Sopenharmony_ci *  e1000_put_hw_semaphore_82574 - Release hardware semaphore
5758c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
5768c2ecf20Sopenharmony_ci *
5778c2ecf20Sopenharmony_ci *  Release hardware semaphore used to access the PHY or NVM
5788c2ecf20Sopenharmony_ci *
5798c2ecf20Sopenharmony_ci **/
5808c2ecf20Sopenharmony_cistatic void e1000_put_hw_semaphore_82574(struct e1000_hw *hw)
5818c2ecf20Sopenharmony_ci{
5828c2ecf20Sopenharmony_ci	e1000_put_hw_semaphore_82573(hw);
5838c2ecf20Sopenharmony_ci	mutex_unlock(&swflag_mutex);
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci/**
5878c2ecf20Sopenharmony_ci *  e1000_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state
5888c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
5898c2ecf20Sopenharmony_ci *  @active: true to enable LPLU, false to disable
5908c2ecf20Sopenharmony_ci *
5918c2ecf20Sopenharmony_ci *  Sets the LPLU D0 state according to the active flag.
5928c2ecf20Sopenharmony_ci *  LPLU will not be activated unless the
5938c2ecf20Sopenharmony_ci *  device autonegotiation advertisement meets standards of
5948c2ecf20Sopenharmony_ci *  either 10 or 10/100 or 10/100/1000 at all duplexes.
5958c2ecf20Sopenharmony_ci *  This is a function pointer entry point only called by
5968c2ecf20Sopenharmony_ci *  PHY setup routines.
5978c2ecf20Sopenharmony_ci **/
5988c2ecf20Sopenharmony_cistatic s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active)
5998c2ecf20Sopenharmony_ci{
6008c2ecf20Sopenharmony_ci	u32 data = er32(POEMB);
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	if (active)
6038c2ecf20Sopenharmony_ci		data |= E1000_PHY_CTRL_D0A_LPLU;
6048c2ecf20Sopenharmony_ci	else
6058c2ecf20Sopenharmony_ci		data &= ~E1000_PHY_CTRL_D0A_LPLU;
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	ew32(POEMB, data);
6088c2ecf20Sopenharmony_ci	return 0;
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci/**
6128c2ecf20Sopenharmony_ci *  e1000_set_d3_lplu_state_82574 - Sets low power link up state for D3
6138c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
6148c2ecf20Sopenharmony_ci *  @active: boolean used to enable/disable lplu
6158c2ecf20Sopenharmony_ci *
6168c2ecf20Sopenharmony_ci *  The low power link up (lplu) state is set to the power management level D3
6178c2ecf20Sopenharmony_ci *  when active is true, else clear lplu for D3. LPLU
6188c2ecf20Sopenharmony_ci *  is used during Dx states where the power conservation is most important.
6198c2ecf20Sopenharmony_ci *  During driver activity, SmartSpeed should be enabled so performance is
6208c2ecf20Sopenharmony_ci *  maintained.
6218c2ecf20Sopenharmony_ci **/
6228c2ecf20Sopenharmony_cistatic s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active)
6238c2ecf20Sopenharmony_ci{
6248c2ecf20Sopenharmony_ci	u32 data = er32(POEMB);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	if (!active) {
6278c2ecf20Sopenharmony_ci		data &= ~E1000_PHY_CTRL_NOND0A_LPLU;
6288c2ecf20Sopenharmony_ci	} else if ((hw->phy.autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
6298c2ecf20Sopenharmony_ci		   (hw->phy.autoneg_advertised == E1000_ALL_NOT_GIG) ||
6308c2ecf20Sopenharmony_ci		   (hw->phy.autoneg_advertised == E1000_ALL_10_SPEED)) {
6318c2ecf20Sopenharmony_ci		data |= E1000_PHY_CTRL_NOND0A_LPLU;
6328c2ecf20Sopenharmony_ci	}
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	ew32(POEMB, data);
6358c2ecf20Sopenharmony_ci	return 0;
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci/**
6398c2ecf20Sopenharmony_ci *  e1000_acquire_nvm_82571 - Request for access to the EEPROM
6408c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
6418c2ecf20Sopenharmony_ci *
6428c2ecf20Sopenharmony_ci *  To gain access to the EEPROM, first we must obtain a hardware semaphore.
6438c2ecf20Sopenharmony_ci *  Then for non-82573 hardware, set the EEPROM access request bit and wait
6448c2ecf20Sopenharmony_ci *  for EEPROM access grant bit.  If the access grant bit is not set, release
6458c2ecf20Sopenharmony_ci *  hardware semaphore.
6468c2ecf20Sopenharmony_ci **/
6478c2ecf20Sopenharmony_cistatic s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	s32 ret_val;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	ret_val = e1000_get_hw_semaphore_82571(hw);
6528c2ecf20Sopenharmony_ci	if (ret_val)
6538c2ecf20Sopenharmony_ci		return ret_val;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
6568c2ecf20Sopenharmony_ci	case e1000_82573:
6578c2ecf20Sopenharmony_ci		break;
6588c2ecf20Sopenharmony_ci	default:
6598c2ecf20Sopenharmony_ci		ret_val = e1000e_acquire_nvm(hw);
6608c2ecf20Sopenharmony_ci		break;
6618c2ecf20Sopenharmony_ci	}
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	if (ret_val)
6648c2ecf20Sopenharmony_ci		e1000_put_hw_semaphore_82571(hw);
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	return ret_val;
6678c2ecf20Sopenharmony_ci}
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci/**
6708c2ecf20Sopenharmony_ci *  e1000_release_nvm_82571 - Release exclusive access to EEPROM
6718c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
6728c2ecf20Sopenharmony_ci *
6738c2ecf20Sopenharmony_ci *  Stop any current commands to the EEPROM and clear the EEPROM request bit.
6748c2ecf20Sopenharmony_ci **/
6758c2ecf20Sopenharmony_cistatic void e1000_release_nvm_82571(struct e1000_hw *hw)
6768c2ecf20Sopenharmony_ci{
6778c2ecf20Sopenharmony_ci	e1000e_release_nvm(hw);
6788c2ecf20Sopenharmony_ci	e1000_put_hw_semaphore_82571(hw);
6798c2ecf20Sopenharmony_ci}
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci/**
6828c2ecf20Sopenharmony_ci *  e1000_write_nvm_82571 - Write to EEPROM using appropriate interface
6838c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
6848c2ecf20Sopenharmony_ci *  @offset: offset within the EEPROM to be written to
6858c2ecf20Sopenharmony_ci *  @words: number of words to write
6868c2ecf20Sopenharmony_ci *  @data: 16 bit word(s) to be written to the EEPROM
6878c2ecf20Sopenharmony_ci *
6888c2ecf20Sopenharmony_ci *  For non-82573 silicon, write data to EEPROM at offset using SPI interface.
6898c2ecf20Sopenharmony_ci *
6908c2ecf20Sopenharmony_ci *  If e1000e_update_nvm_checksum is not called after this function, the
6918c2ecf20Sopenharmony_ci *  EEPROM will most likely contain an invalid checksum.
6928c2ecf20Sopenharmony_ci **/
6938c2ecf20Sopenharmony_cistatic s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words,
6948c2ecf20Sopenharmony_ci				 u16 *data)
6958c2ecf20Sopenharmony_ci{
6968c2ecf20Sopenharmony_ci	s32 ret_val;
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
6998c2ecf20Sopenharmony_ci	case e1000_82573:
7008c2ecf20Sopenharmony_ci	case e1000_82574:
7018c2ecf20Sopenharmony_ci	case e1000_82583:
7028c2ecf20Sopenharmony_ci		ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data);
7038c2ecf20Sopenharmony_ci		break;
7048c2ecf20Sopenharmony_ci	case e1000_82571:
7058c2ecf20Sopenharmony_ci	case e1000_82572:
7068c2ecf20Sopenharmony_ci		ret_val = e1000e_write_nvm_spi(hw, offset, words, data);
7078c2ecf20Sopenharmony_ci		break;
7088c2ecf20Sopenharmony_ci	default:
7098c2ecf20Sopenharmony_ci		ret_val = -E1000_ERR_NVM;
7108c2ecf20Sopenharmony_ci		break;
7118c2ecf20Sopenharmony_ci	}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	return ret_val;
7148c2ecf20Sopenharmony_ci}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci/**
7178c2ecf20Sopenharmony_ci *  e1000_update_nvm_checksum_82571 - Update EEPROM checksum
7188c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
7198c2ecf20Sopenharmony_ci *
7208c2ecf20Sopenharmony_ci *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
7218c2ecf20Sopenharmony_ci *  up to the checksum.  Then calculates the EEPROM checksum and writes the
7228c2ecf20Sopenharmony_ci *  value to the EEPROM.
7238c2ecf20Sopenharmony_ci **/
7248c2ecf20Sopenharmony_cistatic s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
7258c2ecf20Sopenharmony_ci{
7268c2ecf20Sopenharmony_ci	u32 eecd;
7278c2ecf20Sopenharmony_ci	s32 ret_val;
7288c2ecf20Sopenharmony_ci	u16 i;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	ret_val = e1000e_update_nvm_checksum_generic(hw);
7318c2ecf20Sopenharmony_ci	if (ret_val)
7328c2ecf20Sopenharmony_ci		return ret_val;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	/* If our nvm is an EEPROM, then we're done
7358c2ecf20Sopenharmony_ci	 * otherwise, commit the checksum to the flash NVM.
7368c2ecf20Sopenharmony_ci	 */
7378c2ecf20Sopenharmony_ci	if (hw->nvm.type != e1000_nvm_flash_hw)
7388c2ecf20Sopenharmony_ci		return 0;
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	/* Check for pending operations. */
7418c2ecf20Sopenharmony_ci	for (i = 0; i < E1000_FLASH_UPDATES; i++) {
7428c2ecf20Sopenharmony_ci		usleep_range(1000, 2000);
7438c2ecf20Sopenharmony_ci		if (!(er32(EECD) & E1000_EECD_FLUPD))
7448c2ecf20Sopenharmony_ci			break;
7458c2ecf20Sopenharmony_ci	}
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	if (i == E1000_FLASH_UPDATES)
7488c2ecf20Sopenharmony_ci		return -E1000_ERR_NVM;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	/* Reset the firmware if using STM opcode. */
7518c2ecf20Sopenharmony_ci	if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) {
7528c2ecf20Sopenharmony_ci		/* The enabling of and the actual reset must be done
7538c2ecf20Sopenharmony_ci		 * in two write cycles.
7548c2ecf20Sopenharmony_ci		 */
7558c2ecf20Sopenharmony_ci		ew32(HICR, E1000_HICR_FW_RESET_ENABLE);
7568c2ecf20Sopenharmony_ci		e1e_flush();
7578c2ecf20Sopenharmony_ci		ew32(HICR, E1000_HICR_FW_RESET);
7588c2ecf20Sopenharmony_ci	}
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	/* Commit the write to flash */
7618c2ecf20Sopenharmony_ci	eecd = er32(EECD) | E1000_EECD_FLUPD;
7628c2ecf20Sopenharmony_ci	ew32(EECD, eecd);
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	for (i = 0; i < E1000_FLASH_UPDATES; i++) {
7658c2ecf20Sopenharmony_ci		usleep_range(1000, 2000);
7668c2ecf20Sopenharmony_ci		if (!(er32(EECD) & E1000_EECD_FLUPD))
7678c2ecf20Sopenharmony_ci			break;
7688c2ecf20Sopenharmony_ci	}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	if (i == E1000_FLASH_UPDATES)
7718c2ecf20Sopenharmony_ci		return -E1000_ERR_NVM;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	return 0;
7748c2ecf20Sopenharmony_ci}
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci/**
7778c2ecf20Sopenharmony_ci *  e1000_validate_nvm_checksum_82571 - Validate EEPROM checksum
7788c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
7798c2ecf20Sopenharmony_ci *
7808c2ecf20Sopenharmony_ci *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
7818c2ecf20Sopenharmony_ci *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
7828c2ecf20Sopenharmony_ci **/
7838c2ecf20Sopenharmony_cistatic s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw)
7848c2ecf20Sopenharmony_ci{
7858c2ecf20Sopenharmony_ci	if (hw->nvm.type == e1000_nvm_flash_hw)
7868c2ecf20Sopenharmony_ci		e1000_fix_nvm_checksum_82571(hw);
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	return e1000e_validate_nvm_checksum_generic(hw);
7898c2ecf20Sopenharmony_ci}
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci/**
7928c2ecf20Sopenharmony_ci *  e1000_write_nvm_eewr_82571 - Write to EEPROM for 82573 silicon
7938c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
7948c2ecf20Sopenharmony_ci *  @offset: offset within the EEPROM to be written to
7958c2ecf20Sopenharmony_ci *  @words: number of words to write
7968c2ecf20Sopenharmony_ci *  @data: 16 bit word(s) to be written to the EEPROM
7978c2ecf20Sopenharmony_ci *
7988c2ecf20Sopenharmony_ci *  After checking for invalid values, poll the EEPROM to ensure the previous
7998c2ecf20Sopenharmony_ci *  command has completed before trying to write the next word.  After write
8008c2ecf20Sopenharmony_ci *  poll for completion.
8018c2ecf20Sopenharmony_ci *
8028c2ecf20Sopenharmony_ci *  If e1000e_update_nvm_checksum is not called after this function, the
8038c2ecf20Sopenharmony_ci *  EEPROM will most likely contain an invalid checksum.
8048c2ecf20Sopenharmony_ci **/
8058c2ecf20Sopenharmony_cistatic s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
8068c2ecf20Sopenharmony_ci				      u16 words, u16 *data)
8078c2ecf20Sopenharmony_ci{
8088c2ecf20Sopenharmony_ci	struct e1000_nvm_info *nvm = &hw->nvm;
8098c2ecf20Sopenharmony_ci	u32 i, eewr = 0;
8108c2ecf20Sopenharmony_ci	s32 ret_val = 0;
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	/* A check for invalid values:  offset too large, too many words,
8138c2ecf20Sopenharmony_ci	 * and not enough words.
8148c2ecf20Sopenharmony_ci	 */
8158c2ecf20Sopenharmony_ci	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
8168c2ecf20Sopenharmony_ci	    (words == 0)) {
8178c2ecf20Sopenharmony_ci		e_dbg("nvm parameter(s) out of bounds\n");
8188c2ecf20Sopenharmony_ci		return -E1000_ERR_NVM;
8198c2ecf20Sopenharmony_ci	}
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	for (i = 0; i < words; i++) {
8228c2ecf20Sopenharmony_ci		eewr = ((data[i] << E1000_NVM_RW_REG_DATA) |
8238c2ecf20Sopenharmony_ci			((offset + i) << E1000_NVM_RW_ADDR_SHIFT) |
8248c2ecf20Sopenharmony_ci			E1000_NVM_RW_REG_START);
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci		ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE);
8278c2ecf20Sopenharmony_ci		if (ret_val)
8288c2ecf20Sopenharmony_ci			break;
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci		ew32(EEWR, eewr);
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci		ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE);
8338c2ecf20Sopenharmony_ci		if (ret_val)
8348c2ecf20Sopenharmony_ci			break;
8358c2ecf20Sopenharmony_ci	}
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	return ret_val;
8388c2ecf20Sopenharmony_ci}
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci/**
8418c2ecf20Sopenharmony_ci *  e1000_get_cfg_done_82571 - Poll for configuration done
8428c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
8438c2ecf20Sopenharmony_ci *
8448c2ecf20Sopenharmony_ci *  Reads the management control register for the config done bit to be set.
8458c2ecf20Sopenharmony_ci **/
8468c2ecf20Sopenharmony_cistatic s32 e1000_get_cfg_done_82571(struct e1000_hw *hw)
8478c2ecf20Sopenharmony_ci{
8488c2ecf20Sopenharmony_ci	s32 timeout = PHY_CFG_TIMEOUT;
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci	while (timeout) {
8518c2ecf20Sopenharmony_ci		if (er32(EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0)
8528c2ecf20Sopenharmony_ci			break;
8538c2ecf20Sopenharmony_ci		usleep_range(1000, 2000);
8548c2ecf20Sopenharmony_ci		timeout--;
8558c2ecf20Sopenharmony_ci	}
8568c2ecf20Sopenharmony_ci	if (!timeout) {
8578c2ecf20Sopenharmony_ci		e_dbg("MNG configuration cycle has not completed.\n");
8588c2ecf20Sopenharmony_ci		return -E1000_ERR_RESET;
8598c2ecf20Sopenharmony_ci	}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	return 0;
8628c2ecf20Sopenharmony_ci}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci/**
8658c2ecf20Sopenharmony_ci *  e1000_set_d0_lplu_state_82571 - Set Low Power Linkup D0 state
8668c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
8678c2ecf20Sopenharmony_ci *  @active: true to enable LPLU, false to disable
8688c2ecf20Sopenharmony_ci *
8698c2ecf20Sopenharmony_ci *  Sets the LPLU D0 state according to the active flag.  When activating LPLU
8708c2ecf20Sopenharmony_ci *  this function also disables smart speed and vice versa.  LPLU will not be
8718c2ecf20Sopenharmony_ci *  activated unless the device autonegotiation advertisement meets standards
8728c2ecf20Sopenharmony_ci *  of either 10 or 10/100 or 10/100/1000 at all duplexes.  This is a function
8738c2ecf20Sopenharmony_ci *  pointer entry point only called by PHY setup routines.
8748c2ecf20Sopenharmony_ci **/
8758c2ecf20Sopenharmony_cistatic s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
8768c2ecf20Sopenharmony_ci{
8778c2ecf20Sopenharmony_ci	struct e1000_phy_info *phy = &hw->phy;
8788c2ecf20Sopenharmony_ci	s32 ret_val;
8798c2ecf20Sopenharmony_ci	u16 data;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data);
8828c2ecf20Sopenharmony_ci	if (ret_val)
8838c2ecf20Sopenharmony_ci		return ret_val;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	if (active) {
8868c2ecf20Sopenharmony_ci		data |= IGP02E1000_PM_D0_LPLU;
8878c2ecf20Sopenharmony_ci		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
8888c2ecf20Sopenharmony_ci		if (ret_val)
8898c2ecf20Sopenharmony_ci			return ret_val;
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci		/* When LPLU is enabled, we should disable SmartSpeed */
8928c2ecf20Sopenharmony_ci		ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data);
8938c2ecf20Sopenharmony_ci		if (ret_val)
8948c2ecf20Sopenharmony_ci			return ret_val;
8958c2ecf20Sopenharmony_ci		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
8968c2ecf20Sopenharmony_ci		ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);
8978c2ecf20Sopenharmony_ci		if (ret_val)
8988c2ecf20Sopenharmony_ci			return ret_val;
8998c2ecf20Sopenharmony_ci	} else {
9008c2ecf20Sopenharmony_ci		data &= ~IGP02E1000_PM_D0_LPLU;
9018c2ecf20Sopenharmony_ci		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
9028c2ecf20Sopenharmony_ci		if (ret_val)
9038c2ecf20Sopenharmony_ci			return ret_val;
9048c2ecf20Sopenharmony_ci		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
9058c2ecf20Sopenharmony_ci		 * during Dx states where the power conservation is most
9068c2ecf20Sopenharmony_ci		 * important.  During driver activity we should enable
9078c2ecf20Sopenharmony_ci		 * SmartSpeed, so performance is maintained.
9088c2ecf20Sopenharmony_ci		 */
9098c2ecf20Sopenharmony_ci		if (phy->smart_speed == e1000_smart_speed_on) {
9108c2ecf20Sopenharmony_ci			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
9118c2ecf20Sopenharmony_ci					   &data);
9128c2ecf20Sopenharmony_ci			if (ret_val)
9138c2ecf20Sopenharmony_ci				return ret_val;
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci			data |= IGP01E1000_PSCFR_SMART_SPEED;
9168c2ecf20Sopenharmony_ci			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
9178c2ecf20Sopenharmony_ci					   data);
9188c2ecf20Sopenharmony_ci			if (ret_val)
9198c2ecf20Sopenharmony_ci				return ret_val;
9208c2ecf20Sopenharmony_ci		} else if (phy->smart_speed == e1000_smart_speed_off) {
9218c2ecf20Sopenharmony_ci			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
9228c2ecf20Sopenharmony_ci					   &data);
9238c2ecf20Sopenharmony_ci			if (ret_val)
9248c2ecf20Sopenharmony_ci				return ret_val;
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
9278c2ecf20Sopenharmony_ci			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
9288c2ecf20Sopenharmony_ci					   data);
9298c2ecf20Sopenharmony_ci			if (ret_val)
9308c2ecf20Sopenharmony_ci				return ret_val;
9318c2ecf20Sopenharmony_ci		}
9328c2ecf20Sopenharmony_ci	}
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	return 0;
9358c2ecf20Sopenharmony_ci}
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci/**
9388c2ecf20Sopenharmony_ci *  e1000_reset_hw_82571 - Reset hardware
9398c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
9408c2ecf20Sopenharmony_ci *
9418c2ecf20Sopenharmony_ci *  This resets the hardware into a known state.
9428c2ecf20Sopenharmony_ci **/
9438c2ecf20Sopenharmony_cistatic s32 e1000_reset_hw_82571(struct e1000_hw *hw)
9448c2ecf20Sopenharmony_ci{
9458c2ecf20Sopenharmony_ci	u32 ctrl, ctrl_ext, eecd, tctl;
9468c2ecf20Sopenharmony_ci	s32 ret_val;
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	/* Prevent the PCI-E bus from sticking if there is no TLP connection
9498c2ecf20Sopenharmony_ci	 * on the last TLP read/write transaction when MAC is reset.
9508c2ecf20Sopenharmony_ci	 */
9518c2ecf20Sopenharmony_ci	ret_val = e1000e_disable_pcie_master(hw);
9528c2ecf20Sopenharmony_ci	if (ret_val)
9538c2ecf20Sopenharmony_ci		e_dbg("PCI-E Master disable polling has failed.\n");
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	e_dbg("Masking off all interrupts\n");
9568c2ecf20Sopenharmony_ci	ew32(IMC, 0xffffffff);
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	ew32(RCTL, 0);
9598c2ecf20Sopenharmony_ci	tctl = er32(TCTL);
9608c2ecf20Sopenharmony_ci	tctl &= ~E1000_TCTL_EN;
9618c2ecf20Sopenharmony_ci	ew32(TCTL, tctl);
9628c2ecf20Sopenharmony_ci	e1e_flush();
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	usleep_range(10000, 11000);
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	/* Must acquire the MDIO ownership before MAC reset.
9678c2ecf20Sopenharmony_ci	 * Ownership defaults to firmware after a reset.
9688c2ecf20Sopenharmony_ci	 */
9698c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
9708c2ecf20Sopenharmony_ci	case e1000_82573:
9718c2ecf20Sopenharmony_ci		ret_val = e1000_get_hw_semaphore_82573(hw);
9728c2ecf20Sopenharmony_ci		break;
9738c2ecf20Sopenharmony_ci	case e1000_82574:
9748c2ecf20Sopenharmony_ci	case e1000_82583:
9758c2ecf20Sopenharmony_ci		ret_val = e1000_get_hw_semaphore_82574(hw);
9768c2ecf20Sopenharmony_ci		break;
9778c2ecf20Sopenharmony_ci	default:
9788c2ecf20Sopenharmony_ci		break;
9798c2ecf20Sopenharmony_ci	}
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	e_dbg("Issuing a global reset to MAC\n");
9848c2ecf20Sopenharmony_ci	ew32(CTRL, ctrl | E1000_CTRL_RST);
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	/* Must release MDIO ownership and mutex after MAC reset. */
9878c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
9888c2ecf20Sopenharmony_ci	case e1000_82573:
9898c2ecf20Sopenharmony_ci		/* Release mutex only if the hw semaphore is acquired */
9908c2ecf20Sopenharmony_ci		if (!ret_val)
9918c2ecf20Sopenharmony_ci			e1000_put_hw_semaphore_82573(hw);
9928c2ecf20Sopenharmony_ci		break;
9938c2ecf20Sopenharmony_ci	case e1000_82574:
9948c2ecf20Sopenharmony_ci	case e1000_82583:
9958c2ecf20Sopenharmony_ci		/* Release mutex only if the hw semaphore is acquired */
9968c2ecf20Sopenharmony_ci		if (!ret_val)
9978c2ecf20Sopenharmony_ci			e1000_put_hw_semaphore_82574(hw);
9988c2ecf20Sopenharmony_ci		break;
9998c2ecf20Sopenharmony_ci	default:
10008c2ecf20Sopenharmony_ci		break;
10018c2ecf20Sopenharmony_ci	}
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	if (hw->nvm.type == e1000_nvm_flash_hw) {
10048c2ecf20Sopenharmony_ci		usleep_range(10, 20);
10058c2ecf20Sopenharmony_ci		ctrl_ext = er32(CTRL_EXT);
10068c2ecf20Sopenharmony_ci		ctrl_ext |= E1000_CTRL_EXT_EE_RST;
10078c2ecf20Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
10088c2ecf20Sopenharmony_ci		e1e_flush();
10098c2ecf20Sopenharmony_ci	}
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	ret_val = e1000e_get_auto_rd_done(hw);
10128c2ecf20Sopenharmony_ci	if (ret_val)
10138c2ecf20Sopenharmony_ci		/* We don't want to continue accessing MAC registers. */
10148c2ecf20Sopenharmony_ci		return ret_val;
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ci	/* Phy configuration from NVM just starts after EECD_AUTO_RD is set.
10178c2ecf20Sopenharmony_ci	 * Need to wait for Phy configuration completion before accessing
10188c2ecf20Sopenharmony_ci	 * NVM and Phy.
10198c2ecf20Sopenharmony_ci	 */
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
10228c2ecf20Sopenharmony_ci	case e1000_82571:
10238c2ecf20Sopenharmony_ci	case e1000_82572:
10248c2ecf20Sopenharmony_ci		/* REQ and GNT bits need to be cleared when using AUTO_RD
10258c2ecf20Sopenharmony_ci		 * to access the EEPROM.
10268c2ecf20Sopenharmony_ci		 */
10278c2ecf20Sopenharmony_ci		eecd = er32(EECD);
10288c2ecf20Sopenharmony_ci		eecd &= ~(E1000_EECD_REQ | E1000_EECD_GNT);
10298c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
10308c2ecf20Sopenharmony_ci		break;
10318c2ecf20Sopenharmony_ci	case e1000_82573:
10328c2ecf20Sopenharmony_ci	case e1000_82574:
10338c2ecf20Sopenharmony_ci	case e1000_82583:
10348c2ecf20Sopenharmony_ci		msleep(25);
10358c2ecf20Sopenharmony_ci		break;
10368c2ecf20Sopenharmony_ci	default:
10378c2ecf20Sopenharmony_ci		break;
10388c2ecf20Sopenharmony_ci	}
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ci	/* Clear any pending interrupt events. */
10418c2ecf20Sopenharmony_ci	ew32(IMC, 0xffffffff);
10428c2ecf20Sopenharmony_ci	er32(ICR);
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci	if (hw->mac.type == e1000_82571) {
10458c2ecf20Sopenharmony_ci		/* Install any alternate MAC address into RAR0 */
10468c2ecf20Sopenharmony_ci		ret_val = e1000_check_alt_mac_addr_generic(hw);
10478c2ecf20Sopenharmony_ci		if (ret_val)
10488c2ecf20Sopenharmony_ci			return ret_val;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci		e1000e_set_laa_state_82571(hw, true);
10518c2ecf20Sopenharmony_ci	}
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	/* Reinitialize the 82571 serdes link state machine */
10548c2ecf20Sopenharmony_ci	if (hw->phy.media_type == e1000_media_type_internal_serdes)
10558c2ecf20Sopenharmony_ci		hw->mac.serdes_link_state = e1000_serdes_link_down;
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci	return 0;
10588c2ecf20Sopenharmony_ci}
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci/**
10618c2ecf20Sopenharmony_ci *  e1000_init_hw_82571 - Initialize hardware
10628c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
10638c2ecf20Sopenharmony_ci *
10648c2ecf20Sopenharmony_ci *  This inits the hardware readying it for operation.
10658c2ecf20Sopenharmony_ci **/
10668c2ecf20Sopenharmony_cistatic s32 e1000_init_hw_82571(struct e1000_hw *hw)
10678c2ecf20Sopenharmony_ci{
10688c2ecf20Sopenharmony_ci	struct e1000_mac_info *mac = &hw->mac;
10698c2ecf20Sopenharmony_ci	u32 reg_data;
10708c2ecf20Sopenharmony_ci	s32 ret_val;
10718c2ecf20Sopenharmony_ci	u16 i, rar_count = mac->rar_entry_count;
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	e1000_initialize_hw_bits_82571(hw);
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	/* Initialize identification LED */
10768c2ecf20Sopenharmony_ci	ret_val = mac->ops.id_led_init(hw);
10778c2ecf20Sopenharmony_ci	/* An error is not fatal and we should not stop init due to this */
10788c2ecf20Sopenharmony_ci	if (ret_val)
10798c2ecf20Sopenharmony_ci		e_dbg("Error initializing identification LED\n");
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci	/* Disabling VLAN filtering */
10828c2ecf20Sopenharmony_ci	e_dbg("Initializing the IEEE VLAN\n");
10838c2ecf20Sopenharmony_ci	mac->ops.clear_vfta(hw);
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci	/* Setup the receive address.
10868c2ecf20Sopenharmony_ci	 * If, however, a locally administered address was assigned to the
10878c2ecf20Sopenharmony_ci	 * 82571, we must reserve a RAR for it to work around an issue where
10888c2ecf20Sopenharmony_ci	 * resetting one port will reload the MAC on the other port.
10898c2ecf20Sopenharmony_ci	 */
10908c2ecf20Sopenharmony_ci	if (e1000e_get_laa_state_82571(hw))
10918c2ecf20Sopenharmony_ci		rar_count--;
10928c2ecf20Sopenharmony_ci	e1000e_init_rx_addrs(hw, rar_count);
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci	/* Zero out the Multicast HASH table */
10958c2ecf20Sopenharmony_ci	e_dbg("Zeroing the MTA\n");
10968c2ecf20Sopenharmony_ci	for (i = 0; i < mac->mta_reg_count; i++)
10978c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	/* Setup link and flow control */
11008c2ecf20Sopenharmony_ci	ret_val = mac->ops.setup_link(hw);
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	/* Set the transmit descriptor write-back policy */
11038c2ecf20Sopenharmony_ci	reg_data = er32(TXDCTL(0));
11048c2ecf20Sopenharmony_ci	reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
11058c2ecf20Sopenharmony_ci		    E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
11068c2ecf20Sopenharmony_ci	ew32(TXDCTL(0), reg_data);
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci	/* ...for both queues. */
11098c2ecf20Sopenharmony_ci	switch (mac->type) {
11108c2ecf20Sopenharmony_ci	case e1000_82573:
11118c2ecf20Sopenharmony_ci		e1000e_enable_tx_pkt_filtering(hw);
11128c2ecf20Sopenharmony_ci		fallthrough;
11138c2ecf20Sopenharmony_ci	case e1000_82574:
11148c2ecf20Sopenharmony_ci	case e1000_82583:
11158c2ecf20Sopenharmony_ci		reg_data = er32(GCR);
11168c2ecf20Sopenharmony_ci		reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
11178c2ecf20Sopenharmony_ci		ew32(GCR, reg_data);
11188c2ecf20Sopenharmony_ci		break;
11198c2ecf20Sopenharmony_ci	default:
11208c2ecf20Sopenharmony_ci		reg_data = er32(TXDCTL(1));
11218c2ecf20Sopenharmony_ci		reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
11228c2ecf20Sopenharmony_ci			    E1000_TXDCTL_FULL_TX_DESC_WB |
11238c2ecf20Sopenharmony_ci			    E1000_TXDCTL_COUNT_DESC);
11248c2ecf20Sopenharmony_ci		ew32(TXDCTL(1), reg_data);
11258c2ecf20Sopenharmony_ci		break;
11268c2ecf20Sopenharmony_ci	}
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	/* Clear all of the statistics registers (clear on read).  It is
11298c2ecf20Sopenharmony_ci	 * important that we do this after we have tried to establish link
11308c2ecf20Sopenharmony_ci	 * because the symbol error count will increment wildly if there
11318c2ecf20Sopenharmony_ci	 * is no link.
11328c2ecf20Sopenharmony_ci	 */
11338c2ecf20Sopenharmony_ci	e1000_clear_hw_cntrs_82571(hw);
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	return ret_val;
11368c2ecf20Sopenharmony_ci}
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci/**
11398c2ecf20Sopenharmony_ci *  e1000_initialize_hw_bits_82571 - Initialize hardware-dependent bits
11408c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
11418c2ecf20Sopenharmony_ci *
11428c2ecf20Sopenharmony_ci *  Initializes required hardware-dependent bits needed for normal operation.
11438c2ecf20Sopenharmony_ci **/
11448c2ecf20Sopenharmony_cistatic void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
11458c2ecf20Sopenharmony_ci{
11468c2ecf20Sopenharmony_ci	u32 reg;
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	/* Transmit Descriptor Control 0 */
11498c2ecf20Sopenharmony_ci	reg = er32(TXDCTL(0));
11508c2ecf20Sopenharmony_ci	reg |= BIT(22);
11518c2ecf20Sopenharmony_ci	ew32(TXDCTL(0), reg);
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	/* Transmit Descriptor Control 1 */
11548c2ecf20Sopenharmony_ci	reg = er32(TXDCTL(1));
11558c2ecf20Sopenharmony_ci	reg |= BIT(22);
11568c2ecf20Sopenharmony_ci	ew32(TXDCTL(1), reg);
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	/* Transmit Arbitration Control 0 */
11598c2ecf20Sopenharmony_ci	reg = er32(TARC(0));
11608c2ecf20Sopenharmony_ci	reg &= ~(0xF << 27);	/* 30:27 */
11618c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
11628c2ecf20Sopenharmony_ci	case e1000_82571:
11638c2ecf20Sopenharmony_ci	case e1000_82572:
11648c2ecf20Sopenharmony_ci		reg |= BIT(23) | BIT(24) | BIT(25) | BIT(26);
11658c2ecf20Sopenharmony_ci		break;
11668c2ecf20Sopenharmony_ci	case e1000_82574:
11678c2ecf20Sopenharmony_ci	case e1000_82583:
11688c2ecf20Sopenharmony_ci		reg |= BIT(26);
11698c2ecf20Sopenharmony_ci		break;
11708c2ecf20Sopenharmony_ci	default:
11718c2ecf20Sopenharmony_ci		break;
11728c2ecf20Sopenharmony_ci	}
11738c2ecf20Sopenharmony_ci	ew32(TARC(0), reg);
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	/* Transmit Arbitration Control 1 */
11768c2ecf20Sopenharmony_ci	reg = er32(TARC(1));
11778c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
11788c2ecf20Sopenharmony_ci	case e1000_82571:
11798c2ecf20Sopenharmony_ci	case e1000_82572:
11808c2ecf20Sopenharmony_ci		reg &= ~(BIT(29) | BIT(30));
11818c2ecf20Sopenharmony_ci		reg |= BIT(22) | BIT(24) | BIT(25) | BIT(26);
11828c2ecf20Sopenharmony_ci		if (er32(TCTL) & E1000_TCTL_MULR)
11838c2ecf20Sopenharmony_ci			reg &= ~BIT(28);
11848c2ecf20Sopenharmony_ci		else
11858c2ecf20Sopenharmony_ci			reg |= BIT(28);
11868c2ecf20Sopenharmony_ci		ew32(TARC(1), reg);
11878c2ecf20Sopenharmony_ci		break;
11888c2ecf20Sopenharmony_ci	default:
11898c2ecf20Sopenharmony_ci		break;
11908c2ecf20Sopenharmony_ci	}
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	/* Device Control */
11938c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
11948c2ecf20Sopenharmony_ci	case e1000_82573:
11958c2ecf20Sopenharmony_ci	case e1000_82574:
11968c2ecf20Sopenharmony_ci	case e1000_82583:
11978c2ecf20Sopenharmony_ci		reg = er32(CTRL);
11988c2ecf20Sopenharmony_ci		reg &= ~BIT(29);
11998c2ecf20Sopenharmony_ci		ew32(CTRL, reg);
12008c2ecf20Sopenharmony_ci		break;
12018c2ecf20Sopenharmony_ci	default:
12028c2ecf20Sopenharmony_ci		break;
12038c2ecf20Sopenharmony_ci	}
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	/* Extended Device Control */
12068c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
12078c2ecf20Sopenharmony_ci	case e1000_82573:
12088c2ecf20Sopenharmony_ci	case e1000_82574:
12098c2ecf20Sopenharmony_ci	case e1000_82583:
12108c2ecf20Sopenharmony_ci		reg = er32(CTRL_EXT);
12118c2ecf20Sopenharmony_ci		reg &= ~BIT(23);
12128c2ecf20Sopenharmony_ci		reg |= BIT(22);
12138c2ecf20Sopenharmony_ci		ew32(CTRL_EXT, reg);
12148c2ecf20Sopenharmony_ci		break;
12158c2ecf20Sopenharmony_ci	default:
12168c2ecf20Sopenharmony_ci		break;
12178c2ecf20Sopenharmony_ci	}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	if (hw->mac.type == e1000_82571) {
12208c2ecf20Sopenharmony_ci		reg = er32(PBA_ECC);
12218c2ecf20Sopenharmony_ci		reg |= E1000_PBA_ECC_CORR_EN;
12228c2ecf20Sopenharmony_ci		ew32(PBA_ECC, reg);
12238c2ecf20Sopenharmony_ci	}
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci	/* Workaround for hardware errata.
12268c2ecf20Sopenharmony_ci	 * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572
12278c2ecf20Sopenharmony_ci	 */
12288c2ecf20Sopenharmony_ci	if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) {
12298c2ecf20Sopenharmony_ci		reg = er32(CTRL_EXT);
12308c2ecf20Sopenharmony_ci		reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN;
12318c2ecf20Sopenharmony_ci		ew32(CTRL_EXT, reg);
12328c2ecf20Sopenharmony_ci	}
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	/* Disable IPv6 extension header parsing because some malformed
12358c2ecf20Sopenharmony_ci	 * IPv6 headers can hang the Rx.
12368c2ecf20Sopenharmony_ci	 */
12378c2ecf20Sopenharmony_ci	if (hw->mac.type <= e1000_82573) {
12388c2ecf20Sopenharmony_ci		reg = er32(RFCTL);
12398c2ecf20Sopenharmony_ci		reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
12408c2ecf20Sopenharmony_ci		ew32(RFCTL, reg);
12418c2ecf20Sopenharmony_ci	}
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	/* PCI-Ex Control Registers */
12448c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
12458c2ecf20Sopenharmony_ci	case e1000_82574:
12468c2ecf20Sopenharmony_ci	case e1000_82583:
12478c2ecf20Sopenharmony_ci		reg = er32(GCR);
12488c2ecf20Sopenharmony_ci		reg |= BIT(22);
12498c2ecf20Sopenharmony_ci		ew32(GCR, reg);
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci		/* Workaround for hardware errata.
12528c2ecf20Sopenharmony_ci		 * apply workaround for hardware errata documented in errata
12538c2ecf20Sopenharmony_ci		 * docs Fixes issue where some error prone or unreliable PCIe
12548c2ecf20Sopenharmony_ci		 * completions are occurring, particularly with ASPM enabled.
12558c2ecf20Sopenharmony_ci		 * Without fix, issue can cause Tx timeouts.
12568c2ecf20Sopenharmony_ci		 */
12578c2ecf20Sopenharmony_ci		reg = er32(GCR2);
12588c2ecf20Sopenharmony_ci		reg |= 1;
12598c2ecf20Sopenharmony_ci		ew32(GCR2, reg);
12608c2ecf20Sopenharmony_ci		break;
12618c2ecf20Sopenharmony_ci	default:
12628c2ecf20Sopenharmony_ci		break;
12638c2ecf20Sopenharmony_ci	}
12648c2ecf20Sopenharmony_ci}
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci/**
12678c2ecf20Sopenharmony_ci *  e1000_clear_vfta_82571 - Clear VLAN filter table
12688c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
12698c2ecf20Sopenharmony_ci *
12708c2ecf20Sopenharmony_ci *  Clears the register array which contains the VLAN filter table by
12718c2ecf20Sopenharmony_ci *  setting all the values to 0.
12728c2ecf20Sopenharmony_ci **/
12738c2ecf20Sopenharmony_cistatic void e1000_clear_vfta_82571(struct e1000_hw *hw)
12748c2ecf20Sopenharmony_ci{
12758c2ecf20Sopenharmony_ci	u32 offset;
12768c2ecf20Sopenharmony_ci	u32 vfta_value = 0;
12778c2ecf20Sopenharmony_ci	u32 vfta_offset = 0;
12788c2ecf20Sopenharmony_ci	u32 vfta_bit_in_reg = 0;
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
12818c2ecf20Sopenharmony_ci	case e1000_82573:
12828c2ecf20Sopenharmony_ci	case e1000_82574:
12838c2ecf20Sopenharmony_ci	case e1000_82583:
12848c2ecf20Sopenharmony_ci		if (hw->mng_cookie.vlan_id != 0) {
12858c2ecf20Sopenharmony_ci			/* The VFTA is a 4096b bit-field, each identifying
12868c2ecf20Sopenharmony_ci			 * a single VLAN ID.  The following operations
12878c2ecf20Sopenharmony_ci			 * determine which 32b entry (i.e. offset) into the
12888c2ecf20Sopenharmony_ci			 * array we want to set the VLAN ID (i.e. bit) of
12898c2ecf20Sopenharmony_ci			 * the manageability unit.
12908c2ecf20Sopenharmony_ci			 */
12918c2ecf20Sopenharmony_ci			vfta_offset = (hw->mng_cookie.vlan_id >>
12928c2ecf20Sopenharmony_ci				       E1000_VFTA_ENTRY_SHIFT) &
12938c2ecf20Sopenharmony_ci			    E1000_VFTA_ENTRY_MASK;
12948c2ecf20Sopenharmony_ci			vfta_bit_in_reg =
12958c2ecf20Sopenharmony_ci			    BIT(hw->mng_cookie.vlan_id &
12968c2ecf20Sopenharmony_ci				E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
12978c2ecf20Sopenharmony_ci		}
12988c2ecf20Sopenharmony_ci		break;
12998c2ecf20Sopenharmony_ci	default:
13008c2ecf20Sopenharmony_ci		break;
13018c2ecf20Sopenharmony_ci	}
13028c2ecf20Sopenharmony_ci	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
13038c2ecf20Sopenharmony_ci		/* If the offset we want to clear is the same offset of the
13048c2ecf20Sopenharmony_ci		 * manageability VLAN ID, then clear all bits except that of
13058c2ecf20Sopenharmony_ci		 * the manageability unit.
13068c2ecf20Sopenharmony_ci		 */
13078c2ecf20Sopenharmony_ci		vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
13088c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value);
13098c2ecf20Sopenharmony_ci		e1e_flush();
13108c2ecf20Sopenharmony_ci	}
13118c2ecf20Sopenharmony_ci}
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci/**
13148c2ecf20Sopenharmony_ci *  e1000_check_mng_mode_82574 - Check manageability is enabled
13158c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
13168c2ecf20Sopenharmony_ci *
13178c2ecf20Sopenharmony_ci *  Reads the NVM Initialization Control Word 2 and returns true
13188c2ecf20Sopenharmony_ci *  (>0) if any manageability is enabled, else false (0).
13198c2ecf20Sopenharmony_ci **/
13208c2ecf20Sopenharmony_cistatic bool e1000_check_mng_mode_82574(struct e1000_hw *hw)
13218c2ecf20Sopenharmony_ci{
13228c2ecf20Sopenharmony_ci	u16 data;
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci	e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
13258c2ecf20Sopenharmony_ci	return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0;
13268c2ecf20Sopenharmony_ci}
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci/**
13298c2ecf20Sopenharmony_ci *  e1000_led_on_82574 - Turn LED on
13308c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
13318c2ecf20Sopenharmony_ci *
13328c2ecf20Sopenharmony_ci *  Turn LED on.
13338c2ecf20Sopenharmony_ci **/
13348c2ecf20Sopenharmony_cistatic s32 e1000_led_on_82574(struct e1000_hw *hw)
13358c2ecf20Sopenharmony_ci{
13368c2ecf20Sopenharmony_ci	u32 ctrl;
13378c2ecf20Sopenharmony_ci	u32 i;
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci	ctrl = hw->mac.ledctl_mode2;
13408c2ecf20Sopenharmony_ci	if (!(E1000_STATUS_LU & er32(STATUS))) {
13418c2ecf20Sopenharmony_ci		/* If no link, then turn LED on by setting the invert bit
13428c2ecf20Sopenharmony_ci		 * for each LED that's "on" (0x0E) in ledctl_mode2.
13438c2ecf20Sopenharmony_ci		 */
13448c2ecf20Sopenharmony_ci		for (i = 0; i < 4; i++)
13458c2ecf20Sopenharmony_ci			if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
13468c2ecf20Sopenharmony_ci			    E1000_LEDCTL_MODE_LED_ON)
13478c2ecf20Sopenharmony_ci				ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8));
13488c2ecf20Sopenharmony_ci	}
13498c2ecf20Sopenharmony_ci	ew32(LEDCTL, ctrl);
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	return 0;
13528c2ecf20Sopenharmony_ci}
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci/**
13558c2ecf20Sopenharmony_ci *  e1000_check_phy_82574 - check 82574 phy hung state
13568c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
13578c2ecf20Sopenharmony_ci *
13588c2ecf20Sopenharmony_ci *  Returns whether phy is hung or not
13598c2ecf20Sopenharmony_ci **/
13608c2ecf20Sopenharmony_cibool e1000_check_phy_82574(struct e1000_hw *hw)
13618c2ecf20Sopenharmony_ci{
13628c2ecf20Sopenharmony_ci	u16 status_1kbt = 0;
13638c2ecf20Sopenharmony_ci	u16 receive_errors = 0;
13648c2ecf20Sopenharmony_ci	s32 ret_val;
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	/* Read PHY Receive Error counter first, if its is max - all F's then
13678c2ecf20Sopenharmony_ci	 * read the Base1000T status register If both are max then PHY is hung.
13688c2ecf20Sopenharmony_ci	 */
13698c2ecf20Sopenharmony_ci	ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors);
13708c2ecf20Sopenharmony_ci	if (ret_val)
13718c2ecf20Sopenharmony_ci		return false;
13728c2ecf20Sopenharmony_ci	if (receive_errors == E1000_RECEIVE_ERROR_MAX) {
13738c2ecf20Sopenharmony_ci		ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt);
13748c2ecf20Sopenharmony_ci		if (ret_val)
13758c2ecf20Sopenharmony_ci			return false;
13768c2ecf20Sopenharmony_ci		if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) ==
13778c2ecf20Sopenharmony_ci		    E1000_IDLE_ERROR_COUNT_MASK)
13788c2ecf20Sopenharmony_ci			return true;
13798c2ecf20Sopenharmony_ci	}
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	return false;
13828c2ecf20Sopenharmony_ci}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci/**
13858c2ecf20Sopenharmony_ci *  e1000_setup_link_82571 - Setup flow control and link settings
13868c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
13878c2ecf20Sopenharmony_ci *
13888c2ecf20Sopenharmony_ci *  Determines which flow control settings to use, then configures flow
13898c2ecf20Sopenharmony_ci *  control.  Calls the appropriate media-specific link configuration
13908c2ecf20Sopenharmony_ci *  function.  Assuming the adapter has a valid link partner, a valid link
13918c2ecf20Sopenharmony_ci *  should be established.  Assumes the hardware has previously been reset
13928c2ecf20Sopenharmony_ci *  and the transmitter and receiver are not enabled.
13938c2ecf20Sopenharmony_ci **/
13948c2ecf20Sopenharmony_cistatic s32 e1000_setup_link_82571(struct e1000_hw *hw)
13958c2ecf20Sopenharmony_ci{
13968c2ecf20Sopenharmony_ci	/* 82573 does not have a word in the NVM to determine
13978c2ecf20Sopenharmony_ci	 * the default flow control setting, so we explicitly
13988c2ecf20Sopenharmony_ci	 * set it to full.
13998c2ecf20Sopenharmony_ci	 */
14008c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
14018c2ecf20Sopenharmony_ci	case e1000_82573:
14028c2ecf20Sopenharmony_ci	case e1000_82574:
14038c2ecf20Sopenharmony_ci	case e1000_82583:
14048c2ecf20Sopenharmony_ci		if (hw->fc.requested_mode == e1000_fc_default)
14058c2ecf20Sopenharmony_ci			hw->fc.requested_mode = e1000_fc_full;
14068c2ecf20Sopenharmony_ci		break;
14078c2ecf20Sopenharmony_ci	default:
14088c2ecf20Sopenharmony_ci		break;
14098c2ecf20Sopenharmony_ci	}
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	return e1000e_setup_link_generic(hw);
14128c2ecf20Sopenharmony_ci}
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ci/**
14158c2ecf20Sopenharmony_ci *  e1000_setup_copper_link_82571 - Configure copper link settings
14168c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
14178c2ecf20Sopenharmony_ci *
14188c2ecf20Sopenharmony_ci *  Configures the link for auto-neg or forced speed and duplex.  Then we check
14198c2ecf20Sopenharmony_ci *  for link, once link is established calls to configure collision distance
14208c2ecf20Sopenharmony_ci *  and flow control are called.
14218c2ecf20Sopenharmony_ci **/
14228c2ecf20Sopenharmony_cistatic s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
14238c2ecf20Sopenharmony_ci{
14248c2ecf20Sopenharmony_ci	u32 ctrl;
14258c2ecf20Sopenharmony_ci	s32 ret_val;
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
14288c2ecf20Sopenharmony_ci	ctrl |= E1000_CTRL_SLU;
14298c2ecf20Sopenharmony_ci	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
14308c2ecf20Sopenharmony_ci	ew32(CTRL, ctrl);
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci	switch (hw->phy.type) {
14338c2ecf20Sopenharmony_ci	case e1000_phy_m88:
14348c2ecf20Sopenharmony_ci	case e1000_phy_bm:
14358c2ecf20Sopenharmony_ci		ret_val = e1000e_copper_link_setup_m88(hw);
14368c2ecf20Sopenharmony_ci		break;
14378c2ecf20Sopenharmony_ci	case e1000_phy_igp_2:
14388c2ecf20Sopenharmony_ci		ret_val = e1000e_copper_link_setup_igp(hw);
14398c2ecf20Sopenharmony_ci		break;
14408c2ecf20Sopenharmony_ci	default:
14418c2ecf20Sopenharmony_ci		return -E1000_ERR_PHY;
14428c2ecf20Sopenharmony_ci	}
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	if (ret_val)
14458c2ecf20Sopenharmony_ci		return ret_val;
14468c2ecf20Sopenharmony_ci
14478c2ecf20Sopenharmony_ci	return e1000e_setup_copper_link(hw);
14488c2ecf20Sopenharmony_ci}
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci/**
14518c2ecf20Sopenharmony_ci *  e1000_setup_fiber_serdes_link_82571 - Setup link for fiber/serdes
14528c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
14538c2ecf20Sopenharmony_ci *
14548c2ecf20Sopenharmony_ci *  Configures collision distance and flow control for fiber and serdes links.
14558c2ecf20Sopenharmony_ci *  Upon successful setup, poll for link.
14568c2ecf20Sopenharmony_ci **/
14578c2ecf20Sopenharmony_cistatic s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
14588c2ecf20Sopenharmony_ci{
14598c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
14608c2ecf20Sopenharmony_ci	case e1000_82571:
14618c2ecf20Sopenharmony_ci	case e1000_82572:
14628c2ecf20Sopenharmony_ci		/* If SerDes loopback mode is entered, there is no form
14638c2ecf20Sopenharmony_ci		 * of reset to take the adapter out of that mode.  So we
14648c2ecf20Sopenharmony_ci		 * have to explicitly take the adapter out of loopback
14658c2ecf20Sopenharmony_ci		 * mode.  This prevents drivers from twiddling their thumbs
14668c2ecf20Sopenharmony_ci		 * if another tool failed to take it out of loopback mode.
14678c2ecf20Sopenharmony_ci		 */
14688c2ecf20Sopenharmony_ci		ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
14698c2ecf20Sopenharmony_ci		break;
14708c2ecf20Sopenharmony_ci	default:
14718c2ecf20Sopenharmony_ci		break;
14728c2ecf20Sopenharmony_ci	}
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci	return e1000e_setup_fiber_serdes_link(hw);
14758c2ecf20Sopenharmony_ci}
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci/**
14788c2ecf20Sopenharmony_ci *  e1000_check_for_serdes_link_82571 - Check for link (Serdes)
14798c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
14808c2ecf20Sopenharmony_ci *
14818c2ecf20Sopenharmony_ci *  Reports the link state as up or down.
14828c2ecf20Sopenharmony_ci *
14838c2ecf20Sopenharmony_ci *  If autonegotiation is supported by the link partner, the link state is
14848c2ecf20Sopenharmony_ci *  determined by the result of autonegotiation. This is the most likely case.
14858c2ecf20Sopenharmony_ci *  If autonegotiation is not supported by the link partner, and the link
14868c2ecf20Sopenharmony_ci *  has a valid signal, force the link up.
14878c2ecf20Sopenharmony_ci *
14888c2ecf20Sopenharmony_ci *  The link state is represented internally here by 4 states:
14898c2ecf20Sopenharmony_ci *
14908c2ecf20Sopenharmony_ci *  1) down
14918c2ecf20Sopenharmony_ci *  2) autoneg_progress
14928c2ecf20Sopenharmony_ci *  3) autoneg_complete (the link successfully autonegotiated)
14938c2ecf20Sopenharmony_ci *  4) forced_up (the link has been forced up, it did not autonegotiate)
14948c2ecf20Sopenharmony_ci *
14958c2ecf20Sopenharmony_ci **/
14968c2ecf20Sopenharmony_cistatic s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
14978c2ecf20Sopenharmony_ci{
14988c2ecf20Sopenharmony_ci	struct e1000_mac_info *mac = &hw->mac;
14998c2ecf20Sopenharmony_ci	u32 rxcw;
15008c2ecf20Sopenharmony_ci	u32 ctrl;
15018c2ecf20Sopenharmony_ci	u32 status;
15028c2ecf20Sopenharmony_ci	u32 txcw;
15038c2ecf20Sopenharmony_ci	u32 i;
15048c2ecf20Sopenharmony_ci	s32 ret_val = 0;
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
15078c2ecf20Sopenharmony_ci	status = er32(STATUS);
15088c2ecf20Sopenharmony_ci	er32(RXCW);
15098c2ecf20Sopenharmony_ci	/* SYNCH bit and IV bit are sticky */
15108c2ecf20Sopenharmony_ci	usleep_range(10, 20);
15118c2ecf20Sopenharmony_ci	rxcw = er32(RXCW);
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) {
15148c2ecf20Sopenharmony_ci		/* Receiver is synchronized with no invalid bits.  */
15158c2ecf20Sopenharmony_ci		switch (mac->serdes_link_state) {
15168c2ecf20Sopenharmony_ci		case e1000_serdes_link_autoneg_complete:
15178c2ecf20Sopenharmony_ci			if (!(status & E1000_STATUS_LU)) {
15188c2ecf20Sopenharmony_ci				/* We have lost link, retry autoneg before
15198c2ecf20Sopenharmony_ci				 * reporting link failure
15208c2ecf20Sopenharmony_ci				 */
15218c2ecf20Sopenharmony_ci				mac->serdes_link_state =
15228c2ecf20Sopenharmony_ci				    e1000_serdes_link_autoneg_progress;
15238c2ecf20Sopenharmony_ci				mac->serdes_has_link = false;
15248c2ecf20Sopenharmony_ci				e_dbg("AN_UP     -> AN_PROG\n");
15258c2ecf20Sopenharmony_ci			} else {
15268c2ecf20Sopenharmony_ci				mac->serdes_has_link = true;
15278c2ecf20Sopenharmony_ci			}
15288c2ecf20Sopenharmony_ci			break;
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci		case e1000_serdes_link_forced_up:
15318c2ecf20Sopenharmony_ci			/* If we are receiving /C/ ordered sets, re-enable
15328c2ecf20Sopenharmony_ci			 * auto-negotiation in the TXCW register and disable
15338c2ecf20Sopenharmony_ci			 * forced link in the Device Control register in an
15348c2ecf20Sopenharmony_ci			 * attempt to auto-negotiate with our link partner.
15358c2ecf20Sopenharmony_ci			 */
15368c2ecf20Sopenharmony_ci			if (rxcw & E1000_RXCW_C) {
15378c2ecf20Sopenharmony_ci				/* Enable autoneg, and unforce link up */
15388c2ecf20Sopenharmony_ci				ew32(TXCW, mac->txcw);
15398c2ecf20Sopenharmony_ci				ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
15408c2ecf20Sopenharmony_ci				mac->serdes_link_state =
15418c2ecf20Sopenharmony_ci				    e1000_serdes_link_autoneg_progress;
15428c2ecf20Sopenharmony_ci				mac->serdes_has_link = false;
15438c2ecf20Sopenharmony_ci				e_dbg("FORCED_UP -> AN_PROG\n");
15448c2ecf20Sopenharmony_ci			} else {
15458c2ecf20Sopenharmony_ci				mac->serdes_has_link = true;
15468c2ecf20Sopenharmony_ci			}
15478c2ecf20Sopenharmony_ci			break;
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci		case e1000_serdes_link_autoneg_progress:
15508c2ecf20Sopenharmony_ci			if (rxcw & E1000_RXCW_C) {
15518c2ecf20Sopenharmony_ci				/* We received /C/ ordered sets, meaning the
15528c2ecf20Sopenharmony_ci				 * link partner has autonegotiated, and we can
15538c2ecf20Sopenharmony_ci				 * trust the Link Up (LU) status bit.
15548c2ecf20Sopenharmony_ci				 */
15558c2ecf20Sopenharmony_ci				if (status & E1000_STATUS_LU) {
15568c2ecf20Sopenharmony_ci					mac->serdes_link_state =
15578c2ecf20Sopenharmony_ci					    e1000_serdes_link_autoneg_complete;
15588c2ecf20Sopenharmony_ci					e_dbg("AN_PROG   -> AN_UP\n");
15598c2ecf20Sopenharmony_ci					mac->serdes_has_link = true;
15608c2ecf20Sopenharmony_ci				} else {
15618c2ecf20Sopenharmony_ci					/* Autoneg completed, but failed. */
15628c2ecf20Sopenharmony_ci					mac->serdes_link_state =
15638c2ecf20Sopenharmony_ci					    e1000_serdes_link_down;
15648c2ecf20Sopenharmony_ci					e_dbg("AN_PROG   -> DOWN\n");
15658c2ecf20Sopenharmony_ci				}
15668c2ecf20Sopenharmony_ci			} else {
15678c2ecf20Sopenharmony_ci				/* The link partner did not autoneg.
15688c2ecf20Sopenharmony_ci				 * Force link up and full duplex, and change
15698c2ecf20Sopenharmony_ci				 * state to forced.
15708c2ecf20Sopenharmony_ci				 */
15718c2ecf20Sopenharmony_ci				ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
15728c2ecf20Sopenharmony_ci				ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
15738c2ecf20Sopenharmony_ci				ew32(CTRL, ctrl);
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci				/* Configure Flow Control after link up. */
15768c2ecf20Sopenharmony_ci				ret_val = e1000e_config_fc_after_link_up(hw);
15778c2ecf20Sopenharmony_ci				if (ret_val) {
15788c2ecf20Sopenharmony_ci					e_dbg("Error config flow control\n");
15798c2ecf20Sopenharmony_ci					break;
15808c2ecf20Sopenharmony_ci				}
15818c2ecf20Sopenharmony_ci				mac->serdes_link_state =
15828c2ecf20Sopenharmony_ci				    e1000_serdes_link_forced_up;
15838c2ecf20Sopenharmony_ci				mac->serdes_has_link = true;
15848c2ecf20Sopenharmony_ci				e_dbg("AN_PROG   -> FORCED_UP\n");
15858c2ecf20Sopenharmony_ci			}
15868c2ecf20Sopenharmony_ci			break;
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci		case e1000_serdes_link_down:
15898c2ecf20Sopenharmony_ci		default:
15908c2ecf20Sopenharmony_ci			/* The link was down but the receiver has now gained
15918c2ecf20Sopenharmony_ci			 * valid sync, so lets see if we can bring the link
15928c2ecf20Sopenharmony_ci			 * up.
15938c2ecf20Sopenharmony_ci			 */
15948c2ecf20Sopenharmony_ci			ew32(TXCW, mac->txcw);
15958c2ecf20Sopenharmony_ci			ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
15968c2ecf20Sopenharmony_ci			mac->serdes_link_state =
15978c2ecf20Sopenharmony_ci			    e1000_serdes_link_autoneg_progress;
15988c2ecf20Sopenharmony_ci			mac->serdes_has_link = false;
15998c2ecf20Sopenharmony_ci			e_dbg("DOWN      -> AN_PROG\n");
16008c2ecf20Sopenharmony_ci			break;
16018c2ecf20Sopenharmony_ci		}
16028c2ecf20Sopenharmony_ci	} else {
16038c2ecf20Sopenharmony_ci		if (!(rxcw & E1000_RXCW_SYNCH)) {
16048c2ecf20Sopenharmony_ci			mac->serdes_has_link = false;
16058c2ecf20Sopenharmony_ci			mac->serdes_link_state = e1000_serdes_link_down;
16068c2ecf20Sopenharmony_ci			e_dbg("ANYSTATE  -> DOWN\n");
16078c2ecf20Sopenharmony_ci		} else {
16088c2ecf20Sopenharmony_ci			/* Check several times, if SYNCH bit and CONFIG
16098c2ecf20Sopenharmony_ci			 * bit both are consistently 1 then simply ignore
16108c2ecf20Sopenharmony_ci			 * the IV bit and restart Autoneg
16118c2ecf20Sopenharmony_ci			 */
16128c2ecf20Sopenharmony_ci			for (i = 0; i < AN_RETRY_COUNT; i++) {
16138c2ecf20Sopenharmony_ci				usleep_range(10, 20);
16148c2ecf20Sopenharmony_ci				rxcw = er32(RXCW);
16158c2ecf20Sopenharmony_ci				if ((rxcw & E1000_RXCW_SYNCH) &&
16168c2ecf20Sopenharmony_ci				    (rxcw & E1000_RXCW_C))
16178c2ecf20Sopenharmony_ci					continue;
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci				if (rxcw & E1000_RXCW_IV) {
16208c2ecf20Sopenharmony_ci					mac->serdes_has_link = false;
16218c2ecf20Sopenharmony_ci					mac->serdes_link_state =
16228c2ecf20Sopenharmony_ci					    e1000_serdes_link_down;
16238c2ecf20Sopenharmony_ci					e_dbg("ANYSTATE  -> DOWN\n");
16248c2ecf20Sopenharmony_ci					break;
16258c2ecf20Sopenharmony_ci				}
16268c2ecf20Sopenharmony_ci			}
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_ci			if (i == AN_RETRY_COUNT) {
16298c2ecf20Sopenharmony_ci				txcw = er32(TXCW);
16308c2ecf20Sopenharmony_ci				txcw |= E1000_TXCW_ANE;
16318c2ecf20Sopenharmony_ci				ew32(TXCW, txcw);
16328c2ecf20Sopenharmony_ci				mac->serdes_link_state =
16338c2ecf20Sopenharmony_ci				    e1000_serdes_link_autoneg_progress;
16348c2ecf20Sopenharmony_ci				mac->serdes_has_link = false;
16358c2ecf20Sopenharmony_ci				e_dbg("ANYSTATE  -> AN_PROG\n");
16368c2ecf20Sopenharmony_ci			}
16378c2ecf20Sopenharmony_ci		}
16388c2ecf20Sopenharmony_ci	}
16398c2ecf20Sopenharmony_ci
16408c2ecf20Sopenharmony_ci	return ret_val;
16418c2ecf20Sopenharmony_ci}
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci/**
16448c2ecf20Sopenharmony_ci *  e1000_valid_led_default_82571 - Verify a valid default LED config
16458c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
16468c2ecf20Sopenharmony_ci *  @data: pointer to the NVM (EEPROM)
16478c2ecf20Sopenharmony_ci *
16488c2ecf20Sopenharmony_ci *  Read the EEPROM for the current default LED configuration.  If the
16498c2ecf20Sopenharmony_ci *  LED configuration is not valid, set to a valid LED configuration.
16508c2ecf20Sopenharmony_ci **/
16518c2ecf20Sopenharmony_cistatic s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data)
16528c2ecf20Sopenharmony_ci{
16538c2ecf20Sopenharmony_ci	s32 ret_val;
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ci	ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);
16568c2ecf20Sopenharmony_ci	if (ret_val) {
16578c2ecf20Sopenharmony_ci		e_dbg("NVM Read Error\n");
16588c2ecf20Sopenharmony_ci		return ret_val;
16598c2ecf20Sopenharmony_ci	}
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
16628c2ecf20Sopenharmony_ci	case e1000_82573:
16638c2ecf20Sopenharmony_ci	case e1000_82574:
16648c2ecf20Sopenharmony_ci	case e1000_82583:
16658c2ecf20Sopenharmony_ci		if (*data == ID_LED_RESERVED_F746)
16668c2ecf20Sopenharmony_ci			*data = ID_LED_DEFAULT_82573;
16678c2ecf20Sopenharmony_ci		break;
16688c2ecf20Sopenharmony_ci	default:
16698c2ecf20Sopenharmony_ci		if (*data == ID_LED_RESERVED_0000 ||
16708c2ecf20Sopenharmony_ci		    *data == ID_LED_RESERVED_FFFF)
16718c2ecf20Sopenharmony_ci			*data = ID_LED_DEFAULT;
16728c2ecf20Sopenharmony_ci		break;
16738c2ecf20Sopenharmony_ci	}
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_ci	return 0;
16768c2ecf20Sopenharmony_ci}
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci/**
16798c2ecf20Sopenharmony_ci *  e1000e_get_laa_state_82571 - Get locally administered address state
16808c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
16818c2ecf20Sopenharmony_ci *
16828c2ecf20Sopenharmony_ci *  Retrieve and return the current locally administered address state.
16838c2ecf20Sopenharmony_ci **/
16848c2ecf20Sopenharmony_cibool e1000e_get_laa_state_82571(struct e1000_hw *hw)
16858c2ecf20Sopenharmony_ci{
16868c2ecf20Sopenharmony_ci	if (hw->mac.type != e1000_82571)
16878c2ecf20Sopenharmony_ci		return false;
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci	return hw->dev_spec.e82571.laa_is_present;
16908c2ecf20Sopenharmony_ci}
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci/**
16938c2ecf20Sopenharmony_ci *  e1000e_set_laa_state_82571 - Set locally administered address state
16948c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
16958c2ecf20Sopenharmony_ci *  @state: enable/disable locally administered address
16968c2ecf20Sopenharmony_ci *
16978c2ecf20Sopenharmony_ci *  Enable/Disable the current locally administered address state.
16988c2ecf20Sopenharmony_ci **/
16998c2ecf20Sopenharmony_civoid e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state)
17008c2ecf20Sopenharmony_ci{
17018c2ecf20Sopenharmony_ci	if (hw->mac.type != e1000_82571)
17028c2ecf20Sopenharmony_ci		return;
17038c2ecf20Sopenharmony_ci
17048c2ecf20Sopenharmony_ci	hw->dev_spec.e82571.laa_is_present = state;
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	/* If workaround is activated... */
17078c2ecf20Sopenharmony_ci	if (state)
17088c2ecf20Sopenharmony_ci		/* Hold a copy of the LAA in RAR[14] This is done so that
17098c2ecf20Sopenharmony_ci		 * between the time RAR[0] gets clobbered and the time it
17108c2ecf20Sopenharmony_ci		 * gets fixed, the actual LAA is in one of the RARs and no
17118c2ecf20Sopenharmony_ci		 * incoming packets directed to this port are dropped.
17128c2ecf20Sopenharmony_ci		 * Eventually the LAA will be in RAR[0] and RAR[14].
17138c2ecf20Sopenharmony_ci		 */
17148c2ecf20Sopenharmony_ci		hw->mac.ops.rar_set(hw, hw->mac.addr,
17158c2ecf20Sopenharmony_ci				    hw->mac.rar_entry_count - 1);
17168c2ecf20Sopenharmony_ci}
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci/**
17198c2ecf20Sopenharmony_ci *  e1000_fix_nvm_checksum_82571 - Fix EEPROM checksum
17208c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
17218c2ecf20Sopenharmony_ci *
17228c2ecf20Sopenharmony_ci *  Verifies that the EEPROM has completed the update.  After updating the
17238c2ecf20Sopenharmony_ci *  EEPROM, we need to check bit 15 in work 0x23 for the checksum fix.  If
17248c2ecf20Sopenharmony_ci *  the checksum fix is not implemented, we need to set the bit and update
17258c2ecf20Sopenharmony_ci *  the checksum.  Otherwise, if bit 15 is set and the checksum is incorrect,
17268c2ecf20Sopenharmony_ci *  we need to return bad checksum.
17278c2ecf20Sopenharmony_ci **/
17288c2ecf20Sopenharmony_cistatic s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
17298c2ecf20Sopenharmony_ci{
17308c2ecf20Sopenharmony_ci	struct e1000_nvm_info *nvm = &hw->nvm;
17318c2ecf20Sopenharmony_ci	s32 ret_val;
17328c2ecf20Sopenharmony_ci	u16 data;
17338c2ecf20Sopenharmony_ci
17348c2ecf20Sopenharmony_ci	if (nvm->type != e1000_nvm_flash_hw)
17358c2ecf20Sopenharmony_ci		return 0;
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_ci	/* Check bit 4 of word 10h.  If it is 0, firmware is done updating
17388c2ecf20Sopenharmony_ci	 * 10h-12h.  Checksum may need to be fixed.
17398c2ecf20Sopenharmony_ci	 */
17408c2ecf20Sopenharmony_ci	ret_val = e1000_read_nvm(hw, 0x10, 1, &data);
17418c2ecf20Sopenharmony_ci	if (ret_val)
17428c2ecf20Sopenharmony_ci		return ret_val;
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	if (!(data & 0x10)) {
17458c2ecf20Sopenharmony_ci		/* Read 0x23 and check bit 15.  This bit is a 1
17468c2ecf20Sopenharmony_ci		 * when the checksum has already been fixed.  If
17478c2ecf20Sopenharmony_ci		 * the checksum is still wrong and this bit is a
17488c2ecf20Sopenharmony_ci		 * 1, we need to return bad checksum.  Otherwise,
17498c2ecf20Sopenharmony_ci		 * we need to set this bit to a 1 and update the
17508c2ecf20Sopenharmony_ci		 * checksum.
17518c2ecf20Sopenharmony_ci		 */
17528c2ecf20Sopenharmony_ci		ret_val = e1000_read_nvm(hw, 0x23, 1, &data);
17538c2ecf20Sopenharmony_ci		if (ret_val)
17548c2ecf20Sopenharmony_ci			return ret_val;
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ci		if (!(data & 0x8000)) {
17578c2ecf20Sopenharmony_ci			data |= 0x8000;
17588c2ecf20Sopenharmony_ci			ret_val = e1000_write_nvm(hw, 0x23, 1, &data);
17598c2ecf20Sopenharmony_ci			if (ret_val)
17608c2ecf20Sopenharmony_ci				return ret_val;
17618c2ecf20Sopenharmony_ci			ret_val = e1000e_update_nvm_checksum(hw);
17628c2ecf20Sopenharmony_ci			if (ret_val)
17638c2ecf20Sopenharmony_ci				return ret_val;
17648c2ecf20Sopenharmony_ci		}
17658c2ecf20Sopenharmony_ci	}
17668c2ecf20Sopenharmony_ci
17678c2ecf20Sopenharmony_ci	return 0;
17688c2ecf20Sopenharmony_ci}
17698c2ecf20Sopenharmony_ci
17708c2ecf20Sopenharmony_ci/**
17718c2ecf20Sopenharmony_ci *  e1000_read_mac_addr_82571 - Read device MAC address
17728c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
17738c2ecf20Sopenharmony_ci **/
17748c2ecf20Sopenharmony_cistatic s32 e1000_read_mac_addr_82571(struct e1000_hw *hw)
17758c2ecf20Sopenharmony_ci{
17768c2ecf20Sopenharmony_ci	if (hw->mac.type == e1000_82571) {
17778c2ecf20Sopenharmony_ci		s32 ret_val;
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci		/* If there's an alternate MAC address place it in RAR0
17808c2ecf20Sopenharmony_ci		 * so that it will override the Si installed default perm
17818c2ecf20Sopenharmony_ci		 * address.
17828c2ecf20Sopenharmony_ci		 */
17838c2ecf20Sopenharmony_ci		ret_val = e1000_check_alt_mac_addr_generic(hw);
17848c2ecf20Sopenharmony_ci		if (ret_val)
17858c2ecf20Sopenharmony_ci			return ret_val;
17868c2ecf20Sopenharmony_ci	}
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	return e1000_read_mac_addr_generic(hw);
17898c2ecf20Sopenharmony_ci}
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci/**
17928c2ecf20Sopenharmony_ci * e1000_power_down_phy_copper_82571 - Remove link during PHY power down
17938c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure
17948c2ecf20Sopenharmony_ci *
17958c2ecf20Sopenharmony_ci * In the case of a PHY power down to save power, or to turn off link during a
17968c2ecf20Sopenharmony_ci * driver unload, or wake on lan is not enabled, remove the link.
17978c2ecf20Sopenharmony_ci **/
17988c2ecf20Sopenharmony_cistatic void e1000_power_down_phy_copper_82571(struct e1000_hw *hw)
17998c2ecf20Sopenharmony_ci{
18008c2ecf20Sopenharmony_ci	struct e1000_phy_info *phy = &hw->phy;
18018c2ecf20Sopenharmony_ci	struct e1000_mac_info *mac = &hw->mac;
18028c2ecf20Sopenharmony_ci
18038c2ecf20Sopenharmony_ci	if (!phy->ops.check_reset_block)
18048c2ecf20Sopenharmony_ci		return;
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_ci	/* If the management interface is not enabled, then power down */
18078c2ecf20Sopenharmony_ci	if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw)))
18088c2ecf20Sopenharmony_ci		e1000_power_down_phy_copper(hw);
18098c2ecf20Sopenharmony_ci}
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_ci/**
18128c2ecf20Sopenharmony_ci *  e1000_clear_hw_cntrs_82571 - Clear device specific hardware counters
18138c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
18148c2ecf20Sopenharmony_ci *
18158c2ecf20Sopenharmony_ci *  Clears the hardware counters by reading the counter registers.
18168c2ecf20Sopenharmony_ci **/
18178c2ecf20Sopenharmony_cistatic void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw)
18188c2ecf20Sopenharmony_ci{
18198c2ecf20Sopenharmony_ci	e1000e_clear_hw_cntrs_base(hw);
18208c2ecf20Sopenharmony_ci
18218c2ecf20Sopenharmony_ci	er32(PRC64);
18228c2ecf20Sopenharmony_ci	er32(PRC127);
18238c2ecf20Sopenharmony_ci	er32(PRC255);
18248c2ecf20Sopenharmony_ci	er32(PRC511);
18258c2ecf20Sopenharmony_ci	er32(PRC1023);
18268c2ecf20Sopenharmony_ci	er32(PRC1522);
18278c2ecf20Sopenharmony_ci	er32(PTC64);
18288c2ecf20Sopenharmony_ci	er32(PTC127);
18298c2ecf20Sopenharmony_ci	er32(PTC255);
18308c2ecf20Sopenharmony_ci	er32(PTC511);
18318c2ecf20Sopenharmony_ci	er32(PTC1023);
18328c2ecf20Sopenharmony_ci	er32(PTC1522);
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_ci	er32(ALGNERRC);
18358c2ecf20Sopenharmony_ci	er32(RXERRC);
18368c2ecf20Sopenharmony_ci	er32(TNCRS);
18378c2ecf20Sopenharmony_ci	er32(CEXTERR);
18388c2ecf20Sopenharmony_ci	er32(TSCTC);
18398c2ecf20Sopenharmony_ci	er32(TSCTFC);
18408c2ecf20Sopenharmony_ci
18418c2ecf20Sopenharmony_ci	er32(MGTPRC);
18428c2ecf20Sopenharmony_ci	er32(MGTPDC);
18438c2ecf20Sopenharmony_ci	er32(MGTPTC);
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci	er32(IAC);
18468c2ecf20Sopenharmony_ci	er32(ICRXOC);
18478c2ecf20Sopenharmony_ci
18488c2ecf20Sopenharmony_ci	er32(ICRXPTC);
18498c2ecf20Sopenharmony_ci	er32(ICRXATC);
18508c2ecf20Sopenharmony_ci	er32(ICTXPTC);
18518c2ecf20Sopenharmony_ci	er32(ICTXATC);
18528c2ecf20Sopenharmony_ci	er32(ICTXQEC);
18538c2ecf20Sopenharmony_ci	er32(ICTXQMTC);
18548c2ecf20Sopenharmony_ci	er32(ICRXDMTC);
18558c2ecf20Sopenharmony_ci}
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_cistatic const struct e1000_mac_operations e82571_mac_ops = {
18588c2ecf20Sopenharmony_ci	/* .check_mng_mode: mac type dependent */
18598c2ecf20Sopenharmony_ci	/* .check_for_link: media type dependent */
18608c2ecf20Sopenharmony_ci	.id_led_init		= e1000e_id_led_init_generic,
18618c2ecf20Sopenharmony_ci	.cleanup_led		= e1000e_cleanup_led_generic,
18628c2ecf20Sopenharmony_ci	.clear_hw_cntrs		= e1000_clear_hw_cntrs_82571,
18638c2ecf20Sopenharmony_ci	.get_bus_info		= e1000e_get_bus_info_pcie,
18648c2ecf20Sopenharmony_ci	.set_lan_id		= e1000_set_lan_id_multi_port_pcie,
18658c2ecf20Sopenharmony_ci	/* .get_link_up_info: media type dependent */
18668c2ecf20Sopenharmony_ci	/* .led_on: mac type dependent */
18678c2ecf20Sopenharmony_ci	.led_off		= e1000e_led_off_generic,
18688c2ecf20Sopenharmony_ci	.update_mc_addr_list	= e1000e_update_mc_addr_list_generic,
18698c2ecf20Sopenharmony_ci	.write_vfta		= e1000_write_vfta_generic,
18708c2ecf20Sopenharmony_ci	.clear_vfta		= e1000_clear_vfta_82571,
18718c2ecf20Sopenharmony_ci	.reset_hw		= e1000_reset_hw_82571,
18728c2ecf20Sopenharmony_ci	.init_hw		= e1000_init_hw_82571,
18738c2ecf20Sopenharmony_ci	.setup_link		= e1000_setup_link_82571,
18748c2ecf20Sopenharmony_ci	/* .setup_physical_interface: media type dependent */
18758c2ecf20Sopenharmony_ci	.setup_led		= e1000e_setup_led_generic,
18768c2ecf20Sopenharmony_ci	.config_collision_dist	= e1000e_config_collision_dist_generic,
18778c2ecf20Sopenharmony_ci	.read_mac_addr		= e1000_read_mac_addr_82571,
18788c2ecf20Sopenharmony_ci	.rar_set		= e1000e_rar_set_generic,
18798c2ecf20Sopenharmony_ci	.rar_get_count		= e1000e_rar_get_count_generic,
18808c2ecf20Sopenharmony_ci};
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_cistatic const struct e1000_phy_operations e82_phy_ops_igp = {
18838c2ecf20Sopenharmony_ci	.acquire		= e1000_get_hw_semaphore_82571,
18848c2ecf20Sopenharmony_ci	.check_polarity		= e1000_check_polarity_igp,
18858c2ecf20Sopenharmony_ci	.check_reset_block	= e1000e_check_reset_block_generic,
18868c2ecf20Sopenharmony_ci	.commit			= NULL,
18878c2ecf20Sopenharmony_ci	.force_speed_duplex	= e1000e_phy_force_speed_duplex_igp,
18888c2ecf20Sopenharmony_ci	.get_cfg_done		= e1000_get_cfg_done_82571,
18898c2ecf20Sopenharmony_ci	.get_cable_length	= e1000e_get_cable_length_igp_2,
18908c2ecf20Sopenharmony_ci	.get_info		= e1000e_get_phy_info_igp,
18918c2ecf20Sopenharmony_ci	.read_reg		= e1000e_read_phy_reg_igp,
18928c2ecf20Sopenharmony_ci	.release		= e1000_put_hw_semaphore_82571,
18938c2ecf20Sopenharmony_ci	.reset			= e1000e_phy_hw_reset_generic,
18948c2ecf20Sopenharmony_ci	.set_d0_lplu_state	= e1000_set_d0_lplu_state_82571,
18958c2ecf20Sopenharmony_ci	.set_d3_lplu_state	= e1000e_set_d3_lplu_state,
18968c2ecf20Sopenharmony_ci	.write_reg		= e1000e_write_phy_reg_igp,
18978c2ecf20Sopenharmony_ci	.cfg_on_link_up		= NULL,
18988c2ecf20Sopenharmony_ci};
18998c2ecf20Sopenharmony_ci
19008c2ecf20Sopenharmony_cistatic const struct e1000_phy_operations e82_phy_ops_m88 = {
19018c2ecf20Sopenharmony_ci	.acquire		= e1000_get_hw_semaphore_82571,
19028c2ecf20Sopenharmony_ci	.check_polarity		= e1000_check_polarity_m88,
19038c2ecf20Sopenharmony_ci	.check_reset_block	= e1000e_check_reset_block_generic,
19048c2ecf20Sopenharmony_ci	.commit			= e1000e_phy_sw_reset,
19058c2ecf20Sopenharmony_ci	.force_speed_duplex	= e1000e_phy_force_speed_duplex_m88,
19068c2ecf20Sopenharmony_ci	.get_cfg_done		= e1000e_get_cfg_done_generic,
19078c2ecf20Sopenharmony_ci	.get_cable_length	= e1000e_get_cable_length_m88,
19088c2ecf20Sopenharmony_ci	.get_info		= e1000e_get_phy_info_m88,
19098c2ecf20Sopenharmony_ci	.read_reg		= e1000e_read_phy_reg_m88,
19108c2ecf20Sopenharmony_ci	.release		= e1000_put_hw_semaphore_82571,
19118c2ecf20Sopenharmony_ci	.reset			= e1000e_phy_hw_reset_generic,
19128c2ecf20Sopenharmony_ci	.set_d0_lplu_state	= e1000_set_d0_lplu_state_82571,
19138c2ecf20Sopenharmony_ci	.set_d3_lplu_state	= e1000e_set_d3_lplu_state,
19148c2ecf20Sopenharmony_ci	.write_reg		= e1000e_write_phy_reg_m88,
19158c2ecf20Sopenharmony_ci	.cfg_on_link_up		= NULL,
19168c2ecf20Sopenharmony_ci};
19178c2ecf20Sopenharmony_ci
19188c2ecf20Sopenharmony_cistatic const struct e1000_phy_operations e82_phy_ops_bm = {
19198c2ecf20Sopenharmony_ci	.acquire		= e1000_get_hw_semaphore_82571,
19208c2ecf20Sopenharmony_ci	.check_polarity		= e1000_check_polarity_m88,
19218c2ecf20Sopenharmony_ci	.check_reset_block	= e1000e_check_reset_block_generic,
19228c2ecf20Sopenharmony_ci	.commit			= e1000e_phy_sw_reset,
19238c2ecf20Sopenharmony_ci	.force_speed_duplex	= e1000e_phy_force_speed_duplex_m88,
19248c2ecf20Sopenharmony_ci	.get_cfg_done		= e1000e_get_cfg_done_generic,
19258c2ecf20Sopenharmony_ci	.get_cable_length	= e1000e_get_cable_length_m88,
19268c2ecf20Sopenharmony_ci	.get_info		= e1000e_get_phy_info_m88,
19278c2ecf20Sopenharmony_ci	.read_reg		= e1000e_read_phy_reg_bm2,
19288c2ecf20Sopenharmony_ci	.release		= e1000_put_hw_semaphore_82571,
19298c2ecf20Sopenharmony_ci	.reset			= e1000e_phy_hw_reset_generic,
19308c2ecf20Sopenharmony_ci	.set_d0_lplu_state	= e1000_set_d0_lplu_state_82571,
19318c2ecf20Sopenharmony_ci	.set_d3_lplu_state	= e1000e_set_d3_lplu_state,
19328c2ecf20Sopenharmony_ci	.write_reg		= e1000e_write_phy_reg_bm2,
19338c2ecf20Sopenharmony_ci	.cfg_on_link_up		= NULL,
19348c2ecf20Sopenharmony_ci};
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_cistatic const struct e1000_nvm_operations e82571_nvm_ops = {
19378c2ecf20Sopenharmony_ci	.acquire		= e1000_acquire_nvm_82571,
19388c2ecf20Sopenharmony_ci	.read			= e1000e_read_nvm_eerd,
19398c2ecf20Sopenharmony_ci	.release		= e1000_release_nvm_82571,
19408c2ecf20Sopenharmony_ci	.reload			= e1000e_reload_nvm_generic,
19418c2ecf20Sopenharmony_ci	.update			= e1000_update_nvm_checksum_82571,
19428c2ecf20Sopenharmony_ci	.valid_led_default	= e1000_valid_led_default_82571,
19438c2ecf20Sopenharmony_ci	.validate		= e1000_validate_nvm_checksum_82571,
19448c2ecf20Sopenharmony_ci	.write			= e1000_write_nvm_82571,
19458c2ecf20Sopenharmony_ci};
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ciconst struct e1000_info e1000_82571_info = {
19488c2ecf20Sopenharmony_ci	.mac			= e1000_82571,
19498c2ecf20Sopenharmony_ci	.flags			= FLAG_HAS_HW_VLAN_FILTER
19508c2ecf20Sopenharmony_ci				  | FLAG_HAS_JUMBO_FRAMES
19518c2ecf20Sopenharmony_ci				  | FLAG_HAS_WOL
19528c2ecf20Sopenharmony_ci				  | FLAG_APME_IN_CTRL3
19538c2ecf20Sopenharmony_ci				  | FLAG_HAS_CTRLEXT_ON_LOAD
19548c2ecf20Sopenharmony_ci				  | FLAG_HAS_SMART_POWER_DOWN
19558c2ecf20Sopenharmony_ci				  | FLAG_RESET_OVERWRITES_LAA /* errata */
19568c2ecf20Sopenharmony_ci				  | FLAG_TARC_SPEED_MODE_BIT /* errata */
19578c2ecf20Sopenharmony_ci				  | FLAG_APME_CHECK_PORT_B,
19588c2ecf20Sopenharmony_ci	.flags2			= FLAG2_DISABLE_ASPM_L1 /* errata 13 */
19598c2ecf20Sopenharmony_ci				  | FLAG2_DMA_BURST,
19608c2ecf20Sopenharmony_ci	.pba			= 38,
19618c2ecf20Sopenharmony_ci	.max_hw_frame_size	= DEFAULT_JUMBO,
19628c2ecf20Sopenharmony_ci	.get_variants		= e1000_get_variants_82571,
19638c2ecf20Sopenharmony_ci	.mac_ops		= &e82571_mac_ops,
19648c2ecf20Sopenharmony_ci	.phy_ops		= &e82_phy_ops_igp,
19658c2ecf20Sopenharmony_ci	.nvm_ops		= &e82571_nvm_ops,
19668c2ecf20Sopenharmony_ci};
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_ciconst struct e1000_info e1000_82572_info = {
19698c2ecf20Sopenharmony_ci	.mac			= e1000_82572,
19708c2ecf20Sopenharmony_ci	.flags			= FLAG_HAS_HW_VLAN_FILTER
19718c2ecf20Sopenharmony_ci				  | FLAG_HAS_JUMBO_FRAMES
19728c2ecf20Sopenharmony_ci				  | FLAG_HAS_WOL
19738c2ecf20Sopenharmony_ci				  | FLAG_APME_IN_CTRL3
19748c2ecf20Sopenharmony_ci				  | FLAG_HAS_CTRLEXT_ON_LOAD
19758c2ecf20Sopenharmony_ci				  | FLAG_TARC_SPEED_MODE_BIT, /* errata */
19768c2ecf20Sopenharmony_ci	.flags2			= FLAG2_DISABLE_ASPM_L1 /* errata 13 */
19778c2ecf20Sopenharmony_ci				  | FLAG2_DMA_BURST,
19788c2ecf20Sopenharmony_ci	.pba			= 38,
19798c2ecf20Sopenharmony_ci	.max_hw_frame_size	= DEFAULT_JUMBO,
19808c2ecf20Sopenharmony_ci	.get_variants		= e1000_get_variants_82571,
19818c2ecf20Sopenharmony_ci	.mac_ops		= &e82571_mac_ops,
19828c2ecf20Sopenharmony_ci	.phy_ops		= &e82_phy_ops_igp,
19838c2ecf20Sopenharmony_ci	.nvm_ops		= &e82571_nvm_ops,
19848c2ecf20Sopenharmony_ci};
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ciconst struct e1000_info e1000_82573_info = {
19878c2ecf20Sopenharmony_ci	.mac			= e1000_82573,
19888c2ecf20Sopenharmony_ci	.flags			= FLAG_HAS_HW_VLAN_FILTER
19898c2ecf20Sopenharmony_ci				  | FLAG_HAS_WOL
19908c2ecf20Sopenharmony_ci				  | FLAG_APME_IN_CTRL3
19918c2ecf20Sopenharmony_ci				  | FLAG_HAS_SMART_POWER_DOWN
19928c2ecf20Sopenharmony_ci				  | FLAG_HAS_AMT
19938c2ecf20Sopenharmony_ci				  | FLAG_HAS_SWSM_ON_LOAD,
19948c2ecf20Sopenharmony_ci	.flags2			= FLAG2_DISABLE_ASPM_L1
19958c2ecf20Sopenharmony_ci				  | FLAG2_DISABLE_ASPM_L0S,
19968c2ecf20Sopenharmony_ci	.pba			= 20,
19978c2ecf20Sopenharmony_ci	.max_hw_frame_size	= VLAN_ETH_FRAME_LEN + ETH_FCS_LEN,
19988c2ecf20Sopenharmony_ci	.get_variants		= e1000_get_variants_82571,
19998c2ecf20Sopenharmony_ci	.mac_ops		= &e82571_mac_ops,
20008c2ecf20Sopenharmony_ci	.phy_ops		= &e82_phy_ops_m88,
20018c2ecf20Sopenharmony_ci	.nvm_ops		= &e82571_nvm_ops,
20028c2ecf20Sopenharmony_ci};
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ciconst struct e1000_info e1000_82574_info = {
20058c2ecf20Sopenharmony_ci	.mac			= e1000_82574,
20068c2ecf20Sopenharmony_ci	.flags			= FLAG_HAS_HW_VLAN_FILTER
20078c2ecf20Sopenharmony_ci				  | FLAG_HAS_MSIX
20088c2ecf20Sopenharmony_ci				  | FLAG_HAS_JUMBO_FRAMES
20098c2ecf20Sopenharmony_ci				  | FLAG_HAS_WOL
20108c2ecf20Sopenharmony_ci				  | FLAG_HAS_HW_TIMESTAMP
20118c2ecf20Sopenharmony_ci				  | FLAG_APME_IN_CTRL3
20128c2ecf20Sopenharmony_ci				  | FLAG_HAS_SMART_POWER_DOWN
20138c2ecf20Sopenharmony_ci				  | FLAG_HAS_AMT
20148c2ecf20Sopenharmony_ci				  | FLAG_HAS_CTRLEXT_ON_LOAD,
20158c2ecf20Sopenharmony_ci	.flags2			 = FLAG2_CHECK_PHY_HANG
20168c2ecf20Sopenharmony_ci				  | FLAG2_DISABLE_ASPM_L0S
20178c2ecf20Sopenharmony_ci				  | FLAG2_DISABLE_ASPM_L1
20188c2ecf20Sopenharmony_ci				  | FLAG2_NO_DISABLE_RX
20198c2ecf20Sopenharmony_ci				  | FLAG2_DMA_BURST
20208c2ecf20Sopenharmony_ci				  | FLAG2_CHECK_SYSTIM_OVERFLOW,
20218c2ecf20Sopenharmony_ci	.pba			= 32,
20228c2ecf20Sopenharmony_ci	.max_hw_frame_size	= DEFAULT_JUMBO,
20238c2ecf20Sopenharmony_ci	.get_variants		= e1000_get_variants_82571,
20248c2ecf20Sopenharmony_ci	.mac_ops		= &e82571_mac_ops,
20258c2ecf20Sopenharmony_ci	.phy_ops		= &e82_phy_ops_bm,
20268c2ecf20Sopenharmony_ci	.nvm_ops		= &e82571_nvm_ops,
20278c2ecf20Sopenharmony_ci};
20288c2ecf20Sopenharmony_ci
20298c2ecf20Sopenharmony_ciconst struct e1000_info e1000_82583_info = {
20308c2ecf20Sopenharmony_ci	.mac			= e1000_82583,
20318c2ecf20Sopenharmony_ci	.flags			= FLAG_HAS_HW_VLAN_FILTER
20328c2ecf20Sopenharmony_ci				  | FLAG_HAS_WOL
20338c2ecf20Sopenharmony_ci				  | FLAG_HAS_HW_TIMESTAMP
20348c2ecf20Sopenharmony_ci				  | FLAG_APME_IN_CTRL3
20358c2ecf20Sopenharmony_ci				  | FLAG_HAS_SMART_POWER_DOWN
20368c2ecf20Sopenharmony_ci				  | FLAG_HAS_AMT
20378c2ecf20Sopenharmony_ci				  | FLAG_HAS_JUMBO_FRAMES
20388c2ecf20Sopenharmony_ci				  | FLAG_HAS_CTRLEXT_ON_LOAD,
20398c2ecf20Sopenharmony_ci	.flags2			= FLAG2_DISABLE_ASPM_L0S
20408c2ecf20Sopenharmony_ci				  | FLAG2_DISABLE_ASPM_L1
20418c2ecf20Sopenharmony_ci				  | FLAG2_NO_DISABLE_RX
20428c2ecf20Sopenharmony_ci				  | FLAG2_CHECK_SYSTIM_OVERFLOW,
20438c2ecf20Sopenharmony_ci	.pba			= 32,
20448c2ecf20Sopenharmony_ci	.max_hw_frame_size	= DEFAULT_JUMBO,
20458c2ecf20Sopenharmony_ci	.get_variants		= e1000_get_variants_82571,
20468c2ecf20Sopenharmony_ci	.mac_ops		= &e82571_mac_ops,
20478c2ecf20Sopenharmony_ci	.phy_ops		= &e82_phy_ops_bm,
20488c2ecf20Sopenharmony_ci	.nvm_ops		= &e82571_nvm_ops,
20498c2ecf20Sopenharmony_ci};
2050