18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2006 Intel Corporation. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci/* e1000_hw.c
58c2ecf20Sopenharmony_ci * Shared functions for accessing and configuring the MAC
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "e1000.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_cistatic s32 e1000_check_downshift(struct e1000_hw *hw);
118c2ecf20Sopenharmony_cistatic s32 e1000_check_polarity(struct e1000_hw *hw,
128c2ecf20Sopenharmony_ci				e1000_rev_polarity *polarity);
138c2ecf20Sopenharmony_cistatic void e1000_clear_hw_cntrs(struct e1000_hw *hw);
148c2ecf20Sopenharmony_cistatic void e1000_clear_vfta(struct e1000_hw *hw);
158c2ecf20Sopenharmony_cistatic s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
168c2ecf20Sopenharmony_ci					      bool link_up);
178c2ecf20Sopenharmony_cistatic s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
188c2ecf20Sopenharmony_cistatic s32 e1000_detect_gig_phy(struct e1000_hw *hw);
198c2ecf20Sopenharmony_cistatic s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
208c2ecf20Sopenharmony_cistatic s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
218c2ecf20Sopenharmony_ci				  u16 *max_length);
228c2ecf20Sopenharmony_cistatic s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
238c2ecf20Sopenharmony_cistatic s32 e1000_id_led_init(struct e1000_hw *hw);
248c2ecf20Sopenharmony_cistatic void e1000_init_rx_addrs(struct e1000_hw *hw);
258c2ecf20Sopenharmony_cistatic s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
268c2ecf20Sopenharmony_ci				  struct e1000_phy_info *phy_info);
278c2ecf20Sopenharmony_cistatic s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
288c2ecf20Sopenharmony_ci				  struct e1000_phy_info *phy_info);
298c2ecf20Sopenharmony_cistatic s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
308c2ecf20Sopenharmony_cistatic s32 e1000_wait_autoneg(struct e1000_hw *hw);
318c2ecf20Sopenharmony_cistatic void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value);
328c2ecf20Sopenharmony_cistatic s32 e1000_set_phy_type(struct e1000_hw *hw);
338c2ecf20Sopenharmony_cistatic void e1000_phy_init_script(struct e1000_hw *hw);
348c2ecf20Sopenharmony_cistatic s32 e1000_setup_copper_link(struct e1000_hw *hw);
358c2ecf20Sopenharmony_cistatic s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
368c2ecf20Sopenharmony_cistatic s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
378c2ecf20Sopenharmony_cistatic s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw);
388c2ecf20Sopenharmony_cistatic s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
398c2ecf20Sopenharmony_cistatic void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
408c2ecf20Sopenharmony_cistatic void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
418c2ecf20Sopenharmony_cistatic void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count);
428c2ecf20Sopenharmony_cistatic u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
438c2ecf20Sopenharmony_cistatic s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
448c2ecf20Sopenharmony_cistatic s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
458c2ecf20Sopenharmony_ci				  u16 words, u16 *data);
468c2ecf20Sopenharmony_cistatic s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
478c2ecf20Sopenharmony_ci					u16 words, u16 *data);
488c2ecf20Sopenharmony_cistatic s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
498c2ecf20Sopenharmony_cistatic void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd);
508c2ecf20Sopenharmony_cistatic void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd);
518c2ecf20Sopenharmony_cistatic void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count);
528c2ecf20Sopenharmony_cistatic s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
538c2ecf20Sopenharmony_ci				  u16 phy_data);
548c2ecf20Sopenharmony_cistatic s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
558c2ecf20Sopenharmony_ci				 u16 *phy_data);
568c2ecf20Sopenharmony_cistatic u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
578c2ecf20Sopenharmony_cistatic s32 e1000_acquire_eeprom(struct e1000_hw *hw);
588c2ecf20Sopenharmony_cistatic void e1000_release_eeprom(struct e1000_hw *hw);
598c2ecf20Sopenharmony_cistatic void e1000_standby_eeprom(struct e1000_hw *hw);
608c2ecf20Sopenharmony_cistatic s32 e1000_set_vco_speed(struct e1000_hw *hw);
618c2ecf20Sopenharmony_cistatic s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw);
628c2ecf20Sopenharmony_cistatic s32 e1000_set_phy_mode(struct e1000_hw *hw);
638c2ecf20Sopenharmony_cistatic s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
648c2ecf20Sopenharmony_ci				u16 *data);
658c2ecf20Sopenharmony_cistatic s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
668c2ecf20Sopenharmony_ci				 u16 *data);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/* IGP cable length table */
698c2ecf20Sopenharmony_cistatic const
708c2ecf20Sopenharmony_ciu16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = {
718c2ecf20Sopenharmony_ci	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
728c2ecf20Sopenharmony_ci	5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
738c2ecf20Sopenharmony_ci	25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
748c2ecf20Sopenharmony_ci	40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,
758c2ecf20Sopenharmony_ci	60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,
768c2ecf20Sopenharmony_ci	90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100,
778c2ecf20Sopenharmony_ci	    100,
788c2ecf20Sopenharmony_ci	100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
798c2ecf20Sopenharmony_ci	    110, 110,
808c2ecf20Sopenharmony_ci	110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120,
818c2ecf20Sopenharmony_ci	    120, 120
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(e1000_eeprom_lock);
858c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(e1000_phy_lock);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/**
888c2ecf20Sopenharmony_ci * e1000_set_phy_type - Set the phy type member in the hw struct.
898c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
908c2ecf20Sopenharmony_ci */
918c2ecf20Sopenharmony_cistatic s32 e1000_set_phy_type(struct e1000_hw *hw)
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_undefined)
948c2ecf20Sopenharmony_ci		return -E1000_ERR_PHY_TYPE;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	switch (hw->phy_id) {
978c2ecf20Sopenharmony_ci	case M88E1000_E_PHY_ID:
988c2ecf20Sopenharmony_ci	case M88E1000_I_PHY_ID:
998c2ecf20Sopenharmony_ci	case M88E1011_I_PHY_ID:
1008c2ecf20Sopenharmony_ci	case M88E1111_I_PHY_ID:
1018c2ecf20Sopenharmony_ci	case M88E1118_E_PHY_ID:
1028c2ecf20Sopenharmony_ci		hw->phy_type = e1000_phy_m88;
1038c2ecf20Sopenharmony_ci		break;
1048c2ecf20Sopenharmony_ci	case IGP01E1000_I_PHY_ID:
1058c2ecf20Sopenharmony_ci		if (hw->mac_type == e1000_82541 ||
1068c2ecf20Sopenharmony_ci		    hw->mac_type == e1000_82541_rev_2 ||
1078c2ecf20Sopenharmony_ci		    hw->mac_type == e1000_82547 ||
1088c2ecf20Sopenharmony_ci		    hw->mac_type == e1000_82547_rev_2)
1098c2ecf20Sopenharmony_ci			hw->phy_type = e1000_phy_igp;
1108c2ecf20Sopenharmony_ci		break;
1118c2ecf20Sopenharmony_ci	case RTL8211B_PHY_ID:
1128c2ecf20Sopenharmony_ci		hw->phy_type = e1000_phy_8211;
1138c2ecf20Sopenharmony_ci		break;
1148c2ecf20Sopenharmony_ci	case RTL8201N_PHY_ID:
1158c2ecf20Sopenharmony_ci		hw->phy_type = e1000_phy_8201;
1168c2ecf20Sopenharmony_ci		break;
1178c2ecf20Sopenharmony_ci	default:
1188c2ecf20Sopenharmony_ci		/* Should never have loaded on this device */
1198c2ecf20Sopenharmony_ci		hw->phy_type = e1000_phy_undefined;
1208c2ecf20Sopenharmony_ci		return -E1000_ERR_PHY_TYPE;
1218c2ecf20Sopenharmony_ci	}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci/**
1278c2ecf20Sopenharmony_ci * e1000_phy_init_script - IGP phy init script - initializes the GbE PHY
1288c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
1298c2ecf20Sopenharmony_ci */
1308c2ecf20Sopenharmony_cistatic void e1000_phy_init_script(struct e1000_hw *hw)
1318c2ecf20Sopenharmony_ci{
1328c2ecf20Sopenharmony_ci	u16 phy_saved_data;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	if (hw->phy_init_script) {
1358c2ecf20Sopenharmony_ci		msleep(20);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci		/* Save off the current value of register 0x2F5B to be restored
1388c2ecf20Sopenharmony_ci		 * at the end of this routine.
1398c2ecf20Sopenharmony_ci		 */
1408c2ecf20Sopenharmony_ci		e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci		/* Disabled the PHY transmitter */
1438c2ecf20Sopenharmony_ci		e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
1448c2ecf20Sopenharmony_ci		msleep(20);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci		e1000_write_phy_reg(hw, 0x0000, 0x0140);
1478c2ecf20Sopenharmony_ci		msleep(5);
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci		switch (hw->mac_type) {
1508c2ecf20Sopenharmony_ci		case e1000_82541:
1518c2ecf20Sopenharmony_ci		case e1000_82547:
1528c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F95, 0x0001);
1538c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F71, 0xBD21);
1548c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F79, 0x0018);
1558c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F30, 0x1600);
1568c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F31, 0x0014);
1578c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F32, 0x161C);
1588c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F94, 0x0003);
1598c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F96, 0x003F);
1608c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, 0x2010, 0x0008);
1618c2ecf20Sopenharmony_ci			break;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci		case e1000_82541_rev_2:
1648c2ecf20Sopenharmony_ci		case e1000_82547_rev_2:
1658c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F73, 0x0099);
1668c2ecf20Sopenharmony_ci			break;
1678c2ecf20Sopenharmony_ci		default:
1688c2ecf20Sopenharmony_ci			break;
1698c2ecf20Sopenharmony_ci		}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci		e1000_write_phy_reg(hw, 0x0000, 0x3300);
1728c2ecf20Sopenharmony_ci		msleep(20);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci		/* Now enable the transmitter */
1758c2ecf20Sopenharmony_ci		e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci		if (hw->mac_type == e1000_82547) {
1788c2ecf20Sopenharmony_ci			u16 fused, fine, coarse;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci			/* Move to analog registers page */
1818c2ecf20Sopenharmony_ci			e1000_read_phy_reg(hw,
1828c2ecf20Sopenharmony_ci					   IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
1838c2ecf20Sopenharmony_ci					   &fused);
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci			if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
1868c2ecf20Sopenharmony_ci				e1000_read_phy_reg(hw,
1878c2ecf20Sopenharmony_ci						   IGP01E1000_ANALOG_FUSE_STATUS,
1888c2ecf20Sopenharmony_ci						   &fused);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci				fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
1918c2ecf20Sopenharmony_ci				coarse =
1928c2ecf20Sopenharmony_ci				    fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci				if (coarse >
1958c2ecf20Sopenharmony_ci				    IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
1968c2ecf20Sopenharmony_ci					coarse -=
1978c2ecf20Sopenharmony_ci					    IGP01E1000_ANALOG_FUSE_COARSE_10;
1988c2ecf20Sopenharmony_ci					fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
1998c2ecf20Sopenharmony_ci				} else if (coarse ==
2008c2ecf20Sopenharmony_ci					   IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
2018c2ecf20Sopenharmony_ci					fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci				fused =
2048c2ecf20Sopenharmony_ci				    (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
2058c2ecf20Sopenharmony_ci				    (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
2068c2ecf20Sopenharmony_ci				    (coarse &
2078c2ecf20Sopenharmony_ci				     IGP01E1000_ANALOG_FUSE_COARSE_MASK);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci				e1000_write_phy_reg(hw,
2108c2ecf20Sopenharmony_ci						    IGP01E1000_ANALOG_FUSE_CONTROL,
2118c2ecf20Sopenharmony_ci						    fused);
2128c2ecf20Sopenharmony_ci				e1000_write_phy_reg(hw,
2138c2ecf20Sopenharmony_ci						    IGP01E1000_ANALOG_FUSE_BYPASS,
2148c2ecf20Sopenharmony_ci						    IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
2158c2ecf20Sopenharmony_ci			}
2168c2ecf20Sopenharmony_ci		}
2178c2ecf20Sopenharmony_ci	}
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci/**
2218c2ecf20Sopenharmony_ci * e1000_set_mac_type - Set the mac type member in the hw struct.
2228c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
2238c2ecf20Sopenharmony_ci */
2248c2ecf20Sopenharmony_cis32 e1000_set_mac_type(struct e1000_hw *hw)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	switch (hw->device_id) {
2278c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82542:
2288c2ecf20Sopenharmony_ci		switch (hw->revision_id) {
2298c2ecf20Sopenharmony_ci		case E1000_82542_2_0_REV_ID:
2308c2ecf20Sopenharmony_ci			hw->mac_type = e1000_82542_rev2_0;
2318c2ecf20Sopenharmony_ci			break;
2328c2ecf20Sopenharmony_ci		case E1000_82542_2_1_REV_ID:
2338c2ecf20Sopenharmony_ci			hw->mac_type = e1000_82542_rev2_1;
2348c2ecf20Sopenharmony_ci			break;
2358c2ecf20Sopenharmony_ci		default:
2368c2ecf20Sopenharmony_ci			/* Invalid 82542 revision ID */
2378c2ecf20Sopenharmony_ci			return -E1000_ERR_MAC_TYPE;
2388c2ecf20Sopenharmony_ci		}
2398c2ecf20Sopenharmony_ci		break;
2408c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82543GC_FIBER:
2418c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82543GC_COPPER:
2428c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82543;
2438c2ecf20Sopenharmony_ci		break;
2448c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82544EI_COPPER:
2458c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82544EI_FIBER:
2468c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82544GC_COPPER:
2478c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82544GC_LOM:
2488c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82544;
2498c2ecf20Sopenharmony_ci		break;
2508c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82540EM:
2518c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82540EM_LOM:
2528c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82540EP:
2538c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82540EP_LOM:
2548c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82540EP_LP:
2558c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82540;
2568c2ecf20Sopenharmony_ci		break;
2578c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82545EM_COPPER:
2588c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82545EM_FIBER:
2598c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82545;
2608c2ecf20Sopenharmony_ci		break;
2618c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82545GM_COPPER:
2628c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82545GM_FIBER:
2638c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82545GM_SERDES:
2648c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82545_rev_3;
2658c2ecf20Sopenharmony_ci		break;
2668c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546EB_COPPER:
2678c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546EB_FIBER:
2688c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546EB_QUAD_COPPER:
2698c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82546;
2708c2ecf20Sopenharmony_ci		break;
2718c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546GB_COPPER:
2728c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546GB_FIBER:
2738c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546GB_SERDES:
2748c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546GB_PCIE:
2758c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546GB_QUAD_COPPER:
2768c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
2778c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82546_rev_3;
2788c2ecf20Sopenharmony_ci		break;
2798c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541EI:
2808c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541EI_MOBILE:
2818c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541ER_LOM:
2828c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82541;
2838c2ecf20Sopenharmony_ci		break;
2848c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541ER:
2858c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541GI:
2868c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541GI_LF:
2878c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541GI_MOBILE:
2888c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82541_rev_2;
2898c2ecf20Sopenharmony_ci		break;
2908c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82547EI:
2918c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82547EI_MOBILE:
2928c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82547;
2938c2ecf20Sopenharmony_ci		break;
2948c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82547GI:
2958c2ecf20Sopenharmony_ci		hw->mac_type = e1000_82547_rev_2;
2968c2ecf20Sopenharmony_ci		break;
2978c2ecf20Sopenharmony_ci	case E1000_DEV_ID_INTEL_CE4100_GBE:
2988c2ecf20Sopenharmony_ci		hw->mac_type = e1000_ce4100;
2998c2ecf20Sopenharmony_ci		break;
3008c2ecf20Sopenharmony_ci	default:
3018c2ecf20Sopenharmony_ci		/* Should never have loaded on this device */
3028c2ecf20Sopenharmony_ci		return -E1000_ERR_MAC_TYPE;
3038c2ecf20Sopenharmony_ci	}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
3068c2ecf20Sopenharmony_ci	case e1000_82541:
3078c2ecf20Sopenharmony_ci	case e1000_82547:
3088c2ecf20Sopenharmony_ci	case e1000_82541_rev_2:
3098c2ecf20Sopenharmony_ci	case e1000_82547_rev_2:
3108c2ecf20Sopenharmony_ci		hw->asf_firmware_present = true;
3118c2ecf20Sopenharmony_ci		break;
3128c2ecf20Sopenharmony_ci	default:
3138c2ecf20Sopenharmony_ci		break;
3148c2ecf20Sopenharmony_ci	}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	/* The 82543 chip does not count tx_carrier_errors properly in
3178c2ecf20Sopenharmony_ci	 * FD mode
3188c2ecf20Sopenharmony_ci	 */
3198c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82543)
3208c2ecf20Sopenharmony_ci		hw->bad_tx_carr_stats_fd = true;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	if (hw->mac_type > e1000_82544)
3238c2ecf20Sopenharmony_ci		hw->has_smbus = true;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
3268c2ecf20Sopenharmony_ci}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci/**
3298c2ecf20Sopenharmony_ci * e1000_set_media_type - Set media type and TBI compatibility.
3308c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
3318c2ecf20Sopenharmony_ci */
3328c2ecf20Sopenharmony_civoid e1000_set_media_type(struct e1000_hw *hw)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	u32 status;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	if (hw->mac_type != e1000_82543) {
3378c2ecf20Sopenharmony_ci		/* tbi_compatibility is only valid on 82543 */
3388c2ecf20Sopenharmony_ci		hw->tbi_compatibility_en = false;
3398c2ecf20Sopenharmony_ci	}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	switch (hw->device_id) {
3428c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82545GM_SERDES:
3438c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546GB_SERDES:
3448c2ecf20Sopenharmony_ci		hw->media_type = e1000_media_type_internal_serdes;
3458c2ecf20Sopenharmony_ci		break;
3468c2ecf20Sopenharmony_ci	default:
3478c2ecf20Sopenharmony_ci		switch (hw->mac_type) {
3488c2ecf20Sopenharmony_ci		case e1000_82542_rev2_0:
3498c2ecf20Sopenharmony_ci		case e1000_82542_rev2_1:
3508c2ecf20Sopenharmony_ci			hw->media_type = e1000_media_type_fiber;
3518c2ecf20Sopenharmony_ci			break;
3528c2ecf20Sopenharmony_ci		case e1000_ce4100:
3538c2ecf20Sopenharmony_ci			hw->media_type = e1000_media_type_copper;
3548c2ecf20Sopenharmony_ci			break;
3558c2ecf20Sopenharmony_ci		default:
3568c2ecf20Sopenharmony_ci			status = er32(STATUS);
3578c2ecf20Sopenharmony_ci			if (status & E1000_STATUS_TBIMODE) {
3588c2ecf20Sopenharmony_ci				hw->media_type = e1000_media_type_fiber;
3598c2ecf20Sopenharmony_ci				/* tbi_compatibility not valid on fiber */
3608c2ecf20Sopenharmony_ci				hw->tbi_compatibility_en = false;
3618c2ecf20Sopenharmony_ci			} else {
3628c2ecf20Sopenharmony_ci				hw->media_type = e1000_media_type_copper;
3638c2ecf20Sopenharmony_ci			}
3648c2ecf20Sopenharmony_ci			break;
3658c2ecf20Sopenharmony_ci		}
3668c2ecf20Sopenharmony_ci	}
3678c2ecf20Sopenharmony_ci}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci/**
3708c2ecf20Sopenharmony_ci * e1000_reset_hw - reset the hardware completely
3718c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
3728c2ecf20Sopenharmony_ci *
3738c2ecf20Sopenharmony_ci * Reset the transmit and receive units; mask and clear all interrupts.
3748c2ecf20Sopenharmony_ci */
3758c2ecf20Sopenharmony_cis32 e1000_reset_hw(struct e1000_hw *hw)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	u32 ctrl;
3788c2ecf20Sopenharmony_ci	u32 ctrl_ext;
3798c2ecf20Sopenharmony_ci	u32 manc;
3808c2ecf20Sopenharmony_ci	u32 led_ctrl;
3818c2ecf20Sopenharmony_ci	s32 ret_val;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	/* For 82542 (rev 2.0), disable MWI before issuing a device reset */
3848c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0) {
3858c2ecf20Sopenharmony_ci		e_dbg("Disabling MWI on 82542 rev 2.0\n");
3868c2ecf20Sopenharmony_ci		e1000_pci_clear_mwi(hw);
3878c2ecf20Sopenharmony_ci	}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	/* Clear interrupt mask to stop board from generating interrupts */
3908c2ecf20Sopenharmony_ci	e_dbg("Masking off all interrupts\n");
3918c2ecf20Sopenharmony_ci	ew32(IMC, 0xffffffff);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	/* Disable the Transmit and Receive units.  Then delay to allow
3948c2ecf20Sopenharmony_ci	 * any pending transactions to complete before we hit the MAC with
3958c2ecf20Sopenharmony_ci	 * the global reset.
3968c2ecf20Sopenharmony_ci	 */
3978c2ecf20Sopenharmony_ci	ew32(RCTL, 0);
3988c2ecf20Sopenharmony_ci	ew32(TCTL, E1000_TCTL_PSP);
3998c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	/* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
4028c2ecf20Sopenharmony_ci	hw->tbi_compatibility_on = false;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	/* Delay to allow any outstanding PCI transactions to complete before
4058c2ecf20Sopenharmony_ci	 * resetting the device
4068c2ecf20Sopenharmony_ci	 */
4078c2ecf20Sopenharmony_ci	msleep(10);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	/* Must reset the PHY before resetting the MAC */
4128c2ecf20Sopenharmony_ci	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
4138c2ecf20Sopenharmony_ci		ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST));
4148c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
4158c2ecf20Sopenharmony_ci		msleep(5);
4168c2ecf20Sopenharmony_ci	}
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	/* Issue a global reset to the MAC.  This will reset the chip's
4198c2ecf20Sopenharmony_ci	 * transmit, receive, DMA, and link units.  It will not effect
4208c2ecf20Sopenharmony_ci	 * the current PCI configuration.  The global reset bit is self-
4218c2ecf20Sopenharmony_ci	 * clearing, and should clear within a microsecond.
4228c2ecf20Sopenharmony_ci	 */
4238c2ecf20Sopenharmony_ci	e_dbg("Issuing a global reset to MAC\n");
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
4268c2ecf20Sopenharmony_ci	case e1000_82544:
4278c2ecf20Sopenharmony_ci	case e1000_82540:
4288c2ecf20Sopenharmony_ci	case e1000_82545:
4298c2ecf20Sopenharmony_ci	case e1000_82546:
4308c2ecf20Sopenharmony_ci	case e1000_82541:
4318c2ecf20Sopenharmony_ci	case e1000_82541_rev_2:
4328c2ecf20Sopenharmony_ci		/* These controllers can't ack the 64-bit write when issuing the
4338c2ecf20Sopenharmony_ci		 * reset, so use IO-mapping as a workaround to issue the reset
4348c2ecf20Sopenharmony_ci		 */
4358c2ecf20Sopenharmony_ci		E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
4368c2ecf20Sopenharmony_ci		break;
4378c2ecf20Sopenharmony_ci	case e1000_82545_rev_3:
4388c2ecf20Sopenharmony_ci	case e1000_82546_rev_3:
4398c2ecf20Sopenharmony_ci		/* Reset is performed on a shadow of the control register */
4408c2ecf20Sopenharmony_ci		ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST));
4418c2ecf20Sopenharmony_ci		break;
4428c2ecf20Sopenharmony_ci	case e1000_ce4100:
4438c2ecf20Sopenharmony_ci	default:
4448c2ecf20Sopenharmony_ci		ew32(CTRL, (ctrl | E1000_CTRL_RST));
4458c2ecf20Sopenharmony_ci		break;
4468c2ecf20Sopenharmony_ci	}
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	/* After MAC reset, force reload of EEPROM to restore power-on settings
4498c2ecf20Sopenharmony_ci	 * to device.  Later controllers reload the EEPROM automatically, so
4508c2ecf20Sopenharmony_ci	 * just wait for reload to complete.
4518c2ecf20Sopenharmony_ci	 */
4528c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
4538c2ecf20Sopenharmony_ci	case e1000_82542_rev2_0:
4548c2ecf20Sopenharmony_ci	case e1000_82542_rev2_1:
4558c2ecf20Sopenharmony_ci	case e1000_82543:
4568c2ecf20Sopenharmony_ci	case e1000_82544:
4578c2ecf20Sopenharmony_ci		/* Wait for reset to complete */
4588c2ecf20Sopenharmony_ci		udelay(10);
4598c2ecf20Sopenharmony_ci		ctrl_ext = er32(CTRL_EXT);
4608c2ecf20Sopenharmony_ci		ctrl_ext |= E1000_CTRL_EXT_EE_RST;
4618c2ecf20Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
4628c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
4638c2ecf20Sopenharmony_ci		/* Wait for EEPROM reload */
4648c2ecf20Sopenharmony_ci		msleep(2);
4658c2ecf20Sopenharmony_ci		break;
4668c2ecf20Sopenharmony_ci	case e1000_82541:
4678c2ecf20Sopenharmony_ci	case e1000_82541_rev_2:
4688c2ecf20Sopenharmony_ci	case e1000_82547:
4698c2ecf20Sopenharmony_ci	case e1000_82547_rev_2:
4708c2ecf20Sopenharmony_ci		/* Wait for EEPROM reload */
4718c2ecf20Sopenharmony_ci		msleep(20);
4728c2ecf20Sopenharmony_ci		break;
4738c2ecf20Sopenharmony_ci	default:
4748c2ecf20Sopenharmony_ci		/* Auto read done will delay 5ms or poll based on mac type */
4758c2ecf20Sopenharmony_ci		ret_val = e1000_get_auto_rd_done(hw);
4768c2ecf20Sopenharmony_ci		if (ret_val)
4778c2ecf20Sopenharmony_ci			return ret_val;
4788c2ecf20Sopenharmony_ci		break;
4798c2ecf20Sopenharmony_ci	}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	/* Disable HW ARPs on ASF enabled adapters */
4828c2ecf20Sopenharmony_ci	if (hw->mac_type >= e1000_82540) {
4838c2ecf20Sopenharmony_ci		manc = er32(MANC);
4848c2ecf20Sopenharmony_ci		manc &= ~(E1000_MANC_ARP_EN);
4858c2ecf20Sopenharmony_ci		ew32(MANC, manc);
4868c2ecf20Sopenharmony_ci	}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
4898c2ecf20Sopenharmony_ci		e1000_phy_init_script(hw);
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci		/* Configure activity LED after PHY reset */
4928c2ecf20Sopenharmony_ci		led_ctrl = er32(LEDCTL);
4938c2ecf20Sopenharmony_ci		led_ctrl &= IGP_ACTIVITY_LED_MASK;
4948c2ecf20Sopenharmony_ci		led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
4958c2ecf20Sopenharmony_ci		ew32(LEDCTL, led_ctrl);
4968c2ecf20Sopenharmony_ci	}
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	/* Clear interrupt mask to stop board from generating interrupts */
4998c2ecf20Sopenharmony_ci	e_dbg("Masking off all interrupts\n");
5008c2ecf20Sopenharmony_ci	ew32(IMC, 0xffffffff);
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	/* Clear any pending interrupt events. */
5038c2ecf20Sopenharmony_ci	er32(ICR);
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	/* If MWI was previously enabled, reenable it. */
5068c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0) {
5078c2ecf20Sopenharmony_ci		if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
5088c2ecf20Sopenharmony_ci			e1000_pci_set_mwi(hw);
5098c2ecf20Sopenharmony_ci	}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
5128c2ecf20Sopenharmony_ci}
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci/**
5158c2ecf20Sopenharmony_ci * e1000_init_hw - Performs basic configuration of the adapter.
5168c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
5178c2ecf20Sopenharmony_ci *
5188c2ecf20Sopenharmony_ci * Assumes that the controller has previously been reset and is in a
5198c2ecf20Sopenharmony_ci * post-reset uninitialized state. Initializes the receive address registers,
5208c2ecf20Sopenharmony_ci * multicast table, and VLAN filter table. Calls routines to setup link
5218c2ecf20Sopenharmony_ci * configuration and flow control settings. Clears all on-chip counters. Leaves
5228c2ecf20Sopenharmony_ci * the transmit and receive units disabled and uninitialized.
5238c2ecf20Sopenharmony_ci */
5248c2ecf20Sopenharmony_cis32 e1000_init_hw(struct e1000_hw *hw)
5258c2ecf20Sopenharmony_ci{
5268c2ecf20Sopenharmony_ci	u32 ctrl;
5278c2ecf20Sopenharmony_ci	u32 i;
5288c2ecf20Sopenharmony_ci	s32 ret_val;
5298c2ecf20Sopenharmony_ci	u32 mta_size;
5308c2ecf20Sopenharmony_ci	u32 ctrl_ext;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	/* Initialize Identification LED */
5338c2ecf20Sopenharmony_ci	ret_val = e1000_id_led_init(hw);
5348c2ecf20Sopenharmony_ci	if (ret_val) {
5358c2ecf20Sopenharmony_ci		e_dbg("Error Initializing Identification LED\n");
5368c2ecf20Sopenharmony_ci		return ret_val;
5378c2ecf20Sopenharmony_ci	}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	/* Set the media type and TBI compatibility */
5408c2ecf20Sopenharmony_ci	e1000_set_media_type(hw);
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	/* Disabling VLAN filtering. */
5438c2ecf20Sopenharmony_ci	e_dbg("Initializing the IEEE VLAN\n");
5448c2ecf20Sopenharmony_ci	if (hw->mac_type < e1000_82545_rev_3)
5458c2ecf20Sopenharmony_ci		ew32(VET, 0);
5468c2ecf20Sopenharmony_ci	e1000_clear_vfta(hw);
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
5498c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0) {
5508c2ecf20Sopenharmony_ci		e_dbg("Disabling MWI on 82542 rev 2.0\n");
5518c2ecf20Sopenharmony_ci		e1000_pci_clear_mwi(hw);
5528c2ecf20Sopenharmony_ci		ew32(RCTL, E1000_RCTL_RST);
5538c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
5548c2ecf20Sopenharmony_ci		msleep(5);
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	/* Setup the receive address. This involves initializing all of the
5588c2ecf20Sopenharmony_ci	 * Receive Address Registers (RARs 0 - 15).
5598c2ecf20Sopenharmony_ci	 */
5608c2ecf20Sopenharmony_ci	e1000_init_rx_addrs(hw);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	/* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
5638c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0) {
5648c2ecf20Sopenharmony_ci		ew32(RCTL, 0);
5658c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
5668c2ecf20Sopenharmony_ci		msleep(1);
5678c2ecf20Sopenharmony_ci		if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
5688c2ecf20Sopenharmony_ci			e1000_pci_set_mwi(hw);
5698c2ecf20Sopenharmony_ci	}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	/* Zero out the Multicast HASH table */
5728c2ecf20Sopenharmony_ci	e_dbg("Zeroing the MTA\n");
5738c2ecf20Sopenharmony_ci	mta_size = E1000_MC_TBL_SIZE;
5748c2ecf20Sopenharmony_ci	for (i = 0; i < mta_size; i++) {
5758c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
5768c2ecf20Sopenharmony_ci		/* use write flush to prevent Memory Write Block (MWB) from
5778c2ecf20Sopenharmony_ci		 * occurring when accessing our register space
5788c2ecf20Sopenharmony_ci		 */
5798c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
5808c2ecf20Sopenharmony_ci	}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	/* Set the PCI priority bit correctly in the CTRL register.  This
5838c2ecf20Sopenharmony_ci	 * determines if the adapter gives priority to receives, or if it
5848c2ecf20Sopenharmony_ci	 * gives equal priority to transmits and receives.  Valid only on
5858c2ecf20Sopenharmony_ci	 * 82542 and 82543 silicon.
5868c2ecf20Sopenharmony_ci	 */
5878c2ecf20Sopenharmony_ci	if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
5888c2ecf20Sopenharmony_ci		ctrl = er32(CTRL);
5898c2ecf20Sopenharmony_ci		ew32(CTRL, ctrl | E1000_CTRL_PRIOR);
5908c2ecf20Sopenharmony_ci	}
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
5938c2ecf20Sopenharmony_ci	case e1000_82545_rev_3:
5948c2ecf20Sopenharmony_ci	case e1000_82546_rev_3:
5958c2ecf20Sopenharmony_ci		break;
5968c2ecf20Sopenharmony_ci	default:
5978c2ecf20Sopenharmony_ci		/* Workaround for PCI-X problem when BIOS sets MMRBC
5988c2ecf20Sopenharmony_ci		 * incorrectly.
5998c2ecf20Sopenharmony_ci		 */
6008c2ecf20Sopenharmony_ci		if (hw->bus_type == e1000_bus_type_pcix &&
6018c2ecf20Sopenharmony_ci		    e1000_pcix_get_mmrbc(hw) > 2048)
6028c2ecf20Sopenharmony_ci			e1000_pcix_set_mmrbc(hw, 2048);
6038c2ecf20Sopenharmony_ci		break;
6048c2ecf20Sopenharmony_ci	}
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	/* Call a subroutine to configure the link and setup flow control. */
6078c2ecf20Sopenharmony_ci	ret_val = e1000_setup_link(hw);
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	/* Set the transmit descriptor write-back policy */
6108c2ecf20Sopenharmony_ci	if (hw->mac_type > e1000_82544) {
6118c2ecf20Sopenharmony_ci		ctrl = er32(TXDCTL);
6128c2ecf20Sopenharmony_ci		ctrl =
6138c2ecf20Sopenharmony_ci		    (ctrl & ~E1000_TXDCTL_WTHRESH) |
6148c2ecf20Sopenharmony_ci		    E1000_TXDCTL_FULL_TX_DESC_WB;
6158c2ecf20Sopenharmony_ci		ew32(TXDCTL, ctrl);
6168c2ecf20Sopenharmony_ci	}
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	/* Clear all of the statistics registers (clear on read).  It is
6198c2ecf20Sopenharmony_ci	 * important that we do this after we have tried to establish link
6208c2ecf20Sopenharmony_ci	 * because the symbol error count will increment wildly if there
6218c2ecf20Sopenharmony_ci	 * is no link.
6228c2ecf20Sopenharmony_ci	 */
6238c2ecf20Sopenharmony_ci	e1000_clear_hw_cntrs(hw);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
6268c2ecf20Sopenharmony_ci	    hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
6278c2ecf20Sopenharmony_ci		ctrl_ext = er32(CTRL_EXT);
6288c2ecf20Sopenharmony_ci		/* Relaxed ordering must be disabled to avoid a parity
6298c2ecf20Sopenharmony_ci		 * error crash in a PCI slot.
6308c2ecf20Sopenharmony_ci		 */
6318c2ecf20Sopenharmony_ci		ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
6328c2ecf20Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
6338c2ecf20Sopenharmony_ci	}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	return ret_val;
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci/**
6398c2ecf20Sopenharmony_ci * e1000_adjust_serdes_amplitude - Adjust SERDES output amplitude based on EEPROM setting.
6408c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code.
6418c2ecf20Sopenharmony_ci */
6428c2ecf20Sopenharmony_cistatic s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
6438c2ecf20Sopenharmony_ci{
6448c2ecf20Sopenharmony_ci	u16 eeprom_data;
6458c2ecf20Sopenharmony_ci	s32 ret_val;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	if (hw->media_type != e1000_media_type_internal_serdes)
6488c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
6518c2ecf20Sopenharmony_ci	case e1000_82545_rev_3:
6528c2ecf20Sopenharmony_ci	case e1000_82546_rev_3:
6538c2ecf20Sopenharmony_ci		break;
6548c2ecf20Sopenharmony_ci	default:
6558c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
6568c2ecf20Sopenharmony_ci	}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1,
6598c2ecf20Sopenharmony_ci				    &eeprom_data);
6608c2ecf20Sopenharmony_ci	if (ret_val)
6618c2ecf20Sopenharmony_ci		return ret_val;
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	if (eeprom_data != EEPROM_RESERVED_WORD) {
6648c2ecf20Sopenharmony_ci		/* Adjust SERDES output amplitude only. */
6658c2ecf20Sopenharmony_ci		eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
6668c2ecf20Sopenharmony_ci		ret_val =
6678c2ecf20Sopenharmony_ci		    e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
6688c2ecf20Sopenharmony_ci		if (ret_val)
6698c2ecf20Sopenharmony_ci			return ret_val;
6708c2ecf20Sopenharmony_ci	}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
6738c2ecf20Sopenharmony_ci}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci/**
6768c2ecf20Sopenharmony_ci * e1000_setup_link - Configures flow control and link settings.
6778c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
6788c2ecf20Sopenharmony_ci *
6798c2ecf20Sopenharmony_ci * Determines which flow control settings to use. Calls the appropriate media-
6808c2ecf20Sopenharmony_ci * specific link configuration function. Configures the flow control settings.
6818c2ecf20Sopenharmony_ci * Assuming the adapter has a valid link partner, a valid link should be
6828c2ecf20Sopenharmony_ci * established. Assumes the hardware has previously been reset and the
6838c2ecf20Sopenharmony_ci * transmitter and receiver are not enabled.
6848c2ecf20Sopenharmony_ci */
6858c2ecf20Sopenharmony_cis32 e1000_setup_link(struct e1000_hw *hw)
6868c2ecf20Sopenharmony_ci{
6878c2ecf20Sopenharmony_ci	u32 ctrl_ext;
6888c2ecf20Sopenharmony_ci	s32 ret_val;
6898c2ecf20Sopenharmony_ci	u16 eeprom_data;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	/* Read and store word 0x0F of the EEPROM. This word contains bits
6928c2ecf20Sopenharmony_ci	 * that determine the hardware's default PAUSE (flow control) mode,
6938c2ecf20Sopenharmony_ci	 * a bit that determines whether the HW defaults to enabling or
6948c2ecf20Sopenharmony_ci	 * disabling auto-negotiation, and the direction of the
6958c2ecf20Sopenharmony_ci	 * SW defined pins. If there is no SW over-ride of the flow
6968c2ecf20Sopenharmony_ci	 * control setting, then the variable hw->fc will
6978c2ecf20Sopenharmony_ci	 * be initialized based on a value in the EEPROM.
6988c2ecf20Sopenharmony_ci	 */
6998c2ecf20Sopenharmony_ci	if (hw->fc == E1000_FC_DEFAULT) {
7008c2ecf20Sopenharmony_ci		ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
7018c2ecf20Sopenharmony_ci					    1, &eeprom_data);
7028c2ecf20Sopenharmony_ci		if (ret_val) {
7038c2ecf20Sopenharmony_ci			e_dbg("EEPROM Read Error\n");
7048c2ecf20Sopenharmony_ci			return -E1000_ERR_EEPROM;
7058c2ecf20Sopenharmony_ci		}
7068c2ecf20Sopenharmony_ci		if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
7078c2ecf20Sopenharmony_ci			hw->fc = E1000_FC_NONE;
7088c2ecf20Sopenharmony_ci		else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
7098c2ecf20Sopenharmony_ci			 EEPROM_WORD0F_ASM_DIR)
7108c2ecf20Sopenharmony_ci			hw->fc = E1000_FC_TX_PAUSE;
7118c2ecf20Sopenharmony_ci		else
7128c2ecf20Sopenharmony_ci			hw->fc = E1000_FC_FULL;
7138c2ecf20Sopenharmony_ci	}
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	/* We want to save off the original Flow Control configuration just
7168c2ecf20Sopenharmony_ci	 * in case we get disconnected and then reconnected into a different
7178c2ecf20Sopenharmony_ci	 * hub or switch with different Flow Control capabilities.
7188c2ecf20Sopenharmony_ci	 */
7198c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0)
7208c2ecf20Sopenharmony_ci		hw->fc &= (~E1000_FC_TX_PAUSE);
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
7238c2ecf20Sopenharmony_ci		hw->fc &= (~E1000_FC_RX_PAUSE);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	hw->original_fc = hw->fc;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc);
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	/* Take the 4 bits from EEPROM word 0x0F that determine the initial
7308c2ecf20Sopenharmony_ci	 * polarity value for the SW controlled pins, and setup the
7318c2ecf20Sopenharmony_ci	 * Extended Device Control reg with that info.
7328c2ecf20Sopenharmony_ci	 * This is needed because one of the SW controlled pins is used for
7338c2ecf20Sopenharmony_ci	 * signal detection.  So this should be done before e1000_setup_pcs_link()
7348c2ecf20Sopenharmony_ci	 * or e1000_phy_setup() is called.
7358c2ecf20Sopenharmony_ci	 */
7368c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82543) {
7378c2ecf20Sopenharmony_ci		ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
7388c2ecf20Sopenharmony_ci					    1, &eeprom_data);
7398c2ecf20Sopenharmony_ci		if (ret_val) {
7408c2ecf20Sopenharmony_ci			e_dbg("EEPROM Read Error\n");
7418c2ecf20Sopenharmony_ci			return -E1000_ERR_EEPROM;
7428c2ecf20Sopenharmony_ci		}
7438c2ecf20Sopenharmony_ci		ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
7448c2ecf20Sopenharmony_ci			    SWDPIO__EXT_SHIFT);
7458c2ecf20Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
7468c2ecf20Sopenharmony_ci	}
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	/* Call the necessary subroutine to configure the link. */
7498c2ecf20Sopenharmony_ci	ret_val = (hw->media_type == e1000_media_type_copper) ?
7508c2ecf20Sopenharmony_ci	    e1000_setup_copper_link(hw) : e1000_setup_fiber_serdes_link(hw);
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	/* Initialize the flow control address, type, and PAUSE timer
7538c2ecf20Sopenharmony_ci	 * registers to their default values.  This is done even if flow
7548c2ecf20Sopenharmony_ci	 * control is disabled, because it does not hurt anything to
7558c2ecf20Sopenharmony_ci	 * initialize these registers.
7568c2ecf20Sopenharmony_ci	 */
7578c2ecf20Sopenharmony_ci	e_dbg("Initializing the Flow Control address, type and timer regs\n");
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	ew32(FCT, FLOW_CONTROL_TYPE);
7608c2ecf20Sopenharmony_ci	ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
7618c2ecf20Sopenharmony_ci	ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	ew32(FCTTV, hw->fc_pause_time);
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	/* Set the flow control receive threshold registers.  Normally,
7668c2ecf20Sopenharmony_ci	 * these registers will be set to a default threshold that may be
7678c2ecf20Sopenharmony_ci	 * adjusted later by the driver's runtime code.  However, if the
7688c2ecf20Sopenharmony_ci	 * ability to transmit pause frames in not enabled, then these
7698c2ecf20Sopenharmony_ci	 * registers will be set to 0.
7708c2ecf20Sopenharmony_ci	 */
7718c2ecf20Sopenharmony_ci	if (!(hw->fc & E1000_FC_TX_PAUSE)) {
7728c2ecf20Sopenharmony_ci		ew32(FCRTL, 0);
7738c2ecf20Sopenharmony_ci		ew32(FCRTH, 0);
7748c2ecf20Sopenharmony_ci	} else {
7758c2ecf20Sopenharmony_ci		/* We need to set up the Receive Threshold high and low water
7768c2ecf20Sopenharmony_ci		 * marks as well as (optionally) enabling the transmission of
7778c2ecf20Sopenharmony_ci		 * XON frames.
7788c2ecf20Sopenharmony_ci		 */
7798c2ecf20Sopenharmony_ci		if (hw->fc_send_xon) {
7808c2ecf20Sopenharmony_ci			ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
7818c2ecf20Sopenharmony_ci			ew32(FCRTH, hw->fc_high_water);
7828c2ecf20Sopenharmony_ci		} else {
7838c2ecf20Sopenharmony_ci			ew32(FCRTL, hw->fc_low_water);
7848c2ecf20Sopenharmony_ci			ew32(FCRTH, hw->fc_high_water);
7858c2ecf20Sopenharmony_ci		}
7868c2ecf20Sopenharmony_ci	}
7878c2ecf20Sopenharmony_ci	return ret_val;
7888c2ecf20Sopenharmony_ci}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci/**
7918c2ecf20Sopenharmony_ci * e1000_setup_fiber_serdes_link - prepare fiber or serdes link
7928c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
7938c2ecf20Sopenharmony_ci *
7948c2ecf20Sopenharmony_ci * Manipulates Physical Coding Sublayer functions in order to configure
7958c2ecf20Sopenharmony_ci * link. Assumes the hardware has been previously reset and the transmitter
7968c2ecf20Sopenharmony_ci * and receiver are not enabled.
7978c2ecf20Sopenharmony_ci */
7988c2ecf20Sopenharmony_cistatic s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
7998c2ecf20Sopenharmony_ci{
8008c2ecf20Sopenharmony_ci	u32 ctrl;
8018c2ecf20Sopenharmony_ci	u32 status;
8028c2ecf20Sopenharmony_ci	u32 txcw = 0;
8038c2ecf20Sopenharmony_ci	u32 i;
8048c2ecf20Sopenharmony_ci	u32 signal = 0;
8058c2ecf20Sopenharmony_ci	s32 ret_val;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	/* On adapters with a MAC newer than 82544, SWDP 1 will be
8088c2ecf20Sopenharmony_ci	 * set when the optics detect a signal. On older adapters, it will be
8098c2ecf20Sopenharmony_ci	 * cleared when there is a signal.  This applies to fiber media only.
8108c2ecf20Sopenharmony_ci	 * If we're on serdes media, adjust the output amplitude to value
8118c2ecf20Sopenharmony_ci	 * set in the EEPROM.
8128c2ecf20Sopenharmony_ci	 */
8138c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
8148c2ecf20Sopenharmony_ci	if (hw->media_type == e1000_media_type_fiber)
8158c2ecf20Sopenharmony_ci		signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	ret_val = e1000_adjust_serdes_amplitude(hw);
8188c2ecf20Sopenharmony_ci	if (ret_val)
8198c2ecf20Sopenharmony_ci		return ret_val;
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	/* Take the link out of reset */
8228c2ecf20Sopenharmony_ci	ctrl &= ~(E1000_CTRL_LRST);
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	/* Adjust VCO speed to improve BER performance */
8258c2ecf20Sopenharmony_ci	ret_val = e1000_set_vco_speed(hw);
8268c2ecf20Sopenharmony_ci	if (ret_val)
8278c2ecf20Sopenharmony_ci		return ret_val;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	e1000_config_collision_dist(hw);
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	/* Check for a software override of the flow control settings, and setup
8328c2ecf20Sopenharmony_ci	 * the device accordingly.  If auto-negotiation is enabled, then
8338c2ecf20Sopenharmony_ci	 * software will have to set the "PAUSE" bits to the correct value in
8348c2ecf20Sopenharmony_ci	 * the Tranmsit Config Word Register (TXCW) and re-start
8358c2ecf20Sopenharmony_ci	 * auto-negotiation.  However, if auto-negotiation is disabled, then
8368c2ecf20Sopenharmony_ci	 * software will have to manually configure the two flow control enable
8378c2ecf20Sopenharmony_ci	 * bits in the CTRL register.
8388c2ecf20Sopenharmony_ci	 *
8398c2ecf20Sopenharmony_ci	 * The possible values of the "fc" parameter are:
8408c2ecf20Sopenharmony_ci	 *  0:  Flow control is completely disabled
8418c2ecf20Sopenharmony_ci	 *  1:  Rx flow control is enabled (we can receive pause frames, but
8428c2ecf20Sopenharmony_ci	 *      not send pause frames).
8438c2ecf20Sopenharmony_ci	 *  2:  Tx flow control is enabled (we can send pause frames but we do
8448c2ecf20Sopenharmony_ci	 *      not support receiving pause frames).
8458c2ecf20Sopenharmony_ci	 *  3:  Both Rx and TX flow control (symmetric) are enabled.
8468c2ecf20Sopenharmony_ci	 */
8478c2ecf20Sopenharmony_ci	switch (hw->fc) {
8488c2ecf20Sopenharmony_ci	case E1000_FC_NONE:
8498c2ecf20Sopenharmony_ci		/* Flow ctrl is completely disabled by a software over-ride */
8508c2ecf20Sopenharmony_ci		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
8518c2ecf20Sopenharmony_ci		break;
8528c2ecf20Sopenharmony_ci	case E1000_FC_RX_PAUSE:
8538c2ecf20Sopenharmony_ci		/* Rx Flow control is enabled and Tx Flow control is disabled by
8548c2ecf20Sopenharmony_ci		 * a software over-ride. Since there really isn't a way to
8558c2ecf20Sopenharmony_ci		 * advertise that we are capable of Rx Pause ONLY, we will
8568c2ecf20Sopenharmony_ci		 * advertise that we support both symmetric and asymmetric Rx
8578c2ecf20Sopenharmony_ci		 * PAUSE. Later, we will disable the adapter's ability to send
8588c2ecf20Sopenharmony_ci		 * PAUSE frames.
8598c2ecf20Sopenharmony_ci		 */
8608c2ecf20Sopenharmony_ci		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
8618c2ecf20Sopenharmony_ci		break;
8628c2ecf20Sopenharmony_ci	case E1000_FC_TX_PAUSE:
8638c2ecf20Sopenharmony_ci		/* Tx Flow control is enabled, and Rx Flow control is disabled,
8648c2ecf20Sopenharmony_ci		 * by a software over-ride.
8658c2ecf20Sopenharmony_ci		 */
8668c2ecf20Sopenharmony_ci		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
8678c2ecf20Sopenharmony_ci		break;
8688c2ecf20Sopenharmony_ci	case E1000_FC_FULL:
8698c2ecf20Sopenharmony_ci		/* Flow control (both Rx and Tx) is enabled by a software
8708c2ecf20Sopenharmony_ci		 * over-ride.
8718c2ecf20Sopenharmony_ci		 */
8728c2ecf20Sopenharmony_ci		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
8738c2ecf20Sopenharmony_ci		break;
8748c2ecf20Sopenharmony_ci	default:
8758c2ecf20Sopenharmony_ci		e_dbg("Flow control param set incorrectly\n");
8768c2ecf20Sopenharmony_ci		return -E1000_ERR_CONFIG;
8778c2ecf20Sopenharmony_ci	}
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	/* Since auto-negotiation is enabled, take the link out of reset (the
8808c2ecf20Sopenharmony_ci	 * link will be in reset, because we previously reset the chip). This
8818c2ecf20Sopenharmony_ci	 * will restart auto-negotiation.  If auto-negotiation is successful
8828c2ecf20Sopenharmony_ci	 * then the link-up status bit will be set and the flow control enable
8838c2ecf20Sopenharmony_ci	 * bits (RFCE and TFCE) will be set according to their negotiated value.
8848c2ecf20Sopenharmony_ci	 */
8858c2ecf20Sopenharmony_ci	e_dbg("Auto-negotiation enabled\n");
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	ew32(TXCW, txcw);
8888c2ecf20Sopenharmony_ci	ew32(CTRL, ctrl);
8898c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci	hw->txcw = txcw;
8928c2ecf20Sopenharmony_ci	msleep(1);
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci	/* If we have a signal (the cable is plugged in) then poll for a
8958c2ecf20Sopenharmony_ci	 * "Link-Up" indication in the Device Status Register.  Time-out if a
8968c2ecf20Sopenharmony_ci	 * link isn't seen in 500 milliseconds seconds (Auto-negotiation should
8978c2ecf20Sopenharmony_ci	 * complete in less than 500 milliseconds even if the other end is doing
8988c2ecf20Sopenharmony_ci	 * it in SW). For internal serdes, we just assume a signal is present,
8998c2ecf20Sopenharmony_ci	 * then poll.
9008c2ecf20Sopenharmony_ci	 */
9018c2ecf20Sopenharmony_ci	if (hw->media_type == e1000_media_type_internal_serdes ||
9028c2ecf20Sopenharmony_ci	    (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) {
9038c2ecf20Sopenharmony_ci		e_dbg("Looking for Link\n");
9048c2ecf20Sopenharmony_ci		for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
9058c2ecf20Sopenharmony_ci			msleep(10);
9068c2ecf20Sopenharmony_ci			status = er32(STATUS);
9078c2ecf20Sopenharmony_ci			if (status & E1000_STATUS_LU)
9088c2ecf20Sopenharmony_ci				break;
9098c2ecf20Sopenharmony_ci		}
9108c2ecf20Sopenharmony_ci		if (i == (LINK_UP_TIMEOUT / 10)) {
9118c2ecf20Sopenharmony_ci			e_dbg("Never got a valid link from auto-neg!!!\n");
9128c2ecf20Sopenharmony_ci			hw->autoneg_failed = 1;
9138c2ecf20Sopenharmony_ci			/* AutoNeg failed to achieve a link, so we'll call
9148c2ecf20Sopenharmony_ci			 * e1000_check_for_link. This routine will force the
9158c2ecf20Sopenharmony_ci			 * link up if we detect a signal. This will allow us to
9168c2ecf20Sopenharmony_ci			 * communicate with non-autonegotiating link partners.
9178c2ecf20Sopenharmony_ci			 */
9188c2ecf20Sopenharmony_ci			ret_val = e1000_check_for_link(hw);
9198c2ecf20Sopenharmony_ci			if (ret_val) {
9208c2ecf20Sopenharmony_ci				e_dbg("Error while checking for link\n");
9218c2ecf20Sopenharmony_ci				return ret_val;
9228c2ecf20Sopenharmony_ci			}
9238c2ecf20Sopenharmony_ci			hw->autoneg_failed = 0;
9248c2ecf20Sopenharmony_ci		} else {
9258c2ecf20Sopenharmony_ci			hw->autoneg_failed = 0;
9268c2ecf20Sopenharmony_ci			e_dbg("Valid Link Found\n");
9278c2ecf20Sopenharmony_ci		}
9288c2ecf20Sopenharmony_ci	} else {
9298c2ecf20Sopenharmony_ci		e_dbg("No Signal Detected\n");
9308c2ecf20Sopenharmony_ci	}
9318c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
9328c2ecf20Sopenharmony_ci}
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci/**
9358c2ecf20Sopenharmony_ci * e1000_copper_link_rtl_setup - Copper link setup for e1000_phy_rtl series.
9368c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
9378c2ecf20Sopenharmony_ci *
9388c2ecf20Sopenharmony_ci * Commits changes to PHY configuration by calling e1000_phy_reset().
9398c2ecf20Sopenharmony_ci */
9408c2ecf20Sopenharmony_cistatic s32 e1000_copper_link_rtl_setup(struct e1000_hw *hw)
9418c2ecf20Sopenharmony_ci{
9428c2ecf20Sopenharmony_ci	s32 ret_val;
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	/* SW reset the PHY so all changes take effect */
9458c2ecf20Sopenharmony_ci	ret_val = e1000_phy_reset(hw);
9468c2ecf20Sopenharmony_ci	if (ret_val) {
9478c2ecf20Sopenharmony_ci		e_dbg("Error Resetting the PHY\n");
9488c2ecf20Sopenharmony_ci		return ret_val;
9498c2ecf20Sopenharmony_ci	}
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
9528c2ecf20Sopenharmony_ci}
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_cistatic s32 gbe_dhg_phy_setup(struct e1000_hw *hw)
9558c2ecf20Sopenharmony_ci{
9568c2ecf20Sopenharmony_ci	s32 ret_val;
9578c2ecf20Sopenharmony_ci	u32 ctrl_aux;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	switch (hw->phy_type) {
9608c2ecf20Sopenharmony_ci	case e1000_phy_8211:
9618c2ecf20Sopenharmony_ci		ret_val = e1000_copper_link_rtl_setup(hw);
9628c2ecf20Sopenharmony_ci		if (ret_val) {
9638c2ecf20Sopenharmony_ci			e_dbg("e1000_copper_link_rtl_setup failed!\n");
9648c2ecf20Sopenharmony_ci			return ret_val;
9658c2ecf20Sopenharmony_ci		}
9668c2ecf20Sopenharmony_ci		break;
9678c2ecf20Sopenharmony_ci	case e1000_phy_8201:
9688c2ecf20Sopenharmony_ci		/* Set RMII mode */
9698c2ecf20Sopenharmony_ci		ctrl_aux = er32(CTL_AUX);
9708c2ecf20Sopenharmony_ci		ctrl_aux |= E1000_CTL_AUX_RMII;
9718c2ecf20Sopenharmony_ci		ew32(CTL_AUX, ctrl_aux);
9728c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci		/* Disable the J/K bits required for receive */
9758c2ecf20Sopenharmony_ci		ctrl_aux = er32(CTL_AUX);
9768c2ecf20Sopenharmony_ci		ctrl_aux |= 0x4;
9778c2ecf20Sopenharmony_ci		ctrl_aux &= ~0x2;
9788c2ecf20Sopenharmony_ci		ew32(CTL_AUX, ctrl_aux);
9798c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
9808c2ecf20Sopenharmony_ci		ret_val = e1000_copper_link_rtl_setup(hw);
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci		if (ret_val) {
9838c2ecf20Sopenharmony_ci			e_dbg("e1000_copper_link_rtl_setup failed!\n");
9848c2ecf20Sopenharmony_ci			return ret_val;
9858c2ecf20Sopenharmony_ci		}
9868c2ecf20Sopenharmony_ci		break;
9878c2ecf20Sopenharmony_ci	default:
9888c2ecf20Sopenharmony_ci		e_dbg("Error Resetting the PHY\n");
9898c2ecf20Sopenharmony_ci		return E1000_ERR_PHY_TYPE;
9908c2ecf20Sopenharmony_ci	}
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
9938c2ecf20Sopenharmony_ci}
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci/**
9968c2ecf20Sopenharmony_ci * e1000_copper_link_preconfig - early configuration for copper
9978c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
9988c2ecf20Sopenharmony_ci *
9998c2ecf20Sopenharmony_ci * Make sure we have a valid PHY and change PHY mode before link setup.
10008c2ecf20Sopenharmony_ci */
10018c2ecf20Sopenharmony_cistatic s32 e1000_copper_link_preconfig(struct e1000_hw *hw)
10028c2ecf20Sopenharmony_ci{
10038c2ecf20Sopenharmony_ci	u32 ctrl;
10048c2ecf20Sopenharmony_ci	s32 ret_val;
10058c2ecf20Sopenharmony_ci	u16 phy_data;
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
10088c2ecf20Sopenharmony_ci	/* With 82543, we need to force speed and duplex on the MAC equal to
10098c2ecf20Sopenharmony_ci	 * what the PHY speed and duplex configuration is. In addition, we need
10108c2ecf20Sopenharmony_ci	 * to perform a hardware reset on the PHY to take it out of reset.
10118c2ecf20Sopenharmony_ci	 */
10128c2ecf20Sopenharmony_ci	if (hw->mac_type > e1000_82543) {
10138c2ecf20Sopenharmony_ci		ctrl |= E1000_CTRL_SLU;
10148c2ecf20Sopenharmony_ci		ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
10158c2ecf20Sopenharmony_ci		ew32(CTRL, ctrl);
10168c2ecf20Sopenharmony_ci	} else {
10178c2ecf20Sopenharmony_ci		ctrl |=
10188c2ecf20Sopenharmony_ci		    (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
10198c2ecf20Sopenharmony_ci		ew32(CTRL, ctrl);
10208c2ecf20Sopenharmony_ci		ret_val = e1000_phy_hw_reset(hw);
10218c2ecf20Sopenharmony_ci		if (ret_val)
10228c2ecf20Sopenharmony_ci			return ret_val;
10238c2ecf20Sopenharmony_ci	}
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	/* Make sure we have a valid PHY */
10268c2ecf20Sopenharmony_ci	ret_val = e1000_detect_gig_phy(hw);
10278c2ecf20Sopenharmony_ci	if (ret_val) {
10288c2ecf20Sopenharmony_ci		e_dbg("Error, did not detect valid phy.\n");
10298c2ecf20Sopenharmony_ci		return ret_val;
10308c2ecf20Sopenharmony_ci	}
10318c2ecf20Sopenharmony_ci	e_dbg("Phy ID = %x\n", hw->phy_id);
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	/* Set PHY to class A mode (if necessary) */
10348c2ecf20Sopenharmony_ci	ret_val = e1000_set_phy_mode(hw);
10358c2ecf20Sopenharmony_ci	if (ret_val)
10368c2ecf20Sopenharmony_ci		return ret_val;
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	if ((hw->mac_type == e1000_82545_rev_3) ||
10398c2ecf20Sopenharmony_ci	    (hw->mac_type == e1000_82546_rev_3)) {
10408c2ecf20Sopenharmony_ci		ret_val =
10418c2ecf20Sopenharmony_ci		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
10428c2ecf20Sopenharmony_ci		phy_data |= 0x00000008;
10438c2ecf20Sopenharmony_ci		ret_val =
10448c2ecf20Sopenharmony_ci		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
10458c2ecf20Sopenharmony_ci	}
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	if (hw->mac_type <= e1000_82543 ||
10488c2ecf20Sopenharmony_ci	    hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
10498c2ecf20Sopenharmony_ci	    hw->mac_type == e1000_82541_rev_2 ||
10508c2ecf20Sopenharmony_ci	    hw->mac_type == e1000_82547_rev_2)
10518c2ecf20Sopenharmony_ci		hw->phy_reset_disable = false;
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
10548c2ecf20Sopenharmony_ci}
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci/**
10578c2ecf20Sopenharmony_ci * e1000_copper_link_igp_setup - Copper link setup for e1000_phy_igp series.
10588c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
10598c2ecf20Sopenharmony_ci */
10608c2ecf20Sopenharmony_cistatic s32 e1000_copper_link_igp_setup(struct e1000_hw *hw)
10618c2ecf20Sopenharmony_ci{
10628c2ecf20Sopenharmony_ci	u32 led_ctrl;
10638c2ecf20Sopenharmony_ci	s32 ret_val;
10648c2ecf20Sopenharmony_ci	u16 phy_data;
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	if (hw->phy_reset_disable)
10678c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	ret_val = e1000_phy_reset(hw);
10708c2ecf20Sopenharmony_ci	if (ret_val) {
10718c2ecf20Sopenharmony_ci		e_dbg("Error Resetting the PHY\n");
10728c2ecf20Sopenharmony_ci		return ret_val;
10738c2ecf20Sopenharmony_ci	}
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	/* Wait 15ms for MAC to configure PHY from eeprom settings */
10768c2ecf20Sopenharmony_ci	msleep(15);
10778c2ecf20Sopenharmony_ci	/* Configure activity LED after PHY reset */
10788c2ecf20Sopenharmony_ci	led_ctrl = er32(LEDCTL);
10798c2ecf20Sopenharmony_ci	led_ctrl &= IGP_ACTIVITY_LED_MASK;
10808c2ecf20Sopenharmony_ci	led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
10818c2ecf20Sopenharmony_ci	ew32(LEDCTL, led_ctrl);
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	/* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
10848c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp) {
10858c2ecf20Sopenharmony_ci		/* disable lplu d3 during driver init */
10868c2ecf20Sopenharmony_ci		ret_val = e1000_set_d3_lplu_state(hw, false);
10878c2ecf20Sopenharmony_ci		if (ret_val) {
10888c2ecf20Sopenharmony_ci			e_dbg("Error Disabling LPLU D3\n");
10898c2ecf20Sopenharmony_ci			return ret_val;
10908c2ecf20Sopenharmony_ci		}
10918c2ecf20Sopenharmony_ci	}
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	/* Configure mdi-mdix settings */
10948c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
10958c2ecf20Sopenharmony_ci	if (ret_val)
10968c2ecf20Sopenharmony_ci		return ret_val;
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
10998c2ecf20Sopenharmony_ci		hw->dsp_config_state = e1000_dsp_config_disabled;
11008c2ecf20Sopenharmony_ci		/* Force MDI for earlier revs of the IGP PHY */
11018c2ecf20Sopenharmony_ci		phy_data &=
11028c2ecf20Sopenharmony_ci		    ~(IGP01E1000_PSCR_AUTO_MDIX |
11038c2ecf20Sopenharmony_ci		      IGP01E1000_PSCR_FORCE_MDI_MDIX);
11048c2ecf20Sopenharmony_ci		hw->mdix = 1;
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci	} else {
11078c2ecf20Sopenharmony_ci		hw->dsp_config_state = e1000_dsp_config_enabled;
11088c2ecf20Sopenharmony_ci		phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci		switch (hw->mdix) {
11118c2ecf20Sopenharmony_ci		case 1:
11128c2ecf20Sopenharmony_ci			phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
11138c2ecf20Sopenharmony_ci			break;
11148c2ecf20Sopenharmony_ci		case 2:
11158c2ecf20Sopenharmony_ci			phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
11168c2ecf20Sopenharmony_ci			break;
11178c2ecf20Sopenharmony_ci		case 0:
11188c2ecf20Sopenharmony_ci		default:
11198c2ecf20Sopenharmony_ci			phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
11208c2ecf20Sopenharmony_ci			break;
11218c2ecf20Sopenharmony_ci		}
11228c2ecf20Sopenharmony_ci	}
11238c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
11248c2ecf20Sopenharmony_ci	if (ret_val)
11258c2ecf20Sopenharmony_ci		return ret_val;
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	/* set auto-master slave resolution settings */
11288c2ecf20Sopenharmony_ci	if (hw->autoneg) {
11298c2ecf20Sopenharmony_ci		e1000_ms_type phy_ms_setting = hw->master_slave;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci		if (hw->ffe_config_state == e1000_ffe_config_active)
11328c2ecf20Sopenharmony_ci			hw->ffe_config_state = e1000_ffe_config_enabled;
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci		if (hw->dsp_config_state == e1000_dsp_config_activated)
11358c2ecf20Sopenharmony_ci			hw->dsp_config_state = e1000_dsp_config_enabled;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci		/* when autonegotiation advertisement is only 1000Mbps then we
11388c2ecf20Sopenharmony_ci		 * should disable SmartSpeed and enable Auto MasterSlave
11398c2ecf20Sopenharmony_ci		 * resolution as hardware default.
11408c2ecf20Sopenharmony_ci		 */
11418c2ecf20Sopenharmony_ci		if (hw->autoneg_advertised == ADVERTISE_1000_FULL) {
11428c2ecf20Sopenharmony_ci			/* Disable SmartSpeed */
11438c2ecf20Sopenharmony_ci			ret_val =
11448c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
11458c2ecf20Sopenharmony_ci					       &phy_data);
11468c2ecf20Sopenharmony_ci			if (ret_val)
11478c2ecf20Sopenharmony_ci				return ret_val;
11488c2ecf20Sopenharmony_ci			phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
11498c2ecf20Sopenharmony_ci			ret_val =
11508c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
11518c2ecf20Sopenharmony_ci						phy_data);
11528c2ecf20Sopenharmony_ci			if (ret_val)
11538c2ecf20Sopenharmony_ci				return ret_val;
11548c2ecf20Sopenharmony_ci			/* Set auto Master/Slave resolution process */
11558c2ecf20Sopenharmony_ci			ret_val =
11568c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
11578c2ecf20Sopenharmony_ci			if (ret_val)
11588c2ecf20Sopenharmony_ci				return ret_val;
11598c2ecf20Sopenharmony_ci			phy_data &= ~CR_1000T_MS_ENABLE;
11608c2ecf20Sopenharmony_ci			ret_val =
11618c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
11628c2ecf20Sopenharmony_ci			if (ret_val)
11638c2ecf20Sopenharmony_ci				return ret_val;
11648c2ecf20Sopenharmony_ci		}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
11678c2ecf20Sopenharmony_ci		if (ret_val)
11688c2ecf20Sopenharmony_ci			return ret_val;
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci		/* load defaults for future use */
11718c2ecf20Sopenharmony_ci		hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
11728c2ecf20Sopenharmony_ci		    ((phy_data & CR_1000T_MS_VALUE) ?
11738c2ecf20Sopenharmony_ci		     e1000_ms_force_master :
11748c2ecf20Sopenharmony_ci		     e1000_ms_force_slave) : e1000_ms_auto;
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci		switch (phy_ms_setting) {
11778c2ecf20Sopenharmony_ci		case e1000_ms_force_master:
11788c2ecf20Sopenharmony_ci			phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
11798c2ecf20Sopenharmony_ci			break;
11808c2ecf20Sopenharmony_ci		case e1000_ms_force_slave:
11818c2ecf20Sopenharmony_ci			phy_data |= CR_1000T_MS_ENABLE;
11828c2ecf20Sopenharmony_ci			phy_data &= ~(CR_1000T_MS_VALUE);
11838c2ecf20Sopenharmony_ci			break;
11848c2ecf20Sopenharmony_ci		case e1000_ms_auto:
11858c2ecf20Sopenharmony_ci			phy_data &= ~CR_1000T_MS_ENABLE;
11868c2ecf20Sopenharmony_ci		default:
11878c2ecf20Sopenharmony_ci			break;
11888c2ecf20Sopenharmony_ci		}
11898c2ecf20Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
11908c2ecf20Sopenharmony_ci		if (ret_val)
11918c2ecf20Sopenharmony_ci			return ret_val;
11928c2ecf20Sopenharmony_ci	}
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
11958c2ecf20Sopenharmony_ci}
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci/**
11988c2ecf20Sopenharmony_ci * e1000_copper_link_mgp_setup - Copper link setup for e1000_phy_m88 series.
11998c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
12008c2ecf20Sopenharmony_ci */
12018c2ecf20Sopenharmony_cistatic s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw)
12028c2ecf20Sopenharmony_ci{
12038c2ecf20Sopenharmony_ci	s32 ret_val;
12048c2ecf20Sopenharmony_ci	u16 phy_data;
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	if (hw->phy_reset_disable)
12078c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	/* Enable CRS on TX. This must be set for half-duplex operation. */
12108c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
12118c2ecf20Sopenharmony_ci	if (ret_val)
12128c2ecf20Sopenharmony_ci		return ret_val;
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	/* Options:
12178c2ecf20Sopenharmony_ci	 *   MDI/MDI-X = 0 (default)
12188c2ecf20Sopenharmony_ci	 *   0 - Auto for all speeds
12198c2ecf20Sopenharmony_ci	 *   1 - MDI mode
12208c2ecf20Sopenharmony_ci	 *   2 - MDI-X mode
12218c2ecf20Sopenharmony_ci	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
12228c2ecf20Sopenharmony_ci	 */
12238c2ecf20Sopenharmony_ci	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci	switch (hw->mdix) {
12268c2ecf20Sopenharmony_ci	case 1:
12278c2ecf20Sopenharmony_ci		phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
12288c2ecf20Sopenharmony_ci		break;
12298c2ecf20Sopenharmony_ci	case 2:
12308c2ecf20Sopenharmony_ci		phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
12318c2ecf20Sopenharmony_ci		break;
12328c2ecf20Sopenharmony_ci	case 3:
12338c2ecf20Sopenharmony_ci		phy_data |= M88E1000_PSCR_AUTO_X_1000T;
12348c2ecf20Sopenharmony_ci		break;
12358c2ecf20Sopenharmony_ci	case 0:
12368c2ecf20Sopenharmony_ci	default:
12378c2ecf20Sopenharmony_ci		phy_data |= M88E1000_PSCR_AUTO_X_MODE;
12388c2ecf20Sopenharmony_ci		break;
12398c2ecf20Sopenharmony_ci	}
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci	/* Options:
12428c2ecf20Sopenharmony_ci	 *   disable_polarity_correction = 0 (default)
12438c2ecf20Sopenharmony_ci	 *       Automatic Correction for Reversed Cable Polarity
12448c2ecf20Sopenharmony_ci	 *   0 - Disabled
12458c2ecf20Sopenharmony_ci	 *   1 - Enabled
12468c2ecf20Sopenharmony_ci	 */
12478c2ecf20Sopenharmony_ci	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
12488c2ecf20Sopenharmony_ci	if (hw->disable_polarity_correction == 1)
12498c2ecf20Sopenharmony_ci		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
12508c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
12518c2ecf20Sopenharmony_ci	if (ret_val)
12528c2ecf20Sopenharmony_ci		return ret_val;
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci	if (hw->phy_revision < M88E1011_I_REV_4) {
12558c2ecf20Sopenharmony_ci		/* Force TX_CLK in the Extended PHY Specific Control Register
12568c2ecf20Sopenharmony_ci		 * to 25MHz clock.
12578c2ecf20Sopenharmony_ci		 */
12588c2ecf20Sopenharmony_ci		ret_val =
12598c2ecf20Sopenharmony_ci		    e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
12608c2ecf20Sopenharmony_ci				       &phy_data);
12618c2ecf20Sopenharmony_ci		if (ret_val)
12628c2ecf20Sopenharmony_ci			return ret_val;
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci		phy_data |= M88E1000_EPSCR_TX_CLK_25;
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci		if ((hw->phy_revision == E1000_REVISION_2) &&
12678c2ecf20Sopenharmony_ci		    (hw->phy_id == M88E1111_I_PHY_ID)) {
12688c2ecf20Sopenharmony_ci			/* Vidalia Phy, set the downshift counter to 5x */
12698c2ecf20Sopenharmony_ci			phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK);
12708c2ecf20Sopenharmony_ci			phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
12718c2ecf20Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw,
12728c2ecf20Sopenharmony_ci						      M88E1000_EXT_PHY_SPEC_CTRL,
12738c2ecf20Sopenharmony_ci						      phy_data);
12748c2ecf20Sopenharmony_ci			if (ret_val)
12758c2ecf20Sopenharmony_ci				return ret_val;
12768c2ecf20Sopenharmony_ci		} else {
12778c2ecf20Sopenharmony_ci			/* Configure Master and Slave downshift values */
12788c2ecf20Sopenharmony_ci			phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
12798c2ecf20Sopenharmony_ci				      M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
12808c2ecf20Sopenharmony_ci			phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
12818c2ecf20Sopenharmony_ci				     M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
12828c2ecf20Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw,
12838c2ecf20Sopenharmony_ci						      M88E1000_EXT_PHY_SPEC_CTRL,
12848c2ecf20Sopenharmony_ci						      phy_data);
12858c2ecf20Sopenharmony_ci			if (ret_val)
12868c2ecf20Sopenharmony_ci				return ret_val;
12878c2ecf20Sopenharmony_ci		}
12888c2ecf20Sopenharmony_ci	}
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	/* SW Reset the PHY so all changes take effect */
12918c2ecf20Sopenharmony_ci	ret_val = e1000_phy_reset(hw);
12928c2ecf20Sopenharmony_ci	if (ret_val) {
12938c2ecf20Sopenharmony_ci		e_dbg("Error Resetting the PHY\n");
12948c2ecf20Sopenharmony_ci		return ret_val;
12958c2ecf20Sopenharmony_ci	}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
12988c2ecf20Sopenharmony_ci}
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci/**
13018c2ecf20Sopenharmony_ci * e1000_copper_link_autoneg - setup auto-neg
13028c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
13038c2ecf20Sopenharmony_ci *
13048c2ecf20Sopenharmony_ci * Setup auto-negotiation and flow control advertisements,
13058c2ecf20Sopenharmony_ci * and then perform auto-negotiation.
13068c2ecf20Sopenharmony_ci */
13078c2ecf20Sopenharmony_cistatic s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
13088c2ecf20Sopenharmony_ci{
13098c2ecf20Sopenharmony_ci	s32 ret_val;
13108c2ecf20Sopenharmony_ci	u16 phy_data;
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	/* Perform some bounds checking on the hw->autoneg_advertised
13138c2ecf20Sopenharmony_ci	 * parameter.  If this variable is zero, then set it to the default.
13148c2ecf20Sopenharmony_ci	 */
13158c2ecf20Sopenharmony_ci	hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci	/* If autoneg_advertised is zero, we assume it was not defaulted
13188c2ecf20Sopenharmony_ci	 * by the calling code so we set to advertise full capability.
13198c2ecf20Sopenharmony_ci	 */
13208c2ecf20Sopenharmony_ci	if (hw->autoneg_advertised == 0)
13218c2ecf20Sopenharmony_ci		hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci	/* IFE/RTL8201N PHY only supports 10/100 */
13248c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_8201)
13258c2ecf20Sopenharmony_ci		hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL;
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	e_dbg("Reconfiguring auto-neg advertisement params\n");
13288c2ecf20Sopenharmony_ci	ret_val = e1000_phy_setup_autoneg(hw);
13298c2ecf20Sopenharmony_ci	if (ret_val) {
13308c2ecf20Sopenharmony_ci		e_dbg("Error Setting up Auto-Negotiation\n");
13318c2ecf20Sopenharmony_ci		return ret_val;
13328c2ecf20Sopenharmony_ci	}
13338c2ecf20Sopenharmony_ci	e_dbg("Restarting Auto-Neg\n");
13348c2ecf20Sopenharmony_ci
13358c2ecf20Sopenharmony_ci	/* Restart auto-negotiation by setting the Auto Neg Enable bit and
13368c2ecf20Sopenharmony_ci	 * the Auto Neg Restart bit in the PHY control register.
13378c2ecf20Sopenharmony_ci	 */
13388c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
13398c2ecf20Sopenharmony_ci	if (ret_val)
13408c2ecf20Sopenharmony_ci		return ret_val;
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci	phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
13438c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
13448c2ecf20Sopenharmony_ci	if (ret_val)
13458c2ecf20Sopenharmony_ci		return ret_val;
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	/* Does the user want to wait for Auto-Neg to complete here, or
13488c2ecf20Sopenharmony_ci	 * check at a later time (for example, callback routine).
13498c2ecf20Sopenharmony_ci	 */
13508c2ecf20Sopenharmony_ci	if (hw->wait_autoneg_complete) {
13518c2ecf20Sopenharmony_ci		ret_val = e1000_wait_autoneg(hw);
13528c2ecf20Sopenharmony_ci		if (ret_val) {
13538c2ecf20Sopenharmony_ci			e_dbg
13548c2ecf20Sopenharmony_ci			    ("Error while waiting for autoneg to complete\n");
13558c2ecf20Sopenharmony_ci			return ret_val;
13568c2ecf20Sopenharmony_ci		}
13578c2ecf20Sopenharmony_ci	}
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	hw->get_link_status = true;
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
13628c2ecf20Sopenharmony_ci}
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci/**
13658c2ecf20Sopenharmony_ci * e1000_copper_link_postconfig - post link setup
13668c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
13678c2ecf20Sopenharmony_ci *
13688c2ecf20Sopenharmony_ci * Config the MAC and the PHY after link is up.
13698c2ecf20Sopenharmony_ci *   1) Set up the MAC to the current PHY speed/duplex
13708c2ecf20Sopenharmony_ci *      if we are on 82543.  If we
13718c2ecf20Sopenharmony_ci *      are on newer silicon, we only need to configure
13728c2ecf20Sopenharmony_ci *      collision distance in the Transmit Control Register.
13738c2ecf20Sopenharmony_ci *   2) Set up flow control on the MAC to that established with
13748c2ecf20Sopenharmony_ci *      the link partner.
13758c2ecf20Sopenharmony_ci *   3) Config DSP to improve Gigabit link quality for some PHY revisions.
13768c2ecf20Sopenharmony_ci */
13778c2ecf20Sopenharmony_cistatic s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
13788c2ecf20Sopenharmony_ci{
13798c2ecf20Sopenharmony_ci	s32 ret_val;
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) {
13828c2ecf20Sopenharmony_ci		e1000_config_collision_dist(hw);
13838c2ecf20Sopenharmony_ci	} else {
13848c2ecf20Sopenharmony_ci		ret_val = e1000_config_mac_to_phy(hw);
13858c2ecf20Sopenharmony_ci		if (ret_val) {
13868c2ecf20Sopenharmony_ci			e_dbg("Error configuring MAC to PHY settings\n");
13878c2ecf20Sopenharmony_ci			return ret_val;
13888c2ecf20Sopenharmony_ci		}
13898c2ecf20Sopenharmony_ci	}
13908c2ecf20Sopenharmony_ci	ret_val = e1000_config_fc_after_link_up(hw);
13918c2ecf20Sopenharmony_ci	if (ret_val) {
13928c2ecf20Sopenharmony_ci		e_dbg("Error Configuring Flow Control\n");
13938c2ecf20Sopenharmony_ci		return ret_val;
13948c2ecf20Sopenharmony_ci	}
13958c2ecf20Sopenharmony_ci
13968c2ecf20Sopenharmony_ci	/* Config DSP to improve Giga link quality */
13978c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp) {
13988c2ecf20Sopenharmony_ci		ret_val = e1000_config_dsp_after_link_change(hw, true);
13998c2ecf20Sopenharmony_ci		if (ret_val) {
14008c2ecf20Sopenharmony_ci			e_dbg("Error Configuring DSP after link up\n");
14018c2ecf20Sopenharmony_ci			return ret_val;
14028c2ecf20Sopenharmony_ci		}
14038c2ecf20Sopenharmony_ci	}
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
14068c2ecf20Sopenharmony_ci}
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci/**
14098c2ecf20Sopenharmony_ci * e1000_setup_copper_link - phy/speed/duplex setting
14108c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
14118c2ecf20Sopenharmony_ci *
14128c2ecf20Sopenharmony_ci * Detects which PHY is present and sets up the speed and duplex
14138c2ecf20Sopenharmony_ci */
14148c2ecf20Sopenharmony_cistatic s32 e1000_setup_copper_link(struct e1000_hw *hw)
14158c2ecf20Sopenharmony_ci{
14168c2ecf20Sopenharmony_ci	s32 ret_val;
14178c2ecf20Sopenharmony_ci	u16 i;
14188c2ecf20Sopenharmony_ci	u16 phy_data;
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci	/* Check if it is a valid PHY and set PHY mode if necessary. */
14218c2ecf20Sopenharmony_ci	ret_val = e1000_copper_link_preconfig(hw);
14228c2ecf20Sopenharmony_ci	if (ret_val)
14238c2ecf20Sopenharmony_ci		return ret_val;
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp) {
14268c2ecf20Sopenharmony_ci		ret_val = e1000_copper_link_igp_setup(hw);
14278c2ecf20Sopenharmony_ci		if (ret_val)
14288c2ecf20Sopenharmony_ci			return ret_val;
14298c2ecf20Sopenharmony_ci	} else if (hw->phy_type == e1000_phy_m88) {
14308c2ecf20Sopenharmony_ci		ret_val = e1000_copper_link_mgp_setup(hw);
14318c2ecf20Sopenharmony_ci		if (ret_val)
14328c2ecf20Sopenharmony_ci			return ret_val;
14338c2ecf20Sopenharmony_ci	} else {
14348c2ecf20Sopenharmony_ci		ret_val = gbe_dhg_phy_setup(hw);
14358c2ecf20Sopenharmony_ci		if (ret_val) {
14368c2ecf20Sopenharmony_ci			e_dbg("gbe_dhg_phy_setup failed!\n");
14378c2ecf20Sopenharmony_ci			return ret_val;
14388c2ecf20Sopenharmony_ci		}
14398c2ecf20Sopenharmony_ci	}
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci	if (hw->autoneg) {
14428c2ecf20Sopenharmony_ci		/* Setup autoneg and flow control advertisement
14438c2ecf20Sopenharmony_ci		 * and perform autonegotiation
14448c2ecf20Sopenharmony_ci		 */
14458c2ecf20Sopenharmony_ci		ret_val = e1000_copper_link_autoneg(hw);
14468c2ecf20Sopenharmony_ci		if (ret_val)
14478c2ecf20Sopenharmony_ci			return ret_val;
14488c2ecf20Sopenharmony_ci	} else {
14498c2ecf20Sopenharmony_ci		/* PHY will be set to 10H, 10F, 100H,or 100F
14508c2ecf20Sopenharmony_ci		 * depending on value from forced_speed_duplex.
14518c2ecf20Sopenharmony_ci		 */
14528c2ecf20Sopenharmony_ci		e_dbg("Forcing speed and duplex\n");
14538c2ecf20Sopenharmony_ci		ret_val = e1000_phy_force_speed_duplex(hw);
14548c2ecf20Sopenharmony_ci		if (ret_val) {
14558c2ecf20Sopenharmony_ci			e_dbg("Error Forcing Speed and Duplex\n");
14568c2ecf20Sopenharmony_ci			return ret_val;
14578c2ecf20Sopenharmony_ci		}
14588c2ecf20Sopenharmony_ci	}
14598c2ecf20Sopenharmony_ci
14608c2ecf20Sopenharmony_ci	/* Check link status. Wait up to 100 microseconds for link to become
14618c2ecf20Sopenharmony_ci	 * valid.
14628c2ecf20Sopenharmony_ci	 */
14638c2ecf20Sopenharmony_ci	for (i = 0; i < 10; i++) {
14648c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
14658c2ecf20Sopenharmony_ci		if (ret_val)
14668c2ecf20Sopenharmony_ci			return ret_val;
14678c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
14688c2ecf20Sopenharmony_ci		if (ret_val)
14698c2ecf20Sopenharmony_ci			return ret_val;
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci		if (phy_data & MII_SR_LINK_STATUS) {
14728c2ecf20Sopenharmony_ci			/* Config the MAC and PHY after link is up */
14738c2ecf20Sopenharmony_ci			ret_val = e1000_copper_link_postconfig(hw);
14748c2ecf20Sopenharmony_ci			if (ret_val)
14758c2ecf20Sopenharmony_ci				return ret_val;
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci			e_dbg("Valid link established!!!\n");
14788c2ecf20Sopenharmony_ci			return E1000_SUCCESS;
14798c2ecf20Sopenharmony_ci		}
14808c2ecf20Sopenharmony_ci		udelay(10);
14818c2ecf20Sopenharmony_ci	}
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci	e_dbg("Unable to establish link!!!\n");
14848c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
14858c2ecf20Sopenharmony_ci}
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci/**
14888c2ecf20Sopenharmony_ci * e1000_phy_setup_autoneg - phy settings
14898c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
14908c2ecf20Sopenharmony_ci *
14918c2ecf20Sopenharmony_ci * Configures PHY autoneg and flow control advertisement settings
14928c2ecf20Sopenharmony_ci */
14938c2ecf20Sopenharmony_cis32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
14948c2ecf20Sopenharmony_ci{
14958c2ecf20Sopenharmony_ci	s32 ret_val;
14968c2ecf20Sopenharmony_ci	u16 mii_autoneg_adv_reg;
14978c2ecf20Sopenharmony_ci	u16 mii_1000t_ctrl_reg;
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
15008c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
15018c2ecf20Sopenharmony_ci	if (ret_val)
15028c2ecf20Sopenharmony_ci		return ret_val;
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	/* Read the MII 1000Base-T Control Register (Address 9). */
15058c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
15068c2ecf20Sopenharmony_ci	if (ret_val)
15078c2ecf20Sopenharmony_ci		return ret_val;
15088c2ecf20Sopenharmony_ci	else if (hw->phy_type == e1000_phy_8201)
15098c2ecf20Sopenharmony_ci		mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci	/* Need to parse both autoneg_advertised and fc and set up
15128c2ecf20Sopenharmony_ci	 * the appropriate PHY registers.  First we will parse for
15138c2ecf20Sopenharmony_ci	 * autoneg_advertised software override.  Since we can advertise
15148c2ecf20Sopenharmony_ci	 * a plethora of combinations, we need to check each bit
15158c2ecf20Sopenharmony_ci	 * individually.
15168c2ecf20Sopenharmony_ci	 */
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
15198c2ecf20Sopenharmony_ci	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
15208c2ecf20Sopenharmony_ci	 * the  1000Base-T Control Register (Address 9).
15218c2ecf20Sopenharmony_ci	 */
15228c2ecf20Sopenharmony_ci	mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
15238c2ecf20Sopenharmony_ci	mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci	e_dbg("autoneg_advertised %x\n", hw->autoneg_advertised);
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	/* Do we want to advertise 10 Mb Half Duplex? */
15288c2ecf20Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_10_HALF) {
15298c2ecf20Sopenharmony_ci		e_dbg("Advertise 10mb Half duplex\n");
15308c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
15318c2ecf20Sopenharmony_ci	}
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ci	/* Do we want to advertise 10 Mb Full Duplex? */
15348c2ecf20Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_10_FULL) {
15358c2ecf20Sopenharmony_ci		e_dbg("Advertise 10mb Full duplex\n");
15368c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
15378c2ecf20Sopenharmony_ci	}
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ci	/* Do we want to advertise 100 Mb Half Duplex? */
15408c2ecf20Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_100_HALF) {
15418c2ecf20Sopenharmony_ci		e_dbg("Advertise 100mb Half duplex\n");
15428c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
15438c2ecf20Sopenharmony_ci	}
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_ci	/* Do we want to advertise 100 Mb Full Duplex? */
15468c2ecf20Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_100_FULL) {
15478c2ecf20Sopenharmony_ci		e_dbg("Advertise 100mb Full duplex\n");
15488c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
15498c2ecf20Sopenharmony_ci	}
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
15528c2ecf20Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_1000_HALF) {
15538c2ecf20Sopenharmony_ci		e_dbg
15548c2ecf20Sopenharmony_ci		    ("Advertise 1000mb Half duplex requested, request denied!\n");
15558c2ecf20Sopenharmony_ci	}
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci	/* Do we want to advertise 1000 Mb Full Duplex? */
15588c2ecf20Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_1000_FULL) {
15598c2ecf20Sopenharmony_ci		e_dbg("Advertise 1000mb Full duplex\n");
15608c2ecf20Sopenharmony_ci		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
15618c2ecf20Sopenharmony_ci	}
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_ci	/* Check for a software override of the flow control settings, and
15648c2ecf20Sopenharmony_ci	 * setup the PHY advertisement registers accordingly.  If
15658c2ecf20Sopenharmony_ci	 * auto-negotiation is enabled, then software will have to set the
15668c2ecf20Sopenharmony_ci	 * "PAUSE" bits to the correct value in the Auto-Negotiation
15678c2ecf20Sopenharmony_ci	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start
15688c2ecf20Sopenharmony_ci	 * auto-negotiation.
15698c2ecf20Sopenharmony_ci	 *
15708c2ecf20Sopenharmony_ci	 * The possible values of the "fc" parameter are:
15718c2ecf20Sopenharmony_ci	 *      0:  Flow control is completely disabled
15728c2ecf20Sopenharmony_ci	 *      1:  Rx flow control is enabled (we can receive pause frames
15738c2ecf20Sopenharmony_ci	 *          but not send pause frames).
15748c2ecf20Sopenharmony_ci	 *      2:  Tx flow control is enabled (we can send pause frames
15758c2ecf20Sopenharmony_ci	 *          but we do not support receiving pause frames).
15768c2ecf20Sopenharmony_ci	 *      3:  Both Rx and TX flow control (symmetric) are enabled.
15778c2ecf20Sopenharmony_ci	 *  other:  No software override.  The flow control configuration
15788c2ecf20Sopenharmony_ci	 *          in the EEPROM is used.
15798c2ecf20Sopenharmony_ci	 */
15808c2ecf20Sopenharmony_ci	switch (hw->fc) {
15818c2ecf20Sopenharmony_ci	case E1000_FC_NONE:	/* 0 */
15828c2ecf20Sopenharmony_ci		/* Flow control (RX & TX) is completely disabled by a
15838c2ecf20Sopenharmony_ci		 * software over-ride.
15848c2ecf20Sopenharmony_ci		 */
15858c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
15868c2ecf20Sopenharmony_ci		break;
15878c2ecf20Sopenharmony_ci	case E1000_FC_RX_PAUSE:	/* 1 */
15888c2ecf20Sopenharmony_ci		/* RX Flow control is enabled, and TX Flow control is
15898c2ecf20Sopenharmony_ci		 * disabled, by a software over-ride.
15908c2ecf20Sopenharmony_ci		 */
15918c2ecf20Sopenharmony_ci		/* Since there really isn't a way to advertise that we are
15928c2ecf20Sopenharmony_ci		 * capable of RX Pause ONLY, we will advertise that we
15938c2ecf20Sopenharmony_ci		 * support both symmetric and asymmetric RX PAUSE.  Later
15948c2ecf20Sopenharmony_ci		 * (in e1000_config_fc_after_link_up) we will disable the
15958c2ecf20Sopenharmony_ci		 * hw's ability to send PAUSE frames.
15968c2ecf20Sopenharmony_ci		 */
15978c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
15988c2ecf20Sopenharmony_ci		break;
15998c2ecf20Sopenharmony_ci	case E1000_FC_TX_PAUSE:	/* 2 */
16008c2ecf20Sopenharmony_ci		/* TX Flow control is enabled, and RX Flow control is
16018c2ecf20Sopenharmony_ci		 * disabled, by a software over-ride.
16028c2ecf20Sopenharmony_ci		 */
16038c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
16048c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
16058c2ecf20Sopenharmony_ci		break;
16068c2ecf20Sopenharmony_ci	case E1000_FC_FULL:	/* 3 */
16078c2ecf20Sopenharmony_ci		/* Flow control (both RX and TX) is enabled by a software
16088c2ecf20Sopenharmony_ci		 * over-ride.
16098c2ecf20Sopenharmony_ci		 */
16108c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
16118c2ecf20Sopenharmony_ci		break;
16128c2ecf20Sopenharmony_ci	default:
16138c2ecf20Sopenharmony_ci		e_dbg("Flow control param set incorrectly\n");
16148c2ecf20Sopenharmony_ci		return -E1000_ERR_CONFIG;
16158c2ecf20Sopenharmony_ci	}
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
16188c2ecf20Sopenharmony_ci	if (ret_val)
16198c2ecf20Sopenharmony_ci		return ret_val;
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
16228c2ecf20Sopenharmony_ci
16238c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_8201) {
16248c2ecf20Sopenharmony_ci		mii_1000t_ctrl_reg = 0;
16258c2ecf20Sopenharmony_ci	} else {
16268c2ecf20Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
16278c2ecf20Sopenharmony_ci					      mii_1000t_ctrl_reg);
16288c2ecf20Sopenharmony_ci		if (ret_val)
16298c2ecf20Sopenharmony_ci			return ret_val;
16308c2ecf20Sopenharmony_ci	}
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
16338c2ecf20Sopenharmony_ci}
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci/**
16368c2ecf20Sopenharmony_ci * e1000_phy_force_speed_duplex - force link settings
16378c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
16388c2ecf20Sopenharmony_ci *
16398c2ecf20Sopenharmony_ci * Force PHY speed and duplex settings to hw->forced_speed_duplex
16408c2ecf20Sopenharmony_ci */
16418c2ecf20Sopenharmony_cistatic s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
16428c2ecf20Sopenharmony_ci{
16438c2ecf20Sopenharmony_ci	u32 ctrl;
16448c2ecf20Sopenharmony_ci	s32 ret_val;
16458c2ecf20Sopenharmony_ci	u16 mii_ctrl_reg;
16468c2ecf20Sopenharmony_ci	u16 mii_status_reg;
16478c2ecf20Sopenharmony_ci	u16 phy_data;
16488c2ecf20Sopenharmony_ci	u16 i;
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	/* Turn off Flow control if we are forcing speed and duplex. */
16518c2ecf20Sopenharmony_ci	hw->fc = E1000_FC_NONE;
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_ci	e_dbg("hw->fc = %d\n", hw->fc);
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ci	/* Read the Device Control Register. */
16568c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci	/* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
16598c2ecf20Sopenharmony_ci	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
16608c2ecf20Sopenharmony_ci	ctrl &= ~(DEVICE_SPEED_MASK);
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci	/* Clear the Auto Speed Detect Enable bit. */
16638c2ecf20Sopenharmony_ci	ctrl &= ~E1000_CTRL_ASDE;
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	/* Read the MII Control Register. */
16668c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg);
16678c2ecf20Sopenharmony_ci	if (ret_val)
16688c2ecf20Sopenharmony_ci		return ret_val;
16698c2ecf20Sopenharmony_ci
16708c2ecf20Sopenharmony_ci	/* We need to disable autoneg in order to force link and duplex. */
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	/* Are we forcing Full or Half Duplex? */
16758c2ecf20Sopenharmony_ci	if (hw->forced_speed_duplex == e1000_100_full ||
16768c2ecf20Sopenharmony_ci	    hw->forced_speed_duplex == e1000_10_full) {
16778c2ecf20Sopenharmony_ci		/* We want to force full duplex so we SET the full duplex bits
16788c2ecf20Sopenharmony_ci		 * in the Device and MII Control Registers.
16798c2ecf20Sopenharmony_ci		 */
16808c2ecf20Sopenharmony_ci		ctrl |= E1000_CTRL_FD;
16818c2ecf20Sopenharmony_ci		mii_ctrl_reg |= MII_CR_FULL_DUPLEX;
16828c2ecf20Sopenharmony_ci		e_dbg("Full Duplex\n");
16838c2ecf20Sopenharmony_ci	} else {
16848c2ecf20Sopenharmony_ci		/* We want to force half duplex so we CLEAR the full duplex bits
16858c2ecf20Sopenharmony_ci		 * in the Device and MII Control Registers.
16868c2ecf20Sopenharmony_ci		 */
16878c2ecf20Sopenharmony_ci		ctrl &= ~E1000_CTRL_FD;
16888c2ecf20Sopenharmony_ci		mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX;
16898c2ecf20Sopenharmony_ci		e_dbg("Half Duplex\n");
16908c2ecf20Sopenharmony_ci	}
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	/* Are we forcing 100Mbps??? */
16938c2ecf20Sopenharmony_ci	if (hw->forced_speed_duplex == e1000_100_full ||
16948c2ecf20Sopenharmony_ci	    hw->forced_speed_duplex == e1000_100_half) {
16958c2ecf20Sopenharmony_ci		/* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */
16968c2ecf20Sopenharmony_ci		ctrl |= E1000_CTRL_SPD_100;
16978c2ecf20Sopenharmony_ci		mii_ctrl_reg |= MII_CR_SPEED_100;
16988c2ecf20Sopenharmony_ci		mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
16998c2ecf20Sopenharmony_ci		e_dbg("Forcing 100mb ");
17008c2ecf20Sopenharmony_ci	} else {
17018c2ecf20Sopenharmony_ci		/* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */
17028c2ecf20Sopenharmony_ci		ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
17038c2ecf20Sopenharmony_ci		mii_ctrl_reg |= MII_CR_SPEED_10;
17048c2ecf20Sopenharmony_ci		mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
17058c2ecf20Sopenharmony_ci		e_dbg("Forcing 10mb ");
17068c2ecf20Sopenharmony_ci	}
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci	e1000_config_collision_dist(hw);
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci	/* Write the configured values back to the Device Control Reg. */
17118c2ecf20Sopenharmony_ci	ew32(CTRL, ctrl);
17128c2ecf20Sopenharmony_ci
17138c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_m88) {
17148c2ecf20Sopenharmony_ci		ret_val =
17158c2ecf20Sopenharmony_ci		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
17168c2ecf20Sopenharmony_ci		if (ret_val)
17178c2ecf20Sopenharmony_ci			return ret_val;
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci		/* Clear Auto-Crossover to force MDI manually. M88E1000 requires
17208c2ecf20Sopenharmony_ci		 * MDI forced whenever speed are duplex are forced.
17218c2ecf20Sopenharmony_ci		 */
17228c2ecf20Sopenharmony_ci		phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
17238c2ecf20Sopenharmony_ci		ret_val =
17248c2ecf20Sopenharmony_ci		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
17258c2ecf20Sopenharmony_ci		if (ret_val)
17268c2ecf20Sopenharmony_ci			return ret_val;
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_ci		e_dbg("M88E1000 PSCR: %x\n", phy_data);
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci		/* Need to reset the PHY or these changes will be ignored */
17318c2ecf20Sopenharmony_ci		mii_ctrl_reg |= MII_CR_RESET;
17328c2ecf20Sopenharmony_ci
17338c2ecf20Sopenharmony_ci		/* Disable MDI-X support for 10/100 */
17348c2ecf20Sopenharmony_ci	} else {
17358c2ecf20Sopenharmony_ci		/* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
17368c2ecf20Sopenharmony_ci		 * forced whenever speed or duplex are forced.
17378c2ecf20Sopenharmony_ci		 */
17388c2ecf20Sopenharmony_ci		ret_val =
17398c2ecf20Sopenharmony_ci		    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
17408c2ecf20Sopenharmony_ci		if (ret_val)
17418c2ecf20Sopenharmony_ci			return ret_val;
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci		phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
17448c2ecf20Sopenharmony_ci		phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_ci		ret_val =
17478c2ecf20Sopenharmony_ci		    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
17488c2ecf20Sopenharmony_ci		if (ret_val)
17498c2ecf20Sopenharmony_ci			return ret_val;
17508c2ecf20Sopenharmony_ci	}
17518c2ecf20Sopenharmony_ci
17528c2ecf20Sopenharmony_ci	/* Write back the modified PHY MII control register. */
17538c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg);
17548c2ecf20Sopenharmony_ci	if (ret_val)
17558c2ecf20Sopenharmony_ci		return ret_val;
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_ci	udelay(1);
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	/* The wait_autoneg_complete flag may be a little misleading here.
17608c2ecf20Sopenharmony_ci	 * Since we are forcing speed and duplex, Auto-Neg is not enabled.
17618c2ecf20Sopenharmony_ci	 * But we do want to delay for a period while forcing only so we
17628c2ecf20Sopenharmony_ci	 * don't generate false No Link messages.  So we will wait here
17638c2ecf20Sopenharmony_ci	 * only if the user has set wait_autoneg_complete to 1, which is
17648c2ecf20Sopenharmony_ci	 * the default.
17658c2ecf20Sopenharmony_ci	 */
17668c2ecf20Sopenharmony_ci	if (hw->wait_autoneg_complete) {
17678c2ecf20Sopenharmony_ci		/* We will wait for autoneg to complete. */
17688c2ecf20Sopenharmony_ci		e_dbg("Waiting for forced speed/duplex link.\n");
17698c2ecf20Sopenharmony_ci		mii_status_reg = 0;
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci		/* Wait for autoneg to complete or 4.5 seconds to expire */
17728c2ecf20Sopenharmony_ci		for (i = PHY_FORCE_TIME; i > 0; i--) {
17738c2ecf20Sopenharmony_ci			/* Read the MII Status Register and wait for Auto-Neg
17748c2ecf20Sopenharmony_ci			 * Complete bit to be set.
17758c2ecf20Sopenharmony_ci			 */
17768c2ecf20Sopenharmony_ci			ret_val =
17778c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
17788c2ecf20Sopenharmony_ci			if (ret_val)
17798c2ecf20Sopenharmony_ci				return ret_val;
17808c2ecf20Sopenharmony_ci
17818c2ecf20Sopenharmony_ci			ret_val =
17828c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
17838c2ecf20Sopenharmony_ci			if (ret_val)
17848c2ecf20Sopenharmony_ci				return ret_val;
17858c2ecf20Sopenharmony_ci
17868c2ecf20Sopenharmony_ci			if (mii_status_reg & MII_SR_LINK_STATUS)
17878c2ecf20Sopenharmony_ci				break;
17888c2ecf20Sopenharmony_ci			msleep(100);
17898c2ecf20Sopenharmony_ci		}
17908c2ecf20Sopenharmony_ci		if ((i == 0) && (hw->phy_type == e1000_phy_m88)) {
17918c2ecf20Sopenharmony_ci			/* We didn't get link.  Reset the DSP and wait again
17928c2ecf20Sopenharmony_ci			 * for link.
17938c2ecf20Sopenharmony_ci			 */
17948c2ecf20Sopenharmony_ci			ret_val = e1000_phy_reset_dsp(hw);
17958c2ecf20Sopenharmony_ci			if (ret_val) {
17968c2ecf20Sopenharmony_ci				e_dbg("Error Resetting PHY DSP\n");
17978c2ecf20Sopenharmony_ci				return ret_val;
17988c2ecf20Sopenharmony_ci			}
17998c2ecf20Sopenharmony_ci		}
18008c2ecf20Sopenharmony_ci		/* This loop will early-out if the link condition has been
18018c2ecf20Sopenharmony_ci		 * met
18028c2ecf20Sopenharmony_ci		 */
18038c2ecf20Sopenharmony_ci		for (i = PHY_FORCE_TIME; i > 0; i--) {
18048c2ecf20Sopenharmony_ci			if (mii_status_reg & MII_SR_LINK_STATUS)
18058c2ecf20Sopenharmony_ci				break;
18068c2ecf20Sopenharmony_ci			msleep(100);
18078c2ecf20Sopenharmony_ci			/* Read the MII Status Register and wait for Auto-Neg
18088c2ecf20Sopenharmony_ci			 * Complete bit to be set.
18098c2ecf20Sopenharmony_ci			 */
18108c2ecf20Sopenharmony_ci			ret_val =
18118c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
18128c2ecf20Sopenharmony_ci			if (ret_val)
18138c2ecf20Sopenharmony_ci				return ret_val;
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci			ret_val =
18168c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
18178c2ecf20Sopenharmony_ci			if (ret_val)
18188c2ecf20Sopenharmony_ci				return ret_val;
18198c2ecf20Sopenharmony_ci		}
18208c2ecf20Sopenharmony_ci	}
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_m88) {
18238c2ecf20Sopenharmony_ci		/* Because we reset the PHY above, we need to re-force TX_CLK in
18248c2ecf20Sopenharmony_ci		 * the Extended PHY Specific Control Register to 25MHz clock.
18258c2ecf20Sopenharmony_ci		 * This value defaults back to a 2.5MHz clock when the PHY is
18268c2ecf20Sopenharmony_ci		 * reset.
18278c2ecf20Sopenharmony_ci		 */
18288c2ecf20Sopenharmony_ci		ret_val =
18298c2ecf20Sopenharmony_ci		    e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
18308c2ecf20Sopenharmony_ci				       &phy_data);
18318c2ecf20Sopenharmony_ci		if (ret_val)
18328c2ecf20Sopenharmony_ci			return ret_val;
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_ci		phy_data |= M88E1000_EPSCR_TX_CLK_25;
18358c2ecf20Sopenharmony_ci		ret_val =
18368c2ecf20Sopenharmony_ci		    e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
18378c2ecf20Sopenharmony_ci					phy_data);
18388c2ecf20Sopenharmony_ci		if (ret_val)
18398c2ecf20Sopenharmony_ci			return ret_val;
18408c2ecf20Sopenharmony_ci
18418c2ecf20Sopenharmony_ci		/* In addition, because of the s/w reset above, we need to
18428c2ecf20Sopenharmony_ci		 * enable CRS on Tx.  This must be set for both full and half
18438c2ecf20Sopenharmony_ci		 * duplex operation.
18448c2ecf20Sopenharmony_ci		 */
18458c2ecf20Sopenharmony_ci		ret_val =
18468c2ecf20Sopenharmony_ci		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
18478c2ecf20Sopenharmony_ci		if (ret_val)
18488c2ecf20Sopenharmony_ci			return ret_val;
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci		phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
18518c2ecf20Sopenharmony_ci		ret_val =
18528c2ecf20Sopenharmony_ci		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
18538c2ecf20Sopenharmony_ci		if (ret_val)
18548c2ecf20Sopenharmony_ci			return ret_val;
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ci		if ((hw->mac_type == e1000_82544 ||
18578c2ecf20Sopenharmony_ci		     hw->mac_type == e1000_82543) &&
18588c2ecf20Sopenharmony_ci		    (!hw->autoneg) &&
18598c2ecf20Sopenharmony_ci		    (hw->forced_speed_duplex == e1000_10_full ||
18608c2ecf20Sopenharmony_ci		     hw->forced_speed_duplex == e1000_10_half)) {
18618c2ecf20Sopenharmony_ci			ret_val = e1000_polarity_reversal_workaround(hw);
18628c2ecf20Sopenharmony_ci			if (ret_val)
18638c2ecf20Sopenharmony_ci				return ret_val;
18648c2ecf20Sopenharmony_ci		}
18658c2ecf20Sopenharmony_ci	}
18668c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
18678c2ecf20Sopenharmony_ci}
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci/**
18708c2ecf20Sopenharmony_ci * e1000_config_collision_dist - set collision distance register
18718c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
18728c2ecf20Sopenharmony_ci *
18738c2ecf20Sopenharmony_ci * Sets the collision distance in the Transmit Control register.
18748c2ecf20Sopenharmony_ci * Link should have been established previously. Reads the speed and duplex
18758c2ecf20Sopenharmony_ci * information from the Device Status register.
18768c2ecf20Sopenharmony_ci */
18778c2ecf20Sopenharmony_civoid e1000_config_collision_dist(struct e1000_hw *hw)
18788c2ecf20Sopenharmony_ci{
18798c2ecf20Sopenharmony_ci	u32 tctl, coll_dist;
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci	if (hw->mac_type < e1000_82543)
18828c2ecf20Sopenharmony_ci		coll_dist = E1000_COLLISION_DISTANCE_82542;
18838c2ecf20Sopenharmony_ci	else
18848c2ecf20Sopenharmony_ci		coll_dist = E1000_COLLISION_DISTANCE;
18858c2ecf20Sopenharmony_ci
18868c2ecf20Sopenharmony_ci	tctl = er32(TCTL);
18878c2ecf20Sopenharmony_ci
18888c2ecf20Sopenharmony_ci	tctl &= ~E1000_TCTL_COLD;
18898c2ecf20Sopenharmony_ci	tctl |= coll_dist << E1000_COLD_SHIFT;
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci	ew32(TCTL, tctl);
18928c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
18938c2ecf20Sopenharmony_ci}
18948c2ecf20Sopenharmony_ci
18958c2ecf20Sopenharmony_ci/**
18968c2ecf20Sopenharmony_ci * e1000_config_mac_to_phy - sync phy and mac settings
18978c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
18988c2ecf20Sopenharmony_ci *
18998c2ecf20Sopenharmony_ci * Sets MAC speed and duplex settings to reflect the those in the PHY
19008c2ecf20Sopenharmony_ci * The contents of the PHY register containing the needed information need to
19018c2ecf20Sopenharmony_ci * be passed in.
19028c2ecf20Sopenharmony_ci */
19038c2ecf20Sopenharmony_cistatic s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
19048c2ecf20Sopenharmony_ci{
19058c2ecf20Sopenharmony_ci	u32 ctrl;
19068c2ecf20Sopenharmony_ci	s32 ret_val;
19078c2ecf20Sopenharmony_ci	u16 phy_data;
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci	/* 82544 or newer MAC, Auto Speed Detection takes care of
19108c2ecf20Sopenharmony_ci	 * MAC speed/duplex configuration.
19118c2ecf20Sopenharmony_ci	 */
19128c2ecf20Sopenharmony_ci	if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100))
19138c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci	/* Read the Device Control Register and set the bits to Force Speed
19168c2ecf20Sopenharmony_ci	 * and Duplex.
19178c2ecf20Sopenharmony_ci	 */
19188c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
19198c2ecf20Sopenharmony_ci	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
19208c2ecf20Sopenharmony_ci	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
19218c2ecf20Sopenharmony_ci
19228c2ecf20Sopenharmony_ci	switch (hw->phy_type) {
19238c2ecf20Sopenharmony_ci	case e1000_phy_8201:
19248c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
19258c2ecf20Sopenharmony_ci		if (ret_val)
19268c2ecf20Sopenharmony_ci			return ret_val;
19278c2ecf20Sopenharmony_ci
19288c2ecf20Sopenharmony_ci		if (phy_data & RTL_PHY_CTRL_FD)
19298c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_FD;
19308c2ecf20Sopenharmony_ci		else
19318c2ecf20Sopenharmony_ci			ctrl &= ~E1000_CTRL_FD;
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ci		if (phy_data & RTL_PHY_CTRL_SPD_100)
19348c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SPD_100;
19358c2ecf20Sopenharmony_ci		else
19368c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SPD_10;
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_ci		e1000_config_collision_dist(hw);
19398c2ecf20Sopenharmony_ci		break;
19408c2ecf20Sopenharmony_ci	default:
19418c2ecf20Sopenharmony_ci		/* Set up duplex in the Device Control and Transmit Control
19428c2ecf20Sopenharmony_ci		 * registers depending on negotiated values.
19438c2ecf20Sopenharmony_ci		 */
19448c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
19458c2ecf20Sopenharmony_ci					     &phy_data);
19468c2ecf20Sopenharmony_ci		if (ret_val)
19478c2ecf20Sopenharmony_ci			return ret_val;
19488c2ecf20Sopenharmony_ci
19498c2ecf20Sopenharmony_ci		if (phy_data & M88E1000_PSSR_DPLX)
19508c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_FD;
19518c2ecf20Sopenharmony_ci		else
19528c2ecf20Sopenharmony_ci			ctrl &= ~E1000_CTRL_FD;
19538c2ecf20Sopenharmony_ci
19548c2ecf20Sopenharmony_ci		e1000_config_collision_dist(hw);
19558c2ecf20Sopenharmony_ci
19568c2ecf20Sopenharmony_ci		/* Set up speed in the Device Control register depending on
19578c2ecf20Sopenharmony_ci		 * negotiated values.
19588c2ecf20Sopenharmony_ci		 */
19598c2ecf20Sopenharmony_ci		if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
19608c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SPD_1000;
19618c2ecf20Sopenharmony_ci		else if ((phy_data & M88E1000_PSSR_SPEED) ==
19628c2ecf20Sopenharmony_ci			 M88E1000_PSSR_100MBS)
19638c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SPD_100;
19648c2ecf20Sopenharmony_ci	}
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_ci	/* Write the configured values back to the Device Control Reg. */
19678c2ecf20Sopenharmony_ci	ew32(CTRL, ctrl);
19688c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
19698c2ecf20Sopenharmony_ci}
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci/**
19728c2ecf20Sopenharmony_ci * e1000_force_mac_fc - force flow control settings
19738c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
19748c2ecf20Sopenharmony_ci *
19758c2ecf20Sopenharmony_ci * Forces the MAC's flow control settings.
19768c2ecf20Sopenharmony_ci * Sets the TFCE and RFCE bits in the device control register to reflect
19778c2ecf20Sopenharmony_ci * the adapter settings. TFCE and RFCE need to be explicitly set by
19788c2ecf20Sopenharmony_ci * software when a Copper PHY is used because autonegotiation is managed
19798c2ecf20Sopenharmony_ci * by the PHY rather than the MAC. Software must also configure these
19808c2ecf20Sopenharmony_ci * bits when link is forced on a fiber connection.
19818c2ecf20Sopenharmony_ci */
19828c2ecf20Sopenharmony_cis32 e1000_force_mac_fc(struct e1000_hw *hw)
19838c2ecf20Sopenharmony_ci{
19848c2ecf20Sopenharmony_ci	u32 ctrl;
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ci	/* Get the current configuration of the Device Control Register */
19878c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	/* Because we didn't get link via the internal auto-negotiation
19908c2ecf20Sopenharmony_ci	 * mechanism (we either forced link or we got link via PHY
19918c2ecf20Sopenharmony_ci	 * auto-neg), we have to manually enable/disable transmit an
19928c2ecf20Sopenharmony_ci	 * receive flow control.
19938c2ecf20Sopenharmony_ci	 *
19948c2ecf20Sopenharmony_ci	 * The "Case" statement below enables/disable flow control
19958c2ecf20Sopenharmony_ci	 * according to the "hw->fc" parameter.
19968c2ecf20Sopenharmony_ci	 *
19978c2ecf20Sopenharmony_ci	 * The possible values of the "fc" parameter are:
19988c2ecf20Sopenharmony_ci	 *      0:  Flow control is completely disabled
19998c2ecf20Sopenharmony_ci	 *      1:  Rx flow control is enabled (we can receive pause
20008c2ecf20Sopenharmony_ci	 *          frames but not send pause frames).
20018c2ecf20Sopenharmony_ci	 *      2:  Tx flow control is enabled (we can send pause frames
20028c2ecf20Sopenharmony_ci	 *          frames but we do not receive pause frames).
20038c2ecf20Sopenharmony_ci	 *      3:  Both Rx and TX flow control (symmetric) is enabled.
20048c2ecf20Sopenharmony_ci	 *  other:  No other values should be possible at this point.
20058c2ecf20Sopenharmony_ci	 */
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	switch (hw->fc) {
20088c2ecf20Sopenharmony_ci	case E1000_FC_NONE:
20098c2ecf20Sopenharmony_ci		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
20108c2ecf20Sopenharmony_ci		break;
20118c2ecf20Sopenharmony_ci	case E1000_FC_RX_PAUSE:
20128c2ecf20Sopenharmony_ci		ctrl &= (~E1000_CTRL_TFCE);
20138c2ecf20Sopenharmony_ci		ctrl |= E1000_CTRL_RFCE;
20148c2ecf20Sopenharmony_ci		break;
20158c2ecf20Sopenharmony_ci	case E1000_FC_TX_PAUSE:
20168c2ecf20Sopenharmony_ci		ctrl &= (~E1000_CTRL_RFCE);
20178c2ecf20Sopenharmony_ci		ctrl |= E1000_CTRL_TFCE;
20188c2ecf20Sopenharmony_ci		break;
20198c2ecf20Sopenharmony_ci	case E1000_FC_FULL:
20208c2ecf20Sopenharmony_ci		ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
20218c2ecf20Sopenharmony_ci		break;
20228c2ecf20Sopenharmony_ci	default:
20238c2ecf20Sopenharmony_ci		e_dbg("Flow control param set incorrectly\n");
20248c2ecf20Sopenharmony_ci		return -E1000_ERR_CONFIG;
20258c2ecf20Sopenharmony_ci	}
20268c2ecf20Sopenharmony_ci
20278c2ecf20Sopenharmony_ci	/* Disable TX Flow Control for 82542 (rev 2.0) */
20288c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0)
20298c2ecf20Sopenharmony_ci		ctrl &= (~E1000_CTRL_TFCE);
20308c2ecf20Sopenharmony_ci
20318c2ecf20Sopenharmony_ci	ew32(CTRL, ctrl);
20328c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
20338c2ecf20Sopenharmony_ci}
20348c2ecf20Sopenharmony_ci
20358c2ecf20Sopenharmony_ci/**
20368c2ecf20Sopenharmony_ci * e1000_config_fc_after_link_up - configure flow control after autoneg
20378c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
20388c2ecf20Sopenharmony_ci *
20398c2ecf20Sopenharmony_ci * Configures flow control settings after link is established
20408c2ecf20Sopenharmony_ci * Should be called immediately after a valid link has been established.
20418c2ecf20Sopenharmony_ci * Forces MAC flow control settings if link was forced. When in MII/GMII mode
20428c2ecf20Sopenharmony_ci * and autonegotiation is enabled, the MAC flow control settings will be set
20438c2ecf20Sopenharmony_ci * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
20448c2ecf20Sopenharmony_ci * and RFCE bits will be automatically set to the negotiated flow control mode.
20458c2ecf20Sopenharmony_ci */
20468c2ecf20Sopenharmony_cistatic s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
20478c2ecf20Sopenharmony_ci{
20488c2ecf20Sopenharmony_ci	s32 ret_val;
20498c2ecf20Sopenharmony_ci	u16 mii_status_reg;
20508c2ecf20Sopenharmony_ci	u16 mii_nway_adv_reg;
20518c2ecf20Sopenharmony_ci	u16 mii_nway_lp_ability_reg;
20528c2ecf20Sopenharmony_ci	u16 speed;
20538c2ecf20Sopenharmony_ci	u16 duplex;
20548c2ecf20Sopenharmony_ci
20558c2ecf20Sopenharmony_ci	/* Check for the case where we have fiber media and auto-neg failed
20568c2ecf20Sopenharmony_ci	 * so we had to force link.  In this case, we need to force the
20578c2ecf20Sopenharmony_ci	 * configuration of the MAC to match the "fc" parameter.
20588c2ecf20Sopenharmony_ci	 */
20598c2ecf20Sopenharmony_ci	if (((hw->media_type == e1000_media_type_fiber) &&
20608c2ecf20Sopenharmony_ci	     (hw->autoneg_failed)) ||
20618c2ecf20Sopenharmony_ci	    ((hw->media_type == e1000_media_type_internal_serdes) &&
20628c2ecf20Sopenharmony_ci	     (hw->autoneg_failed)) ||
20638c2ecf20Sopenharmony_ci	    ((hw->media_type == e1000_media_type_copper) &&
20648c2ecf20Sopenharmony_ci	     (!hw->autoneg))) {
20658c2ecf20Sopenharmony_ci		ret_val = e1000_force_mac_fc(hw);
20668c2ecf20Sopenharmony_ci		if (ret_val) {
20678c2ecf20Sopenharmony_ci			e_dbg("Error forcing flow control settings\n");
20688c2ecf20Sopenharmony_ci			return ret_val;
20698c2ecf20Sopenharmony_ci		}
20708c2ecf20Sopenharmony_ci	}
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_ci	/* Check for the case where we have copper media and auto-neg is
20738c2ecf20Sopenharmony_ci	 * enabled.  In this case, we need to check and see if Auto-Neg
20748c2ecf20Sopenharmony_ci	 * has completed, and if so, how the PHY and link partner has
20758c2ecf20Sopenharmony_ci	 * flow control configured.
20768c2ecf20Sopenharmony_ci	 */
20778c2ecf20Sopenharmony_ci	if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) {
20788c2ecf20Sopenharmony_ci		/* Read the MII Status Register and check to see if AutoNeg
20798c2ecf20Sopenharmony_ci		 * has completed.  We read this twice because this reg has
20808c2ecf20Sopenharmony_ci		 * some "sticky" (latched) bits.
20818c2ecf20Sopenharmony_ci		 */
20828c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
20838c2ecf20Sopenharmony_ci		if (ret_val)
20848c2ecf20Sopenharmony_ci			return ret_val;
20858c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
20868c2ecf20Sopenharmony_ci		if (ret_val)
20878c2ecf20Sopenharmony_ci			return ret_val;
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_ci		if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
20908c2ecf20Sopenharmony_ci			/* The AutoNeg process has completed, so we now need to
20918c2ecf20Sopenharmony_ci			 * read both the Auto Negotiation Advertisement Register
20928c2ecf20Sopenharmony_ci			 * (Address 4) and the Auto_Negotiation Base Page
20938c2ecf20Sopenharmony_ci			 * Ability Register (Address 5) to determine how flow
20948c2ecf20Sopenharmony_ci			 * control was negotiated.
20958c2ecf20Sopenharmony_ci			 */
20968c2ecf20Sopenharmony_ci			ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
20978c2ecf20Sopenharmony_ci						     &mii_nway_adv_reg);
20988c2ecf20Sopenharmony_ci			if (ret_val)
20998c2ecf20Sopenharmony_ci				return ret_val;
21008c2ecf20Sopenharmony_ci			ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
21018c2ecf20Sopenharmony_ci						     &mii_nway_lp_ability_reg);
21028c2ecf20Sopenharmony_ci			if (ret_val)
21038c2ecf20Sopenharmony_ci				return ret_val;
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ci			/* Two bits in the Auto Negotiation Advertisement
21068c2ecf20Sopenharmony_ci			 * Register (Address 4) and two bits in the Auto
21078c2ecf20Sopenharmony_ci			 * Negotiation Base Page Ability Register (Address 5)
21088c2ecf20Sopenharmony_ci			 * determine flow control for both the PHY and the link
21098c2ecf20Sopenharmony_ci			 * partner.  The following table, taken out of the IEEE
21108c2ecf20Sopenharmony_ci			 * 802.3ab/D6.0 dated March 25, 1999, describes these
21118c2ecf20Sopenharmony_ci			 * PAUSE resolution bits and how flow control is
21128c2ecf20Sopenharmony_ci			 * determined based upon these settings.
21138c2ecf20Sopenharmony_ci			 * NOTE:  DC = Don't Care
21148c2ecf20Sopenharmony_ci			 *
21158c2ecf20Sopenharmony_ci			 *   LOCAL DEVICE  |   LINK PARTNER
21168c2ecf20Sopenharmony_ci			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
21178c2ecf20Sopenharmony_ci			 *-------|---------|-------|---------|------------------
21188c2ecf20Sopenharmony_ci			 *   0   |    0    |  DC   |   DC    | E1000_FC_NONE
21198c2ecf20Sopenharmony_ci			 *   0   |    1    |   0   |   DC    | E1000_FC_NONE
21208c2ecf20Sopenharmony_ci			 *   0   |    1    |   1   |    0    | E1000_FC_NONE
21218c2ecf20Sopenharmony_ci			 *   0   |    1    |   1   |    1    | E1000_FC_TX_PAUSE
21228c2ecf20Sopenharmony_ci			 *   1   |    0    |   0   |   DC    | E1000_FC_NONE
21238c2ecf20Sopenharmony_ci			 *   1   |   DC    |   1   |   DC    | E1000_FC_FULL
21248c2ecf20Sopenharmony_ci			 *   1   |    1    |   0   |    0    | E1000_FC_NONE
21258c2ecf20Sopenharmony_ci			 *   1   |    1    |   0   |    1    | E1000_FC_RX_PAUSE
21268c2ecf20Sopenharmony_ci			 *
21278c2ecf20Sopenharmony_ci			 */
21288c2ecf20Sopenharmony_ci			/* Are both PAUSE bits set to 1?  If so, this implies
21298c2ecf20Sopenharmony_ci			 * Symmetric Flow Control is enabled at both ends.  The
21308c2ecf20Sopenharmony_ci			 * ASM_DIR bits are irrelevant per the spec.
21318c2ecf20Sopenharmony_ci			 *
21328c2ecf20Sopenharmony_ci			 * For Symmetric Flow Control:
21338c2ecf20Sopenharmony_ci			 *
21348c2ecf20Sopenharmony_ci			 *   LOCAL DEVICE  |   LINK PARTNER
21358c2ecf20Sopenharmony_ci			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
21368c2ecf20Sopenharmony_ci			 *-------|---------|-------|---------|------------------
21378c2ecf20Sopenharmony_ci			 *   1   |   DC    |   1   |   DC    | E1000_FC_FULL
21388c2ecf20Sopenharmony_ci			 *
21398c2ecf20Sopenharmony_ci			 */
21408c2ecf20Sopenharmony_ci			if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
21418c2ecf20Sopenharmony_ci			    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
21428c2ecf20Sopenharmony_ci				/* Now we need to check if the user selected Rx
21438c2ecf20Sopenharmony_ci				 * ONLY of pause frames.  In this case, we had
21448c2ecf20Sopenharmony_ci				 * to advertise FULL flow control because we
21458c2ecf20Sopenharmony_ci				 * could not advertise Rx ONLY. Hence, we must
21468c2ecf20Sopenharmony_ci				 * now check to see if we need to turn OFF the
21478c2ecf20Sopenharmony_ci				 * TRANSMISSION of PAUSE frames.
21488c2ecf20Sopenharmony_ci				 */
21498c2ecf20Sopenharmony_ci				if (hw->original_fc == E1000_FC_FULL) {
21508c2ecf20Sopenharmony_ci					hw->fc = E1000_FC_FULL;
21518c2ecf20Sopenharmony_ci					e_dbg("Flow Control = FULL.\n");
21528c2ecf20Sopenharmony_ci				} else {
21538c2ecf20Sopenharmony_ci					hw->fc = E1000_FC_RX_PAUSE;
21548c2ecf20Sopenharmony_ci					e_dbg
21558c2ecf20Sopenharmony_ci					    ("Flow Control = RX PAUSE frames only.\n");
21568c2ecf20Sopenharmony_ci				}
21578c2ecf20Sopenharmony_ci			}
21588c2ecf20Sopenharmony_ci			/* For receiving PAUSE frames ONLY.
21598c2ecf20Sopenharmony_ci			 *
21608c2ecf20Sopenharmony_ci			 *   LOCAL DEVICE  |   LINK PARTNER
21618c2ecf20Sopenharmony_ci			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
21628c2ecf20Sopenharmony_ci			 *-------|---------|-------|---------|------------------
21638c2ecf20Sopenharmony_ci			 *   0   |    1    |   1   |    1    | E1000_FC_TX_PAUSE
21648c2ecf20Sopenharmony_ci			 *
21658c2ecf20Sopenharmony_ci			 */
21668c2ecf20Sopenharmony_ci			else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
21678c2ecf20Sopenharmony_ci				 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
21688c2ecf20Sopenharmony_ci				 (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
21698c2ecf20Sopenharmony_ci				 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
21708c2ecf20Sopenharmony_ci				hw->fc = E1000_FC_TX_PAUSE;
21718c2ecf20Sopenharmony_ci				e_dbg
21728c2ecf20Sopenharmony_ci				    ("Flow Control = TX PAUSE frames only.\n");
21738c2ecf20Sopenharmony_ci			}
21748c2ecf20Sopenharmony_ci			/* For transmitting PAUSE frames ONLY.
21758c2ecf20Sopenharmony_ci			 *
21768c2ecf20Sopenharmony_ci			 *   LOCAL DEVICE  |   LINK PARTNER
21778c2ecf20Sopenharmony_ci			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
21788c2ecf20Sopenharmony_ci			 *-------|---------|-------|---------|------------------
21798c2ecf20Sopenharmony_ci			 *   1   |    1    |   0   |    1    | E1000_FC_RX_PAUSE
21808c2ecf20Sopenharmony_ci			 *
21818c2ecf20Sopenharmony_ci			 */
21828c2ecf20Sopenharmony_ci			else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
21838c2ecf20Sopenharmony_ci				 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
21848c2ecf20Sopenharmony_ci				 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
21858c2ecf20Sopenharmony_ci				 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
21868c2ecf20Sopenharmony_ci				hw->fc = E1000_FC_RX_PAUSE;
21878c2ecf20Sopenharmony_ci				e_dbg
21888c2ecf20Sopenharmony_ci				    ("Flow Control = RX PAUSE frames only.\n");
21898c2ecf20Sopenharmony_ci			}
21908c2ecf20Sopenharmony_ci			/* Per the IEEE spec, at this point flow control should
21918c2ecf20Sopenharmony_ci			 * be disabled.  However, we want to consider that we
21928c2ecf20Sopenharmony_ci			 * could be connected to a legacy switch that doesn't
21938c2ecf20Sopenharmony_ci			 * advertise desired flow control, but can be forced on
21948c2ecf20Sopenharmony_ci			 * the link partner.  So if we advertised no flow
21958c2ecf20Sopenharmony_ci			 * control, that is what we will resolve to.  If we
21968c2ecf20Sopenharmony_ci			 * advertised some kind of receive capability (Rx Pause
21978c2ecf20Sopenharmony_ci			 * Only or Full Flow Control) and the link partner
21988c2ecf20Sopenharmony_ci			 * advertised none, we will configure ourselves to
21998c2ecf20Sopenharmony_ci			 * enable Rx Flow Control only.  We can do this safely
22008c2ecf20Sopenharmony_ci			 * for two reasons:  If the link partner really
22018c2ecf20Sopenharmony_ci			 * didn't want flow control enabled, and we enable Rx,
22028c2ecf20Sopenharmony_ci			 * no harm done since we won't be receiving any PAUSE
22038c2ecf20Sopenharmony_ci			 * frames anyway.  If the intent on the link partner was
22048c2ecf20Sopenharmony_ci			 * to have flow control enabled, then by us enabling Rx
22058c2ecf20Sopenharmony_ci			 * only, we can at least receive pause frames and
22068c2ecf20Sopenharmony_ci			 * process them. This is a good idea because in most
22078c2ecf20Sopenharmony_ci			 * cases, since we are predominantly a server NIC, more
22088c2ecf20Sopenharmony_ci			 * times than not we will be asked to delay transmission
22098c2ecf20Sopenharmony_ci			 * of packets than asking our link partner to pause
22108c2ecf20Sopenharmony_ci			 * transmission of frames.
22118c2ecf20Sopenharmony_ci			 */
22128c2ecf20Sopenharmony_ci			else if ((hw->original_fc == E1000_FC_NONE ||
22138c2ecf20Sopenharmony_ci				  hw->original_fc == E1000_FC_TX_PAUSE) ||
22148c2ecf20Sopenharmony_ci				 hw->fc_strict_ieee) {
22158c2ecf20Sopenharmony_ci				hw->fc = E1000_FC_NONE;
22168c2ecf20Sopenharmony_ci				e_dbg("Flow Control = NONE.\n");
22178c2ecf20Sopenharmony_ci			} else {
22188c2ecf20Sopenharmony_ci				hw->fc = E1000_FC_RX_PAUSE;
22198c2ecf20Sopenharmony_ci				e_dbg
22208c2ecf20Sopenharmony_ci				    ("Flow Control = RX PAUSE frames only.\n");
22218c2ecf20Sopenharmony_ci			}
22228c2ecf20Sopenharmony_ci
22238c2ecf20Sopenharmony_ci			/* Now we need to do one last check...  If we auto-
22248c2ecf20Sopenharmony_ci			 * negotiated to HALF DUPLEX, flow control should not be
22258c2ecf20Sopenharmony_ci			 * enabled per IEEE 802.3 spec.
22268c2ecf20Sopenharmony_ci			 */
22278c2ecf20Sopenharmony_ci			ret_val =
22288c2ecf20Sopenharmony_ci			    e1000_get_speed_and_duplex(hw, &speed, &duplex);
22298c2ecf20Sopenharmony_ci			if (ret_val) {
22308c2ecf20Sopenharmony_ci				e_dbg
22318c2ecf20Sopenharmony_ci				    ("Error getting link speed and duplex\n");
22328c2ecf20Sopenharmony_ci				return ret_val;
22338c2ecf20Sopenharmony_ci			}
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_ci			if (duplex == HALF_DUPLEX)
22368c2ecf20Sopenharmony_ci				hw->fc = E1000_FC_NONE;
22378c2ecf20Sopenharmony_ci
22388c2ecf20Sopenharmony_ci			/* Now we call a subroutine to actually force the MAC
22398c2ecf20Sopenharmony_ci			 * controller to use the correct flow control settings.
22408c2ecf20Sopenharmony_ci			 */
22418c2ecf20Sopenharmony_ci			ret_val = e1000_force_mac_fc(hw);
22428c2ecf20Sopenharmony_ci			if (ret_val) {
22438c2ecf20Sopenharmony_ci				e_dbg
22448c2ecf20Sopenharmony_ci				    ("Error forcing flow control settings\n");
22458c2ecf20Sopenharmony_ci				return ret_val;
22468c2ecf20Sopenharmony_ci			}
22478c2ecf20Sopenharmony_ci		} else {
22488c2ecf20Sopenharmony_ci			e_dbg
22498c2ecf20Sopenharmony_ci			    ("Copper PHY and Auto Neg has not completed.\n");
22508c2ecf20Sopenharmony_ci		}
22518c2ecf20Sopenharmony_ci	}
22528c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
22538c2ecf20Sopenharmony_ci}
22548c2ecf20Sopenharmony_ci
22558c2ecf20Sopenharmony_ci/**
22568c2ecf20Sopenharmony_ci * e1000_check_for_serdes_link_generic - Check for link (Serdes)
22578c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure
22588c2ecf20Sopenharmony_ci *
22598c2ecf20Sopenharmony_ci * Checks for link up on the hardware.  If link is not up and we have
22608c2ecf20Sopenharmony_ci * a signal, then we need to force link up.
22618c2ecf20Sopenharmony_ci */
22628c2ecf20Sopenharmony_cistatic s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
22638c2ecf20Sopenharmony_ci{
22648c2ecf20Sopenharmony_ci	u32 rxcw;
22658c2ecf20Sopenharmony_ci	u32 ctrl;
22668c2ecf20Sopenharmony_ci	u32 status;
22678c2ecf20Sopenharmony_ci	s32 ret_val = E1000_SUCCESS;
22688c2ecf20Sopenharmony_ci
22698c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
22708c2ecf20Sopenharmony_ci	status = er32(STATUS);
22718c2ecf20Sopenharmony_ci	rxcw = er32(RXCW);
22728c2ecf20Sopenharmony_ci
22738c2ecf20Sopenharmony_ci	/* If we don't have link (auto-negotiation failed or link partner
22748c2ecf20Sopenharmony_ci	 * cannot auto-negotiate), and our link partner is not trying to
22758c2ecf20Sopenharmony_ci	 * auto-negotiate with us (we are receiving idles or data),
22768c2ecf20Sopenharmony_ci	 * we need to force link up. We also need to give auto-negotiation
22778c2ecf20Sopenharmony_ci	 * time to complete.
22788c2ecf20Sopenharmony_ci	 */
22798c2ecf20Sopenharmony_ci	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
22808c2ecf20Sopenharmony_ci	if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
22818c2ecf20Sopenharmony_ci		if (hw->autoneg_failed == 0) {
22828c2ecf20Sopenharmony_ci			hw->autoneg_failed = 1;
22838c2ecf20Sopenharmony_ci			goto out;
22848c2ecf20Sopenharmony_ci		}
22858c2ecf20Sopenharmony_ci		e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");
22868c2ecf20Sopenharmony_ci
22878c2ecf20Sopenharmony_ci		/* Disable auto-negotiation in the TXCW register */
22888c2ecf20Sopenharmony_ci		ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
22898c2ecf20Sopenharmony_ci
22908c2ecf20Sopenharmony_ci		/* Force link-up and also force full-duplex. */
22918c2ecf20Sopenharmony_ci		ctrl = er32(CTRL);
22928c2ecf20Sopenharmony_ci		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
22938c2ecf20Sopenharmony_ci		ew32(CTRL, ctrl);
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_ci		/* Configure Flow Control after forcing link up. */
22968c2ecf20Sopenharmony_ci		ret_val = e1000_config_fc_after_link_up(hw);
22978c2ecf20Sopenharmony_ci		if (ret_val) {
22988c2ecf20Sopenharmony_ci			e_dbg("Error configuring flow control\n");
22998c2ecf20Sopenharmony_ci			goto out;
23008c2ecf20Sopenharmony_ci		}
23018c2ecf20Sopenharmony_ci	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
23028c2ecf20Sopenharmony_ci		/* If we are forcing link and we are receiving /C/ ordered
23038c2ecf20Sopenharmony_ci		 * sets, re-enable auto-negotiation in the TXCW register
23048c2ecf20Sopenharmony_ci		 * and disable forced link in the Device Control register
23058c2ecf20Sopenharmony_ci		 * in an attempt to auto-negotiate with our link partner.
23068c2ecf20Sopenharmony_ci		 */
23078c2ecf20Sopenharmony_ci		e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");
23088c2ecf20Sopenharmony_ci		ew32(TXCW, hw->txcw);
23098c2ecf20Sopenharmony_ci		ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
23108c2ecf20Sopenharmony_ci
23118c2ecf20Sopenharmony_ci		hw->serdes_has_link = true;
23128c2ecf20Sopenharmony_ci	} else if (!(E1000_TXCW_ANE & er32(TXCW))) {
23138c2ecf20Sopenharmony_ci		/* If we force link for non-auto-negotiation switch, check
23148c2ecf20Sopenharmony_ci		 * link status based on MAC synchronization for internal
23158c2ecf20Sopenharmony_ci		 * serdes media type.
23168c2ecf20Sopenharmony_ci		 */
23178c2ecf20Sopenharmony_ci		/* SYNCH bit and IV bit are sticky. */
23188c2ecf20Sopenharmony_ci		udelay(10);
23198c2ecf20Sopenharmony_ci		rxcw = er32(RXCW);
23208c2ecf20Sopenharmony_ci		if (rxcw & E1000_RXCW_SYNCH) {
23218c2ecf20Sopenharmony_ci			if (!(rxcw & E1000_RXCW_IV)) {
23228c2ecf20Sopenharmony_ci				hw->serdes_has_link = true;
23238c2ecf20Sopenharmony_ci				e_dbg("SERDES: Link up - forced.\n");
23248c2ecf20Sopenharmony_ci			}
23258c2ecf20Sopenharmony_ci		} else {
23268c2ecf20Sopenharmony_ci			hw->serdes_has_link = false;
23278c2ecf20Sopenharmony_ci			e_dbg("SERDES: Link down - force failed.\n");
23288c2ecf20Sopenharmony_ci		}
23298c2ecf20Sopenharmony_ci	}
23308c2ecf20Sopenharmony_ci
23318c2ecf20Sopenharmony_ci	if (E1000_TXCW_ANE & er32(TXCW)) {
23328c2ecf20Sopenharmony_ci		status = er32(STATUS);
23338c2ecf20Sopenharmony_ci		if (status & E1000_STATUS_LU) {
23348c2ecf20Sopenharmony_ci			/* SYNCH bit and IV bit are sticky, so reread rxcw. */
23358c2ecf20Sopenharmony_ci			udelay(10);
23368c2ecf20Sopenharmony_ci			rxcw = er32(RXCW);
23378c2ecf20Sopenharmony_ci			if (rxcw & E1000_RXCW_SYNCH) {
23388c2ecf20Sopenharmony_ci				if (!(rxcw & E1000_RXCW_IV)) {
23398c2ecf20Sopenharmony_ci					hw->serdes_has_link = true;
23408c2ecf20Sopenharmony_ci					e_dbg("SERDES: Link up - autoneg "
23418c2ecf20Sopenharmony_ci						 "completed successfully.\n");
23428c2ecf20Sopenharmony_ci				} else {
23438c2ecf20Sopenharmony_ci					hw->serdes_has_link = false;
23448c2ecf20Sopenharmony_ci					e_dbg("SERDES: Link down - invalid"
23458c2ecf20Sopenharmony_ci						 "codewords detected in autoneg.\n");
23468c2ecf20Sopenharmony_ci				}
23478c2ecf20Sopenharmony_ci			} else {
23488c2ecf20Sopenharmony_ci				hw->serdes_has_link = false;
23498c2ecf20Sopenharmony_ci				e_dbg("SERDES: Link down - no sync.\n");
23508c2ecf20Sopenharmony_ci			}
23518c2ecf20Sopenharmony_ci		} else {
23528c2ecf20Sopenharmony_ci			hw->serdes_has_link = false;
23538c2ecf20Sopenharmony_ci			e_dbg("SERDES: Link down - autoneg failed\n");
23548c2ecf20Sopenharmony_ci		}
23558c2ecf20Sopenharmony_ci	}
23568c2ecf20Sopenharmony_ci
23578c2ecf20Sopenharmony_ci      out:
23588c2ecf20Sopenharmony_ci	return ret_val;
23598c2ecf20Sopenharmony_ci}
23608c2ecf20Sopenharmony_ci
23618c2ecf20Sopenharmony_ci/**
23628c2ecf20Sopenharmony_ci * e1000_check_for_link
23638c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
23648c2ecf20Sopenharmony_ci *
23658c2ecf20Sopenharmony_ci * Checks to see if the link status of the hardware has changed.
23668c2ecf20Sopenharmony_ci * Called by any function that needs to check the link status of the adapter.
23678c2ecf20Sopenharmony_ci */
23688c2ecf20Sopenharmony_cis32 e1000_check_for_link(struct e1000_hw *hw)
23698c2ecf20Sopenharmony_ci{
23708c2ecf20Sopenharmony_ci	u32 status;
23718c2ecf20Sopenharmony_ci	u32 rctl;
23728c2ecf20Sopenharmony_ci	u32 icr;
23738c2ecf20Sopenharmony_ci	s32 ret_val;
23748c2ecf20Sopenharmony_ci	u16 phy_data;
23758c2ecf20Sopenharmony_ci
23768c2ecf20Sopenharmony_ci	er32(CTRL);
23778c2ecf20Sopenharmony_ci	status = er32(STATUS);
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_ci	/* On adapters with a MAC newer than 82544, SW Definable pin 1 will be
23808c2ecf20Sopenharmony_ci	 * set when the optics detect a signal. On older adapters, it will be
23818c2ecf20Sopenharmony_ci	 * cleared when there is a signal.  This applies to fiber media only.
23828c2ecf20Sopenharmony_ci	 */
23838c2ecf20Sopenharmony_ci	if ((hw->media_type == e1000_media_type_fiber) ||
23848c2ecf20Sopenharmony_ci	    (hw->media_type == e1000_media_type_internal_serdes)) {
23858c2ecf20Sopenharmony_ci		er32(RXCW);
23868c2ecf20Sopenharmony_ci
23878c2ecf20Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
23888c2ecf20Sopenharmony_ci			if (status & E1000_STATUS_LU)
23898c2ecf20Sopenharmony_ci				hw->get_link_status = false;
23908c2ecf20Sopenharmony_ci		}
23918c2ecf20Sopenharmony_ci	}
23928c2ecf20Sopenharmony_ci
23938c2ecf20Sopenharmony_ci	/* If we have a copper PHY then we only want to go out to the PHY
23948c2ecf20Sopenharmony_ci	 * registers to see if Auto-Neg has completed and/or if our link
23958c2ecf20Sopenharmony_ci	 * status has changed.  The get_link_status flag will be set if we
23968c2ecf20Sopenharmony_ci	 * receive a Link Status Change interrupt or we have Rx Sequence
23978c2ecf20Sopenharmony_ci	 * Errors.
23988c2ecf20Sopenharmony_ci	 */
23998c2ecf20Sopenharmony_ci	if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
24008c2ecf20Sopenharmony_ci		/* First we want to see if the MII Status Register reports
24018c2ecf20Sopenharmony_ci		 * link.  If so, then we want to get the current speed/duplex
24028c2ecf20Sopenharmony_ci		 * of the PHY.
24038c2ecf20Sopenharmony_ci		 * Read the register twice since the link bit is sticky.
24048c2ecf20Sopenharmony_ci		 */
24058c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
24068c2ecf20Sopenharmony_ci		if (ret_val)
24078c2ecf20Sopenharmony_ci			return ret_val;
24088c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
24098c2ecf20Sopenharmony_ci		if (ret_val)
24108c2ecf20Sopenharmony_ci			return ret_val;
24118c2ecf20Sopenharmony_ci
24128c2ecf20Sopenharmony_ci		if (phy_data & MII_SR_LINK_STATUS) {
24138c2ecf20Sopenharmony_ci			hw->get_link_status = false;
24148c2ecf20Sopenharmony_ci			/* Check if there was DownShift, must be checked
24158c2ecf20Sopenharmony_ci			 * immediately after link-up
24168c2ecf20Sopenharmony_ci			 */
24178c2ecf20Sopenharmony_ci			e1000_check_downshift(hw);
24188c2ecf20Sopenharmony_ci
24198c2ecf20Sopenharmony_ci			/* If we are on 82544 or 82543 silicon and speed/duplex
24208c2ecf20Sopenharmony_ci			 * are forced to 10H or 10F, then we will implement the
24218c2ecf20Sopenharmony_ci			 * polarity reversal workaround.  We disable interrupts
24228c2ecf20Sopenharmony_ci			 * first, and upon returning, place the devices
24238c2ecf20Sopenharmony_ci			 * interrupt state to its previous value except for the
24248c2ecf20Sopenharmony_ci			 * link status change interrupt which will
24258c2ecf20Sopenharmony_ci			 * happen due to the execution of this workaround.
24268c2ecf20Sopenharmony_ci			 */
24278c2ecf20Sopenharmony_ci
24288c2ecf20Sopenharmony_ci			if ((hw->mac_type == e1000_82544 ||
24298c2ecf20Sopenharmony_ci			     hw->mac_type == e1000_82543) &&
24308c2ecf20Sopenharmony_ci			    (!hw->autoneg) &&
24318c2ecf20Sopenharmony_ci			    (hw->forced_speed_duplex == e1000_10_full ||
24328c2ecf20Sopenharmony_ci			     hw->forced_speed_duplex == e1000_10_half)) {
24338c2ecf20Sopenharmony_ci				ew32(IMC, 0xffffffff);
24348c2ecf20Sopenharmony_ci				ret_val =
24358c2ecf20Sopenharmony_ci				    e1000_polarity_reversal_workaround(hw);
24368c2ecf20Sopenharmony_ci				icr = er32(ICR);
24378c2ecf20Sopenharmony_ci				ew32(ICS, (icr & ~E1000_ICS_LSC));
24388c2ecf20Sopenharmony_ci				ew32(IMS, IMS_ENABLE_MASK);
24398c2ecf20Sopenharmony_ci			}
24408c2ecf20Sopenharmony_ci
24418c2ecf20Sopenharmony_ci		} else {
24428c2ecf20Sopenharmony_ci			/* No link detected */
24438c2ecf20Sopenharmony_ci			e1000_config_dsp_after_link_change(hw, false);
24448c2ecf20Sopenharmony_ci			return 0;
24458c2ecf20Sopenharmony_ci		}
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci		/* If we are forcing speed/duplex, then we simply return since
24488c2ecf20Sopenharmony_ci		 * we have already determined whether we have link or not.
24498c2ecf20Sopenharmony_ci		 */
24508c2ecf20Sopenharmony_ci		if (!hw->autoneg)
24518c2ecf20Sopenharmony_ci			return -E1000_ERR_CONFIG;
24528c2ecf20Sopenharmony_ci
24538c2ecf20Sopenharmony_ci		/* optimize the dsp settings for the igp phy */
24548c2ecf20Sopenharmony_ci		e1000_config_dsp_after_link_change(hw, true);
24558c2ecf20Sopenharmony_ci
24568c2ecf20Sopenharmony_ci		/* We have a M88E1000 PHY and Auto-Neg is enabled.  If we
24578c2ecf20Sopenharmony_ci		 * have Si on board that is 82544 or newer, Auto
24588c2ecf20Sopenharmony_ci		 * Speed Detection takes care of MAC speed/duplex
24598c2ecf20Sopenharmony_ci		 * configuration.  So we only need to configure Collision
24608c2ecf20Sopenharmony_ci		 * Distance in the MAC.  Otherwise, we need to force
24618c2ecf20Sopenharmony_ci		 * speed/duplex on the MAC to the current PHY speed/duplex
24628c2ecf20Sopenharmony_ci		 * settings.
24638c2ecf20Sopenharmony_ci		 */
24648c2ecf20Sopenharmony_ci		if ((hw->mac_type >= e1000_82544) &&
24658c2ecf20Sopenharmony_ci		    (hw->mac_type != e1000_ce4100))
24668c2ecf20Sopenharmony_ci			e1000_config_collision_dist(hw);
24678c2ecf20Sopenharmony_ci		else {
24688c2ecf20Sopenharmony_ci			ret_val = e1000_config_mac_to_phy(hw);
24698c2ecf20Sopenharmony_ci			if (ret_val) {
24708c2ecf20Sopenharmony_ci				e_dbg
24718c2ecf20Sopenharmony_ci				    ("Error configuring MAC to PHY settings\n");
24728c2ecf20Sopenharmony_ci				return ret_val;
24738c2ecf20Sopenharmony_ci			}
24748c2ecf20Sopenharmony_ci		}
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_ci		/* Configure Flow Control now that Auto-Neg has completed.
24778c2ecf20Sopenharmony_ci		 * First, we need to restore the desired flow control settings
24788c2ecf20Sopenharmony_ci		 * because we may have had to re-autoneg with a different link
24798c2ecf20Sopenharmony_ci		 * partner.
24808c2ecf20Sopenharmony_ci		 */
24818c2ecf20Sopenharmony_ci		ret_val = e1000_config_fc_after_link_up(hw);
24828c2ecf20Sopenharmony_ci		if (ret_val) {
24838c2ecf20Sopenharmony_ci			e_dbg("Error configuring flow control\n");
24848c2ecf20Sopenharmony_ci			return ret_val;
24858c2ecf20Sopenharmony_ci		}
24868c2ecf20Sopenharmony_ci
24878c2ecf20Sopenharmony_ci		/* At this point we know that we are on copper and we have
24888c2ecf20Sopenharmony_ci		 * auto-negotiated link.  These are conditions for checking the
24898c2ecf20Sopenharmony_ci		 * link partner capability register.  We use the link speed to
24908c2ecf20Sopenharmony_ci		 * determine if TBI compatibility needs to be turned on or off.
24918c2ecf20Sopenharmony_ci		 * If the link is not at gigabit speed, then TBI compatibility
24928c2ecf20Sopenharmony_ci		 * is not needed.  If we are at gigabit speed, we turn on TBI
24938c2ecf20Sopenharmony_ci		 * compatibility.
24948c2ecf20Sopenharmony_ci		 */
24958c2ecf20Sopenharmony_ci		if (hw->tbi_compatibility_en) {
24968c2ecf20Sopenharmony_ci			u16 speed, duplex;
24978c2ecf20Sopenharmony_ci
24988c2ecf20Sopenharmony_ci			ret_val =
24998c2ecf20Sopenharmony_ci			    e1000_get_speed_and_duplex(hw, &speed, &duplex);
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_ci			if (ret_val) {
25028c2ecf20Sopenharmony_ci				e_dbg
25038c2ecf20Sopenharmony_ci				    ("Error getting link speed and duplex\n");
25048c2ecf20Sopenharmony_ci				return ret_val;
25058c2ecf20Sopenharmony_ci			}
25068c2ecf20Sopenharmony_ci			if (speed != SPEED_1000) {
25078c2ecf20Sopenharmony_ci				/* If link speed is not set to gigabit speed, we
25088c2ecf20Sopenharmony_ci				 * do not need to enable TBI compatibility.
25098c2ecf20Sopenharmony_ci				 */
25108c2ecf20Sopenharmony_ci				if (hw->tbi_compatibility_on) {
25118c2ecf20Sopenharmony_ci					/* If we previously were in the mode,
25128c2ecf20Sopenharmony_ci					 * turn it off.
25138c2ecf20Sopenharmony_ci					 */
25148c2ecf20Sopenharmony_ci					rctl = er32(RCTL);
25158c2ecf20Sopenharmony_ci					rctl &= ~E1000_RCTL_SBP;
25168c2ecf20Sopenharmony_ci					ew32(RCTL, rctl);
25178c2ecf20Sopenharmony_ci					hw->tbi_compatibility_on = false;
25188c2ecf20Sopenharmony_ci				}
25198c2ecf20Sopenharmony_ci			} else {
25208c2ecf20Sopenharmony_ci				/* If TBI compatibility is was previously off,
25218c2ecf20Sopenharmony_ci				 * turn it on. For compatibility with a TBI link
25228c2ecf20Sopenharmony_ci				 * partner, we will store bad packets. Some
25238c2ecf20Sopenharmony_ci				 * frames have an additional byte on the end and
25248c2ecf20Sopenharmony_ci				 * will look like CRC errors to to the hardware.
25258c2ecf20Sopenharmony_ci				 */
25268c2ecf20Sopenharmony_ci				if (!hw->tbi_compatibility_on) {
25278c2ecf20Sopenharmony_ci					hw->tbi_compatibility_on = true;
25288c2ecf20Sopenharmony_ci					rctl = er32(RCTL);
25298c2ecf20Sopenharmony_ci					rctl |= E1000_RCTL_SBP;
25308c2ecf20Sopenharmony_ci					ew32(RCTL, rctl);
25318c2ecf20Sopenharmony_ci				}
25328c2ecf20Sopenharmony_ci			}
25338c2ecf20Sopenharmony_ci		}
25348c2ecf20Sopenharmony_ci	}
25358c2ecf20Sopenharmony_ci
25368c2ecf20Sopenharmony_ci	if ((hw->media_type == e1000_media_type_fiber) ||
25378c2ecf20Sopenharmony_ci	    (hw->media_type == e1000_media_type_internal_serdes))
25388c2ecf20Sopenharmony_ci		e1000_check_for_serdes_link_generic(hw);
25398c2ecf20Sopenharmony_ci
25408c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
25418c2ecf20Sopenharmony_ci}
25428c2ecf20Sopenharmony_ci
25438c2ecf20Sopenharmony_ci/**
25448c2ecf20Sopenharmony_ci * e1000_get_speed_and_duplex
25458c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
25468c2ecf20Sopenharmony_ci * @speed: Speed of the connection
25478c2ecf20Sopenharmony_ci * @duplex: Duplex setting of the connection
25488c2ecf20Sopenharmony_ci *
25498c2ecf20Sopenharmony_ci * Detects the current speed and duplex settings of the hardware.
25508c2ecf20Sopenharmony_ci */
25518c2ecf20Sopenharmony_cis32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
25528c2ecf20Sopenharmony_ci{
25538c2ecf20Sopenharmony_ci	u32 status;
25548c2ecf20Sopenharmony_ci	s32 ret_val;
25558c2ecf20Sopenharmony_ci	u16 phy_data;
25568c2ecf20Sopenharmony_ci
25578c2ecf20Sopenharmony_ci	if (hw->mac_type >= e1000_82543) {
25588c2ecf20Sopenharmony_ci		status = er32(STATUS);
25598c2ecf20Sopenharmony_ci		if (status & E1000_STATUS_SPEED_1000) {
25608c2ecf20Sopenharmony_ci			*speed = SPEED_1000;
25618c2ecf20Sopenharmony_ci			e_dbg("1000 Mbs, ");
25628c2ecf20Sopenharmony_ci		} else if (status & E1000_STATUS_SPEED_100) {
25638c2ecf20Sopenharmony_ci			*speed = SPEED_100;
25648c2ecf20Sopenharmony_ci			e_dbg("100 Mbs, ");
25658c2ecf20Sopenharmony_ci		} else {
25668c2ecf20Sopenharmony_ci			*speed = SPEED_10;
25678c2ecf20Sopenharmony_ci			e_dbg("10 Mbs, ");
25688c2ecf20Sopenharmony_ci		}
25698c2ecf20Sopenharmony_ci
25708c2ecf20Sopenharmony_ci		if (status & E1000_STATUS_FD) {
25718c2ecf20Sopenharmony_ci			*duplex = FULL_DUPLEX;
25728c2ecf20Sopenharmony_ci			e_dbg("Full Duplex\n");
25738c2ecf20Sopenharmony_ci		} else {
25748c2ecf20Sopenharmony_ci			*duplex = HALF_DUPLEX;
25758c2ecf20Sopenharmony_ci			e_dbg(" Half Duplex\n");
25768c2ecf20Sopenharmony_ci		}
25778c2ecf20Sopenharmony_ci	} else {
25788c2ecf20Sopenharmony_ci		e_dbg("1000 Mbs, Full Duplex\n");
25798c2ecf20Sopenharmony_ci		*speed = SPEED_1000;
25808c2ecf20Sopenharmony_ci		*duplex = FULL_DUPLEX;
25818c2ecf20Sopenharmony_ci	}
25828c2ecf20Sopenharmony_ci
25838c2ecf20Sopenharmony_ci	/* IGP01 PHY may advertise full duplex operation after speed downgrade
25848c2ecf20Sopenharmony_ci	 * even if it is operating at half duplex.  Here we set the duplex
25858c2ecf20Sopenharmony_ci	 * settings to match the duplex in the link partner's capabilities.
25868c2ecf20Sopenharmony_ci	 */
25878c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp && hw->speed_downgraded) {
25888c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data);
25898c2ecf20Sopenharmony_ci		if (ret_val)
25908c2ecf20Sopenharmony_ci			return ret_val;
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_ci		if (!(phy_data & NWAY_ER_LP_NWAY_CAPS))
25938c2ecf20Sopenharmony_ci			*duplex = HALF_DUPLEX;
25948c2ecf20Sopenharmony_ci		else {
25958c2ecf20Sopenharmony_ci			ret_val =
25968c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data);
25978c2ecf20Sopenharmony_ci			if (ret_val)
25988c2ecf20Sopenharmony_ci				return ret_val;
25998c2ecf20Sopenharmony_ci			if ((*speed == SPEED_100 &&
26008c2ecf20Sopenharmony_ci			     !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) ||
26018c2ecf20Sopenharmony_ci			    (*speed == SPEED_10 &&
26028c2ecf20Sopenharmony_ci			     !(phy_data & NWAY_LPAR_10T_FD_CAPS)))
26038c2ecf20Sopenharmony_ci				*duplex = HALF_DUPLEX;
26048c2ecf20Sopenharmony_ci		}
26058c2ecf20Sopenharmony_ci	}
26068c2ecf20Sopenharmony_ci
26078c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
26088c2ecf20Sopenharmony_ci}
26098c2ecf20Sopenharmony_ci
26108c2ecf20Sopenharmony_ci/**
26118c2ecf20Sopenharmony_ci * e1000_wait_autoneg
26128c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
26138c2ecf20Sopenharmony_ci *
26148c2ecf20Sopenharmony_ci * Blocks until autoneg completes or times out (~4.5 seconds)
26158c2ecf20Sopenharmony_ci */
26168c2ecf20Sopenharmony_cistatic s32 e1000_wait_autoneg(struct e1000_hw *hw)
26178c2ecf20Sopenharmony_ci{
26188c2ecf20Sopenharmony_ci	s32 ret_val;
26198c2ecf20Sopenharmony_ci	u16 i;
26208c2ecf20Sopenharmony_ci	u16 phy_data;
26218c2ecf20Sopenharmony_ci
26228c2ecf20Sopenharmony_ci	e_dbg("Waiting for Auto-Neg to complete.\n");
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_ci	/* We will wait for autoneg to complete or 4.5 seconds to expire. */
26258c2ecf20Sopenharmony_ci	for (i = PHY_AUTO_NEG_TIME; i > 0; i--) {
26268c2ecf20Sopenharmony_ci		/* Read the MII Status Register and wait for Auto-Neg
26278c2ecf20Sopenharmony_ci		 * Complete bit to be set.
26288c2ecf20Sopenharmony_ci		 */
26298c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
26308c2ecf20Sopenharmony_ci		if (ret_val)
26318c2ecf20Sopenharmony_ci			return ret_val;
26328c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
26338c2ecf20Sopenharmony_ci		if (ret_val)
26348c2ecf20Sopenharmony_ci			return ret_val;
26358c2ecf20Sopenharmony_ci		if (phy_data & MII_SR_AUTONEG_COMPLETE)
26368c2ecf20Sopenharmony_ci			return E1000_SUCCESS;
26378c2ecf20Sopenharmony_ci
26388c2ecf20Sopenharmony_ci		msleep(100);
26398c2ecf20Sopenharmony_ci	}
26408c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
26418c2ecf20Sopenharmony_ci}
26428c2ecf20Sopenharmony_ci
26438c2ecf20Sopenharmony_ci/**
26448c2ecf20Sopenharmony_ci * e1000_raise_mdi_clk - Raises the Management Data Clock
26458c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
26468c2ecf20Sopenharmony_ci * @ctrl: Device control register's current value
26478c2ecf20Sopenharmony_ci */
26488c2ecf20Sopenharmony_cistatic void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
26498c2ecf20Sopenharmony_ci{
26508c2ecf20Sopenharmony_ci	/* Raise the clock input to the Management Data Clock (by setting the
26518c2ecf20Sopenharmony_ci	 * MDC bit), and then delay 10 microseconds.
26528c2ecf20Sopenharmony_ci	 */
26538c2ecf20Sopenharmony_ci	ew32(CTRL, (*ctrl | E1000_CTRL_MDC));
26548c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
26558c2ecf20Sopenharmony_ci	udelay(10);
26568c2ecf20Sopenharmony_ci}
26578c2ecf20Sopenharmony_ci
26588c2ecf20Sopenharmony_ci/**
26598c2ecf20Sopenharmony_ci * e1000_lower_mdi_clk - Lowers the Management Data Clock
26608c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
26618c2ecf20Sopenharmony_ci * @ctrl: Device control register's current value
26628c2ecf20Sopenharmony_ci */
26638c2ecf20Sopenharmony_cistatic void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
26648c2ecf20Sopenharmony_ci{
26658c2ecf20Sopenharmony_ci	/* Lower the clock input to the Management Data Clock (by clearing the
26668c2ecf20Sopenharmony_ci	 * MDC bit), and then delay 10 microseconds.
26678c2ecf20Sopenharmony_ci	 */
26688c2ecf20Sopenharmony_ci	ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC));
26698c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
26708c2ecf20Sopenharmony_ci	udelay(10);
26718c2ecf20Sopenharmony_ci}
26728c2ecf20Sopenharmony_ci
26738c2ecf20Sopenharmony_ci/**
26748c2ecf20Sopenharmony_ci * e1000_shift_out_mdi_bits - Shifts data bits out to the PHY
26758c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
26768c2ecf20Sopenharmony_ci * @data: Data to send out to the PHY
26778c2ecf20Sopenharmony_ci * @count: Number of bits to shift out
26788c2ecf20Sopenharmony_ci *
26798c2ecf20Sopenharmony_ci * Bits are shifted out in MSB to LSB order.
26808c2ecf20Sopenharmony_ci */
26818c2ecf20Sopenharmony_cistatic void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count)
26828c2ecf20Sopenharmony_ci{
26838c2ecf20Sopenharmony_ci	u32 ctrl;
26848c2ecf20Sopenharmony_ci	u32 mask;
26858c2ecf20Sopenharmony_ci
26868c2ecf20Sopenharmony_ci	/* We need to shift "count" number of bits out to the PHY. So, the value
26878c2ecf20Sopenharmony_ci	 * in the "data" parameter will be shifted out to the PHY one bit at a
26888c2ecf20Sopenharmony_ci	 * time. In order to do this, "data" must be broken down into bits.
26898c2ecf20Sopenharmony_ci	 */
26908c2ecf20Sopenharmony_ci	mask = 0x01;
26918c2ecf20Sopenharmony_ci	mask <<= (count - 1);
26928c2ecf20Sopenharmony_ci
26938c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
26948c2ecf20Sopenharmony_ci
26958c2ecf20Sopenharmony_ci	/* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
26968c2ecf20Sopenharmony_ci	ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
26978c2ecf20Sopenharmony_ci
26988c2ecf20Sopenharmony_ci	while (mask) {
26998c2ecf20Sopenharmony_ci		/* A "1" is shifted out to the PHY by setting the MDIO bit to
27008c2ecf20Sopenharmony_ci		 * "1" and then raising and lowering the Management Data Clock.
27018c2ecf20Sopenharmony_ci		 * A "0" is shifted out to the PHY by setting the MDIO bit to
27028c2ecf20Sopenharmony_ci		 * "0" and then raising and lowering the clock.
27038c2ecf20Sopenharmony_ci		 */
27048c2ecf20Sopenharmony_ci		if (data & mask)
27058c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_MDIO;
27068c2ecf20Sopenharmony_ci		else
27078c2ecf20Sopenharmony_ci			ctrl &= ~E1000_CTRL_MDIO;
27088c2ecf20Sopenharmony_ci
27098c2ecf20Sopenharmony_ci		ew32(CTRL, ctrl);
27108c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
27118c2ecf20Sopenharmony_ci
27128c2ecf20Sopenharmony_ci		udelay(10);
27138c2ecf20Sopenharmony_ci
27148c2ecf20Sopenharmony_ci		e1000_raise_mdi_clk(hw, &ctrl);
27158c2ecf20Sopenharmony_ci		e1000_lower_mdi_clk(hw, &ctrl);
27168c2ecf20Sopenharmony_ci
27178c2ecf20Sopenharmony_ci		mask = mask >> 1;
27188c2ecf20Sopenharmony_ci	}
27198c2ecf20Sopenharmony_ci}
27208c2ecf20Sopenharmony_ci
27218c2ecf20Sopenharmony_ci/**
27228c2ecf20Sopenharmony_ci * e1000_shift_in_mdi_bits - Shifts data bits in from the PHY
27238c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
27248c2ecf20Sopenharmony_ci *
27258c2ecf20Sopenharmony_ci * Bits are shifted in in MSB to LSB order.
27268c2ecf20Sopenharmony_ci */
27278c2ecf20Sopenharmony_cistatic u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
27288c2ecf20Sopenharmony_ci{
27298c2ecf20Sopenharmony_ci	u32 ctrl;
27308c2ecf20Sopenharmony_ci	u16 data = 0;
27318c2ecf20Sopenharmony_ci	u8 i;
27328c2ecf20Sopenharmony_ci
27338c2ecf20Sopenharmony_ci	/* In order to read a register from the PHY, we need to shift in a total
27348c2ecf20Sopenharmony_ci	 * of 18 bits from the PHY. The first two bit (turnaround) times are
27358c2ecf20Sopenharmony_ci	 * used to avoid contention on the MDIO pin when a read operation is
27368c2ecf20Sopenharmony_ci	 * performed. These two bits are ignored by us and thrown away. Bits are
27378c2ecf20Sopenharmony_ci	 * "shifted in" by raising the input to the Management Data Clock
27388c2ecf20Sopenharmony_ci	 * (setting the MDC bit), and then reading the value of the MDIO bit.
27398c2ecf20Sopenharmony_ci	 */
27408c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
27418c2ecf20Sopenharmony_ci
27428c2ecf20Sopenharmony_ci	/* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
27438c2ecf20Sopenharmony_ci	 * input.
27448c2ecf20Sopenharmony_ci	 */
27458c2ecf20Sopenharmony_ci	ctrl &= ~E1000_CTRL_MDIO_DIR;
27468c2ecf20Sopenharmony_ci	ctrl &= ~E1000_CTRL_MDIO;
27478c2ecf20Sopenharmony_ci
27488c2ecf20Sopenharmony_ci	ew32(CTRL, ctrl);
27498c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
27508c2ecf20Sopenharmony_ci
27518c2ecf20Sopenharmony_ci	/* Raise and Lower the clock before reading in the data. This accounts
27528c2ecf20Sopenharmony_ci	 * for the turnaround bits. The first clock occurred when we clocked out
27538c2ecf20Sopenharmony_ci	 * the last bit of the Register Address.
27548c2ecf20Sopenharmony_ci	 */
27558c2ecf20Sopenharmony_ci	e1000_raise_mdi_clk(hw, &ctrl);
27568c2ecf20Sopenharmony_ci	e1000_lower_mdi_clk(hw, &ctrl);
27578c2ecf20Sopenharmony_ci
27588c2ecf20Sopenharmony_ci	for (data = 0, i = 0; i < 16; i++) {
27598c2ecf20Sopenharmony_ci		data = data << 1;
27608c2ecf20Sopenharmony_ci		e1000_raise_mdi_clk(hw, &ctrl);
27618c2ecf20Sopenharmony_ci		ctrl = er32(CTRL);
27628c2ecf20Sopenharmony_ci		/* Check to see if we shifted in a "1". */
27638c2ecf20Sopenharmony_ci		if (ctrl & E1000_CTRL_MDIO)
27648c2ecf20Sopenharmony_ci			data |= 1;
27658c2ecf20Sopenharmony_ci		e1000_lower_mdi_clk(hw, &ctrl);
27668c2ecf20Sopenharmony_ci	}
27678c2ecf20Sopenharmony_ci
27688c2ecf20Sopenharmony_ci	e1000_raise_mdi_clk(hw, &ctrl);
27698c2ecf20Sopenharmony_ci	e1000_lower_mdi_clk(hw, &ctrl);
27708c2ecf20Sopenharmony_ci
27718c2ecf20Sopenharmony_ci	return data;
27728c2ecf20Sopenharmony_ci}
27738c2ecf20Sopenharmony_ci
27748c2ecf20Sopenharmony_ci/**
27758c2ecf20Sopenharmony_ci * e1000_read_phy_reg - read a phy register
27768c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
27778c2ecf20Sopenharmony_ci * @reg_addr: address of the PHY register to read
27788c2ecf20Sopenharmony_ci * @phy_data: pointer to the value on the PHY register
27798c2ecf20Sopenharmony_ci *
27808c2ecf20Sopenharmony_ci * Reads the value from a PHY register, if the value is on a specific non zero
27818c2ecf20Sopenharmony_ci * page, sets the page first.
27828c2ecf20Sopenharmony_ci */
27838c2ecf20Sopenharmony_cis32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
27848c2ecf20Sopenharmony_ci{
27858c2ecf20Sopenharmony_ci	u32 ret_val;
27868c2ecf20Sopenharmony_ci	unsigned long flags;
27878c2ecf20Sopenharmony_ci
27888c2ecf20Sopenharmony_ci	spin_lock_irqsave(&e1000_phy_lock, flags);
27898c2ecf20Sopenharmony_ci
27908c2ecf20Sopenharmony_ci	if ((hw->phy_type == e1000_phy_igp) &&
27918c2ecf20Sopenharmony_ci	    (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
27928c2ecf20Sopenharmony_ci		ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
27938c2ecf20Sopenharmony_ci						 (u16) reg_addr);
27948c2ecf20Sopenharmony_ci		if (ret_val)
27958c2ecf20Sopenharmony_ci			goto out;
27968c2ecf20Sopenharmony_ci	}
27978c2ecf20Sopenharmony_ci
27988c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
27998c2ecf20Sopenharmony_ci					phy_data);
28008c2ecf20Sopenharmony_ciout:
28018c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&e1000_phy_lock, flags);
28028c2ecf20Sopenharmony_ci
28038c2ecf20Sopenharmony_ci	return ret_val;
28048c2ecf20Sopenharmony_ci}
28058c2ecf20Sopenharmony_ci
28068c2ecf20Sopenharmony_cistatic s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
28078c2ecf20Sopenharmony_ci				 u16 *phy_data)
28088c2ecf20Sopenharmony_ci{
28098c2ecf20Sopenharmony_ci	u32 i;
28108c2ecf20Sopenharmony_ci	u32 mdic = 0;
28118c2ecf20Sopenharmony_ci	const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1;
28128c2ecf20Sopenharmony_ci
28138c2ecf20Sopenharmony_ci	if (reg_addr > MAX_PHY_REG_ADDRESS) {
28148c2ecf20Sopenharmony_ci		e_dbg("PHY Address %d is out of range\n", reg_addr);
28158c2ecf20Sopenharmony_ci		return -E1000_ERR_PARAM;
28168c2ecf20Sopenharmony_ci	}
28178c2ecf20Sopenharmony_ci
28188c2ecf20Sopenharmony_ci	if (hw->mac_type > e1000_82543) {
28198c2ecf20Sopenharmony_ci		/* Set up Op-code, Phy Address, and register address in the MDI
28208c2ecf20Sopenharmony_ci		 * Control register.  The MAC will take care of interfacing with
28218c2ecf20Sopenharmony_ci		 * the PHY to retrieve the desired data.
28228c2ecf20Sopenharmony_ci		 */
28238c2ecf20Sopenharmony_ci		if (hw->mac_type == e1000_ce4100) {
28248c2ecf20Sopenharmony_ci			mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
28258c2ecf20Sopenharmony_ci				(phy_addr << E1000_MDIC_PHY_SHIFT) |
28268c2ecf20Sopenharmony_ci				(INTEL_CE_GBE_MDIC_OP_READ) |
28278c2ecf20Sopenharmony_ci				(INTEL_CE_GBE_MDIC_GO));
28288c2ecf20Sopenharmony_ci
28298c2ecf20Sopenharmony_ci			writel(mdic, E1000_MDIO_CMD);
28308c2ecf20Sopenharmony_ci
28318c2ecf20Sopenharmony_ci			/* Poll the ready bit to see if the MDI read
28328c2ecf20Sopenharmony_ci			 * completed
28338c2ecf20Sopenharmony_ci			 */
28348c2ecf20Sopenharmony_ci			for (i = 0; i < 64; i++) {
28358c2ecf20Sopenharmony_ci				udelay(50);
28368c2ecf20Sopenharmony_ci				mdic = readl(E1000_MDIO_CMD);
28378c2ecf20Sopenharmony_ci				if (!(mdic & INTEL_CE_GBE_MDIC_GO))
28388c2ecf20Sopenharmony_ci					break;
28398c2ecf20Sopenharmony_ci			}
28408c2ecf20Sopenharmony_ci
28418c2ecf20Sopenharmony_ci			if (mdic & INTEL_CE_GBE_MDIC_GO) {
28428c2ecf20Sopenharmony_ci				e_dbg("MDI Read did not complete\n");
28438c2ecf20Sopenharmony_ci				return -E1000_ERR_PHY;
28448c2ecf20Sopenharmony_ci			}
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci			mdic = readl(E1000_MDIO_STS);
28478c2ecf20Sopenharmony_ci			if (mdic & INTEL_CE_GBE_MDIC_READ_ERROR) {
28488c2ecf20Sopenharmony_ci				e_dbg("MDI Read Error\n");
28498c2ecf20Sopenharmony_ci				return -E1000_ERR_PHY;
28508c2ecf20Sopenharmony_ci			}
28518c2ecf20Sopenharmony_ci			*phy_data = (u16)mdic;
28528c2ecf20Sopenharmony_ci		} else {
28538c2ecf20Sopenharmony_ci			mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
28548c2ecf20Sopenharmony_ci				(phy_addr << E1000_MDIC_PHY_SHIFT) |
28558c2ecf20Sopenharmony_ci				(E1000_MDIC_OP_READ));
28568c2ecf20Sopenharmony_ci
28578c2ecf20Sopenharmony_ci			ew32(MDIC, mdic);
28588c2ecf20Sopenharmony_ci
28598c2ecf20Sopenharmony_ci			/* Poll the ready bit to see if the MDI read
28608c2ecf20Sopenharmony_ci			 * completed
28618c2ecf20Sopenharmony_ci			 */
28628c2ecf20Sopenharmony_ci			for (i = 0; i < 64; i++) {
28638c2ecf20Sopenharmony_ci				udelay(50);
28648c2ecf20Sopenharmony_ci				mdic = er32(MDIC);
28658c2ecf20Sopenharmony_ci				if (mdic & E1000_MDIC_READY)
28668c2ecf20Sopenharmony_ci					break;
28678c2ecf20Sopenharmony_ci			}
28688c2ecf20Sopenharmony_ci			if (!(mdic & E1000_MDIC_READY)) {
28698c2ecf20Sopenharmony_ci				e_dbg("MDI Read did not complete\n");
28708c2ecf20Sopenharmony_ci				return -E1000_ERR_PHY;
28718c2ecf20Sopenharmony_ci			}
28728c2ecf20Sopenharmony_ci			if (mdic & E1000_MDIC_ERROR) {
28738c2ecf20Sopenharmony_ci				e_dbg("MDI Error\n");
28748c2ecf20Sopenharmony_ci				return -E1000_ERR_PHY;
28758c2ecf20Sopenharmony_ci			}
28768c2ecf20Sopenharmony_ci			*phy_data = (u16)mdic;
28778c2ecf20Sopenharmony_ci		}
28788c2ecf20Sopenharmony_ci	} else {
28798c2ecf20Sopenharmony_ci		/* We must first send a preamble through the MDIO pin to signal
28808c2ecf20Sopenharmony_ci		 * the beginning of an MII instruction.  This is done by sending
28818c2ecf20Sopenharmony_ci		 * 32 consecutive "1" bits.
28828c2ecf20Sopenharmony_ci		 */
28838c2ecf20Sopenharmony_ci		e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
28848c2ecf20Sopenharmony_ci
28858c2ecf20Sopenharmony_ci		/* Now combine the next few fields that are required for a read
28868c2ecf20Sopenharmony_ci		 * operation.  We use this method instead of calling the
28878c2ecf20Sopenharmony_ci		 * e1000_shift_out_mdi_bits routine five different times. The
28888c2ecf20Sopenharmony_ci		 * format of a MII read instruction consists of a shift out of
28898c2ecf20Sopenharmony_ci		 * 14 bits and is defined as follows:
28908c2ecf20Sopenharmony_ci		 *    <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
28918c2ecf20Sopenharmony_ci		 * followed by a shift in of 18 bits.  This first two bits
28928c2ecf20Sopenharmony_ci		 * shifted in are TurnAround bits used to avoid contention on
28938c2ecf20Sopenharmony_ci		 * the MDIO pin when a READ operation is performed.  These two
28948c2ecf20Sopenharmony_ci		 * bits are thrown away followed by a shift in of 16 bits which
28958c2ecf20Sopenharmony_ci		 * contains the desired data.
28968c2ecf20Sopenharmony_ci		 */
28978c2ecf20Sopenharmony_ci		mdic = ((reg_addr) | (phy_addr << 5) |
28988c2ecf20Sopenharmony_ci			(PHY_OP_READ << 10) | (PHY_SOF << 12));
28998c2ecf20Sopenharmony_ci
29008c2ecf20Sopenharmony_ci		e1000_shift_out_mdi_bits(hw, mdic, 14);
29018c2ecf20Sopenharmony_ci
29028c2ecf20Sopenharmony_ci		/* Now that we've shifted out the read command to the MII, we
29038c2ecf20Sopenharmony_ci		 * need to "shift in" the 16-bit value (18 total bits) of the
29048c2ecf20Sopenharmony_ci		 * requested PHY register address.
29058c2ecf20Sopenharmony_ci		 */
29068c2ecf20Sopenharmony_ci		*phy_data = e1000_shift_in_mdi_bits(hw);
29078c2ecf20Sopenharmony_ci	}
29088c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
29098c2ecf20Sopenharmony_ci}
29108c2ecf20Sopenharmony_ci
29118c2ecf20Sopenharmony_ci/**
29128c2ecf20Sopenharmony_ci * e1000_write_phy_reg - write a phy register
29138c2ecf20Sopenharmony_ci *
29148c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
29158c2ecf20Sopenharmony_ci * @reg_addr: address of the PHY register to write
29168c2ecf20Sopenharmony_ci * @phy_data: data to write to the PHY
29178c2ecf20Sopenharmony_ci *
29188c2ecf20Sopenharmony_ci * Writes a value to a PHY register
29198c2ecf20Sopenharmony_ci */
29208c2ecf20Sopenharmony_cis32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
29218c2ecf20Sopenharmony_ci{
29228c2ecf20Sopenharmony_ci	u32 ret_val;
29238c2ecf20Sopenharmony_ci	unsigned long flags;
29248c2ecf20Sopenharmony_ci
29258c2ecf20Sopenharmony_ci	spin_lock_irqsave(&e1000_phy_lock, flags);
29268c2ecf20Sopenharmony_ci
29278c2ecf20Sopenharmony_ci	if ((hw->phy_type == e1000_phy_igp) &&
29288c2ecf20Sopenharmony_ci	    (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
29298c2ecf20Sopenharmony_ci		ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
29308c2ecf20Sopenharmony_ci						 (u16)reg_addr);
29318c2ecf20Sopenharmony_ci		if (ret_val) {
29328c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&e1000_phy_lock, flags);
29338c2ecf20Sopenharmony_ci			return ret_val;
29348c2ecf20Sopenharmony_ci		}
29358c2ecf20Sopenharmony_ci	}
29368c2ecf20Sopenharmony_ci
29378c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
29388c2ecf20Sopenharmony_ci					 phy_data);
29398c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&e1000_phy_lock, flags);
29408c2ecf20Sopenharmony_ci
29418c2ecf20Sopenharmony_ci	return ret_val;
29428c2ecf20Sopenharmony_ci}
29438c2ecf20Sopenharmony_ci
29448c2ecf20Sopenharmony_cistatic s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
29458c2ecf20Sopenharmony_ci				  u16 phy_data)
29468c2ecf20Sopenharmony_ci{
29478c2ecf20Sopenharmony_ci	u32 i;
29488c2ecf20Sopenharmony_ci	u32 mdic = 0;
29498c2ecf20Sopenharmony_ci	const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1;
29508c2ecf20Sopenharmony_ci
29518c2ecf20Sopenharmony_ci	if (reg_addr > MAX_PHY_REG_ADDRESS) {
29528c2ecf20Sopenharmony_ci		e_dbg("PHY Address %d is out of range\n", reg_addr);
29538c2ecf20Sopenharmony_ci		return -E1000_ERR_PARAM;
29548c2ecf20Sopenharmony_ci	}
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci	if (hw->mac_type > e1000_82543) {
29578c2ecf20Sopenharmony_ci		/* Set up Op-code, Phy Address, register address, and data
29588c2ecf20Sopenharmony_ci		 * intended for the PHY register in the MDI Control register.
29598c2ecf20Sopenharmony_ci		 * The MAC will take care of interfacing with the PHY to send
29608c2ecf20Sopenharmony_ci		 * the desired data.
29618c2ecf20Sopenharmony_ci		 */
29628c2ecf20Sopenharmony_ci		if (hw->mac_type == e1000_ce4100) {
29638c2ecf20Sopenharmony_ci			mdic = (((u32)phy_data) |
29648c2ecf20Sopenharmony_ci				(reg_addr << E1000_MDIC_REG_SHIFT) |
29658c2ecf20Sopenharmony_ci				(phy_addr << E1000_MDIC_PHY_SHIFT) |
29668c2ecf20Sopenharmony_ci				(INTEL_CE_GBE_MDIC_OP_WRITE) |
29678c2ecf20Sopenharmony_ci				(INTEL_CE_GBE_MDIC_GO));
29688c2ecf20Sopenharmony_ci
29698c2ecf20Sopenharmony_ci			writel(mdic, E1000_MDIO_CMD);
29708c2ecf20Sopenharmony_ci
29718c2ecf20Sopenharmony_ci			/* Poll the ready bit to see if the MDI read
29728c2ecf20Sopenharmony_ci			 * completed
29738c2ecf20Sopenharmony_ci			 */
29748c2ecf20Sopenharmony_ci			for (i = 0; i < 640; i++) {
29758c2ecf20Sopenharmony_ci				udelay(5);
29768c2ecf20Sopenharmony_ci				mdic = readl(E1000_MDIO_CMD);
29778c2ecf20Sopenharmony_ci				if (!(mdic & INTEL_CE_GBE_MDIC_GO))
29788c2ecf20Sopenharmony_ci					break;
29798c2ecf20Sopenharmony_ci			}
29808c2ecf20Sopenharmony_ci			if (mdic & INTEL_CE_GBE_MDIC_GO) {
29818c2ecf20Sopenharmony_ci				e_dbg("MDI Write did not complete\n");
29828c2ecf20Sopenharmony_ci				return -E1000_ERR_PHY;
29838c2ecf20Sopenharmony_ci			}
29848c2ecf20Sopenharmony_ci		} else {
29858c2ecf20Sopenharmony_ci			mdic = (((u32)phy_data) |
29868c2ecf20Sopenharmony_ci				(reg_addr << E1000_MDIC_REG_SHIFT) |
29878c2ecf20Sopenharmony_ci				(phy_addr << E1000_MDIC_PHY_SHIFT) |
29888c2ecf20Sopenharmony_ci				(E1000_MDIC_OP_WRITE));
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci			ew32(MDIC, mdic);
29918c2ecf20Sopenharmony_ci
29928c2ecf20Sopenharmony_ci			/* Poll the ready bit to see if the MDI read
29938c2ecf20Sopenharmony_ci			 * completed
29948c2ecf20Sopenharmony_ci			 */
29958c2ecf20Sopenharmony_ci			for (i = 0; i < 641; i++) {
29968c2ecf20Sopenharmony_ci				udelay(5);
29978c2ecf20Sopenharmony_ci				mdic = er32(MDIC);
29988c2ecf20Sopenharmony_ci				if (mdic & E1000_MDIC_READY)
29998c2ecf20Sopenharmony_ci					break;
30008c2ecf20Sopenharmony_ci			}
30018c2ecf20Sopenharmony_ci			if (!(mdic & E1000_MDIC_READY)) {
30028c2ecf20Sopenharmony_ci				e_dbg("MDI Write did not complete\n");
30038c2ecf20Sopenharmony_ci				return -E1000_ERR_PHY;
30048c2ecf20Sopenharmony_ci			}
30058c2ecf20Sopenharmony_ci		}
30068c2ecf20Sopenharmony_ci	} else {
30078c2ecf20Sopenharmony_ci		/* We'll need to use the SW defined pins to shift the write
30088c2ecf20Sopenharmony_ci		 * command out to the PHY. We first send a preamble to the PHY
30098c2ecf20Sopenharmony_ci		 * to signal the beginning of the MII instruction.  This is done
30108c2ecf20Sopenharmony_ci		 * by sending 32 consecutive "1" bits.
30118c2ecf20Sopenharmony_ci		 */
30128c2ecf20Sopenharmony_ci		e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
30138c2ecf20Sopenharmony_ci
30148c2ecf20Sopenharmony_ci		/* Now combine the remaining required fields that will indicate
30158c2ecf20Sopenharmony_ci		 * a write operation. We use this method instead of calling the
30168c2ecf20Sopenharmony_ci		 * e1000_shift_out_mdi_bits routine for each field in the
30178c2ecf20Sopenharmony_ci		 * command. The format of a MII write instruction is as follows:
30188c2ecf20Sopenharmony_ci		 * <Preamble><SOF><OpCode><PhyAddr><RegAddr><Turnaround><Data>.
30198c2ecf20Sopenharmony_ci		 */
30208c2ecf20Sopenharmony_ci		mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
30218c2ecf20Sopenharmony_ci			(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
30228c2ecf20Sopenharmony_ci		mdic <<= 16;
30238c2ecf20Sopenharmony_ci		mdic |= (u32)phy_data;
30248c2ecf20Sopenharmony_ci
30258c2ecf20Sopenharmony_ci		e1000_shift_out_mdi_bits(hw, mdic, 32);
30268c2ecf20Sopenharmony_ci	}
30278c2ecf20Sopenharmony_ci
30288c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
30298c2ecf20Sopenharmony_ci}
30308c2ecf20Sopenharmony_ci
30318c2ecf20Sopenharmony_ci/**
30328c2ecf20Sopenharmony_ci * e1000_phy_hw_reset - reset the phy, hardware style
30338c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
30348c2ecf20Sopenharmony_ci *
30358c2ecf20Sopenharmony_ci * Returns the PHY to the power-on reset state
30368c2ecf20Sopenharmony_ci */
30378c2ecf20Sopenharmony_cis32 e1000_phy_hw_reset(struct e1000_hw *hw)
30388c2ecf20Sopenharmony_ci{
30398c2ecf20Sopenharmony_ci	u32 ctrl, ctrl_ext;
30408c2ecf20Sopenharmony_ci	u32 led_ctrl;
30418c2ecf20Sopenharmony_ci
30428c2ecf20Sopenharmony_ci	e_dbg("Resetting Phy...\n");
30438c2ecf20Sopenharmony_ci
30448c2ecf20Sopenharmony_ci	if (hw->mac_type > e1000_82543) {
30458c2ecf20Sopenharmony_ci		/* Read the device control register and assert the
30468c2ecf20Sopenharmony_ci		 * E1000_CTRL_PHY_RST bit. Then, take it out of reset.
30478c2ecf20Sopenharmony_ci		 * For e1000 hardware, we delay for 10ms between the assert
30488c2ecf20Sopenharmony_ci		 * and de-assert.
30498c2ecf20Sopenharmony_ci		 */
30508c2ecf20Sopenharmony_ci		ctrl = er32(CTRL);
30518c2ecf20Sopenharmony_ci		ew32(CTRL, ctrl | E1000_CTRL_PHY_RST);
30528c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
30538c2ecf20Sopenharmony_ci
30548c2ecf20Sopenharmony_ci		msleep(10);
30558c2ecf20Sopenharmony_ci
30568c2ecf20Sopenharmony_ci		ew32(CTRL, ctrl);
30578c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
30588c2ecf20Sopenharmony_ci
30598c2ecf20Sopenharmony_ci	} else {
30608c2ecf20Sopenharmony_ci		/* Read the Extended Device Control Register, assert the
30618c2ecf20Sopenharmony_ci		 * PHY_RESET_DIR bit to put the PHY into reset. Then, take it
30628c2ecf20Sopenharmony_ci		 * out of reset.
30638c2ecf20Sopenharmony_ci		 */
30648c2ecf20Sopenharmony_ci		ctrl_ext = er32(CTRL_EXT);
30658c2ecf20Sopenharmony_ci		ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
30668c2ecf20Sopenharmony_ci		ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
30678c2ecf20Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
30688c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
30698c2ecf20Sopenharmony_ci		msleep(10);
30708c2ecf20Sopenharmony_ci		ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
30718c2ecf20Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
30728c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
30738c2ecf20Sopenharmony_ci	}
30748c2ecf20Sopenharmony_ci	udelay(150);
30758c2ecf20Sopenharmony_ci
30768c2ecf20Sopenharmony_ci	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
30778c2ecf20Sopenharmony_ci		/* Configure activity LED after PHY reset */
30788c2ecf20Sopenharmony_ci		led_ctrl = er32(LEDCTL);
30798c2ecf20Sopenharmony_ci		led_ctrl &= IGP_ACTIVITY_LED_MASK;
30808c2ecf20Sopenharmony_ci		led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
30818c2ecf20Sopenharmony_ci		ew32(LEDCTL, led_ctrl);
30828c2ecf20Sopenharmony_ci	}
30838c2ecf20Sopenharmony_ci
30848c2ecf20Sopenharmony_ci	/* Wait for FW to finish PHY configuration. */
30858c2ecf20Sopenharmony_ci	return e1000_get_phy_cfg_done(hw);
30868c2ecf20Sopenharmony_ci}
30878c2ecf20Sopenharmony_ci
30888c2ecf20Sopenharmony_ci/**
30898c2ecf20Sopenharmony_ci * e1000_phy_reset - reset the phy to commit settings
30908c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
30918c2ecf20Sopenharmony_ci *
30928c2ecf20Sopenharmony_ci * Resets the PHY
30938c2ecf20Sopenharmony_ci * Sets bit 15 of the MII Control register
30948c2ecf20Sopenharmony_ci */
30958c2ecf20Sopenharmony_cis32 e1000_phy_reset(struct e1000_hw *hw)
30968c2ecf20Sopenharmony_ci{
30978c2ecf20Sopenharmony_ci	s32 ret_val;
30988c2ecf20Sopenharmony_ci	u16 phy_data;
30998c2ecf20Sopenharmony_ci
31008c2ecf20Sopenharmony_ci	switch (hw->phy_type) {
31018c2ecf20Sopenharmony_ci	case e1000_phy_igp:
31028c2ecf20Sopenharmony_ci		ret_val = e1000_phy_hw_reset(hw);
31038c2ecf20Sopenharmony_ci		if (ret_val)
31048c2ecf20Sopenharmony_ci			return ret_val;
31058c2ecf20Sopenharmony_ci		break;
31068c2ecf20Sopenharmony_ci	default:
31078c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
31088c2ecf20Sopenharmony_ci		if (ret_val)
31098c2ecf20Sopenharmony_ci			return ret_val;
31108c2ecf20Sopenharmony_ci
31118c2ecf20Sopenharmony_ci		phy_data |= MII_CR_RESET;
31128c2ecf20Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
31138c2ecf20Sopenharmony_ci		if (ret_val)
31148c2ecf20Sopenharmony_ci			return ret_val;
31158c2ecf20Sopenharmony_ci
31168c2ecf20Sopenharmony_ci		udelay(1);
31178c2ecf20Sopenharmony_ci		break;
31188c2ecf20Sopenharmony_ci	}
31198c2ecf20Sopenharmony_ci
31208c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp)
31218c2ecf20Sopenharmony_ci		e1000_phy_init_script(hw);
31228c2ecf20Sopenharmony_ci
31238c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
31248c2ecf20Sopenharmony_ci}
31258c2ecf20Sopenharmony_ci
31268c2ecf20Sopenharmony_ci/**
31278c2ecf20Sopenharmony_ci * e1000_detect_gig_phy - check the phy type
31288c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
31298c2ecf20Sopenharmony_ci *
31308c2ecf20Sopenharmony_ci * Probes the expected PHY address for known PHY IDs
31318c2ecf20Sopenharmony_ci */
31328c2ecf20Sopenharmony_cistatic s32 e1000_detect_gig_phy(struct e1000_hw *hw)
31338c2ecf20Sopenharmony_ci{
31348c2ecf20Sopenharmony_ci	s32 phy_init_status, ret_val;
31358c2ecf20Sopenharmony_ci	u16 phy_id_high, phy_id_low;
31368c2ecf20Sopenharmony_ci	bool match = false;
31378c2ecf20Sopenharmony_ci
31388c2ecf20Sopenharmony_ci	if (hw->phy_id != 0)
31398c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
31408c2ecf20Sopenharmony_ci
31418c2ecf20Sopenharmony_ci	/* Read the PHY ID Registers to identify which PHY is onboard. */
31428c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
31438c2ecf20Sopenharmony_ci	if (ret_val)
31448c2ecf20Sopenharmony_ci		return ret_val;
31458c2ecf20Sopenharmony_ci
31468c2ecf20Sopenharmony_ci	hw->phy_id = (u32)(phy_id_high << 16);
31478c2ecf20Sopenharmony_ci	udelay(20);
31488c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
31498c2ecf20Sopenharmony_ci	if (ret_val)
31508c2ecf20Sopenharmony_ci		return ret_val;
31518c2ecf20Sopenharmony_ci
31528c2ecf20Sopenharmony_ci	hw->phy_id |= (u32)(phy_id_low & PHY_REVISION_MASK);
31538c2ecf20Sopenharmony_ci	hw->phy_revision = (u32)phy_id_low & ~PHY_REVISION_MASK;
31548c2ecf20Sopenharmony_ci
31558c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
31568c2ecf20Sopenharmony_ci	case e1000_82543:
31578c2ecf20Sopenharmony_ci		if (hw->phy_id == M88E1000_E_PHY_ID)
31588c2ecf20Sopenharmony_ci			match = true;
31598c2ecf20Sopenharmony_ci		break;
31608c2ecf20Sopenharmony_ci	case e1000_82544:
31618c2ecf20Sopenharmony_ci		if (hw->phy_id == M88E1000_I_PHY_ID)
31628c2ecf20Sopenharmony_ci			match = true;
31638c2ecf20Sopenharmony_ci		break;
31648c2ecf20Sopenharmony_ci	case e1000_82540:
31658c2ecf20Sopenharmony_ci	case e1000_82545:
31668c2ecf20Sopenharmony_ci	case e1000_82545_rev_3:
31678c2ecf20Sopenharmony_ci	case e1000_82546:
31688c2ecf20Sopenharmony_ci	case e1000_82546_rev_3:
31698c2ecf20Sopenharmony_ci		if (hw->phy_id == M88E1011_I_PHY_ID)
31708c2ecf20Sopenharmony_ci			match = true;
31718c2ecf20Sopenharmony_ci		break;
31728c2ecf20Sopenharmony_ci	case e1000_ce4100:
31738c2ecf20Sopenharmony_ci		if ((hw->phy_id == RTL8211B_PHY_ID) ||
31748c2ecf20Sopenharmony_ci		    (hw->phy_id == RTL8201N_PHY_ID) ||
31758c2ecf20Sopenharmony_ci		    (hw->phy_id == M88E1118_E_PHY_ID))
31768c2ecf20Sopenharmony_ci			match = true;
31778c2ecf20Sopenharmony_ci		break;
31788c2ecf20Sopenharmony_ci	case e1000_82541:
31798c2ecf20Sopenharmony_ci	case e1000_82541_rev_2:
31808c2ecf20Sopenharmony_ci	case e1000_82547:
31818c2ecf20Sopenharmony_ci	case e1000_82547_rev_2:
31828c2ecf20Sopenharmony_ci		if (hw->phy_id == IGP01E1000_I_PHY_ID)
31838c2ecf20Sopenharmony_ci			match = true;
31848c2ecf20Sopenharmony_ci		break;
31858c2ecf20Sopenharmony_ci	default:
31868c2ecf20Sopenharmony_ci		e_dbg("Invalid MAC type %d\n", hw->mac_type);
31878c2ecf20Sopenharmony_ci		return -E1000_ERR_CONFIG;
31888c2ecf20Sopenharmony_ci	}
31898c2ecf20Sopenharmony_ci	phy_init_status = e1000_set_phy_type(hw);
31908c2ecf20Sopenharmony_ci
31918c2ecf20Sopenharmony_ci	if ((match) && (phy_init_status == E1000_SUCCESS)) {
31928c2ecf20Sopenharmony_ci		e_dbg("PHY ID 0x%X detected\n", hw->phy_id);
31938c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
31948c2ecf20Sopenharmony_ci	}
31958c2ecf20Sopenharmony_ci	e_dbg("Invalid PHY ID 0x%X\n", hw->phy_id);
31968c2ecf20Sopenharmony_ci	return -E1000_ERR_PHY;
31978c2ecf20Sopenharmony_ci}
31988c2ecf20Sopenharmony_ci
31998c2ecf20Sopenharmony_ci/**
32008c2ecf20Sopenharmony_ci * e1000_phy_reset_dsp - reset DSP
32018c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
32028c2ecf20Sopenharmony_ci *
32038c2ecf20Sopenharmony_ci * Resets the PHY's DSP
32048c2ecf20Sopenharmony_ci */
32058c2ecf20Sopenharmony_cistatic s32 e1000_phy_reset_dsp(struct e1000_hw *hw)
32068c2ecf20Sopenharmony_ci{
32078c2ecf20Sopenharmony_ci	s32 ret_val;
32088c2ecf20Sopenharmony_ci
32098c2ecf20Sopenharmony_ci	do {
32108c2ecf20Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, 29, 0x001d);
32118c2ecf20Sopenharmony_ci		if (ret_val)
32128c2ecf20Sopenharmony_ci			break;
32138c2ecf20Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, 30, 0x00c1);
32148c2ecf20Sopenharmony_ci		if (ret_val)
32158c2ecf20Sopenharmony_ci			break;
32168c2ecf20Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, 30, 0x0000);
32178c2ecf20Sopenharmony_ci		if (ret_val)
32188c2ecf20Sopenharmony_ci			break;
32198c2ecf20Sopenharmony_ci		ret_val = E1000_SUCCESS;
32208c2ecf20Sopenharmony_ci	} while (0);
32218c2ecf20Sopenharmony_ci
32228c2ecf20Sopenharmony_ci	return ret_val;
32238c2ecf20Sopenharmony_ci}
32248c2ecf20Sopenharmony_ci
32258c2ecf20Sopenharmony_ci/**
32268c2ecf20Sopenharmony_ci * e1000_phy_igp_get_info - get igp specific registers
32278c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
32288c2ecf20Sopenharmony_ci * @phy_info: PHY information structure
32298c2ecf20Sopenharmony_ci *
32308c2ecf20Sopenharmony_ci * Get PHY information from various PHY registers for igp PHY only.
32318c2ecf20Sopenharmony_ci */
32328c2ecf20Sopenharmony_cistatic s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
32338c2ecf20Sopenharmony_ci				  struct e1000_phy_info *phy_info)
32348c2ecf20Sopenharmony_ci{
32358c2ecf20Sopenharmony_ci	s32 ret_val;
32368c2ecf20Sopenharmony_ci	u16 phy_data, min_length, max_length, average;
32378c2ecf20Sopenharmony_ci	e1000_rev_polarity polarity;
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci	/* The downshift status is checked only once, after link is established,
32408c2ecf20Sopenharmony_ci	 * and it stored in the hw->speed_downgraded parameter.
32418c2ecf20Sopenharmony_ci	 */
32428c2ecf20Sopenharmony_ci	phy_info->downshift = (e1000_downshift) hw->speed_downgraded;
32438c2ecf20Sopenharmony_ci
32448c2ecf20Sopenharmony_ci	/* IGP01E1000 does not need to support it. */
32458c2ecf20Sopenharmony_ci	phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
32468c2ecf20Sopenharmony_ci
32478c2ecf20Sopenharmony_ci	/* IGP01E1000 always correct polarity reversal */
32488c2ecf20Sopenharmony_ci	phy_info->polarity_correction = e1000_polarity_reversal_enabled;
32498c2ecf20Sopenharmony_ci
32508c2ecf20Sopenharmony_ci	/* Check polarity status */
32518c2ecf20Sopenharmony_ci	ret_val = e1000_check_polarity(hw, &polarity);
32528c2ecf20Sopenharmony_ci	if (ret_val)
32538c2ecf20Sopenharmony_ci		return ret_val;
32548c2ecf20Sopenharmony_ci
32558c2ecf20Sopenharmony_ci	phy_info->cable_polarity = polarity;
32568c2ecf20Sopenharmony_ci
32578c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data);
32588c2ecf20Sopenharmony_ci	if (ret_val)
32598c2ecf20Sopenharmony_ci		return ret_val;
32608c2ecf20Sopenharmony_ci
32618c2ecf20Sopenharmony_ci	phy_info->mdix_mode =
32628c2ecf20Sopenharmony_ci	    (e1000_auto_x_mode) ((phy_data & IGP01E1000_PSSR_MDIX) >>
32638c2ecf20Sopenharmony_ci				 IGP01E1000_PSSR_MDIX_SHIFT);
32648c2ecf20Sopenharmony_ci
32658c2ecf20Sopenharmony_ci	if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
32668c2ecf20Sopenharmony_ci	    IGP01E1000_PSSR_SPEED_1000MBPS) {
32678c2ecf20Sopenharmony_ci		/* Local/Remote Receiver Information are only valid @ 1000
32688c2ecf20Sopenharmony_ci		 * Mbps
32698c2ecf20Sopenharmony_ci		 */
32708c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
32718c2ecf20Sopenharmony_ci		if (ret_val)
32728c2ecf20Sopenharmony_ci			return ret_val;
32738c2ecf20Sopenharmony_ci
32748c2ecf20Sopenharmony_ci		phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
32758c2ecf20Sopenharmony_ci				      SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
32768c2ecf20Sopenharmony_ci		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
32778c2ecf20Sopenharmony_ci		phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
32788c2ecf20Sopenharmony_ci				       SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
32798c2ecf20Sopenharmony_ci		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
32808c2ecf20Sopenharmony_ci
32818c2ecf20Sopenharmony_ci		/* Get cable length */
32828c2ecf20Sopenharmony_ci		ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
32838c2ecf20Sopenharmony_ci		if (ret_val)
32848c2ecf20Sopenharmony_ci			return ret_val;
32858c2ecf20Sopenharmony_ci
32868c2ecf20Sopenharmony_ci		/* Translate to old method */
32878c2ecf20Sopenharmony_ci		average = (max_length + min_length) / 2;
32888c2ecf20Sopenharmony_ci
32898c2ecf20Sopenharmony_ci		if (average <= e1000_igp_cable_length_50)
32908c2ecf20Sopenharmony_ci			phy_info->cable_length = e1000_cable_length_50;
32918c2ecf20Sopenharmony_ci		else if (average <= e1000_igp_cable_length_80)
32928c2ecf20Sopenharmony_ci			phy_info->cable_length = e1000_cable_length_50_80;
32938c2ecf20Sopenharmony_ci		else if (average <= e1000_igp_cable_length_110)
32948c2ecf20Sopenharmony_ci			phy_info->cable_length = e1000_cable_length_80_110;
32958c2ecf20Sopenharmony_ci		else if (average <= e1000_igp_cable_length_140)
32968c2ecf20Sopenharmony_ci			phy_info->cable_length = e1000_cable_length_110_140;
32978c2ecf20Sopenharmony_ci		else
32988c2ecf20Sopenharmony_ci			phy_info->cable_length = e1000_cable_length_140;
32998c2ecf20Sopenharmony_ci	}
33008c2ecf20Sopenharmony_ci
33018c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
33028c2ecf20Sopenharmony_ci}
33038c2ecf20Sopenharmony_ci
33048c2ecf20Sopenharmony_ci/**
33058c2ecf20Sopenharmony_ci * e1000_phy_m88_get_info - get m88 specific registers
33068c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
33078c2ecf20Sopenharmony_ci * @phy_info: PHY information structure
33088c2ecf20Sopenharmony_ci *
33098c2ecf20Sopenharmony_ci * Get PHY information from various PHY registers for m88 PHY only.
33108c2ecf20Sopenharmony_ci */
33118c2ecf20Sopenharmony_cistatic s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
33128c2ecf20Sopenharmony_ci				  struct e1000_phy_info *phy_info)
33138c2ecf20Sopenharmony_ci{
33148c2ecf20Sopenharmony_ci	s32 ret_val;
33158c2ecf20Sopenharmony_ci	u16 phy_data;
33168c2ecf20Sopenharmony_ci	e1000_rev_polarity polarity;
33178c2ecf20Sopenharmony_ci
33188c2ecf20Sopenharmony_ci	/* The downshift status is checked only once, after link is established,
33198c2ecf20Sopenharmony_ci	 * and it stored in the hw->speed_downgraded parameter.
33208c2ecf20Sopenharmony_ci	 */
33218c2ecf20Sopenharmony_ci	phy_info->downshift = (e1000_downshift) hw->speed_downgraded;
33228c2ecf20Sopenharmony_ci
33238c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
33248c2ecf20Sopenharmony_ci	if (ret_val)
33258c2ecf20Sopenharmony_ci		return ret_val;
33268c2ecf20Sopenharmony_ci
33278c2ecf20Sopenharmony_ci	phy_info->extended_10bt_distance =
33288c2ecf20Sopenharmony_ci	    ((phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >>
33298c2ecf20Sopenharmony_ci	     M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT) ?
33308c2ecf20Sopenharmony_ci	    e1000_10bt_ext_dist_enable_lower :
33318c2ecf20Sopenharmony_ci	    e1000_10bt_ext_dist_enable_normal;
33328c2ecf20Sopenharmony_ci
33338c2ecf20Sopenharmony_ci	phy_info->polarity_correction =
33348c2ecf20Sopenharmony_ci	    ((phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >>
33358c2ecf20Sopenharmony_ci	     M88E1000_PSCR_POLARITY_REVERSAL_SHIFT) ?
33368c2ecf20Sopenharmony_ci	    e1000_polarity_reversal_disabled : e1000_polarity_reversal_enabled;
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_ci	/* Check polarity status */
33398c2ecf20Sopenharmony_ci	ret_val = e1000_check_polarity(hw, &polarity);
33408c2ecf20Sopenharmony_ci	if (ret_val)
33418c2ecf20Sopenharmony_ci		return ret_val;
33428c2ecf20Sopenharmony_ci	phy_info->cable_polarity = polarity;
33438c2ecf20Sopenharmony_ci
33448c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
33458c2ecf20Sopenharmony_ci	if (ret_val)
33468c2ecf20Sopenharmony_ci		return ret_val;
33478c2ecf20Sopenharmony_ci
33488c2ecf20Sopenharmony_ci	phy_info->mdix_mode =
33498c2ecf20Sopenharmony_ci	    (e1000_auto_x_mode) ((phy_data & M88E1000_PSSR_MDIX) >>
33508c2ecf20Sopenharmony_ci				 M88E1000_PSSR_MDIX_SHIFT);
33518c2ecf20Sopenharmony_ci
33528c2ecf20Sopenharmony_ci	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
33538c2ecf20Sopenharmony_ci		/* Cable Length Estimation and Local/Remote Receiver Information
33548c2ecf20Sopenharmony_ci		 * are only valid at 1000 Mbps.
33558c2ecf20Sopenharmony_ci		 */
33568c2ecf20Sopenharmony_ci		phy_info->cable_length =
33578c2ecf20Sopenharmony_ci		    (e1000_cable_length) ((phy_data &
33588c2ecf20Sopenharmony_ci					   M88E1000_PSSR_CABLE_LENGTH) >>
33598c2ecf20Sopenharmony_ci					  M88E1000_PSSR_CABLE_LENGTH_SHIFT);
33608c2ecf20Sopenharmony_ci
33618c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
33628c2ecf20Sopenharmony_ci		if (ret_val)
33638c2ecf20Sopenharmony_ci			return ret_val;
33648c2ecf20Sopenharmony_ci
33658c2ecf20Sopenharmony_ci		phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
33668c2ecf20Sopenharmony_ci				      SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
33678c2ecf20Sopenharmony_ci		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
33688c2ecf20Sopenharmony_ci		phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
33698c2ecf20Sopenharmony_ci				       SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
33708c2ecf20Sopenharmony_ci		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
33718c2ecf20Sopenharmony_ci	}
33728c2ecf20Sopenharmony_ci
33738c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
33748c2ecf20Sopenharmony_ci}
33758c2ecf20Sopenharmony_ci
33768c2ecf20Sopenharmony_ci/**
33778c2ecf20Sopenharmony_ci * e1000_phy_get_info - request phy info
33788c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
33798c2ecf20Sopenharmony_ci * @phy_info: PHY information structure
33808c2ecf20Sopenharmony_ci *
33818c2ecf20Sopenharmony_ci * Get PHY information from various PHY registers
33828c2ecf20Sopenharmony_ci */
33838c2ecf20Sopenharmony_cis32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
33848c2ecf20Sopenharmony_ci{
33858c2ecf20Sopenharmony_ci	s32 ret_val;
33868c2ecf20Sopenharmony_ci	u16 phy_data;
33878c2ecf20Sopenharmony_ci
33888c2ecf20Sopenharmony_ci	phy_info->cable_length = e1000_cable_length_undefined;
33898c2ecf20Sopenharmony_ci	phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined;
33908c2ecf20Sopenharmony_ci	phy_info->cable_polarity = e1000_rev_polarity_undefined;
33918c2ecf20Sopenharmony_ci	phy_info->downshift = e1000_downshift_undefined;
33928c2ecf20Sopenharmony_ci	phy_info->polarity_correction = e1000_polarity_reversal_undefined;
33938c2ecf20Sopenharmony_ci	phy_info->mdix_mode = e1000_auto_x_mode_undefined;
33948c2ecf20Sopenharmony_ci	phy_info->local_rx = e1000_1000t_rx_status_undefined;
33958c2ecf20Sopenharmony_ci	phy_info->remote_rx = e1000_1000t_rx_status_undefined;
33968c2ecf20Sopenharmony_ci
33978c2ecf20Sopenharmony_ci	if (hw->media_type != e1000_media_type_copper) {
33988c2ecf20Sopenharmony_ci		e_dbg("PHY info is only valid for copper media\n");
33998c2ecf20Sopenharmony_ci		return -E1000_ERR_CONFIG;
34008c2ecf20Sopenharmony_ci	}
34018c2ecf20Sopenharmony_ci
34028c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
34038c2ecf20Sopenharmony_ci	if (ret_val)
34048c2ecf20Sopenharmony_ci		return ret_val;
34058c2ecf20Sopenharmony_ci
34068c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
34078c2ecf20Sopenharmony_ci	if (ret_val)
34088c2ecf20Sopenharmony_ci		return ret_val;
34098c2ecf20Sopenharmony_ci
34108c2ecf20Sopenharmony_ci	if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
34118c2ecf20Sopenharmony_ci		e_dbg("PHY info is only valid if link is up\n");
34128c2ecf20Sopenharmony_ci		return -E1000_ERR_CONFIG;
34138c2ecf20Sopenharmony_ci	}
34148c2ecf20Sopenharmony_ci
34158c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp)
34168c2ecf20Sopenharmony_ci		return e1000_phy_igp_get_info(hw, phy_info);
34178c2ecf20Sopenharmony_ci	else if ((hw->phy_type == e1000_phy_8211) ||
34188c2ecf20Sopenharmony_ci		 (hw->phy_type == e1000_phy_8201))
34198c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
34208c2ecf20Sopenharmony_ci	else
34218c2ecf20Sopenharmony_ci		return e1000_phy_m88_get_info(hw, phy_info);
34228c2ecf20Sopenharmony_ci}
34238c2ecf20Sopenharmony_ci
34248c2ecf20Sopenharmony_cis32 e1000_validate_mdi_setting(struct e1000_hw *hw)
34258c2ecf20Sopenharmony_ci{
34268c2ecf20Sopenharmony_ci	if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) {
34278c2ecf20Sopenharmony_ci		e_dbg("Invalid MDI setting detected\n");
34288c2ecf20Sopenharmony_ci		hw->mdix = 1;
34298c2ecf20Sopenharmony_ci		return -E1000_ERR_CONFIG;
34308c2ecf20Sopenharmony_ci	}
34318c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
34328c2ecf20Sopenharmony_ci}
34338c2ecf20Sopenharmony_ci
34348c2ecf20Sopenharmony_ci/**
34358c2ecf20Sopenharmony_ci * e1000_init_eeprom_params - initialize sw eeprom vars
34368c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
34378c2ecf20Sopenharmony_ci *
34388c2ecf20Sopenharmony_ci * Sets up eeprom variables in the hw struct.  Must be called after mac_type
34398c2ecf20Sopenharmony_ci * is configured.
34408c2ecf20Sopenharmony_ci */
34418c2ecf20Sopenharmony_cis32 e1000_init_eeprom_params(struct e1000_hw *hw)
34428c2ecf20Sopenharmony_ci{
34438c2ecf20Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
34448c2ecf20Sopenharmony_ci	u32 eecd = er32(EECD);
34458c2ecf20Sopenharmony_ci	s32 ret_val = E1000_SUCCESS;
34468c2ecf20Sopenharmony_ci	u16 eeprom_size;
34478c2ecf20Sopenharmony_ci
34488c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
34498c2ecf20Sopenharmony_ci	case e1000_82542_rev2_0:
34508c2ecf20Sopenharmony_ci	case e1000_82542_rev2_1:
34518c2ecf20Sopenharmony_ci	case e1000_82543:
34528c2ecf20Sopenharmony_ci	case e1000_82544:
34538c2ecf20Sopenharmony_ci		eeprom->type = e1000_eeprom_microwire;
34548c2ecf20Sopenharmony_ci		eeprom->word_size = 64;
34558c2ecf20Sopenharmony_ci		eeprom->opcode_bits = 3;
34568c2ecf20Sopenharmony_ci		eeprom->address_bits = 6;
34578c2ecf20Sopenharmony_ci		eeprom->delay_usec = 50;
34588c2ecf20Sopenharmony_ci		break;
34598c2ecf20Sopenharmony_ci	case e1000_82540:
34608c2ecf20Sopenharmony_ci	case e1000_82545:
34618c2ecf20Sopenharmony_ci	case e1000_82545_rev_3:
34628c2ecf20Sopenharmony_ci	case e1000_82546:
34638c2ecf20Sopenharmony_ci	case e1000_82546_rev_3:
34648c2ecf20Sopenharmony_ci		eeprom->type = e1000_eeprom_microwire;
34658c2ecf20Sopenharmony_ci		eeprom->opcode_bits = 3;
34668c2ecf20Sopenharmony_ci		eeprom->delay_usec = 50;
34678c2ecf20Sopenharmony_ci		if (eecd & E1000_EECD_SIZE) {
34688c2ecf20Sopenharmony_ci			eeprom->word_size = 256;
34698c2ecf20Sopenharmony_ci			eeprom->address_bits = 8;
34708c2ecf20Sopenharmony_ci		} else {
34718c2ecf20Sopenharmony_ci			eeprom->word_size = 64;
34728c2ecf20Sopenharmony_ci			eeprom->address_bits = 6;
34738c2ecf20Sopenharmony_ci		}
34748c2ecf20Sopenharmony_ci		break;
34758c2ecf20Sopenharmony_ci	case e1000_82541:
34768c2ecf20Sopenharmony_ci	case e1000_82541_rev_2:
34778c2ecf20Sopenharmony_ci	case e1000_82547:
34788c2ecf20Sopenharmony_ci	case e1000_82547_rev_2:
34798c2ecf20Sopenharmony_ci		if (eecd & E1000_EECD_TYPE) {
34808c2ecf20Sopenharmony_ci			eeprom->type = e1000_eeprom_spi;
34818c2ecf20Sopenharmony_ci			eeprom->opcode_bits = 8;
34828c2ecf20Sopenharmony_ci			eeprom->delay_usec = 1;
34838c2ecf20Sopenharmony_ci			if (eecd & E1000_EECD_ADDR_BITS) {
34848c2ecf20Sopenharmony_ci				eeprom->page_size = 32;
34858c2ecf20Sopenharmony_ci				eeprom->address_bits = 16;
34868c2ecf20Sopenharmony_ci			} else {
34878c2ecf20Sopenharmony_ci				eeprom->page_size = 8;
34888c2ecf20Sopenharmony_ci				eeprom->address_bits = 8;
34898c2ecf20Sopenharmony_ci			}
34908c2ecf20Sopenharmony_ci		} else {
34918c2ecf20Sopenharmony_ci			eeprom->type = e1000_eeprom_microwire;
34928c2ecf20Sopenharmony_ci			eeprom->opcode_bits = 3;
34938c2ecf20Sopenharmony_ci			eeprom->delay_usec = 50;
34948c2ecf20Sopenharmony_ci			if (eecd & E1000_EECD_ADDR_BITS) {
34958c2ecf20Sopenharmony_ci				eeprom->word_size = 256;
34968c2ecf20Sopenharmony_ci				eeprom->address_bits = 8;
34978c2ecf20Sopenharmony_ci			} else {
34988c2ecf20Sopenharmony_ci				eeprom->word_size = 64;
34998c2ecf20Sopenharmony_ci				eeprom->address_bits = 6;
35008c2ecf20Sopenharmony_ci			}
35018c2ecf20Sopenharmony_ci		}
35028c2ecf20Sopenharmony_ci		break;
35038c2ecf20Sopenharmony_ci	default:
35048c2ecf20Sopenharmony_ci		break;
35058c2ecf20Sopenharmony_ci	}
35068c2ecf20Sopenharmony_ci
35078c2ecf20Sopenharmony_ci	if (eeprom->type == e1000_eeprom_spi) {
35088c2ecf20Sopenharmony_ci		/* eeprom_size will be an enum [0..8] that maps to eeprom sizes
35098c2ecf20Sopenharmony_ci		 * 128B to 32KB (incremented by powers of 2).
35108c2ecf20Sopenharmony_ci		 */
35118c2ecf20Sopenharmony_ci		/* Set to default value for initial eeprom read. */
35128c2ecf20Sopenharmony_ci		eeprom->word_size = 64;
35138c2ecf20Sopenharmony_ci		ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size);
35148c2ecf20Sopenharmony_ci		if (ret_val)
35158c2ecf20Sopenharmony_ci			return ret_val;
35168c2ecf20Sopenharmony_ci		eeprom_size =
35178c2ecf20Sopenharmony_ci		    (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT;
35188c2ecf20Sopenharmony_ci		/* 256B eeprom size was not supported in earlier hardware, so we
35198c2ecf20Sopenharmony_ci		 * bump eeprom_size up one to ensure that "1" (which maps to
35208c2ecf20Sopenharmony_ci		 * 256B) is never the result used in the shifting logic below.
35218c2ecf20Sopenharmony_ci		 */
35228c2ecf20Sopenharmony_ci		if (eeprom_size)
35238c2ecf20Sopenharmony_ci			eeprom_size++;
35248c2ecf20Sopenharmony_ci
35258c2ecf20Sopenharmony_ci		eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT);
35268c2ecf20Sopenharmony_ci	}
35278c2ecf20Sopenharmony_ci	return ret_val;
35288c2ecf20Sopenharmony_ci}
35298c2ecf20Sopenharmony_ci
35308c2ecf20Sopenharmony_ci/**
35318c2ecf20Sopenharmony_ci * e1000_raise_ee_clk - Raises the EEPROM's clock input.
35328c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
35338c2ecf20Sopenharmony_ci * @eecd: EECD's current value
35348c2ecf20Sopenharmony_ci */
35358c2ecf20Sopenharmony_cistatic void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd)
35368c2ecf20Sopenharmony_ci{
35378c2ecf20Sopenharmony_ci	/* Raise the clock input to the EEPROM (by setting the SK bit), and then
35388c2ecf20Sopenharmony_ci	 * wait <delay> microseconds.
35398c2ecf20Sopenharmony_ci	 */
35408c2ecf20Sopenharmony_ci	*eecd = *eecd | E1000_EECD_SK;
35418c2ecf20Sopenharmony_ci	ew32(EECD, *eecd);
35428c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
35438c2ecf20Sopenharmony_ci	udelay(hw->eeprom.delay_usec);
35448c2ecf20Sopenharmony_ci}
35458c2ecf20Sopenharmony_ci
35468c2ecf20Sopenharmony_ci/**
35478c2ecf20Sopenharmony_ci * e1000_lower_ee_clk - Lowers the EEPROM's clock input.
35488c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
35498c2ecf20Sopenharmony_ci * @eecd: EECD's current value
35508c2ecf20Sopenharmony_ci */
35518c2ecf20Sopenharmony_cistatic void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd)
35528c2ecf20Sopenharmony_ci{
35538c2ecf20Sopenharmony_ci	/* Lower the clock input to the EEPROM (by clearing the SK bit), and
35548c2ecf20Sopenharmony_ci	 * then wait 50 microseconds.
35558c2ecf20Sopenharmony_ci	 */
35568c2ecf20Sopenharmony_ci	*eecd = *eecd & ~E1000_EECD_SK;
35578c2ecf20Sopenharmony_ci	ew32(EECD, *eecd);
35588c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
35598c2ecf20Sopenharmony_ci	udelay(hw->eeprom.delay_usec);
35608c2ecf20Sopenharmony_ci}
35618c2ecf20Sopenharmony_ci
35628c2ecf20Sopenharmony_ci/**
35638c2ecf20Sopenharmony_ci * e1000_shift_out_ee_bits - Shift data bits out to the EEPROM.
35648c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
35658c2ecf20Sopenharmony_ci * @data: data to send to the EEPROM
35668c2ecf20Sopenharmony_ci * @count: number of bits to shift out
35678c2ecf20Sopenharmony_ci */
35688c2ecf20Sopenharmony_cistatic void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count)
35698c2ecf20Sopenharmony_ci{
35708c2ecf20Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
35718c2ecf20Sopenharmony_ci	u32 eecd;
35728c2ecf20Sopenharmony_ci	u32 mask;
35738c2ecf20Sopenharmony_ci
35748c2ecf20Sopenharmony_ci	/* We need to shift "count" bits out to the EEPROM. So, value in the
35758c2ecf20Sopenharmony_ci	 * "data" parameter will be shifted out to the EEPROM one bit at a time.
35768c2ecf20Sopenharmony_ci	 * In order to do this, "data" must be broken down into bits.
35778c2ecf20Sopenharmony_ci	 */
35788c2ecf20Sopenharmony_ci	mask = 0x01 << (count - 1);
35798c2ecf20Sopenharmony_ci	eecd = er32(EECD);
35808c2ecf20Sopenharmony_ci	if (eeprom->type == e1000_eeprom_microwire)
35818c2ecf20Sopenharmony_ci		eecd &= ~E1000_EECD_DO;
35828c2ecf20Sopenharmony_ci	else if (eeprom->type == e1000_eeprom_spi)
35838c2ecf20Sopenharmony_ci		eecd |= E1000_EECD_DO;
35848c2ecf20Sopenharmony_ci
35858c2ecf20Sopenharmony_ci	do {
35868c2ecf20Sopenharmony_ci		/* A "1" is shifted out to the EEPROM by setting bit "DI" to a
35878c2ecf20Sopenharmony_ci		 * "1", and then raising and then lowering the clock (the SK bit
35888c2ecf20Sopenharmony_ci		 * controls the clock input to the EEPROM).  A "0" is shifted
35898c2ecf20Sopenharmony_ci		 * out to the EEPROM by setting "DI" to "0" and then raising and
35908c2ecf20Sopenharmony_ci		 * then lowering the clock.
35918c2ecf20Sopenharmony_ci		 */
35928c2ecf20Sopenharmony_ci		eecd &= ~E1000_EECD_DI;
35938c2ecf20Sopenharmony_ci
35948c2ecf20Sopenharmony_ci		if (data & mask)
35958c2ecf20Sopenharmony_ci			eecd |= E1000_EECD_DI;
35968c2ecf20Sopenharmony_ci
35978c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
35988c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
35998c2ecf20Sopenharmony_ci
36008c2ecf20Sopenharmony_ci		udelay(eeprom->delay_usec);
36018c2ecf20Sopenharmony_ci
36028c2ecf20Sopenharmony_ci		e1000_raise_ee_clk(hw, &eecd);
36038c2ecf20Sopenharmony_ci		e1000_lower_ee_clk(hw, &eecd);
36048c2ecf20Sopenharmony_ci
36058c2ecf20Sopenharmony_ci		mask = mask >> 1;
36068c2ecf20Sopenharmony_ci
36078c2ecf20Sopenharmony_ci	} while (mask);
36088c2ecf20Sopenharmony_ci
36098c2ecf20Sopenharmony_ci	/* We leave the "DI" bit set to "0" when we leave this routine. */
36108c2ecf20Sopenharmony_ci	eecd &= ~E1000_EECD_DI;
36118c2ecf20Sopenharmony_ci	ew32(EECD, eecd);
36128c2ecf20Sopenharmony_ci}
36138c2ecf20Sopenharmony_ci
36148c2ecf20Sopenharmony_ci/**
36158c2ecf20Sopenharmony_ci * e1000_shift_in_ee_bits - Shift data bits in from the EEPROM
36168c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
36178c2ecf20Sopenharmony_ci * @count: number of bits to shift in
36188c2ecf20Sopenharmony_ci */
36198c2ecf20Sopenharmony_cistatic u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count)
36208c2ecf20Sopenharmony_ci{
36218c2ecf20Sopenharmony_ci	u32 eecd;
36228c2ecf20Sopenharmony_ci	u32 i;
36238c2ecf20Sopenharmony_ci	u16 data;
36248c2ecf20Sopenharmony_ci
36258c2ecf20Sopenharmony_ci	/* In order to read a register from the EEPROM, we need to shift 'count'
36268c2ecf20Sopenharmony_ci	 * bits in from the EEPROM. Bits are "shifted in" by raising the clock
36278c2ecf20Sopenharmony_ci	 * input to the EEPROM (setting the SK bit), and then reading the value
36288c2ecf20Sopenharmony_ci	 * of the "DO" bit.  During this "shifting in" process the "DI" bit
36298c2ecf20Sopenharmony_ci	 * should always be clear.
36308c2ecf20Sopenharmony_ci	 */
36318c2ecf20Sopenharmony_ci
36328c2ecf20Sopenharmony_ci	eecd = er32(EECD);
36338c2ecf20Sopenharmony_ci
36348c2ecf20Sopenharmony_ci	eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
36358c2ecf20Sopenharmony_ci	data = 0;
36368c2ecf20Sopenharmony_ci
36378c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++) {
36388c2ecf20Sopenharmony_ci		data = data << 1;
36398c2ecf20Sopenharmony_ci		e1000_raise_ee_clk(hw, &eecd);
36408c2ecf20Sopenharmony_ci
36418c2ecf20Sopenharmony_ci		eecd = er32(EECD);
36428c2ecf20Sopenharmony_ci
36438c2ecf20Sopenharmony_ci		eecd &= ~(E1000_EECD_DI);
36448c2ecf20Sopenharmony_ci		if (eecd & E1000_EECD_DO)
36458c2ecf20Sopenharmony_ci			data |= 1;
36468c2ecf20Sopenharmony_ci
36478c2ecf20Sopenharmony_ci		e1000_lower_ee_clk(hw, &eecd);
36488c2ecf20Sopenharmony_ci	}
36498c2ecf20Sopenharmony_ci
36508c2ecf20Sopenharmony_ci	return data;
36518c2ecf20Sopenharmony_ci}
36528c2ecf20Sopenharmony_ci
36538c2ecf20Sopenharmony_ci/**
36548c2ecf20Sopenharmony_ci * e1000_acquire_eeprom - Prepares EEPROM for access
36558c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
36568c2ecf20Sopenharmony_ci *
36578c2ecf20Sopenharmony_ci * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
36588c2ecf20Sopenharmony_ci * function should be called before issuing a command to the EEPROM.
36598c2ecf20Sopenharmony_ci */
36608c2ecf20Sopenharmony_cistatic s32 e1000_acquire_eeprom(struct e1000_hw *hw)
36618c2ecf20Sopenharmony_ci{
36628c2ecf20Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
36638c2ecf20Sopenharmony_ci	u32 eecd, i = 0;
36648c2ecf20Sopenharmony_ci
36658c2ecf20Sopenharmony_ci	eecd = er32(EECD);
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci	/* Request EEPROM Access */
36688c2ecf20Sopenharmony_ci	if (hw->mac_type > e1000_82544) {
36698c2ecf20Sopenharmony_ci		eecd |= E1000_EECD_REQ;
36708c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
36718c2ecf20Sopenharmony_ci		eecd = er32(EECD);
36728c2ecf20Sopenharmony_ci		while ((!(eecd & E1000_EECD_GNT)) &&
36738c2ecf20Sopenharmony_ci		       (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
36748c2ecf20Sopenharmony_ci			i++;
36758c2ecf20Sopenharmony_ci			udelay(5);
36768c2ecf20Sopenharmony_ci			eecd = er32(EECD);
36778c2ecf20Sopenharmony_ci		}
36788c2ecf20Sopenharmony_ci		if (!(eecd & E1000_EECD_GNT)) {
36798c2ecf20Sopenharmony_ci			eecd &= ~E1000_EECD_REQ;
36808c2ecf20Sopenharmony_ci			ew32(EECD, eecd);
36818c2ecf20Sopenharmony_ci			e_dbg("Could not acquire EEPROM grant\n");
36828c2ecf20Sopenharmony_ci			return -E1000_ERR_EEPROM;
36838c2ecf20Sopenharmony_ci		}
36848c2ecf20Sopenharmony_ci	}
36858c2ecf20Sopenharmony_ci
36868c2ecf20Sopenharmony_ci	/* Setup EEPROM for Read/Write */
36878c2ecf20Sopenharmony_ci
36888c2ecf20Sopenharmony_ci	if (eeprom->type == e1000_eeprom_microwire) {
36898c2ecf20Sopenharmony_ci		/* Clear SK and DI */
36908c2ecf20Sopenharmony_ci		eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
36918c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
36928c2ecf20Sopenharmony_ci
36938c2ecf20Sopenharmony_ci		/* Set CS */
36948c2ecf20Sopenharmony_ci		eecd |= E1000_EECD_CS;
36958c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
36968c2ecf20Sopenharmony_ci	} else if (eeprom->type == e1000_eeprom_spi) {
36978c2ecf20Sopenharmony_ci		/* Clear SK and CS */
36988c2ecf20Sopenharmony_ci		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
36998c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37008c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
37018c2ecf20Sopenharmony_ci		udelay(1);
37028c2ecf20Sopenharmony_ci	}
37038c2ecf20Sopenharmony_ci
37048c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
37058c2ecf20Sopenharmony_ci}
37068c2ecf20Sopenharmony_ci
37078c2ecf20Sopenharmony_ci/**
37088c2ecf20Sopenharmony_ci * e1000_standby_eeprom - Returns EEPROM to a "standby" state
37098c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
37108c2ecf20Sopenharmony_ci */
37118c2ecf20Sopenharmony_cistatic void e1000_standby_eeprom(struct e1000_hw *hw)
37128c2ecf20Sopenharmony_ci{
37138c2ecf20Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
37148c2ecf20Sopenharmony_ci	u32 eecd;
37158c2ecf20Sopenharmony_ci
37168c2ecf20Sopenharmony_ci	eecd = er32(EECD);
37178c2ecf20Sopenharmony_ci
37188c2ecf20Sopenharmony_ci	if (eeprom->type == e1000_eeprom_microwire) {
37198c2ecf20Sopenharmony_ci		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
37208c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37218c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
37228c2ecf20Sopenharmony_ci		udelay(eeprom->delay_usec);
37238c2ecf20Sopenharmony_ci
37248c2ecf20Sopenharmony_ci		/* Clock high */
37258c2ecf20Sopenharmony_ci		eecd |= E1000_EECD_SK;
37268c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37278c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
37288c2ecf20Sopenharmony_ci		udelay(eeprom->delay_usec);
37298c2ecf20Sopenharmony_ci
37308c2ecf20Sopenharmony_ci		/* Select EEPROM */
37318c2ecf20Sopenharmony_ci		eecd |= E1000_EECD_CS;
37328c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37338c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
37348c2ecf20Sopenharmony_ci		udelay(eeprom->delay_usec);
37358c2ecf20Sopenharmony_ci
37368c2ecf20Sopenharmony_ci		/* Clock low */
37378c2ecf20Sopenharmony_ci		eecd &= ~E1000_EECD_SK;
37388c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37398c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
37408c2ecf20Sopenharmony_ci		udelay(eeprom->delay_usec);
37418c2ecf20Sopenharmony_ci	} else if (eeprom->type == e1000_eeprom_spi) {
37428c2ecf20Sopenharmony_ci		/* Toggle CS to flush commands */
37438c2ecf20Sopenharmony_ci		eecd |= E1000_EECD_CS;
37448c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37458c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
37468c2ecf20Sopenharmony_ci		udelay(eeprom->delay_usec);
37478c2ecf20Sopenharmony_ci		eecd &= ~E1000_EECD_CS;
37488c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37498c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
37508c2ecf20Sopenharmony_ci		udelay(eeprom->delay_usec);
37518c2ecf20Sopenharmony_ci	}
37528c2ecf20Sopenharmony_ci}
37538c2ecf20Sopenharmony_ci
37548c2ecf20Sopenharmony_ci/**
37558c2ecf20Sopenharmony_ci * e1000_release_eeprom - drop chip select
37568c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
37578c2ecf20Sopenharmony_ci *
37588c2ecf20Sopenharmony_ci * Terminates a command by inverting the EEPROM's chip select pin
37598c2ecf20Sopenharmony_ci */
37608c2ecf20Sopenharmony_cistatic void e1000_release_eeprom(struct e1000_hw *hw)
37618c2ecf20Sopenharmony_ci{
37628c2ecf20Sopenharmony_ci	u32 eecd;
37638c2ecf20Sopenharmony_ci
37648c2ecf20Sopenharmony_ci	eecd = er32(EECD);
37658c2ecf20Sopenharmony_ci
37668c2ecf20Sopenharmony_ci	if (hw->eeprom.type == e1000_eeprom_spi) {
37678c2ecf20Sopenharmony_ci		eecd |= E1000_EECD_CS;	/* Pull CS high */
37688c2ecf20Sopenharmony_ci		eecd &= ~E1000_EECD_SK;	/* Lower SCK */
37698c2ecf20Sopenharmony_ci
37708c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37718c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
37728c2ecf20Sopenharmony_ci
37738c2ecf20Sopenharmony_ci		udelay(hw->eeprom.delay_usec);
37748c2ecf20Sopenharmony_ci	} else if (hw->eeprom.type == e1000_eeprom_microwire) {
37758c2ecf20Sopenharmony_ci		/* cleanup eeprom */
37768c2ecf20Sopenharmony_ci
37778c2ecf20Sopenharmony_ci		/* CS on Microwire is active-high */
37788c2ecf20Sopenharmony_ci		eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
37798c2ecf20Sopenharmony_ci
37808c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37818c2ecf20Sopenharmony_ci
37828c2ecf20Sopenharmony_ci		/* Rising edge of clock */
37838c2ecf20Sopenharmony_ci		eecd |= E1000_EECD_SK;
37848c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37858c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
37868c2ecf20Sopenharmony_ci		udelay(hw->eeprom.delay_usec);
37878c2ecf20Sopenharmony_ci
37888c2ecf20Sopenharmony_ci		/* Falling edge of clock */
37898c2ecf20Sopenharmony_ci		eecd &= ~E1000_EECD_SK;
37908c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37918c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
37928c2ecf20Sopenharmony_ci		udelay(hw->eeprom.delay_usec);
37938c2ecf20Sopenharmony_ci	}
37948c2ecf20Sopenharmony_ci
37958c2ecf20Sopenharmony_ci	/* Stop requesting EEPROM access */
37968c2ecf20Sopenharmony_ci	if (hw->mac_type > e1000_82544) {
37978c2ecf20Sopenharmony_ci		eecd &= ~E1000_EECD_REQ;
37988c2ecf20Sopenharmony_ci		ew32(EECD, eecd);
37998c2ecf20Sopenharmony_ci	}
38008c2ecf20Sopenharmony_ci}
38018c2ecf20Sopenharmony_ci
38028c2ecf20Sopenharmony_ci/**
38038c2ecf20Sopenharmony_ci * e1000_spi_eeprom_ready - Reads a 16 bit word from the EEPROM.
38048c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
38058c2ecf20Sopenharmony_ci */
38068c2ecf20Sopenharmony_cistatic s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
38078c2ecf20Sopenharmony_ci{
38088c2ecf20Sopenharmony_ci	u16 retry_count = 0;
38098c2ecf20Sopenharmony_ci	u8 spi_stat_reg;
38108c2ecf20Sopenharmony_ci
38118c2ecf20Sopenharmony_ci	/* Read "Status Register" repeatedly until the LSB is cleared.  The
38128c2ecf20Sopenharmony_ci	 * EEPROM will signal that the command has been completed by clearing
38138c2ecf20Sopenharmony_ci	 * bit 0 of the internal status register.  If it's not cleared within
38148c2ecf20Sopenharmony_ci	 * 5 milliseconds, then error out.
38158c2ecf20Sopenharmony_ci	 */
38168c2ecf20Sopenharmony_ci	retry_count = 0;
38178c2ecf20Sopenharmony_ci	do {
38188c2ecf20Sopenharmony_ci		e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
38198c2ecf20Sopenharmony_ci					hw->eeprom.opcode_bits);
38208c2ecf20Sopenharmony_ci		spi_stat_reg = (u8)e1000_shift_in_ee_bits(hw, 8);
38218c2ecf20Sopenharmony_ci		if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
38228c2ecf20Sopenharmony_ci			break;
38238c2ecf20Sopenharmony_ci
38248c2ecf20Sopenharmony_ci		udelay(5);
38258c2ecf20Sopenharmony_ci		retry_count += 5;
38268c2ecf20Sopenharmony_ci
38278c2ecf20Sopenharmony_ci		e1000_standby_eeprom(hw);
38288c2ecf20Sopenharmony_ci	} while (retry_count < EEPROM_MAX_RETRY_SPI);
38298c2ecf20Sopenharmony_ci
38308c2ecf20Sopenharmony_ci	/* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
38318c2ecf20Sopenharmony_ci	 * only 0-5mSec on 5V devices)
38328c2ecf20Sopenharmony_ci	 */
38338c2ecf20Sopenharmony_ci	if (retry_count >= EEPROM_MAX_RETRY_SPI) {
38348c2ecf20Sopenharmony_ci		e_dbg("SPI EEPROM Status error\n");
38358c2ecf20Sopenharmony_ci		return -E1000_ERR_EEPROM;
38368c2ecf20Sopenharmony_ci	}
38378c2ecf20Sopenharmony_ci
38388c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
38398c2ecf20Sopenharmony_ci}
38408c2ecf20Sopenharmony_ci
38418c2ecf20Sopenharmony_ci/**
38428c2ecf20Sopenharmony_ci * e1000_read_eeprom - Reads a 16 bit word from the EEPROM.
38438c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
38448c2ecf20Sopenharmony_ci * @offset: offset of  word in the EEPROM to read
38458c2ecf20Sopenharmony_ci * @data: word read from the EEPROM
38468c2ecf20Sopenharmony_ci * @words: number of words to read
38478c2ecf20Sopenharmony_ci */
38488c2ecf20Sopenharmony_cis32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
38498c2ecf20Sopenharmony_ci{
38508c2ecf20Sopenharmony_ci	s32 ret;
38518c2ecf20Sopenharmony_ci
38528c2ecf20Sopenharmony_ci	mutex_lock(&e1000_eeprom_lock);
38538c2ecf20Sopenharmony_ci	ret = e1000_do_read_eeprom(hw, offset, words, data);
38548c2ecf20Sopenharmony_ci	mutex_unlock(&e1000_eeprom_lock);
38558c2ecf20Sopenharmony_ci	return ret;
38568c2ecf20Sopenharmony_ci}
38578c2ecf20Sopenharmony_ci
38588c2ecf20Sopenharmony_cistatic s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
38598c2ecf20Sopenharmony_ci				u16 *data)
38608c2ecf20Sopenharmony_ci{
38618c2ecf20Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
38628c2ecf20Sopenharmony_ci	u32 i = 0;
38638c2ecf20Sopenharmony_ci
38648c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_ce4100) {
38658c2ecf20Sopenharmony_ci		GBE_CONFIG_FLASH_READ(GBE_CONFIG_BASE_VIRT, offset, words,
38668c2ecf20Sopenharmony_ci				      data);
38678c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
38688c2ecf20Sopenharmony_ci	}
38698c2ecf20Sopenharmony_ci
38708c2ecf20Sopenharmony_ci	/* A check for invalid values:  offset too large, too many words, and
38718c2ecf20Sopenharmony_ci	 * not enough words.
38728c2ecf20Sopenharmony_ci	 */
38738c2ecf20Sopenharmony_ci	if ((offset >= eeprom->word_size) ||
38748c2ecf20Sopenharmony_ci	    (words > eeprom->word_size - offset) ||
38758c2ecf20Sopenharmony_ci	    (words == 0)) {
38768c2ecf20Sopenharmony_ci		e_dbg("\"words\" parameter out of bounds. Words = %d,"
38778c2ecf20Sopenharmony_ci		      "size = %d\n", offset, eeprom->word_size);
38788c2ecf20Sopenharmony_ci		return -E1000_ERR_EEPROM;
38798c2ecf20Sopenharmony_ci	}
38808c2ecf20Sopenharmony_ci
38818c2ecf20Sopenharmony_ci	/* EEPROM's that don't use EERD to read require us to bit-bang the SPI
38828c2ecf20Sopenharmony_ci	 * directly. In this case, we need to acquire the EEPROM so that
38838c2ecf20Sopenharmony_ci	 * FW or other port software does not interrupt.
38848c2ecf20Sopenharmony_ci	 */
38858c2ecf20Sopenharmony_ci	/* Prepare the EEPROM for bit-bang reading */
38868c2ecf20Sopenharmony_ci	if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
38878c2ecf20Sopenharmony_ci		return -E1000_ERR_EEPROM;
38888c2ecf20Sopenharmony_ci
38898c2ecf20Sopenharmony_ci	/* Set up the SPI or Microwire EEPROM for bit-bang reading.  We have
38908c2ecf20Sopenharmony_ci	 * acquired the EEPROM at this point, so any returns should release it
38918c2ecf20Sopenharmony_ci	 */
38928c2ecf20Sopenharmony_ci	if (eeprom->type == e1000_eeprom_spi) {
38938c2ecf20Sopenharmony_ci		u16 word_in;
38948c2ecf20Sopenharmony_ci		u8 read_opcode = EEPROM_READ_OPCODE_SPI;
38958c2ecf20Sopenharmony_ci
38968c2ecf20Sopenharmony_ci		if (e1000_spi_eeprom_ready(hw)) {
38978c2ecf20Sopenharmony_ci			e1000_release_eeprom(hw);
38988c2ecf20Sopenharmony_ci			return -E1000_ERR_EEPROM;
38998c2ecf20Sopenharmony_ci		}
39008c2ecf20Sopenharmony_ci
39018c2ecf20Sopenharmony_ci		e1000_standby_eeprom(hw);
39028c2ecf20Sopenharmony_ci
39038c2ecf20Sopenharmony_ci		/* Some SPI eeproms use the 8th address bit embedded in the
39048c2ecf20Sopenharmony_ci		 * opcode
39058c2ecf20Sopenharmony_ci		 */
39068c2ecf20Sopenharmony_ci		if ((eeprom->address_bits == 8) && (offset >= 128))
39078c2ecf20Sopenharmony_ci			read_opcode |= EEPROM_A8_OPCODE_SPI;
39088c2ecf20Sopenharmony_ci
39098c2ecf20Sopenharmony_ci		/* Send the READ command (opcode + addr)  */
39108c2ecf20Sopenharmony_ci		e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
39118c2ecf20Sopenharmony_ci		e1000_shift_out_ee_bits(hw, (u16)(offset * 2),
39128c2ecf20Sopenharmony_ci					eeprom->address_bits);
39138c2ecf20Sopenharmony_ci
39148c2ecf20Sopenharmony_ci		/* Read the data.  The address of the eeprom internally
39158c2ecf20Sopenharmony_ci		 * increments with each byte (spi) being read, saving on the
39168c2ecf20Sopenharmony_ci		 * overhead of eeprom setup and tear-down.  The address counter
39178c2ecf20Sopenharmony_ci		 * will roll over if reading beyond the size of the eeprom, thus
39188c2ecf20Sopenharmony_ci		 * allowing the entire memory to be read starting from any
39198c2ecf20Sopenharmony_ci		 * offset.
39208c2ecf20Sopenharmony_ci		 */
39218c2ecf20Sopenharmony_ci		for (i = 0; i < words; i++) {
39228c2ecf20Sopenharmony_ci			word_in = e1000_shift_in_ee_bits(hw, 16);
39238c2ecf20Sopenharmony_ci			data[i] = (word_in >> 8) | (word_in << 8);
39248c2ecf20Sopenharmony_ci		}
39258c2ecf20Sopenharmony_ci	} else if (eeprom->type == e1000_eeprom_microwire) {
39268c2ecf20Sopenharmony_ci		for (i = 0; i < words; i++) {
39278c2ecf20Sopenharmony_ci			/* Send the READ command (opcode + addr)  */
39288c2ecf20Sopenharmony_ci			e1000_shift_out_ee_bits(hw,
39298c2ecf20Sopenharmony_ci						EEPROM_READ_OPCODE_MICROWIRE,
39308c2ecf20Sopenharmony_ci						eeprom->opcode_bits);
39318c2ecf20Sopenharmony_ci			e1000_shift_out_ee_bits(hw, (u16)(offset + i),
39328c2ecf20Sopenharmony_ci						eeprom->address_bits);
39338c2ecf20Sopenharmony_ci
39348c2ecf20Sopenharmony_ci			/* Read the data.  For microwire, each word requires the
39358c2ecf20Sopenharmony_ci			 * overhead of eeprom setup and tear-down.
39368c2ecf20Sopenharmony_ci			 */
39378c2ecf20Sopenharmony_ci			data[i] = e1000_shift_in_ee_bits(hw, 16);
39388c2ecf20Sopenharmony_ci			e1000_standby_eeprom(hw);
39398c2ecf20Sopenharmony_ci			cond_resched();
39408c2ecf20Sopenharmony_ci		}
39418c2ecf20Sopenharmony_ci	}
39428c2ecf20Sopenharmony_ci
39438c2ecf20Sopenharmony_ci	/* End this read operation */
39448c2ecf20Sopenharmony_ci	e1000_release_eeprom(hw);
39458c2ecf20Sopenharmony_ci
39468c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
39478c2ecf20Sopenharmony_ci}
39488c2ecf20Sopenharmony_ci
39498c2ecf20Sopenharmony_ci/**
39508c2ecf20Sopenharmony_ci * e1000_validate_eeprom_checksum - Verifies that the EEPROM has a valid checksum
39518c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
39528c2ecf20Sopenharmony_ci *
39538c2ecf20Sopenharmony_ci * Reads the first 64 16 bit words of the EEPROM and sums the values read.
39548c2ecf20Sopenharmony_ci * If the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
39558c2ecf20Sopenharmony_ci * valid.
39568c2ecf20Sopenharmony_ci */
39578c2ecf20Sopenharmony_cis32 e1000_validate_eeprom_checksum(struct e1000_hw *hw)
39588c2ecf20Sopenharmony_ci{
39598c2ecf20Sopenharmony_ci	u16 checksum = 0;
39608c2ecf20Sopenharmony_ci	u16 i, eeprom_data;
39618c2ecf20Sopenharmony_ci
39628c2ecf20Sopenharmony_ci	for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
39638c2ecf20Sopenharmony_ci		if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
39648c2ecf20Sopenharmony_ci			e_dbg("EEPROM Read Error\n");
39658c2ecf20Sopenharmony_ci			return -E1000_ERR_EEPROM;
39668c2ecf20Sopenharmony_ci		}
39678c2ecf20Sopenharmony_ci		checksum += eeprom_data;
39688c2ecf20Sopenharmony_ci	}
39698c2ecf20Sopenharmony_ci
39708c2ecf20Sopenharmony_ci#ifdef CONFIG_PARISC
39718c2ecf20Sopenharmony_ci	/* This is a signature and not a checksum on HP c8000 */
39728c2ecf20Sopenharmony_ci	if ((hw->subsystem_vendor_id == 0x103C) && (eeprom_data == 0x16d6))
39738c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
39748c2ecf20Sopenharmony_ci
39758c2ecf20Sopenharmony_ci#endif
39768c2ecf20Sopenharmony_ci	if (checksum == (u16)EEPROM_SUM)
39778c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
39788c2ecf20Sopenharmony_ci	else {
39798c2ecf20Sopenharmony_ci		e_dbg("EEPROM Checksum Invalid\n");
39808c2ecf20Sopenharmony_ci		return -E1000_ERR_EEPROM;
39818c2ecf20Sopenharmony_ci	}
39828c2ecf20Sopenharmony_ci}
39838c2ecf20Sopenharmony_ci
39848c2ecf20Sopenharmony_ci/**
39858c2ecf20Sopenharmony_ci * e1000_update_eeprom_checksum - Calculates/writes the EEPROM checksum
39868c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
39878c2ecf20Sopenharmony_ci *
39888c2ecf20Sopenharmony_ci * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
39898c2ecf20Sopenharmony_ci * Writes the difference to word offset 63 of the EEPROM.
39908c2ecf20Sopenharmony_ci */
39918c2ecf20Sopenharmony_cis32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
39928c2ecf20Sopenharmony_ci{
39938c2ecf20Sopenharmony_ci	u16 checksum = 0;
39948c2ecf20Sopenharmony_ci	u16 i, eeprom_data;
39958c2ecf20Sopenharmony_ci
39968c2ecf20Sopenharmony_ci	for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
39978c2ecf20Sopenharmony_ci		if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
39988c2ecf20Sopenharmony_ci			e_dbg("EEPROM Read Error\n");
39998c2ecf20Sopenharmony_ci			return -E1000_ERR_EEPROM;
40008c2ecf20Sopenharmony_ci		}
40018c2ecf20Sopenharmony_ci		checksum += eeprom_data;
40028c2ecf20Sopenharmony_ci	}
40038c2ecf20Sopenharmony_ci	checksum = (u16)EEPROM_SUM - checksum;
40048c2ecf20Sopenharmony_ci	if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
40058c2ecf20Sopenharmony_ci		e_dbg("EEPROM Write Error\n");
40068c2ecf20Sopenharmony_ci		return -E1000_ERR_EEPROM;
40078c2ecf20Sopenharmony_ci	}
40088c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
40098c2ecf20Sopenharmony_ci}
40108c2ecf20Sopenharmony_ci
40118c2ecf20Sopenharmony_ci/**
40128c2ecf20Sopenharmony_ci * e1000_write_eeprom - write words to the different EEPROM types.
40138c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
40148c2ecf20Sopenharmony_ci * @offset: offset within the EEPROM to be written to
40158c2ecf20Sopenharmony_ci * @words: number of words to write
40168c2ecf20Sopenharmony_ci * @data: 16 bit word to be written to the EEPROM
40178c2ecf20Sopenharmony_ci *
40188c2ecf20Sopenharmony_ci * If e1000_update_eeprom_checksum is not called after this function, the
40198c2ecf20Sopenharmony_ci * EEPROM will most likely contain an invalid checksum.
40208c2ecf20Sopenharmony_ci */
40218c2ecf20Sopenharmony_cis32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
40228c2ecf20Sopenharmony_ci{
40238c2ecf20Sopenharmony_ci	s32 ret;
40248c2ecf20Sopenharmony_ci
40258c2ecf20Sopenharmony_ci	mutex_lock(&e1000_eeprom_lock);
40268c2ecf20Sopenharmony_ci	ret = e1000_do_write_eeprom(hw, offset, words, data);
40278c2ecf20Sopenharmony_ci	mutex_unlock(&e1000_eeprom_lock);
40288c2ecf20Sopenharmony_ci	return ret;
40298c2ecf20Sopenharmony_ci}
40308c2ecf20Sopenharmony_ci
40318c2ecf20Sopenharmony_cistatic s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
40328c2ecf20Sopenharmony_ci				 u16 *data)
40338c2ecf20Sopenharmony_ci{
40348c2ecf20Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
40358c2ecf20Sopenharmony_ci	s32 status = 0;
40368c2ecf20Sopenharmony_ci
40378c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_ce4100) {
40388c2ecf20Sopenharmony_ci		GBE_CONFIG_FLASH_WRITE(GBE_CONFIG_BASE_VIRT, offset, words,
40398c2ecf20Sopenharmony_ci				       data);
40408c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
40418c2ecf20Sopenharmony_ci	}
40428c2ecf20Sopenharmony_ci
40438c2ecf20Sopenharmony_ci	/* A check for invalid values:  offset too large, too many words, and
40448c2ecf20Sopenharmony_ci	 * not enough words.
40458c2ecf20Sopenharmony_ci	 */
40468c2ecf20Sopenharmony_ci	if ((offset >= eeprom->word_size) ||
40478c2ecf20Sopenharmony_ci	    (words > eeprom->word_size - offset) ||
40488c2ecf20Sopenharmony_ci	    (words == 0)) {
40498c2ecf20Sopenharmony_ci		e_dbg("\"words\" parameter out of bounds\n");
40508c2ecf20Sopenharmony_ci		return -E1000_ERR_EEPROM;
40518c2ecf20Sopenharmony_ci	}
40528c2ecf20Sopenharmony_ci
40538c2ecf20Sopenharmony_ci	/* Prepare the EEPROM for writing  */
40548c2ecf20Sopenharmony_ci	if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
40558c2ecf20Sopenharmony_ci		return -E1000_ERR_EEPROM;
40568c2ecf20Sopenharmony_ci
40578c2ecf20Sopenharmony_ci	if (eeprom->type == e1000_eeprom_microwire) {
40588c2ecf20Sopenharmony_ci		status = e1000_write_eeprom_microwire(hw, offset, words, data);
40598c2ecf20Sopenharmony_ci	} else {
40608c2ecf20Sopenharmony_ci		status = e1000_write_eeprom_spi(hw, offset, words, data);
40618c2ecf20Sopenharmony_ci		msleep(10);
40628c2ecf20Sopenharmony_ci	}
40638c2ecf20Sopenharmony_ci
40648c2ecf20Sopenharmony_ci	/* Done with writing */
40658c2ecf20Sopenharmony_ci	e1000_release_eeprom(hw);
40668c2ecf20Sopenharmony_ci
40678c2ecf20Sopenharmony_ci	return status;
40688c2ecf20Sopenharmony_ci}
40698c2ecf20Sopenharmony_ci
40708c2ecf20Sopenharmony_ci/**
40718c2ecf20Sopenharmony_ci * e1000_write_eeprom_spi - Writes a 16 bit word to a given offset in an SPI EEPROM.
40728c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
40738c2ecf20Sopenharmony_ci * @offset: offset within the EEPROM to be written to
40748c2ecf20Sopenharmony_ci * @words: number of words to write
40758c2ecf20Sopenharmony_ci * @data: pointer to array of 8 bit words to be written to the EEPROM
40768c2ecf20Sopenharmony_ci */
40778c2ecf20Sopenharmony_cistatic s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words,
40788c2ecf20Sopenharmony_ci				  u16 *data)
40798c2ecf20Sopenharmony_ci{
40808c2ecf20Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
40818c2ecf20Sopenharmony_ci	u16 widx = 0;
40828c2ecf20Sopenharmony_ci
40838c2ecf20Sopenharmony_ci	while (widx < words) {
40848c2ecf20Sopenharmony_ci		u8 write_opcode = EEPROM_WRITE_OPCODE_SPI;
40858c2ecf20Sopenharmony_ci
40868c2ecf20Sopenharmony_ci		if (e1000_spi_eeprom_ready(hw))
40878c2ecf20Sopenharmony_ci			return -E1000_ERR_EEPROM;
40888c2ecf20Sopenharmony_ci
40898c2ecf20Sopenharmony_ci		e1000_standby_eeprom(hw);
40908c2ecf20Sopenharmony_ci		cond_resched();
40918c2ecf20Sopenharmony_ci
40928c2ecf20Sopenharmony_ci		/*  Send the WRITE ENABLE command (8 bit opcode )  */
40938c2ecf20Sopenharmony_ci		e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI,
40948c2ecf20Sopenharmony_ci					eeprom->opcode_bits);
40958c2ecf20Sopenharmony_ci
40968c2ecf20Sopenharmony_ci		e1000_standby_eeprom(hw);
40978c2ecf20Sopenharmony_ci
40988c2ecf20Sopenharmony_ci		/* Some SPI eeproms use the 8th address bit embedded in the
40998c2ecf20Sopenharmony_ci		 * opcode
41008c2ecf20Sopenharmony_ci		 */
41018c2ecf20Sopenharmony_ci		if ((eeprom->address_bits == 8) && (offset >= 128))
41028c2ecf20Sopenharmony_ci			write_opcode |= EEPROM_A8_OPCODE_SPI;
41038c2ecf20Sopenharmony_ci
41048c2ecf20Sopenharmony_ci		/* Send the Write command (8-bit opcode + addr) */
41058c2ecf20Sopenharmony_ci		e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits);
41068c2ecf20Sopenharmony_ci
41078c2ecf20Sopenharmony_ci		e1000_shift_out_ee_bits(hw, (u16)((offset + widx) * 2),
41088c2ecf20Sopenharmony_ci					eeprom->address_bits);
41098c2ecf20Sopenharmony_ci
41108c2ecf20Sopenharmony_ci		/* Send the data */
41118c2ecf20Sopenharmony_ci
41128c2ecf20Sopenharmony_ci		/* Loop to allow for up to whole page write (32 bytes) of
41138c2ecf20Sopenharmony_ci		 * eeprom
41148c2ecf20Sopenharmony_ci		 */
41158c2ecf20Sopenharmony_ci		while (widx < words) {
41168c2ecf20Sopenharmony_ci			u16 word_out = data[widx];
41178c2ecf20Sopenharmony_ci
41188c2ecf20Sopenharmony_ci			word_out = (word_out >> 8) | (word_out << 8);
41198c2ecf20Sopenharmony_ci			e1000_shift_out_ee_bits(hw, word_out, 16);
41208c2ecf20Sopenharmony_ci			widx++;
41218c2ecf20Sopenharmony_ci
41228c2ecf20Sopenharmony_ci			/* Some larger eeprom sizes are capable of a 32-byte
41238c2ecf20Sopenharmony_ci			 * PAGE WRITE operation, while the smaller eeproms are
41248c2ecf20Sopenharmony_ci			 * capable of an 8-byte PAGE WRITE operation.  Break the
41258c2ecf20Sopenharmony_ci			 * inner loop to pass new address
41268c2ecf20Sopenharmony_ci			 */
41278c2ecf20Sopenharmony_ci			if ((((offset + widx) * 2) % eeprom->page_size) == 0) {
41288c2ecf20Sopenharmony_ci				e1000_standby_eeprom(hw);
41298c2ecf20Sopenharmony_ci				break;
41308c2ecf20Sopenharmony_ci			}
41318c2ecf20Sopenharmony_ci		}
41328c2ecf20Sopenharmony_ci	}
41338c2ecf20Sopenharmony_ci
41348c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
41358c2ecf20Sopenharmony_ci}
41368c2ecf20Sopenharmony_ci
41378c2ecf20Sopenharmony_ci/**
41388c2ecf20Sopenharmony_ci * e1000_write_eeprom_microwire - Writes a 16 bit word to a given offset in a Microwire EEPROM.
41398c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
41408c2ecf20Sopenharmony_ci * @offset: offset within the EEPROM to be written to
41418c2ecf20Sopenharmony_ci * @words: number of words to write
41428c2ecf20Sopenharmony_ci * @data: pointer to array of 8 bit words to be written to the EEPROM
41438c2ecf20Sopenharmony_ci */
41448c2ecf20Sopenharmony_cistatic s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
41458c2ecf20Sopenharmony_ci					u16 words, u16 *data)
41468c2ecf20Sopenharmony_ci{
41478c2ecf20Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
41488c2ecf20Sopenharmony_ci	u32 eecd;
41498c2ecf20Sopenharmony_ci	u16 words_written = 0;
41508c2ecf20Sopenharmony_ci	u16 i = 0;
41518c2ecf20Sopenharmony_ci
41528c2ecf20Sopenharmony_ci	/* Send the write enable command to the EEPROM (3-bit opcode plus
41538c2ecf20Sopenharmony_ci	 * 6/8-bit dummy address beginning with 11).  It's less work to include
41548c2ecf20Sopenharmony_ci	 * the 11 of the dummy address as part of the opcode than it is to shift
41558c2ecf20Sopenharmony_ci	 * it over the correct number of bits for the address.  This puts the
41568c2ecf20Sopenharmony_ci	 * EEPROM into write/erase mode.
41578c2ecf20Sopenharmony_ci	 */
41588c2ecf20Sopenharmony_ci	e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE,
41598c2ecf20Sopenharmony_ci				(u16)(eeprom->opcode_bits + 2));
41608c2ecf20Sopenharmony_ci
41618c2ecf20Sopenharmony_ci	e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
41628c2ecf20Sopenharmony_ci
41638c2ecf20Sopenharmony_ci	/* Prepare the EEPROM */
41648c2ecf20Sopenharmony_ci	e1000_standby_eeprom(hw);
41658c2ecf20Sopenharmony_ci
41668c2ecf20Sopenharmony_ci	while (words_written < words) {
41678c2ecf20Sopenharmony_ci		/* Send the Write command (3-bit opcode + addr) */
41688c2ecf20Sopenharmony_ci		e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE,
41698c2ecf20Sopenharmony_ci					eeprom->opcode_bits);
41708c2ecf20Sopenharmony_ci
41718c2ecf20Sopenharmony_ci		e1000_shift_out_ee_bits(hw, (u16)(offset + words_written),
41728c2ecf20Sopenharmony_ci					eeprom->address_bits);
41738c2ecf20Sopenharmony_ci
41748c2ecf20Sopenharmony_ci		/* Send the data */
41758c2ecf20Sopenharmony_ci		e1000_shift_out_ee_bits(hw, data[words_written], 16);
41768c2ecf20Sopenharmony_ci
41778c2ecf20Sopenharmony_ci		/* Toggle the CS line.  This in effect tells the EEPROM to
41788c2ecf20Sopenharmony_ci		 * execute the previous command.
41798c2ecf20Sopenharmony_ci		 */
41808c2ecf20Sopenharmony_ci		e1000_standby_eeprom(hw);
41818c2ecf20Sopenharmony_ci
41828c2ecf20Sopenharmony_ci		/* Read DO repeatedly until it is high (equal to '1').  The
41838c2ecf20Sopenharmony_ci		 * EEPROM will signal that the command has been completed by
41848c2ecf20Sopenharmony_ci		 * raising the DO signal. If DO does not go high in 10
41858c2ecf20Sopenharmony_ci		 * milliseconds, then error out.
41868c2ecf20Sopenharmony_ci		 */
41878c2ecf20Sopenharmony_ci		for (i = 0; i < 200; i++) {
41888c2ecf20Sopenharmony_ci			eecd = er32(EECD);
41898c2ecf20Sopenharmony_ci			if (eecd & E1000_EECD_DO)
41908c2ecf20Sopenharmony_ci				break;
41918c2ecf20Sopenharmony_ci			udelay(50);
41928c2ecf20Sopenharmony_ci		}
41938c2ecf20Sopenharmony_ci		if (i == 200) {
41948c2ecf20Sopenharmony_ci			e_dbg("EEPROM Write did not complete\n");
41958c2ecf20Sopenharmony_ci			return -E1000_ERR_EEPROM;
41968c2ecf20Sopenharmony_ci		}
41978c2ecf20Sopenharmony_ci
41988c2ecf20Sopenharmony_ci		/* Recover from write */
41998c2ecf20Sopenharmony_ci		e1000_standby_eeprom(hw);
42008c2ecf20Sopenharmony_ci		cond_resched();
42018c2ecf20Sopenharmony_ci
42028c2ecf20Sopenharmony_ci		words_written++;
42038c2ecf20Sopenharmony_ci	}
42048c2ecf20Sopenharmony_ci
42058c2ecf20Sopenharmony_ci	/* Send the write disable command to the EEPROM (3-bit opcode plus
42068c2ecf20Sopenharmony_ci	 * 6/8-bit dummy address beginning with 10).  It's less work to include
42078c2ecf20Sopenharmony_ci	 * the 10 of the dummy address as part of the opcode than it is to shift
42088c2ecf20Sopenharmony_ci	 * it over the correct number of bits for the address.  This takes the
42098c2ecf20Sopenharmony_ci	 * EEPROM out of write/erase mode.
42108c2ecf20Sopenharmony_ci	 */
42118c2ecf20Sopenharmony_ci	e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE,
42128c2ecf20Sopenharmony_ci				(u16)(eeprom->opcode_bits + 2));
42138c2ecf20Sopenharmony_ci
42148c2ecf20Sopenharmony_ci	e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
42158c2ecf20Sopenharmony_ci
42168c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
42178c2ecf20Sopenharmony_ci}
42188c2ecf20Sopenharmony_ci
42198c2ecf20Sopenharmony_ci/**
42208c2ecf20Sopenharmony_ci * e1000_read_mac_addr - read the adapters MAC from eeprom
42218c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
42228c2ecf20Sopenharmony_ci *
42238c2ecf20Sopenharmony_ci * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
42248c2ecf20Sopenharmony_ci * second function of dual function devices
42258c2ecf20Sopenharmony_ci */
42268c2ecf20Sopenharmony_cis32 e1000_read_mac_addr(struct e1000_hw *hw)
42278c2ecf20Sopenharmony_ci{
42288c2ecf20Sopenharmony_ci	u16 offset;
42298c2ecf20Sopenharmony_ci	u16 eeprom_data, i;
42308c2ecf20Sopenharmony_ci
42318c2ecf20Sopenharmony_ci	for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
42328c2ecf20Sopenharmony_ci		offset = i >> 1;
42338c2ecf20Sopenharmony_ci		if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
42348c2ecf20Sopenharmony_ci			e_dbg("EEPROM Read Error\n");
42358c2ecf20Sopenharmony_ci			return -E1000_ERR_EEPROM;
42368c2ecf20Sopenharmony_ci		}
42378c2ecf20Sopenharmony_ci		hw->perm_mac_addr[i] = (u8)(eeprom_data & 0x00FF);
42388c2ecf20Sopenharmony_ci		hw->perm_mac_addr[i + 1] = (u8)(eeprom_data >> 8);
42398c2ecf20Sopenharmony_ci	}
42408c2ecf20Sopenharmony_ci
42418c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
42428c2ecf20Sopenharmony_ci	default:
42438c2ecf20Sopenharmony_ci		break;
42448c2ecf20Sopenharmony_ci	case e1000_82546:
42458c2ecf20Sopenharmony_ci	case e1000_82546_rev_3:
42468c2ecf20Sopenharmony_ci		if (er32(STATUS) & E1000_STATUS_FUNC_1)
42478c2ecf20Sopenharmony_ci			hw->perm_mac_addr[5] ^= 0x01;
42488c2ecf20Sopenharmony_ci		break;
42498c2ecf20Sopenharmony_ci	}
42508c2ecf20Sopenharmony_ci
42518c2ecf20Sopenharmony_ci	for (i = 0; i < NODE_ADDRESS_SIZE; i++)
42528c2ecf20Sopenharmony_ci		hw->mac_addr[i] = hw->perm_mac_addr[i];
42538c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
42548c2ecf20Sopenharmony_ci}
42558c2ecf20Sopenharmony_ci
42568c2ecf20Sopenharmony_ci/**
42578c2ecf20Sopenharmony_ci * e1000_init_rx_addrs - Initializes receive address filters.
42588c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
42598c2ecf20Sopenharmony_ci *
42608c2ecf20Sopenharmony_ci * Places the MAC address in receive address register 0 and clears the rest
42618c2ecf20Sopenharmony_ci * of the receive address registers. Clears the multicast table. Assumes
42628c2ecf20Sopenharmony_ci * the receiver is in reset when the routine is called.
42638c2ecf20Sopenharmony_ci */
42648c2ecf20Sopenharmony_cistatic void e1000_init_rx_addrs(struct e1000_hw *hw)
42658c2ecf20Sopenharmony_ci{
42668c2ecf20Sopenharmony_ci	u32 i;
42678c2ecf20Sopenharmony_ci	u32 rar_num;
42688c2ecf20Sopenharmony_ci
42698c2ecf20Sopenharmony_ci	/* Setup the receive address. */
42708c2ecf20Sopenharmony_ci	e_dbg("Programming MAC Address into RAR[0]\n");
42718c2ecf20Sopenharmony_ci
42728c2ecf20Sopenharmony_ci	e1000_rar_set(hw, hw->mac_addr, 0);
42738c2ecf20Sopenharmony_ci
42748c2ecf20Sopenharmony_ci	rar_num = E1000_RAR_ENTRIES;
42758c2ecf20Sopenharmony_ci
42768c2ecf20Sopenharmony_ci	/* Zero out the following 14 receive addresses. RAR[15] is for
42778c2ecf20Sopenharmony_ci	 * manageability
42788c2ecf20Sopenharmony_ci	 */
42798c2ecf20Sopenharmony_ci	e_dbg("Clearing RAR[1-14]\n");
42808c2ecf20Sopenharmony_ci	for (i = 1; i < rar_num; i++) {
42818c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
42828c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
42838c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
42848c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
42858c2ecf20Sopenharmony_ci	}
42868c2ecf20Sopenharmony_ci}
42878c2ecf20Sopenharmony_ci
42888c2ecf20Sopenharmony_ci/**
42898c2ecf20Sopenharmony_ci * e1000_hash_mc_addr - Hashes an address to determine its location in the multicast table
42908c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
42918c2ecf20Sopenharmony_ci * @mc_addr: the multicast address to hash
42928c2ecf20Sopenharmony_ci */
42938c2ecf20Sopenharmony_ciu32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
42948c2ecf20Sopenharmony_ci{
42958c2ecf20Sopenharmony_ci	u32 hash_value = 0;
42968c2ecf20Sopenharmony_ci
42978c2ecf20Sopenharmony_ci	/* The portion of the address that is used for the hash table is
42988c2ecf20Sopenharmony_ci	 * determined by the mc_filter_type setting.
42998c2ecf20Sopenharmony_ci	 */
43008c2ecf20Sopenharmony_ci	switch (hw->mc_filter_type) {
43018c2ecf20Sopenharmony_ci		/* [0] [1] [2] [3] [4] [5]
43028c2ecf20Sopenharmony_ci		 * 01  AA  00  12  34  56
43038c2ecf20Sopenharmony_ci		 * LSB                 MSB
43048c2ecf20Sopenharmony_ci		 */
43058c2ecf20Sopenharmony_ci	case 0:
43068c2ecf20Sopenharmony_ci		/* [47:36] i.e. 0x563 for above example address */
43078c2ecf20Sopenharmony_ci		hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
43088c2ecf20Sopenharmony_ci		break;
43098c2ecf20Sopenharmony_ci	case 1:
43108c2ecf20Sopenharmony_ci		/* [46:35] i.e. 0xAC6 for above example address */
43118c2ecf20Sopenharmony_ci		hash_value = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
43128c2ecf20Sopenharmony_ci		break;
43138c2ecf20Sopenharmony_ci	case 2:
43148c2ecf20Sopenharmony_ci		/* [45:34] i.e. 0x5D8 for above example address */
43158c2ecf20Sopenharmony_ci		hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
43168c2ecf20Sopenharmony_ci		break;
43178c2ecf20Sopenharmony_ci	case 3:
43188c2ecf20Sopenharmony_ci		/* [43:32] i.e. 0x634 for above example address */
43198c2ecf20Sopenharmony_ci		hash_value = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
43208c2ecf20Sopenharmony_ci		break;
43218c2ecf20Sopenharmony_ci	}
43228c2ecf20Sopenharmony_ci
43238c2ecf20Sopenharmony_ci	hash_value &= 0xFFF;
43248c2ecf20Sopenharmony_ci	return hash_value;
43258c2ecf20Sopenharmony_ci}
43268c2ecf20Sopenharmony_ci
43278c2ecf20Sopenharmony_ci/**
43288c2ecf20Sopenharmony_ci * e1000_rar_set - Puts an ethernet address into a receive address register.
43298c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
43308c2ecf20Sopenharmony_ci * @addr: Address to put into receive address register
43318c2ecf20Sopenharmony_ci * @index: Receive address register to write
43328c2ecf20Sopenharmony_ci */
43338c2ecf20Sopenharmony_civoid e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
43348c2ecf20Sopenharmony_ci{
43358c2ecf20Sopenharmony_ci	u32 rar_low, rar_high;
43368c2ecf20Sopenharmony_ci
43378c2ecf20Sopenharmony_ci	/* HW expects these in little endian so we reverse the byte order
43388c2ecf20Sopenharmony_ci	 * from network order (big endian) to little endian
43398c2ecf20Sopenharmony_ci	 */
43408c2ecf20Sopenharmony_ci	rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
43418c2ecf20Sopenharmony_ci		   ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
43428c2ecf20Sopenharmony_ci	rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
43438c2ecf20Sopenharmony_ci
43448c2ecf20Sopenharmony_ci	/* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
43458c2ecf20Sopenharmony_ci	 * unit hang.
43468c2ecf20Sopenharmony_ci	 *
43478c2ecf20Sopenharmony_ci	 * Description:
43488c2ecf20Sopenharmony_ci	 * If there are any Rx frames queued up or otherwise present in the HW
43498c2ecf20Sopenharmony_ci	 * before RSS is enabled, and then we enable RSS, the HW Rx unit will
43508c2ecf20Sopenharmony_ci	 * hang.  To work around this issue, we have to disable receives and
43518c2ecf20Sopenharmony_ci	 * flush out all Rx frames before we enable RSS. To do so, we modify we
43528c2ecf20Sopenharmony_ci	 * redirect all Rx traffic to manageability and then reset the HW.
43538c2ecf20Sopenharmony_ci	 * This flushes away Rx frames, and (since the redirections to
43548c2ecf20Sopenharmony_ci	 * manageability persists across resets) keeps new ones from coming in
43558c2ecf20Sopenharmony_ci	 * while we work.  Then, we clear the Address Valid AV bit for all MAC
43568c2ecf20Sopenharmony_ci	 * addresses and undo the re-direction to manageability.
43578c2ecf20Sopenharmony_ci	 * Now, frames are coming in again, but the MAC won't accept them, so
43588c2ecf20Sopenharmony_ci	 * far so good.  We now proceed to initialize RSS (if necessary) and
43598c2ecf20Sopenharmony_ci	 * configure the Rx unit.  Last, we re-enable the AV bits and continue
43608c2ecf20Sopenharmony_ci	 * on our merry way.
43618c2ecf20Sopenharmony_ci	 */
43628c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
43638c2ecf20Sopenharmony_ci	default:
43648c2ecf20Sopenharmony_ci		/* Indicate to hardware the Address is Valid. */
43658c2ecf20Sopenharmony_ci		rar_high |= E1000_RAH_AV;
43668c2ecf20Sopenharmony_ci		break;
43678c2ecf20Sopenharmony_ci	}
43688c2ecf20Sopenharmony_ci
43698c2ecf20Sopenharmony_ci	E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
43708c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
43718c2ecf20Sopenharmony_ci	E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
43728c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
43738c2ecf20Sopenharmony_ci}
43748c2ecf20Sopenharmony_ci
43758c2ecf20Sopenharmony_ci/**
43768c2ecf20Sopenharmony_ci * e1000_write_vfta - Writes a value to the specified offset in the VLAN filter table.
43778c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
43788c2ecf20Sopenharmony_ci * @offset: Offset in VLAN filer table to write
43798c2ecf20Sopenharmony_ci * @value: Value to write into VLAN filter table
43808c2ecf20Sopenharmony_ci */
43818c2ecf20Sopenharmony_civoid e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
43828c2ecf20Sopenharmony_ci{
43838c2ecf20Sopenharmony_ci	u32 temp;
43848c2ecf20Sopenharmony_ci
43858c2ecf20Sopenharmony_ci	if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
43868c2ecf20Sopenharmony_ci		temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
43878c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
43888c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
43898c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
43908c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
43918c2ecf20Sopenharmony_ci	} else {
43928c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
43938c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
43948c2ecf20Sopenharmony_ci	}
43958c2ecf20Sopenharmony_ci}
43968c2ecf20Sopenharmony_ci
43978c2ecf20Sopenharmony_ci/**
43988c2ecf20Sopenharmony_ci * e1000_clear_vfta - Clears the VLAN filer table
43998c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
44008c2ecf20Sopenharmony_ci */
44018c2ecf20Sopenharmony_cistatic void e1000_clear_vfta(struct e1000_hw *hw)
44028c2ecf20Sopenharmony_ci{
44038c2ecf20Sopenharmony_ci	u32 offset;
44048c2ecf20Sopenharmony_ci
44058c2ecf20Sopenharmony_ci	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
44068c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
44078c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
44088c2ecf20Sopenharmony_ci	}
44098c2ecf20Sopenharmony_ci}
44108c2ecf20Sopenharmony_ci
44118c2ecf20Sopenharmony_cistatic s32 e1000_id_led_init(struct e1000_hw *hw)
44128c2ecf20Sopenharmony_ci{
44138c2ecf20Sopenharmony_ci	u32 ledctl;
44148c2ecf20Sopenharmony_ci	const u32 ledctl_mask = 0x000000FF;
44158c2ecf20Sopenharmony_ci	const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
44168c2ecf20Sopenharmony_ci	const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
44178c2ecf20Sopenharmony_ci	u16 eeprom_data, i, temp;
44188c2ecf20Sopenharmony_ci	const u16 led_mask = 0x0F;
44198c2ecf20Sopenharmony_ci
44208c2ecf20Sopenharmony_ci	if (hw->mac_type < e1000_82540) {
44218c2ecf20Sopenharmony_ci		/* Nothing to do */
44228c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
44238c2ecf20Sopenharmony_ci	}
44248c2ecf20Sopenharmony_ci
44258c2ecf20Sopenharmony_ci	ledctl = er32(LEDCTL);
44268c2ecf20Sopenharmony_ci	hw->ledctl_default = ledctl;
44278c2ecf20Sopenharmony_ci	hw->ledctl_mode1 = hw->ledctl_default;
44288c2ecf20Sopenharmony_ci	hw->ledctl_mode2 = hw->ledctl_default;
44298c2ecf20Sopenharmony_ci
44308c2ecf20Sopenharmony_ci	if (e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) {
44318c2ecf20Sopenharmony_ci		e_dbg("EEPROM Read Error\n");
44328c2ecf20Sopenharmony_ci		return -E1000_ERR_EEPROM;
44338c2ecf20Sopenharmony_ci	}
44348c2ecf20Sopenharmony_ci
44358c2ecf20Sopenharmony_ci	if ((eeprom_data == ID_LED_RESERVED_0000) ||
44368c2ecf20Sopenharmony_ci	    (eeprom_data == ID_LED_RESERVED_FFFF)) {
44378c2ecf20Sopenharmony_ci		eeprom_data = ID_LED_DEFAULT;
44388c2ecf20Sopenharmony_ci	}
44398c2ecf20Sopenharmony_ci
44408c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
44418c2ecf20Sopenharmony_ci		temp = (eeprom_data >> (i << 2)) & led_mask;
44428c2ecf20Sopenharmony_ci		switch (temp) {
44438c2ecf20Sopenharmony_ci		case ID_LED_ON1_DEF2:
44448c2ecf20Sopenharmony_ci		case ID_LED_ON1_ON2:
44458c2ecf20Sopenharmony_ci		case ID_LED_ON1_OFF2:
44468c2ecf20Sopenharmony_ci			hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
44478c2ecf20Sopenharmony_ci			hw->ledctl_mode1 |= ledctl_on << (i << 3);
44488c2ecf20Sopenharmony_ci			break;
44498c2ecf20Sopenharmony_ci		case ID_LED_OFF1_DEF2:
44508c2ecf20Sopenharmony_ci		case ID_LED_OFF1_ON2:
44518c2ecf20Sopenharmony_ci		case ID_LED_OFF1_OFF2:
44528c2ecf20Sopenharmony_ci			hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
44538c2ecf20Sopenharmony_ci			hw->ledctl_mode1 |= ledctl_off << (i << 3);
44548c2ecf20Sopenharmony_ci			break;
44558c2ecf20Sopenharmony_ci		default:
44568c2ecf20Sopenharmony_ci			/* Do nothing */
44578c2ecf20Sopenharmony_ci			break;
44588c2ecf20Sopenharmony_ci		}
44598c2ecf20Sopenharmony_ci		switch (temp) {
44608c2ecf20Sopenharmony_ci		case ID_LED_DEF1_ON2:
44618c2ecf20Sopenharmony_ci		case ID_LED_ON1_ON2:
44628c2ecf20Sopenharmony_ci		case ID_LED_OFF1_ON2:
44638c2ecf20Sopenharmony_ci			hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
44648c2ecf20Sopenharmony_ci			hw->ledctl_mode2 |= ledctl_on << (i << 3);
44658c2ecf20Sopenharmony_ci			break;
44668c2ecf20Sopenharmony_ci		case ID_LED_DEF1_OFF2:
44678c2ecf20Sopenharmony_ci		case ID_LED_ON1_OFF2:
44688c2ecf20Sopenharmony_ci		case ID_LED_OFF1_OFF2:
44698c2ecf20Sopenharmony_ci			hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
44708c2ecf20Sopenharmony_ci			hw->ledctl_mode2 |= ledctl_off << (i << 3);
44718c2ecf20Sopenharmony_ci			break;
44728c2ecf20Sopenharmony_ci		default:
44738c2ecf20Sopenharmony_ci			/* Do nothing */
44748c2ecf20Sopenharmony_ci			break;
44758c2ecf20Sopenharmony_ci		}
44768c2ecf20Sopenharmony_ci	}
44778c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
44788c2ecf20Sopenharmony_ci}
44798c2ecf20Sopenharmony_ci
44808c2ecf20Sopenharmony_ci/**
44818c2ecf20Sopenharmony_ci * e1000_setup_led
44828c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
44838c2ecf20Sopenharmony_ci *
44848c2ecf20Sopenharmony_ci * Prepares SW controlable LED for use and saves the current state of the LED.
44858c2ecf20Sopenharmony_ci */
44868c2ecf20Sopenharmony_cis32 e1000_setup_led(struct e1000_hw *hw)
44878c2ecf20Sopenharmony_ci{
44888c2ecf20Sopenharmony_ci	u32 ledctl;
44898c2ecf20Sopenharmony_ci	s32 ret_val = E1000_SUCCESS;
44908c2ecf20Sopenharmony_ci
44918c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
44928c2ecf20Sopenharmony_ci	case e1000_82542_rev2_0:
44938c2ecf20Sopenharmony_ci	case e1000_82542_rev2_1:
44948c2ecf20Sopenharmony_ci	case e1000_82543:
44958c2ecf20Sopenharmony_ci	case e1000_82544:
44968c2ecf20Sopenharmony_ci		/* No setup necessary */
44978c2ecf20Sopenharmony_ci		break;
44988c2ecf20Sopenharmony_ci	case e1000_82541:
44998c2ecf20Sopenharmony_ci	case e1000_82547:
45008c2ecf20Sopenharmony_ci	case e1000_82541_rev_2:
45018c2ecf20Sopenharmony_ci	case e1000_82547_rev_2:
45028c2ecf20Sopenharmony_ci		/* Turn off PHY Smart Power Down (if enabled) */
45038c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO,
45048c2ecf20Sopenharmony_ci					     &hw->phy_spd_default);
45058c2ecf20Sopenharmony_ci		if (ret_val)
45068c2ecf20Sopenharmony_ci			return ret_val;
45078c2ecf20Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
45088c2ecf20Sopenharmony_ci					      (u16)(hw->phy_spd_default &
45098c2ecf20Sopenharmony_ci						     ~IGP01E1000_GMII_SPD));
45108c2ecf20Sopenharmony_ci		if (ret_val)
45118c2ecf20Sopenharmony_ci			return ret_val;
45128c2ecf20Sopenharmony_ci		fallthrough;
45138c2ecf20Sopenharmony_ci	default:
45148c2ecf20Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
45158c2ecf20Sopenharmony_ci			ledctl = er32(LEDCTL);
45168c2ecf20Sopenharmony_ci			/* Save current LEDCTL settings */
45178c2ecf20Sopenharmony_ci			hw->ledctl_default = ledctl;
45188c2ecf20Sopenharmony_ci			/* Turn off LED0 */
45198c2ecf20Sopenharmony_ci			ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
45208c2ecf20Sopenharmony_ci				    E1000_LEDCTL_LED0_BLINK |
45218c2ecf20Sopenharmony_ci				    E1000_LEDCTL_LED0_MODE_MASK);
45228c2ecf20Sopenharmony_ci			ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
45238c2ecf20Sopenharmony_ci				   E1000_LEDCTL_LED0_MODE_SHIFT);
45248c2ecf20Sopenharmony_ci			ew32(LEDCTL, ledctl);
45258c2ecf20Sopenharmony_ci		} else if (hw->media_type == e1000_media_type_copper)
45268c2ecf20Sopenharmony_ci			ew32(LEDCTL, hw->ledctl_mode1);
45278c2ecf20Sopenharmony_ci		break;
45288c2ecf20Sopenharmony_ci	}
45298c2ecf20Sopenharmony_ci
45308c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
45318c2ecf20Sopenharmony_ci}
45328c2ecf20Sopenharmony_ci
45338c2ecf20Sopenharmony_ci/**
45348c2ecf20Sopenharmony_ci * e1000_cleanup_led - Restores the saved state of the SW controlable LED.
45358c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
45368c2ecf20Sopenharmony_ci */
45378c2ecf20Sopenharmony_cis32 e1000_cleanup_led(struct e1000_hw *hw)
45388c2ecf20Sopenharmony_ci{
45398c2ecf20Sopenharmony_ci	s32 ret_val = E1000_SUCCESS;
45408c2ecf20Sopenharmony_ci
45418c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
45428c2ecf20Sopenharmony_ci	case e1000_82542_rev2_0:
45438c2ecf20Sopenharmony_ci	case e1000_82542_rev2_1:
45448c2ecf20Sopenharmony_ci	case e1000_82543:
45458c2ecf20Sopenharmony_ci	case e1000_82544:
45468c2ecf20Sopenharmony_ci		/* No cleanup necessary */
45478c2ecf20Sopenharmony_ci		break;
45488c2ecf20Sopenharmony_ci	case e1000_82541:
45498c2ecf20Sopenharmony_ci	case e1000_82547:
45508c2ecf20Sopenharmony_ci	case e1000_82541_rev_2:
45518c2ecf20Sopenharmony_ci	case e1000_82547_rev_2:
45528c2ecf20Sopenharmony_ci		/* Turn on PHY Smart Power Down (if previously enabled) */
45538c2ecf20Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
45548c2ecf20Sopenharmony_ci					      hw->phy_spd_default);
45558c2ecf20Sopenharmony_ci		if (ret_val)
45568c2ecf20Sopenharmony_ci			return ret_val;
45578c2ecf20Sopenharmony_ci		fallthrough;
45588c2ecf20Sopenharmony_ci	default:
45598c2ecf20Sopenharmony_ci		/* Restore LEDCTL settings */
45608c2ecf20Sopenharmony_ci		ew32(LEDCTL, hw->ledctl_default);
45618c2ecf20Sopenharmony_ci		break;
45628c2ecf20Sopenharmony_ci	}
45638c2ecf20Sopenharmony_ci
45648c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
45658c2ecf20Sopenharmony_ci}
45668c2ecf20Sopenharmony_ci
45678c2ecf20Sopenharmony_ci/**
45688c2ecf20Sopenharmony_ci * e1000_led_on - Turns on the software controllable LED
45698c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
45708c2ecf20Sopenharmony_ci */
45718c2ecf20Sopenharmony_cis32 e1000_led_on(struct e1000_hw *hw)
45728c2ecf20Sopenharmony_ci{
45738c2ecf20Sopenharmony_ci	u32 ctrl = er32(CTRL);
45748c2ecf20Sopenharmony_ci
45758c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
45768c2ecf20Sopenharmony_ci	case e1000_82542_rev2_0:
45778c2ecf20Sopenharmony_ci	case e1000_82542_rev2_1:
45788c2ecf20Sopenharmony_ci	case e1000_82543:
45798c2ecf20Sopenharmony_ci		/* Set SW Defineable Pin 0 to turn on the LED */
45808c2ecf20Sopenharmony_ci		ctrl |= E1000_CTRL_SWDPIN0;
45818c2ecf20Sopenharmony_ci		ctrl |= E1000_CTRL_SWDPIO0;
45828c2ecf20Sopenharmony_ci		break;
45838c2ecf20Sopenharmony_ci	case e1000_82544:
45848c2ecf20Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
45858c2ecf20Sopenharmony_ci			/* Set SW Defineable Pin 0 to turn on the LED */
45868c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIN0;
45878c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
45888c2ecf20Sopenharmony_ci		} else {
45898c2ecf20Sopenharmony_ci			/* Clear SW Defineable Pin 0 to turn on the LED */
45908c2ecf20Sopenharmony_ci			ctrl &= ~E1000_CTRL_SWDPIN0;
45918c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
45928c2ecf20Sopenharmony_ci		}
45938c2ecf20Sopenharmony_ci		break;
45948c2ecf20Sopenharmony_ci	default:
45958c2ecf20Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
45968c2ecf20Sopenharmony_ci			/* Clear SW Defineable Pin 0 to turn on the LED */
45978c2ecf20Sopenharmony_ci			ctrl &= ~E1000_CTRL_SWDPIN0;
45988c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
45998c2ecf20Sopenharmony_ci		} else if (hw->media_type == e1000_media_type_copper) {
46008c2ecf20Sopenharmony_ci			ew32(LEDCTL, hw->ledctl_mode2);
46018c2ecf20Sopenharmony_ci			return E1000_SUCCESS;
46028c2ecf20Sopenharmony_ci		}
46038c2ecf20Sopenharmony_ci		break;
46048c2ecf20Sopenharmony_ci	}
46058c2ecf20Sopenharmony_ci
46068c2ecf20Sopenharmony_ci	ew32(CTRL, ctrl);
46078c2ecf20Sopenharmony_ci
46088c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
46098c2ecf20Sopenharmony_ci}
46108c2ecf20Sopenharmony_ci
46118c2ecf20Sopenharmony_ci/**
46128c2ecf20Sopenharmony_ci * e1000_led_off - Turns off the software controllable LED
46138c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
46148c2ecf20Sopenharmony_ci */
46158c2ecf20Sopenharmony_cis32 e1000_led_off(struct e1000_hw *hw)
46168c2ecf20Sopenharmony_ci{
46178c2ecf20Sopenharmony_ci	u32 ctrl = er32(CTRL);
46188c2ecf20Sopenharmony_ci
46198c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
46208c2ecf20Sopenharmony_ci	case e1000_82542_rev2_0:
46218c2ecf20Sopenharmony_ci	case e1000_82542_rev2_1:
46228c2ecf20Sopenharmony_ci	case e1000_82543:
46238c2ecf20Sopenharmony_ci		/* Clear SW Defineable Pin 0 to turn off the LED */
46248c2ecf20Sopenharmony_ci		ctrl &= ~E1000_CTRL_SWDPIN0;
46258c2ecf20Sopenharmony_ci		ctrl |= E1000_CTRL_SWDPIO0;
46268c2ecf20Sopenharmony_ci		break;
46278c2ecf20Sopenharmony_ci	case e1000_82544:
46288c2ecf20Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
46298c2ecf20Sopenharmony_ci			/* Clear SW Defineable Pin 0 to turn off the LED */
46308c2ecf20Sopenharmony_ci			ctrl &= ~E1000_CTRL_SWDPIN0;
46318c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
46328c2ecf20Sopenharmony_ci		} else {
46338c2ecf20Sopenharmony_ci			/* Set SW Defineable Pin 0 to turn off the LED */
46348c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIN0;
46358c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
46368c2ecf20Sopenharmony_ci		}
46378c2ecf20Sopenharmony_ci		break;
46388c2ecf20Sopenharmony_ci	default:
46398c2ecf20Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
46408c2ecf20Sopenharmony_ci			/* Set SW Defineable Pin 0 to turn off the LED */
46418c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIN0;
46428c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
46438c2ecf20Sopenharmony_ci		} else if (hw->media_type == e1000_media_type_copper) {
46448c2ecf20Sopenharmony_ci			ew32(LEDCTL, hw->ledctl_mode1);
46458c2ecf20Sopenharmony_ci			return E1000_SUCCESS;
46468c2ecf20Sopenharmony_ci		}
46478c2ecf20Sopenharmony_ci		break;
46488c2ecf20Sopenharmony_ci	}
46498c2ecf20Sopenharmony_ci
46508c2ecf20Sopenharmony_ci	ew32(CTRL, ctrl);
46518c2ecf20Sopenharmony_ci
46528c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
46538c2ecf20Sopenharmony_ci}
46548c2ecf20Sopenharmony_ci
46558c2ecf20Sopenharmony_ci/**
46568c2ecf20Sopenharmony_ci * e1000_clear_hw_cntrs - Clears all hardware statistics counters.
46578c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
46588c2ecf20Sopenharmony_ci */
46598c2ecf20Sopenharmony_cistatic void e1000_clear_hw_cntrs(struct e1000_hw *hw)
46608c2ecf20Sopenharmony_ci{
46618c2ecf20Sopenharmony_ci	er32(CRCERRS);
46628c2ecf20Sopenharmony_ci	er32(SYMERRS);
46638c2ecf20Sopenharmony_ci	er32(MPC);
46648c2ecf20Sopenharmony_ci	er32(SCC);
46658c2ecf20Sopenharmony_ci	er32(ECOL);
46668c2ecf20Sopenharmony_ci	er32(MCC);
46678c2ecf20Sopenharmony_ci	er32(LATECOL);
46688c2ecf20Sopenharmony_ci	er32(COLC);
46698c2ecf20Sopenharmony_ci	er32(DC);
46708c2ecf20Sopenharmony_ci	er32(SEC);
46718c2ecf20Sopenharmony_ci	er32(RLEC);
46728c2ecf20Sopenharmony_ci	er32(XONRXC);
46738c2ecf20Sopenharmony_ci	er32(XONTXC);
46748c2ecf20Sopenharmony_ci	er32(XOFFRXC);
46758c2ecf20Sopenharmony_ci	er32(XOFFTXC);
46768c2ecf20Sopenharmony_ci	er32(FCRUC);
46778c2ecf20Sopenharmony_ci
46788c2ecf20Sopenharmony_ci	er32(PRC64);
46798c2ecf20Sopenharmony_ci	er32(PRC127);
46808c2ecf20Sopenharmony_ci	er32(PRC255);
46818c2ecf20Sopenharmony_ci	er32(PRC511);
46828c2ecf20Sopenharmony_ci	er32(PRC1023);
46838c2ecf20Sopenharmony_ci	er32(PRC1522);
46848c2ecf20Sopenharmony_ci
46858c2ecf20Sopenharmony_ci	er32(GPRC);
46868c2ecf20Sopenharmony_ci	er32(BPRC);
46878c2ecf20Sopenharmony_ci	er32(MPRC);
46888c2ecf20Sopenharmony_ci	er32(GPTC);
46898c2ecf20Sopenharmony_ci	er32(GORCL);
46908c2ecf20Sopenharmony_ci	er32(GORCH);
46918c2ecf20Sopenharmony_ci	er32(GOTCL);
46928c2ecf20Sopenharmony_ci	er32(GOTCH);
46938c2ecf20Sopenharmony_ci	er32(RNBC);
46948c2ecf20Sopenharmony_ci	er32(RUC);
46958c2ecf20Sopenharmony_ci	er32(RFC);
46968c2ecf20Sopenharmony_ci	er32(ROC);
46978c2ecf20Sopenharmony_ci	er32(RJC);
46988c2ecf20Sopenharmony_ci	er32(TORL);
46998c2ecf20Sopenharmony_ci	er32(TORH);
47008c2ecf20Sopenharmony_ci	er32(TOTL);
47018c2ecf20Sopenharmony_ci	er32(TOTH);
47028c2ecf20Sopenharmony_ci	er32(TPR);
47038c2ecf20Sopenharmony_ci	er32(TPT);
47048c2ecf20Sopenharmony_ci
47058c2ecf20Sopenharmony_ci	er32(PTC64);
47068c2ecf20Sopenharmony_ci	er32(PTC127);
47078c2ecf20Sopenharmony_ci	er32(PTC255);
47088c2ecf20Sopenharmony_ci	er32(PTC511);
47098c2ecf20Sopenharmony_ci	er32(PTC1023);
47108c2ecf20Sopenharmony_ci	er32(PTC1522);
47118c2ecf20Sopenharmony_ci
47128c2ecf20Sopenharmony_ci	er32(MPTC);
47138c2ecf20Sopenharmony_ci	er32(BPTC);
47148c2ecf20Sopenharmony_ci
47158c2ecf20Sopenharmony_ci	if (hw->mac_type < e1000_82543)
47168c2ecf20Sopenharmony_ci		return;
47178c2ecf20Sopenharmony_ci
47188c2ecf20Sopenharmony_ci	er32(ALGNERRC);
47198c2ecf20Sopenharmony_ci	er32(RXERRC);
47208c2ecf20Sopenharmony_ci	er32(TNCRS);
47218c2ecf20Sopenharmony_ci	er32(CEXTERR);
47228c2ecf20Sopenharmony_ci	er32(TSCTC);
47238c2ecf20Sopenharmony_ci	er32(TSCTFC);
47248c2ecf20Sopenharmony_ci
47258c2ecf20Sopenharmony_ci	if (hw->mac_type <= e1000_82544)
47268c2ecf20Sopenharmony_ci		return;
47278c2ecf20Sopenharmony_ci
47288c2ecf20Sopenharmony_ci	er32(MGTPRC);
47298c2ecf20Sopenharmony_ci	er32(MGTPDC);
47308c2ecf20Sopenharmony_ci	er32(MGTPTC);
47318c2ecf20Sopenharmony_ci}
47328c2ecf20Sopenharmony_ci
47338c2ecf20Sopenharmony_ci/**
47348c2ecf20Sopenharmony_ci * e1000_reset_adaptive - Resets Adaptive IFS to its default state.
47358c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
47368c2ecf20Sopenharmony_ci *
47378c2ecf20Sopenharmony_ci * Call this after e1000_init_hw. You may override the IFS defaults by setting
47388c2ecf20Sopenharmony_ci * hw->ifs_params_forced to true. However, you must initialize hw->
47398c2ecf20Sopenharmony_ci * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
47408c2ecf20Sopenharmony_ci * before calling this function.
47418c2ecf20Sopenharmony_ci */
47428c2ecf20Sopenharmony_civoid e1000_reset_adaptive(struct e1000_hw *hw)
47438c2ecf20Sopenharmony_ci{
47448c2ecf20Sopenharmony_ci	if (hw->adaptive_ifs) {
47458c2ecf20Sopenharmony_ci		if (!hw->ifs_params_forced) {
47468c2ecf20Sopenharmony_ci			hw->current_ifs_val = 0;
47478c2ecf20Sopenharmony_ci			hw->ifs_min_val = IFS_MIN;
47488c2ecf20Sopenharmony_ci			hw->ifs_max_val = IFS_MAX;
47498c2ecf20Sopenharmony_ci			hw->ifs_step_size = IFS_STEP;
47508c2ecf20Sopenharmony_ci			hw->ifs_ratio = IFS_RATIO;
47518c2ecf20Sopenharmony_ci		}
47528c2ecf20Sopenharmony_ci		hw->in_ifs_mode = false;
47538c2ecf20Sopenharmony_ci		ew32(AIT, 0);
47548c2ecf20Sopenharmony_ci	} else {
47558c2ecf20Sopenharmony_ci		e_dbg("Not in Adaptive IFS mode!\n");
47568c2ecf20Sopenharmony_ci	}
47578c2ecf20Sopenharmony_ci}
47588c2ecf20Sopenharmony_ci
47598c2ecf20Sopenharmony_ci/**
47608c2ecf20Sopenharmony_ci * e1000_update_adaptive - update adaptive IFS
47618c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
47628c2ecf20Sopenharmony_ci *
47638c2ecf20Sopenharmony_ci * Called during the callback/watchdog routine to update IFS value based on
47648c2ecf20Sopenharmony_ci * the ratio of transmits to collisions.
47658c2ecf20Sopenharmony_ci */
47668c2ecf20Sopenharmony_civoid e1000_update_adaptive(struct e1000_hw *hw)
47678c2ecf20Sopenharmony_ci{
47688c2ecf20Sopenharmony_ci	if (hw->adaptive_ifs) {
47698c2ecf20Sopenharmony_ci		if ((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) {
47708c2ecf20Sopenharmony_ci			if (hw->tx_packet_delta > MIN_NUM_XMITS) {
47718c2ecf20Sopenharmony_ci				hw->in_ifs_mode = true;
47728c2ecf20Sopenharmony_ci				if (hw->current_ifs_val < hw->ifs_max_val) {
47738c2ecf20Sopenharmony_ci					if (hw->current_ifs_val == 0)
47748c2ecf20Sopenharmony_ci						hw->current_ifs_val =
47758c2ecf20Sopenharmony_ci						    hw->ifs_min_val;
47768c2ecf20Sopenharmony_ci					else
47778c2ecf20Sopenharmony_ci						hw->current_ifs_val +=
47788c2ecf20Sopenharmony_ci						    hw->ifs_step_size;
47798c2ecf20Sopenharmony_ci					ew32(AIT, hw->current_ifs_val);
47808c2ecf20Sopenharmony_ci				}
47818c2ecf20Sopenharmony_ci			}
47828c2ecf20Sopenharmony_ci		} else {
47838c2ecf20Sopenharmony_ci			if (hw->in_ifs_mode &&
47848c2ecf20Sopenharmony_ci			    (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
47858c2ecf20Sopenharmony_ci				hw->current_ifs_val = 0;
47868c2ecf20Sopenharmony_ci				hw->in_ifs_mode = false;
47878c2ecf20Sopenharmony_ci				ew32(AIT, 0);
47888c2ecf20Sopenharmony_ci			}
47898c2ecf20Sopenharmony_ci		}
47908c2ecf20Sopenharmony_ci	} else {
47918c2ecf20Sopenharmony_ci		e_dbg("Not in Adaptive IFS mode!\n");
47928c2ecf20Sopenharmony_ci	}
47938c2ecf20Sopenharmony_ci}
47948c2ecf20Sopenharmony_ci
47958c2ecf20Sopenharmony_ci/**
47968c2ecf20Sopenharmony_ci * e1000_get_bus_info
47978c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
47988c2ecf20Sopenharmony_ci *
47998c2ecf20Sopenharmony_ci * Gets the current PCI bus type, speed, and width of the hardware
48008c2ecf20Sopenharmony_ci */
48018c2ecf20Sopenharmony_civoid e1000_get_bus_info(struct e1000_hw *hw)
48028c2ecf20Sopenharmony_ci{
48038c2ecf20Sopenharmony_ci	u32 status;
48048c2ecf20Sopenharmony_ci
48058c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
48068c2ecf20Sopenharmony_ci	case e1000_82542_rev2_0:
48078c2ecf20Sopenharmony_ci	case e1000_82542_rev2_1:
48088c2ecf20Sopenharmony_ci		hw->bus_type = e1000_bus_type_pci;
48098c2ecf20Sopenharmony_ci		hw->bus_speed = e1000_bus_speed_unknown;
48108c2ecf20Sopenharmony_ci		hw->bus_width = e1000_bus_width_unknown;
48118c2ecf20Sopenharmony_ci		break;
48128c2ecf20Sopenharmony_ci	default:
48138c2ecf20Sopenharmony_ci		status = er32(STATUS);
48148c2ecf20Sopenharmony_ci		hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
48158c2ecf20Sopenharmony_ci		    e1000_bus_type_pcix : e1000_bus_type_pci;
48168c2ecf20Sopenharmony_ci
48178c2ecf20Sopenharmony_ci		if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
48188c2ecf20Sopenharmony_ci			hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
48198c2ecf20Sopenharmony_ci			    e1000_bus_speed_66 : e1000_bus_speed_120;
48208c2ecf20Sopenharmony_ci		} else if (hw->bus_type == e1000_bus_type_pci) {
48218c2ecf20Sopenharmony_ci			hw->bus_speed = (status & E1000_STATUS_PCI66) ?
48228c2ecf20Sopenharmony_ci			    e1000_bus_speed_66 : e1000_bus_speed_33;
48238c2ecf20Sopenharmony_ci		} else {
48248c2ecf20Sopenharmony_ci			switch (status & E1000_STATUS_PCIX_SPEED) {
48258c2ecf20Sopenharmony_ci			case E1000_STATUS_PCIX_SPEED_66:
48268c2ecf20Sopenharmony_ci				hw->bus_speed = e1000_bus_speed_66;
48278c2ecf20Sopenharmony_ci				break;
48288c2ecf20Sopenharmony_ci			case E1000_STATUS_PCIX_SPEED_100:
48298c2ecf20Sopenharmony_ci				hw->bus_speed = e1000_bus_speed_100;
48308c2ecf20Sopenharmony_ci				break;
48318c2ecf20Sopenharmony_ci			case E1000_STATUS_PCIX_SPEED_133:
48328c2ecf20Sopenharmony_ci				hw->bus_speed = e1000_bus_speed_133;
48338c2ecf20Sopenharmony_ci				break;
48348c2ecf20Sopenharmony_ci			default:
48358c2ecf20Sopenharmony_ci				hw->bus_speed = e1000_bus_speed_reserved;
48368c2ecf20Sopenharmony_ci				break;
48378c2ecf20Sopenharmony_ci			}
48388c2ecf20Sopenharmony_ci		}
48398c2ecf20Sopenharmony_ci		hw->bus_width = (status & E1000_STATUS_BUS64) ?
48408c2ecf20Sopenharmony_ci		    e1000_bus_width_64 : e1000_bus_width_32;
48418c2ecf20Sopenharmony_ci		break;
48428c2ecf20Sopenharmony_ci	}
48438c2ecf20Sopenharmony_ci}
48448c2ecf20Sopenharmony_ci
48458c2ecf20Sopenharmony_ci/**
48468c2ecf20Sopenharmony_ci * e1000_write_reg_io
48478c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
48488c2ecf20Sopenharmony_ci * @offset: offset to write to
48498c2ecf20Sopenharmony_ci * @value: value to write
48508c2ecf20Sopenharmony_ci *
48518c2ecf20Sopenharmony_ci * Writes a value to one of the devices registers using port I/O (as opposed to
48528c2ecf20Sopenharmony_ci * memory mapped I/O). Only 82544 and newer devices support port I/O.
48538c2ecf20Sopenharmony_ci */
48548c2ecf20Sopenharmony_cistatic void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value)
48558c2ecf20Sopenharmony_ci{
48568c2ecf20Sopenharmony_ci	unsigned long io_addr = hw->io_base;
48578c2ecf20Sopenharmony_ci	unsigned long io_data = hw->io_base + 4;
48588c2ecf20Sopenharmony_ci
48598c2ecf20Sopenharmony_ci	e1000_io_write(hw, io_addr, offset);
48608c2ecf20Sopenharmony_ci	e1000_io_write(hw, io_data, value);
48618c2ecf20Sopenharmony_ci}
48628c2ecf20Sopenharmony_ci
48638c2ecf20Sopenharmony_ci/**
48648c2ecf20Sopenharmony_ci * e1000_get_cable_length - Estimates the cable length.
48658c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
48668c2ecf20Sopenharmony_ci * @min_length: The estimated minimum length
48678c2ecf20Sopenharmony_ci * @max_length: The estimated maximum length
48688c2ecf20Sopenharmony_ci *
48698c2ecf20Sopenharmony_ci * returns: - E1000_ERR_XXX
48708c2ecf20Sopenharmony_ci *            E1000_SUCCESS
48718c2ecf20Sopenharmony_ci *
48728c2ecf20Sopenharmony_ci * This function always returns a ranged length (minimum & maximum).
48738c2ecf20Sopenharmony_ci * So for M88 phy's, this function interprets the one value returned from the
48748c2ecf20Sopenharmony_ci * register to the minimum and maximum range.
48758c2ecf20Sopenharmony_ci * For IGP phy's, the function calculates the range by the AGC registers.
48768c2ecf20Sopenharmony_ci */
48778c2ecf20Sopenharmony_cistatic s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
48788c2ecf20Sopenharmony_ci				  u16 *max_length)
48798c2ecf20Sopenharmony_ci{
48808c2ecf20Sopenharmony_ci	s32 ret_val;
48818c2ecf20Sopenharmony_ci	u16 agc_value = 0;
48828c2ecf20Sopenharmony_ci	u16 i, phy_data;
48838c2ecf20Sopenharmony_ci	u16 cable_length;
48848c2ecf20Sopenharmony_ci
48858c2ecf20Sopenharmony_ci	*min_length = *max_length = 0;
48868c2ecf20Sopenharmony_ci
48878c2ecf20Sopenharmony_ci	/* Use old method for Phy older than IGP */
48888c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_m88) {
48898c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
48908c2ecf20Sopenharmony_ci					     &phy_data);
48918c2ecf20Sopenharmony_ci		if (ret_val)
48928c2ecf20Sopenharmony_ci			return ret_val;
48938c2ecf20Sopenharmony_ci		cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
48948c2ecf20Sopenharmony_ci		    M88E1000_PSSR_CABLE_LENGTH_SHIFT;
48958c2ecf20Sopenharmony_ci
48968c2ecf20Sopenharmony_ci		/* Convert the enum value to ranged values */
48978c2ecf20Sopenharmony_ci		switch (cable_length) {
48988c2ecf20Sopenharmony_ci		case e1000_cable_length_50:
48998c2ecf20Sopenharmony_ci			*min_length = 0;
49008c2ecf20Sopenharmony_ci			*max_length = e1000_igp_cable_length_50;
49018c2ecf20Sopenharmony_ci			break;
49028c2ecf20Sopenharmony_ci		case e1000_cable_length_50_80:
49038c2ecf20Sopenharmony_ci			*min_length = e1000_igp_cable_length_50;
49048c2ecf20Sopenharmony_ci			*max_length = e1000_igp_cable_length_80;
49058c2ecf20Sopenharmony_ci			break;
49068c2ecf20Sopenharmony_ci		case e1000_cable_length_80_110:
49078c2ecf20Sopenharmony_ci			*min_length = e1000_igp_cable_length_80;
49088c2ecf20Sopenharmony_ci			*max_length = e1000_igp_cable_length_110;
49098c2ecf20Sopenharmony_ci			break;
49108c2ecf20Sopenharmony_ci		case e1000_cable_length_110_140:
49118c2ecf20Sopenharmony_ci			*min_length = e1000_igp_cable_length_110;
49128c2ecf20Sopenharmony_ci			*max_length = e1000_igp_cable_length_140;
49138c2ecf20Sopenharmony_ci			break;
49148c2ecf20Sopenharmony_ci		case e1000_cable_length_140:
49158c2ecf20Sopenharmony_ci			*min_length = e1000_igp_cable_length_140;
49168c2ecf20Sopenharmony_ci			*max_length = e1000_igp_cable_length_170;
49178c2ecf20Sopenharmony_ci			break;
49188c2ecf20Sopenharmony_ci		default:
49198c2ecf20Sopenharmony_ci			return -E1000_ERR_PHY;
49208c2ecf20Sopenharmony_ci		}
49218c2ecf20Sopenharmony_ci	} else if (hw->phy_type == e1000_phy_igp) {	/* For IGP PHY */
49228c2ecf20Sopenharmony_ci		u16 cur_agc_value;
49238c2ecf20Sopenharmony_ci		u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
49248c2ecf20Sopenharmony_ci		static const u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
49258c2ecf20Sopenharmony_ci		       IGP01E1000_PHY_AGC_A,
49268c2ecf20Sopenharmony_ci		       IGP01E1000_PHY_AGC_B,
49278c2ecf20Sopenharmony_ci		       IGP01E1000_PHY_AGC_C,
49288c2ecf20Sopenharmony_ci		       IGP01E1000_PHY_AGC_D
49298c2ecf20Sopenharmony_ci		};
49308c2ecf20Sopenharmony_ci		/* Read the AGC registers for all channels */
49318c2ecf20Sopenharmony_ci		for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
49328c2ecf20Sopenharmony_ci			ret_val =
49338c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
49348c2ecf20Sopenharmony_ci			if (ret_val)
49358c2ecf20Sopenharmony_ci				return ret_val;
49368c2ecf20Sopenharmony_ci
49378c2ecf20Sopenharmony_ci			cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
49388c2ecf20Sopenharmony_ci
49398c2ecf20Sopenharmony_ci			/* Value bound check. */
49408c2ecf20Sopenharmony_ci			if ((cur_agc_value >=
49418c2ecf20Sopenharmony_ci			     IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
49428c2ecf20Sopenharmony_ci			    (cur_agc_value == 0))
49438c2ecf20Sopenharmony_ci				return -E1000_ERR_PHY;
49448c2ecf20Sopenharmony_ci
49458c2ecf20Sopenharmony_ci			agc_value += cur_agc_value;
49468c2ecf20Sopenharmony_ci
49478c2ecf20Sopenharmony_ci			/* Update minimal AGC value. */
49488c2ecf20Sopenharmony_ci			if (min_agc_value > cur_agc_value)
49498c2ecf20Sopenharmony_ci				min_agc_value = cur_agc_value;
49508c2ecf20Sopenharmony_ci		}
49518c2ecf20Sopenharmony_ci
49528c2ecf20Sopenharmony_ci		/* Remove the minimal AGC result for length < 50m */
49538c2ecf20Sopenharmony_ci		if (agc_value <
49548c2ecf20Sopenharmony_ci		    IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) {
49558c2ecf20Sopenharmony_ci			agc_value -= min_agc_value;
49568c2ecf20Sopenharmony_ci
49578c2ecf20Sopenharmony_ci			/* Get the average length of the remaining 3 channels */
49588c2ecf20Sopenharmony_ci			agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
49598c2ecf20Sopenharmony_ci		} else {
49608c2ecf20Sopenharmony_ci			/* Get the average length of all the 4 channels. */
49618c2ecf20Sopenharmony_ci			agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
49628c2ecf20Sopenharmony_ci		}
49638c2ecf20Sopenharmony_ci
49648c2ecf20Sopenharmony_ci		/* Set the range of the calculated length. */
49658c2ecf20Sopenharmony_ci		*min_length = ((e1000_igp_cable_length_table[agc_value] -
49668c2ecf20Sopenharmony_ci				IGP01E1000_AGC_RANGE) > 0) ?
49678c2ecf20Sopenharmony_ci		    (e1000_igp_cable_length_table[agc_value] -
49688c2ecf20Sopenharmony_ci		     IGP01E1000_AGC_RANGE) : 0;
49698c2ecf20Sopenharmony_ci		*max_length = e1000_igp_cable_length_table[agc_value] +
49708c2ecf20Sopenharmony_ci		    IGP01E1000_AGC_RANGE;
49718c2ecf20Sopenharmony_ci	}
49728c2ecf20Sopenharmony_ci
49738c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
49748c2ecf20Sopenharmony_ci}
49758c2ecf20Sopenharmony_ci
49768c2ecf20Sopenharmony_ci/**
49778c2ecf20Sopenharmony_ci * e1000_check_polarity - Check the cable polarity
49788c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
49798c2ecf20Sopenharmony_ci * @polarity: output parameter : 0 - Polarity is not reversed
49808c2ecf20Sopenharmony_ci *                               1 - Polarity is reversed.
49818c2ecf20Sopenharmony_ci *
49828c2ecf20Sopenharmony_ci * returns: - E1000_ERR_XXX
49838c2ecf20Sopenharmony_ci *            E1000_SUCCESS
49848c2ecf20Sopenharmony_ci *
49858c2ecf20Sopenharmony_ci * For phy's older than IGP, this function simply reads the polarity bit in the
49868c2ecf20Sopenharmony_ci * Phy Status register.  For IGP phy's, this bit is valid only if link speed is
49878c2ecf20Sopenharmony_ci * 10 Mbps.  If the link speed is 100 Mbps there is no polarity so this bit will
49888c2ecf20Sopenharmony_ci * return 0.  If the link speed is 1000 Mbps the polarity status is in the
49898c2ecf20Sopenharmony_ci * IGP01E1000_PHY_PCS_INIT_REG.
49908c2ecf20Sopenharmony_ci */
49918c2ecf20Sopenharmony_cistatic s32 e1000_check_polarity(struct e1000_hw *hw,
49928c2ecf20Sopenharmony_ci				e1000_rev_polarity *polarity)
49938c2ecf20Sopenharmony_ci{
49948c2ecf20Sopenharmony_ci	s32 ret_val;
49958c2ecf20Sopenharmony_ci	u16 phy_data;
49968c2ecf20Sopenharmony_ci
49978c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_m88) {
49988c2ecf20Sopenharmony_ci		/* return the Polarity bit in the Status register. */
49998c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
50008c2ecf20Sopenharmony_ci					     &phy_data);
50018c2ecf20Sopenharmony_ci		if (ret_val)
50028c2ecf20Sopenharmony_ci			return ret_val;
50038c2ecf20Sopenharmony_ci		*polarity = ((phy_data & M88E1000_PSSR_REV_POLARITY) >>
50048c2ecf20Sopenharmony_ci			     M88E1000_PSSR_REV_POLARITY_SHIFT) ?
50058c2ecf20Sopenharmony_ci		    e1000_rev_polarity_reversed : e1000_rev_polarity_normal;
50068c2ecf20Sopenharmony_ci
50078c2ecf20Sopenharmony_ci	} else if (hw->phy_type == e1000_phy_igp) {
50088c2ecf20Sopenharmony_ci		/* Read the Status register to check the speed */
50098c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
50108c2ecf20Sopenharmony_ci					     &phy_data);
50118c2ecf20Sopenharmony_ci		if (ret_val)
50128c2ecf20Sopenharmony_ci			return ret_val;
50138c2ecf20Sopenharmony_ci
50148c2ecf20Sopenharmony_ci		/* If speed is 1000 Mbps, must read the
50158c2ecf20Sopenharmony_ci		 * IGP01E1000_PHY_PCS_INIT_REG to find the polarity status
50168c2ecf20Sopenharmony_ci		 */
50178c2ecf20Sopenharmony_ci		if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
50188c2ecf20Sopenharmony_ci		    IGP01E1000_PSSR_SPEED_1000MBPS) {
50198c2ecf20Sopenharmony_ci			/* Read the GIG initialization PCS register (0x00B4) */
50208c2ecf20Sopenharmony_ci			ret_val =
50218c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG,
50228c2ecf20Sopenharmony_ci					       &phy_data);
50238c2ecf20Sopenharmony_ci			if (ret_val)
50248c2ecf20Sopenharmony_ci				return ret_val;
50258c2ecf20Sopenharmony_ci
50268c2ecf20Sopenharmony_ci			/* Check the polarity bits */
50278c2ecf20Sopenharmony_ci			*polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ?
50288c2ecf20Sopenharmony_ci			    e1000_rev_polarity_reversed :
50298c2ecf20Sopenharmony_ci			    e1000_rev_polarity_normal;
50308c2ecf20Sopenharmony_ci		} else {
50318c2ecf20Sopenharmony_ci			/* For 10 Mbps, read the polarity bit in the status
50328c2ecf20Sopenharmony_ci			 * register. (for 100 Mbps this bit is always 0)
50338c2ecf20Sopenharmony_ci			 */
50348c2ecf20Sopenharmony_ci			*polarity =
50358c2ecf20Sopenharmony_ci			    (phy_data & IGP01E1000_PSSR_POLARITY_REVERSED) ?
50368c2ecf20Sopenharmony_ci			    e1000_rev_polarity_reversed :
50378c2ecf20Sopenharmony_ci			    e1000_rev_polarity_normal;
50388c2ecf20Sopenharmony_ci		}
50398c2ecf20Sopenharmony_ci	}
50408c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
50418c2ecf20Sopenharmony_ci}
50428c2ecf20Sopenharmony_ci
50438c2ecf20Sopenharmony_ci/**
50448c2ecf20Sopenharmony_ci * e1000_check_downshift - Check if Downshift occurred
50458c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
50468c2ecf20Sopenharmony_ci *
50478c2ecf20Sopenharmony_ci * returns: - E1000_ERR_XXX
50488c2ecf20Sopenharmony_ci *            E1000_SUCCESS
50498c2ecf20Sopenharmony_ci *
50508c2ecf20Sopenharmony_ci * For phy's older than IGP, this function reads the Downshift bit in the Phy
50518c2ecf20Sopenharmony_ci * Specific Status register.  For IGP phy's, it reads the Downgrade bit in the
50528c2ecf20Sopenharmony_ci * Link Health register.  In IGP this bit is latched high, so the driver must
50538c2ecf20Sopenharmony_ci * read it immediately after link is established.
50548c2ecf20Sopenharmony_ci */
50558c2ecf20Sopenharmony_cistatic s32 e1000_check_downshift(struct e1000_hw *hw)
50568c2ecf20Sopenharmony_ci{
50578c2ecf20Sopenharmony_ci	s32 ret_val;
50588c2ecf20Sopenharmony_ci	u16 phy_data;
50598c2ecf20Sopenharmony_ci
50608c2ecf20Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp) {
50618c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
50628c2ecf20Sopenharmony_ci					     &phy_data);
50638c2ecf20Sopenharmony_ci		if (ret_val)
50648c2ecf20Sopenharmony_ci			return ret_val;
50658c2ecf20Sopenharmony_ci
50668c2ecf20Sopenharmony_ci		hw->speed_downgraded =
50678c2ecf20Sopenharmony_ci		    (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
50688c2ecf20Sopenharmony_ci	} else if (hw->phy_type == e1000_phy_m88) {
50698c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
50708c2ecf20Sopenharmony_ci					     &phy_data);
50718c2ecf20Sopenharmony_ci		if (ret_val)
50728c2ecf20Sopenharmony_ci			return ret_val;
50738c2ecf20Sopenharmony_ci
50748c2ecf20Sopenharmony_ci		hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
50758c2ecf20Sopenharmony_ci		    M88E1000_PSSR_DOWNSHIFT_SHIFT;
50768c2ecf20Sopenharmony_ci	}
50778c2ecf20Sopenharmony_ci
50788c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
50798c2ecf20Sopenharmony_ci}
50808c2ecf20Sopenharmony_ci
50818c2ecf20Sopenharmony_cistatic const u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
50828c2ecf20Sopenharmony_ci	IGP01E1000_PHY_AGC_PARAM_A,
50838c2ecf20Sopenharmony_ci	IGP01E1000_PHY_AGC_PARAM_B,
50848c2ecf20Sopenharmony_ci	IGP01E1000_PHY_AGC_PARAM_C,
50858c2ecf20Sopenharmony_ci	IGP01E1000_PHY_AGC_PARAM_D
50868c2ecf20Sopenharmony_ci};
50878c2ecf20Sopenharmony_ci
50888c2ecf20Sopenharmony_cistatic s32 e1000_1000Mb_check_cable_length(struct e1000_hw *hw)
50898c2ecf20Sopenharmony_ci{
50908c2ecf20Sopenharmony_ci	u16 min_length, max_length;
50918c2ecf20Sopenharmony_ci	u16 phy_data, i;
50928c2ecf20Sopenharmony_ci	s32 ret_val;
50938c2ecf20Sopenharmony_ci
50948c2ecf20Sopenharmony_ci	ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
50958c2ecf20Sopenharmony_ci	if (ret_val)
50968c2ecf20Sopenharmony_ci		return ret_val;
50978c2ecf20Sopenharmony_ci
50988c2ecf20Sopenharmony_ci	if (hw->dsp_config_state != e1000_dsp_config_enabled)
50998c2ecf20Sopenharmony_ci		return 0;
51008c2ecf20Sopenharmony_ci
51018c2ecf20Sopenharmony_ci	if (min_length >= e1000_igp_cable_length_50) {
51028c2ecf20Sopenharmony_ci		for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
51038c2ecf20Sopenharmony_ci			ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i],
51048c2ecf20Sopenharmony_ci						     &phy_data);
51058c2ecf20Sopenharmony_ci			if (ret_val)
51068c2ecf20Sopenharmony_ci				return ret_val;
51078c2ecf20Sopenharmony_ci
51088c2ecf20Sopenharmony_ci			phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
51098c2ecf20Sopenharmony_ci
51108c2ecf20Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i],
51118c2ecf20Sopenharmony_ci						      phy_data);
51128c2ecf20Sopenharmony_ci			if (ret_val)
51138c2ecf20Sopenharmony_ci				return ret_val;
51148c2ecf20Sopenharmony_ci		}
51158c2ecf20Sopenharmony_ci		hw->dsp_config_state = e1000_dsp_config_activated;
51168c2ecf20Sopenharmony_ci	} else {
51178c2ecf20Sopenharmony_ci		u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
51188c2ecf20Sopenharmony_ci		u32 idle_errs = 0;
51198c2ecf20Sopenharmony_ci
51208c2ecf20Sopenharmony_ci		/* clear previous idle error counts */
51218c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
51228c2ecf20Sopenharmony_ci		if (ret_val)
51238c2ecf20Sopenharmony_ci			return ret_val;
51248c2ecf20Sopenharmony_ci
51258c2ecf20Sopenharmony_ci		for (i = 0; i < ffe_idle_err_timeout; i++) {
51268c2ecf20Sopenharmony_ci			udelay(1000);
51278c2ecf20Sopenharmony_ci			ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
51288c2ecf20Sopenharmony_ci						     &phy_data);
51298c2ecf20Sopenharmony_ci			if (ret_val)
51308c2ecf20Sopenharmony_ci				return ret_val;
51318c2ecf20Sopenharmony_ci
51328c2ecf20Sopenharmony_ci			idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
51338c2ecf20Sopenharmony_ci			if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
51348c2ecf20Sopenharmony_ci				hw->ffe_config_state = e1000_ffe_config_active;
51358c2ecf20Sopenharmony_ci
51368c2ecf20Sopenharmony_ci				ret_val = e1000_write_phy_reg(hw,
51378c2ecf20Sopenharmony_ci							      IGP01E1000_PHY_DSP_FFE,
51388c2ecf20Sopenharmony_ci							      IGP01E1000_PHY_DSP_FFE_CM_CP);
51398c2ecf20Sopenharmony_ci				if (ret_val)
51408c2ecf20Sopenharmony_ci					return ret_val;
51418c2ecf20Sopenharmony_ci				break;
51428c2ecf20Sopenharmony_ci			}
51438c2ecf20Sopenharmony_ci
51448c2ecf20Sopenharmony_ci			if (idle_errs)
51458c2ecf20Sopenharmony_ci				ffe_idle_err_timeout =
51468c2ecf20Sopenharmony_ci					    FFE_IDLE_ERR_COUNT_TIMEOUT_100;
51478c2ecf20Sopenharmony_ci		}
51488c2ecf20Sopenharmony_ci	}
51498c2ecf20Sopenharmony_ci
51508c2ecf20Sopenharmony_ci	return 0;
51518c2ecf20Sopenharmony_ci}
51528c2ecf20Sopenharmony_ci
51538c2ecf20Sopenharmony_ci/**
51548c2ecf20Sopenharmony_ci * e1000_config_dsp_after_link_change
51558c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
51568c2ecf20Sopenharmony_ci * @link_up: was link up at the time this was called
51578c2ecf20Sopenharmony_ci *
51588c2ecf20Sopenharmony_ci * returns: - E1000_ERR_PHY if fail to read/write the PHY
51598c2ecf20Sopenharmony_ci *            E1000_SUCCESS at any other case.
51608c2ecf20Sopenharmony_ci *
51618c2ecf20Sopenharmony_ci * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
51628c2ecf20Sopenharmony_ci * gigabit link is achieved to improve link quality.
51638c2ecf20Sopenharmony_ci */
51648c2ecf20Sopenharmony_ci
51658c2ecf20Sopenharmony_cistatic s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
51668c2ecf20Sopenharmony_ci{
51678c2ecf20Sopenharmony_ci	s32 ret_val;
51688c2ecf20Sopenharmony_ci	u16 phy_data, phy_saved_data, speed, duplex, i;
51698c2ecf20Sopenharmony_ci
51708c2ecf20Sopenharmony_ci	if (hw->phy_type != e1000_phy_igp)
51718c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
51728c2ecf20Sopenharmony_ci
51738c2ecf20Sopenharmony_ci	if (link_up) {
51748c2ecf20Sopenharmony_ci		ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
51758c2ecf20Sopenharmony_ci		if (ret_val) {
51768c2ecf20Sopenharmony_ci			e_dbg("Error getting link speed and duplex\n");
51778c2ecf20Sopenharmony_ci			return ret_val;
51788c2ecf20Sopenharmony_ci		}
51798c2ecf20Sopenharmony_ci
51808c2ecf20Sopenharmony_ci		if (speed == SPEED_1000) {
51818c2ecf20Sopenharmony_ci			ret_val = e1000_1000Mb_check_cable_length(hw);
51828c2ecf20Sopenharmony_ci			if (ret_val)
51838c2ecf20Sopenharmony_ci				return ret_val;
51848c2ecf20Sopenharmony_ci		}
51858c2ecf20Sopenharmony_ci	} else {
51868c2ecf20Sopenharmony_ci		if (hw->dsp_config_state == e1000_dsp_config_activated) {
51878c2ecf20Sopenharmony_ci			/* Save off the current value of register 0x2F5B to be
51888c2ecf20Sopenharmony_ci			 * restored at the end of the routines.
51898c2ecf20Sopenharmony_ci			 */
51908c2ecf20Sopenharmony_ci			ret_val =
51918c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
51928c2ecf20Sopenharmony_ci
51938c2ecf20Sopenharmony_ci			if (ret_val)
51948c2ecf20Sopenharmony_ci				return ret_val;
51958c2ecf20Sopenharmony_ci
51968c2ecf20Sopenharmony_ci			/* Disable the PHY transmitter */
51978c2ecf20Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
51988c2ecf20Sopenharmony_ci
51998c2ecf20Sopenharmony_ci			if (ret_val)
52008c2ecf20Sopenharmony_ci				return ret_val;
52018c2ecf20Sopenharmony_ci
52028c2ecf20Sopenharmony_ci			msleep(20);
52038c2ecf20Sopenharmony_ci
52048c2ecf20Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x0000,
52058c2ecf20Sopenharmony_ci						      IGP01E1000_IEEE_FORCE_GIGA);
52068c2ecf20Sopenharmony_ci			if (ret_val)
52078c2ecf20Sopenharmony_ci				return ret_val;
52088c2ecf20Sopenharmony_ci			for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
52098c2ecf20Sopenharmony_ci				ret_val =
52108c2ecf20Sopenharmony_ci				    e1000_read_phy_reg(hw, dsp_reg_array[i],
52118c2ecf20Sopenharmony_ci						       &phy_data);
52128c2ecf20Sopenharmony_ci				if (ret_val)
52138c2ecf20Sopenharmony_ci					return ret_val;
52148c2ecf20Sopenharmony_ci
52158c2ecf20Sopenharmony_ci				phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
52168c2ecf20Sopenharmony_ci				phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
52178c2ecf20Sopenharmony_ci
52188c2ecf20Sopenharmony_ci				ret_val =
52198c2ecf20Sopenharmony_ci				    e1000_write_phy_reg(hw, dsp_reg_array[i],
52208c2ecf20Sopenharmony_ci							phy_data);
52218c2ecf20Sopenharmony_ci				if (ret_val)
52228c2ecf20Sopenharmony_ci					return ret_val;
52238c2ecf20Sopenharmony_ci			}
52248c2ecf20Sopenharmony_ci
52258c2ecf20Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x0000,
52268c2ecf20Sopenharmony_ci						      IGP01E1000_IEEE_RESTART_AUTONEG);
52278c2ecf20Sopenharmony_ci			if (ret_val)
52288c2ecf20Sopenharmony_ci				return ret_val;
52298c2ecf20Sopenharmony_ci
52308c2ecf20Sopenharmony_ci			msleep(20);
52318c2ecf20Sopenharmony_ci
52328c2ecf20Sopenharmony_ci			/* Now enable the transmitter */
52338c2ecf20Sopenharmony_ci			ret_val =
52348c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
52358c2ecf20Sopenharmony_ci
52368c2ecf20Sopenharmony_ci			if (ret_val)
52378c2ecf20Sopenharmony_ci				return ret_val;
52388c2ecf20Sopenharmony_ci
52398c2ecf20Sopenharmony_ci			hw->dsp_config_state = e1000_dsp_config_enabled;
52408c2ecf20Sopenharmony_ci		}
52418c2ecf20Sopenharmony_ci
52428c2ecf20Sopenharmony_ci		if (hw->ffe_config_state == e1000_ffe_config_active) {
52438c2ecf20Sopenharmony_ci			/* Save off the current value of register 0x2F5B to be
52448c2ecf20Sopenharmony_ci			 * restored at the end of the routines.
52458c2ecf20Sopenharmony_ci			 */
52468c2ecf20Sopenharmony_ci			ret_val =
52478c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
52488c2ecf20Sopenharmony_ci
52498c2ecf20Sopenharmony_ci			if (ret_val)
52508c2ecf20Sopenharmony_ci				return ret_val;
52518c2ecf20Sopenharmony_ci
52528c2ecf20Sopenharmony_ci			/* Disable the PHY transmitter */
52538c2ecf20Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
52548c2ecf20Sopenharmony_ci
52558c2ecf20Sopenharmony_ci			if (ret_val)
52568c2ecf20Sopenharmony_ci				return ret_val;
52578c2ecf20Sopenharmony_ci
52588c2ecf20Sopenharmony_ci			msleep(20);
52598c2ecf20Sopenharmony_ci
52608c2ecf20Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x0000,
52618c2ecf20Sopenharmony_ci						      IGP01E1000_IEEE_FORCE_GIGA);
52628c2ecf20Sopenharmony_ci			if (ret_val)
52638c2ecf20Sopenharmony_ci				return ret_val;
52648c2ecf20Sopenharmony_ci			ret_val =
52658c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE,
52668c2ecf20Sopenharmony_ci						IGP01E1000_PHY_DSP_FFE_DEFAULT);
52678c2ecf20Sopenharmony_ci			if (ret_val)
52688c2ecf20Sopenharmony_ci				return ret_val;
52698c2ecf20Sopenharmony_ci
52708c2ecf20Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x0000,
52718c2ecf20Sopenharmony_ci						      IGP01E1000_IEEE_RESTART_AUTONEG);
52728c2ecf20Sopenharmony_ci			if (ret_val)
52738c2ecf20Sopenharmony_ci				return ret_val;
52748c2ecf20Sopenharmony_ci
52758c2ecf20Sopenharmony_ci			msleep(20);
52768c2ecf20Sopenharmony_ci
52778c2ecf20Sopenharmony_ci			/* Now enable the transmitter */
52788c2ecf20Sopenharmony_ci			ret_val =
52798c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
52808c2ecf20Sopenharmony_ci
52818c2ecf20Sopenharmony_ci			if (ret_val)
52828c2ecf20Sopenharmony_ci				return ret_val;
52838c2ecf20Sopenharmony_ci
52848c2ecf20Sopenharmony_ci			hw->ffe_config_state = e1000_ffe_config_enabled;
52858c2ecf20Sopenharmony_ci		}
52868c2ecf20Sopenharmony_ci	}
52878c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
52888c2ecf20Sopenharmony_ci}
52898c2ecf20Sopenharmony_ci
52908c2ecf20Sopenharmony_ci/**
52918c2ecf20Sopenharmony_ci * e1000_set_phy_mode - Set PHY to class A mode
52928c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
52938c2ecf20Sopenharmony_ci *
52948c2ecf20Sopenharmony_ci * Assumes the following operations will follow to enable the new class mode.
52958c2ecf20Sopenharmony_ci *  1. Do a PHY soft reset
52968c2ecf20Sopenharmony_ci *  2. Restart auto-negotiation or force link.
52978c2ecf20Sopenharmony_ci */
52988c2ecf20Sopenharmony_cistatic s32 e1000_set_phy_mode(struct e1000_hw *hw)
52998c2ecf20Sopenharmony_ci{
53008c2ecf20Sopenharmony_ci	s32 ret_val;
53018c2ecf20Sopenharmony_ci	u16 eeprom_data;
53028c2ecf20Sopenharmony_ci
53038c2ecf20Sopenharmony_ci	if ((hw->mac_type == e1000_82545_rev_3) &&
53048c2ecf20Sopenharmony_ci	    (hw->media_type == e1000_media_type_copper)) {
53058c2ecf20Sopenharmony_ci		ret_val =
53068c2ecf20Sopenharmony_ci		    e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1,
53078c2ecf20Sopenharmony_ci				      &eeprom_data);
53088c2ecf20Sopenharmony_ci		if (ret_val)
53098c2ecf20Sopenharmony_ci			return ret_val;
53108c2ecf20Sopenharmony_ci
53118c2ecf20Sopenharmony_ci		if ((eeprom_data != EEPROM_RESERVED_WORD) &&
53128c2ecf20Sopenharmony_ci		    (eeprom_data & EEPROM_PHY_CLASS_A)) {
53138c2ecf20Sopenharmony_ci			ret_val =
53148c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
53158c2ecf20Sopenharmony_ci						0x000B);
53168c2ecf20Sopenharmony_ci			if (ret_val)
53178c2ecf20Sopenharmony_ci				return ret_val;
53188c2ecf20Sopenharmony_ci			ret_val =
53198c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
53208c2ecf20Sopenharmony_ci						0x8104);
53218c2ecf20Sopenharmony_ci			if (ret_val)
53228c2ecf20Sopenharmony_ci				return ret_val;
53238c2ecf20Sopenharmony_ci
53248c2ecf20Sopenharmony_ci			hw->phy_reset_disable = false;
53258c2ecf20Sopenharmony_ci		}
53268c2ecf20Sopenharmony_ci	}
53278c2ecf20Sopenharmony_ci
53288c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
53298c2ecf20Sopenharmony_ci}
53308c2ecf20Sopenharmony_ci
53318c2ecf20Sopenharmony_ci/**
53328c2ecf20Sopenharmony_ci * e1000_set_d3_lplu_state - set d3 link power state
53338c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
53348c2ecf20Sopenharmony_ci * @active: true to enable lplu false to disable lplu.
53358c2ecf20Sopenharmony_ci *
53368c2ecf20Sopenharmony_ci * This function sets the lplu state according to the active flag.  When
53378c2ecf20Sopenharmony_ci * activating lplu this function also disables smart speed and vise versa.
53388c2ecf20Sopenharmony_ci * lplu will not be activated unless the device autonegotiation advertisement
53398c2ecf20Sopenharmony_ci * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes.
53408c2ecf20Sopenharmony_ci *
53418c2ecf20Sopenharmony_ci * returns: - E1000_ERR_PHY if fail to read/write the PHY
53428c2ecf20Sopenharmony_ci *            E1000_SUCCESS at any other case.
53438c2ecf20Sopenharmony_ci */
53448c2ecf20Sopenharmony_cistatic s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
53458c2ecf20Sopenharmony_ci{
53468c2ecf20Sopenharmony_ci	s32 ret_val;
53478c2ecf20Sopenharmony_ci	u16 phy_data;
53488c2ecf20Sopenharmony_ci
53498c2ecf20Sopenharmony_ci	if (hw->phy_type != e1000_phy_igp)
53508c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
53518c2ecf20Sopenharmony_ci
53528c2ecf20Sopenharmony_ci	/* During driver activity LPLU should not be used or it will attain link
53538c2ecf20Sopenharmony_ci	 * from the lowest speeds starting from 10Mbps. The capability is used
53548c2ecf20Sopenharmony_ci	 * for Dx transitions and states
53558c2ecf20Sopenharmony_ci	 */
53568c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82541_rev_2 ||
53578c2ecf20Sopenharmony_ci	    hw->mac_type == e1000_82547_rev_2) {
53588c2ecf20Sopenharmony_ci		ret_val =
53598c2ecf20Sopenharmony_ci		    e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
53608c2ecf20Sopenharmony_ci		if (ret_val)
53618c2ecf20Sopenharmony_ci			return ret_val;
53628c2ecf20Sopenharmony_ci	}
53638c2ecf20Sopenharmony_ci
53648c2ecf20Sopenharmony_ci	if (!active) {
53658c2ecf20Sopenharmony_ci		if (hw->mac_type == e1000_82541_rev_2 ||
53668c2ecf20Sopenharmony_ci		    hw->mac_type == e1000_82547_rev_2) {
53678c2ecf20Sopenharmony_ci			phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
53688c2ecf20Sopenharmony_ci			ret_val =
53698c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
53708c2ecf20Sopenharmony_ci						phy_data);
53718c2ecf20Sopenharmony_ci			if (ret_val)
53728c2ecf20Sopenharmony_ci				return ret_val;
53738c2ecf20Sopenharmony_ci		}
53748c2ecf20Sopenharmony_ci
53758c2ecf20Sopenharmony_ci		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
53768c2ecf20Sopenharmony_ci		 * during Dx states where the power conservation is most
53778c2ecf20Sopenharmony_ci		 * important.  During driver activity we should enable
53788c2ecf20Sopenharmony_ci		 * SmartSpeed, so performance is maintained.
53798c2ecf20Sopenharmony_ci		 */
53808c2ecf20Sopenharmony_ci		if (hw->smart_speed == e1000_smart_speed_on) {
53818c2ecf20Sopenharmony_ci			ret_val =
53828c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
53838c2ecf20Sopenharmony_ci					       &phy_data);
53848c2ecf20Sopenharmony_ci			if (ret_val)
53858c2ecf20Sopenharmony_ci				return ret_val;
53868c2ecf20Sopenharmony_ci
53878c2ecf20Sopenharmony_ci			phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
53888c2ecf20Sopenharmony_ci			ret_val =
53898c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
53908c2ecf20Sopenharmony_ci						phy_data);
53918c2ecf20Sopenharmony_ci			if (ret_val)
53928c2ecf20Sopenharmony_ci				return ret_val;
53938c2ecf20Sopenharmony_ci		} else if (hw->smart_speed == e1000_smart_speed_off) {
53948c2ecf20Sopenharmony_ci			ret_val =
53958c2ecf20Sopenharmony_ci			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
53968c2ecf20Sopenharmony_ci					       &phy_data);
53978c2ecf20Sopenharmony_ci			if (ret_val)
53988c2ecf20Sopenharmony_ci				return ret_val;
53998c2ecf20Sopenharmony_ci
54008c2ecf20Sopenharmony_ci			phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
54018c2ecf20Sopenharmony_ci			ret_val =
54028c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
54038c2ecf20Sopenharmony_ci						phy_data);
54048c2ecf20Sopenharmony_ci			if (ret_val)
54058c2ecf20Sopenharmony_ci				return ret_val;
54068c2ecf20Sopenharmony_ci		}
54078c2ecf20Sopenharmony_ci	} else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) ||
54088c2ecf20Sopenharmony_ci		   (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL) ||
54098c2ecf20Sopenharmony_ci		   (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
54108c2ecf20Sopenharmony_ci		if (hw->mac_type == e1000_82541_rev_2 ||
54118c2ecf20Sopenharmony_ci		    hw->mac_type == e1000_82547_rev_2) {
54128c2ecf20Sopenharmony_ci			phy_data |= IGP01E1000_GMII_FLEX_SPD;
54138c2ecf20Sopenharmony_ci			ret_val =
54148c2ecf20Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
54158c2ecf20Sopenharmony_ci						phy_data);
54168c2ecf20Sopenharmony_ci			if (ret_val)
54178c2ecf20Sopenharmony_ci				return ret_val;
54188c2ecf20Sopenharmony_ci		}
54198c2ecf20Sopenharmony_ci
54208c2ecf20Sopenharmony_ci		/* When LPLU is enabled we should disable SmartSpeed */
54218c2ecf20Sopenharmony_ci		ret_val =
54228c2ecf20Sopenharmony_ci		    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
54238c2ecf20Sopenharmony_ci				       &phy_data);
54248c2ecf20Sopenharmony_ci		if (ret_val)
54258c2ecf20Sopenharmony_ci			return ret_val;
54268c2ecf20Sopenharmony_ci
54278c2ecf20Sopenharmony_ci		phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
54288c2ecf20Sopenharmony_ci		ret_val =
54298c2ecf20Sopenharmony_ci		    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
54308c2ecf20Sopenharmony_ci					phy_data);
54318c2ecf20Sopenharmony_ci		if (ret_val)
54328c2ecf20Sopenharmony_ci			return ret_val;
54338c2ecf20Sopenharmony_ci	}
54348c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
54358c2ecf20Sopenharmony_ci}
54368c2ecf20Sopenharmony_ci
54378c2ecf20Sopenharmony_ci/**
54388c2ecf20Sopenharmony_ci * e1000_set_vco_speed
54398c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
54408c2ecf20Sopenharmony_ci *
54418c2ecf20Sopenharmony_ci * Change VCO speed register to improve Bit Error Rate performance of SERDES.
54428c2ecf20Sopenharmony_ci */
54438c2ecf20Sopenharmony_cistatic s32 e1000_set_vco_speed(struct e1000_hw *hw)
54448c2ecf20Sopenharmony_ci{
54458c2ecf20Sopenharmony_ci	s32 ret_val;
54468c2ecf20Sopenharmony_ci	u16 default_page = 0;
54478c2ecf20Sopenharmony_ci	u16 phy_data;
54488c2ecf20Sopenharmony_ci
54498c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
54508c2ecf20Sopenharmony_ci	case e1000_82545_rev_3:
54518c2ecf20Sopenharmony_ci	case e1000_82546_rev_3:
54528c2ecf20Sopenharmony_ci		break;
54538c2ecf20Sopenharmony_ci	default:
54548c2ecf20Sopenharmony_ci		return E1000_SUCCESS;
54558c2ecf20Sopenharmony_ci	}
54568c2ecf20Sopenharmony_ci
54578c2ecf20Sopenharmony_ci	/* Set PHY register 30, page 5, bit 8 to 0 */
54588c2ecf20Sopenharmony_ci
54598c2ecf20Sopenharmony_ci	ret_val =
54608c2ecf20Sopenharmony_ci	    e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page);
54618c2ecf20Sopenharmony_ci	if (ret_val)
54628c2ecf20Sopenharmony_ci		return ret_val;
54638c2ecf20Sopenharmony_ci
54648c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
54658c2ecf20Sopenharmony_ci	if (ret_val)
54668c2ecf20Sopenharmony_ci		return ret_val;
54678c2ecf20Sopenharmony_ci
54688c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
54698c2ecf20Sopenharmony_ci	if (ret_val)
54708c2ecf20Sopenharmony_ci		return ret_val;
54718c2ecf20Sopenharmony_ci
54728c2ecf20Sopenharmony_ci	phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
54738c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
54748c2ecf20Sopenharmony_ci	if (ret_val)
54758c2ecf20Sopenharmony_ci		return ret_val;
54768c2ecf20Sopenharmony_ci
54778c2ecf20Sopenharmony_ci	/* Set PHY register 30, page 4, bit 11 to 1 */
54788c2ecf20Sopenharmony_ci
54798c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
54808c2ecf20Sopenharmony_ci	if (ret_val)
54818c2ecf20Sopenharmony_ci		return ret_val;
54828c2ecf20Sopenharmony_ci
54838c2ecf20Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
54848c2ecf20Sopenharmony_ci	if (ret_val)
54858c2ecf20Sopenharmony_ci		return ret_val;
54868c2ecf20Sopenharmony_ci
54878c2ecf20Sopenharmony_ci	phy_data |= M88E1000_PHY_VCO_REG_BIT11;
54888c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
54898c2ecf20Sopenharmony_ci	if (ret_val)
54908c2ecf20Sopenharmony_ci		return ret_val;
54918c2ecf20Sopenharmony_ci
54928c2ecf20Sopenharmony_ci	ret_val =
54938c2ecf20Sopenharmony_ci	    e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page);
54948c2ecf20Sopenharmony_ci	if (ret_val)
54958c2ecf20Sopenharmony_ci		return ret_val;
54968c2ecf20Sopenharmony_ci
54978c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
54988c2ecf20Sopenharmony_ci}
54998c2ecf20Sopenharmony_ci
55008c2ecf20Sopenharmony_ci/**
55018c2ecf20Sopenharmony_ci * e1000_enable_mng_pass_thru - check for bmc pass through
55028c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
55038c2ecf20Sopenharmony_ci *
55048c2ecf20Sopenharmony_ci * Verifies the hardware needs to allow ARPs to be processed by the host
55058c2ecf20Sopenharmony_ci * returns: - true/false
55068c2ecf20Sopenharmony_ci */
55078c2ecf20Sopenharmony_ciu32 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
55088c2ecf20Sopenharmony_ci{
55098c2ecf20Sopenharmony_ci	u32 manc;
55108c2ecf20Sopenharmony_ci
55118c2ecf20Sopenharmony_ci	if (hw->asf_firmware_present) {
55128c2ecf20Sopenharmony_ci		manc = er32(MANC);
55138c2ecf20Sopenharmony_ci
55148c2ecf20Sopenharmony_ci		if (!(manc & E1000_MANC_RCV_TCO_EN) ||
55158c2ecf20Sopenharmony_ci		    !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
55168c2ecf20Sopenharmony_ci			return false;
55178c2ecf20Sopenharmony_ci		if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
55188c2ecf20Sopenharmony_ci			return true;
55198c2ecf20Sopenharmony_ci	}
55208c2ecf20Sopenharmony_ci	return false;
55218c2ecf20Sopenharmony_ci}
55228c2ecf20Sopenharmony_ci
55238c2ecf20Sopenharmony_cistatic s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
55248c2ecf20Sopenharmony_ci{
55258c2ecf20Sopenharmony_ci	s32 ret_val;
55268c2ecf20Sopenharmony_ci	u16 mii_status_reg;
55278c2ecf20Sopenharmony_ci	u16 i;
55288c2ecf20Sopenharmony_ci
55298c2ecf20Sopenharmony_ci	/* Polarity reversal workaround for forced 10F/10H links. */
55308c2ecf20Sopenharmony_ci
55318c2ecf20Sopenharmony_ci	/* Disable the transmitter on the PHY */
55328c2ecf20Sopenharmony_ci
55338c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
55348c2ecf20Sopenharmony_ci	if (ret_val)
55358c2ecf20Sopenharmony_ci		return ret_val;
55368c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
55378c2ecf20Sopenharmony_ci	if (ret_val)
55388c2ecf20Sopenharmony_ci		return ret_val;
55398c2ecf20Sopenharmony_ci
55408c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
55418c2ecf20Sopenharmony_ci	if (ret_val)
55428c2ecf20Sopenharmony_ci		return ret_val;
55438c2ecf20Sopenharmony_ci
55448c2ecf20Sopenharmony_ci	/* This loop will early-out if the NO link condition has been met. */
55458c2ecf20Sopenharmony_ci	for (i = PHY_FORCE_TIME; i > 0; i--) {
55468c2ecf20Sopenharmony_ci		/* Read the MII Status Register and wait for Link Status bit
55478c2ecf20Sopenharmony_ci		 * to be clear.
55488c2ecf20Sopenharmony_ci		 */
55498c2ecf20Sopenharmony_ci
55508c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
55518c2ecf20Sopenharmony_ci		if (ret_val)
55528c2ecf20Sopenharmony_ci			return ret_val;
55538c2ecf20Sopenharmony_ci
55548c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
55558c2ecf20Sopenharmony_ci		if (ret_val)
55568c2ecf20Sopenharmony_ci			return ret_val;
55578c2ecf20Sopenharmony_ci
55588c2ecf20Sopenharmony_ci		if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0)
55598c2ecf20Sopenharmony_ci			break;
55608c2ecf20Sopenharmony_ci		msleep(100);
55618c2ecf20Sopenharmony_ci	}
55628c2ecf20Sopenharmony_ci
55638c2ecf20Sopenharmony_ci	/* Recommended delay time after link has been lost */
55648c2ecf20Sopenharmony_ci	msleep(1000);
55658c2ecf20Sopenharmony_ci
55668c2ecf20Sopenharmony_ci	/* Now we will re-enable th transmitter on the PHY */
55678c2ecf20Sopenharmony_ci
55688c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
55698c2ecf20Sopenharmony_ci	if (ret_val)
55708c2ecf20Sopenharmony_ci		return ret_val;
55718c2ecf20Sopenharmony_ci	msleep(50);
55728c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
55738c2ecf20Sopenharmony_ci	if (ret_val)
55748c2ecf20Sopenharmony_ci		return ret_val;
55758c2ecf20Sopenharmony_ci	msleep(50);
55768c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
55778c2ecf20Sopenharmony_ci	if (ret_val)
55788c2ecf20Sopenharmony_ci		return ret_val;
55798c2ecf20Sopenharmony_ci	msleep(50);
55808c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
55818c2ecf20Sopenharmony_ci	if (ret_val)
55828c2ecf20Sopenharmony_ci		return ret_val;
55838c2ecf20Sopenharmony_ci
55848c2ecf20Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
55858c2ecf20Sopenharmony_ci	if (ret_val)
55868c2ecf20Sopenharmony_ci		return ret_val;
55878c2ecf20Sopenharmony_ci
55888c2ecf20Sopenharmony_ci	/* This loop will early-out if the link condition has been met. */
55898c2ecf20Sopenharmony_ci	for (i = PHY_FORCE_TIME; i > 0; i--) {
55908c2ecf20Sopenharmony_ci		/* Read the MII Status Register and wait for Link Status bit
55918c2ecf20Sopenharmony_ci		 * to be set.
55928c2ecf20Sopenharmony_ci		 */
55938c2ecf20Sopenharmony_ci
55948c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
55958c2ecf20Sopenharmony_ci		if (ret_val)
55968c2ecf20Sopenharmony_ci			return ret_val;
55978c2ecf20Sopenharmony_ci
55988c2ecf20Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
55998c2ecf20Sopenharmony_ci		if (ret_val)
56008c2ecf20Sopenharmony_ci			return ret_val;
56018c2ecf20Sopenharmony_ci
56028c2ecf20Sopenharmony_ci		if (mii_status_reg & MII_SR_LINK_STATUS)
56038c2ecf20Sopenharmony_ci			break;
56048c2ecf20Sopenharmony_ci		msleep(100);
56058c2ecf20Sopenharmony_ci	}
56068c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
56078c2ecf20Sopenharmony_ci}
56088c2ecf20Sopenharmony_ci
56098c2ecf20Sopenharmony_ci/**
56108c2ecf20Sopenharmony_ci * e1000_get_auto_rd_done
56118c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
56128c2ecf20Sopenharmony_ci *
56138c2ecf20Sopenharmony_ci * Check for EEPROM Auto Read bit done.
56148c2ecf20Sopenharmony_ci * returns: - E1000_ERR_RESET if fail to reset MAC
56158c2ecf20Sopenharmony_ci *            E1000_SUCCESS at any other case.
56168c2ecf20Sopenharmony_ci */
56178c2ecf20Sopenharmony_cistatic s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
56188c2ecf20Sopenharmony_ci{
56198c2ecf20Sopenharmony_ci	msleep(5);
56208c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
56218c2ecf20Sopenharmony_ci}
56228c2ecf20Sopenharmony_ci
56238c2ecf20Sopenharmony_ci/**
56248c2ecf20Sopenharmony_ci * e1000_get_phy_cfg_done
56258c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
56268c2ecf20Sopenharmony_ci *
56278c2ecf20Sopenharmony_ci * Checks if the PHY configuration is done
56288c2ecf20Sopenharmony_ci * returns: - E1000_ERR_RESET if fail to reset MAC
56298c2ecf20Sopenharmony_ci *            E1000_SUCCESS at any other case.
56308c2ecf20Sopenharmony_ci */
56318c2ecf20Sopenharmony_cistatic s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
56328c2ecf20Sopenharmony_ci{
56338c2ecf20Sopenharmony_ci	msleep(10);
56348c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
56358c2ecf20Sopenharmony_ci}
5636