162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2006 Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci/* e1000_hw.c
562306a36Sopenharmony_ci * Shared functions for accessing and configuring the MAC
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "e1000.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_cistatic s32 e1000_check_downshift(struct e1000_hw *hw);
1162306a36Sopenharmony_cistatic s32 e1000_check_polarity(struct e1000_hw *hw,
1262306a36Sopenharmony_ci				e1000_rev_polarity *polarity);
1362306a36Sopenharmony_cistatic void e1000_clear_hw_cntrs(struct e1000_hw *hw);
1462306a36Sopenharmony_cistatic void e1000_clear_vfta(struct e1000_hw *hw);
1562306a36Sopenharmony_cistatic s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
1662306a36Sopenharmony_ci					      bool link_up);
1762306a36Sopenharmony_cistatic s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
1862306a36Sopenharmony_cistatic s32 e1000_detect_gig_phy(struct e1000_hw *hw);
1962306a36Sopenharmony_cistatic s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
2062306a36Sopenharmony_cistatic s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
2162306a36Sopenharmony_ci				  u16 *max_length);
2262306a36Sopenharmony_cistatic s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
2362306a36Sopenharmony_cistatic s32 e1000_id_led_init(struct e1000_hw *hw);
2462306a36Sopenharmony_cistatic void e1000_init_rx_addrs(struct e1000_hw *hw);
2562306a36Sopenharmony_cistatic s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
2662306a36Sopenharmony_ci				  struct e1000_phy_info *phy_info);
2762306a36Sopenharmony_cistatic s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
2862306a36Sopenharmony_ci				  struct e1000_phy_info *phy_info);
2962306a36Sopenharmony_cistatic s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
3062306a36Sopenharmony_cistatic s32 e1000_wait_autoneg(struct e1000_hw *hw);
3162306a36Sopenharmony_cistatic void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value);
3262306a36Sopenharmony_cistatic s32 e1000_set_phy_type(struct e1000_hw *hw);
3362306a36Sopenharmony_cistatic void e1000_phy_init_script(struct e1000_hw *hw);
3462306a36Sopenharmony_cistatic s32 e1000_setup_copper_link(struct e1000_hw *hw);
3562306a36Sopenharmony_cistatic s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
3662306a36Sopenharmony_cistatic s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
3762306a36Sopenharmony_cistatic s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw);
3862306a36Sopenharmony_cistatic s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
3962306a36Sopenharmony_cistatic void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
4062306a36Sopenharmony_cistatic void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
4162306a36Sopenharmony_cistatic void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count);
4262306a36Sopenharmony_cistatic u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
4362306a36Sopenharmony_cistatic s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
4462306a36Sopenharmony_cistatic s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
4562306a36Sopenharmony_ci				  u16 words, u16 *data);
4662306a36Sopenharmony_cistatic s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
4762306a36Sopenharmony_ci					u16 words, u16 *data);
4862306a36Sopenharmony_cistatic s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
4962306a36Sopenharmony_cistatic void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd);
5062306a36Sopenharmony_cistatic void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd);
5162306a36Sopenharmony_cistatic void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count);
5262306a36Sopenharmony_cistatic s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
5362306a36Sopenharmony_ci				  u16 phy_data);
5462306a36Sopenharmony_cistatic s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
5562306a36Sopenharmony_ci				 u16 *phy_data);
5662306a36Sopenharmony_cistatic u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
5762306a36Sopenharmony_cistatic s32 e1000_acquire_eeprom(struct e1000_hw *hw);
5862306a36Sopenharmony_cistatic void e1000_release_eeprom(struct e1000_hw *hw);
5962306a36Sopenharmony_cistatic void e1000_standby_eeprom(struct e1000_hw *hw);
6062306a36Sopenharmony_cistatic s32 e1000_set_vco_speed(struct e1000_hw *hw);
6162306a36Sopenharmony_cistatic s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw);
6262306a36Sopenharmony_cistatic s32 e1000_set_phy_mode(struct e1000_hw *hw);
6362306a36Sopenharmony_cistatic s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
6462306a36Sopenharmony_ci				u16 *data);
6562306a36Sopenharmony_cistatic s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
6662306a36Sopenharmony_ci				 u16 *data);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* IGP cable length table */
6962306a36Sopenharmony_cistatic const
7062306a36Sopenharmony_ciu16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = {
7162306a36Sopenharmony_ci	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
7262306a36Sopenharmony_ci	5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
7362306a36Sopenharmony_ci	25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
7462306a36Sopenharmony_ci	40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,
7562306a36Sopenharmony_ci	60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,
7662306a36Sopenharmony_ci	90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100,
7762306a36Sopenharmony_ci	    100,
7862306a36Sopenharmony_ci	100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
7962306a36Sopenharmony_ci	    110, 110,
8062306a36Sopenharmony_ci	110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120,
8162306a36Sopenharmony_ci	    120, 120
8262306a36Sopenharmony_ci};
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic DEFINE_MUTEX(e1000_eeprom_lock);
8562306a36Sopenharmony_cistatic DEFINE_SPINLOCK(e1000_phy_lock);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/**
8862306a36Sopenharmony_ci * e1000_set_phy_type - Set the phy type member in the hw struct.
8962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
9062306a36Sopenharmony_ci */
9162306a36Sopenharmony_cistatic s32 e1000_set_phy_type(struct e1000_hw *hw)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	if (hw->mac_type == e1000_undefined)
9462306a36Sopenharmony_ci		return -E1000_ERR_PHY_TYPE;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	switch (hw->phy_id) {
9762306a36Sopenharmony_ci	case M88E1000_E_PHY_ID:
9862306a36Sopenharmony_ci	case M88E1000_I_PHY_ID:
9962306a36Sopenharmony_ci	case M88E1011_I_PHY_ID:
10062306a36Sopenharmony_ci	case M88E1111_I_PHY_ID:
10162306a36Sopenharmony_ci	case M88E1118_E_PHY_ID:
10262306a36Sopenharmony_ci		hw->phy_type = e1000_phy_m88;
10362306a36Sopenharmony_ci		break;
10462306a36Sopenharmony_ci	case IGP01E1000_I_PHY_ID:
10562306a36Sopenharmony_ci		if (hw->mac_type == e1000_82541 ||
10662306a36Sopenharmony_ci		    hw->mac_type == e1000_82541_rev_2 ||
10762306a36Sopenharmony_ci		    hw->mac_type == e1000_82547 ||
10862306a36Sopenharmony_ci		    hw->mac_type == e1000_82547_rev_2)
10962306a36Sopenharmony_ci			hw->phy_type = e1000_phy_igp;
11062306a36Sopenharmony_ci		break;
11162306a36Sopenharmony_ci	case RTL8211B_PHY_ID:
11262306a36Sopenharmony_ci		hw->phy_type = e1000_phy_8211;
11362306a36Sopenharmony_ci		break;
11462306a36Sopenharmony_ci	case RTL8201N_PHY_ID:
11562306a36Sopenharmony_ci		hw->phy_type = e1000_phy_8201;
11662306a36Sopenharmony_ci		break;
11762306a36Sopenharmony_ci	default:
11862306a36Sopenharmony_ci		/* Should never have loaded on this device */
11962306a36Sopenharmony_ci		hw->phy_type = e1000_phy_undefined;
12062306a36Sopenharmony_ci		return -E1000_ERR_PHY_TYPE;
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	return E1000_SUCCESS;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/**
12762306a36Sopenharmony_ci * e1000_phy_init_script - IGP phy init script - initializes the GbE PHY
12862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
12962306a36Sopenharmony_ci */
13062306a36Sopenharmony_cistatic void e1000_phy_init_script(struct e1000_hw *hw)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	u16 phy_saved_data;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	if (hw->phy_init_script) {
13562306a36Sopenharmony_ci		msleep(20);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci		/* Save off the current value of register 0x2F5B to be restored
13862306a36Sopenharmony_ci		 * at the end of this routine.
13962306a36Sopenharmony_ci		 */
14062306a36Sopenharmony_ci		e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci		/* Disabled the PHY transmitter */
14362306a36Sopenharmony_ci		e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
14462306a36Sopenharmony_ci		msleep(20);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci		e1000_write_phy_reg(hw, 0x0000, 0x0140);
14762306a36Sopenharmony_ci		msleep(5);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		switch (hw->mac_type) {
15062306a36Sopenharmony_ci		case e1000_82541:
15162306a36Sopenharmony_ci		case e1000_82547:
15262306a36Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F95, 0x0001);
15362306a36Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F71, 0xBD21);
15462306a36Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F79, 0x0018);
15562306a36Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F30, 0x1600);
15662306a36Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F31, 0x0014);
15762306a36Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F32, 0x161C);
15862306a36Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F94, 0x0003);
15962306a36Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F96, 0x003F);
16062306a36Sopenharmony_ci			e1000_write_phy_reg(hw, 0x2010, 0x0008);
16162306a36Sopenharmony_ci			break;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci		case e1000_82541_rev_2:
16462306a36Sopenharmony_ci		case e1000_82547_rev_2:
16562306a36Sopenharmony_ci			e1000_write_phy_reg(hw, 0x1F73, 0x0099);
16662306a36Sopenharmony_ci			break;
16762306a36Sopenharmony_ci		default:
16862306a36Sopenharmony_ci			break;
16962306a36Sopenharmony_ci		}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci		e1000_write_phy_reg(hw, 0x0000, 0x3300);
17262306a36Sopenharmony_ci		msleep(20);
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci		/* Now enable the transmitter */
17562306a36Sopenharmony_ci		e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci		if (hw->mac_type == e1000_82547) {
17862306a36Sopenharmony_ci			u16 fused, fine, coarse;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci			/* Move to analog registers page */
18162306a36Sopenharmony_ci			e1000_read_phy_reg(hw,
18262306a36Sopenharmony_ci					   IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
18362306a36Sopenharmony_ci					   &fused);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci			if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
18662306a36Sopenharmony_ci				e1000_read_phy_reg(hw,
18762306a36Sopenharmony_ci						   IGP01E1000_ANALOG_FUSE_STATUS,
18862306a36Sopenharmony_ci						   &fused);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci				fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
19162306a36Sopenharmony_ci				coarse =
19262306a36Sopenharmony_ci				    fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci				if (coarse >
19562306a36Sopenharmony_ci				    IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
19662306a36Sopenharmony_ci					coarse -=
19762306a36Sopenharmony_ci					    IGP01E1000_ANALOG_FUSE_COARSE_10;
19862306a36Sopenharmony_ci					fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
19962306a36Sopenharmony_ci				} else if (coarse ==
20062306a36Sopenharmony_ci					   IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
20162306a36Sopenharmony_ci					fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci				fused =
20462306a36Sopenharmony_ci				    (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
20562306a36Sopenharmony_ci				    (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
20662306a36Sopenharmony_ci				    (coarse &
20762306a36Sopenharmony_ci				     IGP01E1000_ANALOG_FUSE_COARSE_MASK);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci				e1000_write_phy_reg(hw,
21062306a36Sopenharmony_ci						    IGP01E1000_ANALOG_FUSE_CONTROL,
21162306a36Sopenharmony_ci						    fused);
21262306a36Sopenharmony_ci				e1000_write_phy_reg(hw,
21362306a36Sopenharmony_ci						    IGP01E1000_ANALOG_FUSE_BYPASS,
21462306a36Sopenharmony_ci						    IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
21562306a36Sopenharmony_ci			}
21662306a36Sopenharmony_ci		}
21762306a36Sopenharmony_ci	}
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci/**
22162306a36Sopenharmony_ci * e1000_set_mac_type - Set the mac type member in the hw struct.
22262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
22362306a36Sopenharmony_ci */
22462306a36Sopenharmony_cis32 e1000_set_mac_type(struct e1000_hw *hw)
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci	switch (hw->device_id) {
22762306a36Sopenharmony_ci	case E1000_DEV_ID_82542:
22862306a36Sopenharmony_ci		switch (hw->revision_id) {
22962306a36Sopenharmony_ci		case E1000_82542_2_0_REV_ID:
23062306a36Sopenharmony_ci			hw->mac_type = e1000_82542_rev2_0;
23162306a36Sopenharmony_ci			break;
23262306a36Sopenharmony_ci		case E1000_82542_2_1_REV_ID:
23362306a36Sopenharmony_ci			hw->mac_type = e1000_82542_rev2_1;
23462306a36Sopenharmony_ci			break;
23562306a36Sopenharmony_ci		default:
23662306a36Sopenharmony_ci			/* Invalid 82542 revision ID */
23762306a36Sopenharmony_ci			return -E1000_ERR_MAC_TYPE;
23862306a36Sopenharmony_ci		}
23962306a36Sopenharmony_ci		break;
24062306a36Sopenharmony_ci	case E1000_DEV_ID_82543GC_FIBER:
24162306a36Sopenharmony_ci	case E1000_DEV_ID_82543GC_COPPER:
24262306a36Sopenharmony_ci		hw->mac_type = e1000_82543;
24362306a36Sopenharmony_ci		break;
24462306a36Sopenharmony_ci	case E1000_DEV_ID_82544EI_COPPER:
24562306a36Sopenharmony_ci	case E1000_DEV_ID_82544EI_FIBER:
24662306a36Sopenharmony_ci	case E1000_DEV_ID_82544GC_COPPER:
24762306a36Sopenharmony_ci	case E1000_DEV_ID_82544GC_LOM:
24862306a36Sopenharmony_ci		hw->mac_type = e1000_82544;
24962306a36Sopenharmony_ci		break;
25062306a36Sopenharmony_ci	case E1000_DEV_ID_82540EM:
25162306a36Sopenharmony_ci	case E1000_DEV_ID_82540EM_LOM:
25262306a36Sopenharmony_ci	case E1000_DEV_ID_82540EP:
25362306a36Sopenharmony_ci	case E1000_DEV_ID_82540EP_LOM:
25462306a36Sopenharmony_ci	case E1000_DEV_ID_82540EP_LP:
25562306a36Sopenharmony_ci		hw->mac_type = e1000_82540;
25662306a36Sopenharmony_ci		break;
25762306a36Sopenharmony_ci	case E1000_DEV_ID_82545EM_COPPER:
25862306a36Sopenharmony_ci	case E1000_DEV_ID_82545EM_FIBER:
25962306a36Sopenharmony_ci		hw->mac_type = e1000_82545;
26062306a36Sopenharmony_ci		break;
26162306a36Sopenharmony_ci	case E1000_DEV_ID_82545GM_COPPER:
26262306a36Sopenharmony_ci	case E1000_DEV_ID_82545GM_FIBER:
26362306a36Sopenharmony_ci	case E1000_DEV_ID_82545GM_SERDES:
26462306a36Sopenharmony_ci		hw->mac_type = e1000_82545_rev_3;
26562306a36Sopenharmony_ci		break;
26662306a36Sopenharmony_ci	case E1000_DEV_ID_82546EB_COPPER:
26762306a36Sopenharmony_ci	case E1000_DEV_ID_82546EB_FIBER:
26862306a36Sopenharmony_ci	case E1000_DEV_ID_82546EB_QUAD_COPPER:
26962306a36Sopenharmony_ci		hw->mac_type = e1000_82546;
27062306a36Sopenharmony_ci		break;
27162306a36Sopenharmony_ci	case E1000_DEV_ID_82546GB_COPPER:
27262306a36Sopenharmony_ci	case E1000_DEV_ID_82546GB_FIBER:
27362306a36Sopenharmony_ci	case E1000_DEV_ID_82546GB_SERDES:
27462306a36Sopenharmony_ci	case E1000_DEV_ID_82546GB_PCIE:
27562306a36Sopenharmony_ci	case E1000_DEV_ID_82546GB_QUAD_COPPER:
27662306a36Sopenharmony_ci	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
27762306a36Sopenharmony_ci		hw->mac_type = e1000_82546_rev_3;
27862306a36Sopenharmony_ci		break;
27962306a36Sopenharmony_ci	case E1000_DEV_ID_82541EI:
28062306a36Sopenharmony_ci	case E1000_DEV_ID_82541EI_MOBILE:
28162306a36Sopenharmony_ci	case E1000_DEV_ID_82541ER_LOM:
28262306a36Sopenharmony_ci		hw->mac_type = e1000_82541;
28362306a36Sopenharmony_ci		break;
28462306a36Sopenharmony_ci	case E1000_DEV_ID_82541ER:
28562306a36Sopenharmony_ci	case E1000_DEV_ID_82541GI:
28662306a36Sopenharmony_ci	case E1000_DEV_ID_82541GI_LF:
28762306a36Sopenharmony_ci	case E1000_DEV_ID_82541GI_MOBILE:
28862306a36Sopenharmony_ci		hw->mac_type = e1000_82541_rev_2;
28962306a36Sopenharmony_ci		break;
29062306a36Sopenharmony_ci	case E1000_DEV_ID_82547EI:
29162306a36Sopenharmony_ci	case E1000_DEV_ID_82547EI_MOBILE:
29262306a36Sopenharmony_ci		hw->mac_type = e1000_82547;
29362306a36Sopenharmony_ci		break;
29462306a36Sopenharmony_ci	case E1000_DEV_ID_82547GI:
29562306a36Sopenharmony_ci		hw->mac_type = e1000_82547_rev_2;
29662306a36Sopenharmony_ci		break;
29762306a36Sopenharmony_ci	case E1000_DEV_ID_INTEL_CE4100_GBE:
29862306a36Sopenharmony_ci		hw->mac_type = e1000_ce4100;
29962306a36Sopenharmony_ci		break;
30062306a36Sopenharmony_ci	default:
30162306a36Sopenharmony_ci		/* Should never have loaded on this device */
30262306a36Sopenharmony_ci		return -E1000_ERR_MAC_TYPE;
30362306a36Sopenharmony_ci	}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	switch (hw->mac_type) {
30662306a36Sopenharmony_ci	case e1000_82541:
30762306a36Sopenharmony_ci	case e1000_82547:
30862306a36Sopenharmony_ci	case e1000_82541_rev_2:
30962306a36Sopenharmony_ci	case e1000_82547_rev_2:
31062306a36Sopenharmony_ci		hw->asf_firmware_present = true;
31162306a36Sopenharmony_ci		break;
31262306a36Sopenharmony_ci	default:
31362306a36Sopenharmony_ci		break;
31462306a36Sopenharmony_ci	}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	/* The 82543 chip does not count tx_carrier_errors properly in
31762306a36Sopenharmony_ci	 * FD mode
31862306a36Sopenharmony_ci	 */
31962306a36Sopenharmony_ci	if (hw->mac_type == e1000_82543)
32062306a36Sopenharmony_ci		hw->bad_tx_carr_stats_fd = true;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	if (hw->mac_type > e1000_82544)
32362306a36Sopenharmony_ci		hw->has_smbus = true;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	return E1000_SUCCESS;
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci/**
32962306a36Sopenharmony_ci * e1000_set_media_type - Set media type and TBI compatibility.
33062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
33162306a36Sopenharmony_ci */
33262306a36Sopenharmony_civoid e1000_set_media_type(struct e1000_hw *hw)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	u32 status;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (hw->mac_type != e1000_82543) {
33762306a36Sopenharmony_ci		/* tbi_compatibility is only valid on 82543 */
33862306a36Sopenharmony_ci		hw->tbi_compatibility_en = false;
33962306a36Sopenharmony_ci	}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	switch (hw->device_id) {
34262306a36Sopenharmony_ci	case E1000_DEV_ID_82545GM_SERDES:
34362306a36Sopenharmony_ci	case E1000_DEV_ID_82546GB_SERDES:
34462306a36Sopenharmony_ci		hw->media_type = e1000_media_type_internal_serdes;
34562306a36Sopenharmony_ci		break;
34662306a36Sopenharmony_ci	default:
34762306a36Sopenharmony_ci		switch (hw->mac_type) {
34862306a36Sopenharmony_ci		case e1000_82542_rev2_0:
34962306a36Sopenharmony_ci		case e1000_82542_rev2_1:
35062306a36Sopenharmony_ci			hw->media_type = e1000_media_type_fiber;
35162306a36Sopenharmony_ci			break;
35262306a36Sopenharmony_ci		case e1000_ce4100:
35362306a36Sopenharmony_ci			hw->media_type = e1000_media_type_copper;
35462306a36Sopenharmony_ci			break;
35562306a36Sopenharmony_ci		default:
35662306a36Sopenharmony_ci			status = er32(STATUS);
35762306a36Sopenharmony_ci			if (status & E1000_STATUS_TBIMODE) {
35862306a36Sopenharmony_ci				hw->media_type = e1000_media_type_fiber;
35962306a36Sopenharmony_ci				/* tbi_compatibility not valid on fiber */
36062306a36Sopenharmony_ci				hw->tbi_compatibility_en = false;
36162306a36Sopenharmony_ci			} else {
36262306a36Sopenharmony_ci				hw->media_type = e1000_media_type_copper;
36362306a36Sopenharmony_ci			}
36462306a36Sopenharmony_ci			break;
36562306a36Sopenharmony_ci		}
36662306a36Sopenharmony_ci	}
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci/**
37062306a36Sopenharmony_ci * e1000_reset_hw - reset the hardware completely
37162306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
37262306a36Sopenharmony_ci *
37362306a36Sopenharmony_ci * Reset the transmit and receive units; mask and clear all interrupts.
37462306a36Sopenharmony_ci */
37562306a36Sopenharmony_cis32 e1000_reset_hw(struct e1000_hw *hw)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	u32 ctrl;
37862306a36Sopenharmony_ci	u32 ctrl_ext;
37962306a36Sopenharmony_ci	u32 manc;
38062306a36Sopenharmony_ci	u32 led_ctrl;
38162306a36Sopenharmony_ci	s32 ret_val;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	/* For 82542 (rev 2.0), disable MWI before issuing a device reset */
38462306a36Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0) {
38562306a36Sopenharmony_ci		e_dbg("Disabling MWI on 82542 rev 2.0\n");
38662306a36Sopenharmony_ci		e1000_pci_clear_mwi(hw);
38762306a36Sopenharmony_ci	}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	/* Clear interrupt mask to stop board from generating interrupts */
39062306a36Sopenharmony_ci	e_dbg("Masking off all interrupts\n");
39162306a36Sopenharmony_ci	ew32(IMC, 0xffffffff);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	/* Disable the Transmit and Receive units.  Then delay to allow
39462306a36Sopenharmony_ci	 * any pending transactions to complete before we hit the MAC with
39562306a36Sopenharmony_ci	 * the global reset.
39662306a36Sopenharmony_ci	 */
39762306a36Sopenharmony_ci	ew32(RCTL, 0);
39862306a36Sopenharmony_ci	ew32(TCTL, E1000_TCTL_PSP);
39962306a36Sopenharmony_ci	E1000_WRITE_FLUSH();
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	/* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
40262306a36Sopenharmony_ci	hw->tbi_compatibility_on = false;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	/* Delay to allow any outstanding PCI transactions to complete before
40562306a36Sopenharmony_ci	 * resetting the device
40662306a36Sopenharmony_ci	 */
40762306a36Sopenharmony_ci	msleep(10);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	ctrl = er32(CTRL);
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	/* Must reset the PHY before resetting the MAC */
41262306a36Sopenharmony_ci	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
41362306a36Sopenharmony_ci		ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST));
41462306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
41562306a36Sopenharmony_ci		msleep(5);
41662306a36Sopenharmony_ci	}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	/* Issue a global reset to the MAC.  This will reset the chip's
41962306a36Sopenharmony_ci	 * transmit, receive, DMA, and link units.  It will not effect
42062306a36Sopenharmony_ci	 * the current PCI configuration.  The global reset bit is self-
42162306a36Sopenharmony_ci	 * clearing, and should clear within a microsecond.
42262306a36Sopenharmony_ci	 */
42362306a36Sopenharmony_ci	e_dbg("Issuing a global reset to MAC\n");
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	switch (hw->mac_type) {
42662306a36Sopenharmony_ci	case e1000_82544:
42762306a36Sopenharmony_ci	case e1000_82540:
42862306a36Sopenharmony_ci	case e1000_82545:
42962306a36Sopenharmony_ci	case e1000_82546:
43062306a36Sopenharmony_ci	case e1000_82541:
43162306a36Sopenharmony_ci	case e1000_82541_rev_2:
43262306a36Sopenharmony_ci		/* These controllers can't ack the 64-bit write when issuing the
43362306a36Sopenharmony_ci		 * reset, so use IO-mapping as a workaround to issue the reset
43462306a36Sopenharmony_ci		 */
43562306a36Sopenharmony_ci		E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
43662306a36Sopenharmony_ci		break;
43762306a36Sopenharmony_ci	case e1000_82545_rev_3:
43862306a36Sopenharmony_ci	case e1000_82546_rev_3:
43962306a36Sopenharmony_ci		/* Reset is performed on a shadow of the control register */
44062306a36Sopenharmony_ci		ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST));
44162306a36Sopenharmony_ci		break;
44262306a36Sopenharmony_ci	case e1000_ce4100:
44362306a36Sopenharmony_ci	default:
44462306a36Sopenharmony_ci		ew32(CTRL, (ctrl | E1000_CTRL_RST));
44562306a36Sopenharmony_ci		break;
44662306a36Sopenharmony_ci	}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	/* After MAC reset, force reload of EEPROM to restore power-on settings
44962306a36Sopenharmony_ci	 * to device.  Later controllers reload the EEPROM automatically, so
45062306a36Sopenharmony_ci	 * just wait for reload to complete.
45162306a36Sopenharmony_ci	 */
45262306a36Sopenharmony_ci	switch (hw->mac_type) {
45362306a36Sopenharmony_ci	case e1000_82542_rev2_0:
45462306a36Sopenharmony_ci	case e1000_82542_rev2_1:
45562306a36Sopenharmony_ci	case e1000_82543:
45662306a36Sopenharmony_ci	case e1000_82544:
45762306a36Sopenharmony_ci		/* Wait for reset to complete */
45862306a36Sopenharmony_ci		udelay(10);
45962306a36Sopenharmony_ci		ctrl_ext = er32(CTRL_EXT);
46062306a36Sopenharmony_ci		ctrl_ext |= E1000_CTRL_EXT_EE_RST;
46162306a36Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
46262306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
46362306a36Sopenharmony_ci		/* Wait for EEPROM reload */
46462306a36Sopenharmony_ci		msleep(2);
46562306a36Sopenharmony_ci		break;
46662306a36Sopenharmony_ci	case e1000_82541:
46762306a36Sopenharmony_ci	case e1000_82541_rev_2:
46862306a36Sopenharmony_ci	case e1000_82547:
46962306a36Sopenharmony_ci	case e1000_82547_rev_2:
47062306a36Sopenharmony_ci		/* Wait for EEPROM reload */
47162306a36Sopenharmony_ci		msleep(20);
47262306a36Sopenharmony_ci		break;
47362306a36Sopenharmony_ci	default:
47462306a36Sopenharmony_ci		/* Auto read done will delay 5ms or poll based on mac type */
47562306a36Sopenharmony_ci		ret_val = e1000_get_auto_rd_done(hw);
47662306a36Sopenharmony_ci		if (ret_val)
47762306a36Sopenharmony_ci			return ret_val;
47862306a36Sopenharmony_ci		break;
47962306a36Sopenharmony_ci	}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	/* Disable HW ARPs on ASF enabled adapters */
48262306a36Sopenharmony_ci	if (hw->mac_type >= e1000_82540) {
48362306a36Sopenharmony_ci		manc = er32(MANC);
48462306a36Sopenharmony_ci		manc &= ~(E1000_MANC_ARP_EN);
48562306a36Sopenharmony_ci		ew32(MANC, manc);
48662306a36Sopenharmony_ci	}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
48962306a36Sopenharmony_ci		e1000_phy_init_script(hw);
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci		/* Configure activity LED after PHY reset */
49262306a36Sopenharmony_ci		led_ctrl = er32(LEDCTL);
49362306a36Sopenharmony_ci		led_ctrl &= IGP_ACTIVITY_LED_MASK;
49462306a36Sopenharmony_ci		led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
49562306a36Sopenharmony_ci		ew32(LEDCTL, led_ctrl);
49662306a36Sopenharmony_ci	}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	/* Clear interrupt mask to stop board from generating interrupts */
49962306a36Sopenharmony_ci	e_dbg("Masking off all interrupts\n");
50062306a36Sopenharmony_ci	ew32(IMC, 0xffffffff);
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	/* Clear any pending interrupt events. */
50362306a36Sopenharmony_ci	er32(ICR);
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	/* If MWI was previously enabled, reenable it. */
50662306a36Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0) {
50762306a36Sopenharmony_ci		if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
50862306a36Sopenharmony_ci			e1000_pci_set_mwi(hw);
50962306a36Sopenharmony_ci	}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	return E1000_SUCCESS;
51262306a36Sopenharmony_ci}
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci/**
51562306a36Sopenharmony_ci * e1000_init_hw - Performs basic configuration of the adapter.
51662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
51762306a36Sopenharmony_ci *
51862306a36Sopenharmony_ci * Assumes that the controller has previously been reset and is in a
51962306a36Sopenharmony_ci * post-reset uninitialized state. Initializes the receive address registers,
52062306a36Sopenharmony_ci * multicast table, and VLAN filter table. Calls routines to setup link
52162306a36Sopenharmony_ci * configuration and flow control settings. Clears all on-chip counters. Leaves
52262306a36Sopenharmony_ci * the transmit and receive units disabled and uninitialized.
52362306a36Sopenharmony_ci */
52462306a36Sopenharmony_cis32 e1000_init_hw(struct e1000_hw *hw)
52562306a36Sopenharmony_ci{
52662306a36Sopenharmony_ci	u32 ctrl;
52762306a36Sopenharmony_ci	u32 i;
52862306a36Sopenharmony_ci	s32 ret_val;
52962306a36Sopenharmony_ci	u32 mta_size;
53062306a36Sopenharmony_ci	u32 ctrl_ext;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	/* Initialize Identification LED */
53362306a36Sopenharmony_ci	ret_val = e1000_id_led_init(hw);
53462306a36Sopenharmony_ci	if (ret_val) {
53562306a36Sopenharmony_ci		e_dbg("Error Initializing Identification LED\n");
53662306a36Sopenharmony_ci		return ret_val;
53762306a36Sopenharmony_ci	}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	/* Set the media type and TBI compatibility */
54062306a36Sopenharmony_ci	e1000_set_media_type(hw);
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	/* Disabling VLAN filtering. */
54362306a36Sopenharmony_ci	e_dbg("Initializing the IEEE VLAN\n");
54462306a36Sopenharmony_ci	if (hw->mac_type < e1000_82545_rev_3)
54562306a36Sopenharmony_ci		ew32(VET, 0);
54662306a36Sopenharmony_ci	e1000_clear_vfta(hw);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
54962306a36Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0) {
55062306a36Sopenharmony_ci		e_dbg("Disabling MWI on 82542 rev 2.0\n");
55162306a36Sopenharmony_ci		e1000_pci_clear_mwi(hw);
55262306a36Sopenharmony_ci		ew32(RCTL, E1000_RCTL_RST);
55362306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
55462306a36Sopenharmony_ci		msleep(5);
55562306a36Sopenharmony_ci	}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	/* Setup the receive address. This involves initializing all of the
55862306a36Sopenharmony_ci	 * Receive Address Registers (RARs 0 - 15).
55962306a36Sopenharmony_ci	 */
56062306a36Sopenharmony_ci	e1000_init_rx_addrs(hw);
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	/* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
56362306a36Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0) {
56462306a36Sopenharmony_ci		ew32(RCTL, 0);
56562306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
56662306a36Sopenharmony_ci		msleep(1);
56762306a36Sopenharmony_ci		if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
56862306a36Sopenharmony_ci			e1000_pci_set_mwi(hw);
56962306a36Sopenharmony_ci	}
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	/* Zero out the Multicast HASH table */
57262306a36Sopenharmony_ci	e_dbg("Zeroing the MTA\n");
57362306a36Sopenharmony_ci	mta_size = E1000_MC_TBL_SIZE;
57462306a36Sopenharmony_ci	for (i = 0; i < mta_size; i++) {
57562306a36Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
57662306a36Sopenharmony_ci		/* use write flush to prevent Memory Write Block (MWB) from
57762306a36Sopenharmony_ci		 * occurring when accessing our register space
57862306a36Sopenharmony_ci		 */
57962306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
58062306a36Sopenharmony_ci	}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	/* Set the PCI priority bit correctly in the CTRL register.  This
58362306a36Sopenharmony_ci	 * determines if the adapter gives priority to receives, or if it
58462306a36Sopenharmony_ci	 * gives equal priority to transmits and receives.  Valid only on
58562306a36Sopenharmony_ci	 * 82542 and 82543 silicon.
58662306a36Sopenharmony_ci	 */
58762306a36Sopenharmony_ci	if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
58862306a36Sopenharmony_ci		ctrl = er32(CTRL);
58962306a36Sopenharmony_ci		ew32(CTRL, ctrl | E1000_CTRL_PRIOR);
59062306a36Sopenharmony_ci	}
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	switch (hw->mac_type) {
59362306a36Sopenharmony_ci	case e1000_82545_rev_3:
59462306a36Sopenharmony_ci	case e1000_82546_rev_3:
59562306a36Sopenharmony_ci		break;
59662306a36Sopenharmony_ci	default:
59762306a36Sopenharmony_ci		/* Workaround for PCI-X problem when BIOS sets MMRBC
59862306a36Sopenharmony_ci		 * incorrectly.
59962306a36Sopenharmony_ci		 */
60062306a36Sopenharmony_ci		if (hw->bus_type == e1000_bus_type_pcix &&
60162306a36Sopenharmony_ci		    e1000_pcix_get_mmrbc(hw) > 2048)
60262306a36Sopenharmony_ci			e1000_pcix_set_mmrbc(hw, 2048);
60362306a36Sopenharmony_ci		break;
60462306a36Sopenharmony_ci	}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	/* Call a subroutine to configure the link and setup flow control. */
60762306a36Sopenharmony_ci	ret_val = e1000_setup_link(hw);
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	/* Set the transmit descriptor write-back policy */
61062306a36Sopenharmony_ci	if (hw->mac_type > e1000_82544) {
61162306a36Sopenharmony_ci		ctrl = er32(TXDCTL);
61262306a36Sopenharmony_ci		ctrl =
61362306a36Sopenharmony_ci		    (ctrl & ~E1000_TXDCTL_WTHRESH) |
61462306a36Sopenharmony_ci		    E1000_TXDCTL_FULL_TX_DESC_WB;
61562306a36Sopenharmony_ci		ew32(TXDCTL, ctrl);
61662306a36Sopenharmony_ci	}
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	/* Clear all of the statistics registers (clear on read).  It is
61962306a36Sopenharmony_ci	 * important that we do this after we have tried to establish link
62062306a36Sopenharmony_ci	 * because the symbol error count will increment wildly if there
62162306a36Sopenharmony_ci	 * is no link.
62262306a36Sopenharmony_ci	 */
62362306a36Sopenharmony_ci	e1000_clear_hw_cntrs(hw);
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
62662306a36Sopenharmony_ci	    hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
62762306a36Sopenharmony_ci		ctrl_ext = er32(CTRL_EXT);
62862306a36Sopenharmony_ci		/* Relaxed ordering must be disabled to avoid a parity
62962306a36Sopenharmony_ci		 * error crash in a PCI slot.
63062306a36Sopenharmony_ci		 */
63162306a36Sopenharmony_ci		ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
63262306a36Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
63362306a36Sopenharmony_ci	}
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	return ret_val;
63662306a36Sopenharmony_ci}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci/**
63962306a36Sopenharmony_ci * e1000_adjust_serdes_amplitude - Adjust SERDES output amplitude based on EEPROM setting.
64062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code.
64162306a36Sopenharmony_ci */
64262306a36Sopenharmony_cistatic s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
64362306a36Sopenharmony_ci{
64462306a36Sopenharmony_ci	u16 eeprom_data;
64562306a36Sopenharmony_ci	s32 ret_val;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	if (hw->media_type != e1000_media_type_internal_serdes)
64862306a36Sopenharmony_ci		return E1000_SUCCESS;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	switch (hw->mac_type) {
65162306a36Sopenharmony_ci	case e1000_82545_rev_3:
65262306a36Sopenharmony_ci	case e1000_82546_rev_3:
65362306a36Sopenharmony_ci		break;
65462306a36Sopenharmony_ci	default:
65562306a36Sopenharmony_ci		return E1000_SUCCESS;
65662306a36Sopenharmony_ci	}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1,
65962306a36Sopenharmony_ci				    &eeprom_data);
66062306a36Sopenharmony_ci	if (ret_val)
66162306a36Sopenharmony_ci		return ret_val;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	if (eeprom_data != EEPROM_RESERVED_WORD) {
66462306a36Sopenharmony_ci		/* Adjust SERDES output amplitude only. */
66562306a36Sopenharmony_ci		eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
66662306a36Sopenharmony_ci		ret_val =
66762306a36Sopenharmony_ci		    e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
66862306a36Sopenharmony_ci		if (ret_val)
66962306a36Sopenharmony_ci			return ret_val;
67062306a36Sopenharmony_ci	}
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	return E1000_SUCCESS;
67362306a36Sopenharmony_ci}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci/**
67662306a36Sopenharmony_ci * e1000_setup_link - Configures flow control and link settings.
67762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
67862306a36Sopenharmony_ci *
67962306a36Sopenharmony_ci * Determines which flow control settings to use. Calls the appropriate media-
68062306a36Sopenharmony_ci * specific link configuration function. Configures the flow control settings.
68162306a36Sopenharmony_ci * Assuming the adapter has a valid link partner, a valid link should be
68262306a36Sopenharmony_ci * established. Assumes the hardware has previously been reset and the
68362306a36Sopenharmony_ci * transmitter and receiver are not enabled.
68462306a36Sopenharmony_ci */
68562306a36Sopenharmony_cis32 e1000_setup_link(struct e1000_hw *hw)
68662306a36Sopenharmony_ci{
68762306a36Sopenharmony_ci	u32 ctrl_ext;
68862306a36Sopenharmony_ci	s32 ret_val;
68962306a36Sopenharmony_ci	u16 eeprom_data;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	/* Read and store word 0x0F of the EEPROM. This word contains bits
69262306a36Sopenharmony_ci	 * that determine the hardware's default PAUSE (flow control) mode,
69362306a36Sopenharmony_ci	 * a bit that determines whether the HW defaults to enabling or
69462306a36Sopenharmony_ci	 * disabling auto-negotiation, and the direction of the
69562306a36Sopenharmony_ci	 * SW defined pins. If there is no SW over-ride of the flow
69662306a36Sopenharmony_ci	 * control setting, then the variable hw->fc will
69762306a36Sopenharmony_ci	 * be initialized based on a value in the EEPROM.
69862306a36Sopenharmony_ci	 */
69962306a36Sopenharmony_ci	if (hw->fc == E1000_FC_DEFAULT) {
70062306a36Sopenharmony_ci		ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
70162306a36Sopenharmony_ci					    1, &eeprom_data);
70262306a36Sopenharmony_ci		if (ret_val) {
70362306a36Sopenharmony_ci			e_dbg("EEPROM Read Error\n");
70462306a36Sopenharmony_ci			return -E1000_ERR_EEPROM;
70562306a36Sopenharmony_ci		}
70662306a36Sopenharmony_ci		if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
70762306a36Sopenharmony_ci			hw->fc = E1000_FC_NONE;
70862306a36Sopenharmony_ci		else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
70962306a36Sopenharmony_ci			 EEPROM_WORD0F_ASM_DIR)
71062306a36Sopenharmony_ci			hw->fc = E1000_FC_TX_PAUSE;
71162306a36Sopenharmony_ci		else
71262306a36Sopenharmony_ci			hw->fc = E1000_FC_FULL;
71362306a36Sopenharmony_ci	}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	/* We want to save off the original Flow Control configuration just
71662306a36Sopenharmony_ci	 * in case we get disconnected and then reconnected into a different
71762306a36Sopenharmony_ci	 * hub or switch with different Flow Control capabilities.
71862306a36Sopenharmony_ci	 */
71962306a36Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0)
72062306a36Sopenharmony_ci		hw->fc &= (~E1000_FC_TX_PAUSE);
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
72362306a36Sopenharmony_ci		hw->fc &= (~E1000_FC_RX_PAUSE);
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	hw->original_fc = hw->fc;
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc);
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	/* Take the 4 bits from EEPROM word 0x0F that determine the initial
73062306a36Sopenharmony_ci	 * polarity value for the SW controlled pins, and setup the
73162306a36Sopenharmony_ci	 * Extended Device Control reg with that info.
73262306a36Sopenharmony_ci	 * This is needed because one of the SW controlled pins is used for
73362306a36Sopenharmony_ci	 * signal detection.  So this should be done before e1000_setup_pcs_link()
73462306a36Sopenharmony_ci	 * or e1000_phy_setup() is called.
73562306a36Sopenharmony_ci	 */
73662306a36Sopenharmony_ci	if (hw->mac_type == e1000_82543) {
73762306a36Sopenharmony_ci		ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
73862306a36Sopenharmony_ci					    1, &eeprom_data);
73962306a36Sopenharmony_ci		if (ret_val) {
74062306a36Sopenharmony_ci			e_dbg("EEPROM Read Error\n");
74162306a36Sopenharmony_ci			return -E1000_ERR_EEPROM;
74262306a36Sopenharmony_ci		}
74362306a36Sopenharmony_ci		ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
74462306a36Sopenharmony_ci			    SWDPIO__EXT_SHIFT);
74562306a36Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
74662306a36Sopenharmony_ci	}
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	/* Call the necessary subroutine to configure the link. */
74962306a36Sopenharmony_ci	ret_val = (hw->media_type == e1000_media_type_copper) ?
75062306a36Sopenharmony_ci	    e1000_setup_copper_link(hw) : e1000_setup_fiber_serdes_link(hw);
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	/* Initialize the flow control address, type, and PAUSE timer
75362306a36Sopenharmony_ci	 * registers to their default values.  This is done even if flow
75462306a36Sopenharmony_ci	 * control is disabled, because it does not hurt anything to
75562306a36Sopenharmony_ci	 * initialize these registers.
75662306a36Sopenharmony_ci	 */
75762306a36Sopenharmony_ci	e_dbg("Initializing the Flow Control address, type and timer regs\n");
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	ew32(FCT, FLOW_CONTROL_TYPE);
76062306a36Sopenharmony_ci	ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
76162306a36Sopenharmony_ci	ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	ew32(FCTTV, hw->fc_pause_time);
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	/* Set the flow control receive threshold registers.  Normally,
76662306a36Sopenharmony_ci	 * these registers will be set to a default threshold that may be
76762306a36Sopenharmony_ci	 * adjusted later by the driver's runtime code.  However, if the
76862306a36Sopenharmony_ci	 * ability to transmit pause frames in not enabled, then these
76962306a36Sopenharmony_ci	 * registers will be set to 0.
77062306a36Sopenharmony_ci	 */
77162306a36Sopenharmony_ci	if (!(hw->fc & E1000_FC_TX_PAUSE)) {
77262306a36Sopenharmony_ci		ew32(FCRTL, 0);
77362306a36Sopenharmony_ci		ew32(FCRTH, 0);
77462306a36Sopenharmony_ci	} else {
77562306a36Sopenharmony_ci		/* We need to set up the Receive Threshold high and low water
77662306a36Sopenharmony_ci		 * marks as well as (optionally) enabling the transmission of
77762306a36Sopenharmony_ci		 * XON frames.
77862306a36Sopenharmony_ci		 */
77962306a36Sopenharmony_ci		if (hw->fc_send_xon) {
78062306a36Sopenharmony_ci			ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
78162306a36Sopenharmony_ci			ew32(FCRTH, hw->fc_high_water);
78262306a36Sopenharmony_ci		} else {
78362306a36Sopenharmony_ci			ew32(FCRTL, hw->fc_low_water);
78462306a36Sopenharmony_ci			ew32(FCRTH, hw->fc_high_water);
78562306a36Sopenharmony_ci		}
78662306a36Sopenharmony_ci	}
78762306a36Sopenharmony_ci	return ret_val;
78862306a36Sopenharmony_ci}
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci/**
79162306a36Sopenharmony_ci * e1000_setup_fiber_serdes_link - prepare fiber or serdes link
79262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
79362306a36Sopenharmony_ci *
79462306a36Sopenharmony_ci * Manipulates Physical Coding Sublayer functions in order to configure
79562306a36Sopenharmony_ci * link. Assumes the hardware has been previously reset and the transmitter
79662306a36Sopenharmony_ci * and receiver are not enabled.
79762306a36Sopenharmony_ci */
79862306a36Sopenharmony_cistatic s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
79962306a36Sopenharmony_ci{
80062306a36Sopenharmony_ci	u32 ctrl;
80162306a36Sopenharmony_ci	u32 status;
80262306a36Sopenharmony_ci	u32 txcw = 0;
80362306a36Sopenharmony_ci	u32 i;
80462306a36Sopenharmony_ci	u32 signal = 0;
80562306a36Sopenharmony_ci	s32 ret_val;
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	/* On adapters with a MAC newer than 82544, SWDP 1 will be
80862306a36Sopenharmony_ci	 * set when the optics detect a signal. On older adapters, it will be
80962306a36Sopenharmony_ci	 * cleared when there is a signal.  This applies to fiber media only.
81062306a36Sopenharmony_ci	 * If we're on serdes media, adjust the output amplitude to value
81162306a36Sopenharmony_ci	 * set in the EEPROM.
81262306a36Sopenharmony_ci	 */
81362306a36Sopenharmony_ci	ctrl = er32(CTRL);
81462306a36Sopenharmony_ci	if (hw->media_type == e1000_media_type_fiber)
81562306a36Sopenharmony_ci		signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	ret_val = e1000_adjust_serdes_amplitude(hw);
81862306a36Sopenharmony_ci	if (ret_val)
81962306a36Sopenharmony_ci		return ret_val;
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	/* Take the link out of reset */
82262306a36Sopenharmony_ci	ctrl &= ~(E1000_CTRL_LRST);
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	/* Adjust VCO speed to improve BER performance */
82562306a36Sopenharmony_ci	ret_val = e1000_set_vco_speed(hw);
82662306a36Sopenharmony_ci	if (ret_val)
82762306a36Sopenharmony_ci		return ret_val;
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	e1000_config_collision_dist(hw);
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci	/* Check for a software override of the flow control settings, and setup
83262306a36Sopenharmony_ci	 * the device accordingly.  If auto-negotiation is enabled, then
83362306a36Sopenharmony_ci	 * software will have to set the "PAUSE" bits to the correct value in
83462306a36Sopenharmony_ci	 * the Tranmsit Config Word Register (TXCW) and re-start
83562306a36Sopenharmony_ci	 * auto-negotiation.  However, if auto-negotiation is disabled, then
83662306a36Sopenharmony_ci	 * software will have to manually configure the two flow control enable
83762306a36Sopenharmony_ci	 * bits in the CTRL register.
83862306a36Sopenharmony_ci	 *
83962306a36Sopenharmony_ci	 * The possible values of the "fc" parameter are:
84062306a36Sopenharmony_ci	 *  0:  Flow control is completely disabled
84162306a36Sopenharmony_ci	 *  1:  Rx flow control is enabled (we can receive pause frames, but
84262306a36Sopenharmony_ci	 *      not send pause frames).
84362306a36Sopenharmony_ci	 *  2:  Tx flow control is enabled (we can send pause frames but we do
84462306a36Sopenharmony_ci	 *      not support receiving pause frames).
84562306a36Sopenharmony_ci	 *  3:  Both Rx and TX flow control (symmetric) are enabled.
84662306a36Sopenharmony_ci	 */
84762306a36Sopenharmony_ci	switch (hw->fc) {
84862306a36Sopenharmony_ci	case E1000_FC_NONE:
84962306a36Sopenharmony_ci		/* Flow ctrl is completely disabled by a software over-ride */
85062306a36Sopenharmony_ci		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
85162306a36Sopenharmony_ci		break;
85262306a36Sopenharmony_ci	case E1000_FC_RX_PAUSE:
85362306a36Sopenharmony_ci		/* Rx Flow control is enabled and Tx Flow control is disabled by
85462306a36Sopenharmony_ci		 * a software over-ride. Since there really isn't a way to
85562306a36Sopenharmony_ci		 * advertise that we are capable of Rx Pause ONLY, we will
85662306a36Sopenharmony_ci		 * advertise that we support both symmetric and asymmetric Rx
85762306a36Sopenharmony_ci		 * PAUSE. Later, we will disable the adapter's ability to send
85862306a36Sopenharmony_ci		 * PAUSE frames.
85962306a36Sopenharmony_ci		 */
86062306a36Sopenharmony_ci		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
86162306a36Sopenharmony_ci		break;
86262306a36Sopenharmony_ci	case E1000_FC_TX_PAUSE:
86362306a36Sopenharmony_ci		/* Tx Flow control is enabled, and Rx Flow control is disabled,
86462306a36Sopenharmony_ci		 * by a software over-ride.
86562306a36Sopenharmony_ci		 */
86662306a36Sopenharmony_ci		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
86762306a36Sopenharmony_ci		break;
86862306a36Sopenharmony_ci	case E1000_FC_FULL:
86962306a36Sopenharmony_ci		/* Flow control (both Rx and Tx) is enabled by a software
87062306a36Sopenharmony_ci		 * over-ride.
87162306a36Sopenharmony_ci		 */
87262306a36Sopenharmony_ci		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
87362306a36Sopenharmony_ci		break;
87462306a36Sopenharmony_ci	default:
87562306a36Sopenharmony_ci		e_dbg("Flow control param set incorrectly\n");
87662306a36Sopenharmony_ci		return -E1000_ERR_CONFIG;
87762306a36Sopenharmony_ci	}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	/* Since auto-negotiation is enabled, take the link out of reset (the
88062306a36Sopenharmony_ci	 * link will be in reset, because we previously reset the chip). This
88162306a36Sopenharmony_ci	 * will restart auto-negotiation.  If auto-negotiation is successful
88262306a36Sopenharmony_ci	 * then the link-up status bit will be set and the flow control enable
88362306a36Sopenharmony_ci	 * bits (RFCE and TFCE) will be set according to their negotiated value.
88462306a36Sopenharmony_ci	 */
88562306a36Sopenharmony_ci	e_dbg("Auto-negotiation enabled\n");
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	ew32(TXCW, txcw);
88862306a36Sopenharmony_ci	ew32(CTRL, ctrl);
88962306a36Sopenharmony_ci	E1000_WRITE_FLUSH();
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	hw->txcw = txcw;
89262306a36Sopenharmony_ci	msleep(1);
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	/* If we have a signal (the cable is plugged in) then poll for a
89562306a36Sopenharmony_ci	 * "Link-Up" indication in the Device Status Register.  Time-out if a
89662306a36Sopenharmony_ci	 * link isn't seen in 500 milliseconds seconds (Auto-negotiation should
89762306a36Sopenharmony_ci	 * complete in less than 500 milliseconds even if the other end is doing
89862306a36Sopenharmony_ci	 * it in SW). For internal serdes, we just assume a signal is present,
89962306a36Sopenharmony_ci	 * then poll.
90062306a36Sopenharmony_ci	 */
90162306a36Sopenharmony_ci	if (hw->media_type == e1000_media_type_internal_serdes ||
90262306a36Sopenharmony_ci	    (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) {
90362306a36Sopenharmony_ci		e_dbg("Looking for Link\n");
90462306a36Sopenharmony_ci		for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
90562306a36Sopenharmony_ci			msleep(10);
90662306a36Sopenharmony_ci			status = er32(STATUS);
90762306a36Sopenharmony_ci			if (status & E1000_STATUS_LU)
90862306a36Sopenharmony_ci				break;
90962306a36Sopenharmony_ci		}
91062306a36Sopenharmony_ci		if (i == (LINK_UP_TIMEOUT / 10)) {
91162306a36Sopenharmony_ci			e_dbg("Never got a valid link from auto-neg!!!\n");
91262306a36Sopenharmony_ci			hw->autoneg_failed = 1;
91362306a36Sopenharmony_ci			/* AutoNeg failed to achieve a link, so we'll call
91462306a36Sopenharmony_ci			 * e1000_check_for_link. This routine will force the
91562306a36Sopenharmony_ci			 * link up if we detect a signal. This will allow us to
91662306a36Sopenharmony_ci			 * communicate with non-autonegotiating link partners.
91762306a36Sopenharmony_ci			 */
91862306a36Sopenharmony_ci			ret_val = e1000_check_for_link(hw);
91962306a36Sopenharmony_ci			if (ret_val) {
92062306a36Sopenharmony_ci				e_dbg("Error while checking for link\n");
92162306a36Sopenharmony_ci				return ret_val;
92262306a36Sopenharmony_ci			}
92362306a36Sopenharmony_ci			hw->autoneg_failed = 0;
92462306a36Sopenharmony_ci		} else {
92562306a36Sopenharmony_ci			hw->autoneg_failed = 0;
92662306a36Sopenharmony_ci			e_dbg("Valid Link Found\n");
92762306a36Sopenharmony_ci		}
92862306a36Sopenharmony_ci	} else {
92962306a36Sopenharmony_ci		e_dbg("No Signal Detected\n");
93062306a36Sopenharmony_ci	}
93162306a36Sopenharmony_ci	return E1000_SUCCESS;
93262306a36Sopenharmony_ci}
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci/**
93562306a36Sopenharmony_ci * e1000_copper_link_rtl_setup - Copper link setup for e1000_phy_rtl series.
93662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
93762306a36Sopenharmony_ci *
93862306a36Sopenharmony_ci * Commits changes to PHY configuration by calling e1000_phy_reset().
93962306a36Sopenharmony_ci */
94062306a36Sopenharmony_cistatic s32 e1000_copper_link_rtl_setup(struct e1000_hw *hw)
94162306a36Sopenharmony_ci{
94262306a36Sopenharmony_ci	s32 ret_val;
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	/* SW reset the PHY so all changes take effect */
94562306a36Sopenharmony_ci	ret_val = e1000_phy_reset(hw);
94662306a36Sopenharmony_ci	if (ret_val) {
94762306a36Sopenharmony_ci		e_dbg("Error Resetting the PHY\n");
94862306a36Sopenharmony_ci		return ret_val;
94962306a36Sopenharmony_ci	}
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci	return E1000_SUCCESS;
95262306a36Sopenharmony_ci}
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_cistatic s32 gbe_dhg_phy_setup(struct e1000_hw *hw)
95562306a36Sopenharmony_ci{
95662306a36Sopenharmony_ci	s32 ret_val;
95762306a36Sopenharmony_ci	u32 ctrl_aux;
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	switch (hw->phy_type) {
96062306a36Sopenharmony_ci	case e1000_phy_8211:
96162306a36Sopenharmony_ci		ret_val = e1000_copper_link_rtl_setup(hw);
96262306a36Sopenharmony_ci		if (ret_val) {
96362306a36Sopenharmony_ci			e_dbg("e1000_copper_link_rtl_setup failed!\n");
96462306a36Sopenharmony_ci			return ret_val;
96562306a36Sopenharmony_ci		}
96662306a36Sopenharmony_ci		break;
96762306a36Sopenharmony_ci	case e1000_phy_8201:
96862306a36Sopenharmony_ci		/* Set RMII mode */
96962306a36Sopenharmony_ci		ctrl_aux = er32(CTL_AUX);
97062306a36Sopenharmony_ci		ctrl_aux |= E1000_CTL_AUX_RMII;
97162306a36Sopenharmony_ci		ew32(CTL_AUX, ctrl_aux);
97262306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci		/* Disable the J/K bits required for receive */
97562306a36Sopenharmony_ci		ctrl_aux = er32(CTL_AUX);
97662306a36Sopenharmony_ci		ctrl_aux |= 0x4;
97762306a36Sopenharmony_ci		ctrl_aux &= ~0x2;
97862306a36Sopenharmony_ci		ew32(CTL_AUX, ctrl_aux);
97962306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
98062306a36Sopenharmony_ci		ret_val = e1000_copper_link_rtl_setup(hw);
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci		if (ret_val) {
98362306a36Sopenharmony_ci			e_dbg("e1000_copper_link_rtl_setup failed!\n");
98462306a36Sopenharmony_ci			return ret_val;
98562306a36Sopenharmony_ci		}
98662306a36Sopenharmony_ci		break;
98762306a36Sopenharmony_ci	default:
98862306a36Sopenharmony_ci		e_dbg("Error Resetting the PHY\n");
98962306a36Sopenharmony_ci		return E1000_ERR_PHY_TYPE;
99062306a36Sopenharmony_ci	}
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	return E1000_SUCCESS;
99362306a36Sopenharmony_ci}
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci/**
99662306a36Sopenharmony_ci * e1000_copper_link_preconfig - early configuration for copper
99762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
99862306a36Sopenharmony_ci *
99962306a36Sopenharmony_ci * Make sure we have a valid PHY and change PHY mode before link setup.
100062306a36Sopenharmony_ci */
100162306a36Sopenharmony_cistatic s32 e1000_copper_link_preconfig(struct e1000_hw *hw)
100262306a36Sopenharmony_ci{
100362306a36Sopenharmony_ci	u32 ctrl;
100462306a36Sopenharmony_ci	s32 ret_val;
100562306a36Sopenharmony_ci	u16 phy_data;
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	ctrl = er32(CTRL);
100862306a36Sopenharmony_ci	/* With 82543, we need to force speed and duplex on the MAC equal to
100962306a36Sopenharmony_ci	 * what the PHY speed and duplex configuration is. In addition, we need
101062306a36Sopenharmony_ci	 * to perform a hardware reset on the PHY to take it out of reset.
101162306a36Sopenharmony_ci	 */
101262306a36Sopenharmony_ci	if (hw->mac_type > e1000_82543) {
101362306a36Sopenharmony_ci		ctrl |= E1000_CTRL_SLU;
101462306a36Sopenharmony_ci		ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
101562306a36Sopenharmony_ci		ew32(CTRL, ctrl);
101662306a36Sopenharmony_ci	} else {
101762306a36Sopenharmony_ci		ctrl |=
101862306a36Sopenharmony_ci		    (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
101962306a36Sopenharmony_ci		ew32(CTRL, ctrl);
102062306a36Sopenharmony_ci		ret_val = e1000_phy_hw_reset(hw);
102162306a36Sopenharmony_ci		if (ret_val)
102262306a36Sopenharmony_ci			return ret_val;
102362306a36Sopenharmony_ci	}
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	/* Make sure we have a valid PHY */
102662306a36Sopenharmony_ci	ret_val = e1000_detect_gig_phy(hw);
102762306a36Sopenharmony_ci	if (ret_val) {
102862306a36Sopenharmony_ci		e_dbg("Error, did not detect valid phy.\n");
102962306a36Sopenharmony_ci		return ret_val;
103062306a36Sopenharmony_ci	}
103162306a36Sopenharmony_ci	e_dbg("Phy ID = %x\n", hw->phy_id);
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	/* Set PHY to class A mode (if necessary) */
103462306a36Sopenharmony_ci	ret_val = e1000_set_phy_mode(hw);
103562306a36Sopenharmony_ci	if (ret_val)
103662306a36Sopenharmony_ci		return ret_val;
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	if ((hw->mac_type == e1000_82545_rev_3) ||
103962306a36Sopenharmony_ci	    (hw->mac_type == e1000_82546_rev_3)) {
104062306a36Sopenharmony_ci		ret_val =
104162306a36Sopenharmony_ci		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
104262306a36Sopenharmony_ci		phy_data |= 0x00000008;
104362306a36Sopenharmony_ci		ret_val =
104462306a36Sopenharmony_ci		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
104562306a36Sopenharmony_ci	}
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	if (hw->mac_type <= e1000_82543 ||
104862306a36Sopenharmony_ci	    hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
104962306a36Sopenharmony_ci	    hw->mac_type == e1000_82541_rev_2 ||
105062306a36Sopenharmony_ci	    hw->mac_type == e1000_82547_rev_2)
105162306a36Sopenharmony_ci		hw->phy_reset_disable = false;
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	return E1000_SUCCESS;
105462306a36Sopenharmony_ci}
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci/**
105762306a36Sopenharmony_ci * e1000_copper_link_igp_setup - Copper link setup for e1000_phy_igp series.
105862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
105962306a36Sopenharmony_ci */
106062306a36Sopenharmony_cistatic s32 e1000_copper_link_igp_setup(struct e1000_hw *hw)
106162306a36Sopenharmony_ci{
106262306a36Sopenharmony_ci	u32 led_ctrl;
106362306a36Sopenharmony_ci	s32 ret_val;
106462306a36Sopenharmony_ci	u16 phy_data;
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	if (hw->phy_reset_disable)
106762306a36Sopenharmony_ci		return E1000_SUCCESS;
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	ret_val = e1000_phy_reset(hw);
107062306a36Sopenharmony_ci	if (ret_val) {
107162306a36Sopenharmony_ci		e_dbg("Error Resetting the PHY\n");
107262306a36Sopenharmony_ci		return ret_val;
107362306a36Sopenharmony_ci	}
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	/* Wait 15ms for MAC to configure PHY from eeprom settings */
107662306a36Sopenharmony_ci	msleep(15);
107762306a36Sopenharmony_ci	/* Configure activity LED after PHY reset */
107862306a36Sopenharmony_ci	led_ctrl = er32(LEDCTL);
107962306a36Sopenharmony_ci	led_ctrl &= IGP_ACTIVITY_LED_MASK;
108062306a36Sopenharmony_ci	led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
108162306a36Sopenharmony_ci	ew32(LEDCTL, led_ctrl);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	/* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
108462306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp) {
108562306a36Sopenharmony_ci		/* disable lplu d3 during driver init */
108662306a36Sopenharmony_ci		ret_val = e1000_set_d3_lplu_state(hw, false);
108762306a36Sopenharmony_ci		if (ret_val) {
108862306a36Sopenharmony_ci			e_dbg("Error Disabling LPLU D3\n");
108962306a36Sopenharmony_ci			return ret_val;
109062306a36Sopenharmony_ci		}
109162306a36Sopenharmony_ci	}
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	/* Configure mdi-mdix settings */
109462306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
109562306a36Sopenharmony_ci	if (ret_val)
109662306a36Sopenharmony_ci		return ret_val;
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
109962306a36Sopenharmony_ci		hw->dsp_config_state = e1000_dsp_config_disabled;
110062306a36Sopenharmony_ci		/* Force MDI for earlier revs of the IGP PHY */
110162306a36Sopenharmony_ci		phy_data &=
110262306a36Sopenharmony_ci		    ~(IGP01E1000_PSCR_AUTO_MDIX |
110362306a36Sopenharmony_ci		      IGP01E1000_PSCR_FORCE_MDI_MDIX);
110462306a36Sopenharmony_ci		hw->mdix = 1;
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	} else {
110762306a36Sopenharmony_ci		hw->dsp_config_state = e1000_dsp_config_enabled;
110862306a36Sopenharmony_ci		phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci		switch (hw->mdix) {
111162306a36Sopenharmony_ci		case 1:
111262306a36Sopenharmony_ci			phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
111362306a36Sopenharmony_ci			break;
111462306a36Sopenharmony_ci		case 2:
111562306a36Sopenharmony_ci			phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
111662306a36Sopenharmony_ci			break;
111762306a36Sopenharmony_ci		case 0:
111862306a36Sopenharmony_ci		default:
111962306a36Sopenharmony_ci			phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
112062306a36Sopenharmony_ci			break;
112162306a36Sopenharmony_ci		}
112262306a36Sopenharmony_ci	}
112362306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
112462306a36Sopenharmony_ci	if (ret_val)
112562306a36Sopenharmony_ci		return ret_val;
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	/* set auto-master slave resolution settings */
112862306a36Sopenharmony_ci	if (hw->autoneg) {
112962306a36Sopenharmony_ci		e1000_ms_type phy_ms_setting = hw->master_slave;
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci		if (hw->ffe_config_state == e1000_ffe_config_active)
113262306a36Sopenharmony_ci			hw->ffe_config_state = e1000_ffe_config_enabled;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci		if (hw->dsp_config_state == e1000_dsp_config_activated)
113562306a36Sopenharmony_ci			hw->dsp_config_state = e1000_dsp_config_enabled;
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci		/* when autonegotiation advertisement is only 1000Mbps then we
113862306a36Sopenharmony_ci		 * should disable SmartSpeed and enable Auto MasterSlave
113962306a36Sopenharmony_ci		 * resolution as hardware default.
114062306a36Sopenharmony_ci		 */
114162306a36Sopenharmony_ci		if (hw->autoneg_advertised == ADVERTISE_1000_FULL) {
114262306a36Sopenharmony_ci			/* Disable SmartSpeed */
114362306a36Sopenharmony_ci			ret_val =
114462306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
114562306a36Sopenharmony_ci					       &phy_data);
114662306a36Sopenharmony_ci			if (ret_val)
114762306a36Sopenharmony_ci				return ret_val;
114862306a36Sopenharmony_ci			phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
114962306a36Sopenharmony_ci			ret_val =
115062306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
115162306a36Sopenharmony_ci						phy_data);
115262306a36Sopenharmony_ci			if (ret_val)
115362306a36Sopenharmony_ci				return ret_val;
115462306a36Sopenharmony_ci			/* Set auto Master/Slave resolution process */
115562306a36Sopenharmony_ci			ret_val =
115662306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
115762306a36Sopenharmony_ci			if (ret_val)
115862306a36Sopenharmony_ci				return ret_val;
115962306a36Sopenharmony_ci			phy_data &= ~CR_1000T_MS_ENABLE;
116062306a36Sopenharmony_ci			ret_val =
116162306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
116262306a36Sopenharmony_ci			if (ret_val)
116362306a36Sopenharmony_ci				return ret_val;
116462306a36Sopenharmony_ci		}
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
116762306a36Sopenharmony_ci		if (ret_val)
116862306a36Sopenharmony_ci			return ret_val;
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci		/* load defaults for future use */
117162306a36Sopenharmony_ci		hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
117262306a36Sopenharmony_ci		    ((phy_data & CR_1000T_MS_VALUE) ?
117362306a36Sopenharmony_ci		     e1000_ms_force_master :
117462306a36Sopenharmony_ci		     e1000_ms_force_slave) : e1000_ms_auto;
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci		switch (phy_ms_setting) {
117762306a36Sopenharmony_ci		case e1000_ms_force_master:
117862306a36Sopenharmony_ci			phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
117962306a36Sopenharmony_ci			break;
118062306a36Sopenharmony_ci		case e1000_ms_force_slave:
118162306a36Sopenharmony_ci			phy_data |= CR_1000T_MS_ENABLE;
118262306a36Sopenharmony_ci			phy_data &= ~(CR_1000T_MS_VALUE);
118362306a36Sopenharmony_ci			break;
118462306a36Sopenharmony_ci		case e1000_ms_auto:
118562306a36Sopenharmony_ci			phy_data &= ~CR_1000T_MS_ENABLE;
118662306a36Sopenharmony_ci			break;
118762306a36Sopenharmony_ci		default:
118862306a36Sopenharmony_ci			break;
118962306a36Sopenharmony_ci		}
119062306a36Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
119162306a36Sopenharmony_ci		if (ret_val)
119262306a36Sopenharmony_ci			return ret_val;
119362306a36Sopenharmony_ci	}
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci	return E1000_SUCCESS;
119662306a36Sopenharmony_ci}
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci/**
119962306a36Sopenharmony_ci * e1000_copper_link_mgp_setup - Copper link setup for e1000_phy_m88 series.
120062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
120162306a36Sopenharmony_ci */
120262306a36Sopenharmony_cistatic s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw)
120362306a36Sopenharmony_ci{
120462306a36Sopenharmony_ci	s32 ret_val;
120562306a36Sopenharmony_ci	u16 phy_data;
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci	if (hw->phy_reset_disable)
120862306a36Sopenharmony_ci		return E1000_SUCCESS;
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	/* Enable CRS on TX. This must be set for half-duplex operation. */
121162306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
121262306a36Sopenharmony_ci	if (ret_val)
121362306a36Sopenharmony_ci		return ret_val;
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	/* Options:
121862306a36Sopenharmony_ci	 *   MDI/MDI-X = 0 (default)
121962306a36Sopenharmony_ci	 *   0 - Auto for all speeds
122062306a36Sopenharmony_ci	 *   1 - MDI mode
122162306a36Sopenharmony_ci	 *   2 - MDI-X mode
122262306a36Sopenharmony_ci	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
122362306a36Sopenharmony_ci	 */
122462306a36Sopenharmony_ci	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	switch (hw->mdix) {
122762306a36Sopenharmony_ci	case 1:
122862306a36Sopenharmony_ci		phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
122962306a36Sopenharmony_ci		break;
123062306a36Sopenharmony_ci	case 2:
123162306a36Sopenharmony_ci		phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
123262306a36Sopenharmony_ci		break;
123362306a36Sopenharmony_ci	case 3:
123462306a36Sopenharmony_ci		phy_data |= M88E1000_PSCR_AUTO_X_1000T;
123562306a36Sopenharmony_ci		break;
123662306a36Sopenharmony_ci	case 0:
123762306a36Sopenharmony_ci	default:
123862306a36Sopenharmony_ci		phy_data |= M88E1000_PSCR_AUTO_X_MODE;
123962306a36Sopenharmony_ci		break;
124062306a36Sopenharmony_ci	}
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	/* Options:
124362306a36Sopenharmony_ci	 *   disable_polarity_correction = 0 (default)
124462306a36Sopenharmony_ci	 *       Automatic Correction for Reversed Cable Polarity
124562306a36Sopenharmony_ci	 *   0 - Disabled
124662306a36Sopenharmony_ci	 *   1 - Enabled
124762306a36Sopenharmony_ci	 */
124862306a36Sopenharmony_ci	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
124962306a36Sopenharmony_ci	if (hw->disable_polarity_correction == 1)
125062306a36Sopenharmony_ci		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
125162306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
125262306a36Sopenharmony_ci	if (ret_val)
125362306a36Sopenharmony_ci		return ret_val;
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci	if (hw->phy_revision < M88E1011_I_REV_4) {
125662306a36Sopenharmony_ci		/* Force TX_CLK in the Extended PHY Specific Control Register
125762306a36Sopenharmony_ci		 * to 25MHz clock.
125862306a36Sopenharmony_ci		 */
125962306a36Sopenharmony_ci		ret_val =
126062306a36Sopenharmony_ci		    e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
126162306a36Sopenharmony_ci				       &phy_data);
126262306a36Sopenharmony_ci		if (ret_val)
126362306a36Sopenharmony_ci			return ret_val;
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci		phy_data |= M88E1000_EPSCR_TX_CLK_25;
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci		if ((hw->phy_revision == E1000_REVISION_2) &&
126862306a36Sopenharmony_ci		    (hw->phy_id == M88E1111_I_PHY_ID)) {
126962306a36Sopenharmony_ci			/* Vidalia Phy, set the downshift counter to 5x */
127062306a36Sopenharmony_ci			phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK);
127162306a36Sopenharmony_ci			phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
127262306a36Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw,
127362306a36Sopenharmony_ci						      M88E1000_EXT_PHY_SPEC_CTRL,
127462306a36Sopenharmony_ci						      phy_data);
127562306a36Sopenharmony_ci			if (ret_val)
127662306a36Sopenharmony_ci				return ret_val;
127762306a36Sopenharmony_ci		} else {
127862306a36Sopenharmony_ci			/* Configure Master and Slave downshift values */
127962306a36Sopenharmony_ci			phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
128062306a36Sopenharmony_ci				      M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
128162306a36Sopenharmony_ci			phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
128262306a36Sopenharmony_ci				     M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
128362306a36Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw,
128462306a36Sopenharmony_ci						      M88E1000_EXT_PHY_SPEC_CTRL,
128562306a36Sopenharmony_ci						      phy_data);
128662306a36Sopenharmony_ci			if (ret_val)
128762306a36Sopenharmony_ci				return ret_val;
128862306a36Sopenharmony_ci		}
128962306a36Sopenharmony_ci	}
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci	/* SW Reset the PHY so all changes take effect */
129262306a36Sopenharmony_ci	ret_val = e1000_phy_reset(hw);
129362306a36Sopenharmony_ci	if (ret_val) {
129462306a36Sopenharmony_ci		e_dbg("Error Resetting the PHY\n");
129562306a36Sopenharmony_ci		return ret_val;
129662306a36Sopenharmony_ci	}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	return E1000_SUCCESS;
129962306a36Sopenharmony_ci}
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci/**
130262306a36Sopenharmony_ci * e1000_copper_link_autoneg - setup auto-neg
130362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
130462306a36Sopenharmony_ci *
130562306a36Sopenharmony_ci * Setup auto-negotiation and flow control advertisements,
130662306a36Sopenharmony_ci * and then perform auto-negotiation.
130762306a36Sopenharmony_ci */
130862306a36Sopenharmony_cistatic s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
130962306a36Sopenharmony_ci{
131062306a36Sopenharmony_ci	s32 ret_val;
131162306a36Sopenharmony_ci	u16 phy_data;
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ci	/* Perform some bounds checking on the hw->autoneg_advertised
131462306a36Sopenharmony_ci	 * parameter.  If this variable is zero, then set it to the default.
131562306a36Sopenharmony_ci	 */
131662306a36Sopenharmony_ci	hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	/* If autoneg_advertised is zero, we assume it was not defaulted
131962306a36Sopenharmony_ci	 * by the calling code so we set to advertise full capability.
132062306a36Sopenharmony_ci	 */
132162306a36Sopenharmony_ci	if (hw->autoneg_advertised == 0)
132262306a36Sopenharmony_ci		hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	/* IFE/RTL8201N PHY only supports 10/100 */
132562306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_8201)
132662306a36Sopenharmony_ci		hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL;
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	e_dbg("Reconfiguring auto-neg advertisement params\n");
132962306a36Sopenharmony_ci	ret_val = e1000_phy_setup_autoneg(hw);
133062306a36Sopenharmony_ci	if (ret_val) {
133162306a36Sopenharmony_ci		e_dbg("Error Setting up Auto-Negotiation\n");
133262306a36Sopenharmony_ci		return ret_val;
133362306a36Sopenharmony_ci	}
133462306a36Sopenharmony_ci	e_dbg("Restarting Auto-Neg\n");
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	/* Restart auto-negotiation by setting the Auto Neg Enable bit and
133762306a36Sopenharmony_ci	 * the Auto Neg Restart bit in the PHY control register.
133862306a36Sopenharmony_ci	 */
133962306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
134062306a36Sopenharmony_ci	if (ret_val)
134162306a36Sopenharmony_ci		return ret_val;
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
134462306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
134562306a36Sopenharmony_ci	if (ret_val)
134662306a36Sopenharmony_ci		return ret_val;
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	/* Does the user want to wait for Auto-Neg to complete here, or
134962306a36Sopenharmony_ci	 * check at a later time (for example, callback routine).
135062306a36Sopenharmony_ci	 */
135162306a36Sopenharmony_ci	if (hw->wait_autoneg_complete) {
135262306a36Sopenharmony_ci		ret_val = e1000_wait_autoneg(hw);
135362306a36Sopenharmony_ci		if (ret_val) {
135462306a36Sopenharmony_ci			e_dbg
135562306a36Sopenharmony_ci			    ("Error while waiting for autoneg to complete\n");
135662306a36Sopenharmony_ci			return ret_val;
135762306a36Sopenharmony_ci		}
135862306a36Sopenharmony_ci	}
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	hw->get_link_status = true;
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci	return E1000_SUCCESS;
136362306a36Sopenharmony_ci}
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci/**
136662306a36Sopenharmony_ci * e1000_copper_link_postconfig - post link setup
136762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
136862306a36Sopenharmony_ci *
136962306a36Sopenharmony_ci * Config the MAC and the PHY after link is up.
137062306a36Sopenharmony_ci *   1) Set up the MAC to the current PHY speed/duplex
137162306a36Sopenharmony_ci *      if we are on 82543.  If we
137262306a36Sopenharmony_ci *      are on newer silicon, we only need to configure
137362306a36Sopenharmony_ci *      collision distance in the Transmit Control Register.
137462306a36Sopenharmony_ci *   2) Set up flow control on the MAC to that established with
137562306a36Sopenharmony_ci *      the link partner.
137662306a36Sopenharmony_ci *   3) Config DSP to improve Gigabit link quality for some PHY revisions.
137762306a36Sopenharmony_ci */
137862306a36Sopenharmony_cistatic s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
137962306a36Sopenharmony_ci{
138062306a36Sopenharmony_ci	s32 ret_val;
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) {
138362306a36Sopenharmony_ci		e1000_config_collision_dist(hw);
138462306a36Sopenharmony_ci	} else {
138562306a36Sopenharmony_ci		ret_val = e1000_config_mac_to_phy(hw);
138662306a36Sopenharmony_ci		if (ret_val) {
138762306a36Sopenharmony_ci			e_dbg("Error configuring MAC to PHY settings\n");
138862306a36Sopenharmony_ci			return ret_val;
138962306a36Sopenharmony_ci		}
139062306a36Sopenharmony_ci	}
139162306a36Sopenharmony_ci	ret_val = e1000_config_fc_after_link_up(hw);
139262306a36Sopenharmony_ci	if (ret_val) {
139362306a36Sopenharmony_ci		e_dbg("Error Configuring Flow Control\n");
139462306a36Sopenharmony_ci		return ret_val;
139562306a36Sopenharmony_ci	}
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	/* Config DSP to improve Giga link quality */
139862306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp) {
139962306a36Sopenharmony_ci		ret_val = e1000_config_dsp_after_link_change(hw, true);
140062306a36Sopenharmony_ci		if (ret_val) {
140162306a36Sopenharmony_ci			e_dbg("Error Configuring DSP after link up\n");
140262306a36Sopenharmony_ci			return ret_val;
140362306a36Sopenharmony_ci		}
140462306a36Sopenharmony_ci	}
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci	return E1000_SUCCESS;
140762306a36Sopenharmony_ci}
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci/**
141062306a36Sopenharmony_ci * e1000_setup_copper_link - phy/speed/duplex setting
141162306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
141262306a36Sopenharmony_ci *
141362306a36Sopenharmony_ci * Detects which PHY is present and sets up the speed and duplex
141462306a36Sopenharmony_ci */
141562306a36Sopenharmony_cistatic s32 e1000_setup_copper_link(struct e1000_hw *hw)
141662306a36Sopenharmony_ci{
141762306a36Sopenharmony_ci	s32 ret_val;
141862306a36Sopenharmony_ci	u16 i;
141962306a36Sopenharmony_ci	u16 phy_data;
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	/* Check if it is a valid PHY and set PHY mode if necessary. */
142262306a36Sopenharmony_ci	ret_val = e1000_copper_link_preconfig(hw);
142362306a36Sopenharmony_ci	if (ret_val)
142462306a36Sopenharmony_ci		return ret_val;
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp) {
142762306a36Sopenharmony_ci		ret_val = e1000_copper_link_igp_setup(hw);
142862306a36Sopenharmony_ci		if (ret_val)
142962306a36Sopenharmony_ci			return ret_val;
143062306a36Sopenharmony_ci	} else if (hw->phy_type == e1000_phy_m88) {
143162306a36Sopenharmony_ci		ret_val = e1000_copper_link_mgp_setup(hw);
143262306a36Sopenharmony_ci		if (ret_val)
143362306a36Sopenharmony_ci			return ret_val;
143462306a36Sopenharmony_ci	} else {
143562306a36Sopenharmony_ci		ret_val = gbe_dhg_phy_setup(hw);
143662306a36Sopenharmony_ci		if (ret_val) {
143762306a36Sopenharmony_ci			e_dbg("gbe_dhg_phy_setup failed!\n");
143862306a36Sopenharmony_ci			return ret_val;
143962306a36Sopenharmony_ci		}
144062306a36Sopenharmony_ci	}
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci	if (hw->autoneg) {
144362306a36Sopenharmony_ci		/* Setup autoneg and flow control advertisement
144462306a36Sopenharmony_ci		 * and perform autonegotiation
144562306a36Sopenharmony_ci		 */
144662306a36Sopenharmony_ci		ret_val = e1000_copper_link_autoneg(hw);
144762306a36Sopenharmony_ci		if (ret_val)
144862306a36Sopenharmony_ci			return ret_val;
144962306a36Sopenharmony_ci	} else {
145062306a36Sopenharmony_ci		/* PHY will be set to 10H, 10F, 100H,or 100F
145162306a36Sopenharmony_ci		 * depending on value from forced_speed_duplex.
145262306a36Sopenharmony_ci		 */
145362306a36Sopenharmony_ci		e_dbg("Forcing speed and duplex\n");
145462306a36Sopenharmony_ci		ret_val = e1000_phy_force_speed_duplex(hw);
145562306a36Sopenharmony_ci		if (ret_val) {
145662306a36Sopenharmony_ci			e_dbg("Error Forcing Speed and Duplex\n");
145762306a36Sopenharmony_ci			return ret_val;
145862306a36Sopenharmony_ci		}
145962306a36Sopenharmony_ci	}
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	/* Check link status. Wait up to 100 microseconds for link to become
146262306a36Sopenharmony_ci	 * valid.
146362306a36Sopenharmony_ci	 */
146462306a36Sopenharmony_ci	for (i = 0; i < 10; i++) {
146562306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
146662306a36Sopenharmony_ci		if (ret_val)
146762306a36Sopenharmony_ci			return ret_val;
146862306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
146962306a36Sopenharmony_ci		if (ret_val)
147062306a36Sopenharmony_ci			return ret_val;
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_ci		if (phy_data & MII_SR_LINK_STATUS) {
147362306a36Sopenharmony_ci			/* Config the MAC and PHY after link is up */
147462306a36Sopenharmony_ci			ret_val = e1000_copper_link_postconfig(hw);
147562306a36Sopenharmony_ci			if (ret_val)
147662306a36Sopenharmony_ci				return ret_val;
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci			e_dbg("Valid link established!!!\n");
147962306a36Sopenharmony_ci			return E1000_SUCCESS;
148062306a36Sopenharmony_ci		}
148162306a36Sopenharmony_ci		udelay(10);
148262306a36Sopenharmony_ci	}
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci	e_dbg("Unable to establish link!!!\n");
148562306a36Sopenharmony_ci	return E1000_SUCCESS;
148662306a36Sopenharmony_ci}
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci/**
148962306a36Sopenharmony_ci * e1000_phy_setup_autoneg - phy settings
149062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
149162306a36Sopenharmony_ci *
149262306a36Sopenharmony_ci * Configures PHY autoneg and flow control advertisement settings
149362306a36Sopenharmony_ci */
149462306a36Sopenharmony_cis32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
149562306a36Sopenharmony_ci{
149662306a36Sopenharmony_ci	s32 ret_val;
149762306a36Sopenharmony_ci	u16 mii_autoneg_adv_reg;
149862306a36Sopenharmony_ci	u16 mii_1000t_ctrl_reg;
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
150162306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
150262306a36Sopenharmony_ci	if (ret_val)
150362306a36Sopenharmony_ci		return ret_val;
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	/* Read the MII 1000Base-T Control Register (Address 9). */
150662306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
150762306a36Sopenharmony_ci	if (ret_val)
150862306a36Sopenharmony_ci		return ret_val;
150962306a36Sopenharmony_ci	else if (hw->phy_type == e1000_phy_8201)
151062306a36Sopenharmony_ci		mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	/* Need to parse both autoneg_advertised and fc and set up
151362306a36Sopenharmony_ci	 * the appropriate PHY registers.  First we will parse for
151462306a36Sopenharmony_ci	 * autoneg_advertised software override.  Since we can advertise
151562306a36Sopenharmony_ci	 * a plethora of combinations, we need to check each bit
151662306a36Sopenharmony_ci	 * individually.
151762306a36Sopenharmony_ci	 */
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
152062306a36Sopenharmony_ci	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
152162306a36Sopenharmony_ci	 * the  1000Base-T Control Register (Address 9).
152262306a36Sopenharmony_ci	 */
152362306a36Sopenharmony_ci	mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
152462306a36Sopenharmony_ci	mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	e_dbg("autoneg_advertised %x\n", hw->autoneg_advertised);
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci	/* Do we want to advertise 10 Mb Half Duplex? */
152962306a36Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_10_HALF) {
153062306a36Sopenharmony_ci		e_dbg("Advertise 10mb Half duplex\n");
153162306a36Sopenharmony_ci		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
153262306a36Sopenharmony_ci	}
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_ci	/* Do we want to advertise 10 Mb Full Duplex? */
153562306a36Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_10_FULL) {
153662306a36Sopenharmony_ci		e_dbg("Advertise 10mb Full duplex\n");
153762306a36Sopenharmony_ci		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
153862306a36Sopenharmony_ci	}
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	/* Do we want to advertise 100 Mb Half Duplex? */
154162306a36Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_100_HALF) {
154262306a36Sopenharmony_ci		e_dbg("Advertise 100mb Half duplex\n");
154362306a36Sopenharmony_ci		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
154462306a36Sopenharmony_ci	}
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	/* Do we want to advertise 100 Mb Full Duplex? */
154762306a36Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_100_FULL) {
154862306a36Sopenharmony_ci		e_dbg("Advertise 100mb Full duplex\n");
154962306a36Sopenharmony_ci		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
155062306a36Sopenharmony_ci	}
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_ci	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
155362306a36Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_1000_HALF) {
155462306a36Sopenharmony_ci		e_dbg
155562306a36Sopenharmony_ci		    ("Advertise 1000mb Half duplex requested, request denied!\n");
155662306a36Sopenharmony_ci	}
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci	/* Do we want to advertise 1000 Mb Full Duplex? */
155962306a36Sopenharmony_ci	if (hw->autoneg_advertised & ADVERTISE_1000_FULL) {
156062306a36Sopenharmony_ci		e_dbg("Advertise 1000mb Full duplex\n");
156162306a36Sopenharmony_ci		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
156262306a36Sopenharmony_ci	}
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	/* Check for a software override of the flow control settings, and
156562306a36Sopenharmony_ci	 * setup the PHY advertisement registers accordingly.  If
156662306a36Sopenharmony_ci	 * auto-negotiation is enabled, then software will have to set the
156762306a36Sopenharmony_ci	 * "PAUSE" bits to the correct value in the Auto-Negotiation
156862306a36Sopenharmony_ci	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start
156962306a36Sopenharmony_ci	 * auto-negotiation.
157062306a36Sopenharmony_ci	 *
157162306a36Sopenharmony_ci	 * The possible values of the "fc" parameter are:
157262306a36Sopenharmony_ci	 *      0:  Flow control is completely disabled
157362306a36Sopenharmony_ci	 *      1:  Rx flow control is enabled (we can receive pause frames
157462306a36Sopenharmony_ci	 *          but not send pause frames).
157562306a36Sopenharmony_ci	 *      2:  Tx flow control is enabled (we can send pause frames
157662306a36Sopenharmony_ci	 *          but we do not support receiving pause frames).
157762306a36Sopenharmony_ci	 *      3:  Both Rx and TX flow control (symmetric) are enabled.
157862306a36Sopenharmony_ci	 *  other:  No software override.  The flow control configuration
157962306a36Sopenharmony_ci	 *          in the EEPROM is used.
158062306a36Sopenharmony_ci	 */
158162306a36Sopenharmony_ci	switch (hw->fc) {
158262306a36Sopenharmony_ci	case E1000_FC_NONE:	/* 0 */
158362306a36Sopenharmony_ci		/* Flow control (RX & TX) is completely disabled by a
158462306a36Sopenharmony_ci		 * software over-ride.
158562306a36Sopenharmony_ci		 */
158662306a36Sopenharmony_ci		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
158762306a36Sopenharmony_ci		break;
158862306a36Sopenharmony_ci	case E1000_FC_RX_PAUSE:	/* 1 */
158962306a36Sopenharmony_ci		/* RX Flow control is enabled, and TX Flow control is
159062306a36Sopenharmony_ci		 * disabled, by a software over-ride.
159162306a36Sopenharmony_ci		 */
159262306a36Sopenharmony_ci		/* Since there really isn't a way to advertise that we are
159362306a36Sopenharmony_ci		 * capable of RX Pause ONLY, we will advertise that we
159462306a36Sopenharmony_ci		 * support both symmetric and asymmetric RX PAUSE.  Later
159562306a36Sopenharmony_ci		 * (in e1000_config_fc_after_link_up) we will disable the
159662306a36Sopenharmony_ci		 * hw's ability to send PAUSE frames.
159762306a36Sopenharmony_ci		 */
159862306a36Sopenharmony_ci		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
159962306a36Sopenharmony_ci		break;
160062306a36Sopenharmony_ci	case E1000_FC_TX_PAUSE:	/* 2 */
160162306a36Sopenharmony_ci		/* TX Flow control is enabled, and RX Flow control is
160262306a36Sopenharmony_ci		 * disabled, by a software over-ride.
160362306a36Sopenharmony_ci		 */
160462306a36Sopenharmony_ci		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
160562306a36Sopenharmony_ci		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
160662306a36Sopenharmony_ci		break;
160762306a36Sopenharmony_ci	case E1000_FC_FULL:	/* 3 */
160862306a36Sopenharmony_ci		/* Flow control (both RX and TX) is enabled by a software
160962306a36Sopenharmony_ci		 * over-ride.
161062306a36Sopenharmony_ci		 */
161162306a36Sopenharmony_ci		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
161262306a36Sopenharmony_ci		break;
161362306a36Sopenharmony_ci	default:
161462306a36Sopenharmony_ci		e_dbg("Flow control param set incorrectly\n");
161562306a36Sopenharmony_ci		return -E1000_ERR_CONFIG;
161662306a36Sopenharmony_ci	}
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
161962306a36Sopenharmony_ci	if (ret_val)
162062306a36Sopenharmony_ci		return ret_val;
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci	e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_8201) {
162562306a36Sopenharmony_ci		mii_1000t_ctrl_reg = 0;
162662306a36Sopenharmony_ci	} else {
162762306a36Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
162862306a36Sopenharmony_ci					      mii_1000t_ctrl_reg);
162962306a36Sopenharmony_ci		if (ret_val)
163062306a36Sopenharmony_ci			return ret_val;
163162306a36Sopenharmony_ci	}
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	return E1000_SUCCESS;
163462306a36Sopenharmony_ci}
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci/**
163762306a36Sopenharmony_ci * e1000_phy_force_speed_duplex - force link settings
163862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
163962306a36Sopenharmony_ci *
164062306a36Sopenharmony_ci * Force PHY speed and duplex settings to hw->forced_speed_duplex
164162306a36Sopenharmony_ci */
164262306a36Sopenharmony_cistatic s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
164362306a36Sopenharmony_ci{
164462306a36Sopenharmony_ci	u32 ctrl;
164562306a36Sopenharmony_ci	s32 ret_val;
164662306a36Sopenharmony_ci	u16 mii_ctrl_reg;
164762306a36Sopenharmony_ci	u16 mii_status_reg;
164862306a36Sopenharmony_ci	u16 phy_data;
164962306a36Sopenharmony_ci	u16 i;
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	/* Turn off Flow control if we are forcing speed and duplex. */
165262306a36Sopenharmony_ci	hw->fc = E1000_FC_NONE;
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	e_dbg("hw->fc = %d\n", hw->fc);
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci	/* Read the Device Control Register. */
165762306a36Sopenharmony_ci	ctrl = er32(CTRL);
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_ci	/* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
166062306a36Sopenharmony_ci	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
166162306a36Sopenharmony_ci	ctrl &= ~(DEVICE_SPEED_MASK);
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci	/* Clear the Auto Speed Detect Enable bit. */
166462306a36Sopenharmony_ci	ctrl &= ~E1000_CTRL_ASDE;
166562306a36Sopenharmony_ci
166662306a36Sopenharmony_ci	/* Read the MII Control Register. */
166762306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg);
166862306a36Sopenharmony_ci	if (ret_val)
166962306a36Sopenharmony_ci		return ret_val;
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_ci	/* We need to disable autoneg in order to force link and duplex. */
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	/* Are we forcing Full or Half Duplex? */
167662306a36Sopenharmony_ci	if (hw->forced_speed_duplex == e1000_100_full ||
167762306a36Sopenharmony_ci	    hw->forced_speed_duplex == e1000_10_full) {
167862306a36Sopenharmony_ci		/* We want to force full duplex so we SET the full duplex bits
167962306a36Sopenharmony_ci		 * in the Device and MII Control Registers.
168062306a36Sopenharmony_ci		 */
168162306a36Sopenharmony_ci		ctrl |= E1000_CTRL_FD;
168262306a36Sopenharmony_ci		mii_ctrl_reg |= MII_CR_FULL_DUPLEX;
168362306a36Sopenharmony_ci		e_dbg("Full Duplex\n");
168462306a36Sopenharmony_ci	} else {
168562306a36Sopenharmony_ci		/* We want to force half duplex so we CLEAR the full duplex bits
168662306a36Sopenharmony_ci		 * in the Device and MII Control Registers.
168762306a36Sopenharmony_ci		 */
168862306a36Sopenharmony_ci		ctrl &= ~E1000_CTRL_FD;
168962306a36Sopenharmony_ci		mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX;
169062306a36Sopenharmony_ci		e_dbg("Half Duplex\n");
169162306a36Sopenharmony_ci	}
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_ci	/* Are we forcing 100Mbps??? */
169462306a36Sopenharmony_ci	if (hw->forced_speed_duplex == e1000_100_full ||
169562306a36Sopenharmony_ci	    hw->forced_speed_duplex == e1000_100_half) {
169662306a36Sopenharmony_ci		/* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */
169762306a36Sopenharmony_ci		ctrl |= E1000_CTRL_SPD_100;
169862306a36Sopenharmony_ci		mii_ctrl_reg |= MII_CR_SPEED_100;
169962306a36Sopenharmony_ci		mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
170062306a36Sopenharmony_ci		e_dbg("Forcing 100mb ");
170162306a36Sopenharmony_ci	} else {
170262306a36Sopenharmony_ci		/* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */
170362306a36Sopenharmony_ci		ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
170462306a36Sopenharmony_ci		mii_ctrl_reg |= MII_CR_SPEED_10;
170562306a36Sopenharmony_ci		mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
170662306a36Sopenharmony_ci		e_dbg("Forcing 10mb ");
170762306a36Sopenharmony_ci	}
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	e1000_config_collision_dist(hw);
171062306a36Sopenharmony_ci
171162306a36Sopenharmony_ci	/* Write the configured values back to the Device Control Reg. */
171262306a36Sopenharmony_ci	ew32(CTRL, ctrl);
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_m88) {
171562306a36Sopenharmony_ci		ret_val =
171662306a36Sopenharmony_ci		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
171762306a36Sopenharmony_ci		if (ret_val)
171862306a36Sopenharmony_ci			return ret_val;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci		/* Clear Auto-Crossover to force MDI manually. M88E1000 requires
172162306a36Sopenharmony_ci		 * MDI forced whenever speed are duplex are forced.
172262306a36Sopenharmony_ci		 */
172362306a36Sopenharmony_ci		phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
172462306a36Sopenharmony_ci		ret_val =
172562306a36Sopenharmony_ci		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
172662306a36Sopenharmony_ci		if (ret_val)
172762306a36Sopenharmony_ci			return ret_val;
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci		e_dbg("M88E1000 PSCR: %x\n", phy_data);
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci		/* Need to reset the PHY or these changes will be ignored */
173262306a36Sopenharmony_ci		mii_ctrl_reg |= MII_CR_RESET;
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci		/* Disable MDI-X support for 10/100 */
173562306a36Sopenharmony_ci	} else {
173662306a36Sopenharmony_ci		/* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
173762306a36Sopenharmony_ci		 * forced whenever speed or duplex are forced.
173862306a36Sopenharmony_ci		 */
173962306a36Sopenharmony_ci		ret_val =
174062306a36Sopenharmony_ci		    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
174162306a36Sopenharmony_ci		if (ret_val)
174262306a36Sopenharmony_ci			return ret_val;
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci		phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
174562306a36Sopenharmony_ci		phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
174662306a36Sopenharmony_ci
174762306a36Sopenharmony_ci		ret_val =
174862306a36Sopenharmony_ci		    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
174962306a36Sopenharmony_ci		if (ret_val)
175062306a36Sopenharmony_ci			return ret_val;
175162306a36Sopenharmony_ci	}
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	/* Write back the modified PHY MII control register. */
175462306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg);
175562306a36Sopenharmony_ci	if (ret_val)
175662306a36Sopenharmony_ci		return ret_val;
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_ci	udelay(1);
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	/* The wait_autoneg_complete flag may be a little misleading here.
176162306a36Sopenharmony_ci	 * Since we are forcing speed and duplex, Auto-Neg is not enabled.
176262306a36Sopenharmony_ci	 * But we do want to delay for a period while forcing only so we
176362306a36Sopenharmony_ci	 * don't generate false No Link messages.  So we will wait here
176462306a36Sopenharmony_ci	 * only if the user has set wait_autoneg_complete to 1, which is
176562306a36Sopenharmony_ci	 * the default.
176662306a36Sopenharmony_ci	 */
176762306a36Sopenharmony_ci	if (hw->wait_autoneg_complete) {
176862306a36Sopenharmony_ci		/* We will wait for autoneg to complete. */
176962306a36Sopenharmony_ci		e_dbg("Waiting for forced speed/duplex link.\n");
177062306a36Sopenharmony_ci		mii_status_reg = 0;
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_ci		/* Wait for autoneg to complete or 4.5 seconds to expire */
177362306a36Sopenharmony_ci		for (i = PHY_FORCE_TIME; i > 0; i--) {
177462306a36Sopenharmony_ci			/* Read the MII Status Register and wait for Auto-Neg
177562306a36Sopenharmony_ci			 * Complete bit to be set.
177662306a36Sopenharmony_ci			 */
177762306a36Sopenharmony_ci			ret_val =
177862306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
177962306a36Sopenharmony_ci			if (ret_val)
178062306a36Sopenharmony_ci				return ret_val;
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci			ret_val =
178362306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
178462306a36Sopenharmony_ci			if (ret_val)
178562306a36Sopenharmony_ci				return ret_val;
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci			if (mii_status_reg & MII_SR_LINK_STATUS)
178862306a36Sopenharmony_ci				break;
178962306a36Sopenharmony_ci			msleep(100);
179062306a36Sopenharmony_ci		}
179162306a36Sopenharmony_ci		if ((i == 0) && (hw->phy_type == e1000_phy_m88)) {
179262306a36Sopenharmony_ci			/* We didn't get link.  Reset the DSP and wait again
179362306a36Sopenharmony_ci			 * for link.
179462306a36Sopenharmony_ci			 */
179562306a36Sopenharmony_ci			ret_val = e1000_phy_reset_dsp(hw);
179662306a36Sopenharmony_ci			if (ret_val) {
179762306a36Sopenharmony_ci				e_dbg("Error Resetting PHY DSP\n");
179862306a36Sopenharmony_ci				return ret_val;
179962306a36Sopenharmony_ci			}
180062306a36Sopenharmony_ci		}
180162306a36Sopenharmony_ci		/* This loop will early-out if the link condition has been
180262306a36Sopenharmony_ci		 * met
180362306a36Sopenharmony_ci		 */
180462306a36Sopenharmony_ci		for (i = PHY_FORCE_TIME; i > 0; i--) {
180562306a36Sopenharmony_ci			if (mii_status_reg & MII_SR_LINK_STATUS)
180662306a36Sopenharmony_ci				break;
180762306a36Sopenharmony_ci			msleep(100);
180862306a36Sopenharmony_ci			/* Read the MII Status Register and wait for Auto-Neg
180962306a36Sopenharmony_ci			 * Complete bit to be set.
181062306a36Sopenharmony_ci			 */
181162306a36Sopenharmony_ci			ret_val =
181262306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
181362306a36Sopenharmony_ci			if (ret_val)
181462306a36Sopenharmony_ci				return ret_val;
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci			ret_val =
181762306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
181862306a36Sopenharmony_ci			if (ret_val)
181962306a36Sopenharmony_ci				return ret_val;
182062306a36Sopenharmony_ci		}
182162306a36Sopenharmony_ci	}
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_m88) {
182462306a36Sopenharmony_ci		/* Because we reset the PHY above, we need to re-force TX_CLK in
182562306a36Sopenharmony_ci		 * the Extended PHY Specific Control Register to 25MHz clock.
182662306a36Sopenharmony_ci		 * This value defaults back to a 2.5MHz clock when the PHY is
182762306a36Sopenharmony_ci		 * reset.
182862306a36Sopenharmony_ci		 */
182962306a36Sopenharmony_ci		ret_val =
183062306a36Sopenharmony_ci		    e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
183162306a36Sopenharmony_ci				       &phy_data);
183262306a36Sopenharmony_ci		if (ret_val)
183362306a36Sopenharmony_ci			return ret_val;
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci		phy_data |= M88E1000_EPSCR_TX_CLK_25;
183662306a36Sopenharmony_ci		ret_val =
183762306a36Sopenharmony_ci		    e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
183862306a36Sopenharmony_ci					phy_data);
183962306a36Sopenharmony_ci		if (ret_val)
184062306a36Sopenharmony_ci			return ret_val;
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_ci		/* In addition, because of the s/w reset above, we need to
184362306a36Sopenharmony_ci		 * enable CRS on Tx.  This must be set for both full and half
184462306a36Sopenharmony_ci		 * duplex operation.
184562306a36Sopenharmony_ci		 */
184662306a36Sopenharmony_ci		ret_val =
184762306a36Sopenharmony_ci		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
184862306a36Sopenharmony_ci		if (ret_val)
184962306a36Sopenharmony_ci			return ret_val;
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_ci		phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
185262306a36Sopenharmony_ci		ret_val =
185362306a36Sopenharmony_ci		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
185462306a36Sopenharmony_ci		if (ret_val)
185562306a36Sopenharmony_ci			return ret_val;
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci		if ((hw->mac_type == e1000_82544 ||
185862306a36Sopenharmony_ci		     hw->mac_type == e1000_82543) &&
185962306a36Sopenharmony_ci		    (!hw->autoneg) &&
186062306a36Sopenharmony_ci		    (hw->forced_speed_duplex == e1000_10_full ||
186162306a36Sopenharmony_ci		     hw->forced_speed_duplex == e1000_10_half)) {
186262306a36Sopenharmony_ci			ret_val = e1000_polarity_reversal_workaround(hw);
186362306a36Sopenharmony_ci			if (ret_val)
186462306a36Sopenharmony_ci				return ret_val;
186562306a36Sopenharmony_ci		}
186662306a36Sopenharmony_ci	}
186762306a36Sopenharmony_ci	return E1000_SUCCESS;
186862306a36Sopenharmony_ci}
186962306a36Sopenharmony_ci
187062306a36Sopenharmony_ci/**
187162306a36Sopenharmony_ci * e1000_config_collision_dist - set collision distance register
187262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
187362306a36Sopenharmony_ci *
187462306a36Sopenharmony_ci * Sets the collision distance in the Transmit Control register.
187562306a36Sopenharmony_ci * Link should have been established previously. Reads the speed and duplex
187662306a36Sopenharmony_ci * information from the Device Status register.
187762306a36Sopenharmony_ci */
187862306a36Sopenharmony_civoid e1000_config_collision_dist(struct e1000_hw *hw)
187962306a36Sopenharmony_ci{
188062306a36Sopenharmony_ci	u32 tctl, coll_dist;
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci	if (hw->mac_type < e1000_82543)
188362306a36Sopenharmony_ci		coll_dist = E1000_COLLISION_DISTANCE_82542;
188462306a36Sopenharmony_ci	else
188562306a36Sopenharmony_ci		coll_dist = E1000_COLLISION_DISTANCE;
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	tctl = er32(TCTL);
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci	tctl &= ~E1000_TCTL_COLD;
189062306a36Sopenharmony_ci	tctl |= coll_dist << E1000_COLD_SHIFT;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	ew32(TCTL, tctl);
189362306a36Sopenharmony_ci	E1000_WRITE_FLUSH();
189462306a36Sopenharmony_ci}
189562306a36Sopenharmony_ci
189662306a36Sopenharmony_ci/**
189762306a36Sopenharmony_ci * e1000_config_mac_to_phy - sync phy and mac settings
189862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
189962306a36Sopenharmony_ci *
190062306a36Sopenharmony_ci * Sets MAC speed and duplex settings to reflect the those in the PHY
190162306a36Sopenharmony_ci * The contents of the PHY register containing the needed information need to
190262306a36Sopenharmony_ci * be passed in.
190362306a36Sopenharmony_ci */
190462306a36Sopenharmony_cistatic s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
190562306a36Sopenharmony_ci{
190662306a36Sopenharmony_ci	u32 ctrl;
190762306a36Sopenharmony_ci	s32 ret_val;
190862306a36Sopenharmony_ci	u16 phy_data;
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	/* 82544 or newer MAC, Auto Speed Detection takes care of
191162306a36Sopenharmony_ci	 * MAC speed/duplex configuration.
191262306a36Sopenharmony_ci	 */
191362306a36Sopenharmony_ci	if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100))
191462306a36Sopenharmony_ci		return E1000_SUCCESS;
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci	/* Read the Device Control Register and set the bits to Force Speed
191762306a36Sopenharmony_ci	 * and Duplex.
191862306a36Sopenharmony_ci	 */
191962306a36Sopenharmony_ci	ctrl = er32(CTRL);
192062306a36Sopenharmony_ci	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
192162306a36Sopenharmony_ci	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
192262306a36Sopenharmony_ci
192362306a36Sopenharmony_ci	switch (hw->phy_type) {
192462306a36Sopenharmony_ci	case e1000_phy_8201:
192562306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
192662306a36Sopenharmony_ci		if (ret_val)
192762306a36Sopenharmony_ci			return ret_val;
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci		if (phy_data & RTL_PHY_CTRL_FD)
193062306a36Sopenharmony_ci			ctrl |= E1000_CTRL_FD;
193162306a36Sopenharmony_ci		else
193262306a36Sopenharmony_ci			ctrl &= ~E1000_CTRL_FD;
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci		if (phy_data & RTL_PHY_CTRL_SPD_100)
193562306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SPD_100;
193662306a36Sopenharmony_ci		else
193762306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SPD_10;
193862306a36Sopenharmony_ci
193962306a36Sopenharmony_ci		e1000_config_collision_dist(hw);
194062306a36Sopenharmony_ci		break;
194162306a36Sopenharmony_ci	default:
194262306a36Sopenharmony_ci		/* Set up duplex in the Device Control and Transmit Control
194362306a36Sopenharmony_ci		 * registers depending on negotiated values.
194462306a36Sopenharmony_ci		 */
194562306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
194662306a36Sopenharmony_ci					     &phy_data);
194762306a36Sopenharmony_ci		if (ret_val)
194862306a36Sopenharmony_ci			return ret_val;
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci		if (phy_data & M88E1000_PSSR_DPLX)
195162306a36Sopenharmony_ci			ctrl |= E1000_CTRL_FD;
195262306a36Sopenharmony_ci		else
195362306a36Sopenharmony_ci			ctrl &= ~E1000_CTRL_FD;
195462306a36Sopenharmony_ci
195562306a36Sopenharmony_ci		e1000_config_collision_dist(hw);
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ci		/* Set up speed in the Device Control register depending on
195862306a36Sopenharmony_ci		 * negotiated values.
195962306a36Sopenharmony_ci		 */
196062306a36Sopenharmony_ci		if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
196162306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SPD_1000;
196262306a36Sopenharmony_ci		else if ((phy_data & M88E1000_PSSR_SPEED) ==
196362306a36Sopenharmony_ci			 M88E1000_PSSR_100MBS)
196462306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SPD_100;
196562306a36Sopenharmony_ci	}
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	/* Write the configured values back to the Device Control Reg. */
196862306a36Sopenharmony_ci	ew32(CTRL, ctrl);
196962306a36Sopenharmony_ci	return E1000_SUCCESS;
197062306a36Sopenharmony_ci}
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci/**
197362306a36Sopenharmony_ci * e1000_force_mac_fc - force flow control settings
197462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
197562306a36Sopenharmony_ci *
197662306a36Sopenharmony_ci * Forces the MAC's flow control settings.
197762306a36Sopenharmony_ci * Sets the TFCE and RFCE bits in the device control register to reflect
197862306a36Sopenharmony_ci * the adapter settings. TFCE and RFCE need to be explicitly set by
197962306a36Sopenharmony_ci * software when a Copper PHY is used because autonegotiation is managed
198062306a36Sopenharmony_ci * by the PHY rather than the MAC. Software must also configure these
198162306a36Sopenharmony_ci * bits when link is forced on a fiber connection.
198262306a36Sopenharmony_ci */
198362306a36Sopenharmony_cis32 e1000_force_mac_fc(struct e1000_hw *hw)
198462306a36Sopenharmony_ci{
198562306a36Sopenharmony_ci	u32 ctrl;
198662306a36Sopenharmony_ci
198762306a36Sopenharmony_ci	/* Get the current configuration of the Device Control Register */
198862306a36Sopenharmony_ci	ctrl = er32(CTRL);
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci	/* Because we didn't get link via the internal auto-negotiation
199162306a36Sopenharmony_ci	 * mechanism (we either forced link or we got link via PHY
199262306a36Sopenharmony_ci	 * auto-neg), we have to manually enable/disable transmit an
199362306a36Sopenharmony_ci	 * receive flow control.
199462306a36Sopenharmony_ci	 *
199562306a36Sopenharmony_ci	 * The "Case" statement below enables/disable flow control
199662306a36Sopenharmony_ci	 * according to the "hw->fc" parameter.
199762306a36Sopenharmony_ci	 *
199862306a36Sopenharmony_ci	 * The possible values of the "fc" parameter are:
199962306a36Sopenharmony_ci	 *      0:  Flow control is completely disabled
200062306a36Sopenharmony_ci	 *      1:  Rx flow control is enabled (we can receive pause
200162306a36Sopenharmony_ci	 *          frames but not send pause frames).
200262306a36Sopenharmony_ci	 *      2:  Tx flow control is enabled (we can send pause frames
200362306a36Sopenharmony_ci	 *          but we do not receive pause frames).
200462306a36Sopenharmony_ci	 *      3:  Both Rx and TX flow control (symmetric) is enabled.
200562306a36Sopenharmony_ci	 *  other:  No other values should be possible at this point.
200662306a36Sopenharmony_ci	 */
200762306a36Sopenharmony_ci
200862306a36Sopenharmony_ci	switch (hw->fc) {
200962306a36Sopenharmony_ci	case E1000_FC_NONE:
201062306a36Sopenharmony_ci		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
201162306a36Sopenharmony_ci		break;
201262306a36Sopenharmony_ci	case E1000_FC_RX_PAUSE:
201362306a36Sopenharmony_ci		ctrl &= (~E1000_CTRL_TFCE);
201462306a36Sopenharmony_ci		ctrl |= E1000_CTRL_RFCE;
201562306a36Sopenharmony_ci		break;
201662306a36Sopenharmony_ci	case E1000_FC_TX_PAUSE:
201762306a36Sopenharmony_ci		ctrl &= (~E1000_CTRL_RFCE);
201862306a36Sopenharmony_ci		ctrl |= E1000_CTRL_TFCE;
201962306a36Sopenharmony_ci		break;
202062306a36Sopenharmony_ci	case E1000_FC_FULL:
202162306a36Sopenharmony_ci		ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
202262306a36Sopenharmony_ci		break;
202362306a36Sopenharmony_ci	default:
202462306a36Sopenharmony_ci		e_dbg("Flow control param set incorrectly\n");
202562306a36Sopenharmony_ci		return -E1000_ERR_CONFIG;
202662306a36Sopenharmony_ci	}
202762306a36Sopenharmony_ci
202862306a36Sopenharmony_ci	/* Disable TX Flow Control for 82542 (rev 2.0) */
202962306a36Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0)
203062306a36Sopenharmony_ci		ctrl &= (~E1000_CTRL_TFCE);
203162306a36Sopenharmony_ci
203262306a36Sopenharmony_ci	ew32(CTRL, ctrl);
203362306a36Sopenharmony_ci	return E1000_SUCCESS;
203462306a36Sopenharmony_ci}
203562306a36Sopenharmony_ci
203662306a36Sopenharmony_ci/**
203762306a36Sopenharmony_ci * e1000_config_fc_after_link_up - configure flow control after autoneg
203862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
203962306a36Sopenharmony_ci *
204062306a36Sopenharmony_ci * Configures flow control settings after link is established
204162306a36Sopenharmony_ci * Should be called immediately after a valid link has been established.
204262306a36Sopenharmony_ci * Forces MAC flow control settings if link was forced. When in MII/GMII mode
204362306a36Sopenharmony_ci * and autonegotiation is enabled, the MAC flow control settings will be set
204462306a36Sopenharmony_ci * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
204562306a36Sopenharmony_ci * and RFCE bits will be automatically set to the negotiated flow control mode.
204662306a36Sopenharmony_ci */
204762306a36Sopenharmony_cistatic s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
204862306a36Sopenharmony_ci{
204962306a36Sopenharmony_ci	s32 ret_val;
205062306a36Sopenharmony_ci	u16 mii_status_reg;
205162306a36Sopenharmony_ci	u16 mii_nway_adv_reg;
205262306a36Sopenharmony_ci	u16 mii_nway_lp_ability_reg;
205362306a36Sopenharmony_ci	u16 speed;
205462306a36Sopenharmony_ci	u16 duplex;
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_ci	/* Check for the case where we have fiber media and auto-neg failed
205762306a36Sopenharmony_ci	 * so we had to force link.  In this case, we need to force the
205862306a36Sopenharmony_ci	 * configuration of the MAC to match the "fc" parameter.
205962306a36Sopenharmony_ci	 */
206062306a36Sopenharmony_ci	if (((hw->media_type == e1000_media_type_fiber) &&
206162306a36Sopenharmony_ci	     (hw->autoneg_failed)) ||
206262306a36Sopenharmony_ci	    ((hw->media_type == e1000_media_type_internal_serdes) &&
206362306a36Sopenharmony_ci	     (hw->autoneg_failed)) ||
206462306a36Sopenharmony_ci	    ((hw->media_type == e1000_media_type_copper) &&
206562306a36Sopenharmony_ci	     (!hw->autoneg))) {
206662306a36Sopenharmony_ci		ret_val = e1000_force_mac_fc(hw);
206762306a36Sopenharmony_ci		if (ret_val) {
206862306a36Sopenharmony_ci			e_dbg("Error forcing flow control settings\n");
206962306a36Sopenharmony_ci			return ret_val;
207062306a36Sopenharmony_ci		}
207162306a36Sopenharmony_ci	}
207262306a36Sopenharmony_ci
207362306a36Sopenharmony_ci	/* Check for the case where we have copper media and auto-neg is
207462306a36Sopenharmony_ci	 * enabled.  In this case, we need to check and see if Auto-Neg
207562306a36Sopenharmony_ci	 * has completed, and if so, how the PHY and link partner has
207662306a36Sopenharmony_ci	 * flow control configured.
207762306a36Sopenharmony_ci	 */
207862306a36Sopenharmony_ci	if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) {
207962306a36Sopenharmony_ci		/* Read the MII Status Register and check to see if AutoNeg
208062306a36Sopenharmony_ci		 * has completed.  We read this twice because this reg has
208162306a36Sopenharmony_ci		 * some "sticky" (latched) bits.
208262306a36Sopenharmony_ci		 */
208362306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
208462306a36Sopenharmony_ci		if (ret_val)
208562306a36Sopenharmony_ci			return ret_val;
208662306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
208762306a36Sopenharmony_ci		if (ret_val)
208862306a36Sopenharmony_ci			return ret_val;
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci		if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
209162306a36Sopenharmony_ci			/* The AutoNeg process has completed, so we now need to
209262306a36Sopenharmony_ci			 * read both the Auto Negotiation Advertisement Register
209362306a36Sopenharmony_ci			 * (Address 4) and the Auto_Negotiation Base Page
209462306a36Sopenharmony_ci			 * Ability Register (Address 5) to determine how flow
209562306a36Sopenharmony_ci			 * control was negotiated.
209662306a36Sopenharmony_ci			 */
209762306a36Sopenharmony_ci			ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
209862306a36Sopenharmony_ci						     &mii_nway_adv_reg);
209962306a36Sopenharmony_ci			if (ret_val)
210062306a36Sopenharmony_ci				return ret_val;
210162306a36Sopenharmony_ci			ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
210262306a36Sopenharmony_ci						     &mii_nway_lp_ability_reg);
210362306a36Sopenharmony_ci			if (ret_val)
210462306a36Sopenharmony_ci				return ret_val;
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci			/* Two bits in the Auto Negotiation Advertisement
210762306a36Sopenharmony_ci			 * Register (Address 4) and two bits in the Auto
210862306a36Sopenharmony_ci			 * Negotiation Base Page Ability Register (Address 5)
210962306a36Sopenharmony_ci			 * determine flow control for both the PHY and the link
211062306a36Sopenharmony_ci			 * partner.  The following table, taken out of the IEEE
211162306a36Sopenharmony_ci			 * 802.3ab/D6.0 dated March 25, 1999, describes these
211262306a36Sopenharmony_ci			 * PAUSE resolution bits and how flow control is
211362306a36Sopenharmony_ci			 * determined based upon these settings.
211462306a36Sopenharmony_ci			 * NOTE:  DC = Don't Care
211562306a36Sopenharmony_ci			 *
211662306a36Sopenharmony_ci			 *   LOCAL DEVICE  |   LINK PARTNER
211762306a36Sopenharmony_ci			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
211862306a36Sopenharmony_ci			 *-------|---------|-------|---------|------------------
211962306a36Sopenharmony_ci			 *   0   |    0    |  DC   |   DC    | E1000_FC_NONE
212062306a36Sopenharmony_ci			 *   0   |    1    |   0   |   DC    | E1000_FC_NONE
212162306a36Sopenharmony_ci			 *   0   |    1    |   1   |    0    | E1000_FC_NONE
212262306a36Sopenharmony_ci			 *   0   |    1    |   1   |    1    | E1000_FC_TX_PAUSE
212362306a36Sopenharmony_ci			 *   1   |    0    |   0   |   DC    | E1000_FC_NONE
212462306a36Sopenharmony_ci			 *   1   |   DC    |   1   |   DC    | E1000_FC_FULL
212562306a36Sopenharmony_ci			 *   1   |    1    |   0   |    0    | E1000_FC_NONE
212662306a36Sopenharmony_ci			 *   1   |    1    |   0   |    1    | E1000_FC_RX_PAUSE
212762306a36Sopenharmony_ci			 *
212862306a36Sopenharmony_ci			 */
212962306a36Sopenharmony_ci			/* Are both PAUSE bits set to 1?  If so, this implies
213062306a36Sopenharmony_ci			 * Symmetric Flow Control is enabled at both ends.  The
213162306a36Sopenharmony_ci			 * ASM_DIR bits are irrelevant per the spec.
213262306a36Sopenharmony_ci			 *
213362306a36Sopenharmony_ci			 * For Symmetric Flow Control:
213462306a36Sopenharmony_ci			 *
213562306a36Sopenharmony_ci			 *   LOCAL DEVICE  |   LINK PARTNER
213662306a36Sopenharmony_ci			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
213762306a36Sopenharmony_ci			 *-------|---------|-------|---------|------------------
213862306a36Sopenharmony_ci			 *   1   |   DC    |   1   |   DC    | E1000_FC_FULL
213962306a36Sopenharmony_ci			 *
214062306a36Sopenharmony_ci			 */
214162306a36Sopenharmony_ci			if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
214262306a36Sopenharmony_ci			    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
214362306a36Sopenharmony_ci				/* Now we need to check if the user selected Rx
214462306a36Sopenharmony_ci				 * ONLY of pause frames.  In this case, we had
214562306a36Sopenharmony_ci				 * to advertise FULL flow control because we
214662306a36Sopenharmony_ci				 * could not advertise Rx ONLY. Hence, we must
214762306a36Sopenharmony_ci				 * now check to see if we need to turn OFF the
214862306a36Sopenharmony_ci				 * TRANSMISSION of PAUSE frames.
214962306a36Sopenharmony_ci				 */
215062306a36Sopenharmony_ci				if (hw->original_fc == E1000_FC_FULL) {
215162306a36Sopenharmony_ci					hw->fc = E1000_FC_FULL;
215262306a36Sopenharmony_ci					e_dbg("Flow Control = FULL.\n");
215362306a36Sopenharmony_ci				} else {
215462306a36Sopenharmony_ci					hw->fc = E1000_FC_RX_PAUSE;
215562306a36Sopenharmony_ci					e_dbg
215662306a36Sopenharmony_ci					    ("Flow Control = RX PAUSE frames only.\n");
215762306a36Sopenharmony_ci				}
215862306a36Sopenharmony_ci			}
215962306a36Sopenharmony_ci			/* For receiving PAUSE frames ONLY.
216062306a36Sopenharmony_ci			 *
216162306a36Sopenharmony_ci			 *   LOCAL DEVICE  |   LINK PARTNER
216262306a36Sopenharmony_ci			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
216362306a36Sopenharmony_ci			 *-------|---------|-------|---------|------------------
216462306a36Sopenharmony_ci			 *   0   |    1    |   1   |    1    | E1000_FC_TX_PAUSE
216562306a36Sopenharmony_ci			 *
216662306a36Sopenharmony_ci			 */
216762306a36Sopenharmony_ci			else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
216862306a36Sopenharmony_ci				 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
216962306a36Sopenharmony_ci				 (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
217062306a36Sopenharmony_ci				 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
217162306a36Sopenharmony_ci				hw->fc = E1000_FC_TX_PAUSE;
217262306a36Sopenharmony_ci				e_dbg
217362306a36Sopenharmony_ci				    ("Flow Control = TX PAUSE frames only.\n");
217462306a36Sopenharmony_ci			}
217562306a36Sopenharmony_ci			/* For transmitting PAUSE frames ONLY.
217662306a36Sopenharmony_ci			 *
217762306a36Sopenharmony_ci			 *   LOCAL DEVICE  |   LINK PARTNER
217862306a36Sopenharmony_ci			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
217962306a36Sopenharmony_ci			 *-------|---------|-------|---------|------------------
218062306a36Sopenharmony_ci			 *   1   |    1    |   0   |    1    | E1000_FC_RX_PAUSE
218162306a36Sopenharmony_ci			 *
218262306a36Sopenharmony_ci			 */
218362306a36Sopenharmony_ci			else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
218462306a36Sopenharmony_ci				 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
218562306a36Sopenharmony_ci				 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
218662306a36Sopenharmony_ci				 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
218762306a36Sopenharmony_ci				hw->fc = E1000_FC_RX_PAUSE;
218862306a36Sopenharmony_ci				e_dbg
218962306a36Sopenharmony_ci				    ("Flow Control = RX PAUSE frames only.\n");
219062306a36Sopenharmony_ci			}
219162306a36Sopenharmony_ci			/* Per the IEEE spec, at this point flow control should
219262306a36Sopenharmony_ci			 * be disabled.  However, we want to consider that we
219362306a36Sopenharmony_ci			 * could be connected to a legacy switch that doesn't
219462306a36Sopenharmony_ci			 * advertise desired flow control, but can be forced on
219562306a36Sopenharmony_ci			 * the link partner.  So if we advertised no flow
219662306a36Sopenharmony_ci			 * control, that is what we will resolve to.  If we
219762306a36Sopenharmony_ci			 * advertised some kind of receive capability (Rx Pause
219862306a36Sopenharmony_ci			 * Only or Full Flow Control) and the link partner
219962306a36Sopenharmony_ci			 * advertised none, we will configure ourselves to
220062306a36Sopenharmony_ci			 * enable Rx Flow Control only.  We can do this safely
220162306a36Sopenharmony_ci			 * for two reasons:  If the link partner really
220262306a36Sopenharmony_ci			 * didn't want flow control enabled, and we enable Rx,
220362306a36Sopenharmony_ci			 * no harm done since we won't be receiving any PAUSE
220462306a36Sopenharmony_ci			 * frames anyway.  If the intent on the link partner was
220562306a36Sopenharmony_ci			 * to have flow control enabled, then by us enabling Rx
220662306a36Sopenharmony_ci			 * only, we can at least receive pause frames and
220762306a36Sopenharmony_ci			 * process them. This is a good idea because in most
220862306a36Sopenharmony_ci			 * cases, since we are predominantly a server NIC, more
220962306a36Sopenharmony_ci			 * times than not we will be asked to delay transmission
221062306a36Sopenharmony_ci			 * of packets than asking our link partner to pause
221162306a36Sopenharmony_ci			 * transmission of frames.
221262306a36Sopenharmony_ci			 */
221362306a36Sopenharmony_ci			else if ((hw->original_fc == E1000_FC_NONE ||
221462306a36Sopenharmony_ci				  hw->original_fc == E1000_FC_TX_PAUSE) ||
221562306a36Sopenharmony_ci				 hw->fc_strict_ieee) {
221662306a36Sopenharmony_ci				hw->fc = E1000_FC_NONE;
221762306a36Sopenharmony_ci				e_dbg("Flow Control = NONE.\n");
221862306a36Sopenharmony_ci			} else {
221962306a36Sopenharmony_ci				hw->fc = E1000_FC_RX_PAUSE;
222062306a36Sopenharmony_ci				e_dbg
222162306a36Sopenharmony_ci				    ("Flow Control = RX PAUSE frames only.\n");
222262306a36Sopenharmony_ci			}
222362306a36Sopenharmony_ci
222462306a36Sopenharmony_ci			/* Now we need to do one last check...  If we auto-
222562306a36Sopenharmony_ci			 * negotiated to HALF DUPLEX, flow control should not be
222662306a36Sopenharmony_ci			 * enabled per IEEE 802.3 spec.
222762306a36Sopenharmony_ci			 */
222862306a36Sopenharmony_ci			ret_val =
222962306a36Sopenharmony_ci			    e1000_get_speed_and_duplex(hw, &speed, &duplex);
223062306a36Sopenharmony_ci			if (ret_val) {
223162306a36Sopenharmony_ci				e_dbg
223262306a36Sopenharmony_ci				    ("Error getting link speed and duplex\n");
223362306a36Sopenharmony_ci				return ret_val;
223462306a36Sopenharmony_ci			}
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci			if (duplex == HALF_DUPLEX)
223762306a36Sopenharmony_ci				hw->fc = E1000_FC_NONE;
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ci			/* Now we call a subroutine to actually force the MAC
224062306a36Sopenharmony_ci			 * controller to use the correct flow control settings.
224162306a36Sopenharmony_ci			 */
224262306a36Sopenharmony_ci			ret_val = e1000_force_mac_fc(hw);
224362306a36Sopenharmony_ci			if (ret_val) {
224462306a36Sopenharmony_ci				e_dbg
224562306a36Sopenharmony_ci				    ("Error forcing flow control settings\n");
224662306a36Sopenharmony_ci				return ret_val;
224762306a36Sopenharmony_ci			}
224862306a36Sopenharmony_ci		} else {
224962306a36Sopenharmony_ci			e_dbg
225062306a36Sopenharmony_ci			    ("Copper PHY and Auto Neg has not completed.\n");
225162306a36Sopenharmony_ci		}
225262306a36Sopenharmony_ci	}
225362306a36Sopenharmony_ci	return E1000_SUCCESS;
225462306a36Sopenharmony_ci}
225562306a36Sopenharmony_ci
225662306a36Sopenharmony_ci/**
225762306a36Sopenharmony_ci * e1000_check_for_serdes_link_generic - Check for link (Serdes)
225862306a36Sopenharmony_ci * @hw: pointer to the HW structure
225962306a36Sopenharmony_ci *
226062306a36Sopenharmony_ci * Checks for link up on the hardware.  If link is not up and we have
226162306a36Sopenharmony_ci * a signal, then we need to force link up.
226262306a36Sopenharmony_ci */
226362306a36Sopenharmony_cistatic s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
226462306a36Sopenharmony_ci{
226562306a36Sopenharmony_ci	u32 rxcw;
226662306a36Sopenharmony_ci	u32 ctrl;
226762306a36Sopenharmony_ci	u32 status;
226862306a36Sopenharmony_ci	s32 ret_val = E1000_SUCCESS;
226962306a36Sopenharmony_ci
227062306a36Sopenharmony_ci	ctrl = er32(CTRL);
227162306a36Sopenharmony_ci	status = er32(STATUS);
227262306a36Sopenharmony_ci	rxcw = er32(RXCW);
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ci	/* If we don't have link (auto-negotiation failed or link partner
227562306a36Sopenharmony_ci	 * cannot auto-negotiate), and our link partner is not trying to
227662306a36Sopenharmony_ci	 * auto-negotiate with us (we are receiving idles or data),
227762306a36Sopenharmony_ci	 * we need to force link up. We also need to give auto-negotiation
227862306a36Sopenharmony_ci	 * time to complete.
227962306a36Sopenharmony_ci	 */
228062306a36Sopenharmony_ci	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
228162306a36Sopenharmony_ci	if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
228262306a36Sopenharmony_ci		if (hw->autoneg_failed == 0) {
228362306a36Sopenharmony_ci			hw->autoneg_failed = 1;
228462306a36Sopenharmony_ci			goto out;
228562306a36Sopenharmony_ci		}
228662306a36Sopenharmony_ci		e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");
228762306a36Sopenharmony_ci
228862306a36Sopenharmony_ci		/* Disable auto-negotiation in the TXCW register */
228962306a36Sopenharmony_ci		ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
229062306a36Sopenharmony_ci
229162306a36Sopenharmony_ci		/* Force link-up and also force full-duplex. */
229262306a36Sopenharmony_ci		ctrl = er32(CTRL);
229362306a36Sopenharmony_ci		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
229462306a36Sopenharmony_ci		ew32(CTRL, ctrl);
229562306a36Sopenharmony_ci
229662306a36Sopenharmony_ci		/* Configure Flow Control after forcing link up. */
229762306a36Sopenharmony_ci		ret_val = e1000_config_fc_after_link_up(hw);
229862306a36Sopenharmony_ci		if (ret_val) {
229962306a36Sopenharmony_ci			e_dbg("Error configuring flow control\n");
230062306a36Sopenharmony_ci			goto out;
230162306a36Sopenharmony_ci		}
230262306a36Sopenharmony_ci	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
230362306a36Sopenharmony_ci		/* If we are forcing link and we are receiving /C/ ordered
230462306a36Sopenharmony_ci		 * sets, re-enable auto-negotiation in the TXCW register
230562306a36Sopenharmony_ci		 * and disable forced link in the Device Control register
230662306a36Sopenharmony_ci		 * in an attempt to auto-negotiate with our link partner.
230762306a36Sopenharmony_ci		 */
230862306a36Sopenharmony_ci		e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");
230962306a36Sopenharmony_ci		ew32(TXCW, hw->txcw);
231062306a36Sopenharmony_ci		ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
231162306a36Sopenharmony_ci
231262306a36Sopenharmony_ci		hw->serdes_has_link = true;
231362306a36Sopenharmony_ci	} else if (!(E1000_TXCW_ANE & er32(TXCW))) {
231462306a36Sopenharmony_ci		/* If we force link for non-auto-negotiation switch, check
231562306a36Sopenharmony_ci		 * link status based on MAC synchronization for internal
231662306a36Sopenharmony_ci		 * serdes media type.
231762306a36Sopenharmony_ci		 */
231862306a36Sopenharmony_ci		/* SYNCH bit and IV bit are sticky. */
231962306a36Sopenharmony_ci		udelay(10);
232062306a36Sopenharmony_ci		rxcw = er32(RXCW);
232162306a36Sopenharmony_ci		if (rxcw & E1000_RXCW_SYNCH) {
232262306a36Sopenharmony_ci			if (!(rxcw & E1000_RXCW_IV)) {
232362306a36Sopenharmony_ci				hw->serdes_has_link = true;
232462306a36Sopenharmony_ci				e_dbg("SERDES: Link up - forced.\n");
232562306a36Sopenharmony_ci			}
232662306a36Sopenharmony_ci		} else {
232762306a36Sopenharmony_ci			hw->serdes_has_link = false;
232862306a36Sopenharmony_ci			e_dbg("SERDES: Link down - force failed.\n");
232962306a36Sopenharmony_ci		}
233062306a36Sopenharmony_ci	}
233162306a36Sopenharmony_ci
233262306a36Sopenharmony_ci	if (E1000_TXCW_ANE & er32(TXCW)) {
233362306a36Sopenharmony_ci		status = er32(STATUS);
233462306a36Sopenharmony_ci		if (status & E1000_STATUS_LU) {
233562306a36Sopenharmony_ci			/* SYNCH bit and IV bit are sticky, so reread rxcw. */
233662306a36Sopenharmony_ci			udelay(10);
233762306a36Sopenharmony_ci			rxcw = er32(RXCW);
233862306a36Sopenharmony_ci			if (rxcw & E1000_RXCW_SYNCH) {
233962306a36Sopenharmony_ci				if (!(rxcw & E1000_RXCW_IV)) {
234062306a36Sopenharmony_ci					hw->serdes_has_link = true;
234162306a36Sopenharmony_ci					e_dbg("SERDES: Link up - autoneg "
234262306a36Sopenharmony_ci						 "completed successfully.\n");
234362306a36Sopenharmony_ci				} else {
234462306a36Sopenharmony_ci					hw->serdes_has_link = false;
234562306a36Sopenharmony_ci					e_dbg("SERDES: Link down - invalid"
234662306a36Sopenharmony_ci						 "codewords detected in autoneg.\n");
234762306a36Sopenharmony_ci				}
234862306a36Sopenharmony_ci			} else {
234962306a36Sopenharmony_ci				hw->serdes_has_link = false;
235062306a36Sopenharmony_ci				e_dbg("SERDES: Link down - no sync.\n");
235162306a36Sopenharmony_ci			}
235262306a36Sopenharmony_ci		} else {
235362306a36Sopenharmony_ci			hw->serdes_has_link = false;
235462306a36Sopenharmony_ci			e_dbg("SERDES: Link down - autoneg failed\n");
235562306a36Sopenharmony_ci		}
235662306a36Sopenharmony_ci	}
235762306a36Sopenharmony_ci
235862306a36Sopenharmony_ci      out:
235962306a36Sopenharmony_ci	return ret_val;
236062306a36Sopenharmony_ci}
236162306a36Sopenharmony_ci
236262306a36Sopenharmony_ci/**
236362306a36Sopenharmony_ci * e1000_check_for_link
236462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
236562306a36Sopenharmony_ci *
236662306a36Sopenharmony_ci * Checks to see if the link status of the hardware has changed.
236762306a36Sopenharmony_ci * Called by any function that needs to check the link status of the adapter.
236862306a36Sopenharmony_ci */
236962306a36Sopenharmony_cis32 e1000_check_for_link(struct e1000_hw *hw)
237062306a36Sopenharmony_ci{
237162306a36Sopenharmony_ci	u32 status;
237262306a36Sopenharmony_ci	u32 rctl;
237362306a36Sopenharmony_ci	u32 icr;
237462306a36Sopenharmony_ci	s32 ret_val;
237562306a36Sopenharmony_ci	u16 phy_data;
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci	er32(CTRL);
237862306a36Sopenharmony_ci	status = er32(STATUS);
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_ci	/* On adapters with a MAC newer than 82544, SW Definable pin 1 will be
238162306a36Sopenharmony_ci	 * set when the optics detect a signal. On older adapters, it will be
238262306a36Sopenharmony_ci	 * cleared when there is a signal.  This applies to fiber media only.
238362306a36Sopenharmony_ci	 */
238462306a36Sopenharmony_ci	if ((hw->media_type == e1000_media_type_fiber) ||
238562306a36Sopenharmony_ci	    (hw->media_type == e1000_media_type_internal_serdes)) {
238662306a36Sopenharmony_ci		er32(RXCW);
238762306a36Sopenharmony_ci
238862306a36Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
238962306a36Sopenharmony_ci			if (status & E1000_STATUS_LU)
239062306a36Sopenharmony_ci				hw->get_link_status = false;
239162306a36Sopenharmony_ci		}
239262306a36Sopenharmony_ci	}
239362306a36Sopenharmony_ci
239462306a36Sopenharmony_ci	/* If we have a copper PHY then we only want to go out to the PHY
239562306a36Sopenharmony_ci	 * registers to see if Auto-Neg has completed and/or if our link
239662306a36Sopenharmony_ci	 * status has changed.  The get_link_status flag will be set if we
239762306a36Sopenharmony_ci	 * receive a Link Status Change interrupt or we have Rx Sequence
239862306a36Sopenharmony_ci	 * Errors.
239962306a36Sopenharmony_ci	 */
240062306a36Sopenharmony_ci	if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
240162306a36Sopenharmony_ci		/* First we want to see if the MII Status Register reports
240262306a36Sopenharmony_ci		 * link.  If so, then we want to get the current speed/duplex
240362306a36Sopenharmony_ci		 * of the PHY.
240462306a36Sopenharmony_ci		 * Read the register twice since the link bit is sticky.
240562306a36Sopenharmony_ci		 */
240662306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
240762306a36Sopenharmony_ci		if (ret_val)
240862306a36Sopenharmony_ci			return ret_val;
240962306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
241062306a36Sopenharmony_ci		if (ret_val)
241162306a36Sopenharmony_ci			return ret_val;
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci		if (phy_data & MII_SR_LINK_STATUS) {
241462306a36Sopenharmony_ci			hw->get_link_status = false;
241562306a36Sopenharmony_ci			/* Check if there was DownShift, must be checked
241662306a36Sopenharmony_ci			 * immediately after link-up
241762306a36Sopenharmony_ci			 */
241862306a36Sopenharmony_ci			e1000_check_downshift(hw);
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci			/* If we are on 82544 or 82543 silicon and speed/duplex
242162306a36Sopenharmony_ci			 * are forced to 10H or 10F, then we will implement the
242262306a36Sopenharmony_ci			 * polarity reversal workaround.  We disable interrupts
242362306a36Sopenharmony_ci			 * first, and upon returning, place the devices
242462306a36Sopenharmony_ci			 * interrupt state to its previous value except for the
242562306a36Sopenharmony_ci			 * link status change interrupt which will
242662306a36Sopenharmony_ci			 * happen due to the execution of this workaround.
242762306a36Sopenharmony_ci			 */
242862306a36Sopenharmony_ci
242962306a36Sopenharmony_ci			if ((hw->mac_type == e1000_82544 ||
243062306a36Sopenharmony_ci			     hw->mac_type == e1000_82543) &&
243162306a36Sopenharmony_ci			    (!hw->autoneg) &&
243262306a36Sopenharmony_ci			    (hw->forced_speed_duplex == e1000_10_full ||
243362306a36Sopenharmony_ci			     hw->forced_speed_duplex == e1000_10_half)) {
243462306a36Sopenharmony_ci				ew32(IMC, 0xffffffff);
243562306a36Sopenharmony_ci				ret_val =
243662306a36Sopenharmony_ci				    e1000_polarity_reversal_workaround(hw);
243762306a36Sopenharmony_ci				icr = er32(ICR);
243862306a36Sopenharmony_ci				ew32(ICS, (icr & ~E1000_ICS_LSC));
243962306a36Sopenharmony_ci				ew32(IMS, IMS_ENABLE_MASK);
244062306a36Sopenharmony_ci			}
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci		} else {
244362306a36Sopenharmony_ci			/* No link detected */
244462306a36Sopenharmony_ci			e1000_config_dsp_after_link_change(hw, false);
244562306a36Sopenharmony_ci			return 0;
244662306a36Sopenharmony_ci		}
244762306a36Sopenharmony_ci
244862306a36Sopenharmony_ci		/* If we are forcing speed/duplex, then we simply return since
244962306a36Sopenharmony_ci		 * we have already determined whether we have link or not.
245062306a36Sopenharmony_ci		 */
245162306a36Sopenharmony_ci		if (!hw->autoneg)
245262306a36Sopenharmony_ci			return -E1000_ERR_CONFIG;
245362306a36Sopenharmony_ci
245462306a36Sopenharmony_ci		/* optimize the dsp settings for the igp phy */
245562306a36Sopenharmony_ci		e1000_config_dsp_after_link_change(hw, true);
245662306a36Sopenharmony_ci
245762306a36Sopenharmony_ci		/* We have a M88E1000 PHY and Auto-Neg is enabled.  If we
245862306a36Sopenharmony_ci		 * have Si on board that is 82544 or newer, Auto
245962306a36Sopenharmony_ci		 * Speed Detection takes care of MAC speed/duplex
246062306a36Sopenharmony_ci		 * configuration.  So we only need to configure Collision
246162306a36Sopenharmony_ci		 * Distance in the MAC.  Otherwise, we need to force
246262306a36Sopenharmony_ci		 * speed/duplex on the MAC to the current PHY speed/duplex
246362306a36Sopenharmony_ci		 * settings.
246462306a36Sopenharmony_ci		 */
246562306a36Sopenharmony_ci		if ((hw->mac_type >= e1000_82544) &&
246662306a36Sopenharmony_ci		    (hw->mac_type != e1000_ce4100))
246762306a36Sopenharmony_ci			e1000_config_collision_dist(hw);
246862306a36Sopenharmony_ci		else {
246962306a36Sopenharmony_ci			ret_val = e1000_config_mac_to_phy(hw);
247062306a36Sopenharmony_ci			if (ret_val) {
247162306a36Sopenharmony_ci				e_dbg
247262306a36Sopenharmony_ci				    ("Error configuring MAC to PHY settings\n");
247362306a36Sopenharmony_ci				return ret_val;
247462306a36Sopenharmony_ci			}
247562306a36Sopenharmony_ci		}
247662306a36Sopenharmony_ci
247762306a36Sopenharmony_ci		/* Configure Flow Control now that Auto-Neg has completed.
247862306a36Sopenharmony_ci		 * First, we need to restore the desired flow control settings
247962306a36Sopenharmony_ci		 * because we may have had to re-autoneg with a different link
248062306a36Sopenharmony_ci		 * partner.
248162306a36Sopenharmony_ci		 */
248262306a36Sopenharmony_ci		ret_val = e1000_config_fc_after_link_up(hw);
248362306a36Sopenharmony_ci		if (ret_val) {
248462306a36Sopenharmony_ci			e_dbg("Error configuring flow control\n");
248562306a36Sopenharmony_ci			return ret_val;
248662306a36Sopenharmony_ci		}
248762306a36Sopenharmony_ci
248862306a36Sopenharmony_ci		/* At this point we know that we are on copper and we have
248962306a36Sopenharmony_ci		 * auto-negotiated link.  These are conditions for checking the
249062306a36Sopenharmony_ci		 * link partner capability register.  We use the link speed to
249162306a36Sopenharmony_ci		 * determine if TBI compatibility needs to be turned on or off.
249262306a36Sopenharmony_ci		 * If the link is not at gigabit speed, then TBI compatibility
249362306a36Sopenharmony_ci		 * is not needed.  If we are at gigabit speed, we turn on TBI
249462306a36Sopenharmony_ci		 * compatibility.
249562306a36Sopenharmony_ci		 */
249662306a36Sopenharmony_ci		if (hw->tbi_compatibility_en) {
249762306a36Sopenharmony_ci			u16 speed, duplex;
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci			ret_val =
250062306a36Sopenharmony_ci			    e1000_get_speed_and_duplex(hw, &speed, &duplex);
250162306a36Sopenharmony_ci
250262306a36Sopenharmony_ci			if (ret_val) {
250362306a36Sopenharmony_ci				e_dbg
250462306a36Sopenharmony_ci				    ("Error getting link speed and duplex\n");
250562306a36Sopenharmony_ci				return ret_val;
250662306a36Sopenharmony_ci			}
250762306a36Sopenharmony_ci			if (speed != SPEED_1000) {
250862306a36Sopenharmony_ci				/* If link speed is not set to gigabit speed, we
250962306a36Sopenharmony_ci				 * do not need to enable TBI compatibility.
251062306a36Sopenharmony_ci				 */
251162306a36Sopenharmony_ci				if (hw->tbi_compatibility_on) {
251262306a36Sopenharmony_ci					/* If we previously were in the mode,
251362306a36Sopenharmony_ci					 * turn it off.
251462306a36Sopenharmony_ci					 */
251562306a36Sopenharmony_ci					rctl = er32(RCTL);
251662306a36Sopenharmony_ci					rctl &= ~E1000_RCTL_SBP;
251762306a36Sopenharmony_ci					ew32(RCTL, rctl);
251862306a36Sopenharmony_ci					hw->tbi_compatibility_on = false;
251962306a36Sopenharmony_ci				}
252062306a36Sopenharmony_ci			} else {
252162306a36Sopenharmony_ci				/* If TBI compatibility is was previously off,
252262306a36Sopenharmony_ci				 * turn it on. For compatibility with a TBI link
252362306a36Sopenharmony_ci				 * partner, we will store bad packets. Some
252462306a36Sopenharmony_ci				 * frames have an additional byte on the end and
252562306a36Sopenharmony_ci				 * will look like CRC errors to the hardware.
252662306a36Sopenharmony_ci				 */
252762306a36Sopenharmony_ci				if (!hw->tbi_compatibility_on) {
252862306a36Sopenharmony_ci					hw->tbi_compatibility_on = true;
252962306a36Sopenharmony_ci					rctl = er32(RCTL);
253062306a36Sopenharmony_ci					rctl |= E1000_RCTL_SBP;
253162306a36Sopenharmony_ci					ew32(RCTL, rctl);
253262306a36Sopenharmony_ci				}
253362306a36Sopenharmony_ci			}
253462306a36Sopenharmony_ci		}
253562306a36Sopenharmony_ci	}
253662306a36Sopenharmony_ci
253762306a36Sopenharmony_ci	if ((hw->media_type == e1000_media_type_fiber) ||
253862306a36Sopenharmony_ci	    (hw->media_type == e1000_media_type_internal_serdes))
253962306a36Sopenharmony_ci		e1000_check_for_serdes_link_generic(hw);
254062306a36Sopenharmony_ci
254162306a36Sopenharmony_ci	return E1000_SUCCESS;
254262306a36Sopenharmony_ci}
254362306a36Sopenharmony_ci
254462306a36Sopenharmony_ci/**
254562306a36Sopenharmony_ci * e1000_get_speed_and_duplex
254662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
254762306a36Sopenharmony_ci * @speed: Speed of the connection
254862306a36Sopenharmony_ci * @duplex: Duplex setting of the connection
254962306a36Sopenharmony_ci *
255062306a36Sopenharmony_ci * Detects the current speed and duplex settings of the hardware.
255162306a36Sopenharmony_ci */
255262306a36Sopenharmony_cis32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
255362306a36Sopenharmony_ci{
255462306a36Sopenharmony_ci	u32 status;
255562306a36Sopenharmony_ci	s32 ret_val;
255662306a36Sopenharmony_ci	u16 phy_data;
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	if (hw->mac_type >= e1000_82543) {
255962306a36Sopenharmony_ci		status = er32(STATUS);
256062306a36Sopenharmony_ci		if (status & E1000_STATUS_SPEED_1000) {
256162306a36Sopenharmony_ci			*speed = SPEED_1000;
256262306a36Sopenharmony_ci			e_dbg("1000 Mbs, ");
256362306a36Sopenharmony_ci		} else if (status & E1000_STATUS_SPEED_100) {
256462306a36Sopenharmony_ci			*speed = SPEED_100;
256562306a36Sopenharmony_ci			e_dbg("100 Mbs, ");
256662306a36Sopenharmony_ci		} else {
256762306a36Sopenharmony_ci			*speed = SPEED_10;
256862306a36Sopenharmony_ci			e_dbg("10 Mbs, ");
256962306a36Sopenharmony_ci		}
257062306a36Sopenharmony_ci
257162306a36Sopenharmony_ci		if (status & E1000_STATUS_FD) {
257262306a36Sopenharmony_ci			*duplex = FULL_DUPLEX;
257362306a36Sopenharmony_ci			e_dbg("Full Duplex\n");
257462306a36Sopenharmony_ci		} else {
257562306a36Sopenharmony_ci			*duplex = HALF_DUPLEX;
257662306a36Sopenharmony_ci			e_dbg(" Half Duplex\n");
257762306a36Sopenharmony_ci		}
257862306a36Sopenharmony_ci	} else {
257962306a36Sopenharmony_ci		e_dbg("1000 Mbs, Full Duplex\n");
258062306a36Sopenharmony_ci		*speed = SPEED_1000;
258162306a36Sopenharmony_ci		*duplex = FULL_DUPLEX;
258262306a36Sopenharmony_ci	}
258362306a36Sopenharmony_ci
258462306a36Sopenharmony_ci	/* IGP01 PHY may advertise full duplex operation after speed downgrade
258562306a36Sopenharmony_ci	 * even if it is operating at half duplex.  Here we set the duplex
258662306a36Sopenharmony_ci	 * settings to match the duplex in the link partner's capabilities.
258762306a36Sopenharmony_ci	 */
258862306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp && hw->speed_downgraded) {
258962306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data);
259062306a36Sopenharmony_ci		if (ret_val)
259162306a36Sopenharmony_ci			return ret_val;
259262306a36Sopenharmony_ci
259362306a36Sopenharmony_ci		if (!(phy_data & NWAY_ER_LP_NWAY_CAPS))
259462306a36Sopenharmony_ci			*duplex = HALF_DUPLEX;
259562306a36Sopenharmony_ci		else {
259662306a36Sopenharmony_ci			ret_val =
259762306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data);
259862306a36Sopenharmony_ci			if (ret_val)
259962306a36Sopenharmony_ci				return ret_val;
260062306a36Sopenharmony_ci			if ((*speed == SPEED_100 &&
260162306a36Sopenharmony_ci			     !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) ||
260262306a36Sopenharmony_ci			    (*speed == SPEED_10 &&
260362306a36Sopenharmony_ci			     !(phy_data & NWAY_LPAR_10T_FD_CAPS)))
260462306a36Sopenharmony_ci				*duplex = HALF_DUPLEX;
260562306a36Sopenharmony_ci		}
260662306a36Sopenharmony_ci	}
260762306a36Sopenharmony_ci
260862306a36Sopenharmony_ci	return E1000_SUCCESS;
260962306a36Sopenharmony_ci}
261062306a36Sopenharmony_ci
261162306a36Sopenharmony_ci/**
261262306a36Sopenharmony_ci * e1000_wait_autoneg
261362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
261462306a36Sopenharmony_ci *
261562306a36Sopenharmony_ci * Blocks until autoneg completes or times out (~4.5 seconds)
261662306a36Sopenharmony_ci */
261762306a36Sopenharmony_cistatic s32 e1000_wait_autoneg(struct e1000_hw *hw)
261862306a36Sopenharmony_ci{
261962306a36Sopenharmony_ci	s32 ret_val;
262062306a36Sopenharmony_ci	u16 i;
262162306a36Sopenharmony_ci	u16 phy_data;
262262306a36Sopenharmony_ci
262362306a36Sopenharmony_ci	e_dbg("Waiting for Auto-Neg to complete.\n");
262462306a36Sopenharmony_ci
262562306a36Sopenharmony_ci	/* We will wait for autoneg to complete or 4.5 seconds to expire. */
262662306a36Sopenharmony_ci	for (i = PHY_AUTO_NEG_TIME; i > 0; i--) {
262762306a36Sopenharmony_ci		/* Read the MII Status Register and wait for Auto-Neg
262862306a36Sopenharmony_ci		 * Complete bit to be set.
262962306a36Sopenharmony_ci		 */
263062306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
263162306a36Sopenharmony_ci		if (ret_val)
263262306a36Sopenharmony_ci			return ret_val;
263362306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
263462306a36Sopenharmony_ci		if (ret_val)
263562306a36Sopenharmony_ci			return ret_val;
263662306a36Sopenharmony_ci		if (phy_data & MII_SR_AUTONEG_COMPLETE)
263762306a36Sopenharmony_ci			return E1000_SUCCESS;
263862306a36Sopenharmony_ci
263962306a36Sopenharmony_ci		msleep(100);
264062306a36Sopenharmony_ci	}
264162306a36Sopenharmony_ci	return E1000_SUCCESS;
264262306a36Sopenharmony_ci}
264362306a36Sopenharmony_ci
264462306a36Sopenharmony_ci/**
264562306a36Sopenharmony_ci * e1000_raise_mdi_clk - Raises the Management Data Clock
264662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
264762306a36Sopenharmony_ci * @ctrl: Device control register's current value
264862306a36Sopenharmony_ci */
264962306a36Sopenharmony_cistatic void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
265062306a36Sopenharmony_ci{
265162306a36Sopenharmony_ci	/* Raise the clock input to the Management Data Clock (by setting the
265262306a36Sopenharmony_ci	 * MDC bit), and then delay 10 microseconds.
265362306a36Sopenharmony_ci	 */
265462306a36Sopenharmony_ci	ew32(CTRL, (*ctrl | E1000_CTRL_MDC));
265562306a36Sopenharmony_ci	E1000_WRITE_FLUSH();
265662306a36Sopenharmony_ci	udelay(10);
265762306a36Sopenharmony_ci}
265862306a36Sopenharmony_ci
265962306a36Sopenharmony_ci/**
266062306a36Sopenharmony_ci * e1000_lower_mdi_clk - Lowers the Management Data Clock
266162306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
266262306a36Sopenharmony_ci * @ctrl: Device control register's current value
266362306a36Sopenharmony_ci */
266462306a36Sopenharmony_cistatic void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
266562306a36Sopenharmony_ci{
266662306a36Sopenharmony_ci	/* Lower the clock input to the Management Data Clock (by clearing the
266762306a36Sopenharmony_ci	 * MDC bit), and then delay 10 microseconds.
266862306a36Sopenharmony_ci	 */
266962306a36Sopenharmony_ci	ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC));
267062306a36Sopenharmony_ci	E1000_WRITE_FLUSH();
267162306a36Sopenharmony_ci	udelay(10);
267262306a36Sopenharmony_ci}
267362306a36Sopenharmony_ci
267462306a36Sopenharmony_ci/**
267562306a36Sopenharmony_ci * e1000_shift_out_mdi_bits - Shifts data bits out to the PHY
267662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
267762306a36Sopenharmony_ci * @data: Data to send out to the PHY
267862306a36Sopenharmony_ci * @count: Number of bits to shift out
267962306a36Sopenharmony_ci *
268062306a36Sopenharmony_ci * Bits are shifted out in MSB to LSB order.
268162306a36Sopenharmony_ci */
268262306a36Sopenharmony_cistatic void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count)
268362306a36Sopenharmony_ci{
268462306a36Sopenharmony_ci	u32 ctrl;
268562306a36Sopenharmony_ci	u32 mask;
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_ci	/* We need to shift "count" number of bits out to the PHY. So, the value
268862306a36Sopenharmony_ci	 * in the "data" parameter will be shifted out to the PHY one bit at a
268962306a36Sopenharmony_ci	 * time. In order to do this, "data" must be broken down into bits.
269062306a36Sopenharmony_ci	 */
269162306a36Sopenharmony_ci	mask = 0x01;
269262306a36Sopenharmony_ci	mask <<= (count - 1);
269362306a36Sopenharmony_ci
269462306a36Sopenharmony_ci	ctrl = er32(CTRL);
269562306a36Sopenharmony_ci
269662306a36Sopenharmony_ci	/* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
269762306a36Sopenharmony_ci	ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
269862306a36Sopenharmony_ci
269962306a36Sopenharmony_ci	while (mask) {
270062306a36Sopenharmony_ci		/* A "1" is shifted out to the PHY by setting the MDIO bit to
270162306a36Sopenharmony_ci		 * "1" and then raising and lowering the Management Data Clock.
270262306a36Sopenharmony_ci		 * A "0" is shifted out to the PHY by setting the MDIO bit to
270362306a36Sopenharmony_ci		 * "0" and then raising and lowering the clock.
270462306a36Sopenharmony_ci		 */
270562306a36Sopenharmony_ci		if (data & mask)
270662306a36Sopenharmony_ci			ctrl |= E1000_CTRL_MDIO;
270762306a36Sopenharmony_ci		else
270862306a36Sopenharmony_ci			ctrl &= ~E1000_CTRL_MDIO;
270962306a36Sopenharmony_ci
271062306a36Sopenharmony_ci		ew32(CTRL, ctrl);
271162306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
271262306a36Sopenharmony_ci
271362306a36Sopenharmony_ci		udelay(10);
271462306a36Sopenharmony_ci
271562306a36Sopenharmony_ci		e1000_raise_mdi_clk(hw, &ctrl);
271662306a36Sopenharmony_ci		e1000_lower_mdi_clk(hw, &ctrl);
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci		mask = mask >> 1;
271962306a36Sopenharmony_ci	}
272062306a36Sopenharmony_ci}
272162306a36Sopenharmony_ci
272262306a36Sopenharmony_ci/**
272362306a36Sopenharmony_ci * e1000_shift_in_mdi_bits - Shifts data bits in from the PHY
272462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
272562306a36Sopenharmony_ci *
272662306a36Sopenharmony_ci * Bits are shifted in MSB to LSB order.
272762306a36Sopenharmony_ci */
272862306a36Sopenharmony_cistatic u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
272962306a36Sopenharmony_ci{
273062306a36Sopenharmony_ci	u32 ctrl;
273162306a36Sopenharmony_ci	u16 data = 0;
273262306a36Sopenharmony_ci	u8 i;
273362306a36Sopenharmony_ci
273462306a36Sopenharmony_ci	/* In order to read a register from the PHY, we need to shift in a total
273562306a36Sopenharmony_ci	 * of 18 bits from the PHY. The first two bit (turnaround) times are
273662306a36Sopenharmony_ci	 * used to avoid contention on the MDIO pin when a read operation is
273762306a36Sopenharmony_ci	 * performed. These two bits are ignored by us and thrown away. Bits are
273862306a36Sopenharmony_ci	 * "shifted in" by raising the input to the Management Data Clock
273962306a36Sopenharmony_ci	 * (setting the MDC bit), and then reading the value of the MDIO bit.
274062306a36Sopenharmony_ci	 */
274162306a36Sopenharmony_ci	ctrl = er32(CTRL);
274262306a36Sopenharmony_ci
274362306a36Sopenharmony_ci	/* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
274462306a36Sopenharmony_ci	 * input.
274562306a36Sopenharmony_ci	 */
274662306a36Sopenharmony_ci	ctrl &= ~E1000_CTRL_MDIO_DIR;
274762306a36Sopenharmony_ci	ctrl &= ~E1000_CTRL_MDIO;
274862306a36Sopenharmony_ci
274962306a36Sopenharmony_ci	ew32(CTRL, ctrl);
275062306a36Sopenharmony_ci	E1000_WRITE_FLUSH();
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci	/* Raise and Lower the clock before reading in the data. This accounts
275362306a36Sopenharmony_ci	 * for the turnaround bits. The first clock occurred when we clocked out
275462306a36Sopenharmony_ci	 * the last bit of the Register Address.
275562306a36Sopenharmony_ci	 */
275662306a36Sopenharmony_ci	e1000_raise_mdi_clk(hw, &ctrl);
275762306a36Sopenharmony_ci	e1000_lower_mdi_clk(hw, &ctrl);
275862306a36Sopenharmony_ci
275962306a36Sopenharmony_ci	for (data = 0, i = 0; i < 16; i++) {
276062306a36Sopenharmony_ci		data = data << 1;
276162306a36Sopenharmony_ci		e1000_raise_mdi_clk(hw, &ctrl);
276262306a36Sopenharmony_ci		ctrl = er32(CTRL);
276362306a36Sopenharmony_ci		/* Check to see if we shifted in a "1". */
276462306a36Sopenharmony_ci		if (ctrl & E1000_CTRL_MDIO)
276562306a36Sopenharmony_ci			data |= 1;
276662306a36Sopenharmony_ci		e1000_lower_mdi_clk(hw, &ctrl);
276762306a36Sopenharmony_ci	}
276862306a36Sopenharmony_ci
276962306a36Sopenharmony_ci	e1000_raise_mdi_clk(hw, &ctrl);
277062306a36Sopenharmony_ci	e1000_lower_mdi_clk(hw, &ctrl);
277162306a36Sopenharmony_ci
277262306a36Sopenharmony_ci	return data;
277362306a36Sopenharmony_ci}
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci/**
277662306a36Sopenharmony_ci * e1000_read_phy_reg - read a phy register
277762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
277862306a36Sopenharmony_ci * @reg_addr: address of the PHY register to read
277962306a36Sopenharmony_ci * @phy_data: pointer to the value on the PHY register
278062306a36Sopenharmony_ci *
278162306a36Sopenharmony_ci * Reads the value from a PHY register, if the value is on a specific non zero
278262306a36Sopenharmony_ci * page, sets the page first.
278362306a36Sopenharmony_ci */
278462306a36Sopenharmony_cis32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
278562306a36Sopenharmony_ci{
278662306a36Sopenharmony_ci	u32 ret_val;
278762306a36Sopenharmony_ci	unsigned long flags;
278862306a36Sopenharmony_ci
278962306a36Sopenharmony_ci	spin_lock_irqsave(&e1000_phy_lock, flags);
279062306a36Sopenharmony_ci
279162306a36Sopenharmony_ci	if ((hw->phy_type == e1000_phy_igp) &&
279262306a36Sopenharmony_ci	    (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
279362306a36Sopenharmony_ci		ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
279462306a36Sopenharmony_ci						 (u16) reg_addr);
279562306a36Sopenharmony_ci		if (ret_val)
279662306a36Sopenharmony_ci			goto out;
279762306a36Sopenharmony_ci	}
279862306a36Sopenharmony_ci
279962306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
280062306a36Sopenharmony_ci					phy_data);
280162306a36Sopenharmony_ciout:
280262306a36Sopenharmony_ci	spin_unlock_irqrestore(&e1000_phy_lock, flags);
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_ci	return ret_val;
280562306a36Sopenharmony_ci}
280662306a36Sopenharmony_ci
280762306a36Sopenharmony_cistatic s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
280862306a36Sopenharmony_ci				 u16 *phy_data)
280962306a36Sopenharmony_ci{
281062306a36Sopenharmony_ci	u32 i;
281162306a36Sopenharmony_ci	u32 mdic = 0;
281262306a36Sopenharmony_ci	const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1;
281362306a36Sopenharmony_ci
281462306a36Sopenharmony_ci	if (reg_addr > MAX_PHY_REG_ADDRESS) {
281562306a36Sopenharmony_ci		e_dbg("PHY Address %d is out of range\n", reg_addr);
281662306a36Sopenharmony_ci		return -E1000_ERR_PARAM;
281762306a36Sopenharmony_ci	}
281862306a36Sopenharmony_ci
281962306a36Sopenharmony_ci	if (hw->mac_type > e1000_82543) {
282062306a36Sopenharmony_ci		/* Set up Op-code, Phy Address, and register address in the MDI
282162306a36Sopenharmony_ci		 * Control register.  The MAC will take care of interfacing with
282262306a36Sopenharmony_ci		 * the PHY to retrieve the desired data.
282362306a36Sopenharmony_ci		 */
282462306a36Sopenharmony_ci		if (hw->mac_type == e1000_ce4100) {
282562306a36Sopenharmony_ci			mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
282662306a36Sopenharmony_ci				(phy_addr << E1000_MDIC_PHY_SHIFT) |
282762306a36Sopenharmony_ci				(INTEL_CE_GBE_MDIC_OP_READ) |
282862306a36Sopenharmony_ci				(INTEL_CE_GBE_MDIC_GO));
282962306a36Sopenharmony_ci
283062306a36Sopenharmony_ci			writel(mdic, E1000_MDIO_CMD);
283162306a36Sopenharmony_ci
283262306a36Sopenharmony_ci			/* Poll the ready bit to see if the MDI read
283362306a36Sopenharmony_ci			 * completed
283462306a36Sopenharmony_ci			 */
283562306a36Sopenharmony_ci			for (i = 0; i < 64; i++) {
283662306a36Sopenharmony_ci				udelay(50);
283762306a36Sopenharmony_ci				mdic = readl(E1000_MDIO_CMD);
283862306a36Sopenharmony_ci				if (!(mdic & INTEL_CE_GBE_MDIC_GO))
283962306a36Sopenharmony_ci					break;
284062306a36Sopenharmony_ci			}
284162306a36Sopenharmony_ci
284262306a36Sopenharmony_ci			if (mdic & INTEL_CE_GBE_MDIC_GO) {
284362306a36Sopenharmony_ci				e_dbg("MDI Read did not complete\n");
284462306a36Sopenharmony_ci				return -E1000_ERR_PHY;
284562306a36Sopenharmony_ci			}
284662306a36Sopenharmony_ci
284762306a36Sopenharmony_ci			mdic = readl(E1000_MDIO_STS);
284862306a36Sopenharmony_ci			if (mdic & INTEL_CE_GBE_MDIC_READ_ERROR) {
284962306a36Sopenharmony_ci				e_dbg("MDI Read Error\n");
285062306a36Sopenharmony_ci				return -E1000_ERR_PHY;
285162306a36Sopenharmony_ci			}
285262306a36Sopenharmony_ci			*phy_data = (u16)mdic;
285362306a36Sopenharmony_ci		} else {
285462306a36Sopenharmony_ci			mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
285562306a36Sopenharmony_ci				(phy_addr << E1000_MDIC_PHY_SHIFT) |
285662306a36Sopenharmony_ci				(E1000_MDIC_OP_READ));
285762306a36Sopenharmony_ci
285862306a36Sopenharmony_ci			ew32(MDIC, mdic);
285962306a36Sopenharmony_ci
286062306a36Sopenharmony_ci			/* Poll the ready bit to see if the MDI read
286162306a36Sopenharmony_ci			 * completed
286262306a36Sopenharmony_ci			 */
286362306a36Sopenharmony_ci			for (i = 0; i < 64; i++) {
286462306a36Sopenharmony_ci				udelay(50);
286562306a36Sopenharmony_ci				mdic = er32(MDIC);
286662306a36Sopenharmony_ci				if (mdic & E1000_MDIC_READY)
286762306a36Sopenharmony_ci					break;
286862306a36Sopenharmony_ci			}
286962306a36Sopenharmony_ci			if (!(mdic & E1000_MDIC_READY)) {
287062306a36Sopenharmony_ci				e_dbg("MDI Read did not complete\n");
287162306a36Sopenharmony_ci				return -E1000_ERR_PHY;
287262306a36Sopenharmony_ci			}
287362306a36Sopenharmony_ci			if (mdic & E1000_MDIC_ERROR) {
287462306a36Sopenharmony_ci				e_dbg("MDI Error\n");
287562306a36Sopenharmony_ci				return -E1000_ERR_PHY;
287662306a36Sopenharmony_ci			}
287762306a36Sopenharmony_ci			*phy_data = (u16)mdic;
287862306a36Sopenharmony_ci		}
287962306a36Sopenharmony_ci	} else {
288062306a36Sopenharmony_ci		/* We must first send a preamble through the MDIO pin to signal
288162306a36Sopenharmony_ci		 * the beginning of an MII instruction.  This is done by sending
288262306a36Sopenharmony_ci		 * 32 consecutive "1" bits.
288362306a36Sopenharmony_ci		 */
288462306a36Sopenharmony_ci		e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
288562306a36Sopenharmony_ci
288662306a36Sopenharmony_ci		/* Now combine the next few fields that are required for a read
288762306a36Sopenharmony_ci		 * operation.  We use this method instead of calling the
288862306a36Sopenharmony_ci		 * e1000_shift_out_mdi_bits routine five different times. The
288962306a36Sopenharmony_ci		 * format of a MII read instruction consists of a shift out of
289062306a36Sopenharmony_ci		 * 14 bits and is defined as follows:
289162306a36Sopenharmony_ci		 *    <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
289262306a36Sopenharmony_ci		 * followed by a shift in of 18 bits.  This first two bits
289362306a36Sopenharmony_ci		 * shifted in are TurnAround bits used to avoid contention on
289462306a36Sopenharmony_ci		 * the MDIO pin when a READ operation is performed.  These two
289562306a36Sopenharmony_ci		 * bits are thrown away followed by a shift in of 16 bits which
289662306a36Sopenharmony_ci		 * contains the desired data.
289762306a36Sopenharmony_ci		 */
289862306a36Sopenharmony_ci		mdic = ((reg_addr) | (phy_addr << 5) |
289962306a36Sopenharmony_ci			(PHY_OP_READ << 10) | (PHY_SOF << 12));
290062306a36Sopenharmony_ci
290162306a36Sopenharmony_ci		e1000_shift_out_mdi_bits(hw, mdic, 14);
290262306a36Sopenharmony_ci
290362306a36Sopenharmony_ci		/* Now that we've shifted out the read command to the MII, we
290462306a36Sopenharmony_ci		 * need to "shift in" the 16-bit value (18 total bits) of the
290562306a36Sopenharmony_ci		 * requested PHY register address.
290662306a36Sopenharmony_ci		 */
290762306a36Sopenharmony_ci		*phy_data = e1000_shift_in_mdi_bits(hw);
290862306a36Sopenharmony_ci	}
290962306a36Sopenharmony_ci	return E1000_SUCCESS;
291062306a36Sopenharmony_ci}
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_ci/**
291362306a36Sopenharmony_ci * e1000_write_phy_reg - write a phy register
291462306a36Sopenharmony_ci *
291562306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
291662306a36Sopenharmony_ci * @reg_addr: address of the PHY register to write
291762306a36Sopenharmony_ci * @phy_data: data to write to the PHY
291862306a36Sopenharmony_ci *
291962306a36Sopenharmony_ci * Writes a value to a PHY register
292062306a36Sopenharmony_ci */
292162306a36Sopenharmony_cis32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
292262306a36Sopenharmony_ci{
292362306a36Sopenharmony_ci	u32 ret_val;
292462306a36Sopenharmony_ci	unsigned long flags;
292562306a36Sopenharmony_ci
292662306a36Sopenharmony_ci	spin_lock_irqsave(&e1000_phy_lock, flags);
292762306a36Sopenharmony_ci
292862306a36Sopenharmony_ci	if ((hw->phy_type == e1000_phy_igp) &&
292962306a36Sopenharmony_ci	    (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
293062306a36Sopenharmony_ci		ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
293162306a36Sopenharmony_ci						 (u16)reg_addr);
293262306a36Sopenharmony_ci		if (ret_val) {
293362306a36Sopenharmony_ci			spin_unlock_irqrestore(&e1000_phy_lock, flags);
293462306a36Sopenharmony_ci			return ret_val;
293562306a36Sopenharmony_ci		}
293662306a36Sopenharmony_ci	}
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
293962306a36Sopenharmony_ci					 phy_data);
294062306a36Sopenharmony_ci	spin_unlock_irqrestore(&e1000_phy_lock, flags);
294162306a36Sopenharmony_ci
294262306a36Sopenharmony_ci	return ret_val;
294362306a36Sopenharmony_ci}
294462306a36Sopenharmony_ci
294562306a36Sopenharmony_cistatic s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
294662306a36Sopenharmony_ci				  u16 phy_data)
294762306a36Sopenharmony_ci{
294862306a36Sopenharmony_ci	u32 i;
294962306a36Sopenharmony_ci	u32 mdic = 0;
295062306a36Sopenharmony_ci	const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1;
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci	if (reg_addr > MAX_PHY_REG_ADDRESS) {
295362306a36Sopenharmony_ci		e_dbg("PHY Address %d is out of range\n", reg_addr);
295462306a36Sopenharmony_ci		return -E1000_ERR_PARAM;
295562306a36Sopenharmony_ci	}
295662306a36Sopenharmony_ci
295762306a36Sopenharmony_ci	if (hw->mac_type > e1000_82543) {
295862306a36Sopenharmony_ci		/* Set up Op-code, Phy Address, register address, and data
295962306a36Sopenharmony_ci		 * intended for the PHY register in the MDI Control register.
296062306a36Sopenharmony_ci		 * The MAC will take care of interfacing with the PHY to send
296162306a36Sopenharmony_ci		 * the desired data.
296262306a36Sopenharmony_ci		 */
296362306a36Sopenharmony_ci		if (hw->mac_type == e1000_ce4100) {
296462306a36Sopenharmony_ci			mdic = (((u32)phy_data) |
296562306a36Sopenharmony_ci				(reg_addr << E1000_MDIC_REG_SHIFT) |
296662306a36Sopenharmony_ci				(phy_addr << E1000_MDIC_PHY_SHIFT) |
296762306a36Sopenharmony_ci				(INTEL_CE_GBE_MDIC_OP_WRITE) |
296862306a36Sopenharmony_ci				(INTEL_CE_GBE_MDIC_GO));
296962306a36Sopenharmony_ci
297062306a36Sopenharmony_ci			writel(mdic, E1000_MDIO_CMD);
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_ci			/* Poll the ready bit to see if the MDI read
297362306a36Sopenharmony_ci			 * completed
297462306a36Sopenharmony_ci			 */
297562306a36Sopenharmony_ci			for (i = 0; i < 640; i++) {
297662306a36Sopenharmony_ci				udelay(5);
297762306a36Sopenharmony_ci				mdic = readl(E1000_MDIO_CMD);
297862306a36Sopenharmony_ci				if (!(mdic & INTEL_CE_GBE_MDIC_GO))
297962306a36Sopenharmony_ci					break;
298062306a36Sopenharmony_ci			}
298162306a36Sopenharmony_ci			if (mdic & INTEL_CE_GBE_MDIC_GO) {
298262306a36Sopenharmony_ci				e_dbg("MDI Write did not complete\n");
298362306a36Sopenharmony_ci				return -E1000_ERR_PHY;
298462306a36Sopenharmony_ci			}
298562306a36Sopenharmony_ci		} else {
298662306a36Sopenharmony_ci			mdic = (((u32)phy_data) |
298762306a36Sopenharmony_ci				(reg_addr << E1000_MDIC_REG_SHIFT) |
298862306a36Sopenharmony_ci				(phy_addr << E1000_MDIC_PHY_SHIFT) |
298962306a36Sopenharmony_ci				(E1000_MDIC_OP_WRITE));
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_ci			ew32(MDIC, mdic);
299262306a36Sopenharmony_ci
299362306a36Sopenharmony_ci			/* Poll the ready bit to see if the MDI read
299462306a36Sopenharmony_ci			 * completed
299562306a36Sopenharmony_ci			 */
299662306a36Sopenharmony_ci			for (i = 0; i < 641; i++) {
299762306a36Sopenharmony_ci				udelay(5);
299862306a36Sopenharmony_ci				mdic = er32(MDIC);
299962306a36Sopenharmony_ci				if (mdic & E1000_MDIC_READY)
300062306a36Sopenharmony_ci					break;
300162306a36Sopenharmony_ci			}
300262306a36Sopenharmony_ci			if (!(mdic & E1000_MDIC_READY)) {
300362306a36Sopenharmony_ci				e_dbg("MDI Write did not complete\n");
300462306a36Sopenharmony_ci				return -E1000_ERR_PHY;
300562306a36Sopenharmony_ci			}
300662306a36Sopenharmony_ci		}
300762306a36Sopenharmony_ci	} else {
300862306a36Sopenharmony_ci		/* We'll need to use the SW defined pins to shift the write
300962306a36Sopenharmony_ci		 * command out to the PHY. We first send a preamble to the PHY
301062306a36Sopenharmony_ci		 * to signal the beginning of the MII instruction.  This is done
301162306a36Sopenharmony_ci		 * by sending 32 consecutive "1" bits.
301262306a36Sopenharmony_ci		 */
301362306a36Sopenharmony_ci		e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
301462306a36Sopenharmony_ci
301562306a36Sopenharmony_ci		/* Now combine the remaining required fields that will indicate
301662306a36Sopenharmony_ci		 * a write operation. We use this method instead of calling the
301762306a36Sopenharmony_ci		 * e1000_shift_out_mdi_bits routine for each field in the
301862306a36Sopenharmony_ci		 * command. The format of a MII write instruction is as follows:
301962306a36Sopenharmony_ci		 * <Preamble><SOF><OpCode><PhyAddr><RegAddr><Turnaround><Data>.
302062306a36Sopenharmony_ci		 */
302162306a36Sopenharmony_ci		mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
302262306a36Sopenharmony_ci			(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
302362306a36Sopenharmony_ci		mdic <<= 16;
302462306a36Sopenharmony_ci		mdic |= (u32)phy_data;
302562306a36Sopenharmony_ci
302662306a36Sopenharmony_ci		e1000_shift_out_mdi_bits(hw, mdic, 32);
302762306a36Sopenharmony_ci	}
302862306a36Sopenharmony_ci
302962306a36Sopenharmony_ci	return E1000_SUCCESS;
303062306a36Sopenharmony_ci}
303162306a36Sopenharmony_ci
303262306a36Sopenharmony_ci/**
303362306a36Sopenharmony_ci * e1000_phy_hw_reset - reset the phy, hardware style
303462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
303562306a36Sopenharmony_ci *
303662306a36Sopenharmony_ci * Returns the PHY to the power-on reset state
303762306a36Sopenharmony_ci */
303862306a36Sopenharmony_cis32 e1000_phy_hw_reset(struct e1000_hw *hw)
303962306a36Sopenharmony_ci{
304062306a36Sopenharmony_ci	u32 ctrl, ctrl_ext;
304162306a36Sopenharmony_ci	u32 led_ctrl;
304262306a36Sopenharmony_ci
304362306a36Sopenharmony_ci	e_dbg("Resetting Phy...\n");
304462306a36Sopenharmony_ci
304562306a36Sopenharmony_ci	if (hw->mac_type > e1000_82543) {
304662306a36Sopenharmony_ci		/* Read the device control register and assert the
304762306a36Sopenharmony_ci		 * E1000_CTRL_PHY_RST bit. Then, take it out of reset.
304862306a36Sopenharmony_ci		 * For e1000 hardware, we delay for 10ms between the assert
304962306a36Sopenharmony_ci		 * and de-assert.
305062306a36Sopenharmony_ci		 */
305162306a36Sopenharmony_ci		ctrl = er32(CTRL);
305262306a36Sopenharmony_ci		ew32(CTRL, ctrl | E1000_CTRL_PHY_RST);
305362306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
305462306a36Sopenharmony_ci
305562306a36Sopenharmony_ci		msleep(10);
305662306a36Sopenharmony_ci
305762306a36Sopenharmony_ci		ew32(CTRL, ctrl);
305862306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
305962306a36Sopenharmony_ci
306062306a36Sopenharmony_ci	} else {
306162306a36Sopenharmony_ci		/* Read the Extended Device Control Register, assert the
306262306a36Sopenharmony_ci		 * PHY_RESET_DIR bit to put the PHY into reset. Then, take it
306362306a36Sopenharmony_ci		 * out of reset.
306462306a36Sopenharmony_ci		 */
306562306a36Sopenharmony_ci		ctrl_ext = er32(CTRL_EXT);
306662306a36Sopenharmony_ci		ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
306762306a36Sopenharmony_ci		ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
306862306a36Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
306962306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
307062306a36Sopenharmony_ci		msleep(10);
307162306a36Sopenharmony_ci		ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
307262306a36Sopenharmony_ci		ew32(CTRL_EXT, ctrl_ext);
307362306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
307462306a36Sopenharmony_ci	}
307562306a36Sopenharmony_ci	udelay(150);
307662306a36Sopenharmony_ci
307762306a36Sopenharmony_ci	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
307862306a36Sopenharmony_ci		/* Configure activity LED after PHY reset */
307962306a36Sopenharmony_ci		led_ctrl = er32(LEDCTL);
308062306a36Sopenharmony_ci		led_ctrl &= IGP_ACTIVITY_LED_MASK;
308162306a36Sopenharmony_ci		led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
308262306a36Sopenharmony_ci		ew32(LEDCTL, led_ctrl);
308362306a36Sopenharmony_ci	}
308462306a36Sopenharmony_ci
308562306a36Sopenharmony_ci	/* Wait for FW to finish PHY configuration. */
308662306a36Sopenharmony_ci	return e1000_get_phy_cfg_done(hw);
308762306a36Sopenharmony_ci}
308862306a36Sopenharmony_ci
308962306a36Sopenharmony_ci/**
309062306a36Sopenharmony_ci * e1000_phy_reset - reset the phy to commit settings
309162306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
309262306a36Sopenharmony_ci *
309362306a36Sopenharmony_ci * Resets the PHY
309462306a36Sopenharmony_ci * Sets bit 15 of the MII Control register
309562306a36Sopenharmony_ci */
309662306a36Sopenharmony_cis32 e1000_phy_reset(struct e1000_hw *hw)
309762306a36Sopenharmony_ci{
309862306a36Sopenharmony_ci	s32 ret_val;
309962306a36Sopenharmony_ci	u16 phy_data;
310062306a36Sopenharmony_ci
310162306a36Sopenharmony_ci	switch (hw->phy_type) {
310262306a36Sopenharmony_ci	case e1000_phy_igp:
310362306a36Sopenharmony_ci		ret_val = e1000_phy_hw_reset(hw);
310462306a36Sopenharmony_ci		if (ret_val)
310562306a36Sopenharmony_ci			return ret_val;
310662306a36Sopenharmony_ci		break;
310762306a36Sopenharmony_ci	default:
310862306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
310962306a36Sopenharmony_ci		if (ret_val)
311062306a36Sopenharmony_ci			return ret_val;
311162306a36Sopenharmony_ci
311262306a36Sopenharmony_ci		phy_data |= MII_CR_RESET;
311362306a36Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
311462306a36Sopenharmony_ci		if (ret_val)
311562306a36Sopenharmony_ci			return ret_val;
311662306a36Sopenharmony_ci
311762306a36Sopenharmony_ci		udelay(1);
311862306a36Sopenharmony_ci		break;
311962306a36Sopenharmony_ci	}
312062306a36Sopenharmony_ci
312162306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp)
312262306a36Sopenharmony_ci		e1000_phy_init_script(hw);
312362306a36Sopenharmony_ci
312462306a36Sopenharmony_ci	return E1000_SUCCESS;
312562306a36Sopenharmony_ci}
312662306a36Sopenharmony_ci
312762306a36Sopenharmony_ci/**
312862306a36Sopenharmony_ci * e1000_detect_gig_phy - check the phy type
312962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
313062306a36Sopenharmony_ci *
313162306a36Sopenharmony_ci * Probes the expected PHY address for known PHY IDs
313262306a36Sopenharmony_ci */
313362306a36Sopenharmony_cistatic s32 e1000_detect_gig_phy(struct e1000_hw *hw)
313462306a36Sopenharmony_ci{
313562306a36Sopenharmony_ci	s32 phy_init_status, ret_val;
313662306a36Sopenharmony_ci	u16 phy_id_high, phy_id_low;
313762306a36Sopenharmony_ci	bool match = false;
313862306a36Sopenharmony_ci
313962306a36Sopenharmony_ci	if (hw->phy_id != 0)
314062306a36Sopenharmony_ci		return E1000_SUCCESS;
314162306a36Sopenharmony_ci
314262306a36Sopenharmony_ci	/* Read the PHY ID Registers to identify which PHY is onboard. */
314362306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
314462306a36Sopenharmony_ci	if (ret_val)
314562306a36Sopenharmony_ci		return ret_val;
314662306a36Sopenharmony_ci
314762306a36Sopenharmony_ci	hw->phy_id = (u32)(phy_id_high << 16);
314862306a36Sopenharmony_ci	udelay(20);
314962306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
315062306a36Sopenharmony_ci	if (ret_val)
315162306a36Sopenharmony_ci		return ret_val;
315262306a36Sopenharmony_ci
315362306a36Sopenharmony_ci	hw->phy_id |= (u32)(phy_id_low & PHY_REVISION_MASK);
315462306a36Sopenharmony_ci	hw->phy_revision = (u32)phy_id_low & ~PHY_REVISION_MASK;
315562306a36Sopenharmony_ci
315662306a36Sopenharmony_ci	switch (hw->mac_type) {
315762306a36Sopenharmony_ci	case e1000_82543:
315862306a36Sopenharmony_ci		if (hw->phy_id == M88E1000_E_PHY_ID)
315962306a36Sopenharmony_ci			match = true;
316062306a36Sopenharmony_ci		break;
316162306a36Sopenharmony_ci	case e1000_82544:
316262306a36Sopenharmony_ci		if (hw->phy_id == M88E1000_I_PHY_ID)
316362306a36Sopenharmony_ci			match = true;
316462306a36Sopenharmony_ci		break;
316562306a36Sopenharmony_ci	case e1000_82540:
316662306a36Sopenharmony_ci	case e1000_82545:
316762306a36Sopenharmony_ci	case e1000_82545_rev_3:
316862306a36Sopenharmony_ci	case e1000_82546:
316962306a36Sopenharmony_ci	case e1000_82546_rev_3:
317062306a36Sopenharmony_ci		if (hw->phy_id == M88E1011_I_PHY_ID)
317162306a36Sopenharmony_ci			match = true;
317262306a36Sopenharmony_ci		break;
317362306a36Sopenharmony_ci	case e1000_ce4100:
317462306a36Sopenharmony_ci		if ((hw->phy_id == RTL8211B_PHY_ID) ||
317562306a36Sopenharmony_ci		    (hw->phy_id == RTL8201N_PHY_ID) ||
317662306a36Sopenharmony_ci		    (hw->phy_id == M88E1118_E_PHY_ID))
317762306a36Sopenharmony_ci			match = true;
317862306a36Sopenharmony_ci		break;
317962306a36Sopenharmony_ci	case e1000_82541:
318062306a36Sopenharmony_ci	case e1000_82541_rev_2:
318162306a36Sopenharmony_ci	case e1000_82547:
318262306a36Sopenharmony_ci	case e1000_82547_rev_2:
318362306a36Sopenharmony_ci		if (hw->phy_id == IGP01E1000_I_PHY_ID)
318462306a36Sopenharmony_ci			match = true;
318562306a36Sopenharmony_ci		break;
318662306a36Sopenharmony_ci	default:
318762306a36Sopenharmony_ci		e_dbg("Invalid MAC type %d\n", hw->mac_type);
318862306a36Sopenharmony_ci		return -E1000_ERR_CONFIG;
318962306a36Sopenharmony_ci	}
319062306a36Sopenharmony_ci	phy_init_status = e1000_set_phy_type(hw);
319162306a36Sopenharmony_ci
319262306a36Sopenharmony_ci	if ((match) && (phy_init_status == E1000_SUCCESS)) {
319362306a36Sopenharmony_ci		e_dbg("PHY ID 0x%X detected\n", hw->phy_id);
319462306a36Sopenharmony_ci		return E1000_SUCCESS;
319562306a36Sopenharmony_ci	}
319662306a36Sopenharmony_ci	e_dbg("Invalid PHY ID 0x%X\n", hw->phy_id);
319762306a36Sopenharmony_ci	return -E1000_ERR_PHY;
319862306a36Sopenharmony_ci}
319962306a36Sopenharmony_ci
320062306a36Sopenharmony_ci/**
320162306a36Sopenharmony_ci * e1000_phy_reset_dsp - reset DSP
320262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
320362306a36Sopenharmony_ci *
320462306a36Sopenharmony_ci * Resets the PHY's DSP
320562306a36Sopenharmony_ci */
320662306a36Sopenharmony_cistatic s32 e1000_phy_reset_dsp(struct e1000_hw *hw)
320762306a36Sopenharmony_ci{
320862306a36Sopenharmony_ci	s32 ret_val;
320962306a36Sopenharmony_ci
321062306a36Sopenharmony_ci	do {
321162306a36Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, 29, 0x001d);
321262306a36Sopenharmony_ci		if (ret_val)
321362306a36Sopenharmony_ci			break;
321462306a36Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, 30, 0x00c1);
321562306a36Sopenharmony_ci		if (ret_val)
321662306a36Sopenharmony_ci			break;
321762306a36Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, 30, 0x0000);
321862306a36Sopenharmony_ci		if (ret_val)
321962306a36Sopenharmony_ci			break;
322062306a36Sopenharmony_ci		ret_val = E1000_SUCCESS;
322162306a36Sopenharmony_ci	} while (0);
322262306a36Sopenharmony_ci
322362306a36Sopenharmony_ci	return ret_val;
322462306a36Sopenharmony_ci}
322562306a36Sopenharmony_ci
322662306a36Sopenharmony_ci/**
322762306a36Sopenharmony_ci * e1000_phy_igp_get_info - get igp specific registers
322862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
322962306a36Sopenharmony_ci * @phy_info: PHY information structure
323062306a36Sopenharmony_ci *
323162306a36Sopenharmony_ci * Get PHY information from various PHY registers for igp PHY only.
323262306a36Sopenharmony_ci */
323362306a36Sopenharmony_cistatic s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
323462306a36Sopenharmony_ci				  struct e1000_phy_info *phy_info)
323562306a36Sopenharmony_ci{
323662306a36Sopenharmony_ci	s32 ret_val;
323762306a36Sopenharmony_ci	u16 phy_data, min_length, max_length, average;
323862306a36Sopenharmony_ci	e1000_rev_polarity polarity;
323962306a36Sopenharmony_ci
324062306a36Sopenharmony_ci	/* The downshift status is checked only once, after link is established,
324162306a36Sopenharmony_ci	 * and it stored in the hw->speed_downgraded parameter.
324262306a36Sopenharmony_ci	 */
324362306a36Sopenharmony_ci	phy_info->downshift = (e1000_downshift) hw->speed_downgraded;
324462306a36Sopenharmony_ci
324562306a36Sopenharmony_ci	/* IGP01E1000 does not need to support it. */
324662306a36Sopenharmony_ci	phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
324762306a36Sopenharmony_ci
324862306a36Sopenharmony_ci	/* IGP01E1000 always correct polarity reversal */
324962306a36Sopenharmony_ci	phy_info->polarity_correction = e1000_polarity_reversal_enabled;
325062306a36Sopenharmony_ci
325162306a36Sopenharmony_ci	/* Check polarity status */
325262306a36Sopenharmony_ci	ret_val = e1000_check_polarity(hw, &polarity);
325362306a36Sopenharmony_ci	if (ret_val)
325462306a36Sopenharmony_ci		return ret_val;
325562306a36Sopenharmony_ci
325662306a36Sopenharmony_ci	phy_info->cable_polarity = polarity;
325762306a36Sopenharmony_ci
325862306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data);
325962306a36Sopenharmony_ci	if (ret_val)
326062306a36Sopenharmony_ci		return ret_val;
326162306a36Sopenharmony_ci
326262306a36Sopenharmony_ci	phy_info->mdix_mode =
326362306a36Sopenharmony_ci	    (e1000_auto_x_mode) ((phy_data & IGP01E1000_PSSR_MDIX) >>
326462306a36Sopenharmony_ci				 IGP01E1000_PSSR_MDIX_SHIFT);
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_ci	if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
326762306a36Sopenharmony_ci	    IGP01E1000_PSSR_SPEED_1000MBPS) {
326862306a36Sopenharmony_ci		/* Local/Remote Receiver Information are only valid @ 1000
326962306a36Sopenharmony_ci		 * Mbps
327062306a36Sopenharmony_ci		 */
327162306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
327262306a36Sopenharmony_ci		if (ret_val)
327362306a36Sopenharmony_ci			return ret_val;
327462306a36Sopenharmony_ci
327562306a36Sopenharmony_ci		phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
327662306a36Sopenharmony_ci				      SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
327762306a36Sopenharmony_ci		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
327862306a36Sopenharmony_ci		phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
327962306a36Sopenharmony_ci				       SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
328062306a36Sopenharmony_ci		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
328162306a36Sopenharmony_ci
328262306a36Sopenharmony_ci		/* Get cable length */
328362306a36Sopenharmony_ci		ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
328462306a36Sopenharmony_ci		if (ret_val)
328562306a36Sopenharmony_ci			return ret_val;
328662306a36Sopenharmony_ci
328762306a36Sopenharmony_ci		/* Translate to old method */
328862306a36Sopenharmony_ci		average = (max_length + min_length) / 2;
328962306a36Sopenharmony_ci
329062306a36Sopenharmony_ci		if (average <= e1000_igp_cable_length_50)
329162306a36Sopenharmony_ci			phy_info->cable_length = e1000_cable_length_50;
329262306a36Sopenharmony_ci		else if (average <= e1000_igp_cable_length_80)
329362306a36Sopenharmony_ci			phy_info->cable_length = e1000_cable_length_50_80;
329462306a36Sopenharmony_ci		else if (average <= e1000_igp_cable_length_110)
329562306a36Sopenharmony_ci			phy_info->cable_length = e1000_cable_length_80_110;
329662306a36Sopenharmony_ci		else if (average <= e1000_igp_cable_length_140)
329762306a36Sopenharmony_ci			phy_info->cable_length = e1000_cable_length_110_140;
329862306a36Sopenharmony_ci		else
329962306a36Sopenharmony_ci			phy_info->cable_length = e1000_cable_length_140;
330062306a36Sopenharmony_ci	}
330162306a36Sopenharmony_ci
330262306a36Sopenharmony_ci	return E1000_SUCCESS;
330362306a36Sopenharmony_ci}
330462306a36Sopenharmony_ci
330562306a36Sopenharmony_ci/**
330662306a36Sopenharmony_ci * e1000_phy_m88_get_info - get m88 specific registers
330762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
330862306a36Sopenharmony_ci * @phy_info: PHY information structure
330962306a36Sopenharmony_ci *
331062306a36Sopenharmony_ci * Get PHY information from various PHY registers for m88 PHY only.
331162306a36Sopenharmony_ci */
331262306a36Sopenharmony_cistatic s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
331362306a36Sopenharmony_ci				  struct e1000_phy_info *phy_info)
331462306a36Sopenharmony_ci{
331562306a36Sopenharmony_ci	s32 ret_val;
331662306a36Sopenharmony_ci	u16 phy_data;
331762306a36Sopenharmony_ci	e1000_rev_polarity polarity;
331862306a36Sopenharmony_ci
331962306a36Sopenharmony_ci	/* The downshift status is checked only once, after link is established,
332062306a36Sopenharmony_ci	 * and it stored in the hw->speed_downgraded parameter.
332162306a36Sopenharmony_ci	 */
332262306a36Sopenharmony_ci	phy_info->downshift = (e1000_downshift) hw->speed_downgraded;
332362306a36Sopenharmony_ci
332462306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
332562306a36Sopenharmony_ci	if (ret_val)
332662306a36Sopenharmony_ci		return ret_val;
332762306a36Sopenharmony_ci
332862306a36Sopenharmony_ci	phy_info->extended_10bt_distance =
332962306a36Sopenharmony_ci	    ((phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >>
333062306a36Sopenharmony_ci	     M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT) ?
333162306a36Sopenharmony_ci	    e1000_10bt_ext_dist_enable_lower :
333262306a36Sopenharmony_ci	    e1000_10bt_ext_dist_enable_normal;
333362306a36Sopenharmony_ci
333462306a36Sopenharmony_ci	phy_info->polarity_correction =
333562306a36Sopenharmony_ci	    ((phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >>
333662306a36Sopenharmony_ci	     M88E1000_PSCR_POLARITY_REVERSAL_SHIFT) ?
333762306a36Sopenharmony_ci	    e1000_polarity_reversal_disabled : e1000_polarity_reversal_enabled;
333862306a36Sopenharmony_ci
333962306a36Sopenharmony_ci	/* Check polarity status */
334062306a36Sopenharmony_ci	ret_val = e1000_check_polarity(hw, &polarity);
334162306a36Sopenharmony_ci	if (ret_val)
334262306a36Sopenharmony_ci		return ret_val;
334362306a36Sopenharmony_ci	phy_info->cable_polarity = polarity;
334462306a36Sopenharmony_ci
334562306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
334662306a36Sopenharmony_ci	if (ret_val)
334762306a36Sopenharmony_ci		return ret_val;
334862306a36Sopenharmony_ci
334962306a36Sopenharmony_ci	phy_info->mdix_mode =
335062306a36Sopenharmony_ci	    (e1000_auto_x_mode) ((phy_data & M88E1000_PSSR_MDIX) >>
335162306a36Sopenharmony_ci				 M88E1000_PSSR_MDIX_SHIFT);
335262306a36Sopenharmony_ci
335362306a36Sopenharmony_ci	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
335462306a36Sopenharmony_ci		/* Cable Length Estimation and Local/Remote Receiver Information
335562306a36Sopenharmony_ci		 * are only valid at 1000 Mbps.
335662306a36Sopenharmony_ci		 */
335762306a36Sopenharmony_ci		phy_info->cable_length =
335862306a36Sopenharmony_ci		    (e1000_cable_length) ((phy_data &
335962306a36Sopenharmony_ci					   M88E1000_PSSR_CABLE_LENGTH) >>
336062306a36Sopenharmony_ci					  M88E1000_PSSR_CABLE_LENGTH_SHIFT);
336162306a36Sopenharmony_ci
336262306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
336362306a36Sopenharmony_ci		if (ret_val)
336462306a36Sopenharmony_ci			return ret_val;
336562306a36Sopenharmony_ci
336662306a36Sopenharmony_ci		phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
336762306a36Sopenharmony_ci				      SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
336862306a36Sopenharmony_ci		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
336962306a36Sopenharmony_ci		phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
337062306a36Sopenharmony_ci				       SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
337162306a36Sopenharmony_ci		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
337262306a36Sopenharmony_ci	}
337362306a36Sopenharmony_ci
337462306a36Sopenharmony_ci	return E1000_SUCCESS;
337562306a36Sopenharmony_ci}
337662306a36Sopenharmony_ci
337762306a36Sopenharmony_ci/**
337862306a36Sopenharmony_ci * e1000_phy_get_info - request phy info
337962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
338062306a36Sopenharmony_ci * @phy_info: PHY information structure
338162306a36Sopenharmony_ci *
338262306a36Sopenharmony_ci * Get PHY information from various PHY registers
338362306a36Sopenharmony_ci */
338462306a36Sopenharmony_cis32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
338562306a36Sopenharmony_ci{
338662306a36Sopenharmony_ci	s32 ret_val;
338762306a36Sopenharmony_ci	u16 phy_data;
338862306a36Sopenharmony_ci
338962306a36Sopenharmony_ci	phy_info->cable_length = e1000_cable_length_undefined;
339062306a36Sopenharmony_ci	phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined;
339162306a36Sopenharmony_ci	phy_info->cable_polarity = e1000_rev_polarity_undefined;
339262306a36Sopenharmony_ci	phy_info->downshift = e1000_downshift_undefined;
339362306a36Sopenharmony_ci	phy_info->polarity_correction = e1000_polarity_reversal_undefined;
339462306a36Sopenharmony_ci	phy_info->mdix_mode = e1000_auto_x_mode_undefined;
339562306a36Sopenharmony_ci	phy_info->local_rx = e1000_1000t_rx_status_undefined;
339662306a36Sopenharmony_ci	phy_info->remote_rx = e1000_1000t_rx_status_undefined;
339762306a36Sopenharmony_ci
339862306a36Sopenharmony_ci	if (hw->media_type != e1000_media_type_copper) {
339962306a36Sopenharmony_ci		e_dbg("PHY info is only valid for copper media\n");
340062306a36Sopenharmony_ci		return -E1000_ERR_CONFIG;
340162306a36Sopenharmony_ci	}
340262306a36Sopenharmony_ci
340362306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
340462306a36Sopenharmony_ci	if (ret_val)
340562306a36Sopenharmony_ci		return ret_val;
340662306a36Sopenharmony_ci
340762306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
340862306a36Sopenharmony_ci	if (ret_val)
340962306a36Sopenharmony_ci		return ret_val;
341062306a36Sopenharmony_ci
341162306a36Sopenharmony_ci	if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
341262306a36Sopenharmony_ci		e_dbg("PHY info is only valid if link is up\n");
341362306a36Sopenharmony_ci		return -E1000_ERR_CONFIG;
341462306a36Sopenharmony_ci	}
341562306a36Sopenharmony_ci
341662306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp)
341762306a36Sopenharmony_ci		return e1000_phy_igp_get_info(hw, phy_info);
341862306a36Sopenharmony_ci	else if ((hw->phy_type == e1000_phy_8211) ||
341962306a36Sopenharmony_ci		 (hw->phy_type == e1000_phy_8201))
342062306a36Sopenharmony_ci		return E1000_SUCCESS;
342162306a36Sopenharmony_ci	else
342262306a36Sopenharmony_ci		return e1000_phy_m88_get_info(hw, phy_info);
342362306a36Sopenharmony_ci}
342462306a36Sopenharmony_ci
342562306a36Sopenharmony_cis32 e1000_validate_mdi_setting(struct e1000_hw *hw)
342662306a36Sopenharmony_ci{
342762306a36Sopenharmony_ci	if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) {
342862306a36Sopenharmony_ci		e_dbg("Invalid MDI setting detected\n");
342962306a36Sopenharmony_ci		hw->mdix = 1;
343062306a36Sopenharmony_ci		return -E1000_ERR_CONFIG;
343162306a36Sopenharmony_ci	}
343262306a36Sopenharmony_ci	return E1000_SUCCESS;
343362306a36Sopenharmony_ci}
343462306a36Sopenharmony_ci
343562306a36Sopenharmony_ci/**
343662306a36Sopenharmony_ci * e1000_init_eeprom_params - initialize sw eeprom vars
343762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
343862306a36Sopenharmony_ci *
343962306a36Sopenharmony_ci * Sets up eeprom variables in the hw struct.  Must be called after mac_type
344062306a36Sopenharmony_ci * is configured.
344162306a36Sopenharmony_ci */
344262306a36Sopenharmony_cis32 e1000_init_eeprom_params(struct e1000_hw *hw)
344362306a36Sopenharmony_ci{
344462306a36Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
344562306a36Sopenharmony_ci	u32 eecd = er32(EECD);
344662306a36Sopenharmony_ci	s32 ret_val = E1000_SUCCESS;
344762306a36Sopenharmony_ci	u16 eeprom_size;
344862306a36Sopenharmony_ci
344962306a36Sopenharmony_ci	switch (hw->mac_type) {
345062306a36Sopenharmony_ci	case e1000_82542_rev2_0:
345162306a36Sopenharmony_ci	case e1000_82542_rev2_1:
345262306a36Sopenharmony_ci	case e1000_82543:
345362306a36Sopenharmony_ci	case e1000_82544:
345462306a36Sopenharmony_ci		eeprom->type = e1000_eeprom_microwire;
345562306a36Sopenharmony_ci		eeprom->word_size = 64;
345662306a36Sopenharmony_ci		eeprom->opcode_bits = 3;
345762306a36Sopenharmony_ci		eeprom->address_bits = 6;
345862306a36Sopenharmony_ci		eeprom->delay_usec = 50;
345962306a36Sopenharmony_ci		break;
346062306a36Sopenharmony_ci	case e1000_82540:
346162306a36Sopenharmony_ci	case e1000_82545:
346262306a36Sopenharmony_ci	case e1000_82545_rev_3:
346362306a36Sopenharmony_ci	case e1000_82546:
346462306a36Sopenharmony_ci	case e1000_82546_rev_3:
346562306a36Sopenharmony_ci		eeprom->type = e1000_eeprom_microwire;
346662306a36Sopenharmony_ci		eeprom->opcode_bits = 3;
346762306a36Sopenharmony_ci		eeprom->delay_usec = 50;
346862306a36Sopenharmony_ci		if (eecd & E1000_EECD_SIZE) {
346962306a36Sopenharmony_ci			eeprom->word_size = 256;
347062306a36Sopenharmony_ci			eeprom->address_bits = 8;
347162306a36Sopenharmony_ci		} else {
347262306a36Sopenharmony_ci			eeprom->word_size = 64;
347362306a36Sopenharmony_ci			eeprom->address_bits = 6;
347462306a36Sopenharmony_ci		}
347562306a36Sopenharmony_ci		break;
347662306a36Sopenharmony_ci	case e1000_82541:
347762306a36Sopenharmony_ci	case e1000_82541_rev_2:
347862306a36Sopenharmony_ci	case e1000_82547:
347962306a36Sopenharmony_ci	case e1000_82547_rev_2:
348062306a36Sopenharmony_ci		if (eecd & E1000_EECD_TYPE) {
348162306a36Sopenharmony_ci			eeprom->type = e1000_eeprom_spi;
348262306a36Sopenharmony_ci			eeprom->opcode_bits = 8;
348362306a36Sopenharmony_ci			eeprom->delay_usec = 1;
348462306a36Sopenharmony_ci			if (eecd & E1000_EECD_ADDR_BITS) {
348562306a36Sopenharmony_ci				eeprom->page_size = 32;
348662306a36Sopenharmony_ci				eeprom->address_bits = 16;
348762306a36Sopenharmony_ci			} else {
348862306a36Sopenharmony_ci				eeprom->page_size = 8;
348962306a36Sopenharmony_ci				eeprom->address_bits = 8;
349062306a36Sopenharmony_ci			}
349162306a36Sopenharmony_ci		} else {
349262306a36Sopenharmony_ci			eeprom->type = e1000_eeprom_microwire;
349362306a36Sopenharmony_ci			eeprom->opcode_bits = 3;
349462306a36Sopenharmony_ci			eeprom->delay_usec = 50;
349562306a36Sopenharmony_ci			if (eecd & E1000_EECD_ADDR_BITS) {
349662306a36Sopenharmony_ci				eeprom->word_size = 256;
349762306a36Sopenharmony_ci				eeprom->address_bits = 8;
349862306a36Sopenharmony_ci			} else {
349962306a36Sopenharmony_ci				eeprom->word_size = 64;
350062306a36Sopenharmony_ci				eeprom->address_bits = 6;
350162306a36Sopenharmony_ci			}
350262306a36Sopenharmony_ci		}
350362306a36Sopenharmony_ci		break;
350462306a36Sopenharmony_ci	default:
350562306a36Sopenharmony_ci		break;
350662306a36Sopenharmony_ci	}
350762306a36Sopenharmony_ci
350862306a36Sopenharmony_ci	if (eeprom->type == e1000_eeprom_spi) {
350962306a36Sopenharmony_ci		/* eeprom_size will be an enum [0..8] that maps to eeprom sizes
351062306a36Sopenharmony_ci		 * 128B to 32KB (incremented by powers of 2).
351162306a36Sopenharmony_ci		 */
351262306a36Sopenharmony_ci		/* Set to default value for initial eeprom read. */
351362306a36Sopenharmony_ci		eeprom->word_size = 64;
351462306a36Sopenharmony_ci		ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size);
351562306a36Sopenharmony_ci		if (ret_val)
351662306a36Sopenharmony_ci			return ret_val;
351762306a36Sopenharmony_ci		eeprom_size =
351862306a36Sopenharmony_ci		    (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT;
351962306a36Sopenharmony_ci		/* 256B eeprom size was not supported in earlier hardware, so we
352062306a36Sopenharmony_ci		 * bump eeprom_size up one to ensure that "1" (which maps to
352162306a36Sopenharmony_ci		 * 256B) is never the result used in the shifting logic below.
352262306a36Sopenharmony_ci		 */
352362306a36Sopenharmony_ci		if (eeprom_size)
352462306a36Sopenharmony_ci			eeprom_size++;
352562306a36Sopenharmony_ci
352662306a36Sopenharmony_ci		eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT);
352762306a36Sopenharmony_ci	}
352862306a36Sopenharmony_ci	return ret_val;
352962306a36Sopenharmony_ci}
353062306a36Sopenharmony_ci
353162306a36Sopenharmony_ci/**
353262306a36Sopenharmony_ci * e1000_raise_ee_clk - Raises the EEPROM's clock input.
353362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
353462306a36Sopenharmony_ci * @eecd: EECD's current value
353562306a36Sopenharmony_ci */
353662306a36Sopenharmony_cistatic void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd)
353762306a36Sopenharmony_ci{
353862306a36Sopenharmony_ci	/* Raise the clock input to the EEPROM (by setting the SK bit), and then
353962306a36Sopenharmony_ci	 * wait <delay> microseconds.
354062306a36Sopenharmony_ci	 */
354162306a36Sopenharmony_ci	*eecd = *eecd | E1000_EECD_SK;
354262306a36Sopenharmony_ci	ew32(EECD, *eecd);
354362306a36Sopenharmony_ci	E1000_WRITE_FLUSH();
354462306a36Sopenharmony_ci	udelay(hw->eeprom.delay_usec);
354562306a36Sopenharmony_ci}
354662306a36Sopenharmony_ci
354762306a36Sopenharmony_ci/**
354862306a36Sopenharmony_ci * e1000_lower_ee_clk - Lowers the EEPROM's clock input.
354962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
355062306a36Sopenharmony_ci * @eecd: EECD's current value
355162306a36Sopenharmony_ci */
355262306a36Sopenharmony_cistatic void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd)
355362306a36Sopenharmony_ci{
355462306a36Sopenharmony_ci	/* Lower the clock input to the EEPROM (by clearing the SK bit), and
355562306a36Sopenharmony_ci	 * then wait 50 microseconds.
355662306a36Sopenharmony_ci	 */
355762306a36Sopenharmony_ci	*eecd = *eecd & ~E1000_EECD_SK;
355862306a36Sopenharmony_ci	ew32(EECD, *eecd);
355962306a36Sopenharmony_ci	E1000_WRITE_FLUSH();
356062306a36Sopenharmony_ci	udelay(hw->eeprom.delay_usec);
356162306a36Sopenharmony_ci}
356262306a36Sopenharmony_ci
356362306a36Sopenharmony_ci/**
356462306a36Sopenharmony_ci * e1000_shift_out_ee_bits - Shift data bits out to the EEPROM.
356562306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
356662306a36Sopenharmony_ci * @data: data to send to the EEPROM
356762306a36Sopenharmony_ci * @count: number of bits to shift out
356862306a36Sopenharmony_ci */
356962306a36Sopenharmony_cistatic void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count)
357062306a36Sopenharmony_ci{
357162306a36Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
357262306a36Sopenharmony_ci	u32 eecd;
357362306a36Sopenharmony_ci	u32 mask;
357462306a36Sopenharmony_ci
357562306a36Sopenharmony_ci	/* We need to shift "count" bits out to the EEPROM. So, value in the
357662306a36Sopenharmony_ci	 * "data" parameter will be shifted out to the EEPROM one bit at a time.
357762306a36Sopenharmony_ci	 * In order to do this, "data" must be broken down into bits.
357862306a36Sopenharmony_ci	 */
357962306a36Sopenharmony_ci	mask = 0x01 << (count - 1);
358062306a36Sopenharmony_ci	eecd = er32(EECD);
358162306a36Sopenharmony_ci	if (eeprom->type == e1000_eeprom_microwire)
358262306a36Sopenharmony_ci		eecd &= ~E1000_EECD_DO;
358362306a36Sopenharmony_ci	else if (eeprom->type == e1000_eeprom_spi)
358462306a36Sopenharmony_ci		eecd |= E1000_EECD_DO;
358562306a36Sopenharmony_ci
358662306a36Sopenharmony_ci	do {
358762306a36Sopenharmony_ci		/* A "1" is shifted out to the EEPROM by setting bit "DI" to a
358862306a36Sopenharmony_ci		 * "1", and then raising and then lowering the clock (the SK bit
358962306a36Sopenharmony_ci		 * controls the clock input to the EEPROM).  A "0" is shifted
359062306a36Sopenharmony_ci		 * out to the EEPROM by setting "DI" to "0" and then raising and
359162306a36Sopenharmony_ci		 * then lowering the clock.
359262306a36Sopenharmony_ci		 */
359362306a36Sopenharmony_ci		eecd &= ~E1000_EECD_DI;
359462306a36Sopenharmony_ci
359562306a36Sopenharmony_ci		if (data & mask)
359662306a36Sopenharmony_ci			eecd |= E1000_EECD_DI;
359762306a36Sopenharmony_ci
359862306a36Sopenharmony_ci		ew32(EECD, eecd);
359962306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
360062306a36Sopenharmony_ci
360162306a36Sopenharmony_ci		udelay(eeprom->delay_usec);
360262306a36Sopenharmony_ci
360362306a36Sopenharmony_ci		e1000_raise_ee_clk(hw, &eecd);
360462306a36Sopenharmony_ci		e1000_lower_ee_clk(hw, &eecd);
360562306a36Sopenharmony_ci
360662306a36Sopenharmony_ci		mask = mask >> 1;
360762306a36Sopenharmony_ci
360862306a36Sopenharmony_ci	} while (mask);
360962306a36Sopenharmony_ci
361062306a36Sopenharmony_ci	/* We leave the "DI" bit set to "0" when we leave this routine. */
361162306a36Sopenharmony_ci	eecd &= ~E1000_EECD_DI;
361262306a36Sopenharmony_ci	ew32(EECD, eecd);
361362306a36Sopenharmony_ci}
361462306a36Sopenharmony_ci
361562306a36Sopenharmony_ci/**
361662306a36Sopenharmony_ci * e1000_shift_in_ee_bits - Shift data bits in from the EEPROM
361762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
361862306a36Sopenharmony_ci * @count: number of bits to shift in
361962306a36Sopenharmony_ci */
362062306a36Sopenharmony_cistatic u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count)
362162306a36Sopenharmony_ci{
362262306a36Sopenharmony_ci	u32 eecd;
362362306a36Sopenharmony_ci	u32 i;
362462306a36Sopenharmony_ci	u16 data;
362562306a36Sopenharmony_ci
362662306a36Sopenharmony_ci	/* In order to read a register from the EEPROM, we need to shift 'count'
362762306a36Sopenharmony_ci	 * bits in from the EEPROM. Bits are "shifted in" by raising the clock
362862306a36Sopenharmony_ci	 * input to the EEPROM (setting the SK bit), and then reading the value
362962306a36Sopenharmony_ci	 * of the "DO" bit.  During this "shifting in" process the "DI" bit
363062306a36Sopenharmony_ci	 * should always be clear.
363162306a36Sopenharmony_ci	 */
363262306a36Sopenharmony_ci
363362306a36Sopenharmony_ci	eecd = er32(EECD);
363462306a36Sopenharmony_ci
363562306a36Sopenharmony_ci	eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
363662306a36Sopenharmony_ci	data = 0;
363762306a36Sopenharmony_ci
363862306a36Sopenharmony_ci	for (i = 0; i < count; i++) {
363962306a36Sopenharmony_ci		data = data << 1;
364062306a36Sopenharmony_ci		e1000_raise_ee_clk(hw, &eecd);
364162306a36Sopenharmony_ci
364262306a36Sopenharmony_ci		eecd = er32(EECD);
364362306a36Sopenharmony_ci
364462306a36Sopenharmony_ci		eecd &= ~(E1000_EECD_DI);
364562306a36Sopenharmony_ci		if (eecd & E1000_EECD_DO)
364662306a36Sopenharmony_ci			data |= 1;
364762306a36Sopenharmony_ci
364862306a36Sopenharmony_ci		e1000_lower_ee_clk(hw, &eecd);
364962306a36Sopenharmony_ci	}
365062306a36Sopenharmony_ci
365162306a36Sopenharmony_ci	return data;
365262306a36Sopenharmony_ci}
365362306a36Sopenharmony_ci
365462306a36Sopenharmony_ci/**
365562306a36Sopenharmony_ci * e1000_acquire_eeprom - Prepares EEPROM for access
365662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
365762306a36Sopenharmony_ci *
365862306a36Sopenharmony_ci * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
365962306a36Sopenharmony_ci * function should be called before issuing a command to the EEPROM.
366062306a36Sopenharmony_ci */
366162306a36Sopenharmony_cistatic s32 e1000_acquire_eeprom(struct e1000_hw *hw)
366262306a36Sopenharmony_ci{
366362306a36Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
366462306a36Sopenharmony_ci	u32 eecd, i = 0;
366562306a36Sopenharmony_ci
366662306a36Sopenharmony_ci	eecd = er32(EECD);
366762306a36Sopenharmony_ci
366862306a36Sopenharmony_ci	/* Request EEPROM Access */
366962306a36Sopenharmony_ci	if (hw->mac_type > e1000_82544) {
367062306a36Sopenharmony_ci		eecd |= E1000_EECD_REQ;
367162306a36Sopenharmony_ci		ew32(EECD, eecd);
367262306a36Sopenharmony_ci		eecd = er32(EECD);
367362306a36Sopenharmony_ci		while ((!(eecd & E1000_EECD_GNT)) &&
367462306a36Sopenharmony_ci		       (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
367562306a36Sopenharmony_ci			i++;
367662306a36Sopenharmony_ci			udelay(5);
367762306a36Sopenharmony_ci			eecd = er32(EECD);
367862306a36Sopenharmony_ci		}
367962306a36Sopenharmony_ci		if (!(eecd & E1000_EECD_GNT)) {
368062306a36Sopenharmony_ci			eecd &= ~E1000_EECD_REQ;
368162306a36Sopenharmony_ci			ew32(EECD, eecd);
368262306a36Sopenharmony_ci			e_dbg("Could not acquire EEPROM grant\n");
368362306a36Sopenharmony_ci			return -E1000_ERR_EEPROM;
368462306a36Sopenharmony_ci		}
368562306a36Sopenharmony_ci	}
368662306a36Sopenharmony_ci
368762306a36Sopenharmony_ci	/* Setup EEPROM for Read/Write */
368862306a36Sopenharmony_ci
368962306a36Sopenharmony_ci	if (eeprom->type == e1000_eeprom_microwire) {
369062306a36Sopenharmony_ci		/* Clear SK and DI */
369162306a36Sopenharmony_ci		eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
369262306a36Sopenharmony_ci		ew32(EECD, eecd);
369362306a36Sopenharmony_ci
369462306a36Sopenharmony_ci		/* Set CS */
369562306a36Sopenharmony_ci		eecd |= E1000_EECD_CS;
369662306a36Sopenharmony_ci		ew32(EECD, eecd);
369762306a36Sopenharmony_ci	} else if (eeprom->type == e1000_eeprom_spi) {
369862306a36Sopenharmony_ci		/* Clear SK and CS */
369962306a36Sopenharmony_ci		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
370062306a36Sopenharmony_ci		ew32(EECD, eecd);
370162306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
370262306a36Sopenharmony_ci		udelay(1);
370362306a36Sopenharmony_ci	}
370462306a36Sopenharmony_ci
370562306a36Sopenharmony_ci	return E1000_SUCCESS;
370662306a36Sopenharmony_ci}
370762306a36Sopenharmony_ci
370862306a36Sopenharmony_ci/**
370962306a36Sopenharmony_ci * e1000_standby_eeprom - Returns EEPROM to a "standby" state
371062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
371162306a36Sopenharmony_ci */
371262306a36Sopenharmony_cistatic void e1000_standby_eeprom(struct e1000_hw *hw)
371362306a36Sopenharmony_ci{
371462306a36Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
371562306a36Sopenharmony_ci	u32 eecd;
371662306a36Sopenharmony_ci
371762306a36Sopenharmony_ci	eecd = er32(EECD);
371862306a36Sopenharmony_ci
371962306a36Sopenharmony_ci	if (eeprom->type == e1000_eeprom_microwire) {
372062306a36Sopenharmony_ci		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
372162306a36Sopenharmony_ci		ew32(EECD, eecd);
372262306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
372362306a36Sopenharmony_ci		udelay(eeprom->delay_usec);
372462306a36Sopenharmony_ci
372562306a36Sopenharmony_ci		/* Clock high */
372662306a36Sopenharmony_ci		eecd |= E1000_EECD_SK;
372762306a36Sopenharmony_ci		ew32(EECD, eecd);
372862306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
372962306a36Sopenharmony_ci		udelay(eeprom->delay_usec);
373062306a36Sopenharmony_ci
373162306a36Sopenharmony_ci		/* Select EEPROM */
373262306a36Sopenharmony_ci		eecd |= E1000_EECD_CS;
373362306a36Sopenharmony_ci		ew32(EECD, eecd);
373462306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
373562306a36Sopenharmony_ci		udelay(eeprom->delay_usec);
373662306a36Sopenharmony_ci
373762306a36Sopenharmony_ci		/* Clock low */
373862306a36Sopenharmony_ci		eecd &= ~E1000_EECD_SK;
373962306a36Sopenharmony_ci		ew32(EECD, eecd);
374062306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
374162306a36Sopenharmony_ci		udelay(eeprom->delay_usec);
374262306a36Sopenharmony_ci	} else if (eeprom->type == e1000_eeprom_spi) {
374362306a36Sopenharmony_ci		/* Toggle CS to flush commands */
374462306a36Sopenharmony_ci		eecd |= E1000_EECD_CS;
374562306a36Sopenharmony_ci		ew32(EECD, eecd);
374662306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
374762306a36Sopenharmony_ci		udelay(eeprom->delay_usec);
374862306a36Sopenharmony_ci		eecd &= ~E1000_EECD_CS;
374962306a36Sopenharmony_ci		ew32(EECD, eecd);
375062306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
375162306a36Sopenharmony_ci		udelay(eeprom->delay_usec);
375262306a36Sopenharmony_ci	}
375362306a36Sopenharmony_ci}
375462306a36Sopenharmony_ci
375562306a36Sopenharmony_ci/**
375662306a36Sopenharmony_ci * e1000_release_eeprom - drop chip select
375762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
375862306a36Sopenharmony_ci *
375962306a36Sopenharmony_ci * Terminates a command by inverting the EEPROM's chip select pin
376062306a36Sopenharmony_ci */
376162306a36Sopenharmony_cistatic void e1000_release_eeprom(struct e1000_hw *hw)
376262306a36Sopenharmony_ci{
376362306a36Sopenharmony_ci	u32 eecd;
376462306a36Sopenharmony_ci
376562306a36Sopenharmony_ci	eecd = er32(EECD);
376662306a36Sopenharmony_ci
376762306a36Sopenharmony_ci	if (hw->eeprom.type == e1000_eeprom_spi) {
376862306a36Sopenharmony_ci		eecd |= E1000_EECD_CS;	/* Pull CS high */
376962306a36Sopenharmony_ci		eecd &= ~E1000_EECD_SK;	/* Lower SCK */
377062306a36Sopenharmony_ci
377162306a36Sopenharmony_ci		ew32(EECD, eecd);
377262306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
377362306a36Sopenharmony_ci
377462306a36Sopenharmony_ci		udelay(hw->eeprom.delay_usec);
377562306a36Sopenharmony_ci	} else if (hw->eeprom.type == e1000_eeprom_microwire) {
377662306a36Sopenharmony_ci		/* cleanup eeprom */
377762306a36Sopenharmony_ci
377862306a36Sopenharmony_ci		/* CS on Microwire is active-high */
377962306a36Sopenharmony_ci		eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
378062306a36Sopenharmony_ci
378162306a36Sopenharmony_ci		ew32(EECD, eecd);
378262306a36Sopenharmony_ci
378362306a36Sopenharmony_ci		/* Rising edge of clock */
378462306a36Sopenharmony_ci		eecd |= E1000_EECD_SK;
378562306a36Sopenharmony_ci		ew32(EECD, eecd);
378662306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
378762306a36Sopenharmony_ci		udelay(hw->eeprom.delay_usec);
378862306a36Sopenharmony_ci
378962306a36Sopenharmony_ci		/* Falling edge of clock */
379062306a36Sopenharmony_ci		eecd &= ~E1000_EECD_SK;
379162306a36Sopenharmony_ci		ew32(EECD, eecd);
379262306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
379362306a36Sopenharmony_ci		udelay(hw->eeprom.delay_usec);
379462306a36Sopenharmony_ci	}
379562306a36Sopenharmony_ci
379662306a36Sopenharmony_ci	/* Stop requesting EEPROM access */
379762306a36Sopenharmony_ci	if (hw->mac_type > e1000_82544) {
379862306a36Sopenharmony_ci		eecd &= ~E1000_EECD_REQ;
379962306a36Sopenharmony_ci		ew32(EECD, eecd);
380062306a36Sopenharmony_ci	}
380162306a36Sopenharmony_ci}
380262306a36Sopenharmony_ci
380362306a36Sopenharmony_ci/**
380462306a36Sopenharmony_ci * e1000_spi_eeprom_ready - Reads a 16 bit word from the EEPROM.
380562306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
380662306a36Sopenharmony_ci */
380762306a36Sopenharmony_cistatic s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
380862306a36Sopenharmony_ci{
380962306a36Sopenharmony_ci	u16 retry_count = 0;
381062306a36Sopenharmony_ci	u8 spi_stat_reg;
381162306a36Sopenharmony_ci
381262306a36Sopenharmony_ci	/* Read "Status Register" repeatedly until the LSB is cleared.  The
381362306a36Sopenharmony_ci	 * EEPROM will signal that the command has been completed by clearing
381462306a36Sopenharmony_ci	 * bit 0 of the internal status register.  If it's not cleared within
381562306a36Sopenharmony_ci	 * 5 milliseconds, then error out.
381662306a36Sopenharmony_ci	 */
381762306a36Sopenharmony_ci	retry_count = 0;
381862306a36Sopenharmony_ci	do {
381962306a36Sopenharmony_ci		e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
382062306a36Sopenharmony_ci					hw->eeprom.opcode_bits);
382162306a36Sopenharmony_ci		spi_stat_reg = (u8)e1000_shift_in_ee_bits(hw, 8);
382262306a36Sopenharmony_ci		if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
382362306a36Sopenharmony_ci			break;
382462306a36Sopenharmony_ci
382562306a36Sopenharmony_ci		udelay(5);
382662306a36Sopenharmony_ci		retry_count += 5;
382762306a36Sopenharmony_ci
382862306a36Sopenharmony_ci		e1000_standby_eeprom(hw);
382962306a36Sopenharmony_ci	} while (retry_count < EEPROM_MAX_RETRY_SPI);
383062306a36Sopenharmony_ci
383162306a36Sopenharmony_ci	/* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
383262306a36Sopenharmony_ci	 * only 0-5mSec on 5V devices)
383362306a36Sopenharmony_ci	 */
383462306a36Sopenharmony_ci	if (retry_count >= EEPROM_MAX_RETRY_SPI) {
383562306a36Sopenharmony_ci		e_dbg("SPI EEPROM Status error\n");
383662306a36Sopenharmony_ci		return -E1000_ERR_EEPROM;
383762306a36Sopenharmony_ci	}
383862306a36Sopenharmony_ci
383962306a36Sopenharmony_ci	return E1000_SUCCESS;
384062306a36Sopenharmony_ci}
384162306a36Sopenharmony_ci
384262306a36Sopenharmony_ci/**
384362306a36Sopenharmony_ci * e1000_read_eeprom - Reads a 16 bit word from the EEPROM.
384462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
384562306a36Sopenharmony_ci * @offset: offset of  word in the EEPROM to read
384662306a36Sopenharmony_ci * @data: word read from the EEPROM
384762306a36Sopenharmony_ci * @words: number of words to read
384862306a36Sopenharmony_ci */
384962306a36Sopenharmony_cis32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
385062306a36Sopenharmony_ci{
385162306a36Sopenharmony_ci	s32 ret;
385262306a36Sopenharmony_ci
385362306a36Sopenharmony_ci	mutex_lock(&e1000_eeprom_lock);
385462306a36Sopenharmony_ci	ret = e1000_do_read_eeprom(hw, offset, words, data);
385562306a36Sopenharmony_ci	mutex_unlock(&e1000_eeprom_lock);
385662306a36Sopenharmony_ci	return ret;
385762306a36Sopenharmony_ci}
385862306a36Sopenharmony_ci
385962306a36Sopenharmony_cistatic s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
386062306a36Sopenharmony_ci				u16 *data)
386162306a36Sopenharmony_ci{
386262306a36Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
386362306a36Sopenharmony_ci	u32 i = 0;
386462306a36Sopenharmony_ci
386562306a36Sopenharmony_ci	if (hw->mac_type == e1000_ce4100) {
386662306a36Sopenharmony_ci		GBE_CONFIG_FLASH_READ(GBE_CONFIG_BASE_VIRT, offset, words,
386762306a36Sopenharmony_ci				      data);
386862306a36Sopenharmony_ci		return E1000_SUCCESS;
386962306a36Sopenharmony_ci	}
387062306a36Sopenharmony_ci
387162306a36Sopenharmony_ci	/* A check for invalid values:  offset too large, too many words, and
387262306a36Sopenharmony_ci	 * not enough words.
387362306a36Sopenharmony_ci	 */
387462306a36Sopenharmony_ci	if ((offset >= eeprom->word_size) ||
387562306a36Sopenharmony_ci	    (words > eeprom->word_size - offset) ||
387662306a36Sopenharmony_ci	    (words == 0)) {
387762306a36Sopenharmony_ci		e_dbg("\"words\" parameter out of bounds. Words = %d,"
387862306a36Sopenharmony_ci		      "size = %d\n", offset, eeprom->word_size);
387962306a36Sopenharmony_ci		return -E1000_ERR_EEPROM;
388062306a36Sopenharmony_ci	}
388162306a36Sopenharmony_ci
388262306a36Sopenharmony_ci	/* EEPROM's that don't use EERD to read require us to bit-bang the SPI
388362306a36Sopenharmony_ci	 * directly. In this case, we need to acquire the EEPROM so that
388462306a36Sopenharmony_ci	 * FW or other port software does not interrupt.
388562306a36Sopenharmony_ci	 */
388662306a36Sopenharmony_ci	/* Prepare the EEPROM for bit-bang reading */
388762306a36Sopenharmony_ci	if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
388862306a36Sopenharmony_ci		return -E1000_ERR_EEPROM;
388962306a36Sopenharmony_ci
389062306a36Sopenharmony_ci	/* Set up the SPI or Microwire EEPROM for bit-bang reading.  We have
389162306a36Sopenharmony_ci	 * acquired the EEPROM at this point, so any returns should release it
389262306a36Sopenharmony_ci	 */
389362306a36Sopenharmony_ci	if (eeprom->type == e1000_eeprom_spi) {
389462306a36Sopenharmony_ci		u16 word_in;
389562306a36Sopenharmony_ci		u8 read_opcode = EEPROM_READ_OPCODE_SPI;
389662306a36Sopenharmony_ci
389762306a36Sopenharmony_ci		if (e1000_spi_eeprom_ready(hw)) {
389862306a36Sopenharmony_ci			e1000_release_eeprom(hw);
389962306a36Sopenharmony_ci			return -E1000_ERR_EEPROM;
390062306a36Sopenharmony_ci		}
390162306a36Sopenharmony_ci
390262306a36Sopenharmony_ci		e1000_standby_eeprom(hw);
390362306a36Sopenharmony_ci
390462306a36Sopenharmony_ci		/* Some SPI eeproms use the 8th address bit embedded in the
390562306a36Sopenharmony_ci		 * opcode
390662306a36Sopenharmony_ci		 */
390762306a36Sopenharmony_ci		if ((eeprom->address_bits == 8) && (offset >= 128))
390862306a36Sopenharmony_ci			read_opcode |= EEPROM_A8_OPCODE_SPI;
390962306a36Sopenharmony_ci
391062306a36Sopenharmony_ci		/* Send the READ command (opcode + addr)  */
391162306a36Sopenharmony_ci		e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
391262306a36Sopenharmony_ci		e1000_shift_out_ee_bits(hw, (u16)(offset * 2),
391362306a36Sopenharmony_ci					eeprom->address_bits);
391462306a36Sopenharmony_ci
391562306a36Sopenharmony_ci		/* Read the data.  The address of the eeprom internally
391662306a36Sopenharmony_ci		 * increments with each byte (spi) being read, saving on the
391762306a36Sopenharmony_ci		 * overhead of eeprom setup and tear-down.  The address counter
391862306a36Sopenharmony_ci		 * will roll over if reading beyond the size of the eeprom, thus
391962306a36Sopenharmony_ci		 * allowing the entire memory to be read starting from any
392062306a36Sopenharmony_ci		 * offset.
392162306a36Sopenharmony_ci		 */
392262306a36Sopenharmony_ci		for (i = 0; i < words; i++) {
392362306a36Sopenharmony_ci			word_in = e1000_shift_in_ee_bits(hw, 16);
392462306a36Sopenharmony_ci			data[i] = (word_in >> 8) | (word_in << 8);
392562306a36Sopenharmony_ci		}
392662306a36Sopenharmony_ci	} else if (eeprom->type == e1000_eeprom_microwire) {
392762306a36Sopenharmony_ci		for (i = 0; i < words; i++) {
392862306a36Sopenharmony_ci			/* Send the READ command (opcode + addr)  */
392962306a36Sopenharmony_ci			e1000_shift_out_ee_bits(hw,
393062306a36Sopenharmony_ci						EEPROM_READ_OPCODE_MICROWIRE,
393162306a36Sopenharmony_ci						eeprom->opcode_bits);
393262306a36Sopenharmony_ci			e1000_shift_out_ee_bits(hw, (u16)(offset + i),
393362306a36Sopenharmony_ci						eeprom->address_bits);
393462306a36Sopenharmony_ci
393562306a36Sopenharmony_ci			/* Read the data.  For microwire, each word requires the
393662306a36Sopenharmony_ci			 * overhead of eeprom setup and tear-down.
393762306a36Sopenharmony_ci			 */
393862306a36Sopenharmony_ci			data[i] = e1000_shift_in_ee_bits(hw, 16);
393962306a36Sopenharmony_ci			e1000_standby_eeprom(hw);
394062306a36Sopenharmony_ci			cond_resched();
394162306a36Sopenharmony_ci		}
394262306a36Sopenharmony_ci	}
394362306a36Sopenharmony_ci
394462306a36Sopenharmony_ci	/* End this read operation */
394562306a36Sopenharmony_ci	e1000_release_eeprom(hw);
394662306a36Sopenharmony_ci
394762306a36Sopenharmony_ci	return E1000_SUCCESS;
394862306a36Sopenharmony_ci}
394962306a36Sopenharmony_ci
395062306a36Sopenharmony_ci/**
395162306a36Sopenharmony_ci * e1000_validate_eeprom_checksum - Verifies that the EEPROM has a valid checksum
395262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
395362306a36Sopenharmony_ci *
395462306a36Sopenharmony_ci * Reads the first 64 16 bit words of the EEPROM and sums the values read.
395562306a36Sopenharmony_ci * If the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
395662306a36Sopenharmony_ci * valid.
395762306a36Sopenharmony_ci */
395862306a36Sopenharmony_cis32 e1000_validate_eeprom_checksum(struct e1000_hw *hw)
395962306a36Sopenharmony_ci{
396062306a36Sopenharmony_ci	u16 checksum = 0;
396162306a36Sopenharmony_ci	u16 i, eeprom_data;
396262306a36Sopenharmony_ci
396362306a36Sopenharmony_ci	for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
396462306a36Sopenharmony_ci		if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
396562306a36Sopenharmony_ci			e_dbg("EEPROM Read Error\n");
396662306a36Sopenharmony_ci			return -E1000_ERR_EEPROM;
396762306a36Sopenharmony_ci		}
396862306a36Sopenharmony_ci		checksum += eeprom_data;
396962306a36Sopenharmony_ci	}
397062306a36Sopenharmony_ci
397162306a36Sopenharmony_ci#ifdef CONFIG_PARISC
397262306a36Sopenharmony_ci	/* This is a signature and not a checksum on HP c8000 */
397362306a36Sopenharmony_ci	if ((hw->subsystem_vendor_id == 0x103C) && (eeprom_data == 0x16d6))
397462306a36Sopenharmony_ci		return E1000_SUCCESS;
397562306a36Sopenharmony_ci
397662306a36Sopenharmony_ci#endif
397762306a36Sopenharmony_ci	if (checksum == (u16)EEPROM_SUM)
397862306a36Sopenharmony_ci		return E1000_SUCCESS;
397962306a36Sopenharmony_ci	else {
398062306a36Sopenharmony_ci		e_dbg("EEPROM Checksum Invalid\n");
398162306a36Sopenharmony_ci		return -E1000_ERR_EEPROM;
398262306a36Sopenharmony_ci	}
398362306a36Sopenharmony_ci}
398462306a36Sopenharmony_ci
398562306a36Sopenharmony_ci/**
398662306a36Sopenharmony_ci * e1000_update_eeprom_checksum - Calculates/writes the EEPROM checksum
398762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
398862306a36Sopenharmony_ci *
398962306a36Sopenharmony_ci * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
399062306a36Sopenharmony_ci * Writes the difference to word offset 63 of the EEPROM.
399162306a36Sopenharmony_ci */
399262306a36Sopenharmony_cis32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
399362306a36Sopenharmony_ci{
399462306a36Sopenharmony_ci	u16 checksum = 0;
399562306a36Sopenharmony_ci	u16 i, eeprom_data;
399662306a36Sopenharmony_ci
399762306a36Sopenharmony_ci	for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
399862306a36Sopenharmony_ci		if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
399962306a36Sopenharmony_ci			e_dbg("EEPROM Read Error\n");
400062306a36Sopenharmony_ci			return -E1000_ERR_EEPROM;
400162306a36Sopenharmony_ci		}
400262306a36Sopenharmony_ci		checksum += eeprom_data;
400362306a36Sopenharmony_ci	}
400462306a36Sopenharmony_ci	checksum = (u16)EEPROM_SUM - checksum;
400562306a36Sopenharmony_ci	if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
400662306a36Sopenharmony_ci		e_dbg("EEPROM Write Error\n");
400762306a36Sopenharmony_ci		return -E1000_ERR_EEPROM;
400862306a36Sopenharmony_ci	}
400962306a36Sopenharmony_ci	return E1000_SUCCESS;
401062306a36Sopenharmony_ci}
401162306a36Sopenharmony_ci
401262306a36Sopenharmony_ci/**
401362306a36Sopenharmony_ci * e1000_write_eeprom - write words to the different EEPROM types.
401462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
401562306a36Sopenharmony_ci * @offset: offset within the EEPROM to be written to
401662306a36Sopenharmony_ci * @words: number of words to write
401762306a36Sopenharmony_ci * @data: 16 bit word to be written to the EEPROM
401862306a36Sopenharmony_ci *
401962306a36Sopenharmony_ci * If e1000_update_eeprom_checksum is not called after this function, the
402062306a36Sopenharmony_ci * EEPROM will most likely contain an invalid checksum.
402162306a36Sopenharmony_ci */
402262306a36Sopenharmony_cis32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
402362306a36Sopenharmony_ci{
402462306a36Sopenharmony_ci	s32 ret;
402562306a36Sopenharmony_ci
402662306a36Sopenharmony_ci	mutex_lock(&e1000_eeprom_lock);
402762306a36Sopenharmony_ci	ret = e1000_do_write_eeprom(hw, offset, words, data);
402862306a36Sopenharmony_ci	mutex_unlock(&e1000_eeprom_lock);
402962306a36Sopenharmony_ci	return ret;
403062306a36Sopenharmony_ci}
403162306a36Sopenharmony_ci
403262306a36Sopenharmony_cistatic s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
403362306a36Sopenharmony_ci				 u16 *data)
403462306a36Sopenharmony_ci{
403562306a36Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
403662306a36Sopenharmony_ci	s32 status = 0;
403762306a36Sopenharmony_ci
403862306a36Sopenharmony_ci	if (hw->mac_type == e1000_ce4100) {
403962306a36Sopenharmony_ci		GBE_CONFIG_FLASH_WRITE(GBE_CONFIG_BASE_VIRT, offset, words,
404062306a36Sopenharmony_ci				       data);
404162306a36Sopenharmony_ci		return E1000_SUCCESS;
404262306a36Sopenharmony_ci	}
404362306a36Sopenharmony_ci
404462306a36Sopenharmony_ci	/* A check for invalid values:  offset too large, too many words, and
404562306a36Sopenharmony_ci	 * not enough words.
404662306a36Sopenharmony_ci	 */
404762306a36Sopenharmony_ci	if ((offset >= eeprom->word_size) ||
404862306a36Sopenharmony_ci	    (words > eeprom->word_size - offset) ||
404962306a36Sopenharmony_ci	    (words == 0)) {
405062306a36Sopenharmony_ci		e_dbg("\"words\" parameter out of bounds\n");
405162306a36Sopenharmony_ci		return -E1000_ERR_EEPROM;
405262306a36Sopenharmony_ci	}
405362306a36Sopenharmony_ci
405462306a36Sopenharmony_ci	/* Prepare the EEPROM for writing  */
405562306a36Sopenharmony_ci	if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
405662306a36Sopenharmony_ci		return -E1000_ERR_EEPROM;
405762306a36Sopenharmony_ci
405862306a36Sopenharmony_ci	if (eeprom->type == e1000_eeprom_microwire) {
405962306a36Sopenharmony_ci		status = e1000_write_eeprom_microwire(hw, offset, words, data);
406062306a36Sopenharmony_ci	} else {
406162306a36Sopenharmony_ci		status = e1000_write_eeprom_spi(hw, offset, words, data);
406262306a36Sopenharmony_ci		msleep(10);
406362306a36Sopenharmony_ci	}
406462306a36Sopenharmony_ci
406562306a36Sopenharmony_ci	/* Done with writing */
406662306a36Sopenharmony_ci	e1000_release_eeprom(hw);
406762306a36Sopenharmony_ci
406862306a36Sopenharmony_ci	return status;
406962306a36Sopenharmony_ci}
407062306a36Sopenharmony_ci
407162306a36Sopenharmony_ci/**
407262306a36Sopenharmony_ci * e1000_write_eeprom_spi - Writes a 16 bit word to a given offset in an SPI EEPROM.
407362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
407462306a36Sopenharmony_ci * @offset: offset within the EEPROM to be written to
407562306a36Sopenharmony_ci * @words: number of words to write
407662306a36Sopenharmony_ci * @data: pointer to array of 8 bit words to be written to the EEPROM
407762306a36Sopenharmony_ci */
407862306a36Sopenharmony_cistatic s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words,
407962306a36Sopenharmony_ci				  u16 *data)
408062306a36Sopenharmony_ci{
408162306a36Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
408262306a36Sopenharmony_ci	u16 widx = 0;
408362306a36Sopenharmony_ci
408462306a36Sopenharmony_ci	while (widx < words) {
408562306a36Sopenharmony_ci		u8 write_opcode = EEPROM_WRITE_OPCODE_SPI;
408662306a36Sopenharmony_ci
408762306a36Sopenharmony_ci		if (e1000_spi_eeprom_ready(hw))
408862306a36Sopenharmony_ci			return -E1000_ERR_EEPROM;
408962306a36Sopenharmony_ci
409062306a36Sopenharmony_ci		e1000_standby_eeprom(hw);
409162306a36Sopenharmony_ci		cond_resched();
409262306a36Sopenharmony_ci
409362306a36Sopenharmony_ci		/*  Send the WRITE ENABLE command (8 bit opcode )  */
409462306a36Sopenharmony_ci		e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI,
409562306a36Sopenharmony_ci					eeprom->opcode_bits);
409662306a36Sopenharmony_ci
409762306a36Sopenharmony_ci		e1000_standby_eeprom(hw);
409862306a36Sopenharmony_ci
409962306a36Sopenharmony_ci		/* Some SPI eeproms use the 8th address bit embedded in the
410062306a36Sopenharmony_ci		 * opcode
410162306a36Sopenharmony_ci		 */
410262306a36Sopenharmony_ci		if ((eeprom->address_bits == 8) && (offset >= 128))
410362306a36Sopenharmony_ci			write_opcode |= EEPROM_A8_OPCODE_SPI;
410462306a36Sopenharmony_ci
410562306a36Sopenharmony_ci		/* Send the Write command (8-bit opcode + addr) */
410662306a36Sopenharmony_ci		e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits);
410762306a36Sopenharmony_ci
410862306a36Sopenharmony_ci		e1000_shift_out_ee_bits(hw, (u16)((offset + widx) * 2),
410962306a36Sopenharmony_ci					eeprom->address_bits);
411062306a36Sopenharmony_ci
411162306a36Sopenharmony_ci		/* Send the data */
411262306a36Sopenharmony_ci
411362306a36Sopenharmony_ci		/* Loop to allow for up to whole page write (32 bytes) of
411462306a36Sopenharmony_ci		 * eeprom
411562306a36Sopenharmony_ci		 */
411662306a36Sopenharmony_ci		while (widx < words) {
411762306a36Sopenharmony_ci			u16 word_out = data[widx];
411862306a36Sopenharmony_ci
411962306a36Sopenharmony_ci			word_out = (word_out >> 8) | (word_out << 8);
412062306a36Sopenharmony_ci			e1000_shift_out_ee_bits(hw, word_out, 16);
412162306a36Sopenharmony_ci			widx++;
412262306a36Sopenharmony_ci
412362306a36Sopenharmony_ci			/* Some larger eeprom sizes are capable of a 32-byte
412462306a36Sopenharmony_ci			 * PAGE WRITE operation, while the smaller eeproms are
412562306a36Sopenharmony_ci			 * capable of an 8-byte PAGE WRITE operation.  Break the
412662306a36Sopenharmony_ci			 * inner loop to pass new address
412762306a36Sopenharmony_ci			 */
412862306a36Sopenharmony_ci			if ((((offset + widx) * 2) % eeprom->page_size) == 0) {
412962306a36Sopenharmony_ci				e1000_standby_eeprom(hw);
413062306a36Sopenharmony_ci				break;
413162306a36Sopenharmony_ci			}
413262306a36Sopenharmony_ci		}
413362306a36Sopenharmony_ci	}
413462306a36Sopenharmony_ci
413562306a36Sopenharmony_ci	return E1000_SUCCESS;
413662306a36Sopenharmony_ci}
413762306a36Sopenharmony_ci
413862306a36Sopenharmony_ci/**
413962306a36Sopenharmony_ci * e1000_write_eeprom_microwire - Writes a 16 bit word to a given offset in a Microwire EEPROM.
414062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
414162306a36Sopenharmony_ci * @offset: offset within the EEPROM to be written to
414262306a36Sopenharmony_ci * @words: number of words to write
414362306a36Sopenharmony_ci * @data: pointer to array of 8 bit words to be written to the EEPROM
414462306a36Sopenharmony_ci */
414562306a36Sopenharmony_cistatic s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
414662306a36Sopenharmony_ci					u16 words, u16 *data)
414762306a36Sopenharmony_ci{
414862306a36Sopenharmony_ci	struct e1000_eeprom_info *eeprom = &hw->eeprom;
414962306a36Sopenharmony_ci	u32 eecd;
415062306a36Sopenharmony_ci	u16 words_written = 0;
415162306a36Sopenharmony_ci	u16 i = 0;
415262306a36Sopenharmony_ci
415362306a36Sopenharmony_ci	/* Send the write enable command to the EEPROM (3-bit opcode plus
415462306a36Sopenharmony_ci	 * 6/8-bit dummy address beginning with 11).  It's less work to include
415562306a36Sopenharmony_ci	 * the 11 of the dummy address as part of the opcode than it is to shift
415662306a36Sopenharmony_ci	 * it over the correct number of bits for the address.  This puts the
415762306a36Sopenharmony_ci	 * EEPROM into write/erase mode.
415862306a36Sopenharmony_ci	 */
415962306a36Sopenharmony_ci	e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE,
416062306a36Sopenharmony_ci				(u16)(eeprom->opcode_bits + 2));
416162306a36Sopenharmony_ci
416262306a36Sopenharmony_ci	e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
416362306a36Sopenharmony_ci
416462306a36Sopenharmony_ci	/* Prepare the EEPROM */
416562306a36Sopenharmony_ci	e1000_standby_eeprom(hw);
416662306a36Sopenharmony_ci
416762306a36Sopenharmony_ci	while (words_written < words) {
416862306a36Sopenharmony_ci		/* Send the Write command (3-bit opcode + addr) */
416962306a36Sopenharmony_ci		e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE,
417062306a36Sopenharmony_ci					eeprom->opcode_bits);
417162306a36Sopenharmony_ci
417262306a36Sopenharmony_ci		e1000_shift_out_ee_bits(hw, (u16)(offset + words_written),
417362306a36Sopenharmony_ci					eeprom->address_bits);
417462306a36Sopenharmony_ci
417562306a36Sopenharmony_ci		/* Send the data */
417662306a36Sopenharmony_ci		e1000_shift_out_ee_bits(hw, data[words_written], 16);
417762306a36Sopenharmony_ci
417862306a36Sopenharmony_ci		/* Toggle the CS line.  This in effect tells the EEPROM to
417962306a36Sopenharmony_ci		 * execute the previous command.
418062306a36Sopenharmony_ci		 */
418162306a36Sopenharmony_ci		e1000_standby_eeprom(hw);
418262306a36Sopenharmony_ci
418362306a36Sopenharmony_ci		/* Read DO repeatedly until it is high (equal to '1').  The
418462306a36Sopenharmony_ci		 * EEPROM will signal that the command has been completed by
418562306a36Sopenharmony_ci		 * raising the DO signal. If DO does not go high in 10
418662306a36Sopenharmony_ci		 * milliseconds, then error out.
418762306a36Sopenharmony_ci		 */
418862306a36Sopenharmony_ci		for (i = 0; i < 200; i++) {
418962306a36Sopenharmony_ci			eecd = er32(EECD);
419062306a36Sopenharmony_ci			if (eecd & E1000_EECD_DO)
419162306a36Sopenharmony_ci				break;
419262306a36Sopenharmony_ci			udelay(50);
419362306a36Sopenharmony_ci		}
419462306a36Sopenharmony_ci		if (i == 200) {
419562306a36Sopenharmony_ci			e_dbg("EEPROM Write did not complete\n");
419662306a36Sopenharmony_ci			return -E1000_ERR_EEPROM;
419762306a36Sopenharmony_ci		}
419862306a36Sopenharmony_ci
419962306a36Sopenharmony_ci		/* Recover from write */
420062306a36Sopenharmony_ci		e1000_standby_eeprom(hw);
420162306a36Sopenharmony_ci		cond_resched();
420262306a36Sopenharmony_ci
420362306a36Sopenharmony_ci		words_written++;
420462306a36Sopenharmony_ci	}
420562306a36Sopenharmony_ci
420662306a36Sopenharmony_ci	/* Send the write disable command to the EEPROM (3-bit opcode plus
420762306a36Sopenharmony_ci	 * 6/8-bit dummy address beginning with 10).  It's less work to include
420862306a36Sopenharmony_ci	 * the 10 of the dummy address as part of the opcode than it is to shift
420962306a36Sopenharmony_ci	 * it over the correct number of bits for the address.  This takes the
421062306a36Sopenharmony_ci	 * EEPROM out of write/erase mode.
421162306a36Sopenharmony_ci	 */
421262306a36Sopenharmony_ci	e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE,
421362306a36Sopenharmony_ci				(u16)(eeprom->opcode_bits + 2));
421462306a36Sopenharmony_ci
421562306a36Sopenharmony_ci	e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
421662306a36Sopenharmony_ci
421762306a36Sopenharmony_ci	return E1000_SUCCESS;
421862306a36Sopenharmony_ci}
421962306a36Sopenharmony_ci
422062306a36Sopenharmony_ci/**
422162306a36Sopenharmony_ci * e1000_read_mac_addr - read the adapters MAC from eeprom
422262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
422362306a36Sopenharmony_ci *
422462306a36Sopenharmony_ci * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
422562306a36Sopenharmony_ci * second function of dual function devices
422662306a36Sopenharmony_ci */
422762306a36Sopenharmony_cis32 e1000_read_mac_addr(struct e1000_hw *hw)
422862306a36Sopenharmony_ci{
422962306a36Sopenharmony_ci	u16 offset;
423062306a36Sopenharmony_ci	u16 eeprom_data, i;
423162306a36Sopenharmony_ci
423262306a36Sopenharmony_ci	for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
423362306a36Sopenharmony_ci		offset = i >> 1;
423462306a36Sopenharmony_ci		if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
423562306a36Sopenharmony_ci			e_dbg("EEPROM Read Error\n");
423662306a36Sopenharmony_ci			return -E1000_ERR_EEPROM;
423762306a36Sopenharmony_ci		}
423862306a36Sopenharmony_ci		hw->perm_mac_addr[i] = (u8)(eeprom_data & 0x00FF);
423962306a36Sopenharmony_ci		hw->perm_mac_addr[i + 1] = (u8)(eeprom_data >> 8);
424062306a36Sopenharmony_ci	}
424162306a36Sopenharmony_ci
424262306a36Sopenharmony_ci	switch (hw->mac_type) {
424362306a36Sopenharmony_ci	default:
424462306a36Sopenharmony_ci		break;
424562306a36Sopenharmony_ci	case e1000_82546:
424662306a36Sopenharmony_ci	case e1000_82546_rev_3:
424762306a36Sopenharmony_ci		if (er32(STATUS) & E1000_STATUS_FUNC_1)
424862306a36Sopenharmony_ci			hw->perm_mac_addr[5] ^= 0x01;
424962306a36Sopenharmony_ci		break;
425062306a36Sopenharmony_ci	}
425162306a36Sopenharmony_ci
425262306a36Sopenharmony_ci	for (i = 0; i < NODE_ADDRESS_SIZE; i++)
425362306a36Sopenharmony_ci		hw->mac_addr[i] = hw->perm_mac_addr[i];
425462306a36Sopenharmony_ci	return E1000_SUCCESS;
425562306a36Sopenharmony_ci}
425662306a36Sopenharmony_ci
425762306a36Sopenharmony_ci/**
425862306a36Sopenharmony_ci * e1000_init_rx_addrs - Initializes receive address filters.
425962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
426062306a36Sopenharmony_ci *
426162306a36Sopenharmony_ci * Places the MAC address in receive address register 0 and clears the rest
426262306a36Sopenharmony_ci * of the receive address registers. Clears the multicast table. Assumes
426362306a36Sopenharmony_ci * the receiver is in reset when the routine is called.
426462306a36Sopenharmony_ci */
426562306a36Sopenharmony_cistatic void e1000_init_rx_addrs(struct e1000_hw *hw)
426662306a36Sopenharmony_ci{
426762306a36Sopenharmony_ci	u32 i;
426862306a36Sopenharmony_ci	u32 rar_num;
426962306a36Sopenharmony_ci
427062306a36Sopenharmony_ci	/* Setup the receive address. */
427162306a36Sopenharmony_ci	e_dbg("Programming MAC Address into RAR[0]\n");
427262306a36Sopenharmony_ci
427362306a36Sopenharmony_ci	e1000_rar_set(hw, hw->mac_addr, 0);
427462306a36Sopenharmony_ci
427562306a36Sopenharmony_ci	rar_num = E1000_RAR_ENTRIES;
427662306a36Sopenharmony_ci
427762306a36Sopenharmony_ci	/* Zero out the following 14 receive addresses. RAR[15] is for
427862306a36Sopenharmony_ci	 * manageability
427962306a36Sopenharmony_ci	 */
428062306a36Sopenharmony_ci	e_dbg("Clearing RAR[1-14]\n");
428162306a36Sopenharmony_ci	for (i = 1; i < rar_num; i++) {
428262306a36Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
428362306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
428462306a36Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
428562306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
428662306a36Sopenharmony_ci	}
428762306a36Sopenharmony_ci}
428862306a36Sopenharmony_ci
428962306a36Sopenharmony_ci/**
429062306a36Sopenharmony_ci * e1000_hash_mc_addr - Hashes an address to determine its location in the multicast table
429162306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
429262306a36Sopenharmony_ci * @mc_addr: the multicast address to hash
429362306a36Sopenharmony_ci */
429462306a36Sopenharmony_ciu32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
429562306a36Sopenharmony_ci{
429662306a36Sopenharmony_ci	u32 hash_value = 0;
429762306a36Sopenharmony_ci
429862306a36Sopenharmony_ci	/* The portion of the address that is used for the hash table is
429962306a36Sopenharmony_ci	 * determined by the mc_filter_type setting.
430062306a36Sopenharmony_ci	 */
430162306a36Sopenharmony_ci	switch (hw->mc_filter_type) {
430262306a36Sopenharmony_ci		/* [0] [1] [2] [3] [4] [5]
430362306a36Sopenharmony_ci		 * 01  AA  00  12  34  56
430462306a36Sopenharmony_ci		 * LSB                 MSB
430562306a36Sopenharmony_ci		 */
430662306a36Sopenharmony_ci	case 0:
430762306a36Sopenharmony_ci		/* [47:36] i.e. 0x563 for above example address */
430862306a36Sopenharmony_ci		hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
430962306a36Sopenharmony_ci		break;
431062306a36Sopenharmony_ci	case 1:
431162306a36Sopenharmony_ci		/* [46:35] i.e. 0xAC6 for above example address */
431262306a36Sopenharmony_ci		hash_value = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
431362306a36Sopenharmony_ci		break;
431462306a36Sopenharmony_ci	case 2:
431562306a36Sopenharmony_ci		/* [45:34] i.e. 0x5D8 for above example address */
431662306a36Sopenharmony_ci		hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
431762306a36Sopenharmony_ci		break;
431862306a36Sopenharmony_ci	case 3:
431962306a36Sopenharmony_ci		/* [43:32] i.e. 0x634 for above example address */
432062306a36Sopenharmony_ci		hash_value = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
432162306a36Sopenharmony_ci		break;
432262306a36Sopenharmony_ci	}
432362306a36Sopenharmony_ci
432462306a36Sopenharmony_ci	hash_value &= 0xFFF;
432562306a36Sopenharmony_ci	return hash_value;
432662306a36Sopenharmony_ci}
432762306a36Sopenharmony_ci
432862306a36Sopenharmony_ci/**
432962306a36Sopenharmony_ci * e1000_rar_set - Puts an ethernet address into a receive address register.
433062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
433162306a36Sopenharmony_ci * @addr: Address to put into receive address register
433262306a36Sopenharmony_ci * @index: Receive address register to write
433362306a36Sopenharmony_ci */
433462306a36Sopenharmony_civoid e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
433562306a36Sopenharmony_ci{
433662306a36Sopenharmony_ci	u32 rar_low, rar_high;
433762306a36Sopenharmony_ci
433862306a36Sopenharmony_ci	/* HW expects these in little endian so we reverse the byte order
433962306a36Sopenharmony_ci	 * from network order (big endian) to little endian
434062306a36Sopenharmony_ci	 */
434162306a36Sopenharmony_ci	rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
434262306a36Sopenharmony_ci		   ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
434362306a36Sopenharmony_ci	rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
434462306a36Sopenharmony_ci
434562306a36Sopenharmony_ci	/* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
434662306a36Sopenharmony_ci	 * unit hang.
434762306a36Sopenharmony_ci	 *
434862306a36Sopenharmony_ci	 * Description:
434962306a36Sopenharmony_ci	 * If there are any Rx frames queued up or otherwise present in the HW
435062306a36Sopenharmony_ci	 * before RSS is enabled, and then we enable RSS, the HW Rx unit will
435162306a36Sopenharmony_ci	 * hang.  To work around this issue, we have to disable receives and
435262306a36Sopenharmony_ci	 * flush out all Rx frames before we enable RSS. To do so, we modify we
435362306a36Sopenharmony_ci	 * redirect all Rx traffic to manageability and then reset the HW.
435462306a36Sopenharmony_ci	 * This flushes away Rx frames, and (since the redirections to
435562306a36Sopenharmony_ci	 * manageability persists across resets) keeps new ones from coming in
435662306a36Sopenharmony_ci	 * while we work.  Then, we clear the Address Valid AV bit for all MAC
435762306a36Sopenharmony_ci	 * addresses and undo the re-direction to manageability.
435862306a36Sopenharmony_ci	 * Now, frames are coming in again, but the MAC won't accept them, so
435962306a36Sopenharmony_ci	 * far so good.  We now proceed to initialize RSS (if necessary) and
436062306a36Sopenharmony_ci	 * configure the Rx unit.  Last, we re-enable the AV bits and continue
436162306a36Sopenharmony_ci	 * on our merry way.
436262306a36Sopenharmony_ci	 */
436362306a36Sopenharmony_ci	switch (hw->mac_type) {
436462306a36Sopenharmony_ci	default:
436562306a36Sopenharmony_ci		/* Indicate to hardware the Address is Valid. */
436662306a36Sopenharmony_ci		rar_high |= E1000_RAH_AV;
436762306a36Sopenharmony_ci		break;
436862306a36Sopenharmony_ci	}
436962306a36Sopenharmony_ci
437062306a36Sopenharmony_ci	E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
437162306a36Sopenharmony_ci	E1000_WRITE_FLUSH();
437262306a36Sopenharmony_ci	E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
437362306a36Sopenharmony_ci	E1000_WRITE_FLUSH();
437462306a36Sopenharmony_ci}
437562306a36Sopenharmony_ci
437662306a36Sopenharmony_ci/**
437762306a36Sopenharmony_ci * e1000_write_vfta - Writes a value to the specified offset in the VLAN filter table.
437862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
437962306a36Sopenharmony_ci * @offset: Offset in VLAN filter table to write
438062306a36Sopenharmony_ci * @value: Value to write into VLAN filter table
438162306a36Sopenharmony_ci */
438262306a36Sopenharmony_civoid e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
438362306a36Sopenharmony_ci{
438462306a36Sopenharmony_ci	u32 temp;
438562306a36Sopenharmony_ci
438662306a36Sopenharmony_ci	if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
438762306a36Sopenharmony_ci		temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
438862306a36Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
438962306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
439062306a36Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
439162306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
439262306a36Sopenharmony_ci	} else {
439362306a36Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
439462306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
439562306a36Sopenharmony_ci	}
439662306a36Sopenharmony_ci}
439762306a36Sopenharmony_ci
439862306a36Sopenharmony_ci/**
439962306a36Sopenharmony_ci * e1000_clear_vfta - Clears the VLAN filter table
440062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
440162306a36Sopenharmony_ci */
440262306a36Sopenharmony_cistatic void e1000_clear_vfta(struct e1000_hw *hw)
440362306a36Sopenharmony_ci{
440462306a36Sopenharmony_ci	u32 offset;
440562306a36Sopenharmony_ci
440662306a36Sopenharmony_ci	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
440762306a36Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
440862306a36Sopenharmony_ci		E1000_WRITE_FLUSH();
440962306a36Sopenharmony_ci	}
441062306a36Sopenharmony_ci}
441162306a36Sopenharmony_ci
441262306a36Sopenharmony_cistatic s32 e1000_id_led_init(struct e1000_hw *hw)
441362306a36Sopenharmony_ci{
441462306a36Sopenharmony_ci	u32 ledctl;
441562306a36Sopenharmony_ci	const u32 ledctl_mask = 0x000000FF;
441662306a36Sopenharmony_ci	const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
441762306a36Sopenharmony_ci	const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
441862306a36Sopenharmony_ci	u16 eeprom_data, i, temp;
441962306a36Sopenharmony_ci	const u16 led_mask = 0x0F;
442062306a36Sopenharmony_ci
442162306a36Sopenharmony_ci	if (hw->mac_type < e1000_82540) {
442262306a36Sopenharmony_ci		/* Nothing to do */
442362306a36Sopenharmony_ci		return E1000_SUCCESS;
442462306a36Sopenharmony_ci	}
442562306a36Sopenharmony_ci
442662306a36Sopenharmony_ci	ledctl = er32(LEDCTL);
442762306a36Sopenharmony_ci	hw->ledctl_default = ledctl;
442862306a36Sopenharmony_ci	hw->ledctl_mode1 = hw->ledctl_default;
442962306a36Sopenharmony_ci	hw->ledctl_mode2 = hw->ledctl_default;
443062306a36Sopenharmony_ci
443162306a36Sopenharmony_ci	if (e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) {
443262306a36Sopenharmony_ci		e_dbg("EEPROM Read Error\n");
443362306a36Sopenharmony_ci		return -E1000_ERR_EEPROM;
443462306a36Sopenharmony_ci	}
443562306a36Sopenharmony_ci
443662306a36Sopenharmony_ci	if ((eeprom_data == ID_LED_RESERVED_0000) ||
443762306a36Sopenharmony_ci	    (eeprom_data == ID_LED_RESERVED_FFFF)) {
443862306a36Sopenharmony_ci		eeprom_data = ID_LED_DEFAULT;
443962306a36Sopenharmony_ci	}
444062306a36Sopenharmony_ci
444162306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
444262306a36Sopenharmony_ci		temp = (eeprom_data >> (i << 2)) & led_mask;
444362306a36Sopenharmony_ci		switch (temp) {
444462306a36Sopenharmony_ci		case ID_LED_ON1_DEF2:
444562306a36Sopenharmony_ci		case ID_LED_ON1_ON2:
444662306a36Sopenharmony_ci		case ID_LED_ON1_OFF2:
444762306a36Sopenharmony_ci			hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
444862306a36Sopenharmony_ci			hw->ledctl_mode1 |= ledctl_on << (i << 3);
444962306a36Sopenharmony_ci			break;
445062306a36Sopenharmony_ci		case ID_LED_OFF1_DEF2:
445162306a36Sopenharmony_ci		case ID_LED_OFF1_ON2:
445262306a36Sopenharmony_ci		case ID_LED_OFF1_OFF2:
445362306a36Sopenharmony_ci			hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
445462306a36Sopenharmony_ci			hw->ledctl_mode1 |= ledctl_off << (i << 3);
445562306a36Sopenharmony_ci			break;
445662306a36Sopenharmony_ci		default:
445762306a36Sopenharmony_ci			/* Do nothing */
445862306a36Sopenharmony_ci			break;
445962306a36Sopenharmony_ci		}
446062306a36Sopenharmony_ci		switch (temp) {
446162306a36Sopenharmony_ci		case ID_LED_DEF1_ON2:
446262306a36Sopenharmony_ci		case ID_LED_ON1_ON2:
446362306a36Sopenharmony_ci		case ID_LED_OFF1_ON2:
446462306a36Sopenharmony_ci			hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
446562306a36Sopenharmony_ci			hw->ledctl_mode2 |= ledctl_on << (i << 3);
446662306a36Sopenharmony_ci			break;
446762306a36Sopenharmony_ci		case ID_LED_DEF1_OFF2:
446862306a36Sopenharmony_ci		case ID_LED_ON1_OFF2:
446962306a36Sopenharmony_ci		case ID_LED_OFF1_OFF2:
447062306a36Sopenharmony_ci			hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
447162306a36Sopenharmony_ci			hw->ledctl_mode2 |= ledctl_off << (i << 3);
447262306a36Sopenharmony_ci			break;
447362306a36Sopenharmony_ci		default:
447462306a36Sopenharmony_ci			/* Do nothing */
447562306a36Sopenharmony_ci			break;
447662306a36Sopenharmony_ci		}
447762306a36Sopenharmony_ci	}
447862306a36Sopenharmony_ci	return E1000_SUCCESS;
447962306a36Sopenharmony_ci}
448062306a36Sopenharmony_ci
448162306a36Sopenharmony_ci/**
448262306a36Sopenharmony_ci * e1000_setup_led
448362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
448462306a36Sopenharmony_ci *
448562306a36Sopenharmony_ci * Prepares SW controlable LED for use and saves the current state of the LED.
448662306a36Sopenharmony_ci */
448762306a36Sopenharmony_cis32 e1000_setup_led(struct e1000_hw *hw)
448862306a36Sopenharmony_ci{
448962306a36Sopenharmony_ci	u32 ledctl;
449062306a36Sopenharmony_ci	s32 ret_val = E1000_SUCCESS;
449162306a36Sopenharmony_ci
449262306a36Sopenharmony_ci	switch (hw->mac_type) {
449362306a36Sopenharmony_ci	case e1000_82542_rev2_0:
449462306a36Sopenharmony_ci	case e1000_82542_rev2_1:
449562306a36Sopenharmony_ci	case e1000_82543:
449662306a36Sopenharmony_ci	case e1000_82544:
449762306a36Sopenharmony_ci		/* No setup necessary */
449862306a36Sopenharmony_ci		break;
449962306a36Sopenharmony_ci	case e1000_82541:
450062306a36Sopenharmony_ci	case e1000_82547:
450162306a36Sopenharmony_ci	case e1000_82541_rev_2:
450262306a36Sopenharmony_ci	case e1000_82547_rev_2:
450362306a36Sopenharmony_ci		/* Turn off PHY Smart Power Down (if enabled) */
450462306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO,
450562306a36Sopenharmony_ci					     &hw->phy_spd_default);
450662306a36Sopenharmony_ci		if (ret_val)
450762306a36Sopenharmony_ci			return ret_val;
450862306a36Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
450962306a36Sopenharmony_ci					      (u16)(hw->phy_spd_default &
451062306a36Sopenharmony_ci						     ~IGP01E1000_GMII_SPD));
451162306a36Sopenharmony_ci		if (ret_val)
451262306a36Sopenharmony_ci			return ret_val;
451362306a36Sopenharmony_ci		fallthrough;
451462306a36Sopenharmony_ci	default:
451562306a36Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
451662306a36Sopenharmony_ci			ledctl = er32(LEDCTL);
451762306a36Sopenharmony_ci			/* Save current LEDCTL settings */
451862306a36Sopenharmony_ci			hw->ledctl_default = ledctl;
451962306a36Sopenharmony_ci			/* Turn off LED0 */
452062306a36Sopenharmony_ci			ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
452162306a36Sopenharmony_ci				    E1000_LEDCTL_LED0_BLINK |
452262306a36Sopenharmony_ci				    E1000_LEDCTL_LED0_MODE_MASK);
452362306a36Sopenharmony_ci			ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
452462306a36Sopenharmony_ci				   E1000_LEDCTL_LED0_MODE_SHIFT);
452562306a36Sopenharmony_ci			ew32(LEDCTL, ledctl);
452662306a36Sopenharmony_ci		} else if (hw->media_type == e1000_media_type_copper)
452762306a36Sopenharmony_ci			ew32(LEDCTL, hw->ledctl_mode1);
452862306a36Sopenharmony_ci		break;
452962306a36Sopenharmony_ci	}
453062306a36Sopenharmony_ci
453162306a36Sopenharmony_ci	return E1000_SUCCESS;
453262306a36Sopenharmony_ci}
453362306a36Sopenharmony_ci
453462306a36Sopenharmony_ci/**
453562306a36Sopenharmony_ci * e1000_cleanup_led - Restores the saved state of the SW controlable LED.
453662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
453762306a36Sopenharmony_ci */
453862306a36Sopenharmony_cis32 e1000_cleanup_led(struct e1000_hw *hw)
453962306a36Sopenharmony_ci{
454062306a36Sopenharmony_ci	s32 ret_val = E1000_SUCCESS;
454162306a36Sopenharmony_ci
454262306a36Sopenharmony_ci	switch (hw->mac_type) {
454362306a36Sopenharmony_ci	case e1000_82542_rev2_0:
454462306a36Sopenharmony_ci	case e1000_82542_rev2_1:
454562306a36Sopenharmony_ci	case e1000_82543:
454662306a36Sopenharmony_ci	case e1000_82544:
454762306a36Sopenharmony_ci		/* No cleanup necessary */
454862306a36Sopenharmony_ci		break;
454962306a36Sopenharmony_ci	case e1000_82541:
455062306a36Sopenharmony_ci	case e1000_82547:
455162306a36Sopenharmony_ci	case e1000_82541_rev_2:
455262306a36Sopenharmony_ci	case e1000_82547_rev_2:
455362306a36Sopenharmony_ci		/* Turn on PHY Smart Power Down (if previously enabled) */
455462306a36Sopenharmony_ci		ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
455562306a36Sopenharmony_ci					      hw->phy_spd_default);
455662306a36Sopenharmony_ci		if (ret_val)
455762306a36Sopenharmony_ci			return ret_val;
455862306a36Sopenharmony_ci		fallthrough;
455962306a36Sopenharmony_ci	default:
456062306a36Sopenharmony_ci		/* Restore LEDCTL settings */
456162306a36Sopenharmony_ci		ew32(LEDCTL, hw->ledctl_default);
456262306a36Sopenharmony_ci		break;
456362306a36Sopenharmony_ci	}
456462306a36Sopenharmony_ci
456562306a36Sopenharmony_ci	return E1000_SUCCESS;
456662306a36Sopenharmony_ci}
456762306a36Sopenharmony_ci
456862306a36Sopenharmony_ci/**
456962306a36Sopenharmony_ci * e1000_led_on - Turns on the software controllable LED
457062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
457162306a36Sopenharmony_ci */
457262306a36Sopenharmony_cis32 e1000_led_on(struct e1000_hw *hw)
457362306a36Sopenharmony_ci{
457462306a36Sopenharmony_ci	u32 ctrl = er32(CTRL);
457562306a36Sopenharmony_ci
457662306a36Sopenharmony_ci	switch (hw->mac_type) {
457762306a36Sopenharmony_ci	case e1000_82542_rev2_0:
457862306a36Sopenharmony_ci	case e1000_82542_rev2_1:
457962306a36Sopenharmony_ci	case e1000_82543:
458062306a36Sopenharmony_ci		/* Set SW Defineable Pin 0 to turn on the LED */
458162306a36Sopenharmony_ci		ctrl |= E1000_CTRL_SWDPIN0;
458262306a36Sopenharmony_ci		ctrl |= E1000_CTRL_SWDPIO0;
458362306a36Sopenharmony_ci		break;
458462306a36Sopenharmony_ci	case e1000_82544:
458562306a36Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
458662306a36Sopenharmony_ci			/* Set SW Defineable Pin 0 to turn on the LED */
458762306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIN0;
458862306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
458962306a36Sopenharmony_ci		} else {
459062306a36Sopenharmony_ci			/* Clear SW Defineable Pin 0 to turn on the LED */
459162306a36Sopenharmony_ci			ctrl &= ~E1000_CTRL_SWDPIN0;
459262306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
459362306a36Sopenharmony_ci		}
459462306a36Sopenharmony_ci		break;
459562306a36Sopenharmony_ci	default:
459662306a36Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
459762306a36Sopenharmony_ci			/* Clear SW Defineable Pin 0 to turn on the LED */
459862306a36Sopenharmony_ci			ctrl &= ~E1000_CTRL_SWDPIN0;
459962306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
460062306a36Sopenharmony_ci		} else if (hw->media_type == e1000_media_type_copper) {
460162306a36Sopenharmony_ci			ew32(LEDCTL, hw->ledctl_mode2);
460262306a36Sopenharmony_ci			return E1000_SUCCESS;
460362306a36Sopenharmony_ci		}
460462306a36Sopenharmony_ci		break;
460562306a36Sopenharmony_ci	}
460662306a36Sopenharmony_ci
460762306a36Sopenharmony_ci	ew32(CTRL, ctrl);
460862306a36Sopenharmony_ci
460962306a36Sopenharmony_ci	return E1000_SUCCESS;
461062306a36Sopenharmony_ci}
461162306a36Sopenharmony_ci
461262306a36Sopenharmony_ci/**
461362306a36Sopenharmony_ci * e1000_led_off - Turns off the software controllable LED
461462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
461562306a36Sopenharmony_ci */
461662306a36Sopenharmony_cis32 e1000_led_off(struct e1000_hw *hw)
461762306a36Sopenharmony_ci{
461862306a36Sopenharmony_ci	u32 ctrl = er32(CTRL);
461962306a36Sopenharmony_ci
462062306a36Sopenharmony_ci	switch (hw->mac_type) {
462162306a36Sopenharmony_ci	case e1000_82542_rev2_0:
462262306a36Sopenharmony_ci	case e1000_82542_rev2_1:
462362306a36Sopenharmony_ci	case e1000_82543:
462462306a36Sopenharmony_ci		/* Clear SW Defineable Pin 0 to turn off the LED */
462562306a36Sopenharmony_ci		ctrl &= ~E1000_CTRL_SWDPIN0;
462662306a36Sopenharmony_ci		ctrl |= E1000_CTRL_SWDPIO0;
462762306a36Sopenharmony_ci		break;
462862306a36Sopenharmony_ci	case e1000_82544:
462962306a36Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
463062306a36Sopenharmony_ci			/* Clear SW Defineable Pin 0 to turn off the LED */
463162306a36Sopenharmony_ci			ctrl &= ~E1000_CTRL_SWDPIN0;
463262306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
463362306a36Sopenharmony_ci		} else {
463462306a36Sopenharmony_ci			/* Set SW Defineable Pin 0 to turn off the LED */
463562306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIN0;
463662306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
463762306a36Sopenharmony_ci		}
463862306a36Sopenharmony_ci		break;
463962306a36Sopenharmony_ci	default:
464062306a36Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber) {
464162306a36Sopenharmony_ci			/* Set SW Defineable Pin 0 to turn off the LED */
464262306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIN0;
464362306a36Sopenharmony_ci			ctrl |= E1000_CTRL_SWDPIO0;
464462306a36Sopenharmony_ci		} else if (hw->media_type == e1000_media_type_copper) {
464562306a36Sopenharmony_ci			ew32(LEDCTL, hw->ledctl_mode1);
464662306a36Sopenharmony_ci			return E1000_SUCCESS;
464762306a36Sopenharmony_ci		}
464862306a36Sopenharmony_ci		break;
464962306a36Sopenharmony_ci	}
465062306a36Sopenharmony_ci
465162306a36Sopenharmony_ci	ew32(CTRL, ctrl);
465262306a36Sopenharmony_ci
465362306a36Sopenharmony_ci	return E1000_SUCCESS;
465462306a36Sopenharmony_ci}
465562306a36Sopenharmony_ci
465662306a36Sopenharmony_ci/**
465762306a36Sopenharmony_ci * e1000_clear_hw_cntrs - Clears all hardware statistics counters.
465862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
465962306a36Sopenharmony_ci */
466062306a36Sopenharmony_cistatic void e1000_clear_hw_cntrs(struct e1000_hw *hw)
466162306a36Sopenharmony_ci{
466262306a36Sopenharmony_ci	er32(CRCERRS);
466362306a36Sopenharmony_ci	er32(SYMERRS);
466462306a36Sopenharmony_ci	er32(MPC);
466562306a36Sopenharmony_ci	er32(SCC);
466662306a36Sopenharmony_ci	er32(ECOL);
466762306a36Sopenharmony_ci	er32(MCC);
466862306a36Sopenharmony_ci	er32(LATECOL);
466962306a36Sopenharmony_ci	er32(COLC);
467062306a36Sopenharmony_ci	er32(DC);
467162306a36Sopenharmony_ci	er32(SEC);
467262306a36Sopenharmony_ci	er32(RLEC);
467362306a36Sopenharmony_ci	er32(XONRXC);
467462306a36Sopenharmony_ci	er32(XONTXC);
467562306a36Sopenharmony_ci	er32(XOFFRXC);
467662306a36Sopenharmony_ci	er32(XOFFTXC);
467762306a36Sopenharmony_ci	er32(FCRUC);
467862306a36Sopenharmony_ci
467962306a36Sopenharmony_ci	er32(PRC64);
468062306a36Sopenharmony_ci	er32(PRC127);
468162306a36Sopenharmony_ci	er32(PRC255);
468262306a36Sopenharmony_ci	er32(PRC511);
468362306a36Sopenharmony_ci	er32(PRC1023);
468462306a36Sopenharmony_ci	er32(PRC1522);
468562306a36Sopenharmony_ci
468662306a36Sopenharmony_ci	er32(GPRC);
468762306a36Sopenharmony_ci	er32(BPRC);
468862306a36Sopenharmony_ci	er32(MPRC);
468962306a36Sopenharmony_ci	er32(GPTC);
469062306a36Sopenharmony_ci	er32(GORCL);
469162306a36Sopenharmony_ci	er32(GORCH);
469262306a36Sopenharmony_ci	er32(GOTCL);
469362306a36Sopenharmony_ci	er32(GOTCH);
469462306a36Sopenharmony_ci	er32(RNBC);
469562306a36Sopenharmony_ci	er32(RUC);
469662306a36Sopenharmony_ci	er32(RFC);
469762306a36Sopenharmony_ci	er32(ROC);
469862306a36Sopenharmony_ci	er32(RJC);
469962306a36Sopenharmony_ci	er32(TORL);
470062306a36Sopenharmony_ci	er32(TORH);
470162306a36Sopenharmony_ci	er32(TOTL);
470262306a36Sopenharmony_ci	er32(TOTH);
470362306a36Sopenharmony_ci	er32(TPR);
470462306a36Sopenharmony_ci	er32(TPT);
470562306a36Sopenharmony_ci
470662306a36Sopenharmony_ci	er32(PTC64);
470762306a36Sopenharmony_ci	er32(PTC127);
470862306a36Sopenharmony_ci	er32(PTC255);
470962306a36Sopenharmony_ci	er32(PTC511);
471062306a36Sopenharmony_ci	er32(PTC1023);
471162306a36Sopenharmony_ci	er32(PTC1522);
471262306a36Sopenharmony_ci
471362306a36Sopenharmony_ci	er32(MPTC);
471462306a36Sopenharmony_ci	er32(BPTC);
471562306a36Sopenharmony_ci
471662306a36Sopenharmony_ci	if (hw->mac_type < e1000_82543)
471762306a36Sopenharmony_ci		return;
471862306a36Sopenharmony_ci
471962306a36Sopenharmony_ci	er32(ALGNERRC);
472062306a36Sopenharmony_ci	er32(RXERRC);
472162306a36Sopenharmony_ci	er32(TNCRS);
472262306a36Sopenharmony_ci	er32(CEXTERR);
472362306a36Sopenharmony_ci	er32(TSCTC);
472462306a36Sopenharmony_ci	er32(TSCTFC);
472562306a36Sopenharmony_ci
472662306a36Sopenharmony_ci	if (hw->mac_type <= e1000_82544)
472762306a36Sopenharmony_ci		return;
472862306a36Sopenharmony_ci
472962306a36Sopenharmony_ci	er32(MGTPRC);
473062306a36Sopenharmony_ci	er32(MGTPDC);
473162306a36Sopenharmony_ci	er32(MGTPTC);
473262306a36Sopenharmony_ci}
473362306a36Sopenharmony_ci
473462306a36Sopenharmony_ci/**
473562306a36Sopenharmony_ci * e1000_reset_adaptive - Resets Adaptive IFS to its default state.
473662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
473762306a36Sopenharmony_ci *
473862306a36Sopenharmony_ci * Call this after e1000_init_hw. You may override the IFS defaults by setting
473962306a36Sopenharmony_ci * hw->ifs_params_forced to true. However, you must initialize hw->
474062306a36Sopenharmony_ci * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
474162306a36Sopenharmony_ci * before calling this function.
474262306a36Sopenharmony_ci */
474362306a36Sopenharmony_civoid e1000_reset_adaptive(struct e1000_hw *hw)
474462306a36Sopenharmony_ci{
474562306a36Sopenharmony_ci	if (hw->adaptive_ifs) {
474662306a36Sopenharmony_ci		if (!hw->ifs_params_forced) {
474762306a36Sopenharmony_ci			hw->current_ifs_val = 0;
474862306a36Sopenharmony_ci			hw->ifs_min_val = IFS_MIN;
474962306a36Sopenharmony_ci			hw->ifs_max_val = IFS_MAX;
475062306a36Sopenharmony_ci			hw->ifs_step_size = IFS_STEP;
475162306a36Sopenharmony_ci			hw->ifs_ratio = IFS_RATIO;
475262306a36Sopenharmony_ci		}
475362306a36Sopenharmony_ci		hw->in_ifs_mode = false;
475462306a36Sopenharmony_ci		ew32(AIT, 0);
475562306a36Sopenharmony_ci	} else {
475662306a36Sopenharmony_ci		e_dbg("Not in Adaptive IFS mode!\n");
475762306a36Sopenharmony_ci	}
475862306a36Sopenharmony_ci}
475962306a36Sopenharmony_ci
476062306a36Sopenharmony_ci/**
476162306a36Sopenharmony_ci * e1000_update_adaptive - update adaptive IFS
476262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
476362306a36Sopenharmony_ci *
476462306a36Sopenharmony_ci * Called during the callback/watchdog routine to update IFS value based on
476562306a36Sopenharmony_ci * the ratio of transmits to collisions.
476662306a36Sopenharmony_ci */
476762306a36Sopenharmony_civoid e1000_update_adaptive(struct e1000_hw *hw)
476862306a36Sopenharmony_ci{
476962306a36Sopenharmony_ci	if (hw->adaptive_ifs) {
477062306a36Sopenharmony_ci		if ((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) {
477162306a36Sopenharmony_ci			if (hw->tx_packet_delta > MIN_NUM_XMITS) {
477262306a36Sopenharmony_ci				hw->in_ifs_mode = true;
477362306a36Sopenharmony_ci				if (hw->current_ifs_val < hw->ifs_max_val) {
477462306a36Sopenharmony_ci					if (hw->current_ifs_val == 0)
477562306a36Sopenharmony_ci						hw->current_ifs_val =
477662306a36Sopenharmony_ci						    hw->ifs_min_val;
477762306a36Sopenharmony_ci					else
477862306a36Sopenharmony_ci						hw->current_ifs_val +=
477962306a36Sopenharmony_ci						    hw->ifs_step_size;
478062306a36Sopenharmony_ci					ew32(AIT, hw->current_ifs_val);
478162306a36Sopenharmony_ci				}
478262306a36Sopenharmony_ci			}
478362306a36Sopenharmony_ci		} else {
478462306a36Sopenharmony_ci			if (hw->in_ifs_mode &&
478562306a36Sopenharmony_ci			    (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
478662306a36Sopenharmony_ci				hw->current_ifs_val = 0;
478762306a36Sopenharmony_ci				hw->in_ifs_mode = false;
478862306a36Sopenharmony_ci				ew32(AIT, 0);
478962306a36Sopenharmony_ci			}
479062306a36Sopenharmony_ci		}
479162306a36Sopenharmony_ci	} else {
479262306a36Sopenharmony_ci		e_dbg("Not in Adaptive IFS mode!\n");
479362306a36Sopenharmony_ci	}
479462306a36Sopenharmony_ci}
479562306a36Sopenharmony_ci
479662306a36Sopenharmony_ci/**
479762306a36Sopenharmony_ci * e1000_get_bus_info
479862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
479962306a36Sopenharmony_ci *
480062306a36Sopenharmony_ci * Gets the current PCI bus type, speed, and width of the hardware
480162306a36Sopenharmony_ci */
480262306a36Sopenharmony_civoid e1000_get_bus_info(struct e1000_hw *hw)
480362306a36Sopenharmony_ci{
480462306a36Sopenharmony_ci	u32 status;
480562306a36Sopenharmony_ci
480662306a36Sopenharmony_ci	switch (hw->mac_type) {
480762306a36Sopenharmony_ci	case e1000_82542_rev2_0:
480862306a36Sopenharmony_ci	case e1000_82542_rev2_1:
480962306a36Sopenharmony_ci		hw->bus_type = e1000_bus_type_pci;
481062306a36Sopenharmony_ci		hw->bus_speed = e1000_bus_speed_unknown;
481162306a36Sopenharmony_ci		hw->bus_width = e1000_bus_width_unknown;
481262306a36Sopenharmony_ci		break;
481362306a36Sopenharmony_ci	default:
481462306a36Sopenharmony_ci		status = er32(STATUS);
481562306a36Sopenharmony_ci		hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
481662306a36Sopenharmony_ci		    e1000_bus_type_pcix : e1000_bus_type_pci;
481762306a36Sopenharmony_ci
481862306a36Sopenharmony_ci		if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
481962306a36Sopenharmony_ci			hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
482062306a36Sopenharmony_ci			    e1000_bus_speed_66 : e1000_bus_speed_120;
482162306a36Sopenharmony_ci		} else if (hw->bus_type == e1000_bus_type_pci) {
482262306a36Sopenharmony_ci			hw->bus_speed = (status & E1000_STATUS_PCI66) ?
482362306a36Sopenharmony_ci			    e1000_bus_speed_66 : e1000_bus_speed_33;
482462306a36Sopenharmony_ci		} else {
482562306a36Sopenharmony_ci			switch (status & E1000_STATUS_PCIX_SPEED) {
482662306a36Sopenharmony_ci			case E1000_STATUS_PCIX_SPEED_66:
482762306a36Sopenharmony_ci				hw->bus_speed = e1000_bus_speed_66;
482862306a36Sopenharmony_ci				break;
482962306a36Sopenharmony_ci			case E1000_STATUS_PCIX_SPEED_100:
483062306a36Sopenharmony_ci				hw->bus_speed = e1000_bus_speed_100;
483162306a36Sopenharmony_ci				break;
483262306a36Sopenharmony_ci			case E1000_STATUS_PCIX_SPEED_133:
483362306a36Sopenharmony_ci				hw->bus_speed = e1000_bus_speed_133;
483462306a36Sopenharmony_ci				break;
483562306a36Sopenharmony_ci			default:
483662306a36Sopenharmony_ci				hw->bus_speed = e1000_bus_speed_reserved;
483762306a36Sopenharmony_ci				break;
483862306a36Sopenharmony_ci			}
483962306a36Sopenharmony_ci		}
484062306a36Sopenharmony_ci		hw->bus_width = (status & E1000_STATUS_BUS64) ?
484162306a36Sopenharmony_ci		    e1000_bus_width_64 : e1000_bus_width_32;
484262306a36Sopenharmony_ci		break;
484362306a36Sopenharmony_ci	}
484462306a36Sopenharmony_ci}
484562306a36Sopenharmony_ci
484662306a36Sopenharmony_ci/**
484762306a36Sopenharmony_ci * e1000_write_reg_io
484862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
484962306a36Sopenharmony_ci * @offset: offset to write to
485062306a36Sopenharmony_ci * @value: value to write
485162306a36Sopenharmony_ci *
485262306a36Sopenharmony_ci * Writes a value to one of the devices registers using port I/O (as opposed to
485362306a36Sopenharmony_ci * memory mapped I/O). Only 82544 and newer devices support port I/O.
485462306a36Sopenharmony_ci */
485562306a36Sopenharmony_cistatic void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value)
485662306a36Sopenharmony_ci{
485762306a36Sopenharmony_ci	unsigned long io_addr = hw->io_base;
485862306a36Sopenharmony_ci	unsigned long io_data = hw->io_base + 4;
485962306a36Sopenharmony_ci
486062306a36Sopenharmony_ci	e1000_io_write(hw, io_addr, offset);
486162306a36Sopenharmony_ci	e1000_io_write(hw, io_data, value);
486262306a36Sopenharmony_ci}
486362306a36Sopenharmony_ci
486462306a36Sopenharmony_ci/**
486562306a36Sopenharmony_ci * e1000_get_cable_length - Estimates the cable length.
486662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
486762306a36Sopenharmony_ci * @min_length: The estimated minimum length
486862306a36Sopenharmony_ci * @max_length: The estimated maximum length
486962306a36Sopenharmony_ci *
487062306a36Sopenharmony_ci * returns: - E1000_ERR_XXX
487162306a36Sopenharmony_ci *            E1000_SUCCESS
487262306a36Sopenharmony_ci *
487362306a36Sopenharmony_ci * This function always returns a ranged length (minimum & maximum).
487462306a36Sopenharmony_ci * So for M88 phy's, this function interprets the one value returned from the
487562306a36Sopenharmony_ci * register to the minimum and maximum range.
487662306a36Sopenharmony_ci * For IGP phy's, the function calculates the range by the AGC registers.
487762306a36Sopenharmony_ci */
487862306a36Sopenharmony_cistatic s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
487962306a36Sopenharmony_ci				  u16 *max_length)
488062306a36Sopenharmony_ci{
488162306a36Sopenharmony_ci	s32 ret_val;
488262306a36Sopenharmony_ci	u16 agc_value = 0;
488362306a36Sopenharmony_ci	u16 i, phy_data;
488462306a36Sopenharmony_ci	u16 cable_length;
488562306a36Sopenharmony_ci
488662306a36Sopenharmony_ci	*min_length = *max_length = 0;
488762306a36Sopenharmony_ci
488862306a36Sopenharmony_ci	/* Use old method for Phy older than IGP */
488962306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_m88) {
489062306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
489162306a36Sopenharmony_ci					     &phy_data);
489262306a36Sopenharmony_ci		if (ret_val)
489362306a36Sopenharmony_ci			return ret_val;
489462306a36Sopenharmony_ci		cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
489562306a36Sopenharmony_ci		    M88E1000_PSSR_CABLE_LENGTH_SHIFT;
489662306a36Sopenharmony_ci
489762306a36Sopenharmony_ci		/* Convert the enum value to ranged values */
489862306a36Sopenharmony_ci		switch (cable_length) {
489962306a36Sopenharmony_ci		case e1000_cable_length_50:
490062306a36Sopenharmony_ci			*min_length = 0;
490162306a36Sopenharmony_ci			*max_length = e1000_igp_cable_length_50;
490262306a36Sopenharmony_ci			break;
490362306a36Sopenharmony_ci		case e1000_cable_length_50_80:
490462306a36Sopenharmony_ci			*min_length = e1000_igp_cable_length_50;
490562306a36Sopenharmony_ci			*max_length = e1000_igp_cable_length_80;
490662306a36Sopenharmony_ci			break;
490762306a36Sopenharmony_ci		case e1000_cable_length_80_110:
490862306a36Sopenharmony_ci			*min_length = e1000_igp_cable_length_80;
490962306a36Sopenharmony_ci			*max_length = e1000_igp_cable_length_110;
491062306a36Sopenharmony_ci			break;
491162306a36Sopenharmony_ci		case e1000_cable_length_110_140:
491262306a36Sopenharmony_ci			*min_length = e1000_igp_cable_length_110;
491362306a36Sopenharmony_ci			*max_length = e1000_igp_cable_length_140;
491462306a36Sopenharmony_ci			break;
491562306a36Sopenharmony_ci		case e1000_cable_length_140:
491662306a36Sopenharmony_ci			*min_length = e1000_igp_cable_length_140;
491762306a36Sopenharmony_ci			*max_length = e1000_igp_cable_length_170;
491862306a36Sopenharmony_ci			break;
491962306a36Sopenharmony_ci		default:
492062306a36Sopenharmony_ci			return -E1000_ERR_PHY;
492162306a36Sopenharmony_ci		}
492262306a36Sopenharmony_ci	} else if (hw->phy_type == e1000_phy_igp) {	/* For IGP PHY */
492362306a36Sopenharmony_ci		u16 cur_agc_value;
492462306a36Sopenharmony_ci		u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
492562306a36Sopenharmony_ci		static const u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
492662306a36Sopenharmony_ci		       IGP01E1000_PHY_AGC_A,
492762306a36Sopenharmony_ci		       IGP01E1000_PHY_AGC_B,
492862306a36Sopenharmony_ci		       IGP01E1000_PHY_AGC_C,
492962306a36Sopenharmony_ci		       IGP01E1000_PHY_AGC_D
493062306a36Sopenharmony_ci		};
493162306a36Sopenharmony_ci		/* Read the AGC registers for all channels */
493262306a36Sopenharmony_ci		for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
493362306a36Sopenharmony_ci			ret_val =
493462306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
493562306a36Sopenharmony_ci			if (ret_val)
493662306a36Sopenharmony_ci				return ret_val;
493762306a36Sopenharmony_ci
493862306a36Sopenharmony_ci			cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
493962306a36Sopenharmony_ci
494062306a36Sopenharmony_ci			/* Value bound check. */
494162306a36Sopenharmony_ci			if ((cur_agc_value >=
494262306a36Sopenharmony_ci			     IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
494362306a36Sopenharmony_ci			    (cur_agc_value == 0))
494462306a36Sopenharmony_ci				return -E1000_ERR_PHY;
494562306a36Sopenharmony_ci
494662306a36Sopenharmony_ci			agc_value += cur_agc_value;
494762306a36Sopenharmony_ci
494862306a36Sopenharmony_ci			/* Update minimal AGC value. */
494962306a36Sopenharmony_ci			if (min_agc_value > cur_agc_value)
495062306a36Sopenharmony_ci				min_agc_value = cur_agc_value;
495162306a36Sopenharmony_ci		}
495262306a36Sopenharmony_ci
495362306a36Sopenharmony_ci		/* Remove the minimal AGC result for length < 50m */
495462306a36Sopenharmony_ci		if (agc_value <
495562306a36Sopenharmony_ci		    IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) {
495662306a36Sopenharmony_ci			agc_value -= min_agc_value;
495762306a36Sopenharmony_ci
495862306a36Sopenharmony_ci			/* Get the average length of the remaining 3 channels */
495962306a36Sopenharmony_ci			agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
496062306a36Sopenharmony_ci		} else {
496162306a36Sopenharmony_ci			/* Get the average length of all the 4 channels. */
496262306a36Sopenharmony_ci			agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
496362306a36Sopenharmony_ci		}
496462306a36Sopenharmony_ci
496562306a36Sopenharmony_ci		/* Set the range of the calculated length. */
496662306a36Sopenharmony_ci		*min_length = ((e1000_igp_cable_length_table[agc_value] -
496762306a36Sopenharmony_ci				IGP01E1000_AGC_RANGE) > 0) ?
496862306a36Sopenharmony_ci		    (e1000_igp_cable_length_table[agc_value] -
496962306a36Sopenharmony_ci		     IGP01E1000_AGC_RANGE) : 0;
497062306a36Sopenharmony_ci		*max_length = e1000_igp_cable_length_table[agc_value] +
497162306a36Sopenharmony_ci		    IGP01E1000_AGC_RANGE;
497262306a36Sopenharmony_ci	}
497362306a36Sopenharmony_ci
497462306a36Sopenharmony_ci	return E1000_SUCCESS;
497562306a36Sopenharmony_ci}
497662306a36Sopenharmony_ci
497762306a36Sopenharmony_ci/**
497862306a36Sopenharmony_ci * e1000_check_polarity - Check the cable polarity
497962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
498062306a36Sopenharmony_ci * @polarity: output parameter : 0 - Polarity is not reversed
498162306a36Sopenharmony_ci *                               1 - Polarity is reversed.
498262306a36Sopenharmony_ci *
498362306a36Sopenharmony_ci * returns: - E1000_ERR_XXX
498462306a36Sopenharmony_ci *            E1000_SUCCESS
498562306a36Sopenharmony_ci *
498662306a36Sopenharmony_ci * For phy's older than IGP, this function simply reads the polarity bit in the
498762306a36Sopenharmony_ci * Phy Status register.  For IGP phy's, this bit is valid only if link speed is
498862306a36Sopenharmony_ci * 10 Mbps.  If the link speed is 100 Mbps there is no polarity so this bit will
498962306a36Sopenharmony_ci * return 0.  If the link speed is 1000 Mbps the polarity status is in the
499062306a36Sopenharmony_ci * IGP01E1000_PHY_PCS_INIT_REG.
499162306a36Sopenharmony_ci */
499262306a36Sopenharmony_cistatic s32 e1000_check_polarity(struct e1000_hw *hw,
499362306a36Sopenharmony_ci				e1000_rev_polarity *polarity)
499462306a36Sopenharmony_ci{
499562306a36Sopenharmony_ci	s32 ret_val;
499662306a36Sopenharmony_ci	u16 phy_data;
499762306a36Sopenharmony_ci
499862306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_m88) {
499962306a36Sopenharmony_ci		/* return the Polarity bit in the Status register. */
500062306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
500162306a36Sopenharmony_ci					     &phy_data);
500262306a36Sopenharmony_ci		if (ret_val)
500362306a36Sopenharmony_ci			return ret_val;
500462306a36Sopenharmony_ci		*polarity = ((phy_data & M88E1000_PSSR_REV_POLARITY) >>
500562306a36Sopenharmony_ci			     M88E1000_PSSR_REV_POLARITY_SHIFT) ?
500662306a36Sopenharmony_ci		    e1000_rev_polarity_reversed : e1000_rev_polarity_normal;
500762306a36Sopenharmony_ci
500862306a36Sopenharmony_ci	} else if (hw->phy_type == e1000_phy_igp) {
500962306a36Sopenharmony_ci		/* Read the Status register to check the speed */
501062306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
501162306a36Sopenharmony_ci					     &phy_data);
501262306a36Sopenharmony_ci		if (ret_val)
501362306a36Sopenharmony_ci			return ret_val;
501462306a36Sopenharmony_ci
501562306a36Sopenharmony_ci		/* If speed is 1000 Mbps, must read the
501662306a36Sopenharmony_ci		 * IGP01E1000_PHY_PCS_INIT_REG to find the polarity status
501762306a36Sopenharmony_ci		 */
501862306a36Sopenharmony_ci		if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
501962306a36Sopenharmony_ci		    IGP01E1000_PSSR_SPEED_1000MBPS) {
502062306a36Sopenharmony_ci			/* Read the GIG initialization PCS register (0x00B4) */
502162306a36Sopenharmony_ci			ret_val =
502262306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG,
502362306a36Sopenharmony_ci					       &phy_data);
502462306a36Sopenharmony_ci			if (ret_val)
502562306a36Sopenharmony_ci				return ret_val;
502662306a36Sopenharmony_ci
502762306a36Sopenharmony_ci			/* Check the polarity bits */
502862306a36Sopenharmony_ci			*polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ?
502962306a36Sopenharmony_ci			    e1000_rev_polarity_reversed :
503062306a36Sopenharmony_ci			    e1000_rev_polarity_normal;
503162306a36Sopenharmony_ci		} else {
503262306a36Sopenharmony_ci			/* For 10 Mbps, read the polarity bit in the status
503362306a36Sopenharmony_ci			 * register. (for 100 Mbps this bit is always 0)
503462306a36Sopenharmony_ci			 */
503562306a36Sopenharmony_ci			*polarity =
503662306a36Sopenharmony_ci			    (phy_data & IGP01E1000_PSSR_POLARITY_REVERSED) ?
503762306a36Sopenharmony_ci			    e1000_rev_polarity_reversed :
503862306a36Sopenharmony_ci			    e1000_rev_polarity_normal;
503962306a36Sopenharmony_ci		}
504062306a36Sopenharmony_ci	}
504162306a36Sopenharmony_ci	return E1000_SUCCESS;
504262306a36Sopenharmony_ci}
504362306a36Sopenharmony_ci
504462306a36Sopenharmony_ci/**
504562306a36Sopenharmony_ci * e1000_check_downshift - Check if Downshift occurred
504662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
504762306a36Sopenharmony_ci *
504862306a36Sopenharmony_ci * returns: - E1000_ERR_XXX
504962306a36Sopenharmony_ci *            E1000_SUCCESS
505062306a36Sopenharmony_ci *
505162306a36Sopenharmony_ci * For phy's older than IGP, this function reads the Downshift bit in the Phy
505262306a36Sopenharmony_ci * Specific Status register.  For IGP phy's, it reads the Downgrade bit in the
505362306a36Sopenharmony_ci * Link Health register.  In IGP this bit is latched high, so the driver must
505462306a36Sopenharmony_ci * read it immediately after link is established.
505562306a36Sopenharmony_ci */
505662306a36Sopenharmony_cistatic s32 e1000_check_downshift(struct e1000_hw *hw)
505762306a36Sopenharmony_ci{
505862306a36Sopenharmony_ci	s32 ret_val;
505962306a36Sopenharmony_ci	u16 phy_data;
506062306a36Sopenharmony_ci
506162306a36Sopenharmony_ci	if (hw->phy_type == e1000_phy_igp) {
506262306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
506362306a36Sopenharmony_ci					     &phy_data);
506462306a36Sopenharmony_ci		if (ret_val)
506562306a36Sopenharmony_ci			return ret_val;
506662306a36Sopenharmony_ci
506762306a36Sopenharmony_ci		hw->speed_downgraded =
506862306a36Sopenharmony_ci		    (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
506962306a36Sopenharmony_ci	} else if (hw->phy_type == e1000_phy_m88) {
507062306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
507162306a36Sopenharmony_ci					     &phy_data);
507262306a36Sopenharmony_ci		if (ret_val)
507362306a36Sopenharmony_ci			return ret_val;
507462306a36Sopenharmony_ci
507562306a36Sopenharmony_ci		hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
507662306a36Sopenharmony_ci		    M88E1000_PSSR_DOWNSHIFT_SHIFT;
507762306a36Sopenharmony_ci	}
507862306a36Sopenharmony_ci
507962306a36Sopenharmony_ci	return E1000_SUCCESS;
508062306a36Sopenharmony_ci}
508162306a36Sopenharmony_ci
508262306a36Sopenharmony_cistatic const u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
508362306a36Sopenharmony_ci	IGP01E1000_PHY_AGC_PARAM_A,
508462306a36Sopenharmony_ci	IGP01E1000_PHY_AGC_PARAM_B,
508562306a36Sopenharmony_ci	IGP01E1000_PHY_AGC_PARAM_C,
508662306a36Sopenharmony_ci	IGP01E1000_PHY_AGC_PARAM_D
508762306a36Sopenharmony_ci};
508862306a36Sopenharmony_ci
508962306a36Sopenharmony_cistatic s32 e1000_1000Mb_check_cable_length(struct e1000_hw *hw)
509062306a36Sopenharmony_ci{
509162306a36Sopenharmony_ci	u16 min_length, max_length;
509262306a36Sopenharmony_ci	u16 phy_data, i;
509362306a36Sopenharmony_ci	s32 ret_val;
509462306a36Sopenharmony_ci
509562306a36Sopenharmony_ci	ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
509662306a36Sopenharmony_ci	if (ret_val)
509762306a36Sopenharmony_ci		return ret_val;
509862306a36Sopenharmony_ci
509962306a36Sopenharmony_ci	if (hw->dsp_config_state != e1000_dsp_config_enabled)
510062306a36Sopenharmony_ci		return 0;
510162306a36Sopenharmony_ci
510262306a36Sopenharmony_ci	if (min_length >= e1000_igp_cable_length_50) {
510362306a36Sopenharmony_ci		for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
510462306a36Sopenharmony_ci			ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i],
510562306a36Sopenharmony_ci						     &phy_data);
510662306a36Sopenharmony_ci			if (ret_val)
510762306a36Sopenharmony_ci				return ret_val;
510862306a36Sopenharmony_ci
510962306a36Sopenharmony_ci			phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
511062306a36Sopenharmony_ci
511162306a36Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i],
511262306a36Sopenharmony_ci						      phy_data);
511362306a36Sopenharmony_ci			if (ret_val)
511462306a36Sopenharmony_ci				return ret_val;
511562306a36Sopenharmony_ci		}
511662306a36Sopenharmony_ci		hw->dsp_config_state = e1000_dsp_config_activated;
511762306a36Sopenharmony_ci	} else {
511862306a36Sopenharmony_ci		u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
511962306a36Sopenharmony_ci		u32 idle_errs = 0;
512062306a36Sopenharmony_ci
512162306a36Sopenharmony_ci		/* clear previous idle error counts */
512262306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
512362306a36Sopenharmony_ci		if (ret_val)
512462306a36Sopenharmony_ci			return ret_val;
512562306a36Sopenharmony_ci
512662306a36Sopenharmony_ci		for (i = 0; i < ffe_idle_err_timeout; i++) {
512762306a36Sopenharmony_ci			udelay(1000);
512862306a36Sopenharmony_ci			ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
512962306a36Sopenharmony_ci						     &phy_data);
513062306a36Sopenharmony_ci			if (ret_val)
513162306a36Sopenharmony_ci				return ret_val;
513262306a36Sopenharmony_ci
513362306a36Sopenharmony_ci			idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
513462306a36Sopenharmony_ci			if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
513562306a36Sopenharmony_ci				hw->ffe_config_state = e1000_ffe_config_active;
513662306a36Sopenharmony_ci
513762306a36Sopenharmony_ci				ret_val = e1000_write_phy_reg(hw,
513862306a36Sopenharmony_ci							      IGP01E1000_PHY_DSP_FFE,
513962306a36Sopenharmony_ci							      IGP01E1000_PHY_DSP_FFE_CM_CP);
514062306a36Sopenharmony_ci				if (ret_val)
514162306a36Sopenharmony_ci					return ret_val;
514262306a36Sopenharmony_ci				break;
514362306a36Sopenharmony_ci			}
514462306a36Sopenharmony_ci
514562306a36Sopenharmony_ci			if (idle_errs)
514662306a36Sopenharmony_ci				ffe_idle_err_timeout =
514762306a36Sopenharmony_ci					    FFE_IDLE_ERR_COUNT_TIMEOUT_100;
514862306a36Sopenharmony_ci		}
514962306a36Sopenharmony_ci	}
515062306a36Sopenharmony_ci
515162306a36Sopenharmony_ci	return 0;
515262306a36Sopenharmony_ci}
515362306a36Sopenharmony_ci
515462306a36Sopenharmony_ci/**
515562306a36Sopenharmony_ci * e1000_config_dsp_after_link_change
515662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
515762306a36Sopenharmony_ci * @link_up: was link up at the time this was called
515862306a36Sopenharmony_ci *
515962306a36Sopenharmony_ci * returns: - E1000_ERR_PHY if fail to read/write the PHY
516062306a36Sopenharmony_ci *            E1000_SUCCESS at any other case.
516162306a36Sopenharmony_ci *
516262306a36Sopenharmony_ci * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
516362306a36Sopenharmony_ci * gigabit link is achieved to improve link quality.
516462306a36Sopenharmony_ci */
516562306a36Sopenharmony_ci
516662306a36Sopenharmony_cistatic s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
516762306a36Sopenharmony_ci{
516862306a36Sopenharmony_ci	s32 ret_val;
516962306a36Sopenharmony_ci	u16 phy_data, phy_saved_data, speed, duplex, i;
517062306a36Sopenharmony_ci
517162306a36Sopenharmony_ci	if (hw->phy_type != e1000_phy_igp)
517262306a36Sopenharmony_ci		return E1000_SUCCESS;
517362306a36Sopenharmony_ci
517462306a36Sopenharmony_ci	if (link_up) {
517562306a36Sopenharmony_ci		ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
517662306a36Sopenharmony_ci		if (ret_val) {
517762306a36Sopenharmony_ci			e_dbg("Error getting link speed and duplex\n");
517862306a36Sopenharmony_ci			return ret_val;
517962306a36Sopenharmony_ci		}
518062306a36Sopenharmony_ci
518162306a36Sopenharmony_ci		if (speed == SPEED_1000) {
518262306a36Sopenharmony_ci			ret_val = e1000_1000Mb_check_cable_length(hw);
518362306a36Sopenharmony_ci			if (ret_val)
518462306a36Sopenharmony_ci				return ret_val;
518562306a36Sopenharmony_ci		}
518662306a36Sopenharmony_ci	} else {
518762306a36Sopenharmony_ci		if (hw->dsp_config_state == e1000_dsp_config_activated) {
518862306a36Sopenharmony_ci			/* Save off the current value of register 0x2F5B to be
518962306a36Sopenharmony_ci			 * restored at the end of the routines.
519062306a36Sopenharmony_ci			 */
519162306a36Sopenharmony_ci			ret_val =
519262306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
519362306a36Sopenharmony_ci
519462306a36Sopenharmony_ci			if (ret_val)
519562306a36Sopenharmony_ci				return ret_val;
519662306a36Sopenharmony_ci
519762306a36Sopenharmony_ci			/* Disable the PHY transmitter */
519862306a36Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
519962306a36Sopenharmony_ci
520062306a36Sopenharmony_ci			if (ret_val)
520162306a36Sopenharmony_ci				return ret_val;
520262306a36Sopenharmony_ci
520362306a36Sopenharmony_ci			msleep(20);
520462306a36Sopenharmony_ci
520562306a36Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x0000,
520662306a36Sopenharmony_ci						      IGP01E1000_IEEE_FORCE_GIGA);
520762306a36Sopenharmony_ci			if (ret_val)
520862306a36Sopenharmony_ci				return ret_val;
520962306a36Sopenharmony_ci			for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
521062306a36Sopenharmony_ci				ret_val =
521162306a36Sopenharmony_ci				    e1000_read_phy_reg(hw, dsp_reg_array[i],
521262306a36Sopenharmony_ci						       &phy_data);
521362306a36Sopenharmony_ci				if (ret_val)
521462306a36Sopenharmony_ci					return ret_val;
521562306a36Sopenharmony_ci
521662306a36Sopenharmony_ci				phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
521762306a36Sopenharmony_ci				phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
521862306a36Sopenharmony_ci
521962306a36Sopenharmony_ci				ret_val =
522062306a36Sopenharmony_ci				    e1000_write_phy_reg(hw, dsp_reg_array[i],
522162306a36Sopenharmony_ci							phy_data);
522262306a36Sopenharmony_ci				if (ret_val)
522362306a36Sopenharmony_ci					return ret_val;
522462306a36Sopenharmony_ci			}
522562306a36Sopenharmony_ci
522662306a36Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x0000,
522762306a36Sopenharmony_ci						      IGP01E1000_IEEE_RESTART_AUTONEG);
522862306a36Sopenharmony_ci			if (ret_val)
522962306a36Sopenharmony_ci				return ret_val;
523062306a36Sopenharmony_ci
523162306a36Sopenharmony_ci			msleep(20);
523262306a36Sopenharmony_ci
523362306a36Sopenharmony_ci			/* Now enable the transmitter */
523462306a36Sopenharmony_ci			ret_val =
523562306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
523662306a36Sopenharmony_ci
523762306a36Sopenharmony_ci			if (ret_val)
523862306a36Sopenharmony_ci				return ret_val;
523962306a36Sopenharmony_ci
524062306a36Sopenharmony_ci			hw->dsp_config_state = e1000_dsp_config_enabled;
524162306a36Sopenharmony_ci		}
524262306a36Sopenharmony_ci
524362306a36Sopenharmony_ci		if (hw->ffe_config_state == e1000_ffe_config_active) {
524462306a36Sopenharmony_ci			/* Save off the current value of register 0x2F5B to be
524562306a36Sopenharmony_ci			 * restored at the end of the routines.
524662306a36Sopenharmony_ci			 */
524762306a36Sopenharmony_ci			ret_val =
524862306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
524962306a36Sopenharmony_ci
525062306a36Sopenharmony_ci			if (ret_val)
525162306a36Sopenharmony_ci				return ret_val;
525262306a36Sopenharmony_ci
525362306a36Sopenharmony_ci			/* Disable the PHY transmitter */
525462306a36Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
525562306a36Sopenharmony_ci
525662306a36Sopenharmony_ci			if (ret_val)
525762306a36Sopenharmony_ci				return ret_val;
525862306a36Sopenharmony_ci
525962306a36Sopenharmony_ci			msleep(20);
526062306a36Sopenharmony_ci
526162306a36Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x0000,
526262306a36Sopenharmony_ci						      IGP01E1000_IEEE_FORCE_GIGA);
526362306a36Sopenharmony_ci			if (ret_val)
526462306a36Sopenharmony_ci				return ret_val;
526562306a36Sopenharmony_ci			ret_val =
526662306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE,
526762306a36Sopenharmony_ci						IGP01E1000_PHY_DSP_FFE_DEFAULT);
526862306a36Sopenharmony_ci			if (ret_val)
526962306a36Sopenharmony_ci				return ret_val;
527062306a36Sopenharmony_ci
527162306a36Sopenharmony_ci			ret_val = e1000_write_phy_reg(hw, 0x0000,
527262306a36Sopenharmony_ci						      IGP01E1000_IEEE_RESTART_AUTONEG);
527362306a36Sopenharmony_ci			if (ret_val)
527462306a36Sopenharmony_ci				return ret_val;
527562306a36Sopenharmony_ci
527662306a36Sopenharmony_ci			msleep(20);
527762306a36Sopenharmony_ci
527862306a36Sopenharmony_ci			/* Now enable the transmitter */
527962306a36Sopenharmony_ci			ret_val =
528062306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
528162306a36Sopenharmony_ci
528262306a36Sopenharmony_ci			if (ret_val)
528362306a36Sopenharmony_ci				return ret_val;
528462306a36Sopenharmony_ci
528562306a36Sopenharmony_ci			hw->ffe_config_state = e1000_ffe_config_enabled;
528662306a36Sopenharmony_ci		}
528762306a36Sopenharmony_ci	}
528862306a36Sopenharmony_ci	return E1000_SUCCESS;
528962306a36Sopenharmony_ci}
529062306a36Sopenharmony_ci
529162306a36Sopenharmony_ci/**
529262306a36Sopenharmony_ci * e1000_set_phy_mode - Set PHY to class A mode
529362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
529462306a36Sopenharmony_ci *
529562306a36Sopenharmony_ci * Assumes the following operations will follow to enable the new class mode.
529662306a36Sopenharmony_ci *  1. Do a PHY soft reset
529762306a36Sopenharmony_ci *  2. Restart auto-negotiation or force link.
529862306a36Sopenharmony_ci */
529962306a36Sopenharmony_cistatic s32 e1000_set_phy_mode(struct e1000_hw *hw)
530062306a36Sopenharmony_ci{
530162306a36Sopenharmony_ci	s32 ret_val;
530262306a36Sopenharmony_ci	u16 eeprom_data;
530362306a36Sopenharmony_ci
530462306a36Sopenharmony_ci	if ((hw->mac_type == e1000_82545_rev_3) &&
530562306a36Sopenharmony_ci	    (hw->media_type == e1000_media_type_copper)) {
530662306a36Sopenharmony_ci		ret_val =
530762306a36Sopenharmony_ci		    e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1,
530862306a36Sopenharmony_ci				      &eeprom_data);
530962306a36Sopenharmony_ci		if (ret_val)
531062306a36Sopenharmony_ci			return ret_val;
531162306a36Sopenharmony_ci
531262306a36Sopenharmony_ci		if ((eeprom_data != EEPROM_RESERVED_WORD) &&
531362306a36Sopenharmony_ci		    (eeprom_data & EEPROM_PHY_CLASS_A)) {
531462306a36Sopenharmony_ci			ret_val =
531562306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
531662306a36Sopenharmony_ci						0x000B);
531762306a36Sopenharmony_ci			if (ret_val)
531862306a36Sopenharmony_ci				return ret_val;
531962306a36Sopenharmony_ci			ret_val =
532062306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
532162306a36Sopenharmony_ci						0x8104);
532262306a36Sopenharmony_ci			if (ret_val)
532362306a36Sopenharmony_ci				return ret_val;
532462306a36Sopenharmony_ci
532562306a36Sopenharmony_ci			hw->phy_reset_disable = false;
532662306a36Sopenharmony_ci		}
532762306a36Sopenharmony_ci	}
532862306a36Sopenharmony_ci
532962306a36Sopenharmony_ci	return E1000_SUCCESS;
533062306a36Sopenharmony_ci}
533162306a36Sopenharmony_ci
533262306a36Sopenharmony_ci/**
533362306a36Sopenharmony_ci * e1000_set_d3_lplu_state - set d3 link power state
533462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
533562306a36Sopenharmony_ci * @active: true to enable lplu false to disable lplu.
533662306a36Sopenharmony_ci *
533762306a36Sopenharmony_ci * This function sets the lplu state according to the active flag.  When
533862306a36Sopenharmony_ci * activating lplu this function also disables smart speed and vise versa.
533962306a36Sopenharmony_ci * lplu will not be activated unless the device autonegotiation advertisement
534062306a36Sopenharmony_ci * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes.
534162306a36Sopenharmony_ci *
534262306a36Sopenharmony_ci * returns: - E1000_ERR_PHY if fail to read/write the PHY
534362306a36Sopenharmony_ci *            E1000_SUCCESS at any other case.
534462306a36Sopenharmony_ci */
534562306a36Sopenharmony_cistatic s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
534662306a36Sopenharmony_ci{
534762306a36Sopenharmony_ci	s32 ret_val;
534862306a36Sopenharmony_ci	u16 phy_data;
534962306a36Sopenharmony_ci
535062306a36Sopenharmony_ci	if (hw->phy_type != e1000_phy_igp)
535162306a36Sopenharmony_ci		return E1000_SUCCESS;
535262306a36Sopenharmony_ci
535362306a36Sopenharmony_ci	/* During driver activity LPLU should not be used or it will attain link
535462306a36Sopenharmony_ci	 * from the lowest speeds starting from 10Mbps. The capability is used
535562306a36Sopenharmony_ci	 * for Dx transitions and states
535662306a36Sopenharmony_ci	 */
535762306a36Sopenharmony_ci	if (hw->mac_type == e1000_82541_rev_2 ||
535862306a36Sopenharmony_ci	    hw->mac_type == e1000_82547_rev_2) {
535962306a36Sopenharmony_ci		ret_val =
536062306a36Sopenharmony_ci		    e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
536162306a36Sopenharmony_ci		if (ret_val)
536262306a36Sopenharmony_ci			return ret_val;
536362306a36Sopenharmony_ci	}
536462306a36Sopenharmony_ci
536562306a36Sopenharmony_ci	if (!active) {
536662306a36Sopenharmony_ci		if (hw->mac_type == e1000_82541_rev_2 ||
536762306a36Sopenharmony_ci		    hw->mac_type == e1000_82547_rev_2) {
536862306a36Sopenharmony_ci			phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
536962306a36Sopenharmony_ci			ret_val =
537062306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
537162306a36Sopenharmony_ci						phy_data);
537262306a36Sopenharmony_ci			if (ret_val)
537362306a36Sopenharmony_ci				return ret_val;
537462306a36Sopenharmony_ci		}
537562306a36Sopenharmony_ci
537662306a36Sopenharmony_ci		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
537762306a36Sopenharmony_ci		 * during Dx states where the power conservation is most
537862306a36Sopenharmony_ci		 * important.  During driver activity we should enable
537962306a36Sopenharmony_ci		 * SmartSpeed, so performance is maintained.
538062306a36Sopenharmony_ci		 */
538162306a36Sopenharmony_ci		if (hw->smart_speed == e1000_smart_speed_on) {
538262306a36Sopenharmony_ci			ret_val =
538362306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
538462306a36Sopenharmony_ci					       &phy_data);
538562306a36Sopenharmony_ci			if (ret_val)
538662306a36Sopenharmony_ci				return ret_val;
538762306a36Sopenharmony_ci
538862306a36Sopenharmony_ci			phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
538962306a36Sopenharmony_ci			ret_val =
539062306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
539162306a36Sopenharmony_ci						phy_data);
539262306a36Sopenharmony_ci			if (ret_val)
539362306a36Sopenharmony_ci				return ret_val;
539462306a36Sopenharmony_ci		} else if (hw->smart_speed == e1000_smart_speed_off) {
539562306a36Sopenharmony_ci			ret_val =
539662306a36Sopenharmony_ci			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
539762306a36Sopenharmony_ci					       &phy_data);
539862306a36Sopenharmony_ci			if (ret_val)
539962306a36Sopenharmony_ci				return ret_val;
540062306a36Sopenharmony_ci
540162306a36Sopenharmony_ci			phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
540262306a36Sopenharmony_ci			ret_val =
540362306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
540462306a36Sopenharmony_ci						phy_data);
540562306a36Sopenharmony_ci			if (ret_val)
540662306a36Sopenharmony_ci				return ret_val;
540762306a36Sopenharmony_ci		}
540862306a36Sopenharmony_ci	} else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) ||
540962306a36Sopenharmony_ci		   (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL) ||
541062306a36Sopenharmony_ci		   (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
541162306a36Sopenharmony_ci		if (hw->mac_type == e1000_82541_rev_2 ||
541262306a36Sopenharmony_ci		    hw->mac_type == e1000_82547_rev_2) {
541362306a36Sopenharmony_ci			phy_data |= IGP01E1000_GMII_FLEX_SPD;
541462306a36Sopenharmony_ci			ret_val =
541562306a36Sopenharmony_ci			    e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
541662306a36Sopenharmony_ci						phy_data);
541762306a36Sopenharmony_ci			if (ret_val)
541862306a36Sopenharmony_ci				return ret_val;
541962306a36Sopenharmony_ci		}
542062306a36Sopenharmony_ci
542162306a36Sopenharmony_ci		/* When LPLU is enabled we should disable SmartSpeed */
542262306a36Sopenharmony_ci		ret_val =
542362306a36Sopenharmony_ci		    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
542462306a36Sopenharmony_ci				       &phy_data);
542562306a36Sopenharmony_ci		if (ret_val)
542662306a36Sopenharmony_ci			return ret_val;
542762306a36Sopenharmony_ci
542862306a36Sopenharmony_ci		phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
542962306a36Sopenharmony_ci		ret_val =
543062306a36Sopenharmony_ci		    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
543162306a36Sopenharmony_ci					phy_data);
543262306a36Sopenharmony_ci		if (ret_val)
543362306a36Sopenharmony_ci			return ret_val;
543462306a36Sopenharmony_ci	}
543562306a36Sopenharmony_ci	return E1000_SUCCESS;
543662306a36Sopenharmony_ci}
543762306a36Sopenharmony_ci
543862306a36Sopenharmony_ci/**
543962306a36Sopenharmony_ci * e1000_set_vco_speed
544062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
544162306a36Sopenharmony_ci *
544262306a36Sopenharmony_ci * Change VCO speed register to improve Bit Error Rate performance of SERDES.
544362306a36Sopenharmony_ci */
544462306a36Sopenharmony_cistatic s32 e1000_set_vco_speed(struct e1000_hw *hw)
544562306a36Sopenharmony_ci{
544662306a36Sopenharmony_ci	s32 ret_val;
544762306a36Sopenharmony_ci	u16 default_page = 0;
544862306a36Sopenharmony_ci	u16 phy_data;
544962306a36Sopenharmony_ci
545062306a36Sopenharmony_ci	switch (hw->mac_type) {
545162306a36Sopenharmony_ci	case e1000_82545_rev_3:
545262306a36Sopenharmony_ci	case e1000_82546_rev_3:
545362306a36Sopenharmony_ci		break;
545462306a36Sopenharmony_ci	default:
545562306a36Sopenharmony_ci		return E1000_SUCCESS;
545662306a36Sopenharmony_ci	}
545762306a36Sopenharmony_ci
545862306a36Sopenharmony_ci	/* Set PHY register 30, page 5, bit 8 to 0 */
545962306a36Sopenharmony_ci
546062306a36Sopenharmony_ci	ret_val =
546162306a36Sopenharmony_ci	    e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page);
546262306a36Sopenharmony_ci	if (ret_val)
546362306a36Sopenharmony_ci		return ret_val;
546462306a36Sopenharmony_ci
546562306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
546662306a36Sopenharmony_ci	if (ret_val)
546762306a36Sopenharmony_ci		return ret_val;
546862306a36Sopenharmony_ci
546962306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
547062306a36Sopenharmony_ci	if (ret_val)
547162306a36Sopenharmony_ci		return ret_val;
547262306a36Sopenharmony_ci
547362306a36Sopenharmony_ci	phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
547462306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
547562306a36Sopenharmony_ci	if (ret_val)
547662306a36Sopenharmony_ci		return ret_val;
547762306a36Sopenharmony_ci
547862306a36Sopenharmony_ci	/* Set PHY register 30, page 4, bit 11 to 1 */
547962306a36Sopenharmony_ci
548062306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
548162306a36Sopenharmony_ci	if (ret_val)
548262306a36Sopenharmony_ci		return ret_val;
548362306a36Sopenharmony_ci
548462306a36Sopenharmony_ci	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
548562306a36Sopenharmony_ci	if (ret_val)
548662306a36Sopenharmony_ci		return ret_val;
548762306a36Sopenharmony_ci
548862306a36Sopenharmony_ci	phy_data |= M88E1000_PHY_VCO_REG_BIT11;
548962306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
549062306a36Sopenharmony_ci	if (ret_val)
549162306a36Sopenharmony_ci		return ret_val;
549262306a36Sopenharmony_ci
549362306a36Sopenharmony_ci	ret_val =
549462306a36Sopenharmony_ci	    e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page);
549562306a36Sopenharmony_ci	if (ret_val)
549662306a36Sopenharmony_ci		return ret_val;
549762306a36Sopenharmony_ci
549862306a36Sopenharmony_ci	return E1000_SUCCESS;
549962306a36Sopenharmony_ci}
550062306a36Sopenharmony_ci
550162306a36Sopenharmony_ci/**
550262306a36Sopenharmony_ci * e1000_enable_mng_pass_thru - check for bmc pass through
550362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
550462306a36Sopenharmony_ci *
550562306a36Sopenharmony_ci * Verifies the hardware needs to allow ARPs to be processed by the host
550662306a36Sopenharmony_ci * returns: - true/false
550762306a36Sopenharmony_ci */
550862306a36Sopenharmony_ciu32 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
550962306a36Sopenharmony_ci{
551062306a36Sopenharmony_ci	u32 manc;
551162306a36Sopenharmony_ci
551262306a36Sopenharmony_ci	if (hw->asf_firmware_present) {
551362306a36Sopenharmony_ci		manc = er32(MANC);
551462306a36Sopenharmony_ci
551562306a36Sopenharmony_ci		if (!(manc & E1000_MANC_RCV_TCO_EN) ||
551662306a36Sopenharmony_ci		    !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
551762306a36Sopenharmony_ci			return false;
551862306a36Sopenharmony_ci		if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
551962306a36Sopenharmony_ci			return true;
552062306a36Sopenharmony_ci	}
552162306a36Sopenharmony_ci	return false;
552262306a36Sopenharmony_ci}
552362306a36Sopenharmony_ci
552462306a36Sopenharmony_cistatic s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
552562306a36Sopenharmony_ci{
552662306a36Sopenharmony_ci	s32 ret_val;
552762306a36Sopenharmony_ci	u16 mii_status_reg;
552862306a36Sopenharmony_ci	u16 i;
552962306a36Sopenharmony_ci
553062306a36Sopenharmony_ci	/* Polarity reversal workaround for forced 10F/10H links. */
553162306a36Sopenharmony_ci
553262306a36Sopenharmony_ci	/* Disable the transmitter on the PHY */
553362306a36Sopenharmony_ci
553462306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
553562306a36Sopenharmony_ci	if (ret_val)
553662306a36Sopenharmony_ci		return ret_val;
553762306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
553862306a36Sopenharmony_ci	if (ret_val)
553962306a36Sopenharmony_ci		return ret_val;
554062306a36Sopenharmony_ci
554162306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
554262306a36Sopenharmony_ci	if (ret_val)
554362306a36Sopenharmony_ci		return ret_val;
554462306a36Sopenharmony_ci
554562306a36Sopenharmony_ci	/* This loop will early-out if the NO link condition has been met. */
554662306a36Sopenharmony_ci	for (i = PHY_FORCE_TIME; i > 0; i--) {
554762306a36Sopenharmony_ci		/* Read the MII Status Register and wait for Link Status bit
554862306a36Sopenharmony_ci		 * to be clear.
554962306a36Sopenharmony_ci		 */
555062306a36Sopenharmony_ci
555162306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
555262306a36Sopenharmony_ci		if (ret_val)
555362306a36Sopenharmony_ci			return ret_val;
555462306a36Sopenharmony_ci
555562306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
555662306a36Sopenharmony_ci		if (ret_val)
555762306a36Sopenharmony_ci			return ret_val;
555862306a36Sopenharmony_ci
555962306a36Sopenharmony_ci		if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0)
556062306a36Sopenharmony_ci			break;
556162306a36Sopenharmony_ci		msleep(100);
556262306a36Sopenharmony_ci	}
556362306a36Sopenharmony_ci
556462306a36Sopenharmony_ci	/* Recommended delay time after link has been lost */
556562306a36Sopenharmony_ci	msleep(1000);
556662306a36Sopenharmony_ci
556762306a36Sopenharmony_ci	/* Now we will re-enable th transmitter on the PHY */
556862306a36Sopenharmony_ci
556962306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
557062306a36Sopenharmony_ci	if (ret_val)
557162306a36Sopenharmony_ci		return ret_val;
557262306a36Sopenharmony_ci	msleep(50);
557362306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
557462306a36Sopenharmony_ci	if (ret_val)
557562306a36Sopenharmony_ci		return ret_val;
557662306a36Sopenharmony_ci	msleep(50);
557762306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
557862306a36Sopenharmony_ci	if (ret_val)
557962306a36Sopenharmony_ci		return ret_val;
558062306a36Sopenharmony_ci	msleep(50);
558162306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
558262306a36Sopenharmony_ci	if (ret_val)
558362306a36Sopenharmony_ci		return ret_val;
558462306a36Sopenharmony_ci
558562306a36Sopenharmony_ci	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
558662306a36Sopenharmony_ci	if (ret_val)
558762306a36Sopenharmony_ci		return ret_val;
558862306a36Sopenharmony_ci
558962306a36Sopenharmony_ci	/* This loop will early-out if the link condition has been met. */
559062306a36Sopenharmony_ci	for (i = PHY_FORCE_TIME; i > 0; i--) {
559162306a36Sopenharmony_ci		/* Read the MII Status Register and wait for Link Status bit
559262306a36Sopenharmony_ci		 * to be set.
559362306a36Sopenharmony_ci		 */
559462306a36Sopenharmony_ci
559562306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
559662306a36Sopenharmony_ci		if (ret_val)
559762306a36Sopenharmony_ci			return ret_val;
559862306a36Sopenharmony_ci
559962306a36Sopenharmony_ci		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
560062306a36Sopenharmony_ci		if (ret_val)
560162306a36Sopenharmony_ci			return ret_val;
560262306a36Sopenharmony_ci
560362306a36Sopenharmony_ci		if (mii_status_reg & MII_SR_LINK_STATUS)
560462306a36Sopenharmony_ci			break;
560562306a36Sopenharmony_ci		msleep(100);
560662306a36Sopenharmony_ci	}
560762306a36Sopenharmony_ci	return E1000_SUCCESS;
560862306a36Sopenharmony_ci}
560962306a36Sopenharmony_ci
561062306a36Sopenharmony_ci/**
561162306a36Sopenharmony_ci * e1000_get_auto_rd_done
561262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
561362306a36Sopenharmony_ci *
561462306a36Sopenharmony_ci * Check for EEPROM Auto Read bit done.
561562306a36Sopenharmony_ci * returns: - E1000_ERR_RESET if fail to reset MAC
561662306a36Sopenharmony_ci *            E1000_SUCCESS at any other case.
561762306a36Sopenharmony_ci */
561862306a36Sopenharmony_cistatic s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
561962306a36Sopenharmony_ci{
562062306a36Sopenharmony_ci	msleep(5);
562162306a36Sopenharmony_ci	return E1000_SUCCESS;
562262306a36Sopenharmony_ci}
562362306a36Sopenharmony_ci
562462306a36Sopenharmony_ci/**
562562306a36Sopenharmony_ci * e1000_get_phy_cfg_done
562662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
562762306a36Sopenharmony_ci *
562862306a36Sopenharmony_ci * Checks if the PHY configuration is done
562962306a36Sopenharmony_ci * returns: - E1000_ERR_RESET if fail to reset MAC
563062306a36Sopenharmony_ci *            E1000_SUCCESS at any other case.
563162306a36Sopenharmony_ci */
563262306a36Sopenharmony_cistatic s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
563362306a36Sopenharmony_ci{
563462306a36Sopenharmony_ci	msleep(10);
563562306a36Sopenharmony_ci	return E1000_SUCCESS;
563662306a36Sopenharmony_ci}
5637