162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/pci.h>
562306a36Sopenharmony_ci#include <linux/delay.h>
662306a36Sopenharmony_ci#include <linux/sched.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "ixgbe.h"
962306a36Sopenharmony_ci#include "ixgbe_phy.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define IXGBE_82598_MAX_TX_QUEUES 32
1262306a36Sopenharmony_ci#define IXGBE_82598_MAX_RX_QUEUES 64
1362306a36Sopenharmony_ci#define IXGBE_82598_RAR_ENTRIES   16
1462306a36Sopenharmony_ci#define IXGBE_82598_MC_TBL_SIZE  128
1562306a36Sopenharmony_ci#define IXGBE_82598_VFT_TBL_SIZE 128
1662306a36Sopenharmony_ci#define IXGBE_82598_RX_PB_SIZE	 512
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
1962306a36Sopenharmony_ci					 ixgbe_link_speed speed,
2062306a36Sopenharmony_ci					 bool autoneg_wait_to_complete);
2162306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
2262306a36Sopenharmony_ci				       u8 *eeprom_data);
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/**
2562306a36Sopenharmony_ci *  ixgbe_set_pcie_completion_timeout - set pci-e completion timeout
2662306a36Sopenharmony_ci *  @hw: pointer to the HW structure
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci *  The defaults for 82598 should be in the range of 50us to 50ms,
2962306a36Sopenharmony_ci *  however the hardware default for these parts is 500us to 1ms which is less
3062306a36Sopenharmony_ci *  than the 10ms recommended by the pci-e spec.  To address this we need to
3162306a36Sopenharmony_ci *  increase the value to either 10ms to 250ms for capability version 1 config,
3262306a36Sopenharmony_ci *  or 16ms to 55ms for version 2.
3362306a36Sopenharmony_ci **/
3462306a36Sopenharmony_cistatic void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR);
3762306a36Sopenharmony_ci	u16 pcie_devctl2;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	if (ixgbe_removed(hw->hw_addr))
4062306a36Sopenharmony_ci		return;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	/* only take action if timeout value is defaulted to 0 */
4362306a36Sopenharmony_ci	if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK)
4462306a36Sopenharmony_ci		goto out;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	/*
4762306a36Sopenharmony_ci	 * if capababilities version is type 1 we can write the
4862306a36Sopenharmony_ci	 * timeout of 10ms to 250ms through the GCR register
4962306a36Sopenharmony_ci	 */
5062306a36Sopenharmony_ci	if (!(gcr & IXGBE_GCR_CAP_VER2)) {
5162306a36Sopenharmony_ci		gcr |= IXGBE_GCR_CMPL_TMOUT_10ms;
5262306a36Sopenharmony_ci		goto out;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	/*
5662306a36Sopenharmony_ci	 * for version 2 capabilities we need to write the config space
5762306a36Sopenharmony_ci	 * directly in order to set the completion timeout value for
5862306a36Sopenharmony_ci	 * 16ms to 55ms
5962306a36Sopenharmony_ci	 */
6062306a36Sopenharmony_ci	pcie_devctl2 = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_CONTROL2);
6162306a36Sopenharmony_ci	pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms;
6262306a36Sopenharmony_ci	ixgbe_write_pci_cfg_word(hw, IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2);
6362306a36Sopenharmony_ciout:
6462306a36Sopenharmony_ci	/* disable completion timeout resend */
6562306a36Sopenharmony_ci	gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND;
6662306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr);
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	/* Call PHY identify routine to get the phy type */
7462306a36Sopenharmony_ci	ixgbe_identify_phy_generic(hw);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	mac->mcft_size = IXGBE_82598_MC_TBL_SIZE;
7762306a36Sopenharmony_ci	mac->vft_size = IXGBE_82598_VFT_TBL_SIZE;
7862306a36Sopenharmony_ci	mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES;
7962306a36Sopenharmony_ci	mac->rx_pb_size = IXGBE_82598_RX_PB_SIZE;
8062306a36Sopenharmony_ci	mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
8162306a36Sopenharmony_ci	mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
8262306a36Sopenharmony_ci	mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	return 0;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/**
8862306a36Sopenharmony_ci *  ixgbe_init_phy_ops_82598 - PHY/SFP specific init
8962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
9062306a36Sopenharmony_ci *
9162306a36Sopenharmony_ci *  Initialize any function pointers that were not able to be
9262306a36Sopenharmony_ci *  set during get_invariants because the PHY/SFP type was
9362306a36Sopenharmony_ci *  not known.  Perform the SFP init if necessary.
9462306a36Sopenharmony_ci *
9562306a36Sopenharmony_ci **/
9662306a36Sopenharmony_cistatic s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
9962306a36Sopenharmony_ci	struct ixgbe_phy_info *phy = &hw->phy;
10062306a36Sopenharmony_ci	s32 ret_val;
10162306a36Sopenharmony_ci	u16 list_offset, data_offset;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	/* Identify the PHY */
10462306a36Sopenharmony_ci	phy->ops.identify(hw);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	/* Overwrite the link function pointers if copper PHY */
10762306a36Sopenharmony_ci	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
10862306a36Sopenharmony_ci		mac->ops.setup_link = &ixgbe_setup_copper_link_82598;
10962306a36Sopenharmony_ci		mac->ops.get_link_capabilities =
11062306a36Sopenharmony_ci			&ixgbe_get_copper_link_capabilities_generic;
11162306a36Sopenharmony_ci	}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	switch (hw->phy.type) {
11462306a36Sopenharmony_ci	case ixgbe_phy_tn:
11562306a36Sopenharmony_ci		phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
11662306a36Sopenharmony_ci		phy->ops.check_link = &ixgbe_check_phy_link_tnx;
11762306a36Sopenharmony_ci		break;
11862306a36Sopenharmony_ci	case ixgbe_phy_nl:
11962306a36Sopenharmony_ci		phy->ops.reset = &ixgbe_reset_phy_nl;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci		/* Call SFP+ identify routine to get the SFP+ module type */
12262306a36Sopenharmony_ci		ret_val = phy->ops.identify_sfp(hw);
12362306a36Sopenharmony_ci		if (ret_val)
12462306a36Sopenharmony_ci			return ret_val;
12562306a36Sopenharmony_ci		if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
12662306a36Sopenharmony_ci			return -EOPNOTSUPP;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci		/* Check to see if SFP+ module is supported */
12962306a36Sopenharmony_ci		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
13062306a36Sopenharmony_ci							    &list_offset,
13162306a36Sopenharmony_ci							    &data_offset);
13262306a36Sopenharmony_ci		if (ret_val)
13362306a36Sopenharmony_ci			return -EOPNOTSUPP;
13462306a36Sopenharmony_ci		break;
13562306a36Sopenharmony_ci	default:
13662306a36Sopenharmony_ci		break;
13762306a36Sopenharmony_ci	}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	return 0;
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci/**
14362306a36Sopenharmony_ci *  ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx
14462306a36Sopenharmony_ci *  @hw: pointer to hardware structure
14562306a36Sopenharmony_ci *
14662306a36Sopenharmony_ci *  Starts the hardware using the generic start_hw function.
14762306a36Sopenharmony_ci *  Disables relaxed ordering for archs other than SPARC
14862306a36Sopenharmony_ci *  Then set pcie completion timeout
14962306a36Sopenharmony_ci *
15062306a36Sopenharmony_ci **/
15162306a36Sopenharmony_cistatic s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	s32 ret_val;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	ret_val = ixgbe_start_hw_generic(hw);
15662306a36Sopenharmony_ci	if (ret_val)
15762306a36Sopenharmony_ci		return ret_val;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	/* set the completion timeout for interface */
16062306a36Sopenharmony_ci	ixgbe_set_pcie_completion_timeout(hw);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	return 0;
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/**
16662306a36Sopenharmony_ci *  ixgbe_get_link_capabilities_82598 - Determines link capabilities
16762306a36Sopenharmony_ci *  @hw: pointer to hardware structure
16862306a36Sopenharmony_ci *  @speed: pointer to link speed
16962306a36Sopenharmony_ci *  @autoneg: boolean auto-negotiation value
17062306a36Sopenharmony_ci *
17162306a36Sopenharmony_ci *  Determines the link capabilities by reading the AUTOC register.
17262306a36Sopenharmony_ci **/
17362306a36Sopenharmony_cistatic s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
17462306a36Sopenharmony_ci					     ixgbe_link_speed *speed,
17562306a36Sopenharmony_ci					     bool *autoneg)
17662306a36Sopenharmony_ci{
17762306a36Sopenharmony_ci	u32 autoc = 0;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	/*
18062306a36Sopenharmony_ci	 * Determine link capabilities based on the stored value of AUTOC,
18162306a36Sopenharmony_ci	 * which represents EEPROM defaults.  If AUTOC value has not been
18262306a36Sopenharmony_ci	 * stored, use the current register value.
18362306a36Sopenharmony_ci	 */
18462306a36Sopenharmony_ci	if (hw->mac.orig_link_settings_stored)
18562306a36Sopenharmony_ci		autoc = hw->mac.orig_autoc;
18662306a36Sopenharmony_ci	else
18762306a36Sopenharmony_ci		autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
19062306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
19162306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_1GB_FULL;
19262306a36Sopenharmony_ci		*autoneg = false;
19362306a36Sopenharmony_ci		break;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
19662306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_10GB_FULL;
19762306a36Sopenharmony_ci		*autoneg = false;
19862306a36Sopenharmony_ci		break;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_1G_AN:
20162306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_1GB_FULL;
20262306a36Sopenharmony_ci		*autoneg = true;
20362306a36Sopenharmony_ci		break;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_KX4_AN:
20662306a36Sopenharmony_ci	case IXGBE_AUTOC_LMS_KX4_AN_1G_AN:
20762306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_UNKNOWN;
20862306a36Sopenharmony_ci		if (autoc & IXGBE_AUTOC_KX4_SUPP)
20962306a36Sopenharmony_ci			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
21062306a36Sopenharmony_ci		if (autoc & IXGBE_AUTOC_KX_SUPP)
21162306a36Sopenharmony_ci			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
21262306a36Sopenharmony_ci		*autoneg = true;
21362306a36Sopenharmony_ci		break;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	default:
21662306a36Sopenharmony_ci		return -EIO;
21762306a36Sopenharmony_ci	}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	return 0;
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci/**
22362306a36Sopenharmony_ci *  ixgbe_get_media_type_82598 - Determines media type
22462306a36Sopenharmony_ci *  @hw: pointer to hardware structure
22562306a36Sopenharmony_ci *
22662306a36Sopenharmony_ci *  Returns the media type (fiber, copper, backplane)
22762306a36Sopenharmony_ci **/
22862306a36Sopenharmony_cistatic enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
22962306a36Sopenharmony_ci{
23062306a36Sopenharmony_ci	/* Detect if there is a copper PHY attached. */
23162306a36Sopenharmony_ci	switch (hw->phy.type) {
23262306a36Sopenharmony_ci	case ixgbe_phy_cu_unknown:
23362306a36Sopenharmony_ci	case ixgbe_phy_tn:
23462306a36Sopenharmony_ci		return ixgbe_media_type_copper;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	default:
23762306a36Sopenharmony_ci		break;
23862306a36Sopenharmony_ci	}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	/* Media type for I82598 is based on device ID */
24162306a36Sopenharmony_ci	switch (hw->device_id) {
24262306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598:
24362306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598_BX:
24462306a36Sopenharmony_ci		/* Default device ID is mezzanine card KX/KX4 */
24562306a36Sopenharmony_ci		return ixgbe_media_type_backplane;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598AF_DUAL_PORT:
24862306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
24962306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
25062306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
25162306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598EB_XF_LR:
25262306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598EB_SFP_LOM:
25362306a36Sopenharmony_ci		return ixgbe_media_type_fiber;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598EB_CX4:
25662306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
25762306a36Sopenharmony_ci		return ixgbe_media_type_cx4;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598AT:
26062306a36Sopenharmony_ci	case IXGBE_DEV_ID_82598AT2:
26162306a36Sopenharmony_ci		return ixgbe_media_type_copper;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	default:
26462306a36Sopenharmony_ci		return ixgbe_media_type_unknown;
26562306a36Sopenharmony_ci	}
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci/**
26962306a36Sopenharmony_ci *  ixgbe_fc_enable_82598 - Enable flow control
27062306a36Sopenharmony_ci *  @hw: pointer to hardware structure
27162306a36Sopenharmony_ci *
27262306a36Sopenharmony_ci *  Enable flow control according to the current settings.
27362306a36Sopenharmony_ci **/
27462306a36Sopenharmony_cistatic s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	u32 fctrl_reg;
27762306a36Sopenharmony_ci	u32 rmcs_reg;
27862306a36Sopenharmony_ci	u32 reg;
27962306a36Sopenharmony_ci	u32 fcrtl, fcrth;
28062306a36Sopenharmony_ci	u32 link_speed = 0;
28162306a36Sopenharmony_ci	int i;
28262306a36Sopenharmony_ci	bool link_up;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* Validate the water mark configuration */
28562306a36Sopenharmony_ci	if (!hw->fc.pause_time)
28662306a36Sopenharmony_ci		return -EINVAL;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	/* Low water mark of zero causes XOFF floods */
28962306a36Sopenharmony_ci	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
29062306a36Sopenharmony_ci		if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
29162306a36Sopenharmony_ci		    hw->fc.high_water[i]) {
29262306a36Sopenharmony_ci			if (!hw->fc.low_water[i] ||
29362306a36Sopenharmony_ci			    hw->fc.low_water[i] >= hw->fc.high_water[i]) {
29462306a36Sopenharmony_ci				hw_dbg(hw, "Invalid water mark configuration\n");
29562306a36Sopenharmony_ci				return -EINVAL;
29662306a36Sopenharmony_ci			}
29762306a36Sopenharmony_ci		}
29862306a36Sopenharmony_ci	}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	/*
30162306a36Sopenharmony_ci	 * On 82598 having Rx FC on causes resets while doing 1G
30262306a36Sopenharmony_ci	 * so if it's on turn it off once we know link_speed. For
30362306a36Sopenharmony_ci	 * more details see 82598 Specification update.
30462306a36Sopenharmony_ci	 */
30562306a36Sopenharmony_ci	hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
30662306a36Sopenharmony_ci	if (link_up && link_speed == IXGBE_LINK_SPEED_1GB_FULL) {
30762306a36Sopenharmony_ci		switch (hw->fc.requested_mode) {
30862306a36Sopenharmony_ci		case ixgbe_fc_full:
30962306a36Sopenharmony_ci			hw->fc.requested_mode = ixgbe_fc_tx_pause;
31062306a36Sopenharmony_ci			break;
31162306a36Sopenharmony_ci		case ixgbe_fc_rx_pause:
31262306a36Sopenharmony_ci			hw->fc.requested_mode = ixgbe_fc_none;
31362306a36Sopenharmony_ci			break;
31462306a36Sopenharmony_ci		default:
31562306a36Sopenharmony_ci			/* no change */
31662306a36Sopenharmony_ci			break;
31762306a36Sopenharmony_ci		}
31862306a36Sopenharmony_ci	}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	/* Negotiate the fc mode to use */
32162306a36Sopenharmony_ci	hw->mac.ops.fc_autoneg(hw);
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	/* Disable any previous flow control settings */
32462306a36Sopenharmony_ci	fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
32562306a36Sopenharmony_ci	fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
32862306a36Sopenharmony_ci	rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	/*
33162306a36Sopenharmony_ci	 * The possible values of fc.current_mode are:
33262306a36Sopenharmony_ci	 * 0: Flow control is completely disabled
33362306a36Sopenharmony_ci	 * 1: Rx flow control is enabled (we can receive pause frames,
33462306a36Sopenharmony_ci	 *    but not send pause frames).
33562306a36Sopenharmony_ci	 * 2: Tx flow control is enabled (we can send pause frames but
33662306a36Sopenharmony_ci	 *     we do not support receiving pause frames).
33762306a36Sopenharmony_ci	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
33862306a36Sopenharmony_ci	 * other: Invalid.
33962306a36Sopenharmony_ci	 */
34062306a36Sopenharmony_ci	switch (hw->fc.current_mode) {
34162306a36Sopenharmony_ci	case ixgbe_fc_none:
34262306a36Sopenharmony_ci		/*
34362306a36Sopenharmony_ci		 * Flow control is disabled by software override or autoneg.
34462306a36Sopenharmony_ci		 * The code below will actually disable it in the HW.
34562306a36Sopenharmony_ci		 */
34662306a36Sopenharmony_ci		break;
34762306a36Sopenharmony_ci	case ixgbe_fc_rx_pause:
34862306a36Sopenharmony_ci		/*
34962306a36Sopenharmony_ci		 * Rx Flow control is enabled and Tx Flow control is
35062306a36Sopenharmony_ci		 * disabled by software override. Since there really
35162306a36Sopenharmony_ci		 * isn't a way to advertise that we are capable of RX
35262306a36Sopenharmony_ci		 * Pause ONLY, we will advertise that we support both
35362306a36Sopenharmony_ci		 * symmetric and asymmetric Rx PAUSE.  Later, we will
35462306a36Sopenharmony_ci		 * disable the adapter's ability to send PAUSE frames.
35562306a36Sopenharmony_ci		 */
35662306a36Sopenharmony_ci		fctrl_reg |= IXGBE_FCTRL_RFCE;
35762306a36Sopenharmony_ci		break;
35862306a36Sopenharmony_ci	case ixgbe_fc_tx_pause:
35962306a36Sopenharmony_ci		/*
36062306a36Sopenharmony_ci		 * Tx Flow control is enabled, and Rx Flow control is
36162306a36Sopenharmony_ci		 * disabled by software override.
36262306a36Sopenharmony_ci		 */
36362306a36Sopenharmony_ci		rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
36462306a36Sopenharmony_ci		break;
36562306a36Sopenharmony_ci	case ixgbe_fc_full:
36662306a36Sopenharmony_ci		/* Flow control (both Rx and Tx) is enabled by SW override. */
36762306a36Sopenharmony_ci		fctrl_reg |= IXGBE_FCTRL_RFCE;
36862306a36Sopenharmony_ci		rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
36962306a36Sopenharmony_ci		break;
37062306a36Sopenharmony_ci	default:
37162306a36Sopenharmony_ci		hw_dbg(hw, "Flow control param set incorrectly\n");
37262306a36Sopenharmony_ci		return -EIO;
37362306a36Sopenharmony_ci	}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	/* Set 802.3x based flow control settings. */
37662306a36Sopenharmony_ci	fctrl_reg |= IXGBE_FCTRL_DPF;
37762306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg);
37862306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	/* Set up and enable Rx high/low water mark thresholds, enable XON. */
38162306a36Sopenharmony_ci	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
38262306a36Sopenharmony_ci		if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
38362306a36Sopenharmony_ci		    hw->fc.high_water[i]) {
38462306a36Sopenharmony_ci			fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
38562306a36Sopenharmony_ci			fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
38662306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
38762306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), fcrth);
38862306a36Sopenharmony_ci		} else {
38962306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0);
39062306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0);
39162306a36Sopenharmony_ci		}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	}
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	/* Configure pause time (2 TCs per register) */
39662306a36Sopenharmony_ci	reg = hw->fc.pause_time * 0x00010001;
39762306a36Sopenharmony_ci	for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
39862306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	/* Configure flow control refresh threshold value */
40162306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	return 0;
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci/**
40762306a36Sopenharmony_ci *  ixgbe_start_mac_link_82598 - Configures MAC link settings
40862306a36Sopenharmony_ci *  @hw: pointer to hardware structure
40962306a36Sopenharmony_ci *  @autoneg_wait_to_complete: true when waiting for completion is needed
41062306a36Sopenharmony_ci *
41162306a36Sopenharmony_ci *  Configures link settings based on values in the ixgbe_hw struct.
41262306a36Sopenharmony_ci *  Restarts the link.  Performs autonegotiation if needed.
41362306a36Sopenharmony_ci **/
41462306a36Sopenharmony_cistatic s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw,
41562306a36Sopenharmony_ci				      bool autoneg_wait_to_complete)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	u32 autoc_reg;
41862306a36Sopenharmony_ci	u32 links_reg;
41962306a36Sopenharmony_ci	u32 i;
42062306a36Sopenharmony_ci	s32 status = 0;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	/* Restart link */
42362306a36Sopenharmony_ci	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
42462306a36Sopenharmony_ci	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
42562306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	/* Only poll for autoneg to complete if specified to do so */
42862306a36Sopenharmony_ci	if (autoneg_wait_to_complete) {
42962306a36Sopenharmony_ci		if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
43062306a36Sopenharmony_ci		     IXGBE_AUTOC_LMS_KX4_AN ||
43162306a36Sopenharmony_ci		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
43262306a36Sopenharmony_ci		     IXGBE_AUTOC_LMS_KX4_AN_1G_AN) {
43362306a36Sopenharmony_ci			links_reg = 0; /* Just in case Autoneg time = 0 */
43462306a36Sopenharmony_ci			for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
43562306a36Sopenharmony_ci				links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
43662306a36Sopenharmony_ci				if (links_reg & IXGBE_LINKS_KX_AN_COMP)
43762306a36Sopenharmony_ci					break;
43862306a36Sopenharmony_ci				msleep(100);
43962306a36Sopenharmony_ci			}
44062306a36Sopenharmony_ci			if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
44162306a36Sopenharmony_ci				status = -EIO;
44262306a36Sopenharmony_ci				hw_dbg(hw, "Autonegotiation did not complete.\n");
44362306a36Sopenharmony_ci			}
44462306a36Sopenharmony_ci		}
44562306a36Sopenharmony_ci	}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	/* Add delay to filter out noises during initial link setup */
44862306a36Sopenharmony_ci	msleep(50);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	return status;
45162306a36Sopenharmony_ci}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci/**
45462306a36Sopenharmony_ci *  ixgbe_validate_link_ready - Function looks for phy link
45562306a36Sopenharmony_ci *  @hw: pointer to hardware structure
45662306a36Sopenharmony_ci *
45762306a36Sopenharmony_ci *  Function indicates success when phy link is available. If phy is not ready
45862306a36Sopenharmony_ci *  within 5 seconds of MAC indicating link, the function returns error.
45962306a36Sopenharmony_ci **/
46062306a36Sopenharmony_cistatic s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw)
46162306a36Sopenharmony_ci{
46262306a36Sopenharmony_ci	u32 timeout;
46362306a36Sopenharmony_ci	u16 an_reg;
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	if (hw->device_id != IXGBE_DEV_ID_82598AT2)
46662306a36Sopenharmony_ci		return 0;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	for (timeout = 0;
46962306a36Sopenharmony_ci	     timeout < IXGBE_VALIDATE_LINK_READY_TIMEOUT; timeout++) {
47062306a36Sopenharmony_ci		hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, &an_reg);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci		if ((an_reg & MDIO_AN_STAT1_COMPLETE) &&
47362306a36Sopenharmony_ci		    (an_reg & MDIO_STAT1_LSTATUS))
47462306a36Sopenharmony_ci			break;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci		msleep(100);
47762306a36Sopenharmony_ci	}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	if (timeout == IXGBE_VALIDATE_LINK_READY_TIMEOUT) {
48062306a36Sopenharmony_ci		hw_dbg(hw, "Link was indicated but link is down\n");
48162306a36Sopenharmony_ci		return -EIO;
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	return 0;
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci/**
48862306a36Sopenharmony_ci *  ixgbe_check_mac_link_82598 - Get link/speed status
48962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
49062306a36Sopenharmony_ci *  @speed: pointer to link speed
49162306a36Sopenharmony_ci *  @link_up: true is link is up, false otherwise
49262306a36Sopenharmony_ci *  @link_up_wait_to_complete: bool used to wait for link up or not
49362306a36Sopenharmony_ci *
49462306a36Sopenharmony_ci *  Reads the links register to determine if link is up and the current speed
49562306a36Sopenharmony_ci **/
49662306a36Sopenharmony_cistatic s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
49762306a36Sopenharmony_ci				      ixgbe_link_speed *speed, bool *link_up,
49862306a36Sopenharmony_ci				      bool link_up_wait_to_complete)
49962306a36Sopenharmony_ci{
50062306a36Sopenharmony_ci	u32 links_reg;
50162306a36Sopenharmony_ci	u32 i;
50262306a36Sopenharmony_ci	u16 link_reg, adapt_comp_reg;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	/*
50562306a36Sopenharmony_ci	 * SERDES PHY requires us to read link status from register 0xC79F.
50662306a36Sopenharmony_ci	 * Bit 0 set indicates link is up/ready; clear indicates link down.
50762306a36Sopenharmony_ci	 * 0xC00C is read to check that the XAUI lanes are active.  Bit 0
50862306a36Sopenharmony_ci	 * clear indicates active; set indicates inactive.
50962306a36Sopenharmony_ci	 */
51062306a36Sopenharmony_ci	if (hw->phy.type == ixgbe_phy_nl) {
51162306a36Sopenharmony_ci		hw->phy.ops.read_reg(hw, 0xC79F, MDIO_MMD_PMAPMD, &link_reg);
51262306a36Sopenharmony_ci		hw->phy.ops.read_reg(hw, 0xC79F, MDIO_MMD_PMAPMD, &link_reg);
51362306a36Sopenharmony_ci		hw->phy.ops.read_reg(hw, 0xC00C, MDIO_MMD_PMAPMD,
51462306a36Sopenharmony_ci				     &adapt_comp_reg);
51562306a36Sopenharmony_ci		if (link_up_wait_to_complete) {
51662306a36Sopenharmony_ci			for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
51762306a36Sopenharmony_ci				if ((link_reg & 1) &&
51862306a36Sopenharmony_ci				    ((adapt_comp_reg & 1) == 0)) {
51962306a36Sopenharmony_ci					*link_up = true;
52062306a36Sopenharmony_ci					break;
52162306a36Sopenharmony_ci				} else {
52262306a36Sopenharmony_ci					*link_up = false;
52362306a36Sopenharmony_ci				}
52462306a36Sopenharmony_ci				msleep(100);
52562306a36Sopenharmony_ci				hw->phy.ops.read_reg(hw, 0xC79F,
52662306a36Sopenharmony_ci						     MDIO_MMD_PMAPMD,
52762306a36Sopenharmony_ci						     &link_reg);
52862306a36Sopenharmony_ci				hw->phy.ops.read_reg(hw, 0xC00C,
52962306a36Sopenharmony_ci						     MDIO_MMD_PMAPMD,
53062306a36Sopenharmony_ci						     &adapt_comp_reg);
53162306a36Sopenharmony_ci			}
53262306a36Sopenharmony_ci		} else {
53362306a36Sopenharmony_ci			if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0))
53462306a36Sopenharmony_ci				*link_up = true;
53562306a36Sopenharmony_ci			else
53662306a36Sopenharmony_ci				*link_up = false;
53762306a36Sopenharmony_ci		}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci		if (!*link_up)
54062306a36Sopenharmony_ci			return 0;
54162306a36Sopenharmony_ci	}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
54462306a36Sopenharmony_ci	if (link_up_wait_to_complete) {
54562306a36Sopenharmony_ci		for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
54662306a36Sopenharmony_ci			if (links_reg & IXGBE_LINKS_UP) {
54762306a36Sopenharmony_ci				*link_up = true;
54862306a36Sopenharmony_ci				break;
54962306a36Sopenharmony_ci			} else {
55062306a36Sopenharmony_ci				*link_up = false;
55162306a36Sopenharmony_ci			}
55262306a36Sopenharmony_ci			msleep(100);
55362306a36Sopenharmony_ci			links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
55462306a36Sopenharmony_ci		}
55562306a36Sopenharmony_ci	} else {
55662306a36Sopenharmony_ci		if (links_reg & IXGBE_LINKS_UP)
55762306a36Sopenharmony_ci			*link_up = true;
55862306a36Sopenharmony_ci		else
55962306a36Sopenharmony_ci			*link_up = false;
56062306a36Sopenharmony_ci	}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	if (links_reg & IXGBE_LINKS_SPEED)
56362306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_10GB_FULL;
56462306a36Sopenharmony_ci	else
56562306a36Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_1GB_FULL;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && *link_up &&
56862306a36Sopenharmony_ci	    (ixgbe_validate_link_ready(hw) != 0))
56962306a36Sopenharmony_ci		*link_up = false;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	return 0;
57262306a36Sopenharmony_ci}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci/**
57562306a36Sopenharmony_ci *  ixgbe_setup_mac_link_82598 - Set MAC link speed
57662306a36Sopenharmony_ci *  @hw: pointer to hardware structure
57762306a36Sopenharmony_ci *  @speed: new link speed
57862306a36Sopenharmony_ci *  @autoneg_wait_to_complete: true when waiting for completion is needed
57962306a36Sopenharmony_ci *
58062306a36Sopenharmony_ci *  Set the link speed in the AUTOC register and restarts link.
58162306a36Sopenharmony_ci **/
58262306a36Sopenharmony_cistatic s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
58362306a36Sopenharmony_ci				      ixgbe_link_speed speed,
58462306a36Sopenharmony_ci				      bool autoneg_wait_to_complete)
58562306a36Sopenharmony_ci{
58662306a36Sopenharmony_ci	bool		 autoneg	   = false;
58762306a36Sopenharmony_ci	ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
58862306a36Sopenharmony_ci	u32              curr_autoc        = IXGBE_READ_REG(hw, IXGBE_AUTOC);
58962306a36Sopenharmony_ci	u32              autoc             = curr_autoc;
59062306a36Sopenharmony_ci	u32              link_mode         = autoc & IXGBE_AUTOC_LMS_MASK;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	/* Check to see if speed passed in is supported. */
59362306a36Sopenharmony_ci	ixgbe_get_link_capabilities_82598(hw, &link_capabilities, &autoneg);
59462306a36Sopenharmony_ci	speed &= link_capabilities;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	if (speed == IXGBE_LINK_SPEED_UNKNOWN)
59762306a36Sopenharmony_ci		return -EINVAL;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	/* Set KX4/KX support according to speed requested */
60062306a36Sopenharmony_ci	else if (link_mode == IXGBE_AUTOC_LMS_KX4_AN ||
60162306a36Sopenharmony_ci		 link_mode == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) {
60262306a36Sopenharmony_ci		autoc &= ~IXGBE_AUTOC_KX4_KX_SUPP_MASK;
60362306a36Sopenharmony_ci		if (speed & IXGBE_LINK_SPEED_10GB_FULL)
60462306a36Sopenharmony_ci			autoc |= IXGBE_AUTOC_KX4_SUPP;
60562306a36Sopenharmony_ci		if (speed & IXGBE_LINK_SPEED_1GB_FULL)
60662306a36Sopenharmony_ci			autoc |= IXGBE_AUTOC_KX_SUPP;
60762306a36Sopenharmony_ci		if (autoc != curr_autoc)
60862306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	/* Setup and restart the link based on the new values in
61262306a36Sopenharmony_ci	 * ixgbe_hw This will write the AUTOC register based on the new
61362306a36Sopenharmony_ci	 * stored values
61462306a36Sopenharmony_ci	 */
61562306a36Sopenharmony_ci	return ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
61662306a36Sopenharmony_ci}
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci/**
62062306a36Sopenharmony_ci *  ixgbe_setup_copper_link_82598 - Set the PHY autoneg advertised field
62162306a36Sopenharmony_ci *  @hw: pointer to hardware structure
62262306a36Sopenharmony_ci *  @speed: new link speed
62362306a36Sopenharmony_ci *  @autoneg_wait_to_complete: true if waiting is needed to complete
62462306a36Sopenharmony_ci *
62562306a36Sopenharmony_ci *  Sets the link speed in the AUTOC register in the MAC and restarts link.
62662306a36Sopenharmony_ci **/
62762306a36Sopenharmony_cistatic s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
62862306a36Sopenharmony_ci					       ixgbe_link_speed speed,
62962306a36Sopenharmony_ci					       bool autoneg_wait_to_complete)
63062306a36Sopenharmony_ci{
63162306a36Sopenharmony_ci	s32 status;
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci	/* Setup the PHY according to input speed */
63462306a36Sopenharmony_ci	status = hw->phy.ops.setup_link_speed(hw, speed,
63562306a36Sopenharmony_ci					      autoneg_wait_to_complete);
63662306a36Sopenharmony_ci	/* Set up MAC */
63762306a36Sopenharmony_ci	ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	return status;
64062306a36Sopenharmony_ci}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci/**
64362306a36Sopenharmony_ci *  ixgbe_reset_hw_82598 - Performs hardware reset
64462306a36Sopenharmony_ci *  @hw: pointer to hardware structure
64562306a36Sopenharmony_ci *
64662306a36Sopenharmony_ci *  Resets the hardware by resetting the transmit and receive units, masks and
64762306a36Sopenharmony_ci *  clears all interrupts, performing a PHY reset, and performing a link (MAC)
64862306a36Sopenharmony_ci *  reset.
64962306a36Sopenharmony_ci **/
65062306a36Sopenharmony_cistatic s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
65162306a36Sopenharmony_ci{
65262306a36Sopenharmony_ci	s32 status;
65362306a36Sopenharmony_ci	s32 phy_status = 0;
65462306a36Sopenharmony_ci	u32 ctrl;
65562306a36Sopenharmony_ci	u32 gheccr;
65662306a36Sopenharmony_ci	u32 i;
65762306a36Sopenharmony_ci	u32 autoc;
65862306a36Sopenharmony_ci	u8  analog_val;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	/* Call adapter stop to disable tx/rx and clear interrupts */
66162306a36Sopenharmony_ci	status = hw->mac.ops.stop_adapter(hw);
66262306a36Sopenharmony_ci	if (status)
66362306a36Sopenharmony_ci		return status;
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	/*
66662306a36Sopenharmony_ci	 * Power up the Atlas Tx lanes if they are currently powered down.
66762306a36Sopenharmony_ci	 * Atlas Tx lanes are powered down for MAC loopback tests, but
66862306a36Sopenharmony_ci	 * they are not automatically restored on reset.
66962306a36Sopenharmony_ci	 */
67062306a36Sopenharmony_ci	hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val);
67162306a36Sopenharmony_ci	if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) {
67262306a36Sopenharmony_ci		/* Enable Tx Atlas so packets can be transmitted again */
67362306a36Sopenharmony_ci		hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK,
67462306a36Sopenharmony_ci					     &analog_val);
67562306a36Sopenharmony_ci		analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN;
67662306a36Sopenharmony_ci		hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK,
67762306a36Sopenharmony_ci					      analog_val);
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci		hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G,
68062306a36Sopenharmony_ci					     &analog_val);
68162306a36Sopenharmony_ci		analog_val &= ~IXGBE_ATLAS_PDN_TX_10G_QL_ALL;
68262306a36Sopenharmony_ci		hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G,
68362306a36Sopenharmony_ci					      analog_val);
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci		hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G,
68662306a36Sopenharmony_ci					     &analog_val);
68762306a36Sopenharmony_ci		analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL;
68862306a36Sopenharmony_ci		hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G,
68962306a36Sopenharmony_ci					      analog_val);
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci		hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN,
69262306a36Sopenharmony_ci					     &analog_val);
69362306a36Sopenharmony_ci		analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL;
69462306a36Sopenharmony_ci		hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN,
69562306a36Sopenharmony_ci					      analog_val);
69662306a36Sopenharmony_ci	}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	/* Reset PHY */
69962306a36Sopenharmony_ci	if (hw->phy.reset_disable == false) {
70062306a36Sopenharmony_ci		/* PHY ops must be identified and initialized prior to reset */
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci		/* Init PHY and function pointers, perform SFP setup */
70362306a36Sopenharmony_ci		phy_status = hw->phy.ops.init(hw);
70462306a36Sopenharmony_ci		if (phy_status == -EOPNOTSUPP)
70562306a36Sopenharmony_ci			return phy_status;
70662306a36Sopenharmony_ci		if (phy_status == -ENOENT)
70762306a36Sopenharmony_ci			goto mac_reset_top;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci		hw->phy.ops.reset(hw);
71062306a36Sopenharmony_ci	}
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_cimac_reset_top:
71362306a36Sopenharmony_ci	/*
71462306a36Sopenharmony_ci	 * Issue global reset to the MAC.  This needs to be a SW reset.
71562306a36Sopenharmony_ci	 * If link reset is used, it might reset the MAC when mng is using it
71662306a36Sopenharmony_ci	 */
71762306a36Sopenharmony_ci	ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL) | IXGBE_CTRL_RST;
71862306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
71962306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
72062306a36Sopenharmony_ci	usleep_range(1000, 1200);
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	/* Poll for reset bit to self-clear indicating reset is complete */
72362306a36Sopenharmony_ci	for (i = 0; i < 10; i++) {
72462306a36Sopenharmony_ci		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
72562306a36Sopenharmony_ci		if (!(ctrl & IXGBE_CTRL_RST))
72662306a36Sopenharmony_ci			break;
72762306a36Sopenharmony_ci		udelay(1);
72862306a36Sopenharmony_ci	}
72962306a36Sopenharmony_ci	if (ctrl & IXGBE_CTRL_RST) {
73062306a36Sopenharmony_ci		status = -EIO;
73162306a36Sopenharmony_ci		hw_dbg(hw, "Reset polling failed to complete.\n");
73262306a36Sopenharmony_ci	}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	msleep(50);
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci	/*
73762306a36Sopenharmony_ci	 * Double resets are required for recovery from certain error
73862306a36Sopenharmony_ci	 * conditions.  Between resets, it is necessary to stall to allow time
73962306a36Sopenharmony_ci	 * for any pending HW events to complete.
74062306a36Sopenharmony_ci	 */
74162306a36Sopenharmony_ci	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
74262306a36Sopenharmony_ci		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
74362306a36Sopenharmony_ci		goto mac_reset_top;
74462306a36Sopenharmony_ci	}
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR);
74762306a36Sopenharmony_ci	gheccr &= ~(BIT(21) | BIT(18) | BIT(9) | BIT(6));
74862306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr);
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	/*
75162306a36Sopenharmony_ci	 * Store the original AUTOC value if it has not been
75262306a36Sopenharmony_ci	 * stored off yet.  Otherwise restore the stored original
75362306a36Sopenharmony_ci	 * AUTOC value since the reset operation sets back to deaults.
75462306a36Sopenharmony_ci	 */
75562306a36Sopenharmony_ci	autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
75662306a36Sopenharmony_ci	if (hw->mac.orig_link_settings_stored == false) {
75762306a36Sopenharmony_ci		hw->mac.orig_autoc = autoc;
75862306a36Sopenharmony_ci		hw->mac.orig_link_settings_stored = true;
75962306a36Sopenharmony_ci	} else if (autoc != hw->mac.orig_autoc) {
76062306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
76162306a36Sopenharmony_ci	}
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	/* Store the permanent mac address */
76462306a36Sopenharmony_ci	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	/*
76762306a36Sopenharmony_ci	 * Store MAC address from RAR0, clear receive address registers, and
76862306a36Sopenharmony_ci	 * clear the multicast table
76962306a36Sopenharmony_ci	 */
77062306a36Sopenharmony_ci	hw->mac.ops.init_rx_addrs(hw);
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	if (phy_status)
77362306a36Sopenharmony_ci		status = phy_status;
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	return status;
77662306a36Sopenharmony_ci}
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci/**
77962306a36Sopenharmony_ci *  ixgbe_set_vmdq_82598 - Associate a VMDq set index with a rx address
78062306a36Sopenharmony_ci *  @hw: pointer to hardware struct
78162306a36Sopenharmony_ci *  @rar: receive address register index to associate with a VMDq index
78262306a36Sopenharmony_ci *  @vmdq: VMDq set index
78362306a36Sopenharmony_ci **/
78462306a36Sopenharmony_cistatic s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
78562306a36Sopenharmony_ci{
78662306a36Sopenharmony_ci	u32 rar_high;
78762306a36Sopenharmony_ci	u32 rar_entries = hw->mac.num_rar_entries;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	/* Make sure we are using a valid rar index range */
79062306a36Sopenharmony_ci	if (rar >= rar_entries) {
79162306a36Sopenharmony_ci		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
79262306a36Sopenharmony_ci		return -EINVAL;
79362306a36Sopenharmony_ci	}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
79662306a36Sopenharmony_ci	rar_high &= ~IXGBE_RAH_VIND_MASK;
79762306a36Sopenharmony_ci	rar_high |= ((vmdq << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK);
79862306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
79962306a36Sopenharmony_ci	return 0;
80062306a36Sopenharmony_ci}
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci/**
80362306a36Sopenharmony_ci *  ixgbe_clear_vmdq_82598 - Disassociate a VMDq set index from an rx address
80462306a36Sopenharmony_ci *  @hw: pointer to hardware struct
80562306a36Sopenharmony_ci *  @rar: receive address register index to associate with a VMDq index
80662306a36Sopenharmony_ci *  @vmdq: VMDq clear index (not used in 82598, but elsewhere)
80762306a36Sopenharmony_ci **/
80862306a36Sopenharmony_cistatic s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
80962306a36Sopenharmony_ci{
81062306a36Sopenharmony_ci	u32 rar_high;
81162306a36Sopenharmony_ci	u32 rar_entries = hw->mac.num_rar_entries;
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	/* Make sure we are using a valid rar index range */
81562306a36Sopenharmony_ci	if (rar >= rar_entries) {
81662306a36Sopenharmony_ci		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
81762306a36Sopenharmony_ci		return -EINVAL;
81862306a36Sopenharmony_ci	}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
82162306a36Sopenharmony_ci	if (rar_high & IXGBE_RAH_VIND_MASK) {
82262306a36Sopenharmony_ci		rar_high &= ~IXGBE_RAH_VIND_MASK;
82362306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
82462306a36Sopenharmony_ci	}
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	return 0;
82762306a36Sopenharmony_ci}
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci/**
83062306a36Sopenharmony_ci *  ixgbe_set_vfta_82598 - Set VLAN filter table
83162306a36Sopenharmony_ci *  @hw: pointer to hardware structure
83262306a36Sopenharmony_ci *  @vlan: VLAN id to write to VLAN filter
83362306a36Sopenharmony_ci *  @vind: VMDq output index that maps queue to VLAN id in VFTA
83462306a36Sopenharmony_ci *  @vlan_on: boolean flag to turn on/off VLAN in VFTA
83562306a36Sopenharmony_ci *  @vlvf_bypass: boolean flag - unused
83662306a36Sopenharmony_ci *
83762306a36Sopenharmony_ci *  Turn on/off specified VLAN in the VLAN filter table.
83862306a36Sopenharmony_ci **/
83962306a36Sopenharmony_cistatic s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind,
84062306a36Sopenharmony_ci				bool vlan_on, bool vlvf_bypass)
84162306a36Sopenharmony_ci{
84262306a36Sopenharmony_ci	u32 regindex;
84362306a36Sopenharmony_ci	u32 bitindex;
84462306a36Sopenharmony_ci	u32 bits;
84562306a36Sopenharmony_ci	u32 vftabyte;
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	if (vlan > 4095)
84862306a36Sopenharmony_ci		return -EINVAL;
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	/* Determine 32-bit word position in array */
85162306a36Sopenharmony_ci	regindex = (vlan >> 5) & 0x7F;   /* upper seven bits */
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	/* Determine the location of the (VMD) queue index */
85462306a36Sopenharmony_ci	vftabyte =  ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */
85562306a36Sopenharmony_ci	bitindex = (vlan & 0x7) << 2;    /* lower 3 bits indicate nibble */
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	/* Set the nibble for VMD queue index */
85862306a36Sopenharmony_ci	bits = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex));
85962306a36Sopenharmony_ci	bits &= (~(0x0F << bitindex));
86062306a36Sopenharmony_ci	bits |= (vind << bitindex);
86162306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex), bits);
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	/* Determine the location of the bit for this VLAN id */
86462306a36Sopenharmony_ci	bitindex = vlan & 0x1F;   /* lower five bits */
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
86762306a36Sopenharmony_ci	if (vlan_on)
86862306a36Sopenharmony_ci		/* Turn on this VLAN id */
86962306a36Sopenharmony_ci		bits |= BIT(bitindex);
87062306a36Sopenharmony_ci	else
87162306a36Sopenharmony_ci		/* Turn off this VLAN id */
87262306a36Sopenharmony_ci		bits &= ~BIT(bitindex);
87362306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits);
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	return 0;
87662306a36Sopenharmony_ci}
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci/**
87962306a36Sopenharmony_ci *  ixgbe_clear_vfta_82598 - Clear VLAN filter table
88062306a36Sopenharmony_ci *  @hw: pointer to hardware structure
88162306a36Sopenharmony_ci *
88262306a36Sopenharmony_ci *  Clears the VLAN filter table, and the VMDq index associated with the filter
88362306a36Sopenharmony_ci **/
88462306a36Sopenharmony_cistatic s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw)
88562306a36Sopenharmony_ci{
88662306a36Sopenharmony_ci	u32 offset;
88762306a36Sopenharmony_ci	u32 vlanbyte;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	for (offset = 0; offset < hw->mac.vft_size; offset++)
89062306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	for (vlanbyte = 0; vlanbyte < 4; vlanbyte++)
89362306a36Sopenharmony_ci		for (offset = 0; offset < hw->mac.vft_size; offset++)
89462306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset),
89562306a36Sopenharmony_ci					0);
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	return 0;
89862306a36Sopenharmony_ci}
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci/**
90162306a36Sopenharmony_ci *  ixgbe_read_analog_reg8_82598 - Reads 8 bit Atlas analog register
90262306a36Sopenharmony_ci *  @hw: pointer to hardware structure
90362306a36Sopenharmony_ci *  @reg: analog register to read
90462306a36Sopenharmony_ci *  @val: read value
90562306a36Sopenharmony_ci *
90662306a36Sopenharmony_ci *  Performs read operation to Atlas analog register specified.
90762306a36Sopenharmony_ci **/
90862306a36Sopenharmony_cistatic s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val)
90962306a36Sopenharmony_ci{
91062306a36Sopenharmony_ci	u32  atlas_ctl;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL,
91362306a36Sopenharmony_ci			IXGBE_ATLASCTL_WRITE_CMD | (reg << 8));
91462306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
91562306a36Sopenharmony_ci	udelay(10);
91662306a36Sopenharmony_ci	atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL);
91762306a36Sopenharmony_ci	*val = (u8)atlas_ctl;
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	return 0;
92062306a36Sopenharmony_ci}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci/**
92362306a36Sopenharmony_ci *  ixgbe_write_analog_reg8_82598 - Writes 8 bit Atlas analog register
92462306a36Sopenharmony_ci *  @hw: pointer to hardware structure
92562306a36Sopenharmony_ci *  @reg: atlas register to write
92662306a36Sopenharmony_ci *  @val: value to write
92762306a36Sopenharmony_ci *
92862306a36Sopenharmony_ci *  Performs write operation to Atlas analog register specified.
92962306a36Sopenharmony_ci **/
93062306a36Sopenharmony_cistatic s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
93162306a36Sopenharmony_ci{
93262306a36Sopenharmony_ci	u32  atlas_ctl;
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	atlas_ctl = (reg << 8) | val;
93562306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl);
93662306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
93762306a36Sopenharmony_ci	udelay(10);
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	return 0;
94062306a36Sopenharmony_ci}
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci/**
94362306a36Sopenharmony_ci *  ixgbe_read_i2c_phy_82598 - Reads 8 bit word over I2C interface.
94462306a36Sopenharmony_ci *  @hw: pointer to hardware structure
94562306a36Sopenharmony_ci *  @dev_addr: address to read from
94662306a36Sopenharmony_ci *  @byte_offset: byte offset to read from dev_addr
94762306a36Sopenharmony_ci *  @eeprom_data: value read
94862306a36Sopenharmony_ci *
94962306a36Sopenharmony_ci *  Performs 8 byte read operation to SFP module's data over I2C interface.
95062306a36Sopenharmony_ci **/
95162306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_phy_82598(struct ixgbe_hw *hw, u8 dev_addr,
95262306a36Sopenharmony_ci				    u8 byte_offset, u8 *eeprom_data)
95362306a36Sopenharmony_ci{
95462306a36Sopenharmony_ci	s32 status = 0;
95562306a36Sopenharmony_ci	u16 sfp_addr = 0;
95662306a36Sopenharmony_ci	u16 sfp_data = 0;
95762306a36Sopenharmony_ci	u16 sfp_stat = 0;
95862306a36Sopenharmony_ci	u16 gssr;
95962306a36Sopenharmony_ci	u32 i;
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
96262306a36Sopenharmony_ci		gssr = IXGBE_GSSR_PHY1_SM;
96362306a36Sopenharmony_ci	else
96462306a36Sopenharmony_ci		gssr = IXGBE_GSSR_PHY0_SM;
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0)
96762306a36Sopenharmony_ci		return -EBUSY;
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	if (hw->phy.type == ixgbe_phy_nl) {
97062306a36Sopenharmony_ci		/*
97162306a36Sopenharmony_ci		 * phy SDA/SCL registers are at addresses 0xC30A to
97262306a36Sopenharmony_ci		 * 0xC30D.  These registers are used to talk to the SFP+
97362306a36Sopenharmony_ci		 * module's EEPROM through the SDA/SCL (I2C) interface.
97462306a36Sopenharmony_ci		 */
97562306a36Sopenharmony_ci		sfp_addr = (dev_addr << 8) + byte_offset;
97662306a36Sopenharmony_ci		sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK);
97762306a36Sopenharmony_ci		hw->phy.ops.write_reg_mdi(hw,
97862306a36Sopenharmony_ci					  IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
97962306a36Sopenharmony_ci					  MDIO_MMD_PMAPMD,
98062306a36Sopenharmony_ci					  sfp_addr);
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci		/* Poll status */
98362306a36Sopenharmony_ci		for (i = 0; i < 100; i++) {
98462306a36Sopenharmony_ci			hw->phy.ops.read_reg_mdi(hw,
98562306a36Sopenharmony_ci						IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
98662306a36Sopenharmony_ci						MDIO_MMD_PMAPMD,
98762306a36Sopenharmony_ci						&sfp_stat);
98862306a36Sopenharmony_ci			sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK;
98962306a36Sopenharmony_ci			if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS)
99062306a36Sopenharmony_ci				break;
99162306a36Sopenharmony_ci			usleep_range(10000, 20000);
99262306a36Sopenharmony_ci		}
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci		if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) {
99562306a36Sopenharmony_ci			hw_dbg(hw, "EEPROM read did not pass.\n");
99662306a36Sopenharmony_ci			status = -ENOENT;
99762306a36Sopenharmony_ci			goto out;
99862306a36Sopenharmony_ci		}
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci		/* Read data */
100162306a36Sopenharmony_ci		hw->phy.ops.read_reg_mdi(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
100262306a36Sopenharmony_ci					MDIO_MMD_PMAPMD, &sfp_data);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci		*eeprom_data = (u8)(sfp_data >> 8);
100562306a36Sopenharmony_ci	} else {
100662306a36Sopenharmony_ci		status = -EIO;
100762306a36Sopenharmony_ci	}
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ciout:
101062306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, gssr);
101162306a36Sopenharmony_ci	return status;
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci/**
101562306a36Sopenharmony_ci *  ixgbe_read_i2c_eeprom_82598 - Reads 8 bit word over I2C interface.
101662306a36Sopenharmony_ci *  @hw: pointer to hardware structure
101762306a36Sopenharmony_ci *  @byte_offset: EEPROM byte offset to read
101862306a36Sopenharmony_ci *  @eeprom_data: value read
101962306a36Sopenharmony_ci *
102062306a36Sopenharmony_ci *  Performs 8 byte read operation to SFP module's EEPROM over I2C interface.
102162306a36Sopenharmony_ci **/
102262306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
102362306a36Sopenharmony_ci				       u8 *eeprom_data)
102462306a36Sopenharmony_ci{
102562306a36Sopenharmony_ci	return ixgbe_read_i2c_phy_82598(hw, IXGBE_I2C_EEPROM_DEV_ADDR,
102662306a36Sopenharmony_ci					byte_offset, eeprom_data);
102762306a36Sopenharmony_ci}
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci/**
103062306a36Sopenharmony_ci *  ixgbe_read_i2c_sff8472_82598 - Reads 8 bit word over I2C interface.
103162306a36Sopenharmony_ci *  @hw: pointer to hardware structure
103262306a36Sopenharmony_ci *  @byte_offset: byte offset at address 0xA2
103362306a36Sopenharmony_ci *  @sff8472_data: value read
103462306a36Sopenharmony_ci *
103562306a36Sopenharmony_ci *  Performs 8 byte read operation to SFP module's SFF-8472 data over I2C
103662306a36Sopenharmony_ci **/
103762306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_sff8472_82598(struct ixgbe_hw *hw, u8 byte_offset,
103862306a36Sopenharmony_ci				       u8 *sff8472_data)
103962306a36Sopenharmony_ci{
104062306a36Sopenharmony_ci	return ixgbe_read_i2c_phy_82598(hw, IXGBE_I2C_EEPROM_DEV_ADDR2,
104162306a36Sopenharmony_ci					byte_offset, sff8472_data);
104262306a36Sopenharmony_ci}
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci/**
104562306a36Sopenharmony_ci *  ixgbe_set_lan_id_multi_port_pcie_82598 - Set LAN id for PCIe multiple
104662306a36Sopenharmony_ci *  port devices.
104762306a36Sopenharmony_ci *  @hw: pointer to the HW structure
104862306a36Sopenharmony_ci *
104962306a36Sopenharmony_ci *  Calls common function and corrects issue with some single port devices
105062306a36Sopenharmony_ci *  that enable LAN1 but not LAN0.
105162306a36Sopenharmony_ci **/
105262306a36Sopenharmony_cistatic void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw)
105362306a36Sopenharmony_ci{
105462306a36Sopenharmony_ci	struct ixgbe_bus_info *bus = &hw->bus;
105562306a36Sopenharmony_ci	u16 pci_gen = 0;
105662306a36Sopenharmony_ci	u16 pci_ctrl2 = 0;
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	ixgbe_set_lan_id_multi_port_pcie(hw);
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	/* check if LAN0 is disabled */
106162306a36Sopenharmony_ci	hw->eeprom.ops.read(hw, IXGBE_PCIE_GENERAL_PTR, &pci_gen);
106262306a36Sopenharmony_ci	if ((pci_gen != 0) && (pci_gen != 0xFFFF)) {
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci		hw->eeprom.ops.read(hw, pci_gen + IXGBE_PCIE_CTRL2, &pci_ctrl2);
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci		/* if LAN0 is completely disabled force function to 0 */
106762306a36Sopenharmony_ci		if ((pci_ctrl2 & IXGBE_PCIE_CTRL2_LAN_DISABLE) &&
106862306a36Sopenharmony_ci		    !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DISABLE_SELECT) &&
106962306a36Sopenharmony_ci		    !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DUMMY_ENABLE)) {
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci			bus->func = 0;
107262306a36Sopenharmony_ci		}
107362306a36Sopenharmony_ci	}
107462306a36Sopenharmony_ci}
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci/**
107762306a36Sopenharmony_ci * ixgbe_set_rxpba_82598 - Initialize RX packet buffer
107862306a36Sopenharmony_ci * @hw: pointer to hardware structure
107962306a36Sopenharmony_ci * @num_pb: number of packet buffers to allocate
108062306a36Sopenharmony_ci * @headroom: reserve n KB of headroom
108162306a36Sopenharmony_ci * @strategy: packet buffer allocation strategy
108262306a36Sopenharmony_ci **/
108362306a36Sopenharmony_cistatic void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb,
108462306a36Sopenharmony_ci				  u32 headroom, int strategy)
108562306a36Sopenharmony_ci{
108662306a36Sopenharmony_ci	u32 rxpktsize = IXGBE_RXPBSIZE_64KB;
108762306a36Sopenharmony_ci	u8  i = 0;
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	if (!num_pb)
109062306a36Sopenharmony_ci		return;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	/* Setup Rx packet buffer sizes */
109362306a36Sopenharmony_ci	switch (strategy) {
109462306a36Sopenharmony_ci	case PBA_STRATEGY_WEIGHTED:
109562306a36Sopenharmony_ci		/* Setup the first four at 80KB */
109662306a36Sopenharmony_ci		rxpktsize = IXGBE_RXPBSIZE_80KB;
109762306a36Sopenharmony_ci		for (; i < 4; i++)
109862306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
109962306a36Sopenharmony_ci		/* Setup the last four at 48KB...don't re-init i */
110062306a36Sopenharmony_ci		rxpktsize = IXGBE_RXPBSIZE_48KB;
110162306a36Sopenharmony_ci		fallthrough;
110262306a36Sopenharmony_ci	case PBA_STRATEGY_EQUAL:
110362306a36Sopenharmony_ci	default:
110462306a36Sopenharmony_ci		/* Divide the remaining Rx packet buffer evenly among the TCs */
110562306a36Sopenharmony_ci		for (; i < IXGBE_MAX_PACKET_BUFFERS; i++)
110662306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
110762306a36Sopenharmony_ci		break;
110862306a36Sopenharmony_ci	}
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	/* Setup Tx packet buffer sizes */
111162306a36Sopenharmony_ci	for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++)
111262306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), IXGBE_TXPBSIZE_40KB);
111362306a36Sopenharmony_ci}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_82598 = {
111662306a36Sopenharmony_ci	.init_hw		= &ixgbe_init_hw_generic,
111762306a36Sopenharmony_ci	.reset_hw		= &ixgbe_reset_hw_82598,
111862306a36Sopenharmony_ci	.start_hw		= &ixgbe_start_hw_82598,
111962306a36Sopenharmony_ci	.clear_hw_cntrs		= &ixgbe_clear_hw_cntrs_generic,
112062306a36Sopenharmony_ci	.get_media_type		= &ixgbe_get_media_type_82598,
112162306a36Sopenharmony_ci	.enable_rx_dma          = &ixgbe_enable_rx_dma_generic,
112262306a36Sopenharmony_ci	.get_mac_addr		= &ixgbe_get_mac_addr_generic,
112362306a36Sopenharmony_ci	.stop_adapter		= &ixgbe_stop_adapter_generic,
112462306a36Sopenharmony_ci	.get_bus_info           = &ixgbe_get_bus_info_generic,
112562306a36Sopenharmony_ci	.set_lan_id             = &ixgbe_set_lan_id_multi_port_pcie_82598,
112662306a36Sopenharmony_ci	.read_analog_reg8	= &ixgbe_read_analog_reg8_82598,
112762306a36Sopenharmony_ci	.write_analog_reg8	= &ixgbe_write_analog_reg8_82598,
112862306a36Sopenharmony_ci	.setup_link		= &ixgbe_setup_mac_link_82598,
112962306a36Sopenharmony_ci	.set_rxpba		= &ixgbe_set_rxpba_82598,
113062306a36Sopenharmony_ci	.check_link		= &ixgbe_check_mac_link_82598,
113162306a36Sopenharmony_ci	.get_link_capabilities	= &ixgbe_get_link_capabilities_82598,
113262306a36Sopenharmony_ci	.led_on			= &ixgbe_led_on_generic,
113362306a36Sopenharmony_ci	.led_off		= &ixgbe_led_off_generic,
113462306a36Sopenharmony_ci	.init_led_link_act	= ixgbe_init_led_link_act_generic,
113562306a36Sopenharmony_ci	.blink_led_start	= &ixgbe_blink_led_start_generic,
113662306a36Sopenharmony_ci	.blink_led_stop		= &ixgbe_blink_led_stop_generic,
113762306a36Sopenharmony_ci	.set_rar		= &ixgbe_set_rar_generic,
113862306a36Sopenharmony_ci	.clear_rar		= &ixgbe_clear_rar_generic,
113962306a36Sopenharmony_ci	.set_vmdq		= &ixgbe_set_vmdq_82598,
114062306a36Sopenharmony_ci	.clear_vmdq		= &ixgbe_clear_vmdq_82598,
114162306a36Sopenharmony_ci	.init_rx_addrs		= &ixgbe_init_rx_addrs_generic,
114262306a36Sopenharmony_ci	.update_mc_addr_list	= &ixgbe_update_mc_addr_list_generic,
114362306a36Sopenharmony_ci	.enable_mc		= &ixgbe_enable_mc_generic,
114462306a36Sopenharmony_ci	.disable_mc		= &ixgbe_disable_mc_generic,
114562306a36Sopenharmony_ci	.clear_vfta		= &ixgbe_clear_vfta_82598,
114662306a36Sopenharmony_ci	.set_vfta		= &ixgbe_set_vfta_82598,
114762306a36Sopenharmony_ci	.fc_enable		= &ixgbe_fc_enable_82598,
114862306a36Sopenharmony_ci	.setup_fc		= ixgbe_setup_fc_generic,
114962306a36Sopenharmony_ci	.fc_autoneg		= ixgbe_fc_autoneg,
115062306a36Sopenharmony_ci	.set_fw_drv_ver         = NULL,
115162306a36Sopenharmony_ci	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync,
115262306a36Sopenharmony_ci	.release_swfw_sync      = &ixgbe_release_swfw_sync,
115362306a36Sopenharmony_ci	.init_swfw_sync		= NULL,
115462306a36Sopenharmony_ci	.get_thermal_sensor_data = NULL,
115562306a36Sopenharmony_ci	.init_thermal_sensor_thresh = NULL,
115662306a36Sopenharmony_ci	.prot_autoc_read	= &prot_autoc_read_generic,
115762306a36Sopenharmony_ci	.prot_autoc_write	= &prot_autoc_write_generic,
115862306a36Sopenharmony_ci	.enable_rx		= &ixgbe_enable_rx_generic,
115962306a36Sopenharmony_ci	.disable_rx		= &ixgbe_disable_rx_generic,
116062306a36Sopenharmony_ci};
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_cistatic const struct ixgbe_eeprom_operations eeprom_ops_82598 = {
116362306a36Sopenharmony_ci	.init_params		= &ixgbe_init_eeprom_params_generic,
116462306a36Sopenharmony_ci	.read			= &ixgbe_read_eerd_generic,
116562306a36Sopenharmony_ci	.write			= &ixgbe_write_eeprom_generic,
116662306a36Sopenharmony_ci	.write_buffer		= &ixgbe_write_eeprom_buffer_bit_bang_generic,
116762306a36Sopenharmony_ci	.read_buffer		= &ixgbe_read_eerd_buffer_generic,
116862306a36Sopenharmony_ci	.calc_checksum          = &ixgbe_calc_eeprom_checksum_generic,
116962306a36Sopenharmony_ci	.validate_checksum	= &ixgbe_validate_eeprom_checksum_generic,
117062306a36Sopenharmony_ci	.update_checksum	= &ixgbe_update_eeprom_checksum_generic,
117162306a36Sopenharmony_ci};
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_82598 = {
117462306a36Sopenharmony_ci	.identify		= &ixgbe_identify_phy_generic,
117562306a36Sopenharmony_ci	.identify_sfp		= &ixgbe_identify_module_generic,
117662306a36Sopenharmony_ci	.init			= &ixgbe_init_phy_ops_82598,
117762306a36Sopenharmony_ci	.reset			= &ixgbe_reset_phy_generic,
117862306a36Sopenharmony_ci	.read_reg		= &ixgbe_read_phy_reg_generic,
117962306a36Sopenharmony_ci	.write_reg		= &ixgbe_write_phy_reg_generic,
118062306a36Sopenharmony_ci	.read_reg_mdi		= &ixgbe_read_phy_reg_mdi,
118162306a36Sopenharmony_ci	.write_reg_mdi		= &ixgbe_write_phy_reg_mdi,
118262306a36Sopenharmony_ci	.setup_link		= &ixgbe_setup_phy_link_generic,
118362306a36Sopenharmony_ci	.setup_link_speed	= &ixgbe_setup_phy_link_speed_generic,
118462306a36Sopenharmony_ci	.read_i2c_sff8472	= &ixgbe_read_i2c_sff8472_82598,
118562306a36Sopenharmony_ci	.read_i2c_eeprom	= &ixgbe_read_i2c_eeprom_82598,
118662306a36Sopenharmony_ci	.check_overtemp		= &ixgbe_tn_check_overtemp,
118762306a36Sopenharmony_ci};
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_82598_info = {
119062306a36Sopenharmony_ci	.mac			= ixgbe_mac_82598EB,
119162306a36Sopenharmony_ci	.get_invariants		= &ixgbe_get_invariants_82598,
119262306a36Sopenharmony_ci	.mac_ops		= &mac_ops_82598,
119362306a36Sopenharmony_ci	.eeprom_ops		= &eeprom_ops_82598,
119462306a36Sopenharmony_ci	.phy_ops		= &phy_ops_82598,
119562306a36Sopenharmony_ci	.mvals			= ixgbe_mvals_8259X,
119662306a36Sopenharmony_ci};
1197