162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "ixgbe_x540.h"
562306a36Sopenharmony_ci#include "ixgbe_type.h"
662306a36Sopenharmony_ci#include "ixgbe_common.h"
762306a36Sopenharmony_ci#include "ixgbe_phy.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistatic s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed);
1062306a36Sopenharmony_cistatic s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *);
1162306a36Sopenharmony_cistatic void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *);
1262306a36Sopenharmony_cistatic void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *);
1362306a36Sopenharmony_cistatic s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *);
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
1862306a36Sopenharmony_ci	struct ixgbe_phy_info *phy = &hw->phy;
1962306a36Sopenharmony_ci	struct ixgbe_link_info *link = &hw->link;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	/* Start with X540 invariants, since so simular */
2262306a36Sopenharmony_ci	ixgbe_get_invariants_X540(hw);
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
2562306a36Sopenharmony_ci		phy->ops.set_phy_power = NULL;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	link->addr = IXGBE_CS4227;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	return 0;
3062306a36Sopenharmony_ci}
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_x_fw(struct ixgbe_hw *hw)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	struct ixgbe_phy_info *phy = &hw->phy;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	/* Start with X540 invariants, since so similar */
3762306a36Sopenharmony_ci	ixgbe_get_invariants_X540(hw);
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	phy->ops.set_phy_power = NULL;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	return 0;
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
4762306a36Sopenharmony_ci	struct ixgbe_phy_info *phy = &hw->phy;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	/* Start with X540 invariants, since so simular */
5062306a36Sopenharmony_ci	ixgbe_get_invariants_X540(hw);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
5362306a36Sopenharmony_ci		phy->ops.set_phy_power = NULL;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	return 0;
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_a_fw(struct ixgbe_hw *hw)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	struct ixgbe_phy_info *phy = &hw->phy;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	/* Start with X540 invariants, since so similar */
6362306a36Sopenharmony_ci	ixgbe_get_invariants_X540(hw);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	phy->ops.set_phy_power = NULL;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	return 0;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control
7162306a36Sopenharmony_ci *  @hw: pointer to hardware structure
7262306a36Sopenharmony_ci **/
7362306a36Sopenharmony_cistatic void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	if (hw->bus.lan_id) {
7862306a36Sopenharmony_ci		esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
7962306a36Sopenharmony_ci		esdp |= IXGBE_ESDP_SDP1_DIR;
8062306a36Sopenharmony_ci	}
8162306a36Sopenharmony_ci	esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
8262306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
8362306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/**
8762306a36Sopenharmony_ci * ixgbe_read_cs4227 - Read CS4227 register
8862306a36Sopenharmony_ci * @hw: pointer to hardware structure
8962306a36Sopenharmony_ci * @reg: register number to write
9062306a36Sopenharmony_ci * @value: pointer to receive value read
9162306a36Sopenharmony_ci *
9262306a36Sopenharmony_ci * Returns status code
9362306a36Sopenharmony_ci */
9462306a36Sopenharmony_cistatic s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci/**
10062306a36Sopenharmony_ci * ixgbe_write_cs4227 - Write CS4227 register
10162306a36Sopenharmony_ci * @hw: pointer to hardware structure
10262306a36Sopenharmony_ci * @reg: register number to write
10362306a36Sopenharmony_ci * @value: value to write to register
10462306a36Sopenharmony_ci *
10562306a36Sopenharmony_ci * Returns status code
10662306a36Sopenharmony_ci */
10762306a36Sopenharmony_cistatic s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/**
11362306a36Sopenharmony_ci * ixgbe_read_pe - Read register from port expander
11462306a36Sopenharmony_ci * @hw: pointer to hardware structure
11562306a36Sopenharmony_ci * @reg: register number to read
11662306a36Sopenharmony_ci * @value: pointer to receive read value
11762306a36Sopenharmony_ci *
11862306a36Sopenharmony_ci * Returns status code
11962306a36Sopenharmony_ci */
12062306a36Sopenharmony_cistatic s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	s32 status;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, value);
12562306a36Sopenharmony_ci	if (status)
12662306a36Sopenharmony_ci		hw_err(hw, "port expander access failed with %d\n", status);
12762306a36Sopenharmony_ci	return status;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci/**
13162306a36Sopenharmony_ci * ixgbe_write_pe - Write register to port expander
13262306a36Sopenharmony_ci * @hw: pointer to hardware structure
13362306a36Sopenharmony_ci * @reg: register number to write
13462306a36Sopenharmony_ci * @value: value to write
13562306a36Sopenharmony_ci *
13662306a36Sopenharmony_ci * Returns status code
13762306a36Sopenharmony_ci */
13862306a36Sopenharmony_cistatic s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	s32 status;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE,
14362306a36Sopenharmony_ci						       value);
14462306a36Sopenharmony_ci	if (status)
14562306a36Sopenharmony_ci		hw_err(hw, "port expander access failed with %d\n", status);
14662306a36Sopenharmony_ci	return status;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci/**
15062306a36Sopenharmony_ci * ixgbe_reset_cs4227 - Reset CS4227 using port expander
15162306a36Sopenharmony_ci * @hw: pointer to hardware structure
15262306a36Sopenharmony_ci *
15362306a36Sopenharmony_ci * This function assumes that the caller has acquired the proper semaphore.
15462306a36Sopenharmony_ci * Returns error code
15562306a36Sopenharmony_ci */
15662306a36Sopenharmony_cistatic s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	s32 status;
15962306a36Sopenharmony_ci	u32 retry;
16062306a36Sopenharmony_ci	u16 value;
16162306a36Sopenharmony_ci	u8 reg;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	/* Trigger hard reset. */
16462306a36Sopenharmony_ci	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
16562306a36Sopenharmony_ci	if (status)
16662306a36Sopenharmony_ci		return status;
16762306a36Sopenharmony_ci	reg |= IXGBE_PE_BIT1;
16862306a36Sopenharmony_ci	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
16962306a36Sopenharmony_ci	if (status)
17062306a36Sopenharmony_ci		return status;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, &reg);
17362306a36Sopenharmony_ci	if (status)
17462306a36Sopenharmony_ci		return status;
17562306a36Sopenharmony_ci	reg &= ~IXGBE_PE_BIT1;
17662306a36Sopenharmony_ci	status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg);
17762306a36Sopenharmony_ci	if (status)
17862306a36Sopenharmony_ci		return status;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
18162306a36Sopenharmony_ci	if (status)
18262306a36Sopenharmony_ci		return status;
18362306a36Sopenharmony_ci	reg &= ~IXGBE_PE_BIT1;
18462306a36Sopenharmony_ci	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
18562306a36Sopenharmony_ci	if (status)
18662306a36Sopenharmony_ci		return status;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
19162306a36Sopenharmony_ci	if (status)
19262306a36Sopenharmony_ci		return status;
19362306a36Sopenharmony_ci	reg |= IXGBE_PE_BIT1;
19462306a36Sopenharmony_ci	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
19562306a36Sopenharmony_ci	if (status)
19662306a36Sopenharmony_ci		return status;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	/* Wait for the reset to complete. */
19962306a36Sopenharmony_ci	msleep(IXGBE_CS4227_RESET_DELAY);
20062306a36Sopenharmony_ci	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
20162306a36Sopenharmony_ci		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
20262306a36Sopenharmony_ci					   &value);
20362306a36Sopenharmony_ci		if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK)
20462306a36Sopenharmony_ci			break;
20562306a36Sopenharmony_ci		msleep(IXGBE_CS4227_CHECK_DELAY);
20662306a36Sopenharmony_ci	}
20762306a36Sopenharmony_ci	if (retry == IXGBE_CS4227_RETRIES) {
20862306a36Sopenharmony_ci		hw_err(hw, "CS4227 reset did not complete\n");
20962306a36Sopenharmony_ci		return -EIO;
21062306a36Sopenharmony_ci	}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
21362306a36Sopenharmony_ci	if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
21462306a36Sopenharmony_ci		hw_err(hw, "CS4227 EEPROM did not load successfully\n");
21562306a36Sopenharmony_ci		return -EIO;
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	return 0;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci/**
22262306a36Sopenharmony_ci * ixgbe_check_cs4227 - Check CS4227 and reset as needed
22362306a36Sopenharmony_ci * @hw: pointer to hardware structure
22462306a36Sopenharmony_ci */
22562306a36Sopenharmony_cistatic void ixgbe_check_cs4227(struct ixgbe_hw *hw)
22662306a36Sopenharmony_ci{
22762306a36Sopenharmony_ci	u32 swfw_mask = hw->phy.phy_semaphore_mask;
22862306a36Sopenharmony_ci	s32 status;
22962306a36Sopenharmony_ci	u16 value;
23062306a36Sopenharmony_ci	u8 retry;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
23362306a36Sopenharmony_ci		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
23462306a36Sopenharmony_ci		if (status) {
23562306a36Sopenharmony_ci			hw_err(hw, "semaphore failed with %d\n", status);
23662306a36Sopenharmony_ci			msleep(IXGBE_CS4227_CHECK_DELAY);
23762306a36Sopenharmony_ci			continue;
23862306a36Sopenharmony_ci		}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci		/* Get status of reset flow. */
24162306a36Sopenharmony_ci		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
24262306a36Sopenharmony_ci		if (!status && value == IXGBE_CS4227_RESET_COMPLETE)
24362306a36Sopenharmony_ci			goto out;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci		if (status || value != IXGBE_CS4227_RESET_PENDING)
24662306a36Sopenharmony_ci			break;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci		/* Reset is pending. Wait and check again. */
24962306a36Sopenharmony_ci		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
25062306a36Sopenharmony_ci		msleep(IXGBE_CS4227_CHECK_DELAY);
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci	/* If still pending, assume other instance failed. */
25362306a36Sopenharmony_ci	if (retry == IXGBE_CS4227_RETRIES) {
25462306a36Sopenharmony_ci		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
25562306a36Sopenharmony_ci		if (status) {
25662306a36Sopenharmony_ci			hw_err(hw, "semaphore failed with %d\n", status);
25762306a36Sopenharmony_ci			return;
25862306a36Sopenharmony_ci		}
25962306a36Sopenharmony_ci	}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	/* Reset the CS4227. */
26262306a36Sopenharmony_ci	status = ixgbe_reset_cs4227(hw);
26362306a36Sopenharmony_ci	if (status) {
26462306a36Sopenharmony_ci		hw_err(hw, "CS4227 reset failed: %d", status);
26562306a36Sopenharmony_ci		goto out;
26662306a36Sopenharmony_ci	}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	/* Reset takes so long, temporarily release semaphore in case the
26962306a36Sopenharmony_ci	 * other driver instance is waiting for the reset indication.
27062306a36Sopenharmony_ci	 */
27162306a36Sopenharmony_ci	ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
27262306a36Sopenharmony_ci			   IXGBE_CS4227_RESET_PENDING);
27362306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
27462306a36Sopenharmony_ci	usleep_range(10000, 12000);
27562306a36Sopenharmony_ci	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
27662306a36Sopenharmony_ci	if (status) {
27762306a36Sopenharmony_ci		hw_err(hw, "semaphore failed with %d", status);
27862306a36Sopenharmony_ci		return;
27962306a36Sopenharmony_ci	}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	/* Record completion for next time. */
28262306a36Sopenharmony_ci	status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
28362306a36Sopenharmony_ci				    IXGBE_CS4227_RESET_COMPLETE);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ciout:
28662306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
28762306a36Sopenharmony_ci	msleep(hw->eeprom.semaphore_delay);
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci/** ixgbe_identify_phy_x550em - Get PHY type based on device id
29162306a36Sopenharmony_ci *  @hw: pointer to hardware structure
29262306a36Sopenharmony_ci *
29362306a36Sopenharmony_ci *  Returns error code
29462306a36Sopenharmony_ci */
29562306a36Sopenharmony_cistatic s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	switch (hw->device_id) {
29862306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_SFP:
29962306a36Sopenharmony_ci		if (hw->bus.lan_id)
30062306a36Sopenharmony_ci			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
30162306a36Sopenharmony_ci		else
30262306a36Sopenharmony_ci			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
30362306a36Sopenharmony_ci		return ixgbe_identify_module_generic(hw);
30462306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_SFP:
30562306a36Sopenharmony_ci		/* set up for CS4227 usage */
30662306a36Sopenharmony_ci		hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
30762306a36Sopenharmony_ci		ixgbe_setup_mux_ctl(hw);
30862306a36Sopenharmony_ci		ixgbe_check_cs4227(hw);
30962306a36Sopenharmony_ci		fallthrough;
31062306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_SFP_N:
31162306a36Sopenharmony_ci		return ixgbe_identify_module_generic(hw);
31262306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_KX4:
31362306a36Sopenharmony_ci		hw->phy.type = ixgbe_phy_x550em_kx4;
31462306a36Sopenharmony_ci		break;
31562306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_XFI:
31662306a36Sopenharmony_ci		hw->phy.type = ixgbe_phy_x550em_xfi;
31762306a36Sopenharmony_ci		break;
31862306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_KR:
31962306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_KR:
32062306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_KR_L:
32162306a36Sopenharmony_ci		hw->phy.type = ixgbe_phy_x550em_kr;
32262306a36Sopenharmony_ci		break;
32362306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_10G_T:
32462306a36Sopenharmony_ci		if (hw->bus.lan_id)
32562306a36Sopenharmony_ci			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
32662306a36Sopenharmony_ci		else
32762306a36Sopenharmony_ci			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
32862306a36Sopenharmony_ci		fallthrough;
32962306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_10G_T:
33062306a36Sopenharmony_ci		return ixgbe_identify_phy_generic(hw);
33162306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_1G_T:
33262306a36Sopenharmony_ci		hw->phy.type = ixgbe_phy_ext_1g_t;
33362306a36Sopenharmony_ci		break;
33462306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_1G_T:
33562306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
33662306a36Sopenharmony_ci		hw->phy.type = ixgbe_phy_fw;
33762306a36Sopenharmony_ci		hw->phy.ops.read_reg = NULL;
33862306a36Sopenharmony_ci		hw->phy.ops.write_reg = NULL;
33962306a36Sopenharmony_ci		if (hw->bus.lan_id)
34062306a36Sopenharmony_ci			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
34162306a36Sopenharmony_ci		else
34262306a36Sopenharmony_ci			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
34362306a36Sopenharmony_ci		break;
34462306a36Sopenharmony_ci	default:
34562306a36Sopenharmony_ci		break;
34662306a36Sopenharmony_ci	}
34762306a36Sopenharmony_ci	return 0;
34862306a36Sopenharmony_ci}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_cistatic s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
35162306a36Sopenharmony_ci				     u32 device_type, u16 *phy_data)
35262306a36Sopenharmony_ci{
35362306a36Sopenharmony_ci	return -EOPNOTSUPP;
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_cistatic s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
35762306a36Sopenharmony_ci				      u32 device_type, u16 phy_data)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	return -EOPNOTSUPP;
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci/**
36362306a36Sopenharmony_ci * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
36462306a36Sopenharmony_ci * @hw: pointer to the hardware structure
36562306a36Sopenharmony_ci * @addr: I2C bus address to read from
36662306a36Sopenharmony_ci * @reg: I2C device register to read from
36762306a36Sopenharmony_ci * @val: pointer to location to receive read value
36862306a36Sopenharmony_ci *
36962306a36Sopenharmony_ci * Returns an error code on error.
37062306a36Sopenharmony_ci **/
37162306a36Sopenharmony_cistatic s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
37262306a36Sopenharmony_ci					   u16 reg, u16 *val)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true);
37562306a36Sopenharmony_ci}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci/**
37862306a36Sopenharmony_ci * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
37962306a36Sopenharmony_ci * @hw: pointer to the hardware structure
38062306a36Sopenharmony_ci * @addr: I2C bus address to read from
38162306a36Sopenharmony_ci * @reg: I2C device register to read from
38262306a36Sopenharmony_ci * @val: pointer to location to receive read value
38362306a36Sopenharmony_ci *
38462306a36Sopenharmony_ci * Returns an error code on error.
38562306a36Sopenharmony_ci **/
38662306a36Sopenharmony_cistatic s32
38762306a36Sopenharmony_ciixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
38862306a36Sopenharmony_ci					 u16 reg, u16 *val)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false);
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci/**
39462306a36Sopenharmony_ci * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
39562306a36Sopenharmony_ci * @hw: pointer to the hardware structure
39662306a36Sopenharmony_ci * @addr: I2C bus address to write to
39762306a36Sopenharmony_ci * @reg: I2C device register to write to
39862306a36Sopenharmony_ci * @val: value to write
39962306a36Sopenharmony_ci *
40062306a36Sopenharmony_ci * Returns an error code on error.
40162306a36Sopenharmony_ci **/
40262306a36Sopenharmony_cistatic s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
40362306a36Sopenharmony_ci					    u8 addr, u16 reg, u16 val)
40462306a36Sopenharmony_ci{
40562306a36Sopenharmony_ci	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci/**
40962306a36Sopenharmony_ci * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
41062306a36Sopenharmony_ci * @hw: pointer to the hardware structure
41162306a36Sopenharmony_ci * @addr: I2C bus address to write to
41262306a36Sopenharmony_ci * @reg: I2C device register to write to
41362306a36Sopenharmony_ci * @val: value to write
41462306a36Sopenharmony_ci *
41562306a36Sopenharmony_ci * Returns an error code on error.
41662306a36Sopenharmony_ci **/
41762306a36Sopenharmony_cistatic s32
41862306a36Sopenharmony_ciixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
41962306a36Sopenharmony_ci					  u8 addr, u16 reg, u16 val)
42062306a36Sopenharmony_ci{
42162306a36Sopenharmony_ci	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false);
42262306a36Sopenharmony_ci}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci/**
42562306a36Sopenharmony_ci * ixgbe_fw_phy_activity - Perform an activity on a PHY
42662306a36Sopenharmony_ci * @hw: pointer to hardware structure
42762306a36Sopenharmony_ci * @activity: activity to perform
42862306a36Sopenharmony_ci * @data: Pointer to 4 32-bit words of data
42962306a36Sopenharmony_ci */
43062306a36Sopenharmony_cis32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity,
43162306a36Sopenharmony_ci			  u32 (*data)[FW_PHY_ACT_DATA_COUNT])
43262306a36Sopenharmony_ci{
43362306a36Sopenharmony_ci	union {
43462306a36Sopenharmony_ci		struct ixgbe_hic_phy_activity_req cmd;
43562306a36Sopenharmony_ci		struct ixgbe_hic_phy_activity_resp rsp;
43662306a36Sopenharmony_ci	} hic;
43762306a36Sopenharmony_ci	u16 retries = FW_PHY_ACT_RETRIES;
43862306a36Sopenharmony_ci	s32 rc;
43962306a36Sopenharmony_ci	u32 i;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	do {
44262306a36Sopenharmony_ci		memset(&hic, 0, sizeof(hic));
44362306a36Sopenharmony_ci		hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD;
44462306a36Sopenharmony_ci		hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN;
44562306a36Sopenharmony_ci		hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
44662306a36Sopenharmony_ci		hic.cmd.port_number = hw->bus.lan_id;
44762306a36Sopenharmony_ci		hic.cmd.activity_id = cpu_to_le16(activity);
44862306a36Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(hic.cmd.data); ++i)
44962306a36Sopenharmony_ci			hic.cmd.data[i] = cpu_to_be32((*data)[i]);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci		rc = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd),
45262306a36Sopenharmony_ci						  IXGBE_HI_COMMAND_TIMEOUT,
45362306a36Sopenharmony_ci						  true);
45462306a36Sopenharmony_ci		if (rc)
45562306a36Sopenharmony_ci			return rc;
45662306a36Sopenharmony_ci		if (hic.rsp.hdr.cmd_or_resp.ret_status ==
45762306a36Sopenharmony_ci		    FW_CEM_RESP_STATUS_SUCCESS) {
45862306a36Sopenharmony_ci			for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
45962306a36Sopenharmony_ci				(*data)[i] = be32_to_cpu(hic.rsp.data[i]);
46062306a36Sopenharmony_ci			return 0;
46162306a36Sopenharmony_ci		}
46262306a36Sopenharmony_ci		usleep_range(20, 30);
46362306a36Sopenharmony_ci		--retries;
46462306a36Sopenharmony_ci	} while (retries > 0);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	return -EIO;
46762306a36Sopenharmony_ci}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_cistatic const struct {
47062306a36Sopenharmony_ci	u16 fw_speed;
47162306a36Sopenharmony_ci	ixgbe_link_speed phy_speed;
47262306a36Sopenharmony_ci} ixgbe_fw_map[] = {
47362306a36Sopenharmony_ci	{ FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL },
47462306a36Sopenharmony_ci	{ FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL },
47562306a36Sopenharmony_ci	{ FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL },
47662306a36Sopenharmony_ci	{ FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL },
47762306a36Sopenharmony_ci	{ FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL },
47862306a36Sopenharmony_ci	{ FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL },
47962306a36Sopenharmony_ci};
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci/**
48262306a36Sopenharmony_ci * ixgbe_get_phy_id_fw - Get the phy ID via firmware command
48362306a36Sopenharmony_ci * @hw: pointer to hardware structure
48462306a36Sopenharmony_ci *
48562306a36Sopenharmony_ci * Returns error code
48662306a36Sopenharmony_ci */
48762306a36Sopenharmony_cistatic s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw)
48862306a36Sopenharmony_ci{
48962306a36Sopenharmony_ci	u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
49062306a36Sopenharmony_ci	u16 phy_speeds;
49162306a36Sopenharmony_ci	u16 phy_id_lo;
49262306a36Sopenharmony_ci	s32 rc;
49362306a36Sopenharmony_ci	u16 i;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	if (hw->phy.id)
49662306a36Sopenharmony_ci		return 0;
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info);
49962306a36Sopenharmony_ci	if (rc)
50062306a36Sopenharmony_ci		return rc;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	hw->phy.speeds_supported = 0;
50362306a36Sopenharmony_ci	phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK;
50462306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) {
50562306a36Sopenharmony_ci		if (phy_speeds & ixgbe_fw_map[i].fw_speed)
50662306a36Sopenharmony_ci			hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed;
50762306a36Sopenharmony_ci	}
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK;
51062306a36Sopenharmony_ci	phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK;
51162306a36Sopenharmony_ci	hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK;
51262306a36Sopenharmony_ci	hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK;
51362306a36Sopenharmony_ci	if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK)
51462306a36Sopenharmony_ci		return -EFAULT;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	hw->phy.autoneg_advertised = hw->phy.speeds_supported;
51762306a36Sopenharmony_ci	hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL |
51862306a36Sopenharmony_ci				       IXGBE_LINK_SPEED_1GB_FULL;
51962306a36Sopenharmony_ci	hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
52062306a36Sopenharmony_ci	return 0;
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci/**
52462306a36Sopenharmony_ci * ixgbe_identify_phy_fw - Get PHY type based on firmware command
52562306a36Sopenharmony_ci * @hw: pointer to hardware structure
52662306a36Sopenharmony_ci *
52762306a36Sopenharmony_ci * Returns error code
52862306a36Sopenharmony_ci */
52962306a36Sopenharmony_cistatic s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	if (hw->bus.lan_id)
53262306a36Sopenharmony_ci		hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
53362306a36Sopenharmony_ci	else
53462306a36Sopenharmony_ci		hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	hw->phy.type = ixgbe_phy_fw;
53762306a36Sopenharmony_ci	hw->phy.ops.read_reg = NULL;
53862306a36Sopenharmony_ci	hw->phy.ops.write_reg = NULL;
53962306a36Sopenharmony_ci	return ixgbe_get_phy_id_fw(hw);
54062306a36Sopenharmony_ci}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci/**
54362306a36Sopenharmony_ci * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY
54462306a36Sopenharmony_ci * @hw: pointer to hardware structure
54562306a36Sopenharmony_ci *
54662306a36Sopenharmony_ci * Returns error code
54762306a36Sopenharmony_ci */
54862306a36Sopenharmony_cistatic s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw)
54962306a36Sopenharmony_ci{
55062306a36Sopenharmony_ci	u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF;
55362306a36Sopenharmony_ci	return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup);
55462306a36Sopenharmony_ci}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci/**
55762306a36Sopenharmony_ci * ixgbe_setup_fw_link - Setup firmware-controlled PHYs
55862306a36Sopenharmony_ci * @hw: pointer to hardware structure
55962306a36Sopenharmony_ci */
56062306a36Sopenharmony_cistatic s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw)
56162306a36Sopenharmony_ci{
56262306a36Sopenharmony_ci	u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
56362306a36Sopenharmony_ci	s32 rc;
56462306a36Sopenharmony_ci	u16 i;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
56762306a36Sopenharmony_ci		return 0;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
57062306a36Sopenharmony_ci		hw_err(hw, "rx_pause not valid in strict IEEE mode\n");
57162306a36Sopenharmony_ci		return -EINVAL;
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	switch (hw->fc.requested_mode) {
57562306a36Sopenharmony_ci	case ixgbe_fc_full:
57662306a36Sopenharmony_ci		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX <<
57762306a36Sopenharmony_ci			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
57862306a36Sopenharmony_ci		break;
57962306a36Sopenharmony_ci	case ixgbe_fc_rx_pause:
58062306a36Sopenharmony_ci		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX <<
58162306a36Sopenharmony_ci			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
58262306a36Sopenharmony_ci		break;
58362306a36Sopenharmony_ci	case ixgbe_fc_tx_pause:
58462306a36Sopenharmony_ci		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX <<
58562306a36Sopenharmony_ci			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
58662306a36Sopenharmony_ci		break;
58762306a36Sopenharmony_ci	default:
58862306a36Sopenharmony_ci		break;
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) {
59262306a36Sopenharmony_ci		if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed)
59362306a36Sopenharmony_ci			setup[0] |= ixgbe_fw_map[i].fw_speed;
59462306a36Sopenharmony_ci	}
59562306a36Sopenharmony_ci	setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	if (hw->phy.eee_speeds_advertised)
59862306a36Sopenharmony_ci		setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);
60162306a36Sopenharmony_ci	if (rc)
60262306a36Sopenharmony_ci		return rc;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
60562306a36Sopenharmony_ci		return -EIO;
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	return 0;
60862306a36Sopenharmony_ci}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci/**
61162306a36Sopenharmony_ci * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs
61262306a36Sopenharmony_ci * @hw: pointer to hardware structure
61362306a36Sopenharmony_ci *
61462306a36Sopenharmony_ci * Called at init time to set up flow control.
61562306a36Sopenharmony_ci */
61662306a36Sopenharmony_cistatic s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw)
61762306a36Sopenharmony_ci{
61862306a36Sopenharmony_ci	if (hw->fc.requested_mode == ixgbe_fc_default)
61962306a36Sopenharmony_ci		hw->fc.requested_mode = ixgbe_fc_full;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	return ixgbe_setup_fw_link(hw);
62262306a36Sopenharmony_ci}
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci/** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params
62562306a36Sopenharmony_ci *  @hw: pointer to hardware structure
62662306a36Sopenharmony_ci *
62762306a36Sopenharmony_ci *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
62862306a36Sopenharmony_ci *  ixgbe_hw struct in order to set up EEPROM access.
62962306a36Sopenharmony_ci **/
63062306a36Sopenharmony_cistatic s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
63162306a36Sopenharmony_ci{
63262306a36Sopenharmony_ci	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
63362306a36Sopenharmony_ci	u32 eec;
63462306a36Sopenharmony_ci	u16 eeprom_size;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	if (eeprom->type == ixgbe_eeprom_uninitialized) {
63762306a36Sopenharmony_ci		eeprom->semaphore_delay = 10;
63862306a36Sopenharmony_ci		eeprom->type = ixgbe_flash;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci		eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
64162306a36Sopenharmony_ci		eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
64262306a36Sopenharmony_ci				    IXGBE_EEC_SIZE_SHIFT);
64362306a36Sopenharmony_ci		eeprom->word_size = BIT(eeprom_size +
64462306a36Sopenharmony_ci					IXGBE_EEPROM_WORD_SIZE_SHIFT);
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci		hw_dbg(hw, "Eeprom params: type = %d, size = %d\n",
64762306a36Sopenharmony_ci		       eeprom->type, eeprom->word_size);
64862306a36Sopenharmony_ci	}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	return 0;
65162306a36Sopenharmony_ci}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci/**
65462306a36Sopenharmony_ci * ixgbe_iosf_wait - Wait for IOSF command completion
65562306a36Sopenharmony_ci * @hw: pointer to hardware structure
65662306a36Sopenharmony_ci * @ctrl: pointer to location to receive final IOSF control value
65762306a36Sopenharmony_ci *
65862306a36Sopenharmony_ci * Return: failing status on timeout
65962306a36Sopenharmony_ci *
66062306a36Sopenharmony_ci * Note: ctrl can be NULL if the IOSF control register value is not needed
66162306a36Sopenharmony_ci */
66262306a36Sopenharmony_cistatic s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl)
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	u32 i, command;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	/* Check every 10 usec to see if the address cycle completed.
66762306a36Sopenharmony_ci	 * The SB IOSF BUSY bit will clear when the operation is
66862306a36Sopenharmony_ci	 * complete.
66962306a36Sopenharmony_ci	 */
67062306a36Sopenharmony_ci	for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
67162306a36Sopenharmony_ci		command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
67262306a36Sopenharmony_ci		if (!(command & IXGBE_SB_IOSF_CTRL_BUSY))
67362306a36Sopenharmony_ci			break;
67462306a36Sopenharmony_ci		udelay(10);
67562306a36Sopenharmony_ci	}
67662306a36Sopenharmony_ci	if (ctrl)
67762306a36Sopenharmony_ci		*ctrl = command;
67862306a36Sopenharmony_ci	if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
67962306a36Sopenharmony_ci		hw_dbg(hw, "IOSF wait timed out\n");
68062306a36Sopenharmony_ci		return -EIO;
68162306a36Sopenharmony_ci	}
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	return 0;
68462306a36Sopenharmony_ci}
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci/** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the
68762306a36Sopenharmony_ci *  IOSF device
68862306a36Sopenharmony_ci *  @hw: pointer to hardware structure
68962306a36Sopenharmony_ci *  @reg_addr: 32 bit PHY register to write
69062306a36Sopenharmony_ci *  @device_type: 3 bit device type
69162306a36Sopenharmony_ci *  @phy_data: Pointer to read data from the register
69262306a36Sopenharmony_ci **/
69362306a36Sopenharmony_cistatic s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
69462306a36Sopenharmony_ci				       u32 device_type, u32 *data)
69562306a36Sopenharmony_ci{
69662306a36Sopenharmony_ci	u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
69762306a36Sopenharmony_ci	u32 command, error;
69862306a36Sopenharmony_ci	s32 ret;
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
70162306a36Sopenharmony_ci	if (ret)
70262306a36Sopenharmony_ci		return ret;
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	ret = ixgbe_iosf_wait(hw, NULL);
70562306a36Sopenharmony_ci	if (ret)
70662306a36Sopenharmony_ci		goto out;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
70962306a36Sopenharmony_ci		   (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	/* Write IOSF control register */
71262306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	ret = ixgbe_iosf_wait(hw, &command);
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
71762306a36Sopenharmony_ci		error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
71862306a36Sopenharmony_ci			 IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
71962306a36Sopenharmony_ci		hw_dbg(hw, "Failed to read, error %x\n", error);
72062306a36Sopenharmony_ci		ret = -EIO;
72162306a36Sopenharmony_ci		goto out;
72262306a36Sopenharmony_ci	}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	if (!ret)
72562306a36Sopenharmony_ci		*data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ciout:
72862306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, gssr);
72962306a36Sopenharmony_ci	return ret;
73062306a36Sopenharmony_ci}
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci/**
73362306a36Sopenharmony_ci * ixgbe_get_phy_token - Get the token for shared PHY access
73462306a36Sopenharmony_ci * @hw: Pointer to hardware structure
73562306a36Sopenharmony_ci */
73662306a36Sopenharmony_cistatic s32 ixgbe_get_phy_token(struct ixgbe_hw *hw)
73762306a36Sopenharmony_ci{
73862306a36Sopenharmony_ci	struct ixgbe_hic_phy_token_req token_cmd;
73962306a36Sopenharmony_ci	s32 status;
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
74262306a36Sopenharmony_ci	token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
74362306a36Sopenharmony_ci	token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
74462306a36Sopenharmony_ci	token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
74562306a36Sopenharmony_ci	token_cmd.port_number = hw->bus.lan_id;
74662306a36Sopenharmony_ci	token_cmd.command_type = FW_PHY_TOKEN_REQ;
74762306a36Sopenharmony_ci	token_cmd.pad = 0;
74862306a36Sopenharmony_ci	status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd),
74962306a36Sopenharmony_ci					      IXGBE_HI_COMMAND_TIMEOUT,
75062306a36Sopenharmony_ci					      true);
75162306a36Sopenharmony_ci	if (status)
75262306a36Sopenharmony_ci		return status;
75362306a36Sopenharmony_ci	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
75462306a36Sopenharmony_ci		return 0;
75562306a36Sopenharmony_ci	if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY)
75662306a36Sopenharmony_ci		return -EIO;
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	return -EAGAIN;
75962306a36Sopenharmony_ci}
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci/**
76262306a36Sopenharmony_ci * ixgbe_put_phy_token - Put the token for shared PHY access
76362306a36Sopenharmony_ci * @hw: Pointer to hardware structure
76462306a36Sopenharmony_ci */
76562306a36Sopenharmony_cistatic s32 ixgbe_put_phy_token(struct ixgbe_hw *hw)
76662306a36Sopenharmony_ci{
76762306a36Sopenharmony_ci	struct ixgbe_hic_phy_token_req token_cmd;
76862306a36Sopenharmony_ci	s32 status;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
77162306a36Sopenharmony_ci	token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
77262306a36Sopenharmony_ci	token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
77362306a36Sopenharmony_ci	token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
77462306a36Sopenharmony_ci	token_cmd.port_number = hw->bus.lan_id;
77562306a36Sopenharmony_ci	token_cmd.command_type = FW_PHY_TOKEN_REL;
77662306a36Sopenharmony_ci	token_cmd.pad = 0;
77762306a36Sopenharmony_ci	status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd),
77862306a36Sopenharmony_ci					      IXGBE_HI_COMMAND_TIMEOUT,
77962306a36Sopenharmony_ci					      true);
78062306a36Sopenharmony_ci	if (status)
78162306a36Sopenharmony_ci		return status;
78262306a36Sopenharmony_ci	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
78362306a36Sopenharmony_ci		return 0;
78462306a36Sopenharmony_ci	return -EIO;
78562306a36Sopenharmony_ci}
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci/**
78862306a36Sopenharmony_ci *  ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register
78962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
79062306a36Sopenharmony_ci *  @reg_addr: 32 bit PHY register to write
79162306a36Sopenharmony_ci *  @device_type: 3 bit device type
79262306a36Sopenharmony_ci *  @data: Data to write to the register
79362306a36Sopenharmony_ci **/
79462306a36Sopenharmony_cistatic s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
79562306a36Sopenharmony_ci					 __always_unused u32 device_type,
79662306a36Sopenharmony_ci					 u32 data)
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	struct ixgbe_hic_internal_phy_req write_cmd;
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	memset(&write_cmd, 0, sizeof(write_cmd));
80162306a36Sopenharmony_ci	write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD;
80262306a36Sopenharmony_ci	write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN;
80362306a36Sopenharmony_ci	write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
80462306a36Sopenharmony_ci	write_cmd.port_number = hw->bus.lan_id;
80562306a36Sopenharmony_ci	write_cmd.command_type = FW_INT_PHY_REQ_WRITE;
80662306a36Sopenharmony_ci	write_cmd.address = cpu_to_be16(reg_addr);
80762306a36Sopenharmony_ci	write_cmd.write_data = cpu_to_be32(data);
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd),
81062306a36Sopenharmony_ci					    IXGBE_HI_COMMAND_TIMEOUT, false);
81162306a36Sopenharmony_ci}
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci/**
81462306a36Sopenharmony_ci *  ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register
81562306a36Sopenharmony_ci *  @hw: pointer to hardware structure
81662306a36Sopenharmony_ci *  @reg_addr: 32 bit PHY register to write
81762306a36Sopenharmony_ci *  @device_type: 3 bit device type
81862306a36Sopenharmony_ci *  @data: Pointer to read data from the register
81962306a36Sopenharmony_ci **/
82062306a36Sopenharmony_cistatic s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
82162306a36Sopenharmony_ci					__always_unused u32 device_type,
82262306a36Sopenharmony_ci					u32 *data)
82362306a36Sopenharmony_ci{
82462306a36Sopenharmony_ci	union {
82562306a36Sopenharmony_ci		struct ixgbe_hic_internal_phy_req cmd;
82662306a36Sopenharmony_ci		struct ixgbe_hic_internal_phy_resp rsp;
82762306a36Sopenharmony_ci	} hic;
82862306a36Sopenharmony_ci	s32 status;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	memset(&hic, 0, sizeof(hic));
83162306a36Sopenharmony_ci	hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD;
83262306a36Sopenharmony_ci	hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN;
83362306a36Sopenharmony_ci	hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
83462306a36Sopenharmony_ci	hic.cmd.port_number = hw->bus.lan_id;
83562306a36Sopenharmony_ci	hic.cmd.command_type = FW_INT_PHY_REQ_READ;
83662306a36Sopenharmony_ci	hic.cmd.address = cpu_to_be16(reg_addr);
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd),
83962306a36Sopenharmony_ci					      IXGBE_HI_COMMAND_TIMEOUT, true);
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	/* Extract the register value from the response. */
84262306a36Sopenharmony_ci	*data = be32_to_cpu(hic.rsp.read_data);
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	return status;
84562306a36Sopenharmony_ci}
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci/** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif
84862306a36Sopenharmony_ci *  @hw: pointer to hardware structure
84962306a36Sopenharmony_ci *  @offset: offset of  word in the EEPROM to read
85062306a36Sopenharmony_ci *  @words: number of words
85162306a36Sopenharmony_ci *  @data: word(s) read from the EEPROM
85262306a36Sopenharmony_ci *
85362306a36Sopenharmony_ci *  Reads a 16 bit word(s) from the EEPROM using the hostif.
85462306a36Sopenharmony_ci **/
85562306a36Sopenharmony_cistatic s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
85662306a36Sopenharmony_ci					    u16 offset, u16 words, u16 *data)
85762306a36Sopenharmony_ci{
85862306a36Sopenharmony_ci	const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
85962306a36Sopenharmony_ci	struct ixgbe_hic_read_shadow_ram buffer;
86062306a36Sopenharmony_ci	u32 current_word = 0;
86162306a36Sopenharmony_ci	u16 words_to_read;
86262306a36Sopenharmony_ci	s32 status;
86362306a36Sopenharmony_ci	u32 i;
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	/* Take semaphore for the entire operation. */
86662306a36Sopenharmony_ci	status = hw->mac.ops.acquire_swfw_sync(hw, mask);
86762306a36Sopenharmony_ci	if (status) {
86862306a36Sopenharmony_ci		hw_dbg(hw, "EEPROM read buffer - semaphore failed\n");
86962306a36Sopenharmony_ci		return status;
87062306a36Sopenharmony_ci	}
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	while (words) {
87362306a36Sopenharmony_ci		if (words > FW_MAX_READ_BUFFER_SIZE / 2)
87462306a36Sopenharmony_ci			words_to_read = FW_MAX_READ_BUFFER_SIZE / 2;
87562306a36Sopenharmony_ci		else
87662306a36Sopenharmony_ci			words_to_read = words;
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci		buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
87962306a36Sopenharmony_ci		buffer.hdr.req.buf_lenh = 0;
88062306a36Sopenharmony_ci		buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
88162306a36Sopenharmony_ci		buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci		/* convert offset from words to bytes */
88462306a36Sopenharmony_ci		buffer.address = (__force u32)cpu_to_be32((offset +
88562306a36Sopenharmony_ci							   current_word) * 2);
88662306a36Sopenharmony_ci		buffer.length = (__force u16)cpu_to_be16(words_to_read * 2);
88762306a36Sopenharmony_ci		buffer.pad2 = 0;
88862306a36Sopenharmony_ci		buffer.pad3 = 0;
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci		status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
89162306a36Sopenharmony_ci					    IXGBE_HI_COMMAND_TIMEOUT);
89262306a36Sopenharmony_ci		if (status) {
89362306a36Sopenharmony_ci			hw_dbg(hw, "Host interface command failed\n");
89462306a36Sopenharmony_ci			goto out;
89562306a36Sopenharmony_ci		}
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci		for (i = 0; i < words_to_read; i++) {
89862306a36Sopenharmony_ci			u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) +
89962306a36Sopenharmony_ci				  2 * i;
90062306a36Sopenharmony_ci			u32 value = IXGBE_READ_REG(hw, reg);
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci			data[current_word] = (u16)(value & 0xffff);
90362306a36Sopenharmony_ci			current_word++;
90462306a36Sopenharmony_ci			i++;
90562306a36Sopenharmony_ci			if (i < words_to_read) {
90662306a36Sopenharmony_ci				value >>= 16;
90762306a36Sopenharmony_ci				data[current_word] = (u16)(value & 0xffff);
90862306a36Sopenharmony_ci				current_word++;
90962306a36Sopenharmony_ci			}
91062306a36Sopenharmony_ci		}
91162306a36Sopenharmony_ci		words -= words_to_read;
91262306a36Sopenharmony_ci	}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ciout:
91562306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, mask);
91662306a36Sopenharmony_ci	return status;
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci/** ixgbe_checksum_ptr_x550 - Checksum one pointer region
92062306a36Sopenharmony_ci *  @hw: pointer to hardware structure
92162306a36Sopenharmony_ci *  @ptr: pointer offset in eeprom
92262306a36Sopenharmony_ci *  @size: size of section pointed by ptr, if 0 first word will be used as size
92362306a36Sopenharmony_ci *  @csum: address of checksum to update
92462306a36Sopenharmony_ci *
92562306a36Sopenharmony_ci *  Returns error status for any failure
92662306a36Sopenharmony_ci **/
92762306a36Sopenharmony_cistatic s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
92862306a36Sopenharmony_ci				   u16 size, u16 *csum, u16 *buffer,
92962306a36Sopenharmony_ci				   u32 buffer_size)
93062306a36Sopenharmony_ci{
93162306a36Sopenharmony_ci	u16 buf[256];
93262306a36Sopenharmony_ci	s32 status;
93362306a36Sopenharmony_ci	u16 length, bufsz, i, start;
93462306a36Sopenharmony_ci	u16 *local_buffer;
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	bufsz = ARRAY_SIZE(buf);
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	/* Read a chunk at the pointer location */
93962306a36Sopenharmony_ci	if (!buffer) {
94062306a36Sopenharmony_ci		status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf);
94162306a36Sopenharmony_ci		if (status) {
94262306a36Sopenharmony_ci			hw_dbg(hw, "Failed to read EEPROM image\n");
94362306a36Sopenharmony_ci			return status;
94462306a36Sopenharmony_ci		}
94562306a36Sopenharmony_ci		local_buffer = buf;
94662306a36Sopenharmony_ci	} else {
94762306a36Sopenharmony_ci		if (buffer_size < ptr)
94862306a36Sopenharmony_ci			return  -EINVAL;
94962306a36Sopenharmony_ci		local_buffer = &buffer[ptr];
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	if (size) {
95362306a36Sopenharmony_ci		start = 0;
95462306a36Sopenharmony_ci		length = size;
95562306a36Sopenharmony_ci	} else {
95662306a36Sopenharmony_ci		start = 1;
95762306a36Sopenharmony_ci		length = local_buffer[0];
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci		/* Skip pointer section if length is invalid. */
96062306a36Sopenharmony_ci		if (length == 0xFFFF || length == 0 ||
96162306a36Sopenharmony_ci		    (ptr + length) >= hw->eeprom.word_size)
96262306a36Sopenharmony_ci			return 0;
96362306a36Sopenharmony_ci	}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	if (buffer && ((u32)start + (u32)length > buffer_size))
96662306a36Sopenharmony_ci		return -EINVAL;
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	for (i = start; length; i++, length--) {
96962306a36Sopenharmony_ci		if (i == bufsz && !buffer) {
97062306a36Sopenharmony_ci			ptr += bufsz;
97162306a36Sopenharmony_ci			i = 0;
97262306a36Sopenharmony_ci			if (length < bufsz)
97362306a36Sopenharmony_ci				bufsz = length;
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci			/* Read a chunk at the pointer location */
97662306a36Sopenharmony_ci			status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr,
97762306a36Sopenharmony_ci								  bufsz, buf);
97862306a36Sopenharmony_ci			if (status) {
97962306a36Sopenharmony_ci				hw_dbg(hw, "Failed to read EEPROM image\n");
98062306a36Sopenharmony_ci				return status;
98162306a36Sopenharmony_ci			}
98262306a36Sopenharmony_ci		}
98362306a36Sopenharmony_ci		*csum += local_buffer[i];
98462306a36Sopenharmony_ci	}
98562306a36Sopenharmony_ci	return 0;
98662306a36Sopenharmony_ci}
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci/** ixgbe_calc_checksum_X550 - Calculates and returns the checksum
98962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
99062306a36Sopenharmony_ci *  @buffer: pointer to buffer containing calculated checksum
99162306a36Sopenharmony_ci *  @buffer_size: size of buffer
99262306a36Sopenharmony_ci *
99362306a36Sopenharmony_ci *  Returns a negative error code on error, or the 16-bit checksum
99462306a36Sopenharmony_ci **/
99562306a36Sopenharmony_cistatic s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer,
99662306a36Sopenharmony_ci				    u32 buffer_size)
99762306a36Sopenharmony_ci{
99862306a36Sopenharmony_ci	u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1];
99962306a36Sopenharmony_ci	u16 *local_buffer;
100062306a36Sopenharmony_ci	s32 status;
100162306a36Sopenharmony_ci	u16 checksum = 0;
100262306a36Sopenharmony_ci	u16 pointer, i, size;
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	hw->eeprom.ops.init_params(hw);
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	if (!buffer) {
100762306a36Sopenharmony_ci		/* Read pointer area */
100862306a36Sopenharmony_ci		status = ixgbe_read_ee_hostif_buffer_X550(hw, 0,
100962306a36Sopenharmony_ci						IXGBE_EEPROM_LAST_WORD + 1,
101062306a36Sopenharmony_ci						eeprom_ptrs);
101162306a36Sopenharmony_ci		if (status) {
101262306a36Sopenharmony_ci			hw_dbg(hw, "Failed to read EEPROM image\n");
101362306a36Sopenharmony_ci			return status;
101462306a36Sopenharmony_ci		}
101562306a36Sopenharmony_ci		local_buffer = eeprom_ptrs;
101662306a36Sopenharmony_ci	} else {
101762306a36Sopenharmony_ci		if (buffer_size < IXGBE_EEPROM_LAST_WORD)
101862306a36Sopenharmony_ci			return -EINVAL;
101962306a36Sopenharmony_ci		local_buffer = buffer;
102062306a36Sopenharmony_ci	}
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	/* For X550 hardware include 0x0-0x41 in the checksum, skip the
102362306a36Sopenharmony_ci	 * checksum word itself
102462306a36Sopenharmony_ci	 */
102562306a36Sopenharmony_ci	for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++)
102662306a36Sopenharmony_ci		if (i != IXGBE_EEPROM_CHECKSUM)
102762306a36Sopenharmony_ci			checksum += local_buffer[i];
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	/* Include all data from pointers 0x3, 0x6-0xE.  This excludes the
103062306a36Sopenharmony_ci	 * FW, PHY module, and PCIe Expansion/Option ROM pointers.
103162306a36Sopenharmony_ci	 */
103262306a36Sopenharmony_ci	for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) {
103362306a36Sopenharmony_ci		if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
103462306a36Sopenharmony_ci			continue;
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci		pointer = local_buffer[i];
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci		/* Skip pointer section if the pointer is invalid. */
103962306a36Sopenharmony_ci		if (pointer == 0xFFFF || pointer == 0 ||
104062306a36Sopenharmony_ci		    pointer >= hw->eeprom.word_size)
104162306a36Sopenharmony_ci			continue;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci		switch (i) {
104462306a36Sopenharmony_ci		case IXGBE_PCIE_GENERAL_PTR:
104562306a36Sopenharmony_ci			size = IXGBE_IXGBE_PCIE_GENERAL_SIZE;
104662306a36Sopenharmony_ci			break;
104762306a36Sopenharmony_ci		case IXGBE_PCIE_CONFIG0_PTR:
104862306a36Sopenharmony_ci		case IXGBE_PCIE_CONFIG1_PTR:
104962306a36Sopenharmony_ci			size = IXGBE_PCIE_CONFIG_SIZE;
105062306a36Sopenharmony_ci			break;
105162306a36Sopenharmony_ci		default:
105262306a36Sopenharmony_ci			size = 0;
105362306a36Sopenharmony_ci			break;
105462306a36Sopenharmony_ci		}
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci		status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum,
105762306a36Sopenharmony_ci						 buffer, buffer_size);
105862306a36Sopenharmony_ci		if (status)
105962306a36Sopenharmony_ci			return status;
106062306a36Sopenharmony_ci	}
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	return (s32)checksum;
106562306a36Sopenharmony_ci}
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci/** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum
106862306a36Sopenharmony_ci *  @hw: pointer to hardware structure
106962306a36Sopenharmony_ci *
107062306a36Sopenharmony_ci *  Returns a negative error code on error, or the 16-bit checksum
107162306a36Sopenharmony_ci **/
107262306a36Sopenharmony_cistatic s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
107362306a36Sopenharmony_ci{
107462306a36Sopenharmony_ci	return ixgbe_calc_checksum_X550(hw, NULL, 0);
107562306a36Sopenharmony_ci}
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci/** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command
107862306a36Sopenharmony_ci *  @hw: pointer to hardware structure
107962306a36Sopenharmony_ci *  @offset: offset of  word in the EEPROM to read
108062306a36Sopenharmony_ci *  @data: word read from the EEPROM
108162306a36Sopenharmony_ci *
108262306a36Sopenharmony_ci *   Reads a 16 bit word from the EEPROM using the hostif.
108362306a36Sopenharmony_ci **/
108462306a36Sopenharmony_cistatic s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data)
108562306a36Sopenharmony_ci{
108662306a36Sopenharmony_ci	const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
108762306a36Sopenharmony_ci	struct ixgbe_hic_read_shadow_ram buffer;
108862306a36Sopenharmony_ci	s32 status;
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
109162306a36Sopenharmony_ci	buffer.hdr.req.buf_lenh = 0;
109262306a36Sopenharmony_ci	buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
109362306a36Sopenharmony_ci	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	/* convert offset from words to bytes */
109662306a36Sopenharmony_ci	buffer.address = (__force u32)cpu_to_be32(offset * 2);
109762306a36Sopenharmony_ci	/* one word */
109862306a36Sopenharmony_ci	buffer.length = (__force u16)cpu_to_be16(sizeof(u16));
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	status = hw->mac.ops.acquire_swfw_sync(hw, mask);
110162306a36Sopenharmony_ci	if (status)
110262306a36Sopenharmony_ci		return status;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
110562306a36Sopenharmony_ci				    IXGBE_HI_COMMAND_TIMEOUT);
110662306a36Sopenharmony_ci	if (!status) {
110762306a36Sopenharmony_ci		*data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
110862306a36Sopenharmony_ci						  FW_NVM_DATA_OFFSET);
110962306a36Sopenharmony_ci	}
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, mask);
111262306a36Sopenharmony_ci	return status;
111362306a36Sopenharmony_ci}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci/** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum
111662306a36Sopenharmony_ci *  @hw: pointer to hardware structure
111762306a36Sopenharmony_ci *  @checksum_val: calculated checksum
111862306a36Sopenharmony_ci *
111962306a36Sopenharmony_ci *  Performs checksum calculation and validates the EEPROM checksum.  If the
112062306a36Sopenharmony_ci *  caller does not need checksum_val, the value can be NULL.
112162306a36Sopenharmony_ci **/
112262306a36Sopenharmony_cistatic s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw,
112362306a36Sopenharmony_ci					       u16 *checksum_val)
112462306a36Sopenharmony_ci{
112562306a36Sopenharmony_ci	s32 status;
112662306a36Sopenharmony_ci	u16 checksum;
112762306a36Sopenharmony_ci	u16 read_checksum = 0;
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci	/* Read the first word from the EEPROM. If this times out or fails, do
113062306a36Sopenharmony_ci	 * not continue or we could be in for a very long wait while every
113162306a36Sopenharmony_ci	 * EEPROM read fails
113262306a36Sopenharmony_ci	 */
113362306a36Sopenharmony_ci	status = hw->eeprom.ops.read(hw, 0, &checksum);
113462306a36Sopenharmony_ci	if (status) {
113562306a36Sopenharmony_ci		hw_dbg(hw, "EEPROM read failed\n");
113662306a36Sopenharmony_ci		return status;
113762306a36Sopenharmony_ci	}
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	status = hw->eeprom.ops.calc_checksum(hw);
114062306a36Sopenharmony_ci	if (status < 0)
114162306a36Sopenharmony_ci		return status;
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	checksum = (u16)(status & 0xffff);
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
114662306a36Sopenharmony_ci					   &read_checksum);
114762306a36Sopenharmony_ci	if (status)
114862306a36Sopenharmony_ci		return status;
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	/* Verify read checksum from EEPROM is the same as
115162306a36Sopenharmony_ci	 * calculated checksum
115262306a36Sopenharmony_ci	 */
115362306a36Sopenharmony_ci	if (read_checksum != checksum) {
115462306a36Sopenharmony_ci		status = -EIO;
115562306a36Sopenharmony_ci		hw_dbg(hw, "Invalid EEPROM checksum");
115662306a36Sopenharmony_ci	}
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	/* If the user cares, return the calculated checksum */
115962306a36Sopenharmony_ci	if (checksum_val)
116062306a36Sopenharmony_ci		*checksum_val = checksum;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	return status;
116362306a36Sopenharmony_ci}
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci/** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
116662306a36Sopenharmony_ci *  @hw: pointer to hardware structure
116762306a36Sopenharmony_ci *  @offset: offset of  word in the EEPROM to write
116862306a36Sopenharmony_ci *  @data: word write to the EEPROM
116962306a36Sopenharmony_ci *
117062306a36Sopenharmony_ci *  Write a 16 bit word to the EEPROM using the hostif.
117162306a36Sopenharmony_ci **/
117262306a36Sopenharmony_cistatic s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
117362306a36Sopenharmony_ci					   u16 data)
117462306a36Sopenharmony_ci{
117562306a36Sopenharmony_ci	s32 status;
117662306a36Sopenharmony_ci	struct ixgbe_hic_write_shadow_ram buffer;
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
117962306a36Sopenharmony_ci	buffer.hdr.req.buf_lenh = 0;
118062306a36Sopenharmony_ci	buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
118162306a36Sopenharmony_ci	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	/* one word */
118462306a36Sopenharmony_ci	buffer.length = cpu_to_be16(sizeof(u16));
118562306a36Sopenharmony_ci	buffer.data = data;
118662306a36Sopenharmony_ci	buffer.address = cpu_to_be32(offset * 2);
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer),
118962306a36Sopenharmony_ci					      IXGBE_HI_COMMAND_TIMEOUT, false);
119062306a36Sopenharmony_ci	return status;
119162306a36Sopenharmony_ci}
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci/** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
119462306a36Sopenharmony_ci *  @hw: pointer to hardware structure
119562306a36Sopenharmony_ci *  @offset: offset of  word in the EEPROM to write
119662306a36Sopenharmony_ci *  @data: word write to the EEPROM
119762306a36Sopenharmony_ci *
119862306a36Sopenharmony_ci *  Write a 16 bit word to the EEPROM using the hostif.
119962306a36Sopenharmony_ci **/
120062306a36Sopenharmony_cistatic s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data)
120162306a36Sopenharmony_ci{
120262306a36Sopenharmony_ci	s32 status = 0;
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
120562306a36Sopenharmony_ci		status = ixgbe_write_ee_hostif_data_X550(hw, offset, data);
120662306a36Sopenharmony_ci		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
120762306a36Sopenharmony_ci	} else {
120862306a36Sopenharmony_ci		hw_dbg(hw, "write ee hostif failed to get semaphore");
120962306a36Sopenharmony_ci		status = -EBUSY;
121062306a36Sopenharmony_ci	}
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	return status;
121362306a36Sopenharmony_ci}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci/** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device
121662306a36Sopenharmony_ci *  @hw: pointer to hardware structure
121762306a36Sopenharmony_ci *
121862306a36Sopenharmony_ci *  Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash.
121962306a36Sopenharmony_ci **/
122062306a36Sopenharmony_cistatic s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw)
122162306a36Sopenharmony_ci{
122262306a36Sopenharmony_ci	s32 status = 0;
122362306a36Sopenharmony_ci	union ixgbe_hic_hdr2 buffer;
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_ci	buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD;
122662306a36Sopenharmony_ci	buffer.req.buf_lenh = 0;
122762306a36Sopenharmony_ci	buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN;
122862306a36Sopenharmony_ci	buffer.req.checksum = FW_DEFAULT_CHECKSUM;
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer),
123162306a36Sopenharmony_ci					      IXGBE_HI_COMMAND_TIMEOUT, false);
123262306a36Sopenharmony_ci	return status;
123362306a36Sopenharmony_ci}
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci/**
123662306a36Sopenharmony_ci * ixgbe_get_bus_info_X550em - Set PCI bus info
123762306a36Sopenharmony_ci * @hw: pointer to hardware structure
123862306a36Sopenharmony_ci *
123962306a36Sopenharmony_ci * Sets bus link width and speed to unknown because X550em is
124062306a36Sopenharmony_ci * not a PCI device.
124162306a36Sopenharmony_ci **/
124262306a36Sopenharmony_cistatic s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
124362306a36Sopenharmony_ci{
124462306a36Sopenharmony_ci	hw->bus.type  = ixgbe_bus_type_internal;
124562306a36Sopenharmony_ci	hw->bus.width = ixgbe_bus_width_unknown;
124662306a36Sopenharmony_ci	hw->bus.speed = ixgbe_bus_speed_unknown;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	hw->mac.ops.set_lan_id(hw);
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	return 0;
125162306a36Sopenharmony_ci}
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci/**
125462306a36Sopenharmony_ci * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode
125562306a36Sopenharmony_ci * @hw: pointer t hardware structure
125662306a36Sopenharmony_ci *
125762306a36Sopenharmony_ci * Returns true if in FW NVM recovery mode.
125862306a36Sopenharmony_ci */
125962306a36Sopenharmony_cistatic bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw)
126062306a36Sopenharmony_ci{
126162306a36Sopenharmony_ci	u32 fwsm;
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
126462306a36Sopenharmony_ci	return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE);
126562306a36Sopenharmony_ci}
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci/** ixgbe_disable_rx_x550 - Disable RX unit
126862306a36Sopenharmony_ci *
126962306a36Sopenharmony_ci *  Enables the Rx DMA unit for x550
127062306a36Sopenharmony_ci **/
127162306a36Sopenharmony_cistatic void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
127262306a36Sopenharmony_ci{
127362306a36Sopenharmony_ci	u32 rxctrl, pfdtxgswc;
127462306a36Sopenharmony_ci	s32 status;
127562306a36Sopenharmony_ci	struct ixgbe_hic_disable_rxen fw_cmd;
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
127862306a36Sopenharmony_ci	if (rxctrl & IXGBE_RXCTRL_RXEN) {
127962306a36Sopenharmony_ci		pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
128062306a36Sopenharmony_ci		if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
128162306a36Sopenharmony_ci			pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
128262306a36Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
128362306a36Sopenharmony_ci			hw->mac.set_lben = true;
128462306a36Sopenharmony_ci		} else {
128562306a36Sopenharmony_ci			hw->mac.set_lben = false;
128662306a36Sopenharmony_ci		}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci		fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD;
128962306a36Sopenharmony_ci		fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN;
129062306a36Sopenharmony_ci		fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
129162306a36Sopenharmony_ci		fw_cmd.port_number = hw->bus.lan_id;
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci		status = ixgbe_host_interface_command(hw, &fw_cmd,
129462306a36Sopenharmony_ci					sizeof(struct ixgbe_hic_disable_rxen),
129562306a36Sopenharmony_ci					IXGBE_HI_COMMAND_TIMEOUT, true);
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci		/* If we fail - disable RX using register write */
129862306a36Sopenharmony_ci		if (status) {
129962306a36Sopenharmony_ci			rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
130062306a36Sopenharmony_ci			if (rxctrl & IXGBE_RXCTRL_RXEN) {
130162306a36Sopenharmony_ci				rxctrl &= ~IXGBE_RXCTRL_RXEN;
130262306a36Sopenharmony_ci				IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
130362306a36Sopenharmony_ci			}
130462306a36Sopenharmony_ci		}
130562306a36Sopenharmony_ci	}
130662306a36Sopenharmony_ci}
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci/** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash
130962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
131062306a36Sopenharmony_ci *
131162306a36Sopenharmony_ci *  After writing EEPROM to shadow RAM using EEWR register, software calculates
131262306a36Sopenharmony_ci *  checksum and updates the EEPROM and instructs the hardware to update
131362306a36Sopenharmony_ci *  the flash.
131462306a36Sopenharmony_ci **/
131562306a36Sopenharmony_cistatic s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw)
131662306a36Sopenharmony_ci{
131762306a36Sopenharmony_ci	s32 status;
131862306a36Sopenharmony_ci	u16 checksum = 0;
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	/* Read the first word from the EEPROM. If this times out or fails, do
132162306a36Sopenharmony_ci	 * not continue or we could be in for a very long wait while every
132262306a36Sopenharmony_ci	 * EEPROM read fails
132362306a36Sopenharmony_ci	 */
132462306a36Sopenharmony_ci	status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum);
132562306a36Sopenharmony_ci	if (status) {
132662306a36Sopenharmony_ci		hw_dbg(hw, "EEPROM read failed\n");
132762306a36Sopenharmony_ci		return status;
132862306a36Sopenharmony_ci	}
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci	status = ixgbe_calc_eeprom_checksum_X550(hw);
133162306a36Sopenharmony_ci	if (status < 0)
133262306a36Sopenharmony_ci		return status;
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	checksum = (u16)(status & 0xffff);
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
133762306a36Sopenharmony_ci					    checksum);
133862306a36Sopenharmony_ci	if (status)
133962306a36Sopenharmony_ci		return status;
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	status = ixgbe_update_flash_X550(hw);
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	return status;
134462306a36Sopenharmony_ci}
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci/** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif
134762306a36Sopenharmony_ci *  @hw: pointer to hardware structure
134862306a36Sopenharmony_ci *  @offset: offset of  word in the EEPROM to write
134962306a36Sopenharmony_ci *  @words: number of words
135062306a36Sopenharmony_ci *  @data: word(s) write to the EEPROM
135162306a36Sopenharmony_ci *
135262306a36Sopenharmony_ci *
135362306a36Sopenharmony_ci *  Write a 16 bit word(s) to the EEPROM using the hostif.
135462306a36Sopenharmony_ci **/
135562306a36Sopenharmony_cistatic s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
135662306a36Sopenharmony_ci					     u16 offset, u16 words,
135762306a36Sopenharmony_ci					     u16 *data)
135862306a36Sopenharmony_ci{
135962306a36Sopenharmony_ci	s32 status = 0;
136062306a36Sopenharmony_ci	u32 i = 0;
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci	/* Take semaphore for the entire operation. */
136362306a36Sopenharmony_ci	status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
136462306a36Sopenharmony_ci	if (status) {
136562306a36Sopenharmony_ci		hw_dbg(hw, "EEPROM write buffer - semaphore failed\n");
136662306a36Sopenharmony_ci		return status;
136762306a36Sopenharmony_ci	}
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci	for (i = 0; i < words; i++) {
137062306a36Sopenharmony_ci		status = ixgbe_write_ee_hostif_data_X550(hw, offset + i,
137162306a36Sopenharmony_ci							 data[i]);
137262306a36Sopenharmony_ci		if (status) {
137362306a36Sopenharmony_ci			hw_dbg(hw, "Eeprom buffered write failed\n");
137462306a36Sopenharmony_ci			break;
137562306a36Sopenharmony_ci		}
137662306a36Sopenharmony_ci	}
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	return status;
138162306a36Sopenharmony_ci}
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci/** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the
138462306a36Sopenharmony_ci *  IOSF device
138562306a36Sopenharmony_ci *
138662306a36Sopenharmony_ci *  @hw: pointer to hardware structure
138762306a36Sopenharmony_ci *  @reg_addr: 32 bit PHY register to write
138862306a36Sopenharmony_ci *  @device_type: 3 bit device type
138962306a36Sopenharmony_ci *  @data: Data to write to the register
139062306a36Sopenharmony_ci **/
139162306a36Sopenharmony_cistatic s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
139262306a36Sopenharmony_ci					u32 device_type, u32 data)
139362306a36Sopenharmony_ci{
139462306a36Sopenharmony_ci	u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
139562306a36Sopenharmony_ci	u32 command, error;
139662306a36Sopenharmony_ci	s32 ret;
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
139962306a36Sopenharmony_ci	if (ret)
140062306a36Sopenharmony_ci		return ret;
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_ci	ret = ixgbe_iosf_wait(hw, NULL);
140362306a36Sopenharmony_ci	if (ret)
140462306a36Sopenharmony_ci		goto out;
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci	command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
140762306a36Sopenharmony_ci		   (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci	/* Write IOSF control register */
141062306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci	/* Write IOSF data register */
141362306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data);
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	ret = ixgbe_iosf_wait(hw, &command);
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
141862306a36Sopenharmony_ci		error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
141962306a36Sopenharmony_ci			 IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
142062306a36Sopenharmony_ci		hw_dbg(hw, "Failed to write, error %x\n", error);
142162306a36Sopenharmony_ci		return -EIO;
142262306a36Sopenharmony_ci	}
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ciout:
142562306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, gssr);
142662306a36Sopenharmony_ci	return ret;
142762306a36Sopenharmony_ci}
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci/**
143062306a36Sopenharmony_ci *  ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration
143162306a36Sopenharmony_ci *  @hw: pointer to hardware structure
143262306a36Sopenharmony_ci *
143362306a36Sopenharmony_ci *  iXfI configuration needed for ixgbe_mac_X550EM_x devices.
143462306a36Sopenharmony_ci **/
143562306a36Sopenharmony_cistatic s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)
143662306a36Sopenharmony_ci{
143762306a36Sopenharmony_ci	s32 status;
143862306a36Sopenharmony_ci	u32 reg_val;
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	/* Disable training protocol FSM. */
144162306a36Sopenharmony_ci	status = ixgbe_read_iosf_sb_reg_x550(hw,
144262306a36Sopenharmony_ci				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
144362306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
144462306a36Sopenharmony_ci	if (status)
144562306a36Sopenharmony_ci		return status;
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL;
144862306a36Sopenharmony_ci	status = ixgbe_write_iosf_sb_reg_x550(hw,
144962306a36Sopenharmony_ci				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
145062306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
145162306a36Sopenharmony_ci	if (status)
145262306a36Sopenharmony_ci		return status;
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	/* Disable Flex from training TXFFE. */
145562306a36Sopenharmony_ci	status = ixgbe_read_iosf_sb_reg_x550(hw,
145662306a36Sopenharmony_ci				IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
145762306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
145862306a36Sopenharmony_ci	if (status)
145962306a36Sopenharmony_ci		return status;
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
146262306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
146362306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
146462306a36Sopenharmony_ci	status = ixgbe_write_iosf_sb_reg_x550(hw,
146562306a36Sopenharmony_ci				IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
146662306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
146762306a36Sopenharmony_ci	if (status)
146862306a36Sopenharmony_ci		return status;
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	status = ixgbe_read_iosf_sb_reg_x550(hw,
147162306a36Sopenharmony_ci				IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
147262306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
147362306a36Sopenharmony_ci	if (status)
147462306a36Sopenharmony_ci		return status;
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
147762306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
147862306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
147962306a36Sopenharmony_ci	status = ixgbe_write_iosf_sb_reg_x550(hw,
148062306a36Sopenharmony_ci				IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
148162306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
148262306a36Sopenharmony_ci	if (status)
148362306a36Sopenharmony_ci		return status;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	/* Enable override for coefficients. */
148662306a36Sopenharmony_ci	status = ixgbe_read_iosf_sb_reg_x550(hw,
148762306a36Sopenharmony_ci				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
148862306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
148962306a36Sopenharmony_ci	if (status)
149062306a36Sopenharmony_ci		return status;
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN;
149362306a36Sopenharmony_ci	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN;
149462306a36Sopenharmony_ci	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN;
149562306a36Sopenharmony_ci	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN;
149662306a36Sopenharmony_ci	status = ixgbe_write_iosf_sb_reg_x550(hw,
149762306a36Sopenharmony_ci				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
149862306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
149962306a36Sopenharmony_ci	return status;
150062306a36Sopenharmony_ci}
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci/**
150362306a36Sopenharmony_ci *  ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the
150462306a36Sopenharmony_ci *  internal PHY
150562306a36Sopenharmony_ci *  @hw: pointer to hardware structure
150662306a36Sopenharmony_ci **/
150762306a36Sopenharmony_cistatic s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
150862306a36Sopenharmony_ci{
150962306a36Sopenharmony_ci	s32 status;
151062306a36Sopenharmony_ci	u32 link_ctrl;
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	/* Restart auto-negotiation. */
151362306a36Sopenharmony_ci	status = hw->mac.ops.read_iosf_sb_reg(hw,
151462306a36Sopenharmony_ci				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
151562306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl);
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	if (status) {
151862306a36Sopenharmony_ci		hw_dbg(hw, "Auto-negotiation did not complete\n");
151962306a36Sopenharmony_ci		return status;
152062306a36Sopenharmony_ci	}
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_ci	link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
152362306a36Sopenharmony_ci	status = hw->mac.ops.write_iosf_sb_reg(hw,
152462306a36Sopenharmony_ci				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
152562306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl);
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_x550em_a) {
152862306a36Sopenharmony_ci		u32 flx_mask_st20;
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci		/* Indicate to FW that AN restart has been asserted */
153162306a36Sopenharmony_ci		status = hw->mac.ops.read_iosf_sb_reg(hw,
153262306a36Sopenharmony_ci				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
153362306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20);
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci		if (status) {
153662306a36Sopenharmony_ci			hw_dbg(hw, "Auto-negotiation did not complete\n");
153762306a36Sopenharmony_ci			return status;
153862306a36Sopenharmony_ci		}
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci		flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART;
154162306a36Sopenharmony_ci		status = hw->mac.ops.write_iosf_sb_reg(hw,
154262306a36Sopenharmony_ci				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
154362306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20);
154462306a36Sopenharmony_ci	}
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	return status;
154762306a36Sopenharmony_ci}
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
155062306a36Sopenharmony_ci *  @hw: pointer to hardware structure
155162306a36Sopenharmony_ci *  @speed: the link speed to force
155262306a36Sopenharmony_ci *
155362306a36Sopenharmony_ci *  Configures the integrated KR PHY to use iXFI mode. Used to connect an
155462306a36Sopenharmony_ci *  internal and external PHY at a specific speed, without autonegotiation.
155562306a36Sopenharmony_ci **/
155662306a36Sopenharmony_cistatic s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
155762306a36Sopenharmony_ci{
155862306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
155962306a36Sopenharmony_ci	s32 status;
156062306a36Sopenharmony_ci	u32 reg_val;
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	/* iXFI is only supported with X552 */
156362306a36Sopenharmony_ci	if (mac->type != ixgbe_mac_X550EM_x)
156462306a36Sopenharmony_ci		return -EIO;
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	/* Disable AN and force speed to 10G Serial. */
156762306a36Sopenharmony_ci	status = ixgbe_read_iosf_sb_reg_x550(hw,
156862306a36Sopenharmony_ci					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
156962306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
157062306a36Sopenharmony_ci	if (status)
157162306a36Sopenharmony_ci		return status;
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
157462306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	/* Select forced link speed for internal PHY. */
157762306a36Sopenharmony_ci	switch (*speed) {
157862306a36Sopenharmony_ci	case IXGBE_LINK_SPEED_10GB_FULL:
157962306a36Sopenharmony_ci		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
158062306a36Sopenharmony_ci		break;
158162306a36Sopenharmony_ci	case IXGBE_LINK_SPEED_1GB_FULL:
158262306a36Sopenharmony_ci		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
158362306a36Sopenharmony_ci		break;
158462306a36Sopenharmony_ci	default:
158562306a36Sopenharmony_ci		/* Other link speeds are not supported by internal KR PHY. */
158662306a36Sopenharmony_ci		return -EINVAL;
158762306a36Sopenharmony_ci	}
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci	status = ixgbe_write_iosf_sb_reg_x550(hw,
159062306a36Sopenharmony_ci				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
159162306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
159262306a36Sopenharmony_ci	if (status)
159362306a36Sopenharmony_ci		return status;
159462306a36Sopenharmony_ci
159562306a36Sopenharmony_ci	/* Additional configuration needed for x550em_x */
159662306a36Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_X550EM_x) {
159762306a36Sopenharmony_ci		status = ixgbe_setup_ixfi_x550em_x(hw);
159862306a36Sopenharmony_ci		if (status)
159962306a36Sopenharmony_ci			return status;
160062306a36Sopenharmony_ci	}
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_ci	/* Toggle port SW reset by AN reset. */
160362306a36Sopenharmony_ci	status = ixgbe_restart_an_internal_phy_x550em(hw);
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_ci	return status;
160662306a36Sopenharmony_ci}
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci/**
160962306a36Sopenharmony_ci *  ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported
161062306a36Sopenharmony_ci *  @hw: pointer to hardware structure
161162306a36Sopenharmony_ci *  @linear: true if SFP module is linear
161262306a36Sopenharmony_ci */
161362306a36Sopenharmony_cistatic s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear)
161462306a36Sopenharmony_ci{
161562306a36Sopenharmony_ci	switch (hw->phy.sfp_type) {
161662306a36Sopenharmony_ci	case ixgbe_sfp_type_not_present:
161762306a36Sopenharmony_ci		return -ENOENT;
161862306a36Sopenharmony_ci	case ixgbe_sfp_type_da_cu_core0:
161962306a36Sopenharmony_ci	case ixgbe_sfp_type_da_cu_core1:
162062306a36Sopenharmony_ci		*linear = true;
162162306a36Sopenharmony_ci		break;
162262306a36Sopenharmony_ci	case ixgbe_sfp_type_srlr_core0:
162362306a36Sopenharmony_ci	case ixgbe_sfp_type_srlr_core1:
162462306a36Sopenharmony_ci	case ixgbe_sfp_type_da_act_lmt_core0:
162562306a36Sopenharmony_ci	case ixgbe_sfp_type_da_act_lmt_core1:
162662306a36Sopenharmony_ci	case ixgbe_sfp_type_1g_sx_core0:
162762306a36Sopenharmony_ci	case ixgbe_sfp_type_1g_sx_core1:
162862306a36Sopenharmony_ci	case ixgbe_sfp_type_1g_lx_core0:
162962306a36Sopenharmony_ci	case ixgbe_sfp_type_1g_lx_core1:
163062306a36Sopenharmony_ci		*linear = false;
163162306a36Sopenharmony_ci		break;
163262306a36Sopenharmony_ci	case ixgbe_sfp_type_unknown:
163362306a36Sopenharmony_ci	case ixgbe_sfp_type_1g_cu_core0:
163462306a36Sopenharmony_ci	case ixgbe_sfp_type_1g_cu_core1:
163562306a36Sopenharmony_ci	default:
163662306a36Sopenharmony_ci		return -EOPNOTSUPP;
163762306a36Sopenharmony_ci	}
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci	return 0;
164062306a36Sopenharmony_ci}
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_ci/**
164362306a36Sopenharmony_ci * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP.
164462306a36Sopenharmony_ci * @hw: pointer to hardware structure
164562306a36Sopenharmony_ci * @speed: the link speed to force
164662306a36Sopenharmony_ci * @autoneg_wait_to_complete: unused
164762306a36Sopenharmony_ci *
164862306a36Sopenharmony_ci * Configures the extern PHY and the integrated KR PHY for SFP support.
164962306a36Sopenharmony_ci */
165062306a36Sopenharmony_cistatic s32
165162306a36Sopenharmony_ciixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
165262306a36Sopenharmony_ci				ixgbe_link_speed speed,
165362306a36Sopenharmony_ci				__always_unused bool autoneg_wait_to_complete)
165462306a36Sopenharmony_ci{
165562306a36Sopenharmony_ci	s32 status;
165662306a36Sopenharmony_ci	u16 reg_slice, reg_val;
165762306a36Sopenharmony_ci	bool setup_linear = false;
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_ci	/* Check if SFP module is supported and linear */
166062306a36Sopenharmony_ci	status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci	/* If no SFP module present, then return success. Return success since
166362306a36Sopenharmony_ci	 * there is no reason to configure CS4227 and SFP not present error is
166462306a36Sopenharmony_ci	 * not accepted in the setup MAC link flow.
166562306a36Sopenharmony_ci	 */
166662306a36Sopenharmony_ci	if (status == -ENOENT)
166762306a36Sopenharmony_ci		return 0;
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci	if (status)
167062306a36Sopenharmony_ci		return status;
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci	/* Configure internal PHY for KR/KX. */
167362306a36Sopenharmony_ci	ixgbe_setup_kr_speed_x550em(hw, speed);
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	/* Configure CS4227 LINE side to proper mode. */
167662306a36Sopenharmony_ci	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
167762306a36Sopenharmony_ci	if (setup_linear)
167862306a36Sopenharmony_ci		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
167962306a36Sopenharmony_ci	else
168062306a36Sopenharmony_ci		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice,
168362306a36Sopenharmony_ci					 reg_val);
168462306a36Sopenharmony_ci
168562306a36Sopenharmony_ci	return status;
168662306a36Sopenharmony_ci}
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci/**
168962306a36Sopenharmony_ci * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode
169062306a36Sopenharmony_ci * @hw: pointer to hardware structure
169162306a36Sopenharmony_ci * @speed: the link speed to force
169262306a36Sopenharmony_ci *
169362306a36Sopenharmony_ci * Configures the integrated PHY for native SFI mode. Used to connect the
169462306a36Sopenharmony_ci * internal PHY directly to an SFP cage, without autonegotiation.
169562306a36Sopenharmony_ci **/
169662306a36Sopenharmony_cistatic s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
169762306a36Sopenharmony_ci{
169862306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
169962306a36Sopenharmony_ci	s32 status;
170062306a36Sopenharmony_ci	u32 reg_val;
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci	/* Disable all AN and force speed to 10G Serial. */
170362306a36Sopenharmony_ci	status = mac->ops.read_iosf_sb_reg(hw,
170462306a36Sopenharmony_ci				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
170562306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
170662306a36Sopenharmony_ci	if (status)
170762306a36Sopenharmony_ci		return status;
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
171062306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
171162306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
171262306a36Sopenharmony_ci	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_ci	/* Select forced link speed for internal PHY. */
171562306a36Sopenharmony_ci	switch (*speed) {
171662306a36Sopenharmony_ci	case IXGBE_LINK_SPEED_10GB_FULL:
171762306a36Sopenharmony_ci		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G;
171862306a36Sopenharmony_ci		break;
171962306a36Sopenharmony_ci	case IXGBE_LINK_SPEED_1GB_FULL:
172062306a36Sopenharmony_ci		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
172162306a36Sopenharmony_ci		break;
172262306a36Sopenharmony_ci	default:
172362306a36Sopenharmony_ci		/* Other link speeds are not supported by internal PHY. */
172462306a36Sopenharmony_ci		return -EINVAL;
172562306a36Sopenharmony_ci	}
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	(void)mac->ops.write_iosf_sb_reg(hw,
172862306a36Sopenharmony_ci			IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
172962306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	/* change mode enforcement rules to hybrid */
173262306a36Sopenharmony_ci	(void)mac->ops.read_iosf_sb_reg(hw,
173362306a36Sopenharmony_ci			IXGBE_KRM_FLX_TMRS_CTRL_ST31(hw->bus.lan_id),
173462306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
173562306a36Sopenharmony_ci	reg_val |= 0x0400;
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci	(void)mac->ops.write_iosf_sb_reg(hw,
173862306a36Sopenharmony_ci			IXGBE_KRM_FLX_TMRS_CTRL_ST31(hw->bus.lan_id),
173962306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
174062306a36Sopenharmony_ci
174162306a36Sopenharmony_ci	/* manually control the config */
174262306a36Sopenharmony_ci	(void)mac->ops.read_iosf_sb_reg(hw,
174362306a36Sopenharmony_ci			IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
174462306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
174562306a36Sopenharmony_ci	reg_val |= 0x20002240;
174662306a36Sopenharmony_ci
174762306a36Sopenharmony_ci	(void)mac->ops.write_iosf_sb_reg(hw,
174862306a36Sopenharmony_ci			IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
174962306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
175062306a36Sopenharmony_ci
175162306a36Sopenharmony_ci	/* move the AN base page values */
175262306a36Sopenharmony_ci	(void)mac->ops.read_iosf_sb_reg(hw,
175362306a36Sopenharmony_ci			IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id),
175462306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
175562306a36Sopenharmony_ci	reg_val |= 0x1;
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci	(void)mac->ops.write_iosf_sb_reg(hw,
175862306a36Sopenharmony_ci			IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id),
175962306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci	/* set the AN37 over CB mode */
176262306a36Sopenharmony_ci	(void)mac->ops.read_iosf_sb_reg(hw,
176362306a36Sopenharmony_ci			IXGBE_KRM_AN_CNTL_4(hw->bus.lan_id),
176462306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
176562306a36Sopenharmony_ci	reg_val |= 0x20000000;
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci	(void)mac->ops.write_iosf_sb_reg(hw,
176862306a36Sopenharmony_ci			IXGBE_KRM_AN_CNTL_4(hw->bus.lan_id),
176962306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
177062306a36Sopenharmony_ci
177162306a36Sopenharmony_ci	/* restart AN manually */
177262306a36Sopenharmony_ci	(void)mac->ops.read_iosf_sb_reg(hw,
177362306a36Sopenharmony_ci			IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
177462306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
177562306a36Sopenharmony_ci	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
177662306a36Sopenharmony_ci
177762306a36Sopenharmony_ci	(void)mac->ops.write_iosf_sb_reg(hw,
177862306a36Sopenharmony_ci			IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
177962306a36Sopenharmony_ci			IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci	/* Toggle port SW reset by AN reset. */
178262306a36Sopenharmony_ci	status = ixgbe_restart_an_internal_phy_x550em(hw);
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	return status;
178562306a36Sopenharmony_ci}
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci/**
178862306a36Sopenharmony_ci * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP
178962306a36Sopenharmony_ci * @hw: pointer to hardware structure
179062306a36Sopenharmony_ci * @speed: link speed
179162306a36Sopenharmony_ci * @autoneg_wait_to_complete: unused
179262306a36Sopenharmony_ci *
179362306a36Sopenharmony_ci * Configure the integrated PHY for native SFP support.
179462306a36Sopenharmony_ci */
179562306a36Sopenharmony_cistatic s32
179662306a36Sopenharmony_ciixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed,
179762306a36Sopenharmony_ci			   __always_unused bool autoneg_wait_to_complete)
179862306a36Sopenharmony_ci{
179962306a36Sopenharmony_ci	bool setup_linear = false;
180062306a36Sopenharmony_ci	u32 reg_phy_int;
180162306a36Sopenharmony_ci	s32 ret_val;
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci	/* Check if SFP module is supported and linear */
180462306a36Sopenharmony_ci	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ci	/* If no SFP module present, then return success. Return success since
180762306a36Sopenharmony_ci	 * SFP not present error is not excepted in the setup MAC link flow.
180862306a36Sopenharmony_ci	 */
180962306a36Sopenharmony_ci	if (ret_val == -ENOENT)
181062306a36Sopenharmony_ci		return 0;
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_ci	if (ret_val)
181362306a36Sopenharmony_ci		return ret_val;
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	/* Configure internal PHY for native SFI based on module type */
181662306a36Sopenharmony_ci	ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
181762306a36Sopenharmony_ci				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
181862306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
181962306a36Sopenharmony_ci	if (ret_val)
182062306a36Sopenharmony_ci		return ret_val;
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ci	reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA;
182362306a36Sopenharmony_ci	if (!setup_linear)
182462306a36Sopenharmony_ci		reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR;
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci	ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
182762306a36Sopenharmony_ci				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
182862306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
182962306a36Sopenharmony_ci	if (ret_val)
183062306a36Sopenharmony_ci		return ret_val;
183162306a36Sopenharmony_ci
183262306a36Sopenharmony_ci	/* Setup SFI internal link. */
183362306a36Sopenharmony_ci	return ixgbe_setup_sfi_x550a(hw, &speed);
183462306a36Sopenharmony_ci}
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ci/**
183762306a36Sopenharmony_ci * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP
183862306a36Sopenharmony_ci * @hw: pointer to hardware structure
183962306a36Sopenharmony_ci * @speed: link speed
184062306a36Sopenharmony_ci * @autoneg_wait_to_complete: unused
184162306a36Sopenharmony_ci *
184262306a36Sopenharmony_ci * Configure the integrated PHY for SFP support.
184362306a36Sopenharmony_ci */
184462306a36Sopenharmony_cistatic s32
184562306a36Sopenharmony_ciixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed,
184662306a36Sopenharmony_ci			       __always_unused bool autoneg_wait_to_complete)
184762306a36Sopenharmony_ci{
184862306a36Sopenharmony_ci	u32 reg_slice, slice_offset;
184962306a36Sopenharmony_ci	bool setup_linear = false;
185062306a36Sopenharmony_ci	u16 reg_phy_ext;
185162306a36Sopenharmony_ci	s32 ret_val;
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_ci	/* Check if SFP module is supported and linear */
185462306a36Sopenharmony_ci	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
185562306a36Sopenharmony_ci
185662306a36Sopenharmony_ci	/* If no SFP module present, then return success. Return success since
185762306a36Sopenharmony_ci	 * SFP not present error is not excepted in the setup MAC link flow.
185862306a36Sopenharmony_ci	 */
185962306a36Sopenharmony_ci	if (ret_val == -ENOENT)
186062306a36Sopenharmony_ci		return 0;
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_ci	if (ret_val)
186362306a36Sopenharmony_ci		return ret_val;
186462306a36Sopenharmony_ci
186562306a36Sopenharmony_ci	/* Configure internal PHY for KR/KX. */
186662306a36Sopenharmony_ci	ixgbe_setup_kr_speed_x550em(hw, speed);
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci	if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE)
186962306a36Sopenharmony_ci		return -EFAULT;
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci	/* Get external PHY SKU id */
187262306a36Sopenharmony_ci	ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU,
187362306a36Sopenharmony_ci				       IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
187462306a36Sopenharmony_ci	if (ret_val)
187562306a36Sopenharmony_ci		return ret_val;
187662306a36Sopenharmony_ci
187762306a36Sopenharmony_ci	/* When configuring quad port CS4223, the MAC instance is part
187862306a36Sopenharmony_ci	 * of the slice offset.
187962306a36Sopenharmony_ci	 */
188062306a36Sopenharmony_ci	if (reg_phy_ext == IXGBE_CS4223_SKU_ID)
188162306a36Sopenharmony_ci		slice_offset = (hw->bus.lan_id +
188262306a36Sopenharmony_ci				(hw->bus.instance_id << 1)) << 12;
188362306a36Sopenharmony_ci	else
188462306a36Sopenharmony_ci		slice_offset = hw->bus.lan_id << 12;
188562306a36Sopenharmony_ci
188662306a36Sopenharmony_ci	/* Configure CS4227/CS4223 LINE side to proper mode. */
188762306a36Sopenharmony_ci	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci	ret_val = hw->phy.ops.read_reg(hw, reg_slice,
189062306a36Sopenharmony_ci				       IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
189162306a36Sopenharmony_ci	if (ret_val)
189262306a36Sopenharmony_ci		return ret_val;
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) |
189562306a36Sopenharmony_ci			 (IXGBE_CS4227_EDC_MODE_SR << 1));
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_ci	if (setup_linear)
189862306a36Sopenharmony_ci		reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1;
189962306a36Sopenharmony_ci	else
190062306a36Sopenharmony_ci		reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_SR << 1) | 1;
190162306a36Sopenharmony_ci
190262306a36Sopenharmony_ci	ret_val = hw->phy.ops.write_reg(hw, reg_slice,
190362306a36Sopenharmony_ci					IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
190462306a36Sopenharmony_ci	if (ret_val)
190562306a36Sopenharmony_ci		return ret_val;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	/* Flush previous write with a read */
190862306a36Sopenharmony_ci	return hw->phy.ops.read_reg(hw, reg_slice,
190962306a36Sopenharmony_ci				    IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
191062306a36Sopenharmony_ci}
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci/**
191362306a36Sopenharmony_ci * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
191462306a36Sopenharmony_ci * @hw: pointer to hardware structure
191562306a36Sopenharmony_ci * @speed: new link speed
191662306a36Sopenharmony_ci * @autoneg_wait: true when waiting for completion is needed
191762306a36Sopenharmony_ci *
191862306a36Sopenharmony_ci * Setup internal/external PHY link speed based on link speed, then set
191962306a36Sopenharmony_ci * external PHY auto advertised link speed.
192062306a36Sopenharmony_ci *
192162306a36Sopenharmony_ci * Returns error status for any failure
192262306a36Sopenharmony_ci **/
192362306a36Sopenharmony_cistatic s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
192462306a36Sopenharmony_ci					 ixgbe_link_speed speed,
192562306a36Sopenharmony_ci					 bool autoneg_wait)
192662306a36Sopenharmony_ci{
192762306a36Sopenharmony_ci	s32 status;
192862306a36Sopenharmony_ci	ixgbe_link_speed force_speed;
192962306a36Sopenharmony_ci
193062306a36Sopenharmony_ci	/* Setup internal/external PHY link speed to iXFI (10G), unless
193162306a36Sopenharmony_ci	 * only 1G is auto advertised then setup KX link.
193262306a36Sopenharmony_ci	 */
193362306a36Sopenharmony_ci	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
193462306a36Sopenharmony_ci		force_speed = IXGBE_LINK_SPEED_10GB_FULL;
193562306a36Sopenharmony_ci	else
193662306a36Sopenharmony_ci		force_speed = IXGBE_LINK_SPEED_1GB_FULL;
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ci	/* If X552 and internal link mode is XFI, then setup XFI internal link.
193962306a36Sopenharmony_ci	 */
194062306a36Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_X550EM_x &&
194162306a36Sopenharmony_ci	    !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
194262306a36Sopenharmony_ci		status = ixgbe_setup_ixfi_x550em(hw, &force_speed);
194362306a36Sopenharmony_ci
194462306a36Sopenharmony_ci		if (status)
194562306a36Sopenharmony_ci			return status;
194662306a36Sopenharmony_ci	}
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
194962306a36Sopenharmony_ci}
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_ci/** ixgbe_check_link_t_X550em - Determine link and speed status
195262306a36Sopenharmony_ci  * @hw: pointer to hardware structure
195362306a36Sopenharmony_ci  * @speed: pointer to link speed
195462306a36Sopenharmony_ci  * @link_up: true when link is up
195562306a36Sopenharmony_ci  * @link_up_wait_to_complete: bool used to wait for link up or not
195662306a36Sopenharmony_ci  *
195762306a36Sopenharmony_ci  * Check that both the MAC and X557 external PHY have link.
195862306a36Sopenharmony_ci  **/
195962306a36Sopenharmony_cistatic s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw,
196062306a36Sopenharmony_ci				     ixgbe_link_speed *speed,
196162306a36Sopenharmony_ci				     bool *link_up,
196262306a36Sopenharmony_ci				     bool link_up_wait_to_complete)
196362306a36Sopenharmony_ci{
196462306a36Sopenharmony_ci	u32 status;
196562306a36Sopenharmony_ci	u16 i, autoneg_status;
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
196862306a36Sopenharmony_ci		return -EIO;
196962306a36Sopenharmony_ci
197062306a36Sopenharmony_ci	status = ixgbe_check_mac_link_generic(hw, speed, link_up,
197162306a36Sopenharmony_ci					      link_up_wait_to_complete);
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci	/* If check link fails or MAC link is not up, then return */
197462306a36Sopenharmony_ci	if (status || !(*link_up))
197562306a36Sopenharmony_ci		return status;
197662306a36Sopenharmony_ci
197762306a36Sopenharmony_ci	/* MAC link is up, so check external PHY link.
197862306a36Sopenharmony_ci	 * Link status is latching low, and can only be used to detect link
197962306a36Sopenharmony_ci	 * drop, and not the current status of the link without performing
198062306a36Sopenharmony_ci	 * back-to-back reads.
198162306a36Sopenharmony_ci	 */
198262306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
198362306a36Sopenharmony_ci		status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
198462306a36Sopenharmony_ci					      &autoneg_status);
198562306a36Sopenharmony_ci
198662306a36Sopenharmony_ci		if (status)
198762306a36Sopenharmony_ci			return status;
198862306a36Sopenharmony_ci	}
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci	/* If external PHY link is not up, then indicate link not up */
199162306a36Sopenharmony_ci	if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
199262306a36Sopenharmony_ci		*link_up = false;
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_ci	return 0;
199562306a36Sopenharmony_ci}
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_ci/**
199862306a36Sopenharmony_ci * ixgbe_setup_sgmii - Set up link for sgmii
199962306a36Sopenharmony_ci * @hw: pointer to hardware structure
200062306a36Sopenharmony_ci * @speed: unused
200162306a36Sopenharmony_ci * @autoneg_wait_to_complete: unused
200262306a36Sopenharmony_ci */
200362306a36Sopenharmony_cistatic s32
200462306a36Sopenharmony_ciixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed,
200562306a36Sopenharmony_ci		  __always_unused bool autoneg_wait_to_complete)
200662306a36Sopenharmony_ci{
200762306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
200862306a36Sopenharmony_ci	u32 lval, sval, flx_val;
200962306a36Sopenharmony_ci	s32 rc;
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_ci	rc = mac->ops.read_iosf_sb_reg(hw,
201262306a36Sopenharmony_ci				       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
201362306a36Sopenharmony_ci				       IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
201462306a36Sopenharmony_ci	if (rc)
201562306a36Sopenharmony_ci		return rc;
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
201862306a36Sopenharmony_ci	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
201962306a36Sopenharmony_ci	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
202062306a36Sopenharmony_ci	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
202162306a36Sopenharmony_ci	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
202262306a36Sopenharmony_ci	rc = mac->ops.write_iosf_sb_reg(hw,
202362306a36Sopenharmony_ci					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
202462306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
202562306a36Sopenharmony_ci	if (rc)
202662306a36Sopenharmony_ci		return rc;
202762306a36Sopenharmony_ci
202862306a36Sopenharmony_ci	rc = mac->ops.read_iosf_sb_reg(hw,
202962306a36Sopenharmony_ci				       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
203062306a36Sopenharmony_ci				       IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
203162306a36Sopenharmony_ci	if (rc)
203262306a36Sopenharmony_ci		return rc;
203362306a36Sopenharmony_ci
203462306a36Sopenharmony_ci	sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
203562306a36Sopenharmony_ci	sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
203662306a36Sopenharmony_ci	rc = mac->ops.write_iosf_sb_reg(hw,
203762306a36Sopenharmony_ci					IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
203862306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
203962306a36Sopenharmony_ci	if (rc)
204062306a36Sopenharmony_ci		return rc;
204162306a36Sopenharmony_ci
204262306a36Sopenharmony_ci	rc = mac->ops.read_iosf_sb_reg(hw,
204362306a36Sopenharmony_ci				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
204462306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
204562306a36Sopenharmony_ci	if (rc)
204662306a36Sopenharmony_ci		return rc;
204762306a36Sopenharmony_ci
204862306a36Sopenharmony_ci	rc = mac->ops.read_iosf_sb_reg(hw,
204962306a36Sopenharmony_ci				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
205062306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
205162306a36Sopenharmony_ci	if (rc)
205262306a36Sopenharmony_ci		return rc;
205362306a36Sopenharmony_ci
205462306a36Sopenharmony_ci	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
205562306a36Sopenharmony_ci	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
205662306a36Sopenharmony_ci	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
205762306a36Sopenharmony_ci	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
205862306a36Sopenharmony_ci	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
205962306a36Sopenharmony_ci
206062306a36Sopenharmony_ci	rc = mac->ops.write_iosf_sb_reg(hw,
206162306a36Sopenharmony_ci				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
206262306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
206362306a36Sopenharmony_ci	if (rc)
206462306a36Sopenharmony_ci		return rc;
206562306a36Sopenharmony_ci
206662306a36Sopenharmony_ci	rc = ixgbe_restart_an_internal_phy_x550em(hw);
206762306a36Sopenharmony_ci	return rc;
206862306a36Sopenharmony_ci}
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_ci/**
207162306a36Sopenharmony_ci * ixgbe_setup_sgmii_fw - Set up link for sgmii with firmware-controlled PHYs
207262306a36Sopenharmony_ci * @hw: pointer to hardware structure
207362306a36Sopenharmony_ci * @speed: the link speed to force
207462306a36Sopenharmony_ci * @autoneg_wait: true when waiting for completion is needed
207562306a36Sopenharmony_ci */
207662306a36Sopenharmony_cistatic s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed,
207762306a36Sopenharmony_ci				bool autoneg_wait)
207862306a36Sopenharmony_ci{
207962306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
208062306a36Sopenharmony_ci	u32 lval, sval, flx_val;
208162306a36Sopenharmony_ci	s32 rc;
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	rc = mac->ops.read_iosf_sb_reg(hw,
208462306a36Sopenharmony_ci				       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
208562306a36Sopenharmony_ci				       IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
208662306a36Sopenharmony_ci	if (rc)
208762306a36Sopenharmony_ci		return rc;
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
209062306a36Sopenharmony_ci	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
209162306a36Sopenharmony_ci	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
209262306a36Sopenharmony_ci	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
209362306a36Sopenharmony_ci	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
209462306a36Sopenharmony_ci	rc = mac->ops.write_iosf_sb_reg(hw,
209562306a36Sopenharmony_ci					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
209662306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
209762306a36Sopenharmony_ci	if (rc)
209862306a36Sopenharmony_ci		return rc;
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci	rc = mac->ops.read_iosf_sb_reg(hw,
210162306a36Sopenharmony_ci				       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
210262306a36Sopenharmony_ci				       IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
210362306a36Sopenharmony_ci	if (rc)
210462306a36Sopenharmony_ci		return rc;
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci	sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
210762306a36Sopenharmony_ci	sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
210862306a36Sopenharmony_ci	rc = mac->ops.write_iosf_sb_reg(hw,
210962306a36Sopenharmony_ci					IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
211062306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
211162306a36Sopenharmony_ci	if (rc)
211262306a36Sopenharmony_ci		return rc;
211362306a36Sopenharmony_ci
211462306a36Sopenharmony_ci	rc = mac->ops.write_iosf_sb_reg(hw,
211562306a36Sopenharmony_ci					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
211662306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
211762306a36Sopenharmony_ci	if (rc)
211862306a36Sopenharmony_ci		return rc;
211962306a36Sopenharmony_ci
212062306a36Sopenharmony_ci	rc = mac->ops.read_iosf_sb_reg(hw,
212162306a36Sopenharmony_ci				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
212262306a36Sopenharmony_ci				    IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
212362306a36Sopenharmony_ci	if (rc)
212462306a36Sopenharmony_ci		return rc;
212562306a36Sopenharmony_ci
212662306a36Sopenharmony_ci	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
212762306a36Sopenharmony_ci	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
212862306a36Sopenharmony_ci	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
212962306a36Sopenharmony_ci	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
213062306a36Sopenharmony_ci	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
213162306a36Sopenharmony_ci
213262306a36Sopenharmony_ci	rc = mac->ops.write_iosf_sb_reg(hw,
213362306a36Sopenharmony_ci				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
213462306a36Sopenharmony_ci				    IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
213562306a36Sopenharmony_ci	if (rc)
213662306a36Sopenharmony_ci		return rc;
213762306a36Sopenharmony_ci
213862306a36Sopenharmony_ci	ixgbe_restart_an_internal_phy_x550em(hw);
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ci	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
214162306a36Sopenharmony_ci}
214262306a36Sopenharmony_ci
214362306a36Sopenharmony_ci/**
214462306a36Sopenharmony_ci * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37
214562306a36Sopenharmony_ci * @hw: pointer to hardware structure
214662306a36Sopenharmony_ci *
214762306a36Sopenharmony_ci * Enable flow control according to IEEE clause 37.
214862306a36Sopenharmony_ci */
214962306a36Sopenharmony_cistatic void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)
215062306a36Sopenharmony_ci{
215162306a36Sopenharmony_ci	u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
215262306a36Sopenharmony_ci	ixgbe_link_speed speed;
215362306a36Sopenharmony_ci	s32 status = -EIO;
215462306a36Sopenharmony_ci	bool link_up;
215562306a36Sopenharmony_ci
215662306a36Sopenharmony_ci	/* AN should have completed when the cable was plugged in.
215762306a36Sopenharmony_ci	 * Look for reasons to bail out.  Bail out if:
215862306a36Sopenharmony_ci	 * - FC autoneg is disabled, or if
215962306a36Sopenharmony_ci	 * - link is not up.
216062306a36Sopenharmony_ci	 */
216162306a36Sopenharmony_ci	if (hw->fc.disable_fc_autoneg)
216262306a36Sopenharmony_ci		goto out;
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci	hw->mac.ops.check_link(hw, &speed, &link_up, false);
216562306a36Sopenharmony_ci	if (!link_up)
216662306a36Sopenharmony_ci		goto out;
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci	/* Check if auto-negotiation has completed */
216962306a36Sopenharmony_ci	status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info);
217062306a36Sopenharmony_ci	if (status || !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) {
217162306a36Sopenharmony_ci		status = -EIO;
217262306a36Sopenharmony_ci		goto out;
217362306a36Sopenharmony_ci	}
217462306a36Sopenharmony_ci
217562306a36Sopenharmony_ci	/* Negotiate the flow control */
217662306a36Sopenharmony_ci	status = ixgbe_negotiate_fc(hw, info[0], info[0],
217762306a36Sopenharmony_ci				    FW_PHY_ACT_GET_LINK_INFO_FC_RX,
217862306a36Sopenharmony_ci				    FW_PHY_ACT_GET_LINK_INFO_FC_TX,
217962306a36Sopenharmony_ci				    FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX,
218062306a36Sopenharmony_ci				    FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX);
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ciout:
218362306a36Sopenharmony_ci	if (!status) {
218462306a36Sopenharmony_ci		hw->fc.fc_was_autonegged = true;
218562306a36Sopenharmony_ci	} else {
218662306a36Sopenharmony_ci		hw->fc.fc_was_autonegged = false;
218762306a36Sopenharmony_ci		hw->fc.current_mode = hw->fc.requested_mode;
218862306a36Sopenharmony_ci	}
218962306a36Sopenharmony_ci}
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci/** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers
219262306a36Sopenharmony_ci *  @hw: pointer to hardware structure
219362306a36Sopenharmony_ci **/
219462306a36Sopenharmony_cistatic void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw)
219562306a36Sopenharmony_ci{
219662306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci	switch (mac->ops.get_media_type(hw)) {
219962306a36Sopenharmony_ci	case ixgbe_media_type_fiber:
220062306a36Sopenharmony_ci		mac->ops.setup_fc = NULL;
220162306a36Sopenharmony_ci		mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;
220262306a36Sopenharmony_ci		break;
220362306a36Sopenharmony_ci	case ixgbe_media_type_copper:
220462306a36Sopenharmony_ci		if (hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T &&
220562306a36Sopenharmony_ci		    hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T_L) {
220662306a36Sopenharmony_ci			mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
220762306a36Sopenharmony_ci			break;
220862306a36Sopenharmony_ci		}
220962306a36Sopenharmony_ci		mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a;
221062306a36Sopenharmony_ci		mac->ops.setup_fc = ixgbe_fc_autoneg_fw;
221162306a36Sopenharmony_ci		mac->ops.setup_link = ixgbe_setup_sgmii_fw;
221262306a36Sopenharmony_ci		mac->ops.check_link = ixgbe_check_mac_link_generic;
221362306a36Sopenharmony_ci		break;
221462306a36Sopenharmony_ci	case ixgbe_media_type_backplane:
221562306a36Sopenharmony_ci		mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;
221662306a36Sopenharmony_ci		mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;
221762306a36Sopenharmony_ci		break;
221862306a36Sopenharmony_ci	default:
221962306a36Sopenharmony_ci		break;
222062306a36Sopenharmony_ci	}
222162306a36Sopenharmony_ci}
222262306a36Sopenharmony_ci
222362306a36Sopenharmony_ci/** ixgbe_init_mac_link_ops_X550em - init mac link function pointers
222462306a36Sopenharmony_ci *  @hw: pointer to hardware structure
222562306a36Sopenharmony_ci **/
222662306a36Sopenharmony_cistatic void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
222762306a36Sopenharmony_ci{
222862306a36Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
222962306a36Sopenharmony_ci
223062306a36Sopenharmony_ci	mac->ops.setup_fc = ixgbe_setup_fc_x550em;
223162306a36Sopenharmony_ci
223262306a36Sopenharmony_ci	switch (mac->ops.get_media_type(hw)) {
223362306a36Sopenharmony_ci	case ixgbe_media_type_fiber:
223462306a36Sopenharmony_ci		/* CS4227 does not support autoneg, so disable the laser control
223562306a36Sopenharmony_ci		 * functions for SFP+ fiber
223662306a36Sopenharmony_ci		 */
223762306a36Sopenharmony_ci		mac->ops.disable_tx_laser = NULL;
223862306a36Sopenharmony_ci		mac->ops.enable_tx_laser = NULL;
223962306a36Sopenharmony_ci		mac->ops.flap_tx_laser = NULL;
224062306a36Sopenharmony_ci		mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
224162306a36Sopenharmony_ci		switch (hw->device_id) {
224262306a36Sopenharmony_ci		case IXGBE_DEV_ID_X550EM_A_SFP_N:
224362306a36Sopenharmony_ci			mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n;
224462306a36Sopenharmony_ci			break;
224562306a36Sopenharmony_ci		case IXGBE_DEV_ID_X550EM_A_SFP:
224662306a36Sopenharmony_ci			mac->ops.setup_mac_link =
224762306a36Sopenharmony_ci						ixgbe_setup_mac_link_sfp_x550a;
224862306a36Sopenharmony_ci			break;
224962306a36Sopenharmony_ci		default:
225062306a36Sopenharmony_ci			mac->ops.setup_mac_link =
225162306a36Sopenharmony_ci						ixgbe_setup_mac_link_sfp_x550em;
225262306a36Sopenharmony_ci			break;
225362306a36Sopenharmony_ci		}
225462306a36Sopenharmony_ci		mac->ops.set_rate_select_speed =
225562306a36Sopenharmony_ci					ixgbe_set_soft_rate_select_speed;
225662306a36Sopenharmony_ci		break;
225762306a36Sopenharmony_ci	case ixgbe_media_type_copper:
225862306a36Sopenharmony_ci		if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T)
225962306a36Sopenharmony_ci			break;
226062306a36Sopenharmony_ci		mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
226162306a36Sopenharmony_ci		mac->ops.setup_fc = ixgbe_setup_fc_generic;
226262306a36Sopenharmony_ci		mac->ops.check_link = ixgbe_check_link_t_X550em;
226362306a36Sopenharmony_ci		break;
226462306a36Sopenharmony_ci	case ixgbe_media_type_backplane:
226562306a36Sopenharmony_ci		if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
226662306a36Sopenharmony_ci		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)
226762306a36Sopenharmony_ci			mac->ops.setup_link = ixgbe_setup_sgmii;
226862306a36Sopenharmony_ci		break;
226962306a36Sopenharmony_ci	default:
227062306a36Sopenharmony_ci		break;
227162306a36Sopenharmony_ci	}
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_ci	/* Additional modification for X550em_a devices */
227462306a36Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_x550em_a)
227562306a36Sopenharmony_ci		ixgbe_init_mac_link_ops_X550em_a(hw);
227662306a36Sopenharmony_ci}
227762306a36Sopenharmony_ci
227862306a36Sopenharmony_ci/** ixgbe_setup_sfp_modules_X550em - Setup SFP module
227962306a36Sopenharmony_ci * @hw: pointer to hardware structure
228062306a36Sopenharmony_ci */
228162306a36Sopenharmony_cistatic s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
228262306a36Sopenharmony_ci{
228362306a36Sopenharmony_ci	s32 status;
228462306a36Sopenharmony_ci	bool linear;
228562306a36Sopenharmony_ci
228662306a36Sopenharmony_ci	/* Check if SFP module is supported */
228762306a36Sopenharmony_ci	status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
228862306a36Sopenharmony_ci	if (status)
228962306a36Sopenharmony_ci		return status;
229062306a36Sopenharmony_ci
229162306a36Sopenharmony_ci	ixgbe_init_mac_link_ops_X550em(hw);
229262306a36Sopenharmony_ci	hw->phy.ops.reset = NULL;
229362306a36Sopenharmony_ci
229462306a36Sopenharmony_ci	return 0;
229562306a36Sopenharmony_ci}
229662306a36Sopenharmony_ci
229762306a36Sopenharmony_ci/** ixgbe_get_link_capabilities_x550em - Determines link capabilities
229862306a36Sopenharmony_ci * @hw: pointer to hardware structure
229962306a36Sopenharmony_ci * @speed: pointer to link speed
230062306a36Sopenharmony_ci * @autoneg: true when autoneg or autotry is enabled
230162306a36Sopenharmony_ci **/
230262306a36Sopenharmony_cistatic s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
230362306a36Sopenharmony_ci					      ixgbe_link_speed *speed,
230462306a36Sopenharmony_ci					      bool *autoneg)
230562306a36Sopenharmony_ci{
230662306a36Sopenharmony_ci	if (hw->phy.type == ixgbe_phy_fw) {
230762306a36Sopenharmony_ci		*autoneg = true;
230862306a36Sopenharmony_ci		*speed = hw->phy.speeds_supported;
230962306a36Sopenharmony_ci		return 0;
231062306a36Sopenharmony_ci	}
231162306a36Sopenharmony_ci
231262306a36Sopenharmony_ci	/* SFP */
231362306a36Sopenharmony_ci	if (hw->phy.media_type == ixgbe_media_type_fiber) {
231462306a36Sopenharmony_ci		/* CS4227 SFP must not enable auto-negotiation */
231562306a36Sopenharmony_ci		*autoneg = false;
231662306a36Sopenharmony_ci
231762306a36Sopenharmony_ci		if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
231862306a36Sopenharmony_ci		    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
231962306a36Sopenharmony_ci		    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
232062306a36Sopenharmony_ci		    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) {
232162306a36Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_1GB_FULL;
232262306a36Sopenharmony_ci			return 0;
232362306a36Sopenharmony_ci		}
232462306a36Sopenharmony_ci
232562306a36Sopenharmony_ci		/* Link capabilities are based on SFP */
232662306a36Sopenharmony_ci		if (hw->phy.multispeed_fiber)
232762306a36Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_10GB_FULL |
232862306a36Sopenharmony_ci				 IXGBE_LINK_SPEED_1GB_FULL;
232962306a36Sopenharmony_ci		else
233062306a36Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_10GB_FULL;
233162306a36Sopenharmony_ci	} else {
233262306a36Sopenharmony_ci		switch (hw->phy.type) {
233362306a36Sopenharmony_ci		case ixgbe_phy_x550em_kx4:
233462306a36Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_1GB_FULL |
233562306a36Sopenharmony_ci				 IXGBE_LINK_SPEED_2_5GB_FULL |
233662306a36Sopenharmony_ci				 IXGBE_LINK_SPEED_10GB_FULL;
233762306a36Sopenharmony_ci			break;
233862306a36Sopenharmony_ci		case ixgbe_phy_x550em_xfi:
233962306a36Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_1GB_FULL |
234062306a36Sopenharmony_ci				 IXGBE_LINK_SPEED_10GB_FULL;
234162306a36Sopenharmony_ci			break;
234262306a36Sopenharmony_ci		case ixgbe_phy_ext_1g_t:
234362306a36Sopenharmony_ci		case ixgbe_phy_sgmii:
234462306a36Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_1GB_FULL;
234562306a36Sopenharmony_ci			break;
234662306a36Sopenharmony_ci		case ixgbe_phy_x550em_kr:
234762306a36Sopenharmony_ci			if (hw->mac.type == ixgbe_mac_x550em_a) {
234862306a36Sopenharmony_ci				/* check different backplane modes */
234962306a36Sopenharmony_ci				if (hw->phy.nw_mng_if_sel &
235062306a36Sopenharmony_ci				    IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
235162306a36Sopenharmony_ci					*speed = IXGBE_LINK_SPEED_2_5GB_FULL;
235262306a36Sopenharmony_ci					break;
235362306a36Sopenharmony_ci				} else if (hw->device_id ==
235462306a36Sopenharmony_ci					   IXGBE_DEV_ID_X550EM_A_KR_L) {
235562306a36Sopenharmony_ci					*speed = IXGBE_LINK_SPEED_1GB_FULL;
235662306a36Sopenharmony_ci					break;
235762306a36Sopenharmony_ci				}
235862306a36Sopenharmony_ci			}
235962306a36Sopenharmony_ci			fallthrough;
236062306a36Sopenharmony_ci		default:
236162306a36Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_10GB_FULL |
236262306a36Sopenharmony_ci				 IXGBE_LINK_SPEED_1GB_FULL;
236362306a36Sopenharmony_ci			break;
236462306a36Sopenharmony_ci		}
236562306a36Sopenharmony_ci		*autoneg = true;
236662306a36Sopenharmony_ci	}
236762306a36Sopenharmony_ci	return 0;
236862306a36Sopenharmony_ci}
236962306a36Sopenharmony_ci
237062306a36Sopenharmony_ci/**
237162306a36Sopenharmony_ci * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause
237262306a36Sopenharmony_ci * @hw: pointer to hardware structure
237362306a36Sopenharmony_ci * @lsc: pointer to boolean flag which indicates whether external Base T
237462306a36Sopenharmony_ci *	 PHY interrupt is lsc
237562306a36Sopenharmony_ci * @is_overtemp: indicate whether an overtemp event encountered
237662306a36Sopenharmony_ci *
237762306a36Sopenharmony_ci * Determime if external Base T PHY interrupt cause is high temperature
237862306a36Sopenharmony_ci * failure alarm or link status change.
237962306a36Sopenharmony_ci **/
238062306a36Sopenharmony_cistatic s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc,
238162306a36Sopenharmony_ci				       bool *is_overtemp)
238262306a36Sopenharmony_ci{
238362306a36Sopenharmony_ci	u32 status;
238462306a36Sopenharmony_ci	u16 reg;
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	*is_overtemp = false;
238762306a36Sopenharmony_ci	*lsc = false;
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci	/* Vendor alarm triggered */
239062306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
239162306a36Sopenharmony_ci				      MDIO_MMD_VEND1,
239262306a36Sopenharmony_ci				      &reg);
239362306a36Sopenharmony_ci
239462306a36Sopenharmony_ci	if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
239562306a36Sopenharmony_ci		return status;
239662306a36Sopenharmony_ci
239762306a36Sopenharmony_ci	/* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
239862306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
239962306a36Sopenharmony_ci				      MDIO_MMD_VEND1,
240062306a36Sopenharmony_ci				      &reg);
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_ci	if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
240362306a36Sopenharmony_ci				IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
240462306a36Sopenharmony_ci		return status;
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	/* Global alarm triggered */
240762306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
240862306a36Sopenharmony_ci				      MDIO_MMD_VEND1,
240962306a36Sopenharmony_ci				      &reg);
241062306a36Sopenharmony_ci
241162306a36Sopenharmony_ci	if (status)
241262306a36Sopenharmony_ci		return status;
241362306a36Sopenharmony_ci
241462306a36Sopenharmony_ci	/* If high temperature failure, then return over temp error and exit */
241562306a36Sopenharmony_ci	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
241662306a36Sopenharmony_ci		/* power down the PHY in case the PHY FW didn't already */
241762306a36Sopenharmony_ci		ixgbe_set_copper_phy_power(hw, false);
241862306a36Sopenharmony_ci		*is_overtemp = true;
241962306a36Sopenharmony_ci		return -EIO;
242062306a36Sopenharmony_ci	}
242162306a36Sopenharmony_ci	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
242262306a36Sopenharmony_ci		/*  device fault alarm triggered */
242362306a36Sopenharmony_ci		status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
242462306a36Sopenharmony_ci					  MDIO_MMD_VEND1,
242562306a36Sopenharmony_ci					  &reg);
242662306a36Sopenharmony_ci		if (status)
242762306a36Sopenharmony_ci			return status;
242862306a36Sopenharmony_ci
242962306a36Sopenharmony_ci		/* if device fault was due to high temp alarm handle and exit */
243062306a36Sopenharmony_ci		if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
243162306a36Sopenharmony_ci			/* power down the PHY in case the PHY FW didn't */
243262306a36Sopenharmony_ci			ixgbe_set_copper_phy_power(hw, false);
243362306a36Sopenharmony_ci			*is_overtemp = true;
243462306a36Sopenharmony_ci			return -EIO;
243562306a36Sopenharmony_ci		}
243662306a36Sopenharmony_ci	}
243762306a36Sopenharmony_ci
243862306a36Sopenharmony_ci	/* Vendor alarm 2 triggered */
243962306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
244062306a36Sopenharmony_ci				      MDIO_MMD_AN, &reg);
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
244362306a36Sopenharmony_ci		return status;
244462306a36Sopenharmony_ci
244562306a36Sopenharmony_ci	/* link connect/disconnect event occurred */
244662306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
244762306a36Sopenharmony_ci				      MDIO_MMD_AN, &reg);
244862306a36Sopenharmony_ci
244962306a36Sopenharmony_ci	if (status)
245062306a36Sopenharmony_ci		return status;
245162306a36Sopenharmony_ci
245262306a36Sopenharmony_ci	/* Indicate LSC */
245362306a36Sopenharmony_ci	if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC)
245462306a36Sopenharmony_ci		*lsc = true;
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	return 0;
245762306a36Sopenharmony_ci}
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_ci/**
246062306a36Sopenharmony_ci * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts
246162306a36Sopenharmony_ci * @hw: pointer to hardware structure
246262306a36Sopenharmony_ci *
246362306a36Sopenharmony_ci * Enable link status change and temperature failure alarm for the external
246462306a36Sopenharmony_ci * Base T PHY
246562306a36Sopenharmony_ci *
246662306a36Sopenharmony_ci * Returns PHY access status
246762306a36Sopenharmony_ci **/
246862306a36Sopenharmony_cistatic s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
246962306a36Sopenharmony_ci{
247062306a36Sopenharmony_ci	bool lsc, overtemp;
247162306a36Sopenharmony_ci	u32 status;
247262306a36Sopenharmony_ci	u16 reg;
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci	/* Clear interrupt flags */
247562306a36Sopenharmony_ci	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, &overtemp);
247662306a36Sopenharmony_ci
247762306a36Sopenharmony_ci	/* Enable link status change alarm */
247862306a36Sopenharmony_ci
247962306a36Sopenharmony_ci	/* Enable the LASI interrupts on X552 devices to receive notifications
248062306a36Sopenharmony_ci	 * of the link configurations of the external PHY and correspondingly
248162306a36Sopenharmony_ci	 * support the configuration of the internal iXFI link, since iXFI does
248262306a36Sopenharmony_ci	 * not support auto-negotiation. This is not required for X553 devices
248362306a36Sopenharmony_ci	 * having KR support, which performs auto-negotiations and which is used
248462306a36Sopenharmony_ci	 * as the internal link to the external PHY. Hence adding a check here
248562306a36Sopenharmony_ci	 * to avoid enabling LASI interrupts for X553 devices.
248662306a36Sopenharmony_ci	 */
248762306a36Sopenharmony_ci	if (hw->mac.type != ixgbe_mac_x550em_a) {
248862306a36Sopenharmony_ci		status = hw->phy.ops.read_reg(hw,
248962306a36Sopenharmony_ci					    IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
249062306a36Sopenharmony_ci					    MDIO_MMD_AN, &reg);
249162306a36Sopenharmony_ci		if (status)
249262306a36Sopenharmony_ci			return status;
249362306a36Sopenharmony_ci
249462306a36Sopenharmony_ci		reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
249562306a36Sopenharmony_ci
249662306a36Sopenharmony_ci		status = hw->phy.ops.write_reg(hw,
249762306a36Sopenharmony_ci					    IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
249862306a36Sopenharmony_ci					    MDIO_MMD_AN, reg);
249962306a36Sopenharmony_ci		if (status)
250062306a36Sopenharmony_ci			return status;
250162306a36Sopenharmony_ci	}
250262306a36Sopenharmony_ci
250362306a36Sopenharmony_ci	/* Enable high temperature failure and global fault alarms */
250462306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
250562306a36Sopenharmony_ci				      MDIO_MMD_VEND1,
250662306a36Sopenharmony_ci				      &reg);
250762306a36Sopenharmony_ci	if (status)
250862306a36Sopenharmony_ci		return status;
250962306a36Sopenharmony_ci
251062306a36Sopenharmony_ci	reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN |
251162306a36Sopenharmony_ci		IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);
251262306a36Sopenharmony_ci
251362306a36Sopenharmony_ci	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
251462306a36Sopenharmony_ci				       MDIO_MMD_VEND1,
251562306a36Sopenharmony_ci				       reg);
251662306a36Sopenharmony_ci	if (status)
251762306a36Sopenharmony_ci		return status;
251862306a36Sopenharmony_ci
251962306a36Sopenharmony_ci	/* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
252062306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
252162306a36Sopenharmony_ci				      MDIO_MMD_VEND1,
252262306a36Sopenharmony_ci				      &reg);
252362306a36Sopenharmony_ci	if (status)
252462306a36Sopenharmony_ci		return status;
252562306a36Sopenharmony_ci
252662306a36Sopenharmony_ci	reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
252762306a36Sopenharmony_ci		IXGBE_MDIO_GLOBAL_ALARM_1_INT);
252862306a36Sopenharmony_ci
252962306a36Sopenharmony_ci	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
253062306a36Sopenharmony_ci				       MDIO_MMD_VEND1,
253162306a36Sopenharmony_ci				       reg);
253262306a36Sopenharmony_ci	if (status)
253362306a36Sopenharmony_ci		return status;
253462306a36Sopenharmony_ci
253562306a36Sopenharmony_ci	/* Enable chip-wide vendor alarm */
253662306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
253762306a36Sopenharmony_ci				      MDIO_MMD_VEND1,
253862306a36Sopenharmony_ci				      &reg);
253962306a36Sopenharmony_ci	if (status)
254062306a36Sopenharmony_ci		return status;
254162306a36Sopenharmony_ci
254262306a36Sopenharmony_ci	reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
254362306a36Sopenharmony_ci
254462306a36Sopenharmony_ci	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
254562306a36Sopenharmony_ci				       MDIO_MMD_VEND1,
254662306a36Sopenharmony_ci				       reg);
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci	return status;
254962306a36Sopenharmony_ci}
255062306a36Sopenharmony_ci
255162306a36Sopenharmony_ci/**
255262306a36Sopenharmony_ci * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
255362306a36Sopenharmony_ci * @hw: pointer to hardware structure
255462306a36Sopenharmony_ci * @is_overtemp: indicate whether an overtemp event encountered
255562306a36Sopenharmony_ci *
255662306a36Sopenharmony_ci * Handle external Base T PHY interrupt. If high temperature
255762306a36Sopenharmony_ci * failure alarm then return error, else if link status change
255862306a36Sopenharmony_ci * then setup internal/external PHY link
255962306a36Sopenharmony_ci **/
256062306a36Sopenharmony_cistatic s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw,
256162306a36Sopenharmony_ci					  bool *is_overtemp)
256262306a36Sopenharmony_ci{
256362306a36Sopenharmony_ci	struct ixgbe_phy_info *phy = &hw->phy;
256462306a36Sopenharmony_ci	bool lsc;
256562306a36Sopenharmony_ci	u32 status;
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_ci	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, is_overtemp);
256862306a36Sopenharmony_ci	if (status)
256962306a36Sopenharmony_ci		return status;
257062306a36Sopenharmony_ci
257162306a36Sopenharmony_ci	if (lsc && phy->ops.setup_internal_link)
257262306a36Sopenharmony_ci		return phy->ops.setup_internal_link(hw);
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_ci	return 0;
257562306a36Sopenharmony_ci}
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_ci/**
257862306a36Sopenharmony_ci * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed.
257962306a36Sopenharmony_ci * @hw: pointer to hardware structure
258062306a36Sopenharmony_ci * @speed: link speed
258162306a36Sopenharmony_ci *
258262306a36Sopenharmony_ci * Configures the integrated KR PHY.
258362306a36Sopenharmony_ci **/
258462306a36Sopenharmony_cistatic s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
258562306a36Sopenharmony_ci				       ixgbe_link_speed speed)
258662306a36Sopenharmony_ci{
258762306a36Sopenharmony_ci	s32 status;
258862306a36Sopenharmony_ci	u32 reg_val;
258962306a36Sopenharmony_ci
259062306a36Sopenharmony_ci	status = hw->mac.ops.read_iosf_sb_reg(hw,
259162306a36Sopenharmony_ci					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
259262306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
259362306a36Sopenharmony_ci	if (status)
259462306a36Sopenharmony_ci		return status;
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
259762306a36Sopenharmony_ci	reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
259862306a36Sopenharmony_ci		     IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
259962306a36Sopenharmony_ci
260062306a36Sopenharmony_ci	/* Advertise 10G support. */
260162306a36Sopenharmony_ci	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
260262306a36Sopenharmony_ci		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR;
260362306a36Sopenharmony_ci
260462306a36Sopenharmony_ci	/* Advertise 1G support. */
260562306a36Sopenharmony_ci	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
260662306a36Sopenharmony_ci		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
260762306a36Sopenharmony_ci
260862306a36Sopenharmony_ci	status = hw->mac.ops.write_iosf_sb_reg(hw,
260962306a36Sopenharmony_ci					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
261062306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
261162306a36Sopenharmony_ci
261262306a36Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_x550em_a) {
261362306a36Sopenharmony_ci		/* Set lane mode  to KR auto negotiation */
261462306a36Sopenharmony_ci		status = hw->mac.ops.read_iosf_sb_reg(hw,
261562306a36Sopenharmony_ci				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
261662306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_ci		if (status)
261962306a36Sopenharmony_ci			return status;
262062306a36Sopenharmony_ci
262162306a36Sopenharmony_ci		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
262262306a36Sopenharmony_ci		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
262362306a36Sopenharmony_ci		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
262462306a36Sopenharmony_ci		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
262562306a36Sopenharmony_ci		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
262662306a36Sopenharmony_ci
262762306a36Sopenharmony_ci		status = hw->mac.ops.write_iosf_sb_reg(hw,
262862306a36Sopenharmony_ci				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
262962306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
263062306a36Sopenharmony_ci	}
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	return ixgbe_restart_an_internal_phy_x550em(hw);
263362306a36Sopenharmony_ci}
263462306a36Sopenharmony_ci
263562306a36Sopenharmony_ci/**
263662306a36Sopenharmony_ci * ixgbe_setup_kr_x550em - Configure the KR PHY
263762306a36Sopenharmony_ci * @hw: pointer to hardware structure
263862306a36Sopenharmony_ci **/
263962306a36Sopenharmony_cistatic s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
264062306a36Sopenharmony_ci{
264162306a36Sopenharmony_ci	/* leave link alone for 2.5G */
264262306a36Sopenharmony_ci	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
264362306a36Sopenharmony_ci		return 0;
264462306a36Sopenharmony_ci
264562306a36Sopenharmony_ci	if (ixgbe_check_reset_blocked(hw))
264662306a36Sopenharmony_ci		return 0;
264762306a36Sopenharmony_ci
264862306a36Sopenharmony_ci	return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised);
264962306a36Sopenharmony_ci}
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_ci/** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status
265262306a36Sopenharmony_ci *  @hw: address of hardware structure
265362306a36Sopenharmony_ci *  @link_up: address of boolean to indicate link status
265462306a36Sopenharmony_ci *
265562306a36Sopenharmony_ci *  Returns error code if unable to get link status.
265662306a36Sopenharmony_ci **/
265762306a36Sopenharmony_cistatic s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
265862306a36Sopenharmony_ci{
265962306a36Sopenharmony_ci	u32 ret;
266062306a36Sopenharmony_ci	u16 autoneg_status;
266162306a36Sopenharmony_ci
266262306a36Sopenharmony_ci	*link_up = false;
266362306a36Sopenharmony_ci
266462306a36Sopenharmony_ci	/* read this twice back to back to indicate current status */
266562306a36Sopenharmony_ci	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
266662306a36Sopenharmony_ci				   &autoneg_status);
266762306a36Sopenharmony_ci	if (ret)
266862306a36Sopenharmony_ci		return ret;
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
267162306a36Sopenharmony_ci				   &autoneg_status);
267262306a36Sopenharmony_ci	if (ret)
267362306a36Sopenharmony_ci		return ret;
267462306a36Sopenharmony_ci
267562306a36Sopenharmony_ci	*link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS);
267662306a36Sopenharmony_ci
267762306a36Sopenharmony_ci	return 0;
267862306a36Sopenharmony_ci}
267962306a36Sopenharmony_ci
268062306a36Sopenharmony_ci/** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link
268162306a36Sopenharmony_ci *  @hw: point to hardware structure
268262306a36Sopenharmony_ci *
268362306a36Sopenharmony_ci *  Configures the link between the integrated KR PHY and the external X557 PHY
268462306a36Sopenharmony_ci *  The driver will call this function when it gets a link status change
268562306a36Sopenharmony_ci *  interrupt from the X557 PHY. This function configures the link speed
268662306a36Sopenharmony_ci *  between the PHYs to match the link speed of the BASE-T link.
268762306a36Sopenharmony_ci *
268862306a36Sopenharmony_ci * A return of a non-zero value indicates an error, and the base driver should
268962306a36Sopenharmony_ci * not report link up.
269062306a36Sopenharmony_ci **/
269162306a36Sopenharmony_cistatic s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
269262306a36Sopenharmony_ci{
269362306a36Sopenharmony_ci	ixgbe_link_speed force_speed;
269462306a36Sopenharmony_ci	bool link_up;
269562306a36Sopenharmony_ci	u32 status;
269662306a36Sopenharmony_ci	u16 speed;
269762306a36Sopenharmony_ci
269862306a36Sopenharmony_ci	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
269962306a36Sopenharmony_ci		return -EIO;
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ci	if (!(hw->mac.type == ixgbe_mac_X550EM_x &&
270262306a36Sopenharmony_ci	      !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))) {
270362306a36Sopenharmony_ci		speed = IXGBE_LINK_SPEED_10GB_FULL |
270462306a36Sopenharmony_ci			IXGBE_LINK_SPEED_1GB_FULL;
270562306a36Sopenharmony_ci		return ixgbe_setup_kr_speed_x550em(hw, speed);
270662306a36Sopenharmony_ci	}
270762306a36Sopenharmony_ci
270862306a36Sopenharmony_ci	/* If link is not up, then there is no setup necessary so return  */
270962306a36Sopenharmony_ci	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
271062306a36Sopenharmony_ci	if (status)
271162306a36Sopenharmony_ci		return status;
271262306a36Sopenharmony_ci
271362306a36Sopenharmony_ci	if (!link_up)
271462306a36Sopenharmony_ci		return 0;
271562306a36Sopenharmony_ci
271662306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
271762306a36Sopenharmony_ci				      MDIO_MMD_AN,
271862306a36Sopenharmony_ci				      &speed);
271962306a36Sopenharmony_ci	if (status)
272062306a36Sopenharmony_ci		return status;
272162306a36Sopenharmony_ci
272262306a36Sopenharmony_ci	/* If link is not still up, then no setup is necessary so return */
272362306a36Sopenharmony_ci	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
272462306a36Sopenharmony_ci	if (status)
272562306a36Sopenharmony_ci		return status;
272662306a36Sopenharmony_ci
272762306a36Sopenharmony_ci	if (!link_up)
272862306a36Sopenharmony_ci		return 0;
272962306a36Sopenharmony_ci
273062306a36Sopenharmony_ci	/* clear everything but the speed and duplex bits */
273162306a36Sopenharmony_ci	speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
273262306a36Sopenharmony_ci
273362306a36Sopenharmony_ci	switch (speed) {
273462306a36Sopenharmony_ci	case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
273562306a36Sopenharmony_ci		force_speed = IXGBE_LINK_SPEED_10GB_FULL;
273662306a36Sopenharmony_ci		break;
273762306a36Sopenharmony_ci	case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
273862306a36Sopenharmony_ci		force_speed = IXGBE_LINK_SPEED_1GB_FULL;
273962306a36Sopenharmony_ci		break;
274062306a36Sopenharmony_ci	default:
274162306a36Sopenharmony_ci		/* Internal PHY does not support anything else */
274262306a36Sopenharmony_ci		return -EINVAL;
274362306a36Sopenharmony_ci	}
274462306a36Sopenharmony_ci
274562306a36Sopenharmony_ci	return ixgbe_setup_ixfi_x550em(hw, &force_speed);
274662306a36Sopenharmony_ci}
274762306a36Sopenharmony_ci
274862306a36Sopenharmony_ci/** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI
274962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
275062306a36Sopenharmony_ci **/
275162306a36Sopenharmony_cistatic s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw)
275262306a36Sopenharmony_ci{
275362306a36Sopenharmony_ci	s32 status;
275462306a36Sopenharmony_ci
275562306a36Sopenharmony_ci	status = ixgbe_reset_phy_generic(hw);
275662306a36Sopenharmony_ci
275762306a36Sopenharmony_ci	if (status)
275862306a36Sopenharmony_ci		return status;
275962306a36Sopenharmony_ci
276062306a36Sopenharmony_ci	/* Configure Link Status Alarm and Temperature Threshold interrupts */
276162306a36Sopenharmony_ci	return ixgbe_enable_lasi_ext_t_x550em(hw);
276262306a36Sopenharmony_ci}
276362306a36Sopenharmony_ci
276462306a36Sopenharmony_ci/**
276562306a36Sopenharmony_ci *  ixgbe_led_on_t_x550em - Turns on the software controllable LEDs.
276662306a36Sopenharmony_ci *  @hw: pointer to hardware structure
276762306a36Sopenharmony_ci *  @led_idx: led number to turn on
276862306a36Sopenharmony_ci **/
276962306a36Sopenharmony_cistatic s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
277062306a36Sopenharmony_ci{
277162306a36Sopenharmony_ci	u16 phy_data;
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_ci	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
277462306a36Sopenharmony_ci		return -EINVAL;
277562306a36Sopenharmony_ci
277662306a36Sopenharmony_ci	/* To turn on the LED, set mode to ON. */
277762306a36Sopenharmony_ci	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
277862306a36Sopenharmony_ci			     MDIO_MMD_VEND1, &phy_data);
277962306a36Sopenharmony_ci	phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;
278062306a36Sopenharmony_ci	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
278162306a36Sopenharmony_ci			      MDIO_MMD_VEND1, phy_data);
278262306a36Sopenharmony_ci
278362306a36Sopenharmony_ci	return 0;
278462306a36Sopenharmony_ci}
278562306a36Sopenharmony_ci
278662306a36Sopenharmony_ci/**
278762306a36Sopenharmony_ci *  ixgbe_led_off_t_x550em - Turns off the software controllable LEDs.
278862306a36Sopenharmony_ci *  @hw: pointer to hardware structure
278962306a36Sopenharmony_ci *  @led_idx: led number to turn off
279062306a36Sopenharmony_ci **/
279162306a36Sopenharmony_cistatic s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
279262306a36Sopenharmony_ci{
279362306a36Sopenharmony_ci	u16 phy_data;
279462306a36Sopenharmony_ci
279562306a36Sopenharmony_ci	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
279662306a36Sopenharmony_ci		return -EINVAL;
279762306a36Sopenharmony_ci
279862306a36Sopenharmony_ci	/* To turn on the LED, set mode to ON. */
279962306a36Sopenharmony_ci	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
280062306a36Sopenharmony_ci			     MDIO_MMD_VEND1, &phy_data);
280162306a36Sopenharmony_ci	phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;
280262306a36Sopenharmony_ci	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
280362306a36Sopenharmony_ci			      MDIO_MMD_VEND1, phy_data);
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_ci	return 0;
280662306a36Sopenharmony_ci}
280762306a36Sopenharmony_ci
280862306a36Sopenharmony_ci/**
280962306a36Sopenharmony_ci *  ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware
281062306a36Sopenharmony_ci *  @hw: pointer to the HW structure
281162306a36Sopenharmony_ci *  @maj: driver version major number
281262306a36Sopenharmony_ci *  @min: driver version minor number
281362306a36Sopenharmony_ci *  @build: driver version build number
281462306a36Sopenharmony_ci *  @sub: driver version sub build number
281562306a36Sopenharmony_ci *  @len: length of driver_ver string
281662306a36Sopenharmony_ci *  @driver_ver: driver string
281762306a36Sopenharmony_ci *
281862306a36Sopenharmony_ci *  Sends driver version number to firmware through the manageability
281962306a36Sopenharmony_ci *  block.  On success return 0
282062306a36Sopenharmony_ci *  else returns -EBUSY when encountering an error acquiring
282162306a36Sopenharmony_ci *  semaphore, -EIO when command fails or -ENIVAL when incorrect
282262306a36Sopenharmony_ci *  params passed.
282362306a36Sopenharmony_ci **/
282462306a36Sopenharmony_cistatic s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
282562306a36Sopenharmony_ci				     u8 build, u8 sub, u16 len,
282662306a36Sopenharmony_ci				     const char *driver_ver)
282762306a36Sopenharmony_ci{
282862306a36Sopenharmony_ci	struct ixgbe_hic_drv_info2 fw_cmd;
282962306a36Sopenharmony_ci	s32 ret_val;
283062306a36Sopenharmony_ci	int i;
283162306a36Sopenharmony_ci
283262306a36Sopenharmony_ci	if (!len || !driver_ver || (len > sizeof(fw_cmd.driver_string)))
283362306a36Sopenharmony_ci		return -EINVAL;
283462306a36Sopenharmony_ci
283562306a36Sopenharmony_ci	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
283662306a36Sopenharmony_ci	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len;
283762306a36Sopenharmony_ci	fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
283862306a36Sopenharmony_ci	fw_cmd.port_num = (u8)hw->bus.func;
283962306a36Sopenharmony_ci	fw_cmd.ver_maj = maj;
284062306a36Sopenharmony_ci	fw_cmd.ver_min = min;
284162306a36Sopenharmony_ci	fw_cmd.ver_build = build;
284262306a36Sopenharmony_ci	fw_cmd.ver_sub = sub;
284362306a36Sopenharmony_ci	fw_cmd.hdr.checksum = 0;
284462306a36Sopenharmony_ci	memcpy(fw_cmd.driver_string, driver_ver, len);
284562306a36Sopenharmony_ci	fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
284662306a36Sopenharmony_ci			      (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_ci	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
284962306a36Sopenharmony_ci		ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
285062306a36Sopenharmony_ci						       sizeof(fw_cmd),
285162306a36Sopenharmony_ci						       IXGBE_HI_COMMAND_TIMEOUT,
285262306a36Sopenharmony_ci						       true);
285362306a36Sopenharmony_ci		if (ret_val)
285462306a36Sopenharmony_ci			continue;
285562306a36Sopenharmony_ci
285662306a36Sopenharmony_ci		if (fw_cmd.hdr.cmd_or_resp.ret_status !=
285762306a36Sopenharmony_ci		    FW_CEM_RESP_STATUS_SUCCESS)
285862306a36Sopenharmony_ci			return -EIO;
285962306a36Sopenharmony_ci		return 0;
286062306a36Sopenharmony_ci	}
286162306a36Sopenharmony_ci
286262306a36Sopenharmony_ci	return ret_val;
286362306a36Sopenharmony_ci}
286462306a36Sopenharmony_ci
286562306a36Sopenharmony_ci/** ixgbe_get_lcd_x550em - Determine lowest common denominator
286662306a36Sopenharmony_ci *  @hw: pointer to hardware structure
286762306a36Sopenharmony_ci *  @lcd_speed: pointer to lowest common link speed
286862306a36Sopenharmony_ci *
286962306a36Sopenharmony_ci *  Determine lowest common link speed with link partner.
287062306a36Sopenharmony_ci **/
287162306a36Sopenharmony_cistatic s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw,
287262306a36Sopenharmony_ci				  ixgbe_link_speed *lcd_speed)
287362306a36Sopenharmony_ci{
287462306a36Sopenharmony_ci	u16 an_lp_status;
287562306a36Sopenharmony_ci	s32 status;
287662306a36Sopenharmony_ci	u16 word = hw->eeprom.ctrl_word_3;
287762306a36Sopenharmony_ci
287862306a36Sopenharmony_ci	*lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
288162306a36Sopenharmony_ci				      MDIO_MMD_AN,
288262306a36Sopenharmony_ci				      &an_lp_status);
288362306a36Sopenharmony_ci	if (status)
288462306a36Sopenharmony_ci		return status;
288562306a36Sopenharmony_ci
288662306a36Sopenharmony_ci	/* If link partner advertised 1G, return 1G */
288762306a36Sopenharmony_ci	if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) {
288862306a36Sopenharmony_ci		*lcd_speed = IXGBE_LINK_SPEED_1GB_FULL;
288962306a36Sopenharmony_ci		return status;
289062306a36Sopenharmony_ci	}
289162306a36Sopenharmony_ci
289262306a36Sopenharmony_ci	/* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */
289362306a36Sopenharmony_ci	if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) ||
289462306a36Sopenharmony_ci	    (word & NVM_INIT_CTRL_3_D10GMP_PORT0))
289562306a36Sopenharmony_ci		return status;
289662306a36Sopenharmony_ci
289762306a36Sopenharmony_ci	/* Link partner not capable of lower speeds, return 10G */
289862306a36Sopenharmony_ci	*lcd_speed = IXGBE_LINK_SPEED_10GB_FULL;
289962306a36Sopenharmony_ci	return status;
290062306a36Sopenharmony_ci}
290162306a36Sopenharmony_ci
290262306a36Sopenharmony_ci/**
290362306a36Sopenharmony_ci * ixgbe_setup_fc_x550em - Set up flow control
290462306a36Sopenharmony_ci * @hw: pointer to hardware structure
290562306a36Sopenharmony_ci */
290662306a36Sopenharmony_cistatic s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw)
290762306a36Sopenharmony_ci{
290862306a36Sopenharmony_ci	bool pause, asm_dir;
290962306a36Sopenharmony_ci	u32 reg_val;
291062306a36Sopenharmony_ci	s32 rc = 0;
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_ci	/* Validate the requested mode */
291362306a36Sopenharmony_ci	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
291462306a36Sopenharmony_ci		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
291562306a36Sopenharmony_ci		return -EINVAL;
291662306a36Sopenharmony_ci	}
291762306a36Sopenharmony_ci
291862306a36Sopenharmony_ci	/* 10gig parts do not have a word in the EEPROM to determine the
291962306a36Sopenharmony_ci	 * default flow control setting, so we explicitly set it to full.
292062306a36Sopenharmony_ci	 */
292162306a36Sopenharmony_ci	if (hw->fc.requested_mode == ixgbe_fc_default)
292262306a36Sopenharmony_ci		hw->fc.requested_mode = ixgbe_fc_full;
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_ci	/* Determine PAUSE and ASM_DIR bits. */
292562306a36Sopenharmony_ci	switch (hw->fc.requested_mode) {
292662306a36Sopenharmony_ci	case ixgbe_fc_none:
292762306a36Sopenharmony_ci		pause = false;
292862306a36Sopenharmony_ci		asm_dir = false;
292962306a36Sopenharmony_ci		break;
293062306a36Sopenharmony_ci	case ixgbe_fc_tx_pause:
293162306a36Sopenharmony_ci		pause = false;
293262306a36Sopenharmony_ci		asm_dir = true;
293362306a36Sopenharmony_ci		break;
293462306a36Sopenharmony_ci	case ixgbe_fc_rx_pause:
293562306a36Sopenharmony_ci		/* Rx Flow control is enabled and Tx Flow control is
293662306a36Sopenharmony_ci		 * disabled by software override. Since there really
293762306a36Sopenharmony_ci		 * isn't a way to advertise that we are capable of RX
293862306a36Sopenharmony_ci		 * Pause ONLY, we will advertise that we support both
293962306a36Sopenharmony_ci		 * symmetric and asymmetric Rx PAUSE, as such we fall
294062306a36Sopenharmony_ci		 * through to the fc_full statement.  Later, we will
294162306a36Sopenharmony_ci		 * disable the adapter's ability to send PAUSE frames.
294262306a36Sopenharmony_ci		 */
294362306a36Sopenharmony_ci		fallthrough;
294462306a36Sopenharmony_ci	case ixgbe_fc_full:
294562306a36Sopenharmony_ci		pause = true;
294662306a36Sopenharmony_ci		asm_dir = true;
294762306a36Sopenharmony_ci		break;
294862306a36Sopenharmony_ci	default:
294962306a36Sopenharmony_ci		hw_err(hw, "Flow control param set incorrectly\n");
295062306a36Sopenharmony_ci		return -EIO;
295162306a36Sopenharmony_ci	}
295262306a36Sopenharmony_ci
295362306a36Sopenharmony_ci	switch (hw->device_id) {
295462306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_KR:
295562306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_KR:
295662306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_KR_L:
295762306a36Sopenharmony_ci		rc = hw->mac.ops.read_iosf_sb_reg(hw,
295862306a36Sopenharmony_ci					    IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
295962306a36Sopenharmony_ci					    IXGBE_SB_IOSF_TARGET_KR_PHY,
296062306a36Sopenharmony_ci					    &reg_val);
296162306a36Sopenharmony_ci		if (rc)
296262306a36Sopenharmony_ci			return rc;
296362306a36Sopenharmony_ci
296462306a36Sopenharmony_ci		reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
296562306a36Sopenharmony_ci			     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
296662306a36Sopenharmony_ci		if (pause)
296762306a36Sopenharmony_ci			reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
296862306a36Sopenharmony_ci		if (asm_dir)
296962306a36Sopenharmony_ci			reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
297062306a36Sopenharmony_ci		rc = hw->mac.ops.write_iosf_sb_reg(hw,
297162306a36Sopenharmony_ci					    IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
297262306a36Sopenharmony_ci					    IXGBE_SB_IOSF_TARGET_KR_PHY,
297362306a36Sopenharmony_ci					    reg_val);
297462306a36Sopenharmony_ci
297562306a36Sopenharmony_ci		/* This device does not fully support AN. */
297662306a36Sopenharmony_ci		hw->fc.disable_fc_autoneg = true;
297762306a36Sopenharmony_ci		break;
297862306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_XFI:
297962306a36Sopenharmony_ci		hw->fc.disable_fc_autoneg = true;
298062306a36Sopenharmony_ci		break;
298162306a36Sopenharmony_ci	default:
298262306a36Sopenharmony_ci		break;
298362306a36Sopenharmony_ci	}
298462306a36Sopenharmony_ci	return rc;
298562306a36Sopenharmony_ci}
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ci/**
298862306a36Sopenharmony_ci *  ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37
298962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
299062306a36Sopenharmony_ci **/
299162306a36Sopenharmony_cistatic void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
299262306a36Sopenharmony_ci{
299362306a36Sopenharmony_ci	u32 link_s1, lp_an_page_low, an_cntl_1;
299462306a36Sopenharmony_ci	ixgbe_link_speed speed;
299562306a36Sopenharmony_ci	s32 status = -EIO;
299662306a36Sopenharmony_ci	bool link_up;
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci	/* AN should have completed when the cable was plugged in.
299962306a36Sopenharmony_ci	 * Look for reasons to bail out.  Bail out if:
300062306a36Sopenharmony_ci	 * - FC autoneg is disabled, or if
300162306a36Sopenharmony_ci	 * - link is not up.
300262306a36Sopenharmony_ci	 */
300362306a36Sopenharmony_ci	if (hw->fc.disable_fc_autoneg) {
300462306a36Sopenharmony_ci		hw_err(hw, "Flow control autoneg is disabled");
300562306a36Sopenharmony_ci		goto out;
300662306a36Sopenharmony_ci	}
300762306a36Sopenharmony_ci
300862306a36Sopenharmony_ci	hw->mac.ops.check_link(hw, &speed, &link_up, false);
300962306a36Sopenharmony_ci	if (!link_up) {
301062306a36Sopenharmony_ci		hw_err(hw, "The link is down");
301162306a36Sopenharmony_ci		goto out;
301262306a36Sopenharmony_ci	}
301362306a36Sopenharmony_ci
301462306a36Sopenharmony_ci	/* Check at auto-negotiation has completed */
301562306a36Sopenharmony_ci	status = hw->mac.ops.read_iosf_sb_reg(hw,
301662306a36Sopenharmony_ci					IXGBE_KRM_LINK_S1(hw->bus.lan_id),
301762306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1);
301862306a36Sopenharmony_ci
301962306a36Sopenharmony_ci	if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
302062306a36Sopenharmony_ci		hw_dbg(hw, "Auto-Negotiation did not complete\n");
302162306a36Sopenharmony_ci		status = -EIO;
302262306a36Sopenharmony_ci		goto out;
302362306a36Sopenharmony_ci	}
302462306a36Sopenharmony_ci
302562306a36Sopenharmony_ci	/* Read the 10g AN autoc and LP ability registers and resolve
302662306a36Sopenharmony_ci	 * local flow control settings accordingly
302762306a36Sopenharmony_ci	 */
302862306a36Sopenharmony_ci	status = hw->mac.ops.read_iosf_sb_reg(hw,
302962306a36Sopenharmony_ci				IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
303062306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1);
303162306a36Sopenharmony_ci
303262306a36Sopenharmony_ci	if (status) {
303362306a36Sopenharmony_ci		hw_dbg(hw, "Auto-Negotiation did not complete\n");
303462306a36Sopenharmony_ci		goto out;
303562306a36Sopenharmony_ci	}
303662306a36Sopenharmony_ci
303762306a36Sopenharmony_ci	status = hw->mac.ops.read_iosf_sb_reg(hw,
303862306a36Sopenharmony_ci				IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id),
303962306a36Sopenharmony_ci				IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low);
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_ci	if (status) {
304262306a36Sopenharmony_ci		hw_dbg(hw, "Auto-Negotiation did not complete\n");
304362306a36Sopenharmony_ci		goto out;
304462306a36Sopenharmony_ci	}
304562306a36Sopenharmony_ci
304662306a36Sopenharmony_ci	status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low,
304762306a36Sopenharmony_ci				    IXGBE_KRM_AN_CNTL_1_SYM_PAUSE,
304862306a36Sopenharmony_ci				    IXGBE_KRM_AN_CNTL_1_ASM_PAUSE,
304962306a36Sopenharmony_ci				    IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE,
305062306a36Sopenharmony_ci				    IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE);
305162306a36Sopenharmony_ci
305262306a36Sopenharmony_ciout:
305362306a36Sopenharmony_ci	if (!status) {
305462306a36Sopenharmony_ci		hw->fc.fc_was_autonegged = true;
305562306a36Sopenharmony_ci	} else {
305662306a36Sopenharmony_ci		hw->fc.fc_was_autonegged = false;
305762306a36Sopenharmony_ci		hw->fc.current_mode = hw->fc.requested_mode;
305862306a36Sopenharmony_ci	}
305962306a36Sopenharmony_ci}
306062306a36Sopenharmony_ci
306162306a36Sopenharmony_ci/**
306262306a36Sopenharmony_ci *  ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings
306362306a36Sopenharmony_ci *  @hw: pointer to hardware structure
306462306a36Sopenharmony_ci **/
306562306a36Sopenharmony_cistatic void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw)
306662306a36Sopenharmony_ci{
306762306a36Sopenharmony_ci	hw->fc.fc_was_autonegged = false;
306862306a36Sopenharmony_ci	hw->fc.current_mode = hw->fc.requested_mode;
306962306a36Sopenharmony_ci}
307062306a36Sopenharmony_ci
307162306a36Sopenharmony_ci/** ixgbe_enter_lplu_x550em - Transition to low power states
307262306a36Sopenharmony_ci *  @hw: pointer to hardware structure
307362306a36Sopenharmony_ci *
307462306a36Sopenharmony_ci *  Configures Low Power Link Up on transition to low power states
307562306a36Sopenharmony_ci *  (from D0 to non-D0). Link is required to enter LPLU so avoid resetting
307662306a36Sopenharmony_ci *  the X557 PHY immediately prior to entering LPLU.
307762306a36Sopenharmony_ci **/
307862306a36Sopenharmony_cistatic s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
307962306a36Sopenharmony_ci{
308062306a36Sopenharmony_ci	u16 an_10g_cntl_reg, autoneg_reg, speed;
308162306a36Sopenharmony_ci	s32 status;
308262306a36Sopenharmony_ci	ixgbe_link_speed lcd_speed;
308362306a36Sopenharmony_ci	u32 save_autoneg;
308462306a36Sopenharmony_ci	bool link_up;
308562306a36Sopenharmony_ci
308662306a36Sopenharmony_ci	/* If blocked by MNG FW, then don't restart AN */
308762306a36Sopenharmony_ci	if (ixgbe_check_reset_blocked(hw))
308862306a36Sopenharmony_ci		return 0;
308962306a36Sopenharmony_ci
309062306a36Sopenharmony_ci	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
309162306a36Sopenharmony_ci	if (status)
309262306a36Sopenharmony_ci		return status;
309362306a36Sopenharmony_ci
309462306a36Sopenharmony_ci	status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3,
309562306a36Sopenharmony_ci				     &hw->eeprom.ctrl_word_3);
309662306a36Sopenharmony_ci	if (status)
309762306a36Sopenharmony_ci		return status;
309862306a36Sopenharmony_ci
309962306a36Sopenharmony_ci	/* If link is down, LPLU disabled in NVM, WoL disabled, or
310062306a36Sopenharmony_ci	 * manageability disabled, then force link down by entering
310162306a36Sopenharmony_ci	 * low power mode.
310262306a36Sopenharmony_ci	 */
310362306a36Sopenharmony_ci	if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
310462306a36Sopenharmony_ci	    !(hw->wol_enabled || ixgbe_mng_present(hw)))
310562306a36Sopenharmony_ci		return ixgbe_set_copper_phy_power(hw, false);
310662306a36Sopenharmony_ci
310762306a36Sopenharmony_ci	/* Determine LCD */
310862306a36Sopenharmony_ci	status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed);
310962306a36Sopenharmony_ci	if (status)
311062306a36Sopenharmony_ci		return status;
311162306a36Sopenharmony_ci
311262306a36Sopenharmony_ci	/* If no valid LCD link speed, then force link down and exit. */
311362306a36Sopenharmony_ci	if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN)
311462306a36Sopenharmony_ci		return ixgbe_set_copper_phy_power(hw, false);
311562306a36Sopenharmony_ci
311662306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
311762306a36Sopenharmony_ci				      MDIO_MMD_AN,
311862306a36Sopenharmony_ci				      &speed);
311962306a36Sopenharmony_ci	if (status)
312062306a36Sopenharmony_ci		return status;
312162306a36Sopenharmony_ci
312262306a36Sopenharmony_ci	/* If no link now, speed is invalid so take link down */
312362306a36Sopenharmony_ci	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
312462306a36Sopenharmony_ci	if (status)
312562306a36Sopenharmony_ci		return ixgbe_set_copper_phy_power(hw, false);
312662306a36Sopenharmony_ci
312762306a36Sopenharmony_ci	/* clear everything but the speed bits */
312862306a36Sopenharmony_ci	speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK;
312962306a36Sopenharmony_ci
313062306a36Sopenharmony_ci	/* If current speed is already LCD, then exit. */
313162306a36Sopenharmony_ci	if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) &&
313262306a36Sopenharmony_ci	     (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) ||
313362306a36Sopenharmony_ci	    ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) &&
313462306a36Sopenharmony_ci	     (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL)))
313562306a36Sopenharmony_ci		return status;
313662306a36Sopenharmony_ci
313762306a36Sopenharmony_ci	/* Clear AN completed indication */
313862306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
313962306a36Sopenharmony_ci				      MDIO_MMD_AN,
314062306a36Sopenharmony_ci				      &autoneg_reg);
314162306a36Sopenharmony_ci	if (status)
314262306a36Sopenharmony_ci		return status;
314362306a36Sopenharmony_ci
314462306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
314562306a36Sopenharmony_ci				      MDIO_MMD_AN,
314662306a36Sopenharmony_ci				      &an_10g_cntl_reg);
314762306a36Sopenharmony_ci	if (status)
314862306a36Sopenharmony_ci		return status;
314962306a36Sopenharmony_ci
315062306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw,
315162306a36Sopenharmony_ci				      IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
315262306a36Sopenharmony_ci				      MDIO_MMD_AN,
315362306a36Sopenharmony_ci				      &autoneg_reg);
315462306a36Sopenharmony_ci	if (status)
315562306a36Sopenharmony_ci		return status;
315662306a36Sopenharmony_ci
315762306a36Sopenharmony_ci	save_autoneg = hw->phy.autoneg_advertised;
315862306a36Sopenharmony_ci
315962306a36Sopenharmony_ci	/* Setup link at least common link speed */
316062306a36Sopenharmony_ci	status = hw->mac.ops.setup_link(hw, lcd_speed, false);
316162306a36Sopenharmony_ci
316262306a36Sopenharmony_ci	/* restore autoneg from before setting lplu speed */
316362306a36Sopenharmony_ci	hw->phy.autoneg_advertised = save_autoneg;
316462306a36Sopenharmony_ci
316562306a36Sopenharmony_ci	return status;
316662306a36Sopenharmony_ci}
316762306a36Sopenharmony_ci
316862306a36Sopenharmony_ci/**
316962306a36Sopenharmony_ci * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs
317062306a36Sopenharmony_ci * @hw: pointer to hardware structure
317162306a36Sopenharmony_ci */
317262306a36Sopenharmony_cistatic s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw)
317362306a36Sopenharmony_ci{
317462306a36Sopenharmony_ci	u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
317562306a36Sopenharmony_ci	s32 rc;
317662306a36Sopenharmony_ci
317762306a36Sopenharmony_ci	if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
317862306a36Sopenharmony_ci		return 0;
317962306a36Sopenharmony_ci
318062306a36Sopenharmony_ci	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store);
318162306a36Sopenharmony_ci	if (rc)
318262306a36Sopenharmony_ci		return rc;
318362306a36Sopenharmony_ci	memset(store, 0, sizeof(store));
318462306a36Sopenharmony_ci
318562306a36Sopenharmony_ci	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store);
318662306a36Sopenharmony_ci	if (rc)
318762306a36Sopenharmony_ci		return rc;
318862306a36Sopenharmony_ci
318962306a36Sopenharmony_ci	return ixgbe_setup_fw_link(hw);
319062306a36Sopenharmony_ci}
319162306a36Sopenharmony_ci
319262306a36Sopenharmony_ci/**
319362306a36Sopenharmony_ci * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp
319462306a36Sopenharmony_ci * @hw: pointer to hardware structure
319562306a36Sopenharmony_ci *
319662306a36Sopenharmony_ci * Return true when an overtemp event detected, otherwise false.
319762306a36Sopenharmony_ci */
319862306a36Sopenharmony_cistatic bool ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
319962306a36Sopenharmony_ci{
320062306a36Sopenharmony_ci	u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
320162306a36Sopenharmony_ci	s32 rc;
320262306a36Sopenharmony_ci
320362306a36Sopenharmony_ci	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);
320462306a36Sopenharmony_ci	if (rc)
320562306a36Sopenharmony_ci		return false;
320662306a36Sopenharmony_ci
320762306a36Sopenharmony_ci	if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {
320862306a36Sopenharmony_ci		ixgbe_shutdown_fw_phy(hw);
320962306a36Sopenharmony_ci		return true;
321062306a36Sopenharmony_ci	}
321162306a36Sopenharmony_ci	return false;
321262306a36Sopenharmony_ci}
321362306a36Sopenharmony_ci
321462306a36Sopenharmony_ci/**
321562306a36Sopenharmony_ci * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register
321662306a36Sopenharmony_ci * @hw: pointer to hardware structure
321762306a36Sopenharmony_ci *
321862306a36Sopenharmony_ci * Read NW_MNG_IF_SEL register and save field values.
321962306a36Sopenharmony_ci */
322062306a36Sopenharmony_cistatic void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw)
322162306a36Sopenharmony_ci{
322262306a36Sopenharmony_ci	/* Save NW management interface connected on board. This is used
322362306a36Sopenharmony_ci	 * to determine internal PHY mode.
322462306a36Sopenharmony_ci	 */
322562306a36Sopenharmony_ci	hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
322662306a36Sopenharmony_ci
322762306a36Sopenharmony_ci	/* If X552 (X550EM_a) and MDIO is connected to external PHY, then set
322862306a36Sopenharmony_ci	 * PHY address. This register field was has only been used for X552.
322962306a36Sopenharmony_ci	 */
323062306a36Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_x550em_a &&
323162306a36Sopenharmony_ci	    hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) {
323262306a36Sopenharmony_ci		hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel &
323362306a36Sopenharmony_ci				      IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
323462306a36Sopenharmony_ci				     IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
323562306a36Sopenharmony_ci	}
323662306a36Sopenharmony_ci}
323762306a36Sopenharmony_ci
323862306a36Sopenharmony_ci/** ixgbe_init_phy_ops_X550em - PHY/SFP specific init
323962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
324062306a36Sopenharmony_ci *
324162306a36Sopenharmony_ci *  Initialize any function pointers that were not able to be
324262306a36Sopenharmony_ci *  set during init_shared_code because the PHY/SFP type was
324362306a36Sopenharmony_ci *  not known.  Perform the SFP init if necessary.
324462306a36Sopenharmony_ci **/
324562306a36Sopenharmony_cistatic s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
324662306a36Sopenharmony_ci{
324762306a36Sopenharmony_ci	struct ixgbe_phy_info *phy = &hw->phy;
324862306a36Sopenharmony_ci	s32 ret_val;
324962306a36Sopenharmony_ci
325062306a36Sopenharmony_ci	hw->mac.ops.set_lan_id(hw);
325162306a36Sopenharmony_ci
325262306a36Sopenharmony_ci	ixgbe_read_mng_if_sel_x550em(hw);
325362306a36Sopenharmony_ci
325462306a36Sopenharmony_ci	if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) {
325562306a36Sopenharmony_ci		phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
325662306a36Sopenharmony_ci		ixgbe_setup_mux_ctl(hw);
325762306a36Sopenharmony_ci	}
325862306a36Sopenharmony_ci
325962306a36Sopenharmony_ci	/* Identify the PHY or SFP module */
326062306a36Sopenharmony_ci	ret_val = phy->ops.identify(hw);
326162306a36Sopenharmony_ci	if (ret_val == -EOPNOTSUPP || ret_val == -EFAULT)
326262306a36Sopenharmony_ci		return ret_val;
326362306a36Sopenharmony_ci
326462306a36Sopenharmony_ci	/* Setup function pointers based on detected hardware */
326562306a36Sopenharmony_ci	ixgbe_init_mac_link_ops_X550em(hw);
326662306a36Sopenharmony_ci	if (phy->sfp_type != ixgbe_sfp_type_unknown)
326762306a36Sopenharmony_ci		phy->ops.reset = NULL;
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ci	/* Set functions pointers based on phy type */
327062306a36Sopenharmony_ci	switch (hw->phy.type) {
327162306a36Sopenharmony_ci	case ixgbe_phy_x550em_kx4:
327262306a36Sopenharmony_ci		phy->ops.setup_link = NULL;
327362306a36Sopenharmony_ci		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
327462306a36Sopenharmony_ci		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
327562306a36Sopenharmony_ci		break;
327662306a36Sopenharmony_ci	case ixgbe_phy_x550em_kr:
327762306a36Sopenharmony_ci		phy->ops.setup_link = ixgbe_setup_kr_x550em;
327862306a36Sopenharmony_ci		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
327962306a36Sopenharmony_ci		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
328062306a36Sopenharmony_ci		break;
328162306a36Sopenharmony_ci	case ixgbe_phy_x550em_xfi:
328262306a36Sopenharmony_ci		/* link is managed by HW */
328362306a36Sopenharmony_ci		phy->ops.setup_link = NULL;
328462306a36Sopenharmony_ci		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
328562306a36Sopenharmony_ci		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
328662306a36Sopenharmony_ci		break;
328762306a36Sopenharmony_ci	case ixgbe_phy_x550em_ext_t:
328862306a36Sopenharmony_ci		/* Save NW management interface connected on board. This is used
328962306a36Sopenharmony_ci		 * to determine internal PHY mode
329062306a36Sopenharmony_ci		 */
329162306a36Sopenharmony_ci		phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
329262306a36Sopenharmony_ci
329362306a36Sopenharmony_ci		/* If internal link mode is XFI, then setup iXFI internal link,
329462306a36Sopenharmony_ci		 * else setup KR now.
329562306a36Sopenharmony_ci		 */
329662306a36Sopenharmony_ci		phy->ops.setup_internal_link =
329762306a36Sopenharmony_ci					      ixgbe_setup_internal_phy_t_x550em;
329862306a36Sopenharmony_ci
329962306a36Sopenharmony_ci		/* setup SW LPLU only for first revision */
330062306a36Sopenharmony_ci		if (hw->mac.type == ixgbe_mac_X550EM_x &&
330162306a36Sopenharmony_ci		    !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) &
330262306a36Sopenharmony_ci		      IXGBE_FUSES0_REV_MASK))
330362306a36Sopenharmony_ci			phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
330462306a36Sopenharmony_ci
330562306a36Sopenharmony_ci		phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
330662306a36Sopenharmony_ci		phy->ops.reset = ixgbe_reset_phy_t_X550em;
330762306a36Sopenharmony_ci		break;
330862306a36Sopenharmony_ci	case ixgbe_phy_sgmii:
330962306a36Sopenharmony_ci		phy->ops.setup_link = NULL;
331062306a36Sopenharmony_ci		break;
331162306a36Sopenharmony_ci	case ixgbe_phy_fw:
331262306a36Sopenharmony_ci		phy->ops.setup_link = ixgbe_setup_fw_link;
331362306a36Sopenharmony_ci		phy->ops.reset = ixgbe_reset_phy_fw;
331462306a36Sopenharmony_ci		break;
331562306a36Sopenharmony_ci	case ixgbe_phy_ext_1g_t:
331662306a36Sopenharmony_ci		phy->ops.setup_link = NULL;
331762306a36Sopenharmony_ci		phy->ops.read_reg = NULL;
331862306a36Sopenharmony_ci		phy->ops.write_reg = NULL;
331962306a36Sopenharmony_ci		phy->ops.reset = NULL;
332062306a36Sopenharmony_ci		break;
332162306a36Sopenharmony_ci	default:
332262306a36Sopenharmony_ci		break;
332362306a36Sopenharmony_ci	}
332462306a36Sopenharmony_ci
332562306a36Sopenharmony_ci	return ret_val;
332662306a36Sopenharmony_ci}
332762306a36Sopenharmony_ci
332862306a36Sopenharmony_ci/** ixgbe_get_media_type_X550em - Get media type
332962306a36Sopenharmony_ci *  @hw: pointer to hardware structure
333062306a36Sopenharmony_ci *
333162306a36Sopenharmony_ci *  Returns the media type (fiber, copper, backplane)
333262306a36Sopenharmony_ci *
333362306a36Sopenharmony_ci */
333462306a36Sopenharmony_cistatic enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
333562306a36Sopenharmony_ci{
333662306a36Sopenharmony_ci	enum ixgbe_media_type media_type;
333762306a36Sopenharmony_ci
333862306a36Sopenharmony_ci	/* Detect if there is a copper PHY attached. */
333962306a36Sopenharmony_ci	switch (hw->device_id) {
334062306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_SGMII:
334162306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_SGMII_L:
334262306a36Sopenharmony_ci		hw->phy.type = ixgbe_phy_sgmii;
334362306a36Sopenharmony_ci		fallthrough;
334462306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_KR:
334562306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_KX4:
334662306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_XFI:
334762306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_KR:
334862306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_KR_L:
334962306a36Sopenharmony_ci		media_type = ixgbe_media_type_backplane;
335062306a36Sopenharmony_ci		break;
335162306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_SFP:
335262306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_SFP:
335362306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_SFP_N:
335462306a36Sopenharmony_ci		media_type = ixgbe_media_type_fiber;
335562306a36Sopenharmony_ci		break;
335662306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_1G_T:
335762306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_10G_T:
335862306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_10G_T:
335962306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_1G_T:
336062306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
336162306a36Sopenharmony_ci		media_type = ixgbe_media_type_copper;
336262306a36Sopenharmony_ci		break;
336362306a36Sopenharmony_ci	default:
336462306a36Sopenharmony_ci		media_type = ixgbe_media_type_unknown;
336562306a36Sopenharmony_ci		break;
336662306a36Sopenharmony_ci	}
336762306a36Sopenharmony_ci	return media_type;
336862306a36Sopenharmony_ci}
336962306a36Sopenharmony_ci
337062306a36Sopenharmony_ci/** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY.
337162306a36Sopenharmony_ci ** @hw: pointer to hardware structure
337262306a36Sopenharmony_ci **/
337362306a36Sopenharmony_cistatic s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
337462306a36Sopenharmony_ci{
337562306a36Sopenharmony_ci	s32 status;
337662306a36Sopenharmony_ci	u16 reg;
337762306a36Sopenharmony_ci
337862306a36Sopenharmony_ci	status = hw->phy.ops.read_reg(hw,
337962306a36Sopenharmony_ci				      IXGBE_MDIO_TX_VENDOR_ALARMS_3,
338062306a36Sopenharmony_ci				      MDIO_MMD_PMAPMD,
338162306a36Sopenharmony_ci				      &reg);
338262306a36Sopenharmony_ci	if (status)
338362306a36Sopenharmony_ci		return status;
338462306a36Sopenharmony_ci
338562306a36Sopenharmony_ci	/* If PHY FW reset completed bit is set then this is the first
338662306a36Sopenharmony_ci	 * SW instance after a power on so the PHY FW must be un-stalled.
338762306a36Sopenharmony_ci	 */
338862306a36Sopenharmony_ci	if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
338962306a36Sopenharmony_ci		status = hw->phy.ops.read_reg(hw,
339062306a36Sopenharmony_ci					IXGBE_MDIO_GLOBAL_RES_PR_10,
339162306a36Sopenharmony_ci					MDIO_MMD_VEND1,
339262306a36Sopenharmony_ci					&reg);
339362306a36Sopenharmony_ci		if (status)
339462306a36Sopenharmony_ci			return status;
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_ci		reg &= ~IXGBE_MDIO_POWER_UP_STALL;
339762306a36Sopenharmony_ci
339862306a36Sopenharmony_ci		status = hw->phy.ops.write_reg(hw,
339962306a36Sopenharmony_ci					IXGBE_MDIO_GLOBAL_RES_PR_10,
340062306a36Sopenharmony_ci					MDIO_MMD_VEND1,
340162306a36Sopenharmony_ci					reg);
340262306a36Sopenharmony_ci		if (status)
340362306a36Sopenharmony_ci			return status;
340462306a36Sopenharmony_ci	}
340562306a36Sopenharmony_ci
340662306a36Sopenharmony_ci	return status;
340762306a36Sopenharmony_ci}
340862306a36Sopenharmony_ci
340962306a36Sopenharmony_ci/**
341062306a36Sopenharmony_ci * ixgbe_set_mdio_speed - Set MDIO clock speed
341162306a36Sopenharmony_ci * @hw: pointer to hardware structure
341262306a36Sopenharmony_ci */
341362306a36Sopenharmony_cistatic void ixgbe_set_mdio_speed(struct ixgbe_hw *hw)
341462306a36Sopenharmony_ci{
341562306a36Sopenharmony_ci	u32 hlreg0;
341662306a36Sopenharmony_ci
341762306a36Sopenharmony_ci	switch (hw->device_id) {
341862306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_X_10G_T:
341962306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_SGMII:
342062306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_SGMII_L:
342162306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_10G_T:
342262306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_SFP:
342362306a36Sopenharmony_ci		/* Config MDIO clock speed before the first MDIO PHY access */
342462306a36Sopenharmony_ci		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
342562306a36Sopenharmony_ci		hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
342662306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
342762306a36Sopenharmony_ci		break;
342862306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_1G_T:
342962306a36Sopenharmony_ci	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
343062306a36Sopenharmony_ci		/* Select fast MDIO clock speed for these devices */
343162306a36Sopenharmony_ci		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
343262306a36Sopenharmony_ci		hlreg0 |= IXGBE_HLREG0_MDCSPD;
343362306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
343462306a36Sopenharmony_ci		break;
343562306a36Sopenharmony_ci	default:
343662306a36Sopenharmony_ci		break;
343762306a36Sopenharmony_ci	}
343862306a36Sopenharmony_ci}
343962306a36Sopenharmony_ci
344062306a36Sopenharmony_ci/**  ixgbe_reset_hw_X550em - Perform hardware reset
344162306a36Sopenharmony_ci **  @hw: pointer to hardware structure
344262306a36Sopenharmony_ci **
344362306a36Sopenharmony_ci **  Resets the hardware by resetting the transmit and receive units, masks
344462306a36Sopenharmony_ci **  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
344562306a36Sopenharmony_ci **  reset.
344662306a36Sopenharmony_ci **/
344762306a36Sopenharmony_cistatic s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
344862306a36Sopenharmony_ci{
344962306a36Sopenharmony_ci	ixgbe_link_speed link_speed;
345062306a36Sopenharmony_ci	s32 status;
345162306a36Sopenharmony_ci	u32 ctrl = 0;
345262306a36Sopenharmony_ci	u32 i;
345362306a36Sopenharmony_ci	bool link_up = false;
345462306a36Sopenharmony_ci	u32 swfw_mask = hw->phy.phy_semaphore_mask;
345562306a36Sopenharmony_ci
345662306a36Sopenharmony_ci	/* Call adapter stop to disable Tx/Rx and clear interrupts */
345762306a36Sopenharmony_ci	status = hw->mac.ops.stop_adapter(hw);
345862306a36Sopenharmony_ci	if (status)
345962306a36Sopenharmony_ci		return status;
346062306a36Sopenharmony_ci
346162306a36Sopenharmony_ci	/* flush pending Tx transactions */
346262306a36Sopenharmony_ci	ixgbe_clear_tx_pending(hw);
346362306a36Sopenharmony_ci
346462306a36Sopenharmony_ci	/* set MDIO speed before talking to the PHY in case it's the 1st time */
346562306a36Sopenharmony_ci	ixgbe_set_mdio_speed(hw);
346662306a36Sopenharmony_ci
346762306a36Sopenharmony_ci	/* PHY ops must be identified and initialized prior to reset */
346862306a36Sopenharmony_ci	status = hw->phy.ops.init(hw);
346962306a36Sopenharmony_ci	if (status == -EOPNOTSUPP || status == -EFAULT)
347062306a36Sopenharmony_ci		return status;
347162306a36Sopenharmony_ci
347262306a36Sopenharmony_ci	/* start the external PHY */
347362306a36Sopenharmony_ci	if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
347462306a36Sopenharmony_ci		status = ixgbe_init_ext_t_x550em(hw);
347562306a36Sopenharmony_ci		if (status)
347662306a36Sopenharmony_ci			return status;
347762306a36Sopenharmony_ci	}
347862306a36Sopenharmony_ci
347962306a36Sopenharmony_ci	/* Setup SFP module if there is one present. */
348062306a36Sopenharmony_ci	if (hw->phy.sfp_setup_needed) {
348162306a36Sopenharmony_ci		status = hw->mac.ops.setup_sfp(hw);
348262306a36Sopenharmony_ci		hw->phy.sfp_setup_needed = false;
348362306a36Sopenharmony_ci	}
348462306a36Sopenharmony_ci
348562306a36Sopenharmony_ci	if (status == -EOPNOTSUPP)
348662306a36Sopenharmony_ci		return status;
348762306a36Sopenharmony_ci
348862306a36Sopenharmony_ci	/* Reset PHY */
348962306a36Sopenharmony_ci	if (!hw->phy.reset_disable && hw->phy.ops.reset)
349062306a36Sopenharmony_ci		hw->phy.ops.reset(hw);
349162306a36Sopenharmony_ci
349262306a36Sopenharmony_cimac_reset_top:
349362306a36Sopenharmony_ci	/* Issue global reset to the MAC.  Needs to be SW reset if link is up.
349462306a36Sopenharmony_ci	 * If link reset is used when link is up, it might reset the PHY when
349562306a36Sopenharmony_ci	 * mng is using it.  If link is down or the flag to force full link
349662306a36Sopenharmony_ci	 * reset is set, then perform link reset.
349762306a36Sopenharmony_ci	 */
349862306a36Sopenharmony_ci	ctrl = IXGBE_CTRL_LNK_RST;
349962306a36Sopenharmony_ci
350062306a36Sopenharmony_ci	if (!hw->force_full_reset) {
350162306a36Sopenharmony_ci		hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
350262306a36Sopenharmony_ci		if (link_up)
350362306a36Sopenharmony_ci			ctrl = IXGBE_CTRL_RST;
350462306a36Sopenharmony_ci	}
350562306a36Sopenharmony_ci
350662306a36Sopenharmony_ci	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
350762306a36Sopenharmony_ci	if (status) {
350862306a36Sopenharmony_ci		hw_dbg(hw, "semaphore failed with %d", status);
350962306a36Sopenharmony_ci		return -EBUSY;
351062306a36Sopenharmony_ci	}
351162306a36Sopenharmony_ci
351262306a36Sopenharmony_ci	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
351362306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
351462306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
351562306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
351662306a36Sopenharmony_ci	usleep_range(1000, 1200);
351762306a36Sopenharmony_ci
351862306a36Sopenharmony_ci	/* Poll for reset bit to self-clear meaning reset is complete */
351962306a36Sopenharmony_ci	for (i = 0; i < 10; i++) {
352062306a36Sopenharmony_ci		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
352162306a36Sopenharmony_ci		if (!(ctrl & IXGBE_CTRL_RST_MASK))
352262306a36Sopenharmony_ci			break;
352362306a36Sopenharmony_ci		udelay(1);
352462306a36Sopenharmony_ci	}
352562306a36Sopenharmony_ci
352662306a36Sopenharmony_ci	if (ctrl & IXGBE_CTRL_RST_MASK) {
352762306a36Sopenharmony_ci		status = -EIO;
352862306a36Sopenharmony_ci		hw_dbg(hw, "Reset polling failed to complete.\n");
352962306a36Sopenharmony_ci	}
353062306a36Sopenharmony_ci
353162306a36Sopenharmony_ci	msleep(50);
353262306a36Sopenharmony_ci
353362306a36Sopenharmony_ci	/* Double resets are required for recovery from certain error
353462306a36Sopenharmony_ci	 * clear the multicast table.  Also reset num_rar_entries to 128,
353562306a36Sopenharmony_ci	 * since we modify this value when programming the SAN MAC address.
353662306a36Sopenharmony_ci	 */
353762306a36Sopenharmony_ci	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
353862306a36Sopenharmony_ci		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
353962306a36Sopenharmony_ci		goto mac_reset_top;
354062306a36Sopenharmony_ci	}
354162306a36Sopenharmony_ci
354262306a36Sopenharmony_ci	/* Store the permanent mac address */
354362306a36Sopenharmony_ci	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
354462306a36Sopenharmony_ci
354562306a36Sopenharmony_ci	/* Store MAC address from RAR0, clear receive address registers, and
354662306a36Sopenharmony_ci	 * clear the multicast table.  Also reset num_rar_entries to 128,
354762306a36Sopenharmony_ci	 * since we modify this value when programming the SAN MAC address.
354862306a36Sopenharmony_ci	 */
354962306a36Sopenharmony_ci	hw->mac.num_rar_entries = 128;
355062306a36Sopenharmony_ci	hw->mac.ops.init_rx_addrs(hw);
355162306a36Sopenharmony_ci
355262306a36Sopenharmony_ci	ixgbe_set_mdio_speed(hw);
355362306a36Sopenharmony_ci
355462306a36Sopenharmony_ci	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
355562306a36Sopenharmony_ci		ixgbe_setup_mux_ctl(hw);
355662306a36Sopenharmony_ci
355762306a36Sopenharmony_ci	return status;
355862306a36Sopenharmony_ci}
355962306a36Sopenharmony_ci
356062306a36Sopenharmony_ci/** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype
356162306a36Sopenharmony_ci *	anti-spoofing
356262306a36Sopenharmony_ci *  @hw:  pointer to hardware structure
356362306a36Sopenharmony_ci *  @enable: enable or disable switch for Ethertype anti-spoofing
356462306a36Sopenharmony_ci *  @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing
356562306a36Sopenharmony_ci **/
356662306a36Sopenharmony_cistatic void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
356762306a36Sopenharmony_ci						   bool enable, int vf)
356862306a36Sopenharmony_ci{
356962306a36Sopenharmony_ci	int vf_target_reg = vf >> 3;
357062306a36Sopenharmony_ci	int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT;
357162306a36Sopenharmony_ci	u32 pfvfspoof;
357262306a36Sopenharmony_ci
357362306a36Sopenharmony_ci	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
357462306a36Sopenharmony_ci	if (enable)
357562306a36Sopenharmony_ci		pfvfspoof |= BIT(vf_target_shift);
357662306a36Sopenharmony_ci	else
357762306a36Sopenharmony_ci		pfvfspoof &= ~BIT(vf_target_shift);
357862306a36Sopenharmony_ci
357962306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
358062306a36Sopenharmony_ci}
358162306a36Sopenharmony_ci
358262306a36Sopenharmony_ci/** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning
358362306a36Sopenharmony_ci *  @hw: pointer to hardware structure
358462306a36Sopenharmony_ci *  @enable: enable or disable source address pruning
358562306a36Sopenharmony_ci *  @pool: Rx pool to set source address pruning for
358662306a36Sopenharmony_ci **/
358762306a36Sopenharmony_cistatic void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
358862306a36Sopenharmony_ci						  bool enable,
358962306a36Sopenharmony_ci						  unsigned int pool)
359062306a36Sopenharmony_ci{
359162306a36Sopenharmony_ci	u64 pfflp;
359262306a36Sopenharmony_ci
359362306a36Sopenharmony_ci	/* max rx pool is 63 */
359462306a36Sopenharmony_ci	if (pool > 63)
359562306a36Sopenharmony_ci		return;
359662306a36Sopenharmony_ci
359762306a36Sopenharmony_ci	pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL);
359862306a36Sopenharmony_ci	pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32;
359962306a36Sopenharmony_ci
360062306a36Sopenharmony_ci	if (enable)
360162306a36Sopenharmony_ci		pfflp |= (1ULL << pool);
360262306a36Sopenharmony_ci	else
360362306a36Sopenharmony_ci		pfflp &= ~(1ULL << pool);
360462306a36Sopenharmony_ci
360562306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp);
360662306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32));
360762306a36Sopenharmony_ci}
360862306a36Sopenharmony_ci
360962306a36Sopenharmony_ci/**
361062306a36Sopenharmony_ci *  ixgbe_setup_fc_backplane_x550em_a - Set up flow control
361162306a36Sopenharmony_ci *  @hw: pointer to hardware structure
361262306a36Sopenharmony_ci *
361362306a36Sopenharmony_ci *  Called at init time to set up flow control.
361462306a36Sopenharmony_ci **/
361562306a36Sopenharmony_cistatic s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw)
361662306a36Sopenharmony_ci{
361762306a36Sopenharmony_ci	s32 status = 0;
361862306a36Sopenharmony_ci	u32 an_cntl = 0;
361962306a36Sopenharmony_ci
362062306a36Sopenharmony_ci	/* Validate the requested mode */
362162306a36Sopenharmony_ci	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
362262306a36Sopenharmony_ci		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
362362306a36Sopenharmony_ci		return -EINVAL;
362462306a36Sopenharmony_ci	}
362562306a36Sopenharmony_ci
362662306a36Sopenharmony_ci	if (hw->fc.requested_mode == ixgbe_fc_default)
362762306a36Sopenharmony_ci		hw->fc.requested_mode = ixgbe_fc_full;
362862306a36Sopenharmony_ci
362962306a36Sopenharmony_ci	/* Set up the 1G and 10G flow control advertisement registers so the
363062306a36Sopenharmony_ci	 * HW will be able to do FC autoneg once the cable is plugged in.  If
363162306a36Sopenharmony_ci	 * we link at 10G, the 1G advertisement is harmless and vice versa.
363262306a36Sopenharmony_ci	 */
363362306a36Sopenharmony_ci	status = hw->mac.ops.read_iosf_sb_reg(hw,
363462306a36Sopenharmony_ci					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
363562306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl);
363662306a36Sopenharmony_ci
363762306a36Sopenharmony_ci	if (status) {
363862306a36Sopenharmony_ci		hw_dbg(hw, "Auto-Negotiation did not complete\n");
363962306a36Sopenharmony_ci		return status;
364062306a36Sopenharmony_ci	}
364162306a36Sopenharmony_ci
364262306a36Sopenharmony_ci	/* The possible values of fc.requested_mode are:
364362306a36Sopenharmony_ci	 * 0: Flow control is completely disabled
364462306a36Sopenharmony_ci	 * 1: Rx flow control is enabled (we can receive pause frames,
364562306a36Sopenharmony_ci	 *    but not send pause frames).
364662306a36Sopenharmony_ci	 * 2: Tx flow control is enabled (we can send pause frames but
364762306a36Sopenharmony_ci	 *    we do not support receiving pause frames).
364862306a36Sopenharmony_ci	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
364962306a36Sopenharmony_ci	 * other: Invalid.
365062306a36Sopenharmony_ci	 */
365162306a36Sopenharmony_ci	switch (hw->fc.requested_mode) {
365262306a36Sopenharmony_ci	case ixgbe_fc_none:
365362306a36Sopenharmony_ci		/* Flow control completely disabled by software override. */
365462306a36Sopenharmony_ci		an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
365562306a36Sopenharmony_ci			     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
365662306a36Sopenharmony_ci		break;
365762306a36Sopenharmony_ci	case ixgbe_fc_tx_pause:
365862306a36Sopenharmony_ci		/* Tx Flow control is enabled, and Rx Flow control is
365962306a36Sopenharmony_ci		 * disabled by software override.
366062306a36Sopenharmony_ci		 */
366162306a36Sopenharmony_ci		an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
366262306a36Sopenharmony_ci		an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
366362306a36Sopenharmony_ci		break;
366462306a36Sopenharmony_ci	case ixgbe_fc_rx_pause:
366562306a36Sopenharmony_ci		/* Rx Flow control is enabled and Tx Flow control is
366662306a36Sopenharmony_ci		 * disabled by software override. Since there really
366762306a36Sopenharmony_ci		 * isn't a way to advertise that we are capable of RX
366862306a36Sopenharmony_ci		 * Pause ONLY, we will advertise that we support both
366962306a36Sopenharmony_ci		 * symmetric and asymmetric Rx PAUSE, as such we fall
367062306a36Sopenharmony_ci		 * through to the fc_full statement.  Later, we will
367162306a36Sopenharmony_ci		 * disable the adapter's ability to send PAUSE frames.
367262306a36Sopenharmony_ci		 */
367362306a36Sopenharmony_ci	case ixgbe_fc_full:
367462306a36Sopenharmony_ci		/* Flow control (both Rx and Tx) is enabled by SW override. */
367562306a36Sopenharmony_ci		an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
367662306a36Sopenharmony_ci			   IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
367762306a36Sopenharmony_ci		break;
367862306a36Sopenharmony_ci	default:
367962306a36Sopenharmony_ci		hw_err(hw, "Flow control param set incorrectly\n");
368062306a36Sopenharmony_ci		return -EIO;
368162306a36Sopenharmony_ci	}
368262306a36Sopenharmony_ci
368362306a36Sopenharmony_ci	status = hw->mac.ops.write_iosf_sb_reg(hw,
368462306a36Sopenharmony_ci					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
368562306a36Sopenharmony_ci					IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl);
368662306a36Sopenharmony_ci
368762306a36Sopenharmony_ci	/* Restart auto-negotiation. */
368862306a36Sopenharmony_ci	status = ixgbe_restart_an_internal_phy_x550em(hw);
368962306a36Sopenharmony_ci
369062306a36Sopenharmony_ci	return status;
369162306a36Sopenharmony_ci}
369262306a36Sopenharmony_ci
369362306a36Sopenharmony_ci/**
369462306a36Sopenharmony_ci * ixgbe_set_mux - Set mux for port 1 access with CS4227
369562306a36Sopenharmony_ci * @hw: pointer to hardware structure
369662306a36Sopenharmony_ci * @state: set mux if 1, clear if 0
369762306a36Sopenharmony_ci */
369862306a36Sopenharmony_cistatic void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state)
369962306a36Sopenharmony_ci{
370062306a36Sopenharmony_ci	u32 esdp;
370162306a36Sopenharmony_ci
370262306a36Sopenharmony_ci	if (!hw->bus.lan_id)
370362306a36Sopenharmony_ci		return;
370462306a36Sopenharmony_ci	esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
370562306a36Sopenharmony_ci	if (state)
370662306a36Sopenharmony_ci		esdp |= IXGBE_ESDP_SDP1;
370762306a36Sopenharmony_ci	else
370862306a36Sopenharmony_ci		esdp &= ~IXGBE_ESDP_SDP1;
370962306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
371062306a36Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
371162306a36Sopenharmony_ci}
371262306a36Sopenharmony_ci
371362306a36Sopenharmony_ci/**
371462306a36Sopenharmony_ci * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore
371562306a36Sopenharmony_ci * @hw: pointer to hardware structure
371662306a36Sopenharmony_ci * @mask: Mask to specify which semaphore to acquire
371762306a36Sopenharmony_ci *
371862306a36Sopenharmony_ci * Acquires the SWFW semaphore and sets the I2C MUX
371962306a36Sopenharmony_ci */
372062306a36Sopenharmony_cistatic s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
372162306a36Sopenharmony_ci{
372262306a36Sopenharmony_ci	s32 status;
372362306a36Sopenharmony_ci
372462306a36Sopenharmony_ci	status = ixgbe_acquire_swfw_sync_X540(hw, mask);
372562306a36Sopenharmony_ci	if (status)
372662306a36Sopenharmony_ci		return status;
372762306a36Sopenharmony_ci
372862306a36Sopenharmony_ci	if (mask & IXGBE_GSSR_I2C_MASK)
372962306a36Sopenharmony_ci		ixgbe_set_mux(hw, 1);
373062306a36Sopenharmony_ci
373162306a36Sopenharmony_ci	return 0;
373262306a36Sopenharmony_ci}
373362306a36Sopenharmony_ci
373462306a36Sopenharmony_ci/**
373562306a36Sopenharmony_ci * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore
373662306a36Sopenharmony_ci * @hw: pointer to hardware structure
373762306a36Sopenharmony_ci * @mask: Mask to specify which semaphore to release
373862306a36Sopenharmony_ci *
373962306a36Sopenharmony_ci * Releases the SWFW semaphore and sets the I2C MUX
374062306a36Sopenharmony_ci */
374162306a36Sopenharmony_cistatic void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
374262306a36Sopenharmony_ci{
374362306a36Sopenharmony_ci	if (mask & IXGBE_GSSR_I2C_MASK)
374462306a36Sopenharmony_ci		ixgbe_set_mux(hw, 0);
374562306a36Sopenharmony_ci
374662306a36Sopenharmony_ci	ixgbe_release_swfw_sync_X540(hw, mask);
374762306a36Sopenharmony_ci}
374862306a36Sopenharmony_ci
374962306a36Sopenharmony_ci/**
375062306a36Sopenharmony_ci * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore
375162306a36Sopenharmony_ci * @hw: pointer to hardware structure
375262306a36Sopenharmony_ci * @mask: Mask to specify which semaphore to acquire
375362306a36Sopenharmony_ci *
375462306a36Sopenharmony_ci * Acquires the SWFW semaphore and get the shared PHY token as needed
375562306a36Sopenharmony_ci */
375662306a36Sopenharmony_cistatic s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask)
375762306a36Sopenharmony_ci{
375862306a36Sopenharmony_ci	u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
375962306a36Sopenharmony_ci	int retries = FW_PHY_TOKEN_RETRIES;
376062306a36Sopenharmony_ci	s32 status;
376162306a36Sopenharmony_ci
376262306a36Sopenharmony_ci	while (--retries) {
376362306a36Sopenharmony_ci		status = 0;
376462306a36Sopenharmony_ci		if (hmask)
376562306a36Sopenharmony_ci			status = ixgbe_acquire_swfw_sync_X540(hw, hmask);
376662306a36Sopenharmony_ci		if (status)
376762306a36Sopenharmony_ci			return status;
376862306a36Sopenharmony_ci		if (!(mask & IXGBE_GSSR_TOKEN_SM))
376962306a36Sopenharmony_ci			return 0;
377062306a36Sopenharmony_ci
377162306a36Sopenharmony_ci		status = ixgbe_get_phy_token(hw);
377262306a36Sopenharmony_ci		if (!status)
377362306a36Sopenharmony_ci			return 0;
377462306a36Sopenharmony_ci		if (hmask)
377562306a36Sopenharmony_ci			ixgbe_release_swfw_sync_X540(hw, hmask);
377662306a36Sopenharmony_ci		if (status != -EAGAIN)
377762306a36Sopenharmony_ci			return status;
377862306a36Sopenharmony_ci		msleep(FW_PHY_TOKEN_DELAY);
377962306a36Sopenharmony_ci	}
378062306a36Sopenharmony_ci
378162306a36Sopenharmony_ci	return status;
378262306a36Sopenharmony_ci}
378362306a36Sopenharmony_ci
378462306a36Sopenharmony_ci/**
378562306a36Sopenharmony_ci * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore
378662306a36Sopenharmony_ci * @hw: pointer to hardware structure
378762306a36Sopenharmony_ci * @mask: Mask to specify which semaphore to release
378862306a36Sopenharmony_ci *
378962306a36Sopenharmony_ci * Release the SWFW semaphore and puts the shared PHY token as needed
379062306a36Sopenharmony_ci */
379162306a36Sopenharmony_cistatic void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask)
379262306a36Sopenharmony_ci{
379362306a36Sopenharmony_ci	u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
379462306a36Sopenharmony_ci
379562306a36Sopenharmony_ci	if (mask & IXGBE_GSSR_TOKEN_SM)
379662306a36Sopenharmony_ci		ixgbe_put_phy_token(hw);
379762306a36Sopenharmony_ci
379862306a36Sopenharmony_ci	if (hmask)
379962306a36Sopenharmony_ci		ixgbe_release_swfw_sync_X540(hw, hmask);
380062306a36Sopenharmony_ci}
380162306a36Sopenharmony_ci
380262306a36Sopenharmony_ci/**
380362306a36Sopenharmony_ci * ixgbe_read_phy_reg_x550a - Reads specified PHY register
380462306a36Sopenharmony_ci * @hw: pointer to hardware structure
380562306a36Sopenharmony_ci * @reg_addr: 32 bit address of PHY register to read
380662306a36Sopenharmony_ci * @device_type: 5 bit device type
380762306a36Sopenharmony_ci * @phy_data: Pointer to read data from PHY register
380862306a36Sopenharmony_ci *
380962306a36Sopenharmony_ci * Reads a value from a specified PHY register using the SWFW lock and PHY
381062306a36Sopenharmony_ci * Token. The PHY Token is needed since the MDIO is shared between to MAC
381162306a36Sopenharmony_ci * instances.
381262306a36Sopenharmony_ci */
381362306a36Sopenharmony_cistatic s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
381462306a36Sopenharmony_ci				    u32 device_type, u16 *phy_data)
381562306a36Sopenharmony_ci{
381662306a36Sopenharmony_ci	u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
381762306a36Sopenharmony_ci	s32 status;
381862306a36Sopenharmony_ci
381962306a36Sopenharmony_ci	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
382062306a36Sopenharmony_ci		return -EBUSY;
382162306a36Sopenharmony_ci
382262306a36Sopenharmony_ci	status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data);
382362306a36Sopenharmony_ci
382462306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, mask);
382562306a36Sopenharmony_ci
382662306a36Sopenharmony_ci	return status;
382762306a36Sopenharmony_ci}
382862306a36Sopenharmony_ci
382962306a36Sopenharmony_ci/**
383062306a36Sopenharmony_ci * ixgbe_write_phy_reg_x550a - Writes specified PHY register
383162306a36Sopenharmony_ci * @hw: pointer to hardware structure
383262306a36Sopenharmony_ci * @reg_addr: 32 bit PHY register to write
383362306a36Sopenharmony_ci * @device_type: 5 bit device type
383462306a36Sopenharmony_ci * @phy_data: Data to write to the PHY register
383562306a36Sopenharmony_ci *
383662306a36Sopenharmony_ci * Writes a value to specified PHY register using the SWFW lock and PHY Token.
383762306a36Sopenharmony_ci * The PHY Token is needed since the MDIO is shared between to MAC instances.
383862306a36Sopenharmony_ci */
383962306a36Sopenharmony_cistatic s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
384062306a36Sopenharmony_ci				     u32 device_type, u16 phy_data)
384162306a36Sopenharmony_ci{
384262306a36Sopenharmony_ci	u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
384362306a36Sopenharmony_ci	s32 status;
384462306a36Sopenharmony_ci
384562306a36Sopenharmony_ci	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
384662306a36Sopenharmony_ci		return -EBUSY;
384762306a36Sopenharmony_ci
384862306a36Sopenharmony_ci	status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data);
384962306a36Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, mask);
385062306a36Sopenharmony_ci
385162306a36Sopenharmony_ci	return status;
385262306a36Sopenharmony_ci}
385362306a36Sopenharmony_ci
385462306a36Sopenharmony_ci#define X550_COMMON_MAC \
385562306a36Sopenharmony_ci	.init_hw			= &ixgbe_init_hw_generic, \
385662306a36Sopenharmony_ci	.start_hw			= &ixgbe_start_hw_X540, \
385762306a36Sopenharmony_ci	.clear_hw_cntrs			= &ixgbe_clear_hw_cntrs_generic, \
385862306a36Sopenharmony_ci	.enable_rx_dma			= &ixgbe_enable_rx_dma_generic, \
385962306a36Sopenharmony_ci	.get_mac_addr			= &ixgbe_get_mac_addr_generic, \
386062306a36Sopenharmony_ci	.get_device_caps		= &ixgbe_get_device_caps_generic, \
386162306a36Sopenharmony_ci	.stop_adapter			= &ixgbe_stop_adapter_generic, \
386262306a36Sopenharmony_ci	.set_lan_id			= &ixgbe_set_lan_id_multi_port_pcie, \
386362306a36Sopenharmony_ci	.read_analog_reg8		= NULL, \
386462306a36Sopenharmony_ci	.write_analog_reg8		= NULL, \
386562306a36Sopenharmony_ci	.set_rxpba			= &ixgbe_set_rxpba_generic, \
386662306a36Sopenharmony_ci	.check_link			= &ixgbe_check_mac_link_generic, \
386762306a36Sopenharmony_ci	.blink_led_start		= &ixgbe_blink_led_start_X540, \
386862306a36Sopenharmony_ci	.blink_led_stop			= &ixgbe_blink_led_stop_X540, \
386962306a36Sopenharmony_ci	.set_rar			= &ixgbe_set_rar_generic, \
387062306a36Sopenharmony_ci	.clear_rar			= &ixgbe_clear_rar_generic, \
387162306a36Sopenharmony_ci	.set_vmdq			= &ixgbe_set_vmdq_generic, \
387262306a36Sopenharmony_ci	.set_vmdq_san_mac		= &ixgbe_set_vmdq_san_mac_generic, \
387362306a36Sopenharmony_ci	.clear_vmdq			= &ixgbe_clear_vmdq_generic, \
387462306a36Sopenharmony_ci	.init_rx_addrs			= &ixgbe_init_rx_addrs_generic, \
387562306a36Sopenharmony_ci	.update_mc_addr_list		= &ixgbe_update_mc_addr_list_generic, \
387662306a36Sopenharmony_ci	.enable_mc			= &ixgbe_enable_mc_generic, \
387762306a36Sopenharmony_ci	.disable_mc			= &ixgbe_disable_mc_generic, \
387862306a36Sopenharmony_ci	.clear_vfta			= &ixgbe_clear_vfta_generic, \
387962306a36Sopenharmony_ci	.set_vfta			= &ixgbe_set_vfta_generic, \
388062306a36Sopenharmony_ci	.fc_enable			= &ixgbe_fc_enable_generic, \
388162306a36Sopenharmony_ci	.set_fw_drv_ver			= &ixgbe_set_fw_drv_ver_x550, \
388262306a36Sopenharmony_ci	.init_uta_tables		= &ixgbe_init_uta_tables_generic, \
388362306a36Sopenharmony_ci	.set_mac_anti_spoofing		= &ixgbe_set_mac_anti_spoofing, \
388462306a36Sopenharmony_ci	.set_vlan_anti_spoofing		= &ixgbe_set_vlan_anti_spoofing, \
388562306a36Sopenharmony_ci	.set_source_address_pruning	= \
388662306a36Sopenharmony_ci				&ixgbe_set_source_address_pruning_X550, \
388762306a36Sopenharmony_ci	.set_ethertype_anti_spoofing	= \
388862306a36Sopenharmony_ci				&ixgbe_set_ethertype_anti_spoofing_X550, \
388962306a36Sopenharmony_ci	.disable_rx_buff		= &ixgbe_disable_rx_buff_generic, \
389062306a36Sopenharmony_ci	.enable_rx_buff			= &ixgbe_enable_rx_buff_generic, \
389162306a36Sopenharmony_ci	.get_thermal_sensor_data	= NULL, \
389262306a36Sopenharmony_ci	.init_thermal_sensor_thresh	= NULL, \
389362306a36Sopenharmony_ci	.fw_recovery_mode		= &ixgbe_fw_recovery_mode_X550, \
389462306a36Sopenharmony_ci	.enable_rx			= &ixgbe_enable_rx_generic, \
389562306a36Sopenharmony_ci	.disable_rx			= &ixgbe_disable_rx_x550, \
389662306a36Sopenharmony_ci
389762306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_X550 = {
389862306a36Sopenharmony_ci	X550_COMMON_MAC
389962306a36Sopenharmony_ci	.led_on			= ixgbe_led_on_generic,
390062306a36Sopenharmony_ci	.led_off		= ixgbe_led_off_generic,
390162306a36Sopenharmony_ci	.init_led_link_act	= ixgbe_init_led_link_act_generic,
390262306a36Sopenharmony_ci	.reset_hw		= &ixgbe_reset_hw_X540,
390362306a36Sopenharmony_ci	.get_media_type		= &ixgbe_get_media_type_X540,
390462306a36Sopenharmony_ci	.get_san_mac_addr	= &ixgbe_get_san_mac_addr_generic,
390562306a36Sopenharmony_ci	.get_wwn_prefix		= &ixgbe_get_wwn_prefix_generic,
390662306a36Sopenharmony_ci	.setup_link		= &ixgbe_setup_mac_link_X540,
390762306a36Sopenharmony_ci	.get_link_capabilities	= &ixgbe_get_copper_link_capabilities_generic,
390862306a36Sopenharmony_ci	.get_bus_info		= &ixgbe_get_bus_info_generic,
390962306a36Sopenharmony_ci	.setup_sfp		= NULL,
391062306a36Sopenharmony_ci	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X540,
391162306a36Sopenharmony_ci	.release_swfw_sync	= &ixgbe_release_swfw_sync_X540,
391262306a36Sopenharmony_ci	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
391362306a36Sopenharmony_ci	.prot_autoc_read	= prot_autoc_read_generic,
391462306a36Sopenharmony_ci	.prot_autoc_write	= prot_autoc_write_generic,
391562306a36Sopenharmony_ci	.setup_fc		= ixgbe_setup_fc_generic,
391662306a36Sopenharmony_ci	.fc_autoneg		= ixgbe_fc_autoneg,
391762306a36Sopenharmony_ci};
391862306a36Sopenharmony_ci
391962306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_X550EM_x = {
392062306a36Sopenharmony_ci	X550_COMMON_MAC
392162306a36Sopenharmony_ci	.led_on			= ixgbe_led_on_t_x550em,
392262306a36Sopenharmony_ci	.led_off		= ixgbe_led_off_t_x550em,
392362306a36Sopenharmony_ci	.init_led_link_act	= ixgbe_init_led_link_act_generic,
392462306a36Sopenharmony_ci	.reset_hw		= &ixgbe_reset_hw_X550em,
392562306a36Sopenharmony_ci	.get_media_type		= &ixgbe_get_media_type_X550em,
392662306a36Sopenharmony_ci	.get_san_mac_addr	= NULL,
392762306a36Sopenharmony_ci	.get_wwn_prefix		= NULL,
392862306a36Sopenharmony_ci	.setup_link		= &ixgbe_setup_mac_link_X540,
392962306a36Sopenharmony_ci	.get_link_capabilities	= &ixgbe_get_link_capabilities_X550em,
393062306a36Sopenharmony_ci	.get_bus_info		= &ixgbe_get_bus_info_X550em,
393162306a36Sopenharmony_ci	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
393262306a36Sopenharmony_ci	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X550em,
393362306a36Sopenharmony_ci	.release_swfw_sync	= &ixgbe_release_swfw_sync_X550em,
393462306a36Sopenharmony_ci	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
393562306a36Sopenharmony_ci	.setup_fc		= NULL, /* defined later */
393662306a36Sopenharmony_ci	.fc_autoneg		= ixgbe_fc_autoneg,
393762306a36Sopenharmony_ci	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550,
393862306a36Sopenharmony_ci	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550,
393962306a36Sopenharmony_ci};
394062306a36Sopenharmony_ci
394162306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_X550EM_x_fw = {
394262306a36Sopenharmony_ci	X550_COMMON_MAC
394362306a36Sopenharmony_ci	.led_on			= NULL,
394462306a36Sopenharmony_ci	.led_off		= NULL,
394562306a36Sopenharmony_ci	.init_led_link_act	= NULL,
394662306a36Sopenharmony_ci	.reset_hw		= &ixgbe_reset_hw_X550em,
394762306a36Sopenharmony_ci	.get_media_type		= &ixgbe_get_media_type_X550em,
394862306a36Sopenharmony_ci	.get_san_mac_addr	= NULL,
394962306a36Sopenharmony_ci	.get_wwn_prefix		= NULL,
395062306a36Sopenharmony_ci	.setup_link		= &ixgbe_setup_mac_link_X540,
395162306a36Sopenharmony_ci	.get_link_capabilities	= &ixgbe_get_link_capabilities_X550em,
395262306a36Sopenharmony_ci	.get_bus_info		= &ixgbe_get_bus_info_X550em,
395362306a36Sopenharmony_ci	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
395462306a36Sopenharmony_ci	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X550em,
395562306a36Sopenharmony_ci	.release_swfw_sync	= &ixgbe_release_swfw_sync_X550em,
395662306a36Sopenharmony_ci	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
395762306a36Sopenharmony_ci	.setup_fc		= NULL,
395862306a36Sopenharmony_ci	.fc_autoneg		= ixgbe_fc_autoneg,
395962306a36Sopenharmony_ci	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550,
396062306a36Sopenharmony_ci	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550,
396162306a36Sopenharmony_ci};
396262306a36Sopenharmony_ci
396362306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_x550em_a = {
396462306a36Sopenharmony_ci	X550_COMMON_MAC
396562306a36Sopenharmony_ci	.led_on			= ixgbe_led_on_t_x550em,
396662306a36Sopenharmony_ci	.led_off		= ixgbe_led_off_t_x550em,
396762306a36Sopenharmony_ci	.init_led_link_act	= ixgbe_init_led_link_act_generic,
396862306a36Sopenharmony_ci	.reset_hw		= ixgbe_reset_hw_X550em,
396962306a36Sopenharmony_ci	.get_media_type		= ixgbe_get_media_type_X550em,
397062306a36Sopenharmony_ci	.get_san_mac_addr	= NULL,
397162306a36Sopenharmony_ci	.get_wwn_prefix		= NULL,
397262306a36Sopenharmony_ci	.setup_link		= &ixgbe_setup_mac_link_X540,
397362306a36Sopenharmony_ci	.get_link_capabilities	= ixgbe_get_link_capabilities_X550em,
397462306a36Sopenharmony_ci	.get_bus_info		= ixgbe_get_bus_info_X550em,
397562306a36Sopenharmony_ci	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
397662306a36Sopenharmony_ci	.acquire_swfw_sync	= ixgbe_acquire_swfw_sync_x550em_a,
397762306a36Sopenharmony_ci	.release_swfw_sync	= ixgbe_release_swfw_sync_x550em_a,
397862306a36Sopenharmony_ci	.setup_fc		= ixgbe_setup_fc_x550em,
397962306a36Sopenharmony_ci	.fc_autoneg		= ixgbe_fc_autoneg,
398062306a36Sopenharmony_ci	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550a,
398162306a36Sopenharmony_ci	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550a,
398262306a36Sopenharmony_ci};
398362306a36Sopenharmony_ci
398462306a36Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_x550em_a_fw = {
398562306a36Sopenharmony_ci	X550_COMMON_MAC
398662306a36Sopenharmony_ci	.led_on			= ixgbe_led_on_generic,
398762306a36Sopenharmony_ci	.led_off		= ixgbe_led_off_generic,
398862306a36Sopenharmony_ci	.init_led_link_act	= ixgbe_init_led_link_act_generic,
398962306a36Sopenharmony_ci	.reset_hw		= ixgbe_reset_hw_X550em,
399062306a36Sopenharmony_ci	.get_media_type		= ixgbe_get_media_type_X550em,
399162306a36Sopenharmony_ci	.get_san_mac_addr	= NULL,
399262306a36Sopenharmony_ci	.get_wwn_prefix		= NULL,
399362306a36Sopenharmony_ci	.setup_link		= NULL, /* defined later */
399462306a36Sopenharmony_ci	.get_link_capabilities	= ixgbe_get_link_capabilities_X550em,
399562306a36Sopenharmony_ci	.get_bus_info		= ixgbe_get_bus_info_X550em,
399662306a36Sopenharmony_ci	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
399762306a36Sopenharmony_ci	.acquire_swfw_sync	= ixgbe_acquire_swfw_sync_x550em_a,
399862306a36Sopenharmony_ci	.release_swfw_sync	= ixgbe_release_swfw_sync_x550em_a,
399962306a36Sopenharmony_ci	.setup_fc		= ixgbe_setup_fc_x550em,
400062306a36Sopenharmony_ci	.fc_autoneg		= ixgbe_fc_autoneg,
400162306a36Sopenharmony_ci	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550a,
400262306a36Sopenharmony_ci	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550a,
400362306a36Sopenharmony_ci};
400462306a36Sopenharmony_ci
400562306a36Sopenharmony_ci#define X550_COMMON_EEP \
400662306a36Sopenharmony_ci	.read			= &ixgbe_read_ee_hostif_X550, \
400762306a36Sopenharmony_ci	.read_buffer		= &ixgbe_read_ee_hostif_buffer_X550, \
400862306a36Sopenharmony_ci	.write			= &ixgbe_write_ee_hostif_X550, \
400962306a36Sopenharmony_ci	.write_buffer		= &ixgbe_write_ee_hostif_buffer_X550, \
401062306a36Sopenharmony_ci	.validate_checksum	= &ixgbe_validate_eeprom_checksum_X550, \
401162306a36Sopenharmony_ci	.update_checksum	= &ixgbe_update_eeprom_checksum_X550, \
401262306a36Sopenharmony_ci	.calc_checksum		= &ixgbe_calc_eeprom_checksum_X550, \
401362306a36Sopenharmony_ci
401462306a36Sopenharmony_cistatic const struct ixgbe_eeprom_operations eeprom_ops_X550 = {
401562306a36Sopenharmony_ci	X550_COMMON_EEP
401662306a36Sopenharmony_ci	.init_params		= &ixgbe_init_eeprom_params_X550,
401762306a36Sopenharmony_ci};
401862306a36Sopenharmony_ci
401962306a36Sopenharmony_cistatic const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = {
402062306a36Sopenharmony_ci	X550_COMMON_EEP
402162306a36Sopenharmony_ci	.init_params		= &ixgbe_init_eeprom_params_X540,
402262306a36Sopenharmony_ci};
402362306a36Sopenharmony_ci
402462306a36Sopenharmony_ci#define X550_COMMON_PHY	\
402562306a36Sopenharmony_ci	.identify_sfp		= &ixgbe_identify_module_generic, \
402662306a36Sopenharmony_ci	.reset			= NULL, \
402762306a36Sopenharmony_ci	.setup_link_speed	= &ixgbe_setup_phy_link_speed_generic, \
402862306a36Sopenharmony_ci	.read_i2c_byte		= &ixgbe_read_i2c_byte_generic, \
402962306a36Sopenharmony_ci	.write_i2c_byte		= &ixgbe_write_i2c_byte_generic, \
403062306a36Sopenharmony_ci	.read_i2c_sff8472	= &ixgbe_read_i2c_sff8472_generic, \
403162306a36Sopenharmony_ci	.read_i2c_eeprom	= &ixgbe_read_i2c_eeprom_generic, \
403262306a36Sopenharmony_ci	.write_i2c_eeprom	= &ixgbe_write_i2c_eeprom_generic, \
403362306a36Sopenharmony_ci	.setup_link		= &ixgbe_setup_phy_link_generic, \
403462306a36Sopenharmony_ci	.set_phy_power		= NULL,
403562306a36Sopenharmony_ci
403662306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_X550 = {
403762306a36Sopenharmony_ci	X550_COMMON_PHY
403862306a36Sopenharmony_ci	.check_overtemp		= &ixgbe_tn_check_overtemp,
403962306a36Sopenharmony_ci	.init			= NULL,
404062306a36Sopenharmony_ci	.identify		= &ixgbe_identify_phy_generic,
404162306a36Sopenharmony_ci	.read_reg		= &ixgbe_read_phy_reg_generic,
404262306a36Sopenharmony_ci	.write_reg		= &ixgbe_write_phy_reg_generic,
404362306a36Sopenharmony_ci};
404462306a36Sopenharmony_ci
404562306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_X550EM_x = {
404662306a36Sopenharmony_ci	X550_COMMON_PHY
404762306a36Sopenharmony_ci	.check_overtemp		= &ixgbe_tn_check_overtemp,
404862306a36Sopenharmony_ci	.init			= &ixgbe_init_phy_ops_X550em,
404962306a36Sopenharmony_ci	.identify		= &ixgbe_identify_phy_x550em,
405062306a36Sopenharmony_ci	.read_reg		= &ixgbe_read_phy_reg_generic,
405162306a36Sopenharmony_ci	.write_reg		= &ixgbe_write_phy_reg_generic,
405262306a36Sopenharmony_ci};
405362306a36Sopenharmony_ci
405462306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_x550em_x_fw = {
405562306a36Sopenharmony_ci	X550_COMMON_PHY
405662306a36Sopenharmony_ci	.check_overtemp		= NULL,
405762306a36Sopenharmony_ci	.init			= ixgbe_init_phy_ops_X550em,
405862306a36Sopenharmony_ci	.identify		= ixgbe_identify_phy_x550em,
405962306a36Sopenharmony_ci	.read_reg		= NULL,
406062306a36Sopenharmony_ci	.write_reg		= NULL,
406162306a36Sopenharmony_ci	.read_reg_mdi		= NULL,
406262306a36Sopenharmony_ci	.write_reg_mdi		= NULL,
406362306a36Sopenharmony_ci};
406462306a36Sopenharmony_ci
406562306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_x550em_a = {
406662306a36Sopenharmony_ci	X550_COMMON_PHY
406762306a36Sopenharmony_ci	.check_overtemp		= &ixgbe_tn_check_overtemp,
406862306a36Sopenharmony_ci	.init			= &ixgbe_init_phy_ops_X550em,
406962306a36Sopenharmony_ci	.identify		= &ixgbe_identify_phy_x550em,
407062306a36Sopenharmony_ci	.read_reg		= &ixgbe_read_phy_reg_x550a,
407162306a36Sopenharmony_ci	.write_reg		= &ixgbe_write_phy_reg_x550a,
407262306a36Sopenharmony_ci	.read_reg_mdi		= &ixgbe_read_phy_reg_mdi,
407362306a36Sopenharmony_ci	.write_reg_mdi		= &ixgbe_write_phy_reg_mdi,
407462306a36Sopenharmony_ci};
407562306a36Sopenharmony_ci
407662306a36Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_x550em_a_fw = {
407762306a36Sopenharmony_ci	X550_COMMON_PHY
407862306a36Sopenharmony_ci	.check_overtemp		= ixgbe_check_overtemp_fw,
407962306a36Sopenharmony_ci	.init			= ixgbe_init_phy_ops_X550em,
408062306a36Sopenharmony_ci	.identify		= ixgbe_identify_phy_fw,
408162306a36Sopenharmony_ci	.read_reg		= NULL,
408262306a36Sopenharmony_ci	.write_reg		= NULL,
408362306a36Sopenharmony_ci	.read_reg_mdi		= NULL,
408462306a36Sopenharmony_ci	.write_reg_mdi		= NULL,
408562306a36Sopenharmony_ci};
408662306a36Sopenharmony_ci
408762306a36Sopenharmony_cistatic const struct ixgbe_link_operations link_ops_x550em_x = {
408862306a36Sopenharmony_ci	.read_link		= &ixgbe_read_i2c_combined_generic,
408962306a36Sopenharmony_ci	.read_link_unlocked	= &ixgbe_read_i2c_combined_generic_unlocked,
409062306a36Sopenharmony_ci	.write_link		= &ixgbe_write_i2c_combined_generic,
409162306a36Sopenharmony_ci	.write_link_unlocked	= &ixgbe_write_i2c_combined_generic_unlocked,
409262306a36Sopenharmony_ci};
409362306a36Sopenharmony_ci
409462306a36Sopenharmony_cistatic const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = {
409562306a36Sopenharmony_ci	IXGBE_MVALS_INIT(X550)
409662306a36Sopenharmony_ci};
409762306a36Sopenharmony_ci
409862306a36Sopenharmony_cistatic const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = {
409962306a36Sopenharmony_ci	IXGBE_MVALS_INIT(X550EM_x)
410062306a36Sopenharmony_ci};
410162306a36Sopenharmony_ci
410262306a36Sopenharmony_cistatic const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = {
410362306a36Sopenharmony_ci	IXGBE_MVALS_INIT(X550EM_a)
410462306a36Sopenharmony_ci};
410562306a36Sopenharmony_ci
410662306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_X550_info = {
410762306a36Sopenharmony_ci	.mac			= ixgbe_mac_X550,
410862306a36Sopenharmony_ci	.get_invariants		= &ixgbe_get_invariants_X540,
410962306a36Sopenharmony_ci	.mac_ops		= &mac_ops_X550,
411062306a36Sopenharmony_ci	.eeprom_ops		= &eeprom_ops_X550,
411162306a36Sopenharmony_ci	.phy_ops		= &phy_ops_X550,
411262306a36Sopenharmony_ci	.mbx_ops		= &mbx_ops_generic,
411362306a36Sopenharmony_ci	.mvals			= ixgbe_mvals_X550,
411462306a36Sopenharmony_ci};
411562306a36Sopenharmony_ci
411662306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_X550EM_x_info = {
411762306a36Sopenharmony_ci	.mac			= ixgbe_mac_X550EM_x,
411862306a36Sopenharmony_ci	.get_invariants		= &ixgbe_get_invariants_X550_x,
411962306a36Sopenharmony_ci	.mac_ops		= &mac_ops_X550EM_x,
412062306a36Sopenharmony_ci	.eeprom_ops		= &eeprom_ops_X550EM_x,
412162306a36Sopenharmony_ci	.phy_ops		= &phy_ops_X550EM_x,
412262306a36Sopenharmony_ci	.mbx_ops		= &mbx_ops_generic,
412362306a36Sopenharmony_ci	.mvals			= ixgbe_mvals_X550EM_x,
412462306a36Sopenharmony_ci	.link_ops		= &link_ops_x550em_x,
412562306a36Sopenharmony_ci};
412662306a36Sopenharmony_ci
412762306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_x550em_x_fw_info = {
412862306a36Sopenharmony_ci	.mac			= ixgbe_mac_X550EM_x,
412962306a36Sopenharmony_ci	.get_invariants		= ixgbe_get_invariants_X550_x_fw,
413062306a36Sopenharmony_ci	.mac_ops		= &mac_ops_X550EM_x_fw,
413162306a36Sopenharmony_ci	.eeprom_ops		= &eeprom_ops_X550EM_x,
413262306a36Sopenharmony_ci	.phy_ops		= &phy_ops_x550em_x_fw,
413362306a36Sopenharmony_ci	.mbx_ops		= &mbx_ops_generic,
413462306a36Sopenharmony_ci	.mvals			= ixgbe_mvals_X550EM_x,
413562306a36Sopenharmony_ci};
413662306a36Sopenharmony_ci
413762306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_x550em_a_info = {
413862306a36Sopenharmony_ci	.mac			= ixgbe_mac_x550em_a,
413962306a36Sopenharmony_ci	.get_invariants		= &ixgbe_get_invariants_X550_a,
414062306a36Sopenharmony_ci	.mac_ops		= &mac_ops_x550em_a,
414162306a36Sopenharmony_ci	.eeprom_ops		= &eeprom_ops_X550EM_x,
414262306a36Sopenharmony_ci	.phy_ops		= &phy_ops_x550em_a,
414362306a36Sopenharmony_ci	.mbx_ops		= &mbx_ops_generic,
414462306a36Sopenharmony_ci	.mvals			= ixgbe_mvals_x550em_a,
414562306a36Sopenharmony_ci};
414662306a36Sopenharmony_ci
414762306a36Sopenharmony_ciconst struct ixgbe_info ixgbe_x550em_a_fw_info = {
414862306a36Sopenharmony_ci	.mac			= ixgbe_mac_x550em_a,
414962306a36Sopenharmony_ci	.get_invariants		= ixgbe_get_invariants_X550_a_fw,
415062306a36Sopenharmony_ci	.mac_ops		= &mac_ops_x550em_a_fw,
415162306a36Sopenharmony_ci	.eeprom_ops		= &eeprom_ops_X550EM_x,
415262306a36Sopenharmony_ci	.phy_ops		= &phy_ops_x550em_a_fw,
415362306a36Sopenharmony_ci	.mbx_ops		= &mbx_ops_generic,
415462306a36Sopenharmony_ci	.mvals			= ixgbe_mvals_x550em_a,
415562306a36Sopenharmony_ci};
4156