18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/pci.h>
58c2ecf20Sopenharmony_ci#include <linux/delay.h>
68c2ecf20Sopenharmony_ci#include <linux/sched.h>
78c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "ixgbe.h"
108c2ecf20Sopenharmony_ci#include "ixgbe_common.h"
118c2ecf20Sopenharmony_ci#include "ixgbe_phy.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistatic s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw);
148c2ecf20Sopenharmony_cistatic s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);
158c2ecf20Sopenharmony_cistatic void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw);
168c2ecf20Sopenharmony_cistatic s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw);
178c2ecf20Sopenharmony_cistatic void ixgbe_standby_eeprom(struct ixgbe_hw *hw);
188c2ecf20Sopenharmony_cistatic void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
198c2ecf20Sopenharmony_ci					u16 count);
208c2ecf20Sopenharmony_cistatic u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count);
218c2ecf20Sopenharmony_cistatic void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
228c2ecf20Sopenharmony_cistatic void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
238c2ecf20Sopenharmony_cistatic void ixgbe_release_eeprom(struct ixgbe_hw *hw);
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
268c2ecf20Sopenharmony_cistatic s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
278c2ecf20Sopenharmony_cistatic s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
288c2ecf20Sopenharmony_ci					     u16 words, u16 *data);
298c2ecf20Sopenharmony_cistatic s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
308c2ecf20Sopenharmony_ci					     u16 words, u16 *data);
318c2ecf20Sopenharmony_cistatic s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
328c2ecf20Sopenharmony_ci						 u16 offset);
338c2ecf20Sopenharmony_cistatic s32 ixgbe_disable_pcie_primary(struct ixgbe_hw *hw);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/* Base table for registers values that change by MAC */
368c2ecf20Sopenharmony_ciconst u32 ixgbe_mvals_8259X[IXGBE_MVALS_IDX_LIMIT] = {
378c2ecf20Sopenharmony_ci	IXGBE_MVALS_INIT(8259X)
388c2ecf20Sopenharmony_ci};
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/**
418c2ecf20Sopenharmony_ci *  ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
428c2ecf20Sopenharmony_ci *  control
438c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
448c2ecf20Sopenharmony_ci *
458c2ecf20Sopenharmony_ci *  There are several phys that do not support autoneg flow control. This
468c2ecf20Sopenharmony_ci *  function check the device id to see if the associated phy supports
478c2ecf20Sopenharmony_ci *  autoneg flow control.
488c2ecf20Sopenharmony_ci **/
498c2ecf20Sopenharmony_cibool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	bool supported = false;
528c2ecf20Sopenharmony_ci	ixgbe_link_speed speed;
538c2ecf20Sopenharmony_ci	bool link_up;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	switch (hw->phy.media_type) {
568c2ecf20Sopenharmony_ci	case ixgbe_media_type_fiber:
578c2ecf20Sopenharmony_ci		/* flow control autoneg black list */
588c2ecf20Sopenharmony_ci		switch (hw->device_id) {
598c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_X550EM_A_SFP:
608c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_X550EM_A_SFP_N:
618c2ecf20Sopenharmony_ci			supported = false;
628c2ecf20Sopenharmony_ci			break;
638c2ecf20Sopenharmony_ci		default:
648c2ecf20Sopenharmony_ci			hw->mac.ops.check_link(hw, &speed, &link_up, false);
658c2ecf20Sopenharmony_ci			/* if link is down, assume supported */
668c2ecf20Sopenharmony_ci			if (link_up)
678c2ecf20Sopenharmony_ci				supported = speed == IXGBE_LINK_SPEED_1GB_FULL;
688c2ecf20Sopenharmony_ci			else
698c2ecf20Sopenharmony_ci				supported = true;
708c2ecf20Sopenharmony_ci		}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci		break;
738c2ecf20Sopenharmony_ci	case ixgbe_media_type_backplane:
748c2ecf20Sopenharmony_ci		if (hw->device_id == IXGBE_DEV_ID_X550EM_X_XFI)
758c2ecf20Sopenharmony_ci			supported = false;
768c2ecf20Sopenharmony_ci		else
778c2ecf20Sopenharmony_ci			supported = true;
788c2ecf20Sopenharmony_ci		break;
798c2ecf20Sopenharmony_ci	case ixgbe_media_type_copper:
808c2ecf20Sopenharmony_ci		/* only some copper devices support flow control autoneg */
818c2ecf20Sopenharmony_ci		switch (hw->device_id) {
828c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_82599_T3_LOM:
838c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_X540T:
848c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_X540T1:
858c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_X550T:
868c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_X550T1:
878c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_X550EM_X_10G_T:
888c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_X550EM_A_10G_T:
898c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_X550EM_A_1G_T:
908c2ecf20Sopenharmony_ci		case IXGBE_DEV_ID_X550EM_A_1G_T_L:
918c2ecf20Sopenharmony_ci			supported = true;
928c2ecf20Sopenharmony_ci			break;
938c2ecf20Sopenharmony_ci		default:
948c2ecf20Sopenharmony_ci			break;
958c2ecf20Sopenharmony_ci		}
968c2ecf20Sopenharmony_ci	default:
978c2ecf20Sopenharmony_ci		break;
988c2ecf20Sopenharmony_ci	}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	if (!supported)
1018c2ecf20Sopenharmony_ci		hw_dbg(hw, "Device %x does not support flow control autoneg\n",
1028c2ecf20Sopenharmony_ci		       hw->device_id);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	return supported;
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci/**
1088c2ecf20Sopenharmony_ci *  ixgbe_setup_fc_generic - Set up flow control
1098c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
1108c2ecf20Sopenharmony_ci *
1118c2ecf20Sopenharmony_ci *  Called at init time to set up flow control.
1128c2ecf20Sopenharmony_ci **/
1138c2ecf20Sopenharmony_cis32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	s32 ret_val = 0;
1168c2ecf20Sopenharmony_ci	u32 reg = 0, reg_bp = 0;
1178c2ecf20Sopenharmony_ci	u16 reg_cu = 0;
1188c2ecf20Sopenharmony_ci	bool locked = false;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	/*
1218c2ecf20Sopenharmony_ci	 * Validate the requested mode.  Strict IEEE mode does not allow
1228c2ecf20Sopenharmony_ci	 * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
1238c2ecf20Sopenharmony_ci	 */
1248c2ecf20Sopenharmony_ci	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
1258c2ecf20Sopenharmony_ci		hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
1268c2ecf20Sopenharmony_ci		return -EINVAL;
1278c2ecf20Sopenharmony_ci	}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	/*
1308c2ecf20Sopenharmony_ci	 * 10gig parts do not have a word in the EEPROM to determine the
1318c2ecf20Sopenharmony_ci	 * default flow control setting, so we explicitly set it to full.
1328c2ecf20Sopenharmony_ci	 */
1338c2ecf20Sopenharmony_ci	if (hw->fc.requested_mode == ixgbe_fc_default)
1348c2ecf20Sopenharmony_ci		hw->fc.requested_mode = ixgbe_fc_full;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	/*
1378c2ecf20Sopenharmony_ci	 * Set up the 1G and 10G flow control advertisement registers so the
1388c2ecf20Sopenharmony_ci	 * HW will be able to do fc autoneg once the cable is plugged in.  If
1398c2ecf20Sopenharmony_ci	 * we link at 10G, the 1G advertisement is harmless and vice versa.
1408c2ecf20Sopenharmony_ci	 */
1418c2ecf20Sopenharmony_ci	switch (hw->phy.media_type) {
1428c2ecf20Sopenharmony_ci	case ixgbe_media_type_backplane:
1438c2ecf20Sopenharmony_ci		/* some MAC's need RMW protection on AUTOC */
1448c2ecf20Sopenharmony_ci		ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &reg_bp);
1458c2ecf20Sopenharmony_ci		if (ret_val)
1468c2ecf20Sopenharmony_ci			return ret_val;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci		fallthrough; /* only backplane uses autoc */
1498c2ecf20Sopenharmony_ci	case ixgbe_media_type_fiber:
1508c2ecf20Sopenharmony_ci		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci		break;
1538c2ecf20Sopenharmony_ci	case ixgbe_media_type_copper:
1548c2ecf20Sopenharmony_ci		hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
1558c2ecf20Sopenharmony_ci					MDIO_MMD_AN, &reg_cu);
1568c2ecf20Sopenharmony_ci		break;
1578c2ecf20Sopenharmony_ci	default:
1588c2ecf20Sopenharmony_ci		break;
1598c2ecf20Sopenharmony_ci	}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	/*
1628c2ecf20Sopenharmony_ci	 * The possible values of fc.requested_mode are:
1638c2ecf20Sopenharmony_ci	 * 0: Flow control is completely disabled
1648c2ecf20Sopenharmony_ci	 * 1: Rx flow control is enabled (we can receive pause frames,
1658c2ecf20Sopenharmony_ci	 *    but not send pause frames).
1668c2ecf20Sopenharmony_ci	 * 2: Tx flow control is enabled (we can send pause frames but
1678c2ecf20Sopenharmony_ci	 *    we do not support receiving pause frames).
1688c2ecf20Sopenharmony_ci	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
1698c2ecf20Sopenharmony_ci	 * other: Invalid.
1708c2ecf20Sopenharmony_ci	 */
1718c2ecf20Sopenharmony_ci	switch (hw->fc.requested_mode) {
1728c2ecf20Sopenharmony_ci	case ixgbe_fc_none:
1738c2ecf20Sopenharmony_ci		/* Flow control completely disabled by software override. */
1748c2ecf20Sopenharmony_ci		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
1758c2ecf20Sopenharmony_ci		if (hw->phy.media_type == ixgbe_media_type_backplane)
1768c2ecf20Sopenharmony_ci			reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
1778c2ecf20Sopenharmony_ci				    IXGBE_AUTOC_ASM_PAUSE);
1788c2ecf20Sopenharmony_ci		else if (hw->phy.media_type == ixgbe_media_type_copper)
1798c2ecf20Sopenharmony_ci			reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
1808c2ecf20Sopenharmony_ci		break;
1818c2ecf20Sopenharmony_ci	case ixgbe_fc_tx_pause:
1828c2ecf20Sopenharmony_ci		/*
1838c2ecf20Sopenharmony_ci		 * Tx Flow control is enabled, and Rx Flow control is
1848c2ecf20Sopenharmony_ci		 * disabled by software override.
1858c2ecf20Sopenharmony_ci		 */
1868c2ecf20Sopenharmony_ci		reg |= IXGBE_PCS1GANA_ASM_PAUSE;
1878c2ecf20Sopenharmony_ci		reg &= ~IXGBE_PCS1GANA_SYM_PAUSE;
1888c2ecf20Sopenharmony_ci		if (hw->phy.media_type == ixgbe_media_type_backplane) {
1898c2ecf20Sopenharmony_ci			reg_bp |= IXGBE_AUTOC_ASM_PAUSE;
1908c2ecf20Sopenharmony_ci			reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE;
1918c2ecf20Sopenharmony_ci		} else if (hw->phy.media_type == ixgbe_media_type_copper) {
1928c2ecf20Sopenharmony_ci			reg_cu |= IXGBE_TAF_ASM_PAUSE;
1938c2ecf20Sopenharmony_ci			reg_cu &= ~IXGBE_TAF_SYM_PAUSE;
1948c2ecf20Sopenharmony_ci		}
1958c2ecf20Sopenharmony_ci		break;
1968c2ecf20Sopenharmony_ci	case ixgbe_fc_rx_pause:
1978c2ecf20Sopenharmony_ci		/*
1988c2ecf20Sopenharmony_ci		 * Rx Flow control is enabled and Tx Flow control is
1998c2ecf20Sopenharmony_ci		 * disabled by software override. Since there really
2008c2ecf20Sopenharmony_ci		 * isn't a way to advertise that we are capable of RX
2018c2ecf20Sopenharmony_ci		 * Pause ONLY, we will advertise that we support both
2028c2ecf20Sopenharmony_ci		 * symmetric and asymmetric Rx PAUSE, as such we fall
2038c2ecf20Sopenharmony_ci		 * through to the fc_full statement.  Later, we will
2048c2ecf20Sopenharmony_ci		 * disable the adapter's ability to send PAUSE frames.
2058c2ecf20Sopenharmony_ci		 */
2068c2ecf20Sopenharmony_ci	case ixgbe_fc_full:
2078c2ecf20Sopenharmony_ci		/* Flow control (both Rx and Tx) is enabled by SW override. */
2088c2ecf20Sopenharmony_ci		reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE;
2098c2ecf20Sopenharmony_ci		if (hw->phy.media_type == ixgbe_media_type_backplane)
2108c2ecf20Sopenharmony_ci			reg_bp |= IXGBE_AUTOC_SYM_PAUSE |
2118c2ecf20Sopenharmony_ci				  IXGBE_AUTOC_ASM_PAUSE;
2128c2ecf20Sopenharmony_ci		else if (hw->phy.media_type == ixgbe_media_type_copper)
2138c2ecf20Sopenharmony_ci			reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE;
2148c2ecf20Sopenharmony_ci		break;
2158c2ecf20Sopenharmony_ci	default:
2168c2ecf20Sopenharmony_ci		hw_dbg(hw, "Flow control param set incorrectly\n");
2178c2ecf20Sopenharmony_ci		return -EIO;
2188c2ecf20Sopenharmony_ci	}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	if (hw->mac.type != ixgbe_mac_X540) {
2218c2ecf20Sopenharmony_ci		/*
2228c2ecf20Sopenharmony_ci		 * Enable auto-negotiation between the MAC & PHY;
2238c2ecf20Sopenharmony_ci		 * the MAC will advertise clause 37 flow control.
2248c2ecf20Sopenharmony_ci		 */
2258c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
2268c2ecf20Sopenharmony_ci		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci		/* Disable AN timeout */
2298c2ecf20Sopenharmony_ci		if (hw->fc.strict_ieee)
2308c2ecf20Sopenharmony_ci			reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
2338c2ecf20Sopenharmony_ci		hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	/*
2378c2ecf20Sopenharmony_ci	 * AUTOC restart handles negotiation of 1G and 10G on backplane
2388c2ecf20Sopenharmony_ci	 * and copper. There is no need to set the PCS1GCTL register.
2398c2ecf20Sopenharmony_ci	 *
2408c2ecf20Sopenharmony_ci	 */
2418c2ecf20Sopenharmony_ci	if (hw->phy.media_type == ixgbe_media_type_backplane) {
2428c2ecf20Sopenharmony_ci		/* Need the SW/FW semaphore around AUTOC writes if 82599 and
2438c2ecf20Sopenharmony_ci		 * LESM is on, likewise reset_pipeline requries the lock as
2448c2ecf20Sopenharmony_ci		 * it also writes AUTOC.
2458c2ecf20Sopenharmony_ci		 */
2468c2ecf20Sopenharmony_ci		ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked);
2478c2ecf20Sopenharmony_ci		if (ret_val)
2488c2ecf20Sopenharmony_ci			return ret_val;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
2518c2ecf20Sopenharmony_ci		   ixgbe_device_supports_autoneg_fc(hw)) {
2528c2ecf20Sopenharmony_ci		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
2538c2ecf20Sopenharmony_ci				      MDIO_MMD_AN, reg_cu);
2548c2ecf20Sopenharmony_ci	}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
2578c2ecf20Sopenharmony_ci	return ret_val;
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci/**
2618c2ecf20Sopenharmony_ci *  ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
2628c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
2638c2ecf20Sopenharmony_ci *
2648c2ecf20Sopenharmony_ci *  Starts the hardware by filling the bus info structure and media type, clears
2658c2ecf20Sopenharmony_ci *  all on chip counters, initializes receive address registers, multicast
2668c2ecf20Sopenharmony_ci *  table, VLAN filter table, calls routine to set up link and flow control
2678c2ecf20Sopenharmony_ci *  settings, and leaves transmit and receive units disabled and uninitialized
2688c2ecf20Sopenharmony_ci **/
2698c2ecf20Sopenharmony_cis32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	s32 ret_val;
2728c2ecf20Sopenharmony_ci	u32 ctrl_ext;
2738c2ecf20Sopenharmony_ci	u16 device_caps;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	/* Set the media type */
2768c2ecf20Sopenharmony_ci	hw->phy.media_type = hw->mac.ops.get_media_type(hw);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	/* Identify the PHY */
2798c2ecf20Sopenharmony_ci	hw->phy.ops.identify(hw);
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	/* Clear the VLAN filter table */
2828c2ecf20Sopenharmony_ci	hw->mac.ops.clear_vfta(hw);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	/* Clear statistics registers */
2858c2ecf20Sopenharmony_ci	hw->mac.ops.clear_hw_cntrs(hw);
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	/* Set No Snoop Disable */
2888c2ecf20Sopenharmony_ci	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
2898c2ecf20Sopenharmony_ci	ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS;
2908c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
2918c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	/* Setup flow control if method for doing so */
2948c2ecf20Sopenharmony_ci	if (hw->mac.ops.setup_fc) {
2958c2ecf20Sopenharmony_ci		ret_val = hw->mac.ops.setup_fc(hw);
2968c2ecf20Sopenharmony_ci		if (ret_val)
2978c2ecf20Sopenharmony_ci			return ret_val;
2988c2ecf20Sopenharmony_ci	}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	/* Cashe bit indicating need for crosstalk fix */
3018c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
3028c2ecf20Sopenharmony_ci	case ixgbe_mac_82599EB:
3038c2ecf20Sopenharmony_ci	case ixgbe_mac_X550EM_x:
3048c2ecf20Sopenharmony_ci	case ixgbe_mac_x550em_a:
3058c2ecf20Sopenharmony_ci		hw->mac.ops.get_device_caps(hw, &device_caps);
3068c2ecf20Sopenharmony_ci		if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR)
3078c2ecf20Sopenharmony_ci			hw->need_crosstalk_fix = false;
3088c2ecf20Sopenharmony_ci		else
3098c2ecf20Sopenharmony_ci			hw->need_crosstalk_fix = true;
3108c2ecf20Sopenharmony_ci		break;
3118c2ecf20Sopenharmony_ci	default:
3128c2ecf20Sopenharmony_ci		hw->need_crosstalk_fix = false;
3138c2ecf20Sopenharmony_ci		break;
3148c2ecf20Sopenharmony_ci	}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	/* Clear adapter stopped flag */
3178c2ecf20Sopenharmony_ci	hw->adapter_stopped = false;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	return 0;
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci/**
3238c2ecf20Sopenharmony_ci *  ixgbe_start_hw_gen2 - Init sequence for common device family
3248c2ecf20Sopenharmony_ci *  @hw: pointer to hw structure
3258c2ecf20Sopenharmony_ci *
3268c2ecf20Sopenharmony_ci * Performs the init sequence common to the second generation
3278c2ecf20Sopenharmony_ci * of 10 GbE devices.
3288c2ecf20Sopenharmony_ci * Devices in the second generation:
3298c2ecf20Sopenharmony_ci *     82599
3308c2ecf20Sopenharmony_ci *     X540
3318c2ecf20Sopenharmony_ci **/
3328c2ecf20Sopenharmony_cis32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	u32 i;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	/* Clear the rate limiters */
3378c2ecf20Sopenharmony_ci	for (i = 0; i < hw->mac.max_tx_queues; i++) {
3388c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i);
3398c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0);
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	return 0;
3448c2ecf20Sopenharmony_ci}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci/**
3478c2ecf20Sopenharmony_ci *  ixgbe_init_hw_generic - Generic hardware initialization
3488c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
3498c2ecf20Sopenharmony_ci *
3508c2ecf20Sopenharmony_ci *  Initialize the hardware by resetting the hardware, filling the bus info
3518c2ecf20Sopenharmony_ci *  structure and media type, clears all on chip counters, initializes receive
3528c2ecf20Sopenharmony_ci *  address registers, multicast table, VLAN filter table, calls routine to set
3538c2ecf20Sopenharmony_ci *  up link and flow control settings, and leaves transmit and receive units
3548c2ecf20Sopenharmony_ci *  disabled and uninitialized
3558c2ecf20Sopenharmony_ci **/
3568c2ecf20Sopenharmony_cis32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	s32 status;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	/* Reset the hardware */
3618c2ecf20Sopenharmony_ci	status = hw->mac.ops.reset_hw(hw);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	if (status == 0) {
3648c2ecf20Sopenharmony_ci		/* Start the HW */
3658c2ecf20Sopenharmony_ci		status = hw->mac.ops.start_hw(hw);
3668c2ecf20Sopenharmony_ci	}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	/* Initialize the LED link active for LED blink support */
3698c2ecf20Sopenharmony_ci	if (hw->mac.ops.init_led_link_act)
3708c2ecf20Sopenharmony_ci		hw->mac.ops.init_led_link_act(hw);
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	return status;
3738c2ecf20Sopenharmony_ci}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci/**
3768c2ecf20Sopenharmony_ci *  ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters
3778c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
3788c2ecf20Sopenharmony_ci *
3798c2ecf20Sopenharmony_ci *  Clears all hardware statistics counters by reading them from the hardware
3808c2ecf20Sopenharmony_ci *  Statistics counters are clear on read.
3818c2ecf20Sopenharmony_ci **/
3828c2ecf20Sopenharmony_cis32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	u16 i = 0;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_CRCERRS);
3878c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_ILLERRC);
3888c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_ERRBC);
3898c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_MSPDC);
3908c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++)
3918c2ecf20Sopenharmony_ci		IXGBE_READ_REG(hw, IXGBE_MPC(i));
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_MLFC);
3948c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_MRFC);
3958c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_RLEC);
3968c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_LXONTXC);
3978c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
3988c2ecf20Sopenharmony_ci	if (hw->mac.type >= ixgbe_mac_82599EB) {
3998c2ecf20Sopenharmony_ci		IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
4008c2ecf20Sopenharmony_ci		IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
4018c2ecf20Sopenharmony_ci	} else {
4028c2ecf20Sopenharmony_ci		IXGBE_READ_REG(hw, IXGBE_LXONRXC);
4038c2ecf20Sopenharmony_ci		IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
4048c2ecf20Sopenharmony_ci	}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++) {
4078c2ecf20Sopenharmony_ci		IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
4088c2ecf20Sopenharmony_ci		IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
4098c2ecf20Sopenharmony_ci		if (hw->mac.type >= ixgbe_mac_82599EB) {
4108c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
4118c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
4128c2ecf20Sopenharmony_ci		} else {
4138c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
4148c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
4158c2ecf20Sopenharmony_ci		}
4168c2ecf20Sopenharmony_ci	}
4178c2ecf20Sopenharmony_ci	if (hw->mac.type >= ixgbe_mac_82599EB)
4188c2ecf20Sopenharmony_ci		for (i = 0; i < 8; i++)
4198c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
4208c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PRC64);
4218c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PRC127);
4228c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PRC255);
4238c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PRC511);
4248c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PRC1023);
4258c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PRC1522);
4268c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_GPRC);
4278c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_BPRC);
4288c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_MPRC);
4298c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_GPTC);
4308c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_GORCL);
4318c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_GORCH);
4328c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_GOTCL);
4338c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_GOTCH);
4348c2ecf20Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_82598EB)
4358c2ecf20Sopenharmony_ci		for (i = 0; i < 8; i++)
4368c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_RNBC(i));
4378c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_RUC);
4388c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_RFC);
4398c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_ROC);
4408c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_RJC);
4418c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_MNGPRC);
4428c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_MNGPDC);
4438c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_MNGPTC);
4448c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_TORL);
4458c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_TORH);
4468c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_TPR);
4478c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_TPT);
4488c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PTC64);
4498c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PTC127);
4508c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PTC255);
4518c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PTC511);
4528c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PTC1023);
4538c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_PTC1522);
4548c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_MPTC);
4558c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_BPTC);
4568c2ecf20Sopenharmony_ci	for (i = 0; i < 16; i++) {
4578c2ecf20Sopenharmony_ci		IXGBE_READ_REG(hw, IXGBE_QPRC(i));
4588c2ecf20Sopenharmony_ci		IXGBE_READ_REG(hw, IXGBE_QPTC(i));
4598c2ecf20Sopenharmony_ci		if (hw->mac.type >= ixgbe_mac_82599EB) {
4608c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
4618c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_QBRC_H(i));
4628c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
4638c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_QBTC_H(i));
4648c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
4658c2ecf20Sopenharmony_ci		} else {
4668c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_QBRC(i));
4678c2ecf20Sopenharmony_ci			IXGBE_READ_REG(hw, IXGBE_QBTC(i));
4688c2ecf20Sopenharmony_ci		}
4698c2ecf20Sopenharmony_ci	}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) {
4728c2ecf20Sopenharmony_ci		if (hw->phy.id == 0)
4738c2ecf20Sopenharmony_ci			hw->phy.ops.identify(hw);
4748c2ecf20Sopenharmony_ci		hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, MDIO_MMD_PCS, &i);
4758c2ecf20Sopenharmony_ci		hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, MDIO_MMD_PCS, &i);
4768c2ecf20Sopenharmony_ci		hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, MDIO_MMD_PCS, &i);
4778c2ecf20Sopenharmony_ci		hw->phy.ops.read_reg(hw, IXGBE_LDPCECH, MDIO_MMD_PCS, &i);
4788c2ecf20Sopenharmony_ci	}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	return 0;
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci/**
4848c2ecf20Sopenharmony_ci *  ixgbe_read_pba_string_generic - Reads part number string from EEPROM
4858c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
4868c2ecf20Sopenharmony_ci *  @pba_num: stores the part number string from the EEPROM
4878c2ecf20Sopenharmony_ci *  @pba_num_size: part number string buffer length
4888c2ecf20Sopenharmony_ci *
4898c2ecf20Sopenharmony_ci *  Reads the part number string from the EEPROM.
4908c2ecf20Sopenharmony_ci **/
4918c2ecf20Sopenharmony_cis32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num,
4928c2ecf20Sopenharmony_ci				  u32 pba_num_size)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	s32 ret_val;
4958c2ecf20Sopenharmony_ci	u16 data;
4968c2ecf20Sopenharmony_ci	u16 pba_ptr;
4978c2ecf20Sopenharmony_ci	u16 offset;
4988c2ecf20Sopenharmony_ci	u16 length;
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	if (pba_num == NULL) {
5018c2ecf20Sopenharmony_ci		hw_dbg(hw, "PBA string buffer was null\n");
5028c2ecf20Sopenharmony_ci		return -EINVAL;
5038c2ecf20Sopenharmony_ci	}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
5068c2ecf20Sopenharmony_ci	if (ret_val) {
5078c2ecf20Sopenharmony_ci		hw_dbg(hw, "NVM Read Error\n");
5088c2ecf20Sopenharmony_ci		return ret_val;
5098c2ecf20Sopenharmony_ci	}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr);
5128c2ecf20Sopenharmony_ci	if (ret_val) {
5138c2ecf20Sopenharmony_ci		hw_dbg(hw, "NVM Read Error\n");
5148c2ecf20Sopenharmony_ci		return ret_val;
5158c2ecf20Sopenharmony_ci	}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	/*
5188c2ecf20Sopenharmony_ci	 * if data is not ptr guard the PBA must be in legacy format which
5198c2ecf20Sopenharmony_ci	 * means pba_ptr is actually our second data word for the PBA number
5208c2ecf20Sopenharmony_ci	 * and we can decode it into an ascii string
5218c2ecf20Sopenharmony_ci	 */
5228c2ecf20Sopenharmony_ci	if (data != IXGBE_PBANUM_PTR_GUARD) {
5238c2ecf20Sopenharmony_ci		hw_dbg(hw, "NVM PBA number is not stored as string\n");
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci		/* we will need 11 characters to store the PBA */
5268c2ecf20Sopenharmony_ci		if (pba_num_size < 11) {
5278c2ecf20Sopenharmony_ci			hw_dbg(hw, "PBA string buffer too small\n");
5288c2ecf20Sopenharmony_ci			return -ENOSPC;
5298c2ecf20Sopenharmony_ci		}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci		/* extract hex string from data and pba_ptr */
5328c2ecf20Sopenharmony_ci		pba_num[0] = (data >> 12) & 0xF;
5338c2ecf20Sopenharmony_ci		pba_num[1] = (data >> 8) & 0xF;
5348c2ecf20Sopenharmony_ci		pba_num[2] = (data >> 4) & 0xF;
5358c2ecf20Sopenharmony_ci		pba_num[3] = data & 0xF;
5368c2ecf20Sopenharmony_ci		pba_num[4] = (pba_ptr >> 12) & 0xF;
5378c2ecf20Sopenharmony_ci		pba_num[5] = (pba_ptr >> 8) & 0xF;
5388c2ecf20Sopenharmony_ci		pba_num[6] = '-';
5398c2ecf20Sopenharmony_ci		pba_num[7] = 0;
5408c2ecf20Sopenharmony_ci		pba_num[8] = (pba_ptr >> 4) & 0xF;
5418c2ecf20Sopenharmony_ci		pba_num[9] = pba_ptr & 0xF;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci		/* put a null character on the end of our string */
5448c2ecf20Sopenharmony_ci		pba_num[10] = '\0';
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci		/* switch all the data but the '-' to hex char */
5478c2ecf20Sopenharmony_ci		for (offset = 0; offset < 10; offset++) {
5488c2ecf20Sopenharmony_ci			if (pba_num[offset] < 0xA)
5498c2ecf20Sopenharmony_ci				pba_num[offset] += '0';
5508c2ecf20Sopenharmony_ci			else if (pba_num[offset] < 0x10)
5518c2ecf20Sopenharmony_ci				pba_num[offset] += 'A' - 0xA;
5528c2ecf20Sopenharmony_ci		}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci		return 0;
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length);
5588c2ecf20Sopenharmony_ci	if (ret_val) {
5598c2ecf20Sopenharmony_ci		hw_dbg(hw, "NVM Read Error\n");
5608c2ecf20Sopenharmony_ci		return ret_val;
5618c2ecf20Sopenharmony_ci	}
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	if (length == 0xFFFF || length == 0) {
5648c2ecf20Sopenharmony_ci		hw_dbg(hw, "NVM PBA number section invalid length\n");
5658c2ecf20Sopenharmony_ci		return -EIO;
5668c2ecf20Sopenharmony_ci	}
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	/* check if pba_num buffer is big enough */
5698c2ecf20Sopenharmony_ci	if (pba_num_size  < (((u32)length * 2) - 1)) {
5708c2ecf20Sopenharmony_ci		hw_dbg(hw, "PBA string buffer too small\n");
5718c2ecf20Sopenharmony_ci		return -ENOSPC;
5728c2ecf20Sopenharmony_ci	}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	/* trim pba length from start of string */
5758c2ecf20Sopenharmony_ci	pba_ptr++;
5768c2ecf20Sopenharmony_ci	length--;
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	for (offset = 0; offset < length; offset++) {
5798c2ecf20Sopenharmony_ci		ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data);
5808c2ecf20Sopenharmony_ci		if (ret_val) {
5818c2ecf20Sopenharmony_ci			hw_dbg(hw, "NVM Read Error\n");
5828c2ecf20Sopenharmony_ci			return ret_val;
5838c2ecf20Sopenharmony_ci		}
5848c2ecf20Sopenharmony_ci		pba_num[offset * 2] = (u8)(data >> 8);
5858c2ecf20Sopenharmony_ci		pba_num[(offset * 2) + 1] = (u8)(data & 0xFF);
5868c2ecf20Sopenharmony_ci	}
5878c2ecf20Sopenharmony_ci	pba_num[offset * 2] = '\0';
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	return 0;
5908c2ecf20Sopenharmony_ci}
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci/**
5938c2ecf20Sopenharmony_ci *  ixgbe_get_mac_addr_generic - Generic get MAC address
5948c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
5958c2ecf20Sopenharmony_ci *  @mac_addr: Adapter MAC address
5968c2ecf20Sopenharmony_ci *
5978c2ecf20Sopenharmony_ci *  Reads the adapter's MAC address from first Receive Address Register (RAR0)
5988c2ecf20Sopenharmony_ci *  A reset of the adapter must be performed prior to calling this function
5998c2ecf20Sopenharmony_ci *  in order for the MAC address to have been loaded from the EEPROM into RAR0
6008c2ecf20Sopenharmony_ci **/
6018c2ecf20Sopenharmony_cis32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr)
6028c2ecf20Sopenharmony_ci{
6038c2ecf20Sopenharmony_ci	u32 rar_high;
6048c2ecf20Sopenharmony_ci	u32 rar_low;
6058c2ecf20Sopenharmony_ci	u16 i;
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0));
6088c2ecf20Sopenharmony_ci	rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0));
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++)
6118c2ecf20Sopenharmony_ci		mac_addr[i] = (u8)(rar_low >> (i*8));
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	for (i = 0; i < 2; i++)
6148c2ecf20Sopenharmony_ci		mac_addr[i+4] = (u8)(rar_high >> (i*8));
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	return 0;
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cienum ixgbe_bus_width ixgbe_convert_bus_width(u16 link_status)
6208c2ecf20Sopenharmony_ci{
6218c2ecf20Sopenharmony_ci	switch (link_status & IXGBE_PCI_LINK_WIDTH) {
6228c2ecf20Sopenharmony_ci	case IXGBE_PCI_LINK_WIDTH_1:
6238c2ecf20Sopenharmony_ci		return ixgbe_bus_width_pcie_x1;
6248c2ecf20Sopenharmony_ci	case IXGBE_PCI_LINK_WIDTH_2:
6258c2ecf20Sopenharmony_ci		return ixgbe_bus_width_pcie_x2;
6268c2ecf20Sopenharmony_ci	case IXGBE_PCI_LINK_WIDTH_4:
6278c2ecf20Sopenharmony_ci		return ixgbe_bus_width_pcie_x4;
6288c2ecf20Sopenharmony_ci	case IXGBE_PCI_LINK_WIDTH_8:
6298c2ecf20Sopenharmony_ci		return ixgbe_bus_width_pcie_x8;
6308c2ecf20Sopenharmony_ci	default:
6318c2ecf20Sopenharmony_ci		return ixgbe_bus_width_unknown;
6328c2ecf20Sopenharmony_ci	}
6338c2ecf20Sopenharmony_ci}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_cienum ixgbe_bus_speed ixgbe_convert_bus_speed(u16 link_status)
6368c2ecf20Sopenharmony_ci{
6378c2ecf20Sopenharmony_ci	switch (link_status & IXGBE_PCI_LINK_SPEED) {
6388c2ecf20Sopenharmony_ci	case IXGBE_PCI_LINK_SPEED_2500:
6398c2ecf20Sopenharmony_ci		return ixgbe_bus_speed_2500;
6408c2ecf20Sopenharmony_ci	case IXGBE_PCI_LINK_SPEED_5000:
6418c2ecf20Sopenharmony_ci		return ixgbe_bus_speed_5000;
6428c2ecf20Sopenharmony_ci	case IXGBE_PCI_LINK_SPEED_8000:
6438c2ecf20Sopenharmony_ci		return ixgbe_bus_speed_8000;
6448c2ecf20Sopenharmony_ci	default:
6458c2ecf20Sopenharmony_ci		return ixgbe_bus_speed_unknown;
6468c2ecf20Sopenharmony_ci	}
6478c2ecf20Sopenharmony_ci}
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci/**
6508c2ecf20Sopenharmony_ci *  ixgbe_get_bus_info_generic - Generic set PCI bus info
6518c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
6528c2ecf20Sopenharmony_ci *
6538c2ecf20Sopenharmony_ci *  Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure
6548c2ecf20Sopenharmony_ci **/
6558c2ecf20Sopenharmony_cis32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
6568c2ecf20Sopenharmony_ci{
6578c2ecf20Sopenharmony_ci	u16 link_status;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	hw->bus.type = ixgbe_bus_type_pci_express;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	/* Get the negotiated link width and speed from PCI config space */
6628c2ecf20Sopenharmony_ci	link_status = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_LINK_STATUS);
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	hw->bus.width = ixgbe_convert_bus_width(link_status);
6658c2ecf20Sopenharmony_ci	hw->bus.speed = ixgbe_convert_bus_speed(link_status);
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci	hw->mac.ops.set_lan_id(hw);
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	return 0;
6708c2ecf20Sopenharmony_ci}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci/**
6738c2ecf20Sopenharmony_ci *  ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
6748c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
6758c2ecf20Sopenharmony_ci *
6768c2ecf20Sopenharmony_ci *  Determines the LAN function id by reading memory-mapped registers
6778c2ecf20Sopenharmony_ci *  and swaps the port value if requested.
6788c2ecf20Sopenharmony_ci **/
6798c2ecf20Sopenharmony_civoid ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
6808c2ecf20Sopenharmony_ci{
6818c2ecf20Sopenharmony_ci	struct ixgbe_bus_info *bus = &hw->bus;
6828c2ecf20Sopenharmony_ci	u16 ee_ctrl_4;
6838c2ecf20Sopenharmony_ci	u32 reg;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	reg = IXGBE_READ_REG(hw, IXGBE_STATUS);
6868c2ecf20Sopenharmony_ci	bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT;
6878c2ecf20Sopenharmony_ci	bus->lan_id = bus->func;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	/* check for a port swap */
6908c2ecf20Sopenharmony_ci	reg = IXGBE_READ_REG(hw, IXGBE_FACTPS(hw));
6918c2ecf20Sopenharmony_ci	if (reg & IXGBE_FACTPS_LFS)
6928c2ecf20Sopenharmony_ci		bus->func ^= 0x1;
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	/* Get MAC instance from EEPROM for configuring CS4227 */
6958c2ecf20Sopenharmony_ci	if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) {
6968c2ecf20Sopenharmony_ci		hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4);
6978c2ecf20Sopenharmony_ci		bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >>
6988c2ecf20Sopenharmony_ci				   IXGBE_EE_CTRL_4_INST_ID_SHIFT;
6998c2ecf20Sopenharmony_ci	}
7008c2ecf20Sopenharmony_ci}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci/**
7038c2ecf20Sopenharmony_ci *  ixgbe_stop_adapter_generic - Generic stop Tx/Rx units
7048c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
7058c2ecf20Sopenharmony_ci *
7068c2ecf20Sopenharmony_ci *  Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts,
7078c2ecf20Sopenharmony_ci *  disables transmit and receive units. The adapter_stopped flag is used by
7088c2ecf20Sopenharmony_ci *  the shared code and drivers to determine if the adapter is in a stopped
7098c2ecf20Sopenharmony_ci *  state and should not touch the hardware.
7108c2ecf20Sopenharmony_ci **/
7118c2ecf20Sopenharmony_cis32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
7128c2ecf20Sopenharmony_ci{
7138c2ecf20Sopenharmony_ci	u32 reg_val;
7148c2ecf20Sopenharmony_ci	u16 i;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	/*
7178c2ecf20Sopenharmony_ci	 * Set the adapter_stopped flag so other driver functions stop touching
7188c2ecf20Sopenharmony_ci	 * the hardware
7198c2ecf20Sopenharmony_ci	 */
7208c2ecf20Sopenharmony_ci	hw->adapter_stopped = true;
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	/* Disable the receive unit */
7238c2ecf20Sopenharmony_ci	hw->mac.ops.disable_rx(hw);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	/* Clear interrupt mask to stop interrupts from being generated */
7268c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	/* Clear any pending interrupts, flush previous writes */
7298c2ecf20Sopenharmony_ci	IXGBE_READ_REG(hw, IXGBE_EICR);
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	/* Disable the transmit unit.  Each queue must be disabled. */
7328c2ecf20Sopenharmony_ci	for (i = 0; i < hw->mac.max_tx_queues; i++)
7338c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH);
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	/* Disable the receive unit by stopping each queue */
7368c2ecf20Sopenharmony_ci	for (i = 0; i < hw->mac.max_rx_queues; i++) {
7378c2ecf20Sopenharmony_ci		reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
7388c2ecf20Sopenharmony_ci		reg_val &= ~IXGBE_RXDCTL_ENABLE;
7398c2ecf20Sopenharmony_ci		reg_val |= IXGBE_RXDCTL_SWFLSH;
7408c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val);
7418c2ecf20Sopenharmony_ci	}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	/* flush all queues disables */
7448c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
7458c2ecf20Sopenharmony_ci	usleep_range(1000, 2000);
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	/*
7488c2ecf20Sopenharmony_ci	 * Prevent the PCI-E bus from hanging by disabling PCI-E primary
7498c2ecf20Sopenharmony_ci	 * access and verify no pending requests
7508c2ecf20Sopenharmony_ci	 */
7518c2ecf20Sopenharmony_ci	return ixgbe_disable_pcie_primary(hw);
7528c2ecf20Sopenharmony_ci}
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci/**
7558c2ecf20Sopenharmony_ci *  ixgbe_init_led_link_act_generic - Store the LED index link/activity.
7568c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
7578c2ecf20Sopenharmony_ci *
7588c2ecf20Sopenharmony_ci *  Store the index for the link active LED. This will be used to support
7598c2ecf20Sopenharmony_ci *  blinking the LED.
7608c2ecf20Sopenharmony_ci **/
7618c2ecf20Sopenharmony_cis32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw)
7628c2ecf20Sopenharmony_ci{
7638c2ecf20Sopenharmony_ci	struct ixgbe_mac_info *mac = &hw->mac;
7648c2ecf20Sopenharmony_ci	u32 led_reg, led_mode;
7658c2ecf20Sopenharmony_ci	u16 i;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	/* Get LED link active from the LEDCTL register */
7708c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
7718c2ecf20Sopenharmony_ci		led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i);
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci		if ((led_mode & IXGBE_LED_MODE_MASK_BASE) ==
7748c2ecf20Sopenharmony_ci		    IXGBE_LED_LINK_ACTIVE) {
7758c2ecf20Sopenharmony_ci			mac->led_link_act = i;
7768c2ecf20Sopenharmony_ci			return 0;
7778c2ecf20Sopenharmony_ci		}
7788c2ecf20Sopenharmony_ci	}
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	/* If LEDCTL register does not have the LED link active set, then use
7818c2ecf20Sopenharmony_ci	 * known MAC defaults.
7828c2ecf20Sopenharmony_ci	 */
7838c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
7848c2ecf20Sopenharmony_ci	case ixgbe_mac_x550em_a:
7858c2ecf20Sopenharmony_ci		mac->led_link_act = 0;
7868c2ecf20Sopenharmony_ci		break;
7878c2ecf20Sopenharmony_ci	case ixgbe_mac_X550EM_x:
7888c2ecf20Sopenharmony_ci		mac->led_link_act = 1;
7898c2ecf20Sopenharmony_ci		break;
7908c2ecf20Sopenharmony_ci	default:
7918c2ecf20Sopenharmony_ci		mac->led_link_act = 2;
7928c2ecf20Sopenharmony_ci	}
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	return 0;
7958c2ecf20Sopenharmony_ci}
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci/**
7988c2ecf20Sopenharmony_ci *  ixgbe_led_on_generic - Turns on the software controllable LEDs.
7998c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
8008c2ecf20Sopenharmony_ci *  @index: led number to turn on
8018c2ecf20Sopenharmony_ci **/
8028c2ecf20Sopenharmony_cis32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index)
8038c2ecf20Sopenharmony_ci{
8048c2ecf20Sopenharmony_ci	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	if (index > 3)
8078c2ecf20Sopenharmony_ci		return -EINVAL;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	/* To turn on the LED, set mode to ON. */
8108c2ecf20Sopenharmony_ci	led_reg &= ~IXGBE_LED_MODE_MASK(index);
8118c2ecf20Sopenharmony_ci	led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index);
8128c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
8138c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	return 0;
8168c2ecf20Sopenharmony_ci}
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci/**
8198c2ecf20Sopenharmony_ci *  ixgbe_led_off_generic - Turns off the software controllable LEDs.
8208c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
8218c2ecf20Sopenharmony_ci *  @index: led number to turn off
8228c2ecf20Sopenharmony_ci **/
8238c2ecf20Sopenharmony_cis32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index)
8248c2ecf20Sopenharmony_ci{
8258c2ecf20Sopenharmony_ci	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	if (index > 3)
8288c2ecf20Sopenharmony_ci		return -EINVAL;
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	/* To turn off the LED, set mode to OFF. */
8318c2ecf20Sopenharmony_ci	led_reg &= ~IXGBE_LED_MODE_MASK(index);
8328c2ecf20Sopenharmony_ci	led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index);
8338c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
8348c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	return 0;
8378c2ecf20Sopenharmony_ci}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci/**
8408c2ecf20Sopenharmony_ci *  ixgbe_init_eeprom_params_generic - Initialize EEPROM params
8418c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
8428c2ecf20Sopenharmony_ci *
8438c2ecf20Sopenharmony_ci *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
8448c2ecf20Sopenharmony_ci *  ixgbe_hw struct in order to set up EEPROM access.
8458c2ecf20Sopenharmony_ci **/
8468c2ecf20Sopenharmony_cis32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
8478c2ecf20Sopenharmony_ci{
8488c2ecf20Sopenharmony_ci	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
8498c2ecf20Sopenharmony_ci	u32 eec;
8508c2ecf20Sopenharmony_ci	u16 eeprom_size;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	if (eeprom->type == ixgbe_eeprom_uninitialized) {
8538c2ecf20Sopenharmony_ci		eeprom->type = ixgbe_eeprom_none;
8548c2ecf20Sopenharmony_ci		/* Set default semaphore delay to 10ms which is a well
8558c2ecf20Sopenharmony_ci		 * tested value */
8568c2ecf20Sopenharmony_ci		eeprom->semaphore_delay = 10;
8578c2ecf20Sopenharmony_ci		/* Clear EEPROM page size, it will be initialized as needed */
8588c2ecf20Sopenharmony_ci		eeprom->word_page_size = 0;
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci		/*
8618c2ecf20Sopenharmony_ci		 * Check for EEPROM present first.
8628c2ecf20Sopenharmony_ci		 * If not present leave as none
8638c2ecf20Sopenharmony_ci		 */
8648c2ecf20Sopenharmony_ci		eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
8658c2ecf20Sopenharmony_ci		if (eec & IXGBE_EEC_PRES) {
8668c2ecf20Sopenharmony_ci			eeprom->type = ixgbe_eeprom_spi;
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci			/*
8698c2ecf20Sopenharmony_ci			 * SPI EEPROM is assumed here.  This code would need to
8708c2ecf20Sopenharmony_ci			 * change if a future EEPROM is not SPI.
8718c2ecf20Sopenharmony_ci			 */
8728c2ecf20Sopenharmony_ci			eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
8738c2ecf20Sopenharmony_ci					    IXGBE_EEC_SIZE_SHIFT);
8748c2ecf20Sopenharmony_ci			eeprom->word_size = BIT(eeprom_size +
8758c2ecf20Sopenharmony_ci						 IXGBE_EEPROM_WORD_SIZE_SHIFT);
8768c2ecf20Sopenharmony_ci		}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci		if (eec & IXGBE_EEC_ADDR_SIZE)
8798c2ecf20Sopenharmony_ci			eeprom->address_bits = 16;
8808c2ecf20Sopenharmony_ci		else
8818c2ecf20Sopenharmony_ci			eeprom->address_bits = 8;
8828c2ecf20Sopenharmony_ci		hw_dbg(hw, "Eeprom params: type = %d, size = %d, address bits: %d\n",
8838c2ecf20Sopenharmony_ci		       eeprom->type, eeprom->word_size, eeprom->address_bits);
8848c2ecf20Sopenharmony_ci	}
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	return 0;
8878c2ecf20Sopenharmony_ci}
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci/**
8908c2ecf20Sopenharmony_ci *  ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang
8918c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
8928c2ecf20Sopenharmony_ci *  @offset: offset within the EEPROM to write
8938c2ecf20Sopenharmony_ci *  @words: number of words
8948c2ecf20Sopenharmony_ci *  @data: 16 bit word(s) to write to EEPROM
8958c2ecf20Sopenharmony_ci *
8968c2ecf20Sopenharmony_ci *  Reads 16 bit word(s) from EEPROM through bit-bang method
8978c2ecf20Sopenharmony_ci **/
8988c2ecf20Sopenharmony_cis32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
8998c2ecf20Sopenharmony_ci					       u16 words, u16 *data)
9008c2ecf20Sopenharmony_ci{
9018c2ecf20Sopenharmony_ci	s32 status;
9028c2ecf20Sopenharmony_ci	u16 i, count;
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci	hw->eeprom.ops.init_params(hw);
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	if (words == 0 || (offset + words > hw->eeprom.word_size))
9078c2ecf20Sopenharmony_ci		return -EINVAL;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	/*
9108c2ecf20Sopenharmony_ci	 * The EEPROM page size cannot be queried from the chip. We do lazy
9118c2ecf20Sopenharmony_ci	 * initialization. It is worth to do that when we write large buffer.
9128c2ecf20Sopenharmony_ci	 */
9138c2ecf20Sopenharmony_ci	if ((hw->eeprom.word_page_size == 0) &&
9148c2ecf20Sopenharmony_ci	    (words > IXGBE_EEPROM_PAGE_SIZE_MAX))
9158c2ecf20Sopenharmony_ci		ixgbe_detect_eeprom_page_size_generic(hw, offset);
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	/*
9188c2ecf20Sopenharmony_ci	 * We cannot hold synchronization semaphores for too long
9198c2ecf20Sopenharmony_ci	 * to avoid other entity starvation. However it is more efficient
9208c2ecf20Sopenharmony_ci	 * to read in bursts than synchronizing access for each word.
9218c2ecf20Sopenharmony_ci	 */
9228c2ecf20Sopenharmony_ci	for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) {
9238c2ecf20Sopenharmony_ci		count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ?
9248c2ecf20Sopenharmony_ci			 IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i);
9258c2ecf20Sopenharmony_ci		status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i,
9268c2ecf20Sopenharmony_ci							    count, &data[i]);
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci		if (status != 0)
9298c2ecf20Sopenharmony_ci			break;
9308c2ecf20Sopenharmony_ci	}
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	return status;
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci/**
9368c2ecf20Sopenharmony_ci *  ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM
9378c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
9388c2ecf20Sopenharmony_ci *  @offset: offset within the EEPROM to be written to
9398c2ecf20Sopenharmony_ci *  @words: number of word(s)
9408c2ecf20Sopenharmony_ci *  @data: 16 bit word(s) to be written to the EEPROM
9418c2ecf20Sopenharmony_ci *
9428c2ecf20Sopenharmony_ci *  If ixgbe_eeprom_update_checksum is not called after this function, the
9438c2ecf20Sopenharmony_ci *  EEPROM will most likely contain an invalid checksum.
9448c2ecf20Sopenharmony_ci **/
9458c2ecf20Sopenharmony_cistatic s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
9468c2ecf20Sopenharmony_ci					      u16 words, u16 *data)
9478c2ecf20Sopenharmony_ci{
9488c2ecf20Sopenharmony_ci	s32 status;
9498c2ecf20Sopenharmony_ci	u16 word;
9508c2ecf20Sopenharmony_ci	u16 page_size;
9518c2ecf20Sopenharmony_ci	u16 i;
9528c2ecf20Sopenharmony_ci	u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	/* Prepare the EEPROM for writing  */
9558c2ecf20Sopenharmony_ci	status = ixgbe_acquire_eeprom(hw);
9568c2ecf20Sopenharmony_ci	if (status)
9578c2ecf20Sopenharmony_ci		return status;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	if (ixgbe_ready_eeprom(hw) != 0) {
9608c2ecf20Sopenharmony_ci		ixgbe_release_eeprom(hw);
9618c2ecf20Sopenharmony_ci		return -EIO;
9628c2ecf20Sopenharmony_ci	}
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	for (i = 0; i < words; i++) {
9658c2ecf20Sopenharmony_ci		ixgbe_standby_eeprom(hw);
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci		/* Send the WRITE ENABLE command (8 bit opcode) */
9688c2ecf20Sopenharmony_ci		ixgbe_shift_out_eeprom_bits(hw,
9698c2ecf20Sopenharmony_ci					    IXGBE_EEPROM_WREN_OPCODE_SPI,
9708c2ecf20Sopenharmony_ci					    IXGBE_EEPROM_OPCODE_BITS);
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci		ixgbe_standby_eeprom(hw);
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci		/* Some SPI eeproms use the 8th address bit embedded
9758c2ecf20Sopenharmony_ci		 * in the opcode
9768c2ecf20Sopenharmony_ci		 */
9778c2ecf20Sopenharmony_ci		if ((hw->eeprom.address_bits == 8) &&
9788c2ecf20Sopenharmony_ci		    ((offset + i) >= 128))
9798c2ecf20Sopenharmony_ci			write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci		/* Send the Write command (8-bit opcode + addr) */
9828c2ecf20Sopenharmony_ci		ixgbe_shift_out_eeprom_bits(hw, write_opcode,
9838c2ecf20Sopenharmony_ci					    IXGBE_EEPROM_OPCODE_BITS);
9848c2ecf20Sopenharmony_ci		ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
9858c2ecf20Sopenharmony_ci					    hw->eeprom.address_bits);
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci		page_size = hw->eeprom.word_page_size;
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci		/* Send the data in burst via SPI */
9908c2ecf20Sopenharmony_ci		do {
9918c2ecf20Sopenharmony_ci			word = data[i];
9928c2ecf20Sopenharmony_ci			word = (word >> 8) | (word << 8);
9938c2ecf20Sopenharmony_ci			ixgbe_shift_out_eeprom_bits(hw, word, 16);
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci			if (page_size == 0)
9968c2ecf20Sopenharmony_ci				break;
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci			/* do not wrap around page */
9998c2ecf20Sopenharmony_ci			if (((offset + i) & (page_size - 1)) ==
10008c2ecf20Sopenharmony_ci			    (page_size - 1))
10018c2ecf20Sopenharmony_ci				break;
10028c2ecf20Sopenharmony_ci		} while (++i < words);
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci		ixgbe_standby_eeprom(hw);
10058c2ecf20Sopenharmony_ci		usleep_range(10000, 20000);
10068c2ecf20Sopenharmony_ci	}
10078c2ecf20Sopenharmony_ci	/* Done with writing - release the EEPROM */
10088c2ecf20Sopenharmony_ci	ixgbe_release_eeprom(hw);
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	return 0;
10118c2ecf20Sopenharmony_ci}
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci/**
10148c2ecf20Sopenharmony_ci *  ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
10158c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
10168c2ecf20Sopenharmony_ci *  @offset: offset within the EEPROM to be written to
10178c2ecf20Sopenharmony_ci *  @data: 16 bit word to be written to the EEPROM
10188c2ecf20Sopenharmony_ci *
10198c2ecf20Sopenharmony_ci *  If ixgbe_eeprom_update_checksum is not called after this function, the
10208c2ecf20Sopenharmony_ci *  EEPROM will most likely contain an invalid checksum.
10218c2ecf20Sopenharmony_ci **/
10228c2ecf20Sopenharmony_cis32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
10238c2ecf20Sopenharmony_ci{
10248c2ecf20Sopenharmony_ci	hw->eeprom.ops.init_params(hw);
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	if (offset >= hw->eeprom.word_size)
10278c2ecf20Sopenharmony_ci		return -EINVAL;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	return ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data);
10308c2ecf20Sopenharmony_ci}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci/**
10338c2ecf20Sopenharmony_ci *  ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang
10348c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
10358c2ecf20Sopenharmony_ci *  @offset: offset within the EEPROM to be read
10368c2ecf20Sopenharmony_ci *  @words: number of word(s)
10378c2ecf20Sopenharmony_ci *  @data: read 16 bit words(s) from EEPROM
10388c2ecf20Sopenharmony_ci *
10398c2ecf20Sopenharmony_ci *  Reads 16 bit word(s) from EEPROM through bit-bang method
10408c2ecf20Sopenharmony_ci **/
10418c2ecf20Sopenharmony_cis32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
10428c2ecf20Sopenharmony_ci					      u16 words, u16 *data)
10438c2ecf20Sopenharmony_ci{
10448c2ecf20Sopenharmony_ci	s32 status;
10458c2ecf20Sopenharmony_ci	u16 i, count;
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	hw->eeprom.ops.init_params(hw);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	if (words == 0 || (offset + words > hw->eeprom.word_size))
10508c2ecf20Sopenharmony_ci		return -EINVAL;
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci	/*
10538c2ecf20Sopenharmony_ci	 * We cannot hold synchronization semaphores for too long
10548c2ecf20Sopenharmony_ci	 * to avoid other entity starvation. However it is more efficient
10558c2ecf20Sopenharmony_ci	 * to read in bursts than synchronizing access for each word.
10568c2ecf20Sopenharmony_ci	 */
10578c2ecf20Sopenharmony_ci	for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) {
10588c2ecf20Sopenharmony_ci		count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ?
10598c2ecf20Sopenharmony_ci			 IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i);
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci		status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i,
10628c2ecf20Sopenharmony_ci							   count, &data[i]);
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci		if (status)
10658c2ecf20Sopenharmony_ci			return status;
10668c2ecf20Sopenharmony_ci	}
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci	return 0;
10698c2ecf20Sopenharmony_ci}
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci/**
10728c2ecf20Sopenharmony_ci *  ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang
10738c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
10748c2ecf20Sopenharmony_ci *  @offset: offset within the EEPROM to be read
10758c2ecf20Sopenharmony_ci *  @words: number of word(s)
10768c2ecf20Sopenharmony_ci *  @data: read 16 bit word(s) from EEPROM
10778c2ecf20Sopenharmony_ci *
10788c2ecf20Sopenharmony_ci *  Reads 16 bit word(s) from EEPROM through bit-bang method
10798c2ecf20Sopenharmony_ci **/
10808c2ecf20Sopenharmony_cistatic s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
10818c2ecf20Sopenharmony_ci					     u16 words, u16 *data)
10828c2ecf20Sopenharmony_ci{
10838c2ecf20Sopenharmony_ci	s32 status;
10848c2ecf20Sopenharmony_ci	u16 word_in;
10858c2ecf20Sopenharmony_ci	u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
10868c2ecf20Sopenharmony_ci	u16 i;
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	/* Prepare the EEPROM for reading  */
10898c2ecf20Sopenharmony_ci	status = ixgbe_acquire_eeprom(hw);
10908c2ecf20Sopenharmony_ci	if (status)
10918c2ecf20Sopenharmony_ci		return status;
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	if (ixgbe_ready_eeprom(hw) != 0) {
10948c2ecf20Sopenharmony_ci		ixgbe_release_eeprom(hw);
10958c2ecf20Sopenharmony_ci		return -EIO;
10968c2ecf20Sopenharmony_ci	}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci	for (i = 0; i < words; i++) {
10998c2ecf20Sopenharmony_ci		ixgbe_standby_eeprom(hw);
11008c2ecf20Sopenharmony_ci		/* Some SPI eeproms use the 8th address bit embedded
11018c2ecf20Sopenharmony_ci		 * in the opcode
11028c2ecf20Sopenharmony_ci		 */
11038c2ecf20Sopenharmony_ci		if ((hw->eeprom.address_bits == 8) &&
11048c2ecf20Sopenharmony_ci		    ((offset + i) >= 128))
11058c2ecf20Sopenharmony_ci			read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci		/* Send the READ command (opcode + addr) */
11088c2ecf20Sopenharmony_ci		ixgbe_shift_out_eeprom_bits(hw, read_opcode,
11098c2ecf20Sopenharmony_ci					    IXGBE_EEPROM_OPCODE_BITS);
11108c2ecf20Sopenharmony_ci		ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
11118c2ecf20Sopenharmony_ci					    hw->eeprom.address_bits);
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci		/* Read the data. */
11148c2ecf20Sopenharmony_ci		word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
11158c2ecf20Sopenharmony_ci		data[i] = (word_in >> 8) | (word_in << 8);
11168c2ecf20Sopenharmony_ci	}
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	/* End this read operation */
11198c2ecf20Sopenharmony_ci	ixgbe_release_eeprom(hw);
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	return 0;
11228c2ecf20Sopenharmony_ci}
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci/**
11258c2ecf20Sopenharmony_ci *  ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
11268c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
11278c2ecf20Sopenharmony_ci *  @offset: offset within the EEPROM to be read
11288c2ecf20Sopenharmony_ci *  @data: read 16 bit value from EEPROM
11298c2ecf20Sopenharmony_ci *
11308c2ecf20Sopenharmony_ci *  Reads 16 bit value from EEPROM through bit-bang method
11318c2ecf20Sopenharmony_ci **/
11328c2ecf20Sopenharmony_cis32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
11338c2ecf20Sopenharmony_ci				       u16 *data)
11348c2ecf20Sopenharmony_ci{
11358c2ecf20Sopenharmony_ci	hw->eeprom.ops.init_params(hw);
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	if (offset >= hw->eeprom.word_size)
11388c2ecf20Sopenharmony_ci		return -EINVAL;
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci	return ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
11418c2ecf20Sopenharmony_ci}
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci/**
11448c2ecf20Sopenharmony_ci *  ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD
11458c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
11468c2ecf20Sopenharmony_ci *  @offset: offset of word in the EEPROM to read
11478c2ecf20Sopenharmony_ci *  @words: number of word(s)
11488c2ecf20Sopenharmony_ci *  @data: 16 bit word(s) from the EEPROM
11498c2ecf20Sopenharmony_ci *
11508c2ecf20Sopenharmony_ci *  Reads a 16 bit word(s) from the EEPROM using the EERD register.
11518c2ecf20Sopenharmony_ci **/
11528c2ecf20Sopenharmony_cis32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset,
11538c2ecf20Sopenharmony_ci				   u16 words, u16 *data)
11548c2ecf20Sopenharmony_ci{
11558c2ecf20Sopenharmony_ci	u32 eerd;
11568c2ecf20Sopenharmony_ci	s32 status;
11578c2ecf20Sopenharmony_ci	u32 i;
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	hw->eeprom.ops.init_params(hw);
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci	if (words == 0 || offset >= hw->eeprom.word_size)
11628c2ecf20Sopenharmony_ci		return -EINVAL;
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	for (i = 0; i < words; i++) {
11658c2ecf20Sopenharmony_ci		eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
11668c2ecf20Sopenharmony_ci		       IXGBE_EEPROM_RW_REG_START;
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
11698c2ecf20Sopenharmony_ci		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ);
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci		if (status == 0) {
11728c2ecf20Sopenharmony_ci			data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
11738c2ecf20Sopenharmony_ci				   IXGBE_EEPROM_RW_REG_DATA);
11748c2ecf20Sopenharmony_ci		} else {
11758c2ecf20Sopenharmony_ci			hw_dbg(hw, "Eeprom read timed out\n");
11768c2ecf20Sopenharmony_ci			return status;
11778c2ecf20Sopenharmony_ci		}
11788c2ecf20Sopenharmony_ci	}
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	return 0;
11818c2ecf20Sopenharmony_ci}
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci/**
11848c2ecf20Sopenharmony_ci *  ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size
11858c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
11868c2ecf20Sopenharmony_ci *  @offset: offset within the EEPROM to be used as a scratch pad
11878c2ecf20Sopenharmony_ci *
11888c2ecf20Sopenharmony_ci *  Discover EEPROM page size by writing marching data at given offset.
11898c2ecf20Sopenharmony_ci *  This function is called only when we are writing a new large buffer
11908c2ecf20Sopenharmony_ci *  at given offset so the data would be overwritten anyway.
11918c2ecf20Sopenharmony_ci **/
11928c2ecf20Sopenharmony_cistatic s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
11938c2ecf20Sopenharmony_ci						 u16 offset)
11948c2ecf20Sopenharmony_ci{
11958c2ecf20Sopenharmony_ci	u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX];
11968c2ecf20Sopenharmony_ci	s32 status;
11978c2ecf20Sopenharmony_ci	u16 i;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++)
12008c2ecf20Sopenharmony_ci		data[i] = i;
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX;
12038c2ecf20Sopenharmony_ci	status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset,
12048c2ecf20Sopenharmony_ci					     IXGBE_EEPROM_PAGE_SIZE_MAX, data);
12058c2ecf20Sopenharmony_ci	hw->eeprom.word_page_size = 0;
12068c2ecf20Sopenharmony_ci	if (status)
12078c2ecf20Sopenharmony_ci		return status;
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
12108c2ecf20Sopenharmony_ci	if (status)
12118c2ecf20Sopenharmony_ci		return status;
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	/*
12148c2ecf20Sopenharmony_ci	 * When writing in burst more than the actual page size
12158c2ecf20Sopenharmony_ci	 * EEPROM address wraps around current page.
12168c2ecf20Sopenharmony_ci	 */
12178c2ecf20Sopenharmony_ci	hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0];
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	hw_dbg(hw, "Detected EEPROM page size = %d words.\n",
12208c2ecf20Sopenharmony_ci	       hw->eeprom.word_page_size);
12218c2ecf20Sopenharmony_ci	return 0;
12228c2ecf20Sopenharmony_ci}
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci/**
12258c2ecf20Sopenharmony_ci *  ixgbe_read_eerd_generic - Read EEPROM word using EERD
12268c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
12278c2ecf20Sopenharmony_ci *  @offset: offset of  word in the EEPROM to read
12288c2ecf20Sopenharmony_ci *  @data: word read from the EEPROM
12298c2ecf20Sopenharmony_ci *
12308c2ecf20Sopenharmony_ci *  Reads a 16 bit word from the EEPROM using the EERD register.
12318c2ecf20Sopenharmony_ci **/
12328c2ecf20Sopenharmony_cis32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
12338c2ecf20Sopenharmony_ci{
12348c2ecf20Sopenharmony_ci	return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data);
12358c2ecf20Sopenharmony_ci}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci/**
12388c2ecf20Sopenharmony_ci *  ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR
12398c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
12408c2ecf20Sopenharmony_ci *  @offset: offset of  word in the EEPROM to write
12418c2ecf20Sopenharmony_ci *  @words: number of words
12428c2ecf20Sopenharmony_ci *  @data: word(s) write to the EEPROM
12438c2ecf20Sopenharmony_ci *
12448c2ecf20Sopenharmony_ci *  Write a 16 bit word(s) to the EEPROM using the EEWR register.
12458c2ecf20Sopenharmony_ci **/
12468c2ecf20Sopenharmony_cis32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset,
12478c2ecf20Sopenharmony_ci				    u16 words, u16 *data)
12488c2ecf20Sopenharmony_ci{
12498c2ecf20Sopenharmony_ci	u32 eewr;
12508c2ecf20Sopenharmony_ci	s32 status;
12518c2ecf20Sopenharmony_ci	u16 i;
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci	hw->eeprom.ops.init_params(hw);
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	if (words == 0 || offset >= hw->eeprom.word_size)
12568c2ecf20Sopenharmony_ci		return -EINVAL;
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	for (i = 0; i < words; i++) {
12598c2ecf20Sopenharmony_ci		eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
12608c2ecf20Sopenharmony_ci		       (data[i] << IXGBE_EEPROM_RW_REG_DATA) |
12618c2ecf20Sopenharmony_ci		       IXGBE_EEPROM_RW_REG_START;
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
12648c2ecf20Sopenharmony_ci		if (status) {
12658c2ecf20Sopenharmony_ci			hw_dbg(hw, "Eeprom write EEWR timed out\n");
12668c2ecf20Sopenharmony_ci			return status;
12678c2ecf20Sopenharmony_ci		}
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
12728c2ecf20Sopenharmony_ci		if (status) {
12738c2ecf20Sopenharmony_ci			hw_dbg(hw, "Eeprom write EEWR timed out\n");
12748c2ecf20Sopenharmony_ci			return status;
12758c2ecf20Sopenharmony_ci		}
12768c2ecf20Sopenharmony_ci	}
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	return 0;
12798c2ecf20Sopenharmony_ci}
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci/**
12828c2ecf20Sopenharmony_ci *  ixgbe_write_eewr_generic - Write EEPROM word using EEWR
12838c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
12848c2ecf20Sopenharmony_ci *  @offset: offset of  word in the EEPROM to write
12858c2ecf20Sopenharmony_ci *  @data: word write to the EEPROM
12868c2ecf20Sopenharmony_ci *
12878c2ecf20Sopenharmony_ci *  Write a 16 bit word to the EEPROM using the EEWR register.
12888c2ecf20Sopenharmony_ci **/
12898c2ecf20Sopenharmony_cis32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
12908c2ecf20Sopenharmony_ci{
12918c2ecf20Sopenharmony_ci	return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data);
12928c2ecf20Sopenharmony_ci}
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci/**
12958c2ecf20Sopenharmony_ci *  ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
12968c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
12978c2ecf20Sopenharmony_ci *  @ee_reg: EEPROM flag for polling
12988c2ecf20Sopenharmony_ci *
12998c2ecf20Sopenharmony_ci *  Polls the status bit (bit 1) of the EERD or EEWR to determine when the
13008c2ecf20Sopenharmony_ci *  read or write is done respectively.
13018c2ecf20Sopenharmony_ci **/
13028c2ecf20Sopenharmony_cistatic s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
13038c2ecf20Sopenharmony_ci{
13048c2ecf20Sopenharmony_ci	u32 i;
13058c2ecf20Sopenharmony_ci	u32 reg;
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) {
13088c2ecf20Sopenharmony_ci		if (ee_reg == IXGBE_NVM_POLL_READ)
13098c2ecf20Sopenharmony_ci			reg = IXGBE_READ_REG(hw, IXGBE_EERD);
13108c2ecf20Sopenharmony_ci		else
13118c2ecf20Sopenharmony_ci			reg = IXGBE_READ_REG(hw, IXGBE_EEWR);
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci		if (reg & IXGBE_EEPROM_RW_REG_DONE) {
13148c2ecf20Sopenharmony_ci			return 0;
13158c2ecf20Sopenharmony_ci		}
13168c2ecf20Sopenharmony_ci		udelay(5);
13178c2ecf20Sopenharmony_ci	}
13188c2ecf20Sopenharmony_ci	return -EIO;
13198c2ecf20Sopenharmony_ci}
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci/**
13228c2ecf20Sopenharmony_ci *  ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang
13238c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
13248c2ecf20Sopenharmony_ci *
13258c2ecf20Sopenharmony_ci *  Prepares EEPROM for access using bit-bang method. This function should
13268c2ecf20Sopenharmony_ci *  be called before issuing a command to the EEPROM.
13278c2ecf20Sopenharmony_ci **/
13288c2ecf20Sopenharmony_cistatic s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
13298c2ecf20Sopenharmony_ci{
13308c2ecf20Sopenharmony_ci	u32 eec;
13318c2ecf20Sopenharmony_ci	u32 i;
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
13348c2ecf20Sopenharmony_ci		return -EBUSY;
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci	eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci	/* Request EEPROM Access */
13398c2ecf20Sopenharmony_ci	eec |= IXGBE_EEC_REQ;
13408c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci	for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
13438c2ecf20Sopenharmony_ci		eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
13448c2ecf20Sopenharmony_ci		if (eec & IXGBE_EEC_GNT)
13458c2ecf20Sopenharmony_ci			break;
13468c2ecf20Sopenharmony_ci		udelay(5);
13478c2ecf20Sopenharmony_ci	}
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ci	/* Release if grant not acquired */
13508c2ecf20Sopenharmony_ci	if (!(eec & IXGBE_EEC_GNT)) {
13518c2ecf20Sopenharmony_ci		eec &= ~IXGBE_EEC_REQ;
13528c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
13538c2ecf20Sopenharmony_ci		hw_dbg(hw, "Could not acquire EEPROM grant\n");
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
13568c2ecf20Sopenharmony_ci		return -EIO;
13578c2ecf20Sopenharmony_ci	}
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	/* Setup EEPROM for Read/Write */
13608c2ecf20Sopenharmony_ci	/* Clear CS and SK */
13618c2ecf20Sopenharmony_ci	eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
13628c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
13638c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
13648c2ecf20Sopenharmony_ci	udelay(1);
13658c2ecf20Sopenharmony_ci	return 0;
13668c2ecf20Sopenharmony_ci}
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci/**
13698c2ecf20Sopenharmony_ci *  ixgbe_get_eeprom_semaphore - Get hardware semaphore
13708c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
13718c2ecf20Sopenharmony_ci *
13728c2ecf20Sopenharmony_ci *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
13738c2ecf20Sopenharmony_ci **/
13748c2ecf20Sopenharmony_cistatic s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
13758c2ecf20Sopenharmony_ci{
13768c2ecf20Sopenharmony_ci	u32 timeout = 2000;
13778c2ecf20Sopenharmony_ci	u32 i;
13788c2ecf20Sopenharmony_ci	u32 swsm;
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci	/* Get SMBI software semaphore between device drivers first */
13818c2ecf20Sopenharmony_ci	for (i = 0; i < timeout; i++) {
13828c2ecf20Sopenharmony_ci		/*
13838c2ecf20Sopenharmony_ci		 * If the SMBI bit is 0 when we read it, then the bit will be
13848c2ecf20Sopenharmony_ci		 * set and we have the semaphore
13858c2ecf20Sopenharmony_ci		 */
13868c2ecf20Sopenharmony_ci		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
13878c2ecf20Sopenharmony_ci		if (!(swsm & IXGBE_SWSM_SMBI))
13888c2ecf20Sopenharmony_ci			break;
13898c2ecf20Sopenharmony_ci		usleep_range(50, 100);
13908c2ecf20Sopenharmony_ci	}
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci	if (i == timeout) {
13938c2ecf20Sopenharmony_ci		hw_dbg(hw, "Driver can't access the Eeprom - SMBI Semaphore not granted.\n");
13948c2ecf20Sopenharmony_ci		/* this release is particularly important because our attempts
13958c2ecf20Sopenharmony_ci		 * above to get the semaphore may have succeeded, and if there
13968c2ecf20Sopenharmony_ci		 * was a timeout, we should unconditionally clear the semaphore
13978c2ecf20Sopenharmony_ci		 * bits to free the driver to make progress
13988c2ecf20Sopenharmony_ci		 */
13998c2ecf20Sopenharmony_ci		ixgbe_release_eeprom_semaphore(hw);
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci		usleep_range(50, 100);
14028c2ecf20Sopenharmony_ci		/* one last try
14038c2ecf20Sopenharmony_ci		 * If the SMBI bit is 0 when we read it, then the bit will be
14048c2ecf20Sopenharmony_ci		 * set and we have the semaphore
14058c2ecf20Sopenharmony_ci		 */
14068c2ecf20Sopenharmony_ci		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
14078c2ecf20Sopenharmony_ci		if (swsm & IXGBE_SWSM_SMBI) {
14088c2ecf20Sopenharmony_ci			hw_dbg(hw, "Software semaphore SMBI between device drivers not granted.\n");
14098c2ecf20Sopenharmony_ci			return -EIO;
14108c2ecf20Sopenharmony_ci		}
14118c2ecf20Sopenharmony_ci	}
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci	/* Now get the semaphore between SW/FW through the SWESMBI bit */
14148c2ecf20Sopenharmony_ci	for (i = 0; i < timeout; i++) {
14158c2ecf20Sopenharmony_ci		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_ci		/* Set the SW EEPROM semaphore bit to request access */
14188c2ecf20Sopenharmony_ci		swsm |= IXGBE_SWSM_SWESMBI;
14198c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_SWSM(hw), swsm);
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci		/* If we set the bit successfully then we got the
14228c2ecf20Sopenharmony_ci		 * semaphore.
14238c2ecf20Sopenharmony_ci		 */
14248c2ecf20Sopenharmony_ci		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
14258c2ecf20Sopenharmony_ci		if (swsm & IXGBE_SWSM_SWESMBI)
14268c2ecf20Sopenharmony_ci			break;
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ci		usleep_range(50, 100);
14298c2ecf20Sopenharmony_ci	}
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci	/* Release semaphores and return error if SW EEPROM semaphore
14328c2ecf20Sopenharmony_ci	 * was not granted because we don't have access to the EEPROM
14338c2ecf20Sopenharmony_ci	 */
14348c2ecf20Sopenharmony_ci	if (i >= timeout) {
14358c2ecf20Sopenharmony_ci		hw_dbg(hw, "SWESMBI Software EEPROM semaphore not granted.\n");
14368c2ecf20Sopenharmony_ci		ixgbe_release_eeprom_semaphore(hw);
14378c2ecf20Sopenharmony_ci		return -EIO;
14388c2ecf20Sopenharmony_ci	}
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	return 0;
14418c2ecf20Sopenharmony_ci}
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci/**
14448c2ecf20Sopenharmony_ci *  ixgbe_release_eeprom_semaphore - Release hardware semaphore
14458c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
14468c2ecf20Sopenharmony_ci *
14478c2ecf20Sopenharmony_ci *  This function clears hardware semaphore bits.
14488c2ecf20Sopenharmony_ci **/
14498c2ecf20Sopenharmony_cistatic void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw)
14508c2ecf20Sopenharmony_ci{
14518c2ecf20Sopenharmony_ci	u32 swsm;
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci	/* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */
14568c2ecf20Sopenharmony_ci	swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI);
14578c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_SWSM(hw), swsm);
14588c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
14598c2ecf20Sopenharmony_ci}
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci/**
14628c2ecf20Sopenharmony_ci *  ixgbe_ready_eeprom - Polls for EEPROM ready
14638c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
14648c2ecf20Sopenharmony_ci **/
14658c2ecf20Sopenharmony_cistatic s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
14668c2ecf20Sopenharmony_ci{
14678c2ecf20Sopenharmony_ci	u16 i;
14688c2ecf20Sopenharmony_ci	u8 spi_stat_reg;
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	/*
14718c2ecf20Sopenharmony_ci	 * Read "Status Register" repeatedly until the LSB is cleared.  The
14728c2ecf20Sopenharmony_ci	 * EEPROM will signal that the command has been completed by clearing
14738c2ecf20Sopenharmony_ci	 * bit 0 of the internal status register.  If it's not cleared within
14748c2ecf20Sopenharmony_ci	 * 5 milliseconds, then error out.
14758c2ecf20Sopenharmony_ci	 */
14768c2ecf20Sopenharmony_ci	for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) {
14778c2ecf20Sopenharmony_ci		ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI,
14788c2ecf20Sopenharmony_ci					    IXGBE_EEPROM_OPCODE_BITS);
14798c2ecf20Sopenharmony_ci		spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8);
14808c2ecf20Sopenharmony_ci		if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI))
14818c2ecf20Sopenharmony_ci			break;
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci		udelay(5);
14848c2ecf20Sopenharmony_ci		ixgbe_standby_eeprom(hw);
14858c2ecf20Sopenharmony_ci	}
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	/*
14888c2ecf20Sopenharmony_ci	 * On some parts, SPI write time could vary from 0-20mSec on 3.3V
14898c2ecf20Sopenharmony_ci	 * devices (and only 0-5mSec on 5V devices)
14908c2ecf20Sopenharmony_ci	 */
14918c2ecf20Sopenharmony_ci	if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
14928c2ecf20Sopenharmony_ci		hw_dbg(hw, "SPI EEPROM Status error\n");
14938c2ecf20Sopenharmony_ci		return -EIO;
14948c2ecf20Sopenharmony_ci	}
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci	return 0;
14978c2ecf20Sopenharmony_ci}
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci/**
15008c2ecf20Sopenharmony_ci *  ixgbe_standby_eeprom - Returns EEPROM to a "standby" state
15018c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
15028c2ecf20Sopenharmony_ci **/
15038c2ecf20Sopenharmony_cistatic void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
15048c2ecf20Sopenharmony_ci{
15058c2ecf20Sopenharmony_ci	u32 eec;
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ci	eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	/* Toggle CS to flush commands */
15108c2ecf20Sopenharmony_ci	eec |= IXGBE_EEC_CS;
15118c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
15128c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
15138c2ecf20Sopenharmony_ci	udelay(1);
15148c2ecf20Sopenharmony_ci	eec &= ~IXGBE_EEC_CS;
15158c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
15168c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
15178c2ecf20Sopenharmony_ci	udelay(1);
15188c2ecf20Sopenharmony_ci}
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_ci/**
15218c2ecf20Sopenharmony_ci *  ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM.
15228c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
15238c2ecf20Sopenharmony_ci *  @data: data to send to the EEPROM
15248c2ecf20Sopenharmony_ci *  @count: number of bits to shift out
15258c2ecf20Sopenharmony_ci **/
15268c2ecf20Sopenharmony_cistatic void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
15278c2ecf20Sopenharmony_ci					u16 count)
15288c2ecf20Sopenharmony_ci{
15298c2ecf20Sopenharmony_ci	u32 eec;
15308c2ecf20Sopenharmony_ci	u32 mask;
15318c2ecf20Sopenharmony_ci	u32 i;
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ci	eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci	/*
15368c2ecf20Sopenharmony_ci	 * Mask is used to shift "count" bits of "data" out to the EEPROM
15378c2ecf20Sopenharmony_ci	 * one bit at a time.  Determine the starting bit based on count
15388c2ecf20Sopenharmony_ci	 */
15398c2ecf20Sopenharmony_ci	mask = BIT(count - 1);
15408c2ecf20Sopenharmony_ci
15418c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++) {
15428c2ecf20Sopenharmony_ci		/*
15438c2ecf20Sopenharmony_ci		 * A "1" is shifted out to the EEPROM by setting bit "DI" to a
15448c2ecf20Sopenharmony_ci		 * "1", and then raising and then lowering the clock (the SK
15458c2ecf20Sopenharmony_ci		 * bit controls the clock input to the EEPROM).  A "0" is
15468c2ecf20Sopenharmony_ci		 * shifted out to the EEPROM by setting "DI" to "0" and then
15478c2ecf20Sopenharmony_ci		 * raising and then lowering the clock.
15488c2ecf20Sopenharmony_ci		 */
15498c2ecf20Sopenharmony_ci		if (data & mask)
15508c2ecf20Sopenharmony_ci			eec |= IXGBE_EEC_DI;
15518c2ecf20Sopenharmony_ci		else
15528c2ecf20Sopenharmony_ci			eec &= ~IXGBE_EEC_DI;
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
15558c2ecf20Sopenharmony_ci		IXGBE_WRITE_FLUSH(hw);
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci		udelay(1);
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci		ixgbe_raise_eeprom_clk(hw, &eec);
15608c2ecf20Sopenharmony_ci		ixgbe_lower_eeprom_clk(hw, &eec);
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci		/*
15638c2ecf20Sopenharmony_ci		 * Shift mask to signify next bit of data to shift in to the
15648c2ecf20Sopenharmony_ci		 * EEPROM
15658c2ecf20Sopenharmony_ci		 */
15668c2ecf20Sopenharmony_ci		mask = mask >> 1;
15678c2ecf20Sopenharmony_ci	}
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_ci	/* We leave the "DI" bit set to "0" when we leave this routine. */
15708c2ecf20Sopenharmony_ci	eec &= ~IXGBE_EEC_DI;
15718c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
15728c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
15738c2ecf20Sopenharmony_ci}
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci/**
15768c2ecf20Sopenharmony_ci *  ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM
15778c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
15788c2ecf20Sopenharmony_ci *  @count: number of bits to shift
15798c2ecf20Sopenharmony_ci **/
15808c2ecf20Sopenharmony_cistatic u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
15818c2ecf20Sopenharmony_ci{
15828c2ecf20Sopenharmony_ci	u32 eec;
15838c2ecf20Sopenharmony_ci	u32 i;
15848c2ecf20Sopenharmony_ci	u16 data = 0;
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	/*
15878c2ecf20Sopenharmony_ci	 * In order to read a register from the EEPROM, we need to shift
15888c2ecf20Sopenharmony_ci	 * 'count' bits in from the EEPROM. Bits are "shifted in" by raising
15898c2ecf20Sopenharmony_ci	 * the clock input to the EEPROM (setting the SK bit), and then reading
15908c2ecf20Sopenharmony_ci	 * the value of the "DO" bit.  During this "shifting in" process the
15918c2ecf20Sopenharmony_ci	 * "DI" bit should always be clear.
15928c2ecf20Sopenharmony_ci	 */
15938c2ecf20Sopenharmony_ci	eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci	eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++) {
15988c2ecf20Sopenharmony_ci		data = data << 1;
15998c2ecf20Sopenharmony_ci		ixgbe_raise_eeprom_clk(hw, &eec);
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci		eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci		eec &= ~(IXGBE_EEC_DI);
16048c2ecf20Sopenharmony_ci		if (eec & IXGBE_EEC_DO)
16058c2ecf20Sopenharmony_ci			data |= 1;
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci		ixgbe_lower_eeprom_clk(hw, &eec);
16088c2ecf20Sopenharmony_ci	}
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci	return data;
16118c2ecf20Sopenharmony_ci}
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ci/**
16148c2ecf20Sopenharmony_ci *  ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input.
16158c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
16168c2ecf20Sopenharmony_ci *  @eec: EEC register's current value
16178c2ecf20Sopenharmony_ci **/
16188c2ecf20Sopenharmony_cistatic void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
16198c2ecf20Sopenharmony_ci{
16208c2ecf20Sopenharmony_ci	/*
16218c2ecf20Sopenharmony_ci	 * Raise the clock input to the EEPROM
16228c2ecf20Sopenharmony_ci	 * (setting the SK bit), then delay
16238c2ecf20Sopenharmony_ci	 */
16248c2ecf20Sopenharmony_ci	*eec = *eec | IXGBE_EEC_SK;
16258c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), *eec);
16268c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
16278c2ecf20Sopenharmony_ci	udelay(1);
16288c2ecf20Sopenharmony_ci}
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci/**
16318c2ecf20Sopenharmony_ci *  ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input.
16328c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
16338c2ecf20Sopenharmony_ci *  @eec: EEC's current value
16348c2ecf20Sopenharmony_ci **/
16358c2ecf20Sopenharmony_cistatic void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
16368c2ecf20Sopenharmony_ci{
16378c2ecf20Sopenharmony_ci	/*
16388c2ecf20Sopenharmony_ci	 * Lower the clock input to the EEPROM (clearing the SK bit), then
16398c2ecf20Sopenharmony_ci	 * delay
16408c2ecf20Sopenharmony_ci	 */
16418c2ecf20Sopenharmony_ci	*eec = *eec & ~IXGBE_EEC_SK;
16428c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), *eec);
16438c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
16448c2ecf20Sopenharmony_ci	udelay(1);
16458c2ecf20Sopenharmony_ci}
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci/**
16488c2ecf20Sopenharmony_ci *  ixgbe_release_eeprom - Release EEPROM, release semaphores
16498c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
16508c2ecf20Sopenharmony_ci **/
16518c2ecf20Sopenharmony_cistatic void ixgbe_release_eeprom(struct ixgbe_hw *hw)
16528c2ecf20Sopenharmony_ci{
16538c2ecf20Sopenharmony_ci	u32 eec;
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ci	eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci	eec |= IXGBE_EEC_CS;  /* Pull CS high */
16588c2ecf20Sopenharmony_ci	eec &= ~IXGBE_EEC_SK; /* Lower SCK */
16598c2ecf20Sopenharmony_ci
16608c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
16618c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
16628c2ecf20Sopenharmony_ci
16638c2ecf20Sopenharmony_ci	udelay(1);
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	/* Stop requesting EEPROM access */
16668c2ecf20Sopenharmony_ci	eec &= ~IXGBE_EEC_REQ;
16678c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci	/*
16728c2ecf20Sopenharmony_ci	 * Delay before attempt to obtain semaphore again to allow FW
16738c2ecf20Sopenharmony_ci	 * access. semaphore_delay is in ms we need us for usleep_range
16748c2ecf20Sopenharmony_ci	 */
16758c2ecf20Sopenharmony_ci	usleep_range(hw->eeprom.semaphore_delay * 1000,
16768c2ecf20Sopenharmony_ci		     hw->eeprom.semaphore_delay * 2000);
16778c2ecf20Sopenharmony_ci}
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci/**
16808c2ecf20Sopenharmony_ci *  ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
16818c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
16828c2ecf20Sopenharmony_ci **/
16838c2ecf20Sopenharmony_cis32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
16848c2ecf20Sopenharmony_ci{
16858c2ecf20Sopenharmony_ci	u16 i;
16868c2ecf20Sopenharmony_ci	u16 j;
16878c2ecf20Sopenharmony_ci	u16 checksum = 0;
16888c2ecf20Sopenharmony_ci	u16 length = 0;
16898c2ecf20Sopenharmony_ci	u16 pointer = 0;
16908c2ecf20Sopenharmony_ci	u16 word = 0;
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	/* Include 0x0-0x3F in the checksum */
16938c2ecf20Sopenharmony_ci	for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
16948c2ecf20Sopenharmony_ci		if (hw->eeprom.ops.read(hw, i, &word)) {
16958c2ecf20Sopenharmony_ci			hw_dbg(hw, "EEPROM read failed\n");
16968c2ecf20Sopenharmony_ci			break;
16978c2ecf20Sopenharmony_ci		}
16988c2ecf20Sopenharmony_ci		checksum += word;
16998c2ecf20Sopenharmony_ci	}
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci	/* Include all data from pointers except for the fw pointer */
17028c2ecf20Sopenharmony_ci	for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
17038c2ecf20Sopenharmony_ci		if (hw->eeprom.ops.read(hw, i, &pointer)) {
17048c2ecf20Sopenharmony_ci			hw_dbg(hw, "EEPROM read failed\n");
17058c2ecf20Sopenharmony_ci			return -EIO;
17068c2ecf20Sopenharmony_ci		}
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci		/* If the pointer seems invalid */
17098c2ecf20Sopenharmony_ci		if (pointer == 0xFFFF || pointer == 0)
17108c2ecf20Sopenharmony_ci			continue;
17118c2ecf20Sopenharmony_ci
17128c2ecf20Sopenharmony_ci		if (hw->eeprom.ops.read(hw, pointer, &length)) {
17138c2ecf20Sopenharmony_ci			hw_dbg(hw, "EEPROM read failed\n");
17148c2ecf20Sopenharmony_ci			return -EIO;
17158c2ecf20Sopenharmony_ci		}
17168c2ecf20Sopenharmony_ci
17178c2ecf20Sopenharmony_ci		if (length == 0xFFFF || length == 0)
17188c2ecf20Sopenharmony_ci			continue;
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci		for (j = pointer + 1; j <= pointer + length; j++) {
17218c2ecf20Sopenharmony_ci			if (hw->eeprom.ops.read(hw, j, &word)) {
17228c2ecf20Sopenharmony_ci				hw_dbg(hw, "EEPROM read failed\n");
17238c2ecf20Sopenharmony_ci				return -EIO;
17248c2ecf20Sopenharmony_ci			}
17258c2ecf20Sopenharmony_ci			checksum += word;
17268c2ecf20Sopenharmony_ci		}
17278c2ecf20Sopenharmony_ci	}
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
17308c2ecf20Sopenharmony_ci
17318c2ecf20Sopenharmony_ci	return (s32)checksum;
17328c2ecf20Sopenharmony_ci}
17338c2ecf20Sopenharmony_ci
17348c2ecf20Sopenharmony_ci/**
17358c2ecf20Sopenharmony_ci *  ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum
17368c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
17378c2ecf20Sopenharmony_ci *  @checksum_val: calculated checksum
17388c2ecf20Sopenharmony_ci *
17398c2ecf20Sopenharmony_ci *  Performs checksum calculation and validates the EEPROM checksum.  If the
17408c2ecf20Sopenharmony_ci *  caller does not need checksum_val, the value can be NULL.
17418c2ecf20Sopenharmony_ci **/
17428c2ecf20Sopenharmony_cis32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
17438c2ecf20Sopenharmony_ci					   u16 *checksum_val)
17448c2ecf20Sopenharmony_ci{
17458c2ecf20Sopenharmony_ci	s32 status;
17468c2ecf20Sopenharmony_ci	u16 checksum;
17478c2ecf20Sopenharmony_ci	u16 read_checksum = 0;
17488c2ecf20Sopenharmony_ci
17498c2ecf20Sopenharmony_ci	/*
17508c2ecf20Sopenharmony_ci	 * Read the first word from the EEPROM. If this times out or fails, do
17518c2ecf20Sopenharmony_ci	 * not continue or we could be in for a very long wait while every
17528c2ecf20Sopenharmony_ci	 * EEPROM read fails
17538c2ecf20Sopenharmony_ci	 */
17548c2ecf20Sopenharmony_ci	status = hw->eeprom.ops.read(hw, 0, &checksum);
17558c2ecf20Sopenharmony_ci	if (status) {
17568c2ecf20Sopenharmony_ci		hw_dbg(hw, "EEPROM read failed\n");
17578c2ecf20Sopenharmony_ci		return status;
17588c2ecf20Sopenharmony_ci	}
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ci	status = hw->eeprom.ops.calc_checksum(hw);
17618c2ecf20Sopenharmony_ci	if (status < 0)
17628c2ecf20Sopenharmony_ci		return status;
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci	checksum = (u16)(status & 0xffff);
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_ci	status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
17678c2ecf20Sopenharmony_ci	if (status) {
17688c2ecf20Sopenharmony_ci		hw_dbg(hw, "EEPROM read failed\n");
17698c2ecf20Sopenharmony_ci		return status;
17708c2ecf20Sopenharmony_ci	}
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_ci	/* Verify read checksum from EEPROM is the same as
17738c2ecf20Sopenharmony_ci	 * calculated checksum
17748c2ecf20Sopenharmony_ci	 */
17758c2ecf20Sopenharmony_ci	if (read_checksum != checksum)
17768c2ecf20Sopenharmony_ci		status = -EIO;
17778c2ecf20Sopenharmony_ci
17788c2ecf20Sopenharmony_ci	/* If the user cares, return the calculated checksum */
17798c2ecf20Sopenharmony_ci	if (checksum_val)
17808c2ecf20Sopenharmony_ci		*checksum_val = checksum;
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	return status;
17838c2ecf20Sopenharmony_ci}
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci/**
17868c2ecf20Sopenharmony_ci *  ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum
17878c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
17888c2ecf20Sopenharmony_ci **/
17898c2ecf20Sopenharmony_cis32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
17908c2ecf20Sopenharmony_ci{
17918c2ecf20Sopenharmony_ci	s32 status;
17928c2ecf20Sopenharmony_ci	u16 checksum;
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_ci	/*
17958c2ecf20Sopenharmony_ci	 * Read the first word from the EEPROM. If this times out or fails, do
17968c2ecf20Sopenharmony_ci	 * not continue or we could be in for a very long wait while every
17978c2ecf20Sopenharmony_ci	 * EEPROM read fails
17988c2ecf20Sopenharmony_ci	 */
17998c2ecf20Sopenharmony_ci	status = hw->eeprom.ops.read(hw, 0, &checksum);
18008c2ecf20Sopenharmony_ci	if (status) {
18018c2ecf20Sopenharmony_ci		hw_dbg(hw, "EEPROM read failed\n");
18028c2ecf20Sopenharmony_ci		return status;
18038c2ecf20Sopenharmony_ci	}
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci	status = hw->eeprom.ops.calc_checksum(hw);
18068c2ecf20Sopenharmony_ci	if (status < 0)
18078c2ecf20Sopenharmony_ci		return status;
18088c2ecf20Sopenharmony_ci
18098c2ecf20Sopenharmony_ci	checksum = (u16)(status & 0xffff);
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_ci	status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum);
18128c2ecf20Sopenharmony_ci
18138c2ecf20Sopenharmony_ci	return status;
18148c2ecf20Sopenharmony_ci}
18158c2ecf20Sopenharmony_ci
18168c2ecf20Sopenharmony_ci/**
18178c2ecf20Sopenharmony_ci *  ixgbe_set_rar_generic - Set Rx address register
18188c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
18198c2ecf20Sopenharmony_ci *  @index: Receive address register to write
18208c2ecf20Sopenharmony_ci *  @addr: Address to put into receive address register
18218c2ecf20Sopenharmony_ci *  @vmdq: VMDq "set" or "pool" index
18228c2ecf20Sopenharmony_ci *  @enable_addr: set flag that address is active
18238c2ecf20Sopenharmony_ci *
18248c2ecf20Sopenharmony_ci *  Puts an ethernet address into a receive address register.
18258c2ecf20Sopenharmony_ci **/
18268c2ecf20Sopenharmony_cis32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
18278c2ecf20Sopenharmony_ci			  u32 enable_addr)
18288c2ecf20Sopenharmony_ci{
18298c2ecf20Sopenharmony_ci	u32 rar_low, rar_high;
18308c2ecf20Sopenharmony_ci	u32 rar_entries = hw->mac.num_rar_entries;
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci	/* Make sure we are using a valid rar index range */
18338c2ecf20Sopenharmony_ci	if (index >= rar_entries) {
18348c2ecf20Sopenharmony_ci		hw_dbg(hw, "RAR index %d is out of range.\n", index);
18358c2ecf20Sopenharmony_ci		return -EINVAL;
18368c2ecf20Sopenharmony_ci	}
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci	/* setup VMDq pool selection before this RAR gets enabled */
18398c2ecf20Sopenharmony_ci	hw->mac.ops.set_vmdq(hw, index, vmdq);
18408c2ecf20Sopenharmony_ci
18418c2ecf20Sopenharmony_ci	/*
18428c2ecf20Sopenharmony_ci	 * HW expects these in little endian so we reverse the byte
18438c2ecf20Sopenharmony_ci	 * order from network order (big endian) to little endian
18448c2ecf20Sopenharmony_ci	 */
18458c2ecf20Sopenharmony_ci	rar_low = ((u32)addr[0] |
18468c2ecf20Sopenharmony_ci		   ((u32)addr[1] << 8) |
18478c2ecf20Sopenharmony_ci		   ((u32)addr[2] << 16) |
18488c2ecf20Sopenharmony_ci		   ((u32)addr[3] << 24));
18498c2ecf20Sopenharmony_ci	/*
18508c2ecf20Sopenharmony_ci	 * Some parts put the VMDq setting in the extra RAH bits,
18518c2ecf20Sopenharmony_ci	 * so save everything except the lower 16 bits that hold part
18528c2ecf20Sopenharmony_ci	 * of the address and the address valid bit.
18538c2ecf20Sopenharmony_ci	 */
18548c2ecf20Sopenharmony_ci	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
18558c2ecf20Sopenharmony_ci	rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
18568c2ecf20Sopenharmony_ci	rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	if (enable_addr != 0)
18598c2ecf20Sopenharmony_ci		rar_high |= IXGBE_RAH_AV;
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci	/* Record lower 32 bits of MAC address and then make
18628c2ecf20Sopenharmony_ci	 * sure that write is flushed to hardware before writing
18638c2ecf20Sopenharmony_ci	 * the upper 16 bits and setting the valid bit.
18648c2ecf20Sopenharmony_ci	 */
18658c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
18668c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
18678c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci	return 0;
18708c2ecf20Sopenharmony_ci}
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ci/**
18738c2ecf20Sopenharmony_ci *  ixgbe_clear_rar_generic - Remove Rx address register
18748c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
18758c2ecf20Sopenharmony_ci *  @index: Receive address register to write
18768c2ecf20Sopenharmony_ci *
18778c2ecf20Sopenharmony_ci *  Clears an ethernet address from a receive address register.
18788c2ecf20Sopenharmony_ci **/
18798c2ecf20Sopenharmony_cis32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
18808c2ecf20Sopenharmony_ci{
18818c2ecf20Sopenharmony_ci	u32 rar_high;
18828c2ecf20Sopenharmony_ci	u32 rar_entries = hw->mac.num_rar_entries;
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_ci	/* Make sure we are using a valid rar index range */
18858c2ecf20Sopenharmony_ci	if (index >= rar_entries) {
18868c2ecf20Sopenharmony_ci		hw_dbg(hw, "RAR index %d is out of range.\n", index);
18878c2ecf20Sopenharmony_ci		return -EINVAL;
18888c2ecf20Sopenharmony_ci	}
18898c2ecf20Sopenharmony_ci
18908c2ecf20Sopenharmony_ci	/*
18918c2ecf20Sopenharmony_ci	 * Some parts put the VMDq setting in the extra RAH bits,
18928c2ecf20Sopenharmony_ci	 * so save everything except the lower 16 bits that hold part
18938c2ecf20Sopenharmony_ci	 * of the address and the address valid bit.
18948c2ecf20Sopenharmony_ci	 */
18958c2ecf20Sopenharmony_ci	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
18968c2ecf20Sopenharmony_ci	rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
18978c2ecf20Sopenharmony_ci
18988c2ecf20Sopenharmony_ci	/* Clear the address valid bit and upper 16 bits of the address
18998c2ecf20Sopenharmony_ci	 * before clearing the lower bits. This way we aren't updating
19008c2ecf20Sopenharmony_ci	 * a live filter.
19018c2ecf20Sopenharmony_ci	 */
19028c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
19038c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
19048c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
19058c2ecf20Sopenharmony_ci
19068c2ecf20Sopenharmony_ci	/* clear VMDq pool/queue selection for this RAR */
19078c2ecf20Sopenharmony_ci	hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci	return 0;
19108c2ecf20Sopenharmony_ci}
19118c2ecf20Sopenharmony_ci
19128c2ecf20Sopenharmony_ci/**
19138c2ecf20Sopenharmony_ci *  ixgbe_init_rx_addrs_generic - Initializes receive address filters.
19148c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
19158c2ecf20Sopenharmony_ci *
19168c2ecf20Sopenharmony_ci *  Places the MAC address in receive address register 0 and clears the rest
19178c2ecf20Sopenharmony_ci *  of the receive address registers. Clears the multicast table. Assumes
19188c2ecf20Sopenharmony_ci *  the receiver is in reset when the routine is called.
19198c2ecf20Sopenharmony_ci **/
19208c2ecf20Sopenharmony_cis32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
19218c2ecf20Sopenharmony_ci{
19228c2ecf20Sopenharmony_ci	u32 i;
19238c2ecf20Sopenharmony_ci	u32 rar_entries = hw->mac.num_rar_entries;
19248c2ecf20Sopenharmony_ci
19258c2ecf20Sopenharmony_ci	/*
19268c2ecf20Sopenharmony_ci	 * If the current mac address is valid, assume it is a software override
19278c2ecf20Sopenharmony_ci	 * to the permanent address.
19288c2ecf20Sopenharmony_ci	 * Otherwise, use the permanent address from the eeprom.
19298c2ecf20Sopenharmony_ci	 */
19308c2ecf20Sopenharmony_ci	if (!is_valid_ether_addr(hw->mac.addr)) {
19318c2ecf20Sopenharmony_ci		/* Get the MAC address from the RAR0 for later reference */
19328c2ecf20Sopenharmony_ci		hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
19338c2ecf20Sopenharmony_ci
19348c2ecf20Sopenharmony_ci		hw_dbg(hw, " Keeping Current RAR0 Addr =%pM\n", hw->mac.addr);
19358c2ecf20Sopenharmony_ci	} else {
19368c2ecf20Sopenharmony_ci		/* Setup the receive address. */
19378c2ecf20Sopenharmony_ci		hw_dbg(hw, "Overriding MAC Address in RAR[0]\n");
19388c2ecf20Sopenharmony_ci		hw_dbg(hw, " New MAC Addr =%pM\n", hw->mac.addr);
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_ci		hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
19418c2ecf20Sopenharmony_ci	}
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci	/*  clear VMDq pool/queue selection for RAR 0 */
19448c2ecf20Sopenharmony_ci	hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL);
19458c2ecf20Sopenharmony_ci
19468c2ecf20Sopenharmony_ci	hw->addr_ctrl.overflow_promisc = 0;
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci	hw->addr_ctrl.rar_used_count = 1;
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci	/* Zero out the other receive addresses. */
19518c2ecf20Sopenharmony_ci	hw_dbg(hw, "Clearing RAR[1-%d]\n", rar_entries - 1);
19528c2ecf20Sopenharmony_ci	for (i = 1; i < rar_entries; i++) {
19538c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
19548c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
19558c2ecf20Sopenharmony_ci	}
19568c2ecf20Sopenharmony_ci
19578c2ecf20Sopenharmony_ci	/* Clear the MTA */
19588c2ecf20Sopenharmony_ci	hw->addr_ctrl.mta_in_use = 0;
19598c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ci	hw_dbg(hw, " Clearing MTA\n");
19628c2ecf20Sopenharmony_ci	for (i = 0; i < hw->mac.mcft_size; i++)
19638c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_ci	if (hw->mac.ops.init_uta_tables)
19668c2ecf20Sopenharmony_ci		hw->mac.ops.init_uta_tables(hw);
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_ci	return 0;
19698c2ecf20Sopenharmony_ci}
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci/**
19728c2ecf20Sopenharmony_ci *  ixgbe_mta_vector - Determines bit-vector in multicast table to set
19738c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
19748c2ecf20Sopenharmony_ci *  @mc_addr: the multicast address
19758c2ecf20Sopenharmony_ci *
19768c2ecf20Sopenharmony_ci *  Extracts the 12 bits, from a multicast address, to determine which
19778c2ecf20Sopenharmony_ci *  bit-vector to set in the multicast table. The hardware uses 12 bits, from
19788c2ecf20Sopenharmony_ci *  incoming rx multicast addresses, to determine the bit-vector to check in
19798c2ecf20Sopenharmony_ci *  the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set
19808c2ecf20Sopenharmony_ci *  by the MO field of the MCSTCTRL. The MO field is set during initialization
19818c2ecf20Sopenharmony_ci *  to mc_filter_type.
19828c2ecf20Sopenharmony_ci **/
19838c2ecf20Sopenharmony_cistatic s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr)
19848c2ecf20Sopenharmony_ci{
19858c2ecf20Sopenharmony_ci	u32 vector = 0;
19868c2ecf20Sopenharmony_ci
19878c2ecf20Sopenharmony_ci	switch (hw->mac.mc_filter_type) {
19888c2ecf20Sopenharmony_ci	case 0:   /* use bits [47:36] of the address */
19898c2ecf20Sopenharmony_ci		vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
19908c2ecf20Sopenharmony_ci		break;
19918c2ecf20Sopenharmony_ci	case 1:   /* use bits [46:35] of the address */
19928c2ecf20Sopenharmony_ci		vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
19938c2ecf20Sopenharmony_ci		break;
19948c2ecf20Sopenharmony_ci	case 2:   /* use bits [45:34] of the address */
19958c2ecf20Sopenharmony_ci		vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
19968c2ecf20Sopenharmony_ci		break;
19978c2ecf20Sopenharmony_ci	case 3:   /* use bits [43:32] of the address */
19988c2ecf20Sopenharmony_ci		vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
19998c2ecf20Sopenharmony_ci		break;
20008c2ecf20Sopenharmony_ci	default:  /* Invalid mc_filter_type */
20018c2ecf20Sopenharmony_ci		hw_dbg(hw, "MC filter type param set incorrectly\n");
20028c2ecf20Sopenharmony_ci		break;
20038c2ecf20Sopenharmony_ci	}
20048c2ecf20Sopenharmony_ci
20058c2ecf20Sopenharmony_ci	/* vector can only be 12-bits or boundary will be exceeded */
20068c2ecf20Sopenharmony_ci	vector &= 0xFFF;
20078c2ecf20Sopenharmony_ci	return vector;
20088c2ecf20Sopenharmony_ci}
20098c2ecf20Sopenharmony_ci
20108c2ecf20Sopenharmony_ci/**
20118c2ecf20Sopenharmony_ci *  ixgbe_set_mta - Set bit-vector in multicast table
20128c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
20138c2ecf20Sopenharmony_ci *  @mc_addr: Multicast address
20148c2ecf20Sopenharmony_ci *
20158c2ecf20Sopenharmony_ci *  Sets the bit-vector in the multicast table.
20168c2ecf20Sopenharmony_ci **/
20178c2ecf20Sopenharmony_cistatic void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
20188c2ecf20Sopenharmony_ci{
20198c2ecf20Sopenharmony_ci	u32 vector;
20208c2ecf20Sopenharmony_ci	u32 vector_bit;
20218c2ecf20Sopenharmony_ci	u32 vector_reg;
20228c2ecf20Sopenharmony_ci
20238c2ecf20Sopenharmony_ci	hw->addr_ctrl.mta_in_use++;
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci	vector = ixgbe_mta_vector(hw, mc_addr);
20268c2ecf20Sopenharmony_ci	hw_dbg(hw, " bit-vector = 0x%03X\n", vector);
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci	/*
20298c2ecf20Sopenharmony_ci	 * The MTA is a register array of 128 32-bit registers. It is treated
20308c2ecf20Sopenharmony_ci	 * like an array of 4096 bits.  We want to set bit
20318c2ecf20Sopenharmony_ci	 * BitArray[vector_value]. So we figure out what register the bit is
20328c2ecf20Sopenharmony_ci	 * in, read it, OR in the new bit, then write back the new value.  The
20338c2ecf20Sopenharmony_ci	 * register is determined by the upper 7 bits of the vector value and
20348c2ecf20Sopenharmony_ci	 * the bit within that register are determined by the lower 5 bits of
20358c2ecf20Sopenharmony_ci	 * the value.
20368c2ecf20Sopenharmony_ci	 */
20378c2ecf20Sopenharmony_ci	vector_reg = (vector >> 5) & 0x7F;
20388c2ecf20Sopenharmony_ci	vector_bit = vector & 0x1F;
20398c2ecf20Sopenharmony_ci	hw->mac.mta_shadow[vector_reg] |= BIT(vector_bit);
20408c2ecf20Sopenharmony_ci}
20418c2ecf20Sopenharmony_ci
20428c2ecf20Sopenharmony_ci/**
20438c2ecf20Sopenharmony_ci *  ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
20448c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
20458c2ecf20Sopenharmony_ci *  @netdev: pointer to net device structure
20468c2ecf20Sopenharmony_ci *
20478c2ecf20Sopenharmony_ci *  The given list replaces any existing list. Clears the MC addrs from receive
20488c2ecf20Sopenharmony_ci *  address registers and the multicast table. Uses unused receive address
20498c2ecf20Sopenharmony_ci *  registers for the first multicast addresses, and hashes the rest into the
20508c2ecf20Sopenharmony_ci *  multicast table.
20518c2ecf20Sopenharmony_ci **/
20528c2ecf20Sopenharmony_cis32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw,
20538c2ecf20Sopenharmony_ci				      struct net_device *netdev)
20548c2ecf20Sopenharmony_ci{
20558c2ecf20Sopenharmony_ci	struct netdev_hw_addr *ha;
20568c2ecf20Sopenharmony_ci	u32 i;
20578c2ecf20Sopenharmony_ci
20588c2ecf20Sopenharmony_ci	/*
20598c2ecf20Sopenharmony_ci	 * Set the new number of MC addresses that we are being requested to
20608c2ecf20Sopenharmony_ci	 * use.
20618c2ecf20Sopenharmony_ci	 */
20628c2ecf20Sopenharmony_ci	hw->addr_ctrl.num_mc_addrs = netdev_mc_count(netdev);
20638c2ecf20Sopenharmony_ci	hw->addr_ctrl.mta_in_use = 0;
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_ci	/* Clear mta_shadow */
20668c2ecf20Sopenharmony_ci	hw_dbg(hw, " Clearing MTA\n");
20678c2ecf20Sopenharmony_ci	memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
20688c2ecf20Sopenharmony_ci
20698c2ecf20Sopenharmony_ci	/* Update mta shadow */
20708c2ecf20Sopenharmony_ci	netdev_for_each_mc_addr(ha, netdev) {
20718c2ecf20Sopenharmony_ci		hw_dbg(hw, " Adding the multicast addresses:\n");
20728c2ecf20Sopenharmony_ci		ixgbe_set_mta(hw, ha->addr);
20738c2ecf20Sopenharmony_ci	}
20748c2ecf20Sopenharmony_ci
20758c2ecf20Sopenharmony_ci	/* Enable mta */
20768c2ecf20Sopenharmony_ci	for (i = 0; i < hw->mac.mcft_size; i++)
20778c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i,
20788c2ecf20Sopenharmony_ci				      hw->mac.mta_shadow[i]);
20798c2ecf20Sopenharmony_ci
20808c2ecf20Sopenharmony_ci	if (hw->addr_ctrl.mta_in_use > 0)
20818c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,
20828c2ecf20Sopenharmony_ci				IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_ci	hw_dbg(hw, "ixgbe_update_mc_addr_list_generic Complete\n");
20858c2ecf20Sopenharmony_ci	return 0;
20868c2ecf20Sopenharmony_ci}
20878c2ecf20Sopenharmony_ci
20888c2ecf20Sopenharmony_ci/**
20898c2ecf20Sopenharmony_ci *  ixgbe_enable_mc_generic - Enable multicast address in RAR
20908c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
20918c2ecf20Sopenharmony_ci *
20928c2ecf20Sopenharmony_ci *  Enables multicast address in RAR and the use of the multicast hash table.
20938c2ecf20Sopenharmony_ci **/
20948c2ecf20Sopenharmony_cis32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
20958c2ecf20Sopenharmony_ci{
20968c2ecf20Sopenharmony_ci	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
20978c2ecf20Sopenharmony_ci
20988c2ecf20Sopenharmony_ci	if (a->mta_in_use > 0)
20998c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
21008c2ecf20Sopenharmony_ci				hw->mac.mc_filter_type);
21018c2ecf20Sopenharmony_ci
21028c2ecf20Sopenharmony_ci	return 0;
21038c2ecf20Sopenharmony_ci}
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ci/**
21068c2ecf20Sopenharmony_ci *  ixgbe_disable_mc_generic - Disable multicast address in RAR
21078c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
21088c2ecf20Sopenharmony_ci *
21098c2ecf20Sopenharmony_ci *  Disables multicast address in RAR and the use of the multicast hash table.
21108c2ecf20Sopenharmony_ci **/
21118c2ecf20Sopenharmony_cis32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
21128c2ecf20Sopenharmony_ci{
21138c2ecf20Sopenharmony_ci	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci	if (a->mta_in_use > 0)
21168c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
21178c2ecf20Sopenharmony_ci
21188c2ecf20Sopenharmony_ci	return 0;
21198c2ecf20Sopenharmony_ci}
21208c2ecf20Sopenharmony_ci
21218c2ecf20Sopenharmony_ci/**
21228c2ecf20Sopenharmony_ci *  ixgbe_fc_enable_generic - Enable flow control
21238c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
21248c2ecf20Sopenharmony_ci *
21258c2ecf20Sopenharmony_ci *  Enable flow control according to the current settings.
21268c2ecf20Sopenharmony_ci **/
21278c2ecf20Sopenharmony_cis32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
21288c2ecf20Sopenharmony_ci{
21298c2ecf20Sopenharmony_ci	u32 mflcn_reg, fccfg_reg;
21308c2ecf20Sopenharmony_ci	u32 reg;
21318c2ecf20Sopenharmony_ci	u32 fcrtl, fcrth;
21328c2ecf20Sopenharmony_ci	int i;
21338c2ecf20Sopenharmony_ci
21348c2ecf20Sopenharmony_ci	/* Validate the water mark configuration. */
21358c2ecf20Sopenharmony_ci	if (!hw->fc.pause_time)
21368c2ecf20Sopenharmony_ci		return -EINVAL;
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_ci	/* Low water mark of zero causes XOFF floods */
21398c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
21408c2ecf20Sopenharmony_ci		if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
21418c2ecf20Sopenharmony_ci		    hw->fc.high_water[i]) {
21428c2ecf20Sopenharmony_ci			if (!hw->fc.low_water[i] ||
21438c2ecf20Sopenharmony_ci			    hw->fc.low_water[i] >= hw->fc.high_water[i]) {
21448c2ecf20Sopenharmony_ci				hw_dbg(hw, "Invalid water mark configuration\n");
21458c2ecf20Sopenharmony_ci				return -EINVAL;
21468c2ecf20Sopenharmony_ci			}
21478c2ecf20Sopenharmony_ci		}
21488c2ecf20Sopenharmony_ci	}
21498c2ecf20Sopenharmony_ci
21508c2ecf20Sopenharmony_ci	/* Negotiate the fc mode to use */
21518c2ecf20Sopenharmony_ci	hw->mac.ops.fc_autoneg(hw);
21528c2ecf20Sopenharmony_ci
21538c2ecf20Sopenharmony_ci	/* Disable any previous flow control settings */
21548c2ecf20Sopenharmony_ci	mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
21558c2ecf20Sopenharmony_ci	mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE);
21568c2ecf20Sopenharmony_ci
21578c2ecf20Sopenharmony_ci	fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
21588c2ecf20Sopenharmony_ci	fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_ci	/*
21618c2ecf20Sopenharmony_ci	 * The possible values of fc.current_mode are:
21628c2ecf20Sopenharmony_ci	 * 0: Flow control is completely disabled
21638c2ecf20Sopenharmony_ci	 * 1: Rx flow control is enabled (we can receive pause frames,
21648c2ecf20Sopenharmony_ci	 *    but not send pause frames).
21658c2ecf20Sopenharmony_ci	 * 2: Tx flow control is enabled (we can send pause frames but
21668c2ecf20Sopenharmony_ci	 *    we do not support receiving pause frames).
21678c2ecf20Sopenharmony_ci	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
21688c2ecf20Sopenharmony_ci	 * other: Invalid.
21698c2ecf20Sopenharmony_ci	 */
21708c2ecf20Sopenharmony_ci	switch (hw->fc.current_mode) {
21718c2ecf20Sopenharmony_ci	case ixgbe_fc_none:
21728c2ecf20Sopenharmony_ci		/*
21738c2ecf20Sopenharmony_ci		 * Flow control is disabled by software override or autoneg.
21748c2ecf20Sopenharmony_ci		 * The code below will actually disable it in the HW.
21758c2ecf20Sopenharmony_ci		 */
21768c2ecf20Sopenharmony_ci		break;
21778c2ecf20Sopenharmony_ci	case ixgbe_fc_rx_pause:
21788c2ecf20Sopenharmony_ci		/*
21798c2ecf20Sopenharmony_ci		 * Rx Flow control is enabled and Tx Flow control is
21808c2ecf20Sopenharmony_ci		 * disabled by software override. Since there really
21818c2ecf20Sopenharmony_ci		 * isn't a way to advertise that we are capable of RX
21828c2ecf20Sopenharmony_ci		 * Pause ONLY, we will advertise that we support both
21838c2ecf20Sopenharmony_ci		 * symmetric and asymmetric Rx PAUSE.  Later, we will
21848c2ecf20Sopenharmony_ci		 * disable the adapter's ability to send PAUSE frames.
21858c2ecf20Sopenharmony_ci		 */
21868c2ecf20Sopenharmony_ci		mflcn_reg |= IXGBE_MFLCN_RFCE;
21878c2ecf20Sopenharmony_ci		break;
21888c2ecf20Sopenharmony_ci	case ixgbe_fc_tx_pause:
21898c2ecf20Sopenharmony_ci		/*
21908c2ecf20Sopenharmony_ci		 * Tx Flow control is enabled, and Rx Flow control is
21918c2ecf20Sopenharmony_ci		 * disabled by software override.
21928c2ecf20Sopenharmony_ci		 */
21938c2ecf20Sopenharmony_ci		fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
21948c2ecf20Sopenharmony_ci		break;
21958c2ecf20Sopenharmony_ci	case ixgbe_fc_full:
21968c2ecf20Sopenharmony_ci		/* Flow control (both Rx and Tx) is enabled by SW override. */
21978c2ecf20Sopenharmony_ci		mflcn_reg |= IXGBE_MFLCN_RFCE;
21988c2ecf20Sopenharmony_ci		fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
21998c2ecf20Sopenharmony_ci		break;
22008c2ecf20Sopenharmony_ci	default:
22018c2ecf20Sopenharmony_ci		hw_dbg(hw, "Flow control param set incorrectly\n");
22028c2ecf20Sopenharmony_ci		return -EIO;
22038c2ecf20Sopenharmony_ci	}
22048c2ecf20Sopenharmony_ci
22058c2ecf20Sopenharmony_ci	/* Set 802.3x based flow control settings. */
22068c2ecf20Sopenharmony_ci	mflcn_reg |= IXGBE_MFLCN_DPF;
22078c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
22088c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ci	/* Set up and enable Rx high/low water mark thresholds, enable XON. */
22118c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
22128c2ecf20Sopenharmony_ci		if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
22138c2ecf20Sopenharmony_ci		    hw->fc.high_water[i]) {
22148c2ecf20Sopenharmony_ci			fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
22158c2ecf20Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
22168c2ecf20Sopenharmony_ci			fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
22178c2ecf20Sopenharmony_ci		} else {
22188c2ecf20Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
22198c2ecf20Sopenharmony_ci			/*
22208c2ecf20Sopenharmony_ci			 * In order to prevent Tx hangs when the internal Tx
22218c2ecf20Sopenharmony_ci			 * switch is enabled we must set the high water mark
22228c2ecf20Sopenharmony_ci			 * to the Rx packet buffer size - 24KB.  This allows
22238c2ecf20Sopenharmony_ci			 * the Tx switch to function even under heavy Rx
22248c2ecf20Sopenharmony_ci			 * workloads.
22258c2ecf20Sopenharmony_ci			 */
22268c2ecf20Sopenharmony_ci			fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576;
22278c2ecf20Sopenharmony_ci		}
22288c2ecf20Sopenharmony_ci
22298c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth);
22308c2ecf20Sopenharmony_ci	}
22318c2ecf20Sopenharmony_ci
22328c2ecf20Sopenharmony_ci	/* Configure pause time (2 TCs per register) */
22338c2ecf20Sopenharmony_ci	reg = hw->fc.pause_time * 0x00010001U;
22348c2ecf20Sopenharmony_ci	for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
22358c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
22368c2ecf20Sopenharmony_ci
22378c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci	return 0;
22408c2ecf20Sopenharmony_ci}
22418c2ecf20Sopenharmony_ci
22428c2ecf20Sopenharmony_ci/**
22438c2ecf20Sopenharmony_ci *  ixgbe_negotiate_fc - Negotiate flow control
22448c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
22458c2ecf20Sopenharmony_ci *  @adv_reg: flow control advertised settings
22468c2ecf20Sopenharmony_ci *  @lp_reg: link partner's flow control settings
22478c2ecf20Sopenharmony_ci *  @adv_sym: symmetric pause bit in advertisement
22488c2ecf20Sopenharmony_ci *  @adv_asm: asymmetric pause bit in advertisement
22498c2ecf20Sopenharmony_ci *  @lp_sym: symmetric pause bit in link partner advertisement
22508c2ecf20Sopenharmony_ci *  @lp_asm: asymmetric pause bit in link partner advertisement
22518c2ecf20Sopenharmony_ci *
22528c2ecf20Sopenharmony_ci *  Find the intersection between advertised settings and link partner's
22538c2ecf20Sopenharmony_ci *  advertised settings
22548c2ecf20Sopenharmony_ci **/
22558c2ecf20Sopenharmony_cis32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
22568c2ecf20Sopenharmony_ci		       u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
22578c2ecf20Sopenharmony_ci{
22588c2ecf20Sopenharmony_ci	if ((!(adv_reg)) ||  (!(lp_reg)))
22598c2ecf20Sopenharmony_ci		return -EINVAL;
22608c2ecf20Sopenharmony_ci
22618c2ecf20Sopenharmony_ci	if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
22628c2ecf20Sopenharmony_ci		/*
22638c2ecf20Sopenharmony_ci		 * Now we need to check if the user selected Rx ONLY
22648c2ecf20Sopenharmony_ci		 * of pause frames.  In this case, we had to advertise
22658c2ecf20Sopenharmony_ci		 * FULL flow control because we could not advertise RX
22668c2ecf20Sopenharmony_ci		 * ONLY. Hence, we must now check to see if we need to
22678c2ecf20Sopenharmony_ci		 * turn OFF the TRANSMISSION of PAUSE frames.
22688c2ecf20Sopenharmony_ci		 */
22698c2ecf20Sopenharmony_ci		if (hw->fc.requested_mode == ixgbe_fc_full) {
22708c2ecf20Sopenharmony_ci			hw->fc.current_mode = ixgbe_fc_full;
22718c2ecf20Sopenharmony_ci			hw_dbg(hw, "Flow Control = FULL.\n");
22728c2ecf20Sopenharmony_ci		} else {
22738c2ecf20Sopenharmony_ci			hw->fc.current_mode = ixgbe_fc_rx_pause;
22748c2ecf20Sopenharmony_ci			hw_dbg(hw, "Flow Control=RX PAUSE frames only\n");
22758c2ecf20Sopenharmony_ci		}
22768c2ecf20Sopenharmony_ci	} else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
22778c2ecf20Sopenharmony_ci		   (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
22788c2ecf20Sopenharmony_ci		hw->fc.current_mode = ixgbe_fc_tx_pause;
22798c2ecf20Sopenharmony_ci		hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
22808c2ecf20Sopenharmony_ci	} else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
22818c2ecf20Sopenharmony_ci		   !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
22828c2ecf20Sopenharmony_ci		hw->fc.current_mode = ixgbe_fc_rx_pause;
22838c2ecf20Sopenharmony_ci		hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
22848c2ecf20Sopenharmony_ci	} else {
22858c2ecf20Sopenharmony_ci		hw->fc.current_mode = ixgbe_fc_none;
22868c2ecf20Sopenharmony_ci		hw_dbg(hw, "Flow Control = NONE.\n");
22878c2ecf20Sopenharmony_ci	}
22888c2ecf20Sopenharmony_ci	return 0;
22898c2ecf20Sopenharmony_ci}
22908c2ecf20Sopenharmony_ci
22918c2ecf20Sopenharmony_ci/**
22928c2ecf20Sopenharmony_ci *  ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber
22938c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
22948c2ecf20Sopenharmony_ci *
22958c2ecf20Sopenharmony_ci *  Enable flow control according on 1 gig fiber.
22968c2ecf20Sopenharmony_ci **/
22978c2ecf20Sopenharmony_cistatic s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
22988c2ecf20Sopenharmony_ci{
22998c2ecf20Sopenharmony_ci	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
23008c2ecf20Sopenharmony_ci	s32 ret_val;
23018c2ecf20Sopenharmony_ci
23028c2ecf20Sopenharmony_ci	/*
23038c2ecf20Sopenharmony_ci	 * On multispeed fiber at 1g, bail out if
23048c2ecf20Sopenharmony_ci	 * - link is up but AN did not complete, or if
23058c2ecf20Sopenharmony_ci	 * - link is up and AN completed but timed out
23068c2ecf20Sopenharmony_ci	 */
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci	linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
23098c2ecf20Sopenharmony_ci	if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
23108c2ecf20Sopenharmony_ci	    (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1))
23118c2ecf20Sopenharmony_ci		return -EIO;
23128c2ecf20Sopenharmony_ci
23138c2ecf20Sopenharmony_ci	pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
23148c2ecf20Sopenharmony_ci	pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_ci	ret_val =  ixgbe_negotiate_fc(hw, pcs_anadv_reg,
23178c2ecf20Sopenharmony_ci			       pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE,
23188c2ecf20Sopenharmony_ci			       IXGBE_PCS1GANA_ASM_PAUSE,
23198c2ecf20Sopenharmony_ci			       IXGBE_PCS1GANA_SYM_PAUSE,
23208c2ecf20Sopenharmony_ci			       IXGBE_PCS1GANA_ASM_PAUSE);
23218c2ecf20Sopenharmony_ci
23228c2ecf20Sopenharmony_ci	return ret_val;
23238c2ecf20Sopenharmony_ci}
23248c2ecf20Sopenharmony_ci
23258c2ecf20Sopenharmony_ci/**
23268c2ecf20Sopenharmony_ci *  ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37
23278c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
23288c2ecf20Sopenharmony_ci *
23298c2ecf20Sopenharmony_ci *  Enable flow control according to IEEE clause 37.
23308c2ecf20Sopenharmony_ci **/
23318c2ecf20Sopenharmony_cistatic s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
23328c2ecf20Sopenharmony_ci{
23338c2ecf20Sopenharmony_ci	u32 links2, anlp1_reg, autoc_reg, links;
23348c2ecf20Sopenharmony_ci	s32 ret_val;
23358c2ecf20Sopenharmony_ci
23368c2ecf20Sopenharmony_ci	/*
23378c2ecf20Sopenharmony_ci	 * On backplane, bail out if
23388c2ecf20Sopenharmony_ci	 * - backplane autoneg was not completed, or if
23398c2ecf20Sopenharmony_ci	 * - we are 82599 and link partner is not AN enabled
23408c2ecf20Sopenharmony_ci	 */
23418c2ecf20Sopenharmony_ci	links = IXGBE_READ_REG(hw, IXGBE_LINKS);
23428c2ecf20Sopenharmony_ci	if ((links & IXGBE_LINKS_KX_AN_COMP) == 0)
23438c2ecf20Sopenharmony_ci		return -EIO;
23448c2ecf20Sopenharmony_ci
23458c2ecf20Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_82599EB) {
23468c2ecf20Sopenharmony_ci		links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
23478c2ecf20Sopenharmony_ci		if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)
23488c2ecf20Sopenharmony_ci			return -EIO;
23498c2ecf20Sopenharmony_ci	}
23508c2ecf20Sopenharmony_ci	/*
23518c2ecf20Sopenharmony_ci	 * Read the 10g AN autoc and LP ability registers and resolve
23528c2ecf20Sopenharmony_ci	 * local flow control settings accordingly
23538c2ecf20Sopenharmony_ci	 */
23548c2ecf20Sopenharmony_ci	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
23558c2ecf20Sopenharmony_ci	anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
23568c2ecf20Sopenharmony_ci
23578c2ecf20Sopenharmony_ci	ret_val = ixgbe_negotiate_fc(hw, autoc_reg,
23588c2ecf20Sopenharmony_ci		anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE,
23598c2ecf20Sopenharmony_ci		IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE);
23608c2ecf20Sopenharmony_ci
23618c2ecf20Sopenharmony_ci	return ret_val;
23628c2ecf20Sopenharmony_ci}
23638c2ecf20Sopenharmony_ci
23648c2ecf20Sopenharmony_ci/**
23658c2ecf20Sopenharmony_ci *  ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37
23668c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
23678c2ecf20Sopenharmony_ci *
23688c2ecf20Sopenharmony_ci *  Enable flow control according to IEEE clause 37.
23698c2ecf20Sopenharmony_ci **/
23708c2ecf20Sopenharmony_cistatic s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw)
23718c2ecf20Sopenharmony_ci{
23728c2ecf20Sopenharmony_ci	u16 technology_ability_reg = 0;
23738c2ecf20Sopenharmony_ci	u16 lp_technology_ability_reg = 0;
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_ci	hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
23768c2ecf20Sopenharmony_ci			     MDIO_MMD_AN,
23778c2ecf20Sopenharmony_ci			     &technology_ability_reg);
23788c2ecf20Sopenharmony_ci	hw->phy.ops.read_reg(hw, MDIO_AN_LPA,
23798c2ecf20Sopenharmony_ci			     MDIO_MMD_AN,
23808c2ecf20Sopenharmony_ci			     &lp_technology_ability_reg);
23818c2ecf20Sopenharmony_ci
23828c2ecf20Sopenharmony_ci	return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg,
23838c2ecf20Sopenharmony_ci				  (u32)lp_technology_ability_reg,
23848c2ecf20Sopenharmony_ci				  IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE,
23858c2ecf20Sopenharmony_ci				  IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE);
23868c2ecf20Sopenharmony_ci}
23878c2ecf20Sopenharmony_ci
23888c2ecf20Sopenharmony_ci/**
23898c2ecf20Sopenharmony_ci *  ixgbe_fc_autoneg - Configure flow control
23908c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
23918c2ecf20Sopenharmony_ci *
23928c2ecf20Sopenharmony_ci *  Compares our advertised flow control capabilities to those advertised by
23938c2ecf20Sopenharmony_ci *  our link partner, and determines the proper flow control mode to use.
23948c2ecf20Sopenharmony_ci **/
23958c2ecf20Sopenharmony_civoid ixgbe_fc_autoneg(struct ixgbe_hw *hw)
23968c2ecf20Sopenharmony_ci{
23978c2ecf20Sopenharmony_ci	ixgbe_link_speed speed;
23988c2ecf20Sopenharmony_ci	s32 ret_val = -EIO;
23998c2ecf20Sopenharmony_ci	bool link_up;
24008c2ecf20Sopenharmony_ci
24018c2ecf20Sopenharmony_ci	/*
24028c2ecf20Sopenharmony_ci	 * AN should have completed when the cable was plugged in.
24038c2ecf20Sopenharmony_ci	 * Look for reasons to bail out.  Bail out if:
24048c2ecf20Sopenharmony_ci	 * - FC autoneg is disabled, or if
24058c2ecf20Sopenharmony_ci	 * - link is not up.
24068c2ecf20Sopenharmony_ci	 *
24078c2ecf20Sopenharmony_ci	 * Since we're being called from an LSC, link is already known to be up.
24088c2ecf20Sopenharmony_ci	 * So use link_up_wait_to_complete=false.
24098c2ecf20Sopenharmony_ci	 */
24108c2ecf20Sopenharmony_ci	if (hw->fc.disable_fc_autoneg)
24118c2ecf20Sopenharmony_ci		goto out;
24128c2ecf20Sopenharmony_ci
24138c2ecf20Sopenharmony_ci	hw->mac.ops.check_link(hw, &speed, &link_up, false);
24148c2ecf20Sopenharmony_ci	if (!link_up)
24158c2ecf20Sopenharmony_ci		goto out;
24168c2ecf20Sopenharmony_ci
24178c2ecf20Sopenharmony_ci	switch (hw->phy.media_type) {
24188c2ecf20Sopenharmony_ci	/* Autoneg flow control on fiber adapters */
24198c2ecf20Sopenharmony_ci	case ixgbe_media_type_fiber:
24208c2ecf20Sopenharmony_ci		if (speed == IXGBE_LINK_SPEED_1GB_FULL)
24218c2ecf20Sopenharmony_ci			ret_val = ixgbe_fc_autoneg_fiber(hw);
24228c2ecf20Sopenharmony_ci		break;
24238c2ecf20Sopenharmony_ci
24248c2ecf20Sopenharmony_ci	/* Autoneg flow control on backplane adapters */
24258c2ecf20Sopenharmony_ci	case ixgbe_media_type_backplane:
24268c2ecf20Sopenharmony_ci		ret_val = ixgbe_fc_autoneg_backplane(hw);
24278c2ecf20Sopenharmony_ci		break;
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_ci	/* Autoneg flow control on copper adapters */
24308c2ecf20Sopenharmony_ci	case ixgbe_media_type_copper:
24318c2ecf20Sopenharmony_ci		if (ixgbe_device_supports_autoneg_fc(hw))
24328c2ecf20Sopenharmony_ci			ret_val = ixgbe_fc_autoneg_copper(hw);
24338c2ecf20Sopenharmony_ci		break;
24348c2ecf20Sopenharmony_ci
24358c2ecf20Sopenharmony_ci	default:
24368c2ecf20Sopenharmony_ci		break;
24378c2ecf20Sopenharmony_ci	}
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_ciout:
24408c2ecf20Sopenharmony_ci	if (ret_val == 0) {
24418c2ecf20Sopenharmony_ci		hw->fc.fc_was_autonegged = true;
24428c2ecf20Sopenharmony_ci	} else {
24438c2ecf20Sopenharmony_ci		hw->fc.fc_was_autonegged = false;
24448c2ecf20Sopenharmony_ci		hw->fc.current_mode = hw->fc.requested_mode;
24458c2ecf20Sopenharmony_ci	}
24468c2ecf20Sopenharmony_ci}
24478c2ecf20Sopenharmony_ci
24488c2ecf20Sopenharmony_ci/**
24498c2ecf20Sopenharmony_ci * ixgbe_pcie_timeout_poll - Return number of times to poll for completion
24508c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure
24518c2ecf20Sopenharmony_ci *
24528c2ecf20Sopenharmony_ci * System-wide timeout range is encoded in PCIe Device Control2 register.
24538c2ecf20Sopenharmony_ci *
24548c2ecf20Sopenharmony_ci *  Add 10% to specified maximum and return the number of times to poll for
24558c2ecf20Sopenharmony_ci *  completion timeout, in units of 100 microsec.  Never return less than
24568c2ecf20Sopenharmony_ci *  800 = 80 millisec.
24578c2ecf20Sopenharmony_ci **/
24588c2ecf20Sopenharmony_cistatic u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw)
24598c2ecf20Sopenharmony_ci{
24608c2ecf20Sopenharmony_ci	s16 devctl2;
24618c2ecf20Sopenharmony_ci	u32 pollcnt;
24628c2ecf20Sopenharmony_ci
24638c2ecf20Sopenharmony_ci	devctl2 = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_CONTROL2);
24648c2ecf20Sopenharmony_ci	devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK;
24658c2ecf20Sopenharmony_ci
24668c2ecf20Sopenharmony_ci	switch (devctl2) {
24678c2ecf20Sopenharmony_ci	case IXGBE_PCIDEVCTRL2_65_130ms:
24688c2ecf20Sopenharmony_ci		 pollcnt = 1300;         /* 130 millisec */
24698c2ecf20Sopenharmony_ci		break;
24708c2ecf20Sopenharmony_ci	case IXGBE_PCIDEVCTRL2_260_520ms:
24718c2ecf20Sopenharmony_ci		pollcnt = 5200;         /* 520 millisec */
24728c2ecf20Sopenharmony_ci		break;
24738c2ecf20Sopenharmony_ci	case IXGBE_PCIDEVCTRL2_1_2s:
24748c2ecf20Sopenharmony_ci		pollcnt = 20000;        /* 2 sec */
24758c2ecf20Sopenharmony_ci		break;
24768c2ecf20Sopenharmony_ci	case IXGBE_PCIDEVCTRL2_4_8s:
24778c2ecf20Sopenharmony_ci		pollcnt = 80000;        /* 8 sec */
24788c2ecf20Sopenharmony_ci		break;
24798c2ecf20Sopenharmony_ci	case IXGBE_PCIDEVCTRL2_17_34s:
24808c2ecf20Sopenharmony_ci		pollcnt = 34000;        /* 34 sec */
24818c2ecf20Sopenharmony_ci		break;
24828c2ecf20Sopenharmony_ci	case IXGBE_PCIDEVCTRL2_50_100us:        /* 100 microsecs */
24838c2ecf20Sopenharmony_ci	case IXGBE_PCIDEVCTRL2_1_2ms:           /* 2 millisecs */
24848c2ecf20Sopenharmony_ci	case IXGBE_PCIDEVCTRL2_16_32ms:         /* 32 millisec */
24858c2ecf20Sopenharmony_ci	case IXGBE_PCIDEVCTRL2_16_32ms_def:     /* 32 millisec default */
24868c2ecf20Sopenharmony_ci	default:
24878c2ecf20Sopenharmony_ci		pollcnt = 800;          /* 80 millisec minimum */
24888c2ecf20Sopenharmony_ci		break;
24898c2ecf20Sopenharmony_ci	}
24908c2ecf20Sopenharmony_ci
24918c2ecf20Sopenharmony_ci	/* add 10% to spec maximum */
24928c2ecf20Sopenharmony_ci	return (pollcnt * 11) / 10;
24938c2ecf20Sopenharmony_ci}
24948c2ecf20Sopenharmony_ci
24958c2ecf20Sopenharmony_ci/**
24968c2ecf20Sopenharmony_ci *  ixgbe_disable_pcie_primary - Disable PCI-express primary access
24978c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
24988c2ecf20Sopenharmony_ci *
24998c2ecf20Sopenharmony_ci *  Disables PCI-Express primary access and verifies there are no pending
25008c2ecf20Sopenharmony_ci *  requests. -EALREADY is returned if primary disable
25018c2ecf20Sopenharmony_ci *  bit hasn't caused the primary requests to be disabled, else 0
25028c2ecf20Sopenharmony_ci *  is returned signifying primary requests disabled.
25038c2ecf20Sopenharmony_ci **/
25048c2ecf20Sopenharmony_cistatic s32 ixgbe_disable_pcie_primary(struct ixgbe_hw *hw)
25058c2ecf20Sopenharmony_ci{
25068c2ecf20Sopenharmony_ci	u32 i, poll;
25078c2ecf20Sopenharmony_ci	u16 value;
25088c2ecf20Sopenharmony_ci
25098c2ecf20Sopenharmony_ci	/* Always set this bit to ensure any future transactions are blocked */
25108c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS);
25118c2ecf20Sopenharmony_ci
25128c2ecf20Sopenharmony_ci	/* Poll for bit to read as set */
25138c2ecf20Sopenharmony_ci	for (i = 0; i < IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT; i++) {
25148c2ecf20Sopenharmony_ci		if (IXGBE_READ_REG(hw, IXGBE_CTRL) & IXGBE_CTRL_GIO_DIS)
25158c2ecf20Sopenharmony_ci			break;
25168c2ecf20Sopenharmony_ci		usleep_range(100, 120);
25178c2ecf20Sopenharmony_ci	}
25188c2ecf20Sopenharmony_ci	if (i >= IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT) {
25198c2ecf20Sopenharmony_ci		hw_dbg(hw, "GIO disable did not set - requesting resets\n");
25208c2ecf20Sopenharmony_ci		goto gio_disable_fail;
25218c2ecf20Sopenharmony_ci	}
25228c2ecf20Sopenharmony_ci
25238c2ecf20Sopenharmony_ci	/* Exit if primary requests are blocked */
25248c2ecf20Sopenharmony_ci	if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) ||
25258c2ecf20Sopenharmony_ci	    ixgbe_removed(hw->hw_addr))
25268c2ecf20Sopenharmony_ci		return 0;
25278c2ecf20Sopenharmony_ci
25288c2ecf20Sopenharmony_ci	/* Poll for primary request bit to clear */
25298c2ecf20Sopenharmony_ci	for (i = 0; i < IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT; i++) {
25308c2ecf20Sopenharmony_ci		udelay(100);
25318c2ecf20Sopenharmony_ci		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
25328c2ecf20Sopenharmony_ci			return 0;
25338c2ecf20Sopenharmony_ci	}
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_ci	/*
25368c2ecf20Sopenharmony_ci	 * Two consecutive resets are required via CTRL.RST per datasheet
25378c2ecf20Sopenharmony_ci	 * 5.2.5.3.2 Primary Disable.  We set a flag to inform the reset routine
25388c2ecf20Sopenharmony_ci	 * of this need.  The first reset prevents new primary requests from
25398c2ecf20Sopenharmony_ci	 * being issued by our device.  We then must wait 1usec or more for any
25408c2ecf20Sopenharmony_ci	 * remaining completions from the PCIe bus to trickle in, and then reset
25418c2ecf20Sopenharmony_ci	 * again to clear out any effects they may have had on our device.
25428c2ecf20Sopenharmony_ci	 */
25438c2ecf20Sopenharmony_ci	hw_dbg(hw, "GIO Primary Disable bit didn't clear - requesting resets\n");
25448c2ecf20Sopenharmony_cigio_disable_fail:
25458c2ecf20Sopenharmony_ci	hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
25468c2ecf20Sopenharmony_ci
25478c2ecf20Sopenharmony_ci	if (hw->mac.type >= ixgbe_mac_X550)
25488c2ecf20Sopenharmony_ci		return 0;
25498c2ecf20Sopenharmony_ci
25508c2ecf20Sopenharmony_ci	/*
25518c2ecf20Sopenharmony_ci	 * Before proceeding, make sure that the PCIe block does not have
25528c2ecf20Sopenharmony_ci	 * transactions pending.
25538c2ecf20Sopenharmony_ci	 */
25548c2ecf20Sopenharmony_ci	poll = ixgbe_pcie_timeout_poll(hw);
25558c2ecf20Sopenharmony_ci	for (i = 0; i < poll; i++) {
25568c2ecf20Sopenharmony_ci		udelay(100);
25578c2ecf20Sopenharmony_ci		value = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_STATUS);
25588c2ecf20Sopenharmony_ci		if (ixgbe_removed(hw->hw_addr))
25598c2ecf20Sopenharmony_ci			return 0;
25608c2ecf20Sopenharmony_ci		if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
25618c2ecf20Sopenharmony_ci			return 0;
25628c2ecf20Sopenharmony_ci	}
25638c2ecf20Sopenharmony_ci
25648c2ecf20Sopenharmony_ci	hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n");
25658c2ecf20Sopenharmony_ci	return -EALREADY;
25668c2ecf20Sopenharmony_ci}
25678c2ecf20Sopenharmony_ci
25688c2ecf20Sopenharmony_ci/**
25698c2ecf20Sopenharmony_ci *  ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
25708c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
25718c2ecf20Sopenharmony_ci *  @mask: Mask to specify which semaphore to acquire
25728c2ecf20Sopenharmony_ci *
25738c2ecf20Sopenharmony_ci *  Acquires the SWFW semaphore through the GSSR register for the specified
25748c2ecf20Sopenharmony_ci *  function (CSR, PHY0, PHY1, EEPROM, Flash)
25758c2ecf20Sopenharmony_ci **/
25768c2ecf20Sopenharmony_cis32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask)
25778c2ecf20Sopenharmony_ci{
25788c2ecf20Sopenharmony_ci	u32 gssr = 0;
25798c2ecf20Sopenharmony_ci	u32 swmask = mask;
25808c2ecf20Sopenharmony_ci	u32 fwmask = mask << 5;
25818c2ecf20Sopenharmony_ci	u32 timeout = 200;
25828c2ecf20Sopenharmony_ci	u32 i;
25838c2ecf20Sopenharmony_ci
25848c2ecf20Sopenharmony_ci	for (i = 0; i < timeout; i++) {
25858c2ecf20Sopenharmony_ci		/*
25868c2ecf20Sopenharmony_ci		 * SW NVM semaphore bit is used for access to all
25878c2ecf20Sopenharmony_ci		 * SW_FW_SYNC bits (not just NVM)
25888c2ecf20Sopenharmony_ci		 */
25898c2ecf20Sopenharmony_ci		if (ixgbe_get_eeprom_semaphore(hw))
25908c2ecf20Sopenharmony_ci			return -EBUSY;
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_ci		gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
25938c2ecf20Sopenharmony_ci		if (!(gssr & (fwmask | swmask))) {
25948c2ecf20Sopenharmony_ci			gssr |= swmask;
25958c2ecf20Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
25968c2ecf20Sopenharmony_ci			ixgbe_release_eeprom_semaphore(hw);
25978c2ecf20Sopenharmony_ci			return 0;
25988c2ecf20Sopenharmony_ci		} else {
25998c2ecf20Sopenharmony_ci			/* Resource is currently in use by FW or SW */
26008c2ecf20Sopenharmony_ci			ixgbe_release_eeprom_semaphore(hw);
26018c2ecf20Sopenharmony_ci			usleep_range(5000, 10000);
26028c2ecf20Sopenharmony_ci		}
26038c2ecf20Sopenharmony_ci	}
26048c2ecf20Sopenharmony_ci
26058c2ecf20Sopenharmony_ci	/* If time expired clear the bits holding the lock and retry */
26068c2ecf20Sopenharmony_ci	if (gssr & (fwmask | swmask))
26078c2ecf20Sopenharmony_ci		ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask));
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ci	usleep_range(5000, 10000);
26108c2ecf20Sopenharmony_ci	return -EBUSY;
26118c2ecf20Sopenharmony_ci}
26128c2ecf20Sopenharmony_ci
26138c2ecf20Sopenharmony_ci/**
26148c2ecf20Sopenharmony_ci *  ixgbe_release_swfw_sync - Release SWFW semaphore
26158c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
26168c2ecf20Sopenharmony_ci *  @mask: Mask to specify which semaphore to release
26178c2ecf20Sopenharmony_ci *
26188c2ecf20Sopenharmony_ci *  Releases the SWFW semaphore through the GSSR register for the specified
26198c2ecf20Sopenharmony_ci *  function (CSR, PHY0, PHY1, EEPROM, Flash)
26208c2ecf20Sopenharmony_ci **/
26218c2ecf20Sopenharmony_civoid ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask)
26228c2ecf20Sopenharmony_ci{
26238c2ecf20Sopenharmony_ci	u32 gssr;
26248c2ecf20Sopenharmony_ci	u32 swmask = mask;
26258c2ecf20Sopenharmony_ci
26268c2ecf20Sopenharmony_ci	ixgbe_get_eeprom_semaphore(hw);
26278c2ecf20Sopenharmony_ci
26288c2ecf20Sopenharmony_ci	gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
26298c2ecf20Sopenharmony_ci	gssr &= ~swmask;
26308c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
26318c2ecf20Sopenharmony_ci
26328c2ecf20Sopenharmony_ci	ixgbe_release_eeprom_semaphore(hw);
26338c2ecf20Sopenharmony_ci}
26348c2ecf20Sopenharmony_ci
26358c2ecf20Sopenharmony_ci/**
26368c2ecf20Sopenharmony_ci * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read
26378c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure
26388c2ecf20Sopenharmony_ci * @reg_val: Value we read from AUTOC
26398c2ecf20Sopenharmony_ci * @locked: bool to indicate whether the SW/FW lock should be taken.  Never
26408c2ecf20Sopenharmony_ci *	    true in this the generic case.
26418c2ecf20Sopenharmony_ci *
26428c2ecf20Sopenharmony_ci * The default case requires no protection so just to the register read.
26438c2ecf20Sopenharmony_ci **/
26448c2ecf20Sopenharmony_cis32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val)
26458c2ecf20Sopenharmony_ci{
26468c2ecf20Sopenharmony_ci	*locked = false;
26478c2ecf20Sopenharmony_ci	*reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
26488c2ecf20Sopenharmony_ci	return 0;
26498c2ecf20Sopenharmony_ci}
26508c2ecf20Sopenharmony_ci
26518c2ecf20Sopenharmony_ci/**
26528c2ecf20Sopenharmony_ci * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write
26538c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure
26548c2ecf20Sopenharmony_ci * @reg_val: value to write to AUTOC
26558c2ecf20Sopenharmony_ci * @locked: bool to indicate whether the SW/FW lock was already taken by
26568c2ecf20Sopenharmony_ci *	    previous read.
26578c2ecf20Sopenharmony_ci **/
26588c2ecf20Sopenharmony_cis32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked)
26598c2ecf20Sopenharmony_ci{
26608c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val);
26618c2ecf20Sopenharmony_ci	return 0;
26628c2ecf20Sopenharmony_ci}
26638c2ecf20Sopenharmony_ci
26648c2ecf20Sopenharmony_ci/**
26658c2ecf20Sopenharmony_ci *  ixgbe_disable_rx_buff_generic - Stops the receive data path
26668c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
26678c2ecf20Sopenharmony_ci *
26688c2ecf20Sopenharmony_ci *  Stops the receive data path and waits for the HW to internally
26698c2ecf20Sopenharmony_ci *  empty the Rx security block.
26708c2ecf20Sopenharmony_ci **/
26718c2ecf20Sopenharmony_cis32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw)
26728c2ecf20Sopenharmony_ci{
26738c2ecf20Sopenharmony_ci#define IXGBE_MAX_SECRX_POLL 40
26748c2ecf20Sopenharmony_ci	int i;
26758c2ecf20Sopenharmony_ci	int secrxreg;
26768c2ecf20Sopenharmony_ci
26778c2ecf20Sopenharmony_ci	secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
26788c2ecf20Sopenharmony_ci	secrxreg |= IXGBE_SECRXCTRL_RX_DIS;
26798c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg);
26808c2ecf20Sopenharmony_ci	for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) {
26818c2ecf20Sopenharmony_ci		secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT);
26828c2ecf20Sopenharmony_ci		if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY)
26838c2ecf20Sopenharmony_ci			break;
26848c2ecf20Sopenharmony_ci		else
26858c2ecf20Sopenharmony_ci			/* Use interrupt-safe sleep just in case */
26868c2ecf20Sopenharmony_ci			udelay(1000);
26878c2ecf20Sopenharmony_ci	}
26888c2ecf20Sopenharmony_ci
26898c2ecf20Sopenharmony_ci	/* For informational purposes only */
26908c2ecf20Sopenharmony_ci	if (i >= IXGBE_MAX_SECRX_POLL)
26918c2ecf20Sopenharmony_ci		hw_dbg(hw, "Rx unit being enabled before security path fully disabled. Continuing with init.\n");
26928c2ecf20Sopenharmony_ci
26938c2ecf20Sopenharmony_ci	return 0;
26948c2ecf20Sopenharmony_ci
26958c2ecf20Sopenharmony_ci}
26968c2ecf20Sopenharmony_ci
26978c2ecf20Sopenharmony_ci/**
26988c2ecf20Sopenharmony_ci *  ixgbe_enable_rx_buff - Enables the receive data path
26998c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
27008c2ecf20Sopenharmony_ci *
27018c2ecf20Sopenharmony_ci *  Enables the receive data path
27028c2ecf20Sopenharmony_ci **/
27038c2ecf20Sopenharmony_cis32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw)
27048c2ecf20Sopenharmony_ci{
27058c2ecf20Sopenharmony_ci	u32 secrxreg;
27068c2ecf20Sopenharmony_ci
27078c2ecf20Sopenharmony_ci	secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
27088c2ecf20Sopenharmony_ci	secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS;
27098c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg);
27108c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
27118c2ecf20Sopenharmony_ci
27128c2ecf20Sopenharmony_ci	return 0;
27138c2ecf20Sopenharmony_ci}
27148c2ecf20Sopenharmony_ci
27158c2ecf20Sopenharmony_ci/**
27168c2ecf20Sopenharmony_ci *  ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit
27178c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
27188c2ecf20Sopenharmony_ci *  @regval: register value to write to RXCTRL
27198c2ecf20Sopenharmony_ci *
27208c2ecf20Sopenharmony_ci *  Enables the Rx DMA unit
27218c2ecf20Sopenharmony_ci **/
27228c2ecf20Sopenharmony_cis32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval)
27238c2ecf20Sopenharmony_ci{
27248c2ecf20Sopenharmony_ci	if (regval & IXGBE_RXCTRL_RXEN)
27258c2ecf20Sopenharmony_ci		hw->mac.ops.enable_rx(hw);
27268c2ecf20Sopenharmony_ci	else
27278c2ecf20Sopenharmony_ci		hw->mac.ops.disable_rx(hw);
27288c2ecf20Sopenharmony_ci
27298c2ecf20Sopenharmony_ci	return 0;
27308c2ecf20Sopenharmony_ci}
27318c2ecf20Sopenharmony_ci
27328c2ecf20Sopenharmony_ci/**
27338c2ecf20Sopenharmony_ci *  ixgbe_blink_led_start_generic - Blink LED based on index.
27348c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
27358c2ecf20Sopenharmony_ci *  @index: led number to blink
27368c2ecf20Sopenharmony_ci **/
27378c2ecf20Sopenharmony_cis32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
27388c2ecf20Sopenharmony_ci{
27398c2ecf20Sopenharmony_ci	ixgbe_link_speed speed = 0;
27408c2ecf20Sopenharmony_ci	bool link_up = false;
27418c2ecf20Sopenharmony_ci	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
27428c2ecf20Sopenharmony_ci	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
27438c2ecf20Sopenharmony_ci	bool locked = false;
27448c2ecf20Sopenharmony_ci	s32 ret_val;
27458c2ecf20Sopenharmony_ci
27468c2ecf20Sopenharmony_ci	if (index > 3)
27478c2ecf20Sopenharmony_ci		return -EINVAL;
27488c2ecf20Sopenharmony_ci
27498c2ecf20Sopenharmony_ci	/*
27508c2ecf20Sopenharmony_ci	 * Link must be up to auto-blink the LEDs;
27518c2ecf20Sopenharmony_ci	 * Force it if link is down.
27528c2ecf20Sopenharmony_ci	 */
27538c2ecf20Sopenharmony_ci	hw->mac.ops.check_link(hw, &speed, &link_up, false);
27548c2ecf20Sopenharmony_ci
27558c2ecf20Sopenharmony_ci	if (!link_up) {
27568c2ecf20Sopenharmony_ci		ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
27578c2ecf20Sopenharmony_ci		if (ret_val)
27588c2ecf20Sopenharmony_ci			return ret_val;
27598c2ecf20Sopenharmony_ci
27608c2ecf20Sopenharmony_ci		autoc_reg |= IXGBE_AUTOC_AN_RESTART;
27618c2ecf20Sopenharmony_ci		autoc_reg |= IXGBE_AUTOC_FLU;
27628c2ecf20Sopenharmony_ci
27638c2ecf20Sopenharmony_ci		ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
27648c2ecf20Sopenharmony_ci		if (ret_val)
27658c2ecf20Sopenharmony_ci			return ret_val;
27668c2ecf20Sopenharmony_ci
27678c2ecf20Sopenharmony_ci		IXGBE_WRITE_FLUSH(hw);
27688c2ecf20Sopenharmony_ci
27698c2ecf20Sopenharmony_ci		usleep_range(10000, 20000);
27708c2ecf20Sopenharmony_ci	}
27718c2ecf20Sopenharmony_ci
27728c2ecf20Sopenharmony_ci	led_reg &= ~IXGBE_LED_MODE_MASK(index);
27738c2ecf20Sopenharmony_ci	led_reg |= IXGBE_LED_BLINK(index);
27748c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
27758c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
27768c2ecf20Sopenharmony_ci
27778c2ecf20Sopenharmony_ci	return 0;
27788c2ecf20Sopenharmony_ci}
27798c2ecf20Sopenharmony_ci
27808c2ecf20Sopenharmony_ci/**
27818c2ecf20Sopenharmony_ci *  ixgbe_blink_led_stop_generic - Stop blinking LED based on index.
27828c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
27838c2ecf20Sopenharmony_ci *  @index: led number to stop blinking
27848c2ecf20Sopenharmony_ci **/
27858c2ecf20Sopenharmony_cis32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
27868c2ecf20Sopenharmony_ci{
27878c2ecf20Sopenharmony_ci	u32 autoc_reg = 0;
27888c2ecf20Sopenharmony_ci	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
27898c2ecf20Sopenharmony_ci	bool locked = false;
27908c2ecf20Sopenharmony_ci	s32 ret_val;
27918c2ecf20Sopenharmony_ci
27928c2ecf20Sopenharmony_ci	if (index > 3)
27938c2ecf20Sopenharmony_ci		return -EINVAL;
27948c2ecf20Sopenharmony_ci
27958c2ecf20Sopenharmony_ci	ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
27968c2ecf20Sopenharmony_ci	if (ret_val)
27978c2ecf20Sopenharmony_ci		return ret_val;
27988c2ecf20Sopenharmony_ci
27998c2ecf20Sopenharmony_ci	autoc_reg &= ~IXGBE_AUTOC_FLU;
28008c2ecf20Sopenharmony_ci	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
28018c2ecf20Sopenharmony_ci
28028c2ecf20Sopenharmony_ci	ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
28038c2ecf20Sopenharmony_ci	if (ret_val)
28048c2ecf20Sopenharmony_ci		return ret_val;
28058c2ecf20Sopenharmony_ci
28068c2ecf20Sopenharmony_ci	led_reg &= ~IXGBE_LED_MODE_MASK(index);
28078c2ecf20Sopenharmony_ci	led_reg &= ~IXGBE_LED_BLINK(index);
28088c2ecf20Sopenharmony_ci	led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
28098c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
28108c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_ci	return 0;
28138c2ecf20Sopenharmony_ci}
28148c2ecf20Sopenharmony_ci
28158c2ecf20Sopenharmony_ci/**
28168c2ecf20Sopenharmony_ci *  ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM
28178c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
28188c2ecf20Sopenharmony_ci *  @san_mac_offset: SAN MAC address offset
28198c2ecf20Sopenharmony_ci *
28208c2ecf20Sopenharmony_ci *  This function will read the EEPROM location for the SAN MAC address
28218c2ecf20Sopenharmony_ci *  pointer, and returns the value at that location.  This is used in both
28228c2ecf20Sopenharmony_ci *  get and set mac_addr routines.
28238c2ecf20Sopenharmony_ci **/
28248c2ecf20Sopenharmony_cistatic s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
28258c2ecf20Sopenharmony_ci					u16 *san_mac_offset)
28268c2ecf20Sopenharmony_ci{
28278c2ecf20Sopenharmony_ci	s32 ret_val;
28288c2ecf20Sopenharmony_ci
28298c2ecf20Sopenharmony_ci	/*
28308c2ecf20Sopenharmony_ci	 * First read the EEPROM pointer to see if the MAC addresses are
28318c2ecf20Sopenharmony_ci	 * available.
28328c2ecf20Sopenharmony_ci	 */
28338c2ecf20Sopenharmony_ci	ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR,
28348c2ecf20Sopenharmony_ci				      san_mac_offset);
28358c2ecf20Sopenharmony_ci	if (ret_val)
28368c2ecf20Sopenharmony_ci		hw_err(hw, "eeprom read at offset %d failed\n",
28378c2ecf20Sopenharmony_ci		       IXGBE_SAN_MAC_ADDR_PTR);
28388c2ecf20Sopenharmony_ci
28398c2ecf20Sopenharmony_ci	return ret_val;
28408c2ecf20Sopenharmony_ci}
28418c2ecf20Sopenharmony_ci
28428c2ecf20Sopenharmony_ci/**
28438c2ecf20Sopenharmony_ci *  ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM
28448c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
28458c2ecf20Sopenharmony_ci *  @san_mac_addr: SAN MAC address
28468c2ecf20Sopenharmony_ci *
28478c2ecf20Sopenharmony_ci *  Reads the SAN MAC address from the EEPROM, if it's available.  This is
28488c2ecf20Sopenharmony_ci *  per-port, so set_lan_id() must be called before reading the addresses.
28498c2ecf20Sopenharmony_ci *  set_lan_id() is called by identify_sfp(), but this cannot be relied
28508c2ecf20Sopenharmony_ci *  upon for non-SFP connections, so we must call it here.
28518c2ecf20Sopenharmony_ci **/
28528c2ecf20Sopenharmony_cis32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
28538c2ecf20Sopenharmony_ci{
28548c2ecf20Sopenharmony_ci	u16 san_mac_data, san_mac_offset;
28558c2ecf20Sopenharmony_ci	u8 i;
28568c2ecf20Sopenharmony_ci	s32 ret_val;
28578c2ecf20Sopenharmony_ci
28588c2ecf20Sopenharmony_ci	/*
28598c2ecf20Sopenharmony_ci	 * First read the EEPROM pointer to see if the MAC addresses are
28608c2ecf20Sopenharmony_ci	 * available.  If they're not, no point in calling set_lan_id() here.
28618c2ecf20Sopenharmony_ci	 */
28628c2ecf20Sopenharmony_ci	ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
28638c2ecf20Sopenharmony_ci	if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF)
28648c2ecf20Sopenharmony_ci
28658c2ecf20Sopenharmony_ci		goto san_mac_addr_clr;
28668c2ecf20Sopenharmony_ci
28678c2ecf20Sopenharmony_ci	/* make sure we know which port we need to program */
28688c2ecf20Sopenharmony_ci	hw->mac.ops.set_lan_id(hw);
28698c2ecf20Sopenharmony_ci	/* apply the port offset to the address offset */
28708c2ecf20Sopenharmony_ci	(hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
28718c2ecf20Sopenharmony_ci			 (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
28728c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++) {
28738c2ecf20Sopenharmony_ci		ret_val = hw->eeprom.ops.read(hw, san_mac_offset,
28748c2ecf20Sopenharmony_ci					      &san_mac_data);
28758c2ecf20Sopenharmony_ci		if (ret_val) {
28768c2ecf20Sopenharmony_ci			hw_err(hw, "eeprom read at offset %d failed\n",
28778c2ecf20Sopenharmony_ci			       san_mac_offset);
28788c2ecf20Sopenharmony_ci			goto san_mac_addr_clr;
28798c2ecf20Sopenharmony_ci		}
28808c2ecf20Sopenharmony_ci		san_mac_addr[i * 2] = (u8)(san_mac_data);
28818c2ecf20Sopenharmony_ci		san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8);
28828c2ecf20Sopenharmony_ci		san_mac_offset++;
28838c2ecf20Sopenharmony_ci	}
28848c2ecf20Sopenharmony_ci	return 0;
28858c2ecf20Sopenharmony_ci
28868c2ecf20Sopenharmony_cisan_mac_addr_clr:
28878c2ecf20Sopenharmony_ci	/* No addresses available in this EEPROM.  It's not necessarily an
28888c2ecf20Sopenharmony_ci	 * error though, so just wipe the local address and return.
28898c2ecf20Sopenharmony_ci	 */
28908c2ecf20Sopenharmony_ci	for (i = 0; i < 6; i++)
28918c2ecf20Sopenharmony_ci		san_mac_addr[i] = 0xFF;
28928c2ecf20Sopenharmony_ci	return ret_val;
28938c2ecf20Sopenharmony_ci}
28948c2ecf20Sopenharmony_ci
28958c2ecf20Sopenharmony_ci/**
28968c2ecf20Sopenharmony_ci *  ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count
28978c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
28988c2ecf20Sopenharmony_ci *
28998c2ecf20Sopenharmony_ci *  Read PCIe configuration space, and get the MSI-X vector count from
29008c2ecf20Sopenharmony_ci *  the capabilities table.
29018c2ecf20Sopenharmony_ci **/
29028c2ecf20Sopenharmony_ciu16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
29038c2ecf20Sopenharmony_ci{
29048c2ecf20Sopenharmony_ci	u16 msix_count;
29058c2ecf20Sopenharmony_ci	u16 max_msix_count;
29068c2ecf20Sopenharmony_ci	u16 pcie_offset;
29078c2ecf20Sopenharmony_ci
29088c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
29098c2ecf20Sopenharmony_ci	case ixgbe_mac_82598EB:
29108c2ecf20Sopenharmony_ci		pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS;
29118c2ecf20Sopenharmony_ci		max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598;
29128c2ecf20Sopenharmony_ci		break;
29138c2ecf20Sopenharmony_ci	case ixgbe_mac_82599EB:
29148c2ecf20Sopenharmony_ci	case ixgbe_mac_X540:
29158c2ecf20Sopenharmony_ci	case ixgbe_mac_X550:
29168c2ecf20Sopenharmony_ci	case ixgbe_mac_X550EM_x:
29178c2ecf20Sopenharmony_ci	case ixgbe_mac_x550em_a:
29188c2ecf20Sopenharmony_ci		pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS;
29198c2ecf20Sopenharmony_ci		max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
29208c2ecf20Sopenharmony_ci		break;
29218c2ecf20Sopenharmony_ci	default:
29228c2ecf20Sopenharmony_ci		return 1;
29238c2ecf20Sopenharmony_ci	}
29248c2ecf20Sopenharmony_ci
29258c2ecf20Sopenharmony_ci	msix_count = ixgbe_read_pci_cfg_word(hw, pcie_offset);
29268c2ecf20Sopenharmony_ci	if (ixgbe_removed(hw->hw_addr))
29278c2ecf20Sopenharmony_ci		msix_count = 0;
29288c2ecf20Sopenharmony_ci	msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
29298c2ecf20Sopenharmony_ci
29308c2ecf20Sopenharmony_ci	/* MSI-X count is zero-based in HW */
29318c2ecf20Sopenharmony_ci	msix_count++;
29328c2ecf20Sopenharmony_ci
29338c2ecf20Sopenharmony_ci	if (msix_count > max_msix_count)
29348c2ecf20Sopenharmony_ci		msix_count = max_msix_count;
29358c2ecf20Sopenharmony_ci
29368c2ecf20Sopenharmony_ci	return msix_count;
29378c2ecf20Sopenharmony_ci}
29388c2ecf20Sopenharmony_ci
29398c2ecf20Sopenharmony_ci/**
29408c2ecf20Sopenharmony_ci *  ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address
29418c2ecf20Sopenharmony_ci *  @hw: pointer to hardware struct
29428c2ecf20Sopenharmony_ci *  @rar: receive address register index to disassociate
29438c2ecf20Sopenharmony_ci *  @vmdq: VMDq pool index to remove from the rar
29448c2ecf20Sopenharmony_ci **/
29458c2ecf20Sopenharmony_cis32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
29468c2ecf20Sopenharmony_ci{
29478c2ecf20Sopenharmony_ci	u32 mpsar_lo, mpsar_hi;
29488c2ecf20Sopenharmony_ci	u32 rar_entries = hw->mac.num_rar_entries;
29498c2ecf20Sopenharmony_ci
29508c2ecf20Sopenharmony_ci	/* Make sure we are using a valid rar index range */
29518c2ecf20Sopenharmony_ci	if (rar >= rar_entries) {
29528c2ecf20Sopenharmony_ci		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
29538c2ecf20Sopenharmony_ci		return -EINVAL;
29548c2ecf20Sopenharmony_ci	}
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci	mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
29578c2ecf20Sopenharmony_ci	mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
29588c2ecf20Sopenharmony_ci
29598c2ecf20Sopenharmony_ci	if (ixgbe_removed(hw->hw_addr))
29608c2ecf20Sopenharmony_ci		return 0;
29618c2ecf20Sopenharmony_ci
29628c2ecf20Sopenharmony_ci	if (!mpsar_lo && !mpsar_hi)
29638c2ecf20Sopenharmony_ci		return 0;
29648c2ecf20Sopenharmony_ci
29658c2ecf20Sopenharmony_ci	if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
29668c2ecf20Sopenharmony_ci		if (mpsar_lo) {
29678c2ecf20Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
29688c2ecf20Sopenharmony_ci			mpsar_lo = 0;
29698c2ecf20Sopenharmony_ci		}
29708c2ecf20Sopenharmony_ci		if (mpsar_hi) {
29718c2ecf20Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
29728c2ecf20Sopenharmony_ci			mpsar_hi = 0;
29738c2ecf20Sopenharmony_ci		}
29748c2ecf20Sopenharmony_ci	} else if (vmdq < 32) {
29758c2ecf20Sopenharmony_ci		mpsar_lo &= ~BIT(vmdq);
29768c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
29778c2ecf20Sopenharmony_ci	} else {
29788c2ecf20Sopenharmony_ci		mpsar_hi &= ~BIT(vmdq - 32);
29798c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
29808c2ecf20Sopenharmony_ci	}
29818c2ecf20Sopenharmony_ci
29828c2ecf20Sopenharmony_ci	/* was that the last pool using this rar? */
29838c2ecf20Sopenharmony_ci	if (mpsar_lo == 0 && mpsar_hi == 0 &&
29848c2ecf20Sopenharmony_ci	    rar != 0 && rar != hw->mac.san_mac_rar_index)
29858c2ecf20Sopenharmony_ci		hw->mac.ops.clear_rar(hw, rar);
29868c2ecf20Sopenharmony_ci
29878c2ecf20Sopenharmony_ci	return 0;
29888c2ecf20Sopenharmony_ci}
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci/**
29918c2ecf20Sopenharmony_ci *  ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address
29928c2ecf20Sopenharmony_ci *  @hw: pointer to hardware struct
29938c2ecf20Sopenharmony_ci *  @rar: receive address register index to associate with a VMDq index
29948c2ecf20Sopenharmony_ci *  @vmdq: VMDq pool index
29958c2ecf20Sopenharmony_ci **/
29968c2ecf20Sopenharmony_cis32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
29978c2ecf20Sopenharmony_ci{
29988c2ecf20Sopenharmony_ci	u32 mpsar;
29998c2ecf20Sopenharmony_ci	u32 rar_entries = hw->mac.num_rar_entries;
30008c2ecf20Sopenharmony_ci
30018c2ecf20Sopenharmony_ci	/* Make sure we are using a valid rar index range */
30028c2ecf20Sopenharmony_ci	if (rar >= rar_entries) {
30038c2ecf20Sopenharmony_ci		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
30048c2ecf20Sopenharmony_ci		return -EINVAL;
30058c2ecf20Sopenharmony_ci	}
30068c2ecf20Sopenharmony_ci
30078c2ecf20Sopenharmony_ci	if (vmdq < 32) {
30088c2ecf20Sopenharmony_ci		mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
30098c2ecf20Sopenharmony_ci		mpsar |= BIT(vmdq);
30108c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
30118c2ecf20Sopenharmony_ci	} else {
30128c2ecf20Sopenharmony_ci		mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
30138c2ecf20Sopenharmony_ci		mpsar |= BIT(vmdq - 32);
30148c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
30158c2ecf20Sopenharmony_ci	}
30168c2ecf20Sopenharmony_ci	return 0;
30178c2ecf20Sopenharmony_ci}
30188c2ecf20Sopenharmony_ci
30198c2ecf20Sopenharmony_ci/**
30208c2ecf20Sopenharmony_ci *  This function should only be involved in the IOV mode.
30218c2ecf20Sopenharmony_ci *  In IOV mode, Default pool is next pool after the number of
30228c2ecf20Sopenharmony_ci *  VFs advertized and not 0.
30238c2ecf20Sopenharmony_ci *  MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index]
30248c2ecf20Sopenharmony_ci *
30258c2ecf20Sopenharmony_ci *  ixgbe_set_vmdq_san_mac - Associate default VMDq pool index with a rx address
30268c2ecf20Sopenharmony_ci *  @hw: pointer to hardware struct
30278c2ecf20Sopenharmony_ci *  @vmdq: VMDq pool index
30288c2ecf20Sopenharmony_ci **/
30298c2ecf20Sopenharmony_cis32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq)
30308c2ecf20Sopenharmony_ci{
30318c2ecf20Sopenharmony_ci	u32 rar = hw->mac.san_mac_rar_index;
30328c2ecf20Sopenharmony_ci
30338c2ecf20Sopenharmony_ci	if (vmdq < 32) {
30348c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), BIT(vmdq));
30358c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
30368c2ecf20Sopenharmony_ci	} else {
30378c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
30388c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), BIT(vmdq - 32));
30398c2ecf20Sopenharmony_ci	}
30408c2ecf20Sopenharmony_ci
30418c2ecf20Sopenharmony_ci	return 0;
30428c2ecf20Sopenharmony_ci}
30438c2ecf20Sopenharmony_ci
30448c2ecf20Sopenharmony_ci/**
30458c2ecf20Sopenharmony_ci *  ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array
30468c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
30478c2ecf20Sopenharmony_ci **/
30488c2ecf20Sopenharmony_cis32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
30498c2ecf20Sopenharmony_ci{
30508c2ecf20Sopenharmony_ci	int i;
30518c2ecf20Sopenharmony_ci
30528c2ecf20Sopenharmony_ci	for (i = 0; i < 128; i++)
30538c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0);
30548c2ecf20Sopenharmony_ci
30558c2ecf20Sopenharmony_ci	return 0;
30568c2ecf20Sopenharmony_ci}
30578c2ecf20Sopenharmony_ci
30588c2ecf20Sopenharmony_ci/**
30598c2ecf20Sopenharmony_ci *  ixgbe_find_vlvf_slot - find the vlanid or the first empty slot
30608c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
30618c2ecf20Sopenharmony_ci *  @vlan: VLAN id to write to VLAN filter
30628c2ecf20Sopenharmony_ci *  @vlvf_bypass: true to find vlanid only, false returns first empty slot if
30638c2ecf20Sopenharmony_ci *		  vlanid not found
30648c2ecf20Sopenharmony_ci *
30658c2ecf20Sopenharmony_ci *  return the VLVF index where this VLAN id should be placed
30668c2ecf20Sopenharmony_ci *
30678c2ecf20Sopenharmony_ci **/
30688c2ecf20Sopenharmony_cistatic s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass)
30698c2ecf20Sopenharmony_ci{
30708c2ecf20Sopenharmony_ci	s32 regindex, first_empty_slot;
30718c2ecf20Sopenharmony_ci	u32 bits;
30728c2ecf20Sopenharmony_ci
30738c2ecf20Sopenharmony_ci	/* short cut the special case */
30748c2ecf20Sopenharmony_ci	if (vlan == 0)
30758c2ecf20Sopenharmony_ci		return 0;
30768c2ecf20Sopenharmony_ci
30778c2ecf20Sopenharmony_ci	/* if vlvf_bypass is set we don't want to use an empty slot, we
30788c2ecf20Sopenharmony_ci	 * will simply bypass the VLVF if there are no entries present in the
30798c2ecf20Sopenharmony_ci	 * VLVF that contain our VLAN
30808c2ecf20Sopenharmony_ci	 */
30818c2ecf20Sopenharmony_ci	first_empty_slot = vlvf_bypass ? -ENOSPC : 0;
30828c2ecf20Sopenharmony_ci
30838c2ecf20Sopenharmony_ci	/* add VLAN enable bit for comparison */
30848c2ecf20Sopenharmony_ci	vlan |= IXGBE_VLVF_VIEN;
30858c2ecf20Sopenharmony_ci
30868c2ecf20Sopenharmony_ci	/* Search for the vlan id in the VLVF entries. Save off the first empty
30878c2ecf20Sopenharmony_ci	 * slot found along the way.
30888c2ecf20Sopenharmony_ci	 *
30898c2ecf20Sopenharmony_ci	 * pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1
30908c2ecf20Sopenharmony_ci	 */
30918c2ecf20Sopenharmony_ci	for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) {
30928c2ecf20Sopenharmony_ci		bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
30938c2ecf20Sopenharmony_ci		if (bits == vlan)
30948c2ecf20Sopenharmony_ci			return regindex;
30958c2ecf20Sopenharmony_ci		if (!first_empty_slot && !bits)
30968c2ecf20Sopenharmony_ci			first_empty_slot = regindex;
30978c2ecf20Sopenharmony_ci	}
30988c2ecf20Sopenharmony_ci
30998c2ecf20Sopenharmony_ci	/* If we are here then we didn't find the VLAN.  Return first empty
31008c2ecf20Sopenharmony_ci	 * slot we found during our search, else error.
31018c2ecf20Sopenharmony_ci	 */
31028c2ecf20Sopenharmony_ci	if (!first_empty_slot)
31038c2ecf20Sopenharmony_ci		hw_dbg(hw, "No space in VLVF.\n");
31048c2ecf20Sopenharmony_ci
31058c2ecf20Sopenharmony_ci	return first_empty_slot ? : -ENOSPC;
31068c2ecf20Sopenharmony_ci}
31078c2ecf20Sopenharmony_ci
31088c2ecf20Sopenharmony_ci/**
31098c2ecf20Sopenharmony_ci *  ixgbe_set_vfta_generic - Set VLAN filter table
31108c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
31118c2ecf20Sopenharmony_ci *  @vlan: VLAN id to write to VLAN filter
31128c2ecf20Sopenharmony_ci *  @vind: VMDq output index that maps queue to VLAN id in VFVFB
31138c2ecf20Sopenharmony_ci *  @vlan_on: boolean flag to turn on/off VLAN in VFVF
31148c2ecf20Sopenharmony_ci *  @vlvf_bypass: boolean flag indicating updating default pool is okay
31158c2ecf20Sopenharmony_ci *
31168c2ecf20Sopenharmony_ci *  Turn on/off specified VLAN in the VLAN filter table.
31178c2ecf20Sopenharmony_ci **/
31188c2ecf20Sopenharmony_cis32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
31198c2ecf20Sopenharmony_ci			   bool vlan_on, bool vlvf_bypass)
31208c2ecf20Sopenharmony_ci{
31218c2ecf20Sopenharmony_ci	u32 regidx, vfta_delta, vfta, bits;
31228c2ecf20Sopenharmony_ci	s32 vlvf_index;
31238c2ecf20Sopenharmony_ci
31248c2ecf20Sopenharmony_ci	if ((vlan > 4095) || (vind > 63))
31258c2ecf20Sopenharmony_ci		return -EINVAL;
31268c2ecf20Sopenharmony_ci
31278c2ecf20Sopenharmony_ci	/*
31288c2ecf20Sopenharmony_ci	 * this is a 2 part operation - first the VFTA, then the
31298c2ecf20Sopenharmony_ci	 * VLVF and VLVFB if VT Mode is set
31308c2ecf20Sopenharmony_ci	 * We don't write the VFTA until we know the VLVF part succeeded.
31318c2ecf20Sopenharmony_ci	 */
31328c2ecf20Sopenharmony_ci
31338c2ecf20Sopenharmony_ci	/* Part 1
31348c2ecf20Sopenharmony_ci	 * The VFTA is a bitstring made up of 128 32-bit registers
31358c2ecf20Sopenharmony_ci	 * that enable the particular VLAN id, much like the MTA:
31368c2ecf20Sopenharmony_ci	 *    bits[11-5]: which register
31378c2ecf20Sopenharmony_ci	 *    bits[4-0]:  which bit in the register
31388c2ecf20Sopenharmony_ci	 */
31398c2ecf20Sopenharmony_ci	regidx = vlan / 32;
31408c2ecf20Sopenharmony_ci	vfta_delta = BIT(vlan % 32);
31418c2ecf20Sopenharmony_ci	vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx));
31428c2ecf20Sopenharmony_ci
31438c2ecf20Sopenharmony_ci	/* vfta_delta represents the difference between the current value
31448c2ecf20Sopenharmony_ci	 * of vfta and the value we want in the register.  Since the diff
31458c2ecf20Sopenharmony_ci	 * is an XOR mask we can just update vfta using an XOR.
31468c2ecf20Sopenharmony_ci	 */
31478c2ecf20Sopenharmony_ci	vfta_delta &= vlan_on ? ~vfta : vfta;
31488c2ecf20Sopenharmony_ci	vfta ^= vfta_delta;
31498c2ecf20Sopenharmony_ci
31508c2ecf20Sopenharmony_ci	/* Part 2
31518c2ecf20Sopenharmony_ci	 * If VT Mode is set
31528c2ecf20Sopenharmony_ci	 *   Either vlan_on
31538c2ecf20Sopenharmony_ci	 *     make sure the vlan is in VLVF
31548c2ecf20Sopenharmony_ci	 *     set the vind bit in the matching VLVFB
31558c2ecf20Sopenharmony_ci	 *   Or !vlan_on
31568c2ecf20Sopenharmony_ci	 *     clear the pool bit and possibly the vind
31578c2ecf20Sopenharmony_ci	 */
31588c2ecf20Sopenharmony_ci	if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE))
31598c2ecf20Sopenharmony_ci		goto vfta_update;
31608c2ecf20Sopenharmony_ci
31618c2ecf20Sopenharmony_ci	vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass);
31628c2ecf20Sopenharmony_ci	if (vlvf_index < 0) {
31638c2ecf20Sopenharmony_ci		if (vlvf_bypass)
31648c2ecf20Sopenharmony_ci			goto vfta_update;
31658c2ecf20Sopenharmony_ci		return vlvf_index;
31668c2ecf20Sopenharmony_ci	}
31678c2ecf20Sopenharmony_ci
31688c2ecf20Sopenharmony_ci	bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32));
31698c2ecf20Sopenharmony_ci
31708c2ecf20Sopenharmony_ci	/* set the pool bit */
31718c2ecf20Sopenharmony_ci	bits |= BIT(vind % 32);
31728c2ecf20Sopenharmony_ci	if (vlan_on)
31738c2ecf20Sopenharmony_ci		goto vlvf_update;
31748c2ecf20Sopenharmony_ci
31758c2ecf20Sopenharmony_ci	/* clear the pool bit */
31768c2ecf20Sopenharmony_ci	bits ^= BIT(vind % 32);
31778c2ecf20Sopenharmony_ci
31788c2ecf20Sopenharmony_ci	if (!bits &&
31798c2ecf20Sopenharmony_ci	    !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) {
31808c2ecf20Sopenharmony_ci		/* Clear VFTA first, then disable VLVF.  Otherwise
31818c2ecf20Sopenharmony_ci		 * we run the risk of stray packets leaking into
31828c2ecf20Sopenharmony_ci		 * the PF via the default pool
31838c2ecf20Sopenharmony_ci		 */
31848c2ecf20Sopenharmony_ci		if (vfta_delta)
31858c2ecf20Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta);
31868c2ecf20Sopenharmony_ci
31878c2ecf20Sopenharmony_ci		/* disable VLVF and clear remaining bit from pool */
31888c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
31898c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0);
31908c2ecf20Sopenharmony_ci
31918c2ecf20Sopenharmony_ci		return 0;
31928c2ecf20Sopenharmony_ci	}
31938c2ecf20Sopenharmony_ci
31948c2ecf20Sopenharmony_ci	/* If there are still bits set in the VLVFB registers
31958c2ecf20Sopenharmony_ci	 * for the VLAN ID indicated we need to see if the
31968c2ecf20Sopenharmony_ci	 * caller is requesting that we clear the VFTA entry bit.
31978c2ecf20Sopenharmony_ci	 * If the caller has requested that we clear the VFTA
31988c2ecf20Sopenharmony_ci	 * entry bit but there are still pools/VFs using this VLAN
31998c2ecf20Sopenharmony_ci	 * ID entry then ignore the request.  We're not worried
32008c2ecf20Sopenharmony_ci	 * about the case where we're turning the VFTA VLAN ID
32018c2ecf20Sopenharmony_ci	 * entry bit on, only when requested to turn it off as
32028c2ecf20Sopenharmony_ci	 * there may be multiple pools and/or VFs using the
32038c2ecf20Sopenharmony_ci	 * VLAN ID entry.  In that case we cannot clear the
32048c2ecf20Sopenharmony_ci	 * VFTA bit until all pools/VFs using that VLAN ID have also
32058c2ecf20Sopenharmony_ci	 * been cleared.  This will be indicated by "bits" being
32068c2ecf20Sopenharmony_ci	 * zero.
32078c2ecf20Sopenharmony_ci	 */
32088c2ecf20Sopenharmony_ci	vfta_delta = 0;
32098c2ecf20Sopenharmony_ci
32108c2ecf20Sopenharmony_civlvf_update:
32118c2ecf20Sopenharmony_ci	/* record pool change and enable VLAN ID if not already enabled */
32128c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits);
32138c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan);
32148c2ecf20Sopenharmony_ci
32158c2ecf20Sopenharmony_civfta_update:
32168c2ecf20Sopenharmony_ci	/* Update VFTA now that we are ready for traffic */
32178c2ecf20Sopenharmony_ci	if (vfta_delta)
32188c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta);
32198c2ecf20Sopenharmony_ci
32208c2ecf20Sopenharmony_ci	return 0;
32218c2ecf20Sopenharmony_ci}
32228c2ecf20Sopenharmony_ci
32238c2ecf20Sopenharmony_ci/**
32248c2ecf20Sopenharmony_ci *  ixgbe_clear_vfta_generic - Clear VLAN filter table
32258c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
32268c2ecf20Sopenharmony_ci *
32278c2ecf20Sopenharmony_ci *  Clears the VLAN filer table, and the VMDq index associated with the filter
32288c2ecf20Sopenharmony_ci **/
32298c2ecf20Sopenharmony_cis32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
32308c2ecf20Sopenharmony_ci{
32318c2ecf20Sopenharmony_ci	u32 offset;
32328c2ecf20Sopenharmony_ci
32338c2ecf20Sopenharmony_ci	for (offset = 0; offset < hw->mac.vft_size; offset++)
32348c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
32358c2ecf20Sopenharmony_ci
32368c2ecf20Sopenharmony_ci	for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) {
32378c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0);
32388c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0);
32398c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2 + 1), 0);
32408c2ecf20Sopenharmony_ci	}
32418c2ecf20Sopenharmony_ci
32428c2ecf20Sopenharmony_ci	return 0;
32438c2ecf20Sopenharmony_ci}
32448c2ecf20Sopenharmony_ci
32458c2ecf20Sopenharmony_ci/**
32468c2ecf20Sopenharmony_ci *  ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix
32478c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
32488c2ecf20Sopenharmony_ci *
32498c2ecf20Sopenharmony_ci *  Contains the logic to identify if we need to verify link for the
32508c2ecf20Sopenharmony_ci *  crosstalk fix
32518c2ecf20Sopenharmony_ci **/
32528c2ecf20Sopenharmony_cistatic bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw)
32538c2ecf20Sopenharmony_ci{
32548c2ecf20Sopenharmony_ci	/* Does FW say we need the fix */
32558c2ecf20Sopenharmony_ci	if (!hw->need_crosstalk_fix)
32568c2ecf20Sopenharmony_ci		return false;
32578c2ecf20Sopenharmony_ci
32588c2ecf20Sopenharmony_ci	/* Only consider SFP+ PHYs i.e. media type fiber */
32598c2ecf20Sopenharmony_ci	switch (hw->mac.ops.get_media_type(hw)) {
32608c2ecf20Sopenharmony_ci	case ixgbe_media_type_fiber:
32618c2ecf20Sopenharmony_ci	case ixgbe_media_type_fiber_qsfp:
32628c2ecf20Sopenharmony_ci		break;
32638c2ecf20Sopenharmony_ci	default:
32648c2ecf20Sopenharmony_ci		return false;
32658c2ecf20Sopenharmony_ci	}
32668c2ecf20Sopenharmony_ci
32678c2ecf20Sopenharmony_ci	return true;
32688c2ecf20Sopenharmony_ci}
32698c2ecf20Sopenharmony_ci
32708c2ecf20Sopenharmony_ci/**
32718c2ecf20Sopenharmony_ci *  ixgbe_check_mac_link_generic - Determine link and speed status
32728c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
32738c2ecf20Sopenharmony_ci *  @speed: pointer to link speed
32748c2ecf20Sopenharmony_ci *  @link_up: true when link is up
32758c2ecf20Sopenharmony_ci *  @link_up_wait_to_complete: bool used to wait for link up or not
32768c2ecf20Sopenharmony_ci *
32778c2ecf20Sopenharmony_ci *  Reads the links register to determine if link is up and the current speed
32788c2ecf20Sopenharmony_ci **/
32798c2ecf20Sopenharmony_cis32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
32808c2ecf20Sopenharmony_ci				 bool *link_up, bool link_up_wait_to_complete)
32818c2ecf20Sopenharmony_ci{
32828c2ecf20Sopenharmony_ci	u32 links_reg, links_orig;
32838c2ecf20Sopenharmony_ci	u32 i;
32848c2ecf20Sopenharmony_ci
32858c2ecf20Sopenharmony_ci	/* If Crosstalk fix enabled do the sanity check of making sure
32868c2ecf20Sopenharmony_ci	 * the SFP+ cage is full.
32878c2ecf20Sopenharmony_ci	 */
32888c2ecf20Sopenharmony_ci	if (ixgbe_need_crosstalk_fix(hw)) {
32898c2ecf20Sopenharmony_ci		u32 sfp_cage_full;
32908c2ecf20Sopenharmony_ci
32918c2ecf20Sopenharmony_ci		switch (hw->mac.type) {
32928c2ecf20Sopenharmony_ci		case ixgbe_mac_82599EB:
32938c2ecf20Sopenharmony_ci			sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
32948c2ecf20Sopenharmony_ci					IXGBE_ESDP_SDP2;
32958c2ecf20Sopenharmony_ci			break;
32968c2ecf20Sopenharmony_ci		case ixgbe_mac_X550EM_x:
32978c2ecf20Sopenharmony_ci		case ixgbe_mac_x550em_a:
32988c2ecf20Sopenharmony_ci			sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
32998c2ecf20Sopenharmony_ci					IXGBE_ESDP_SDP0;
33008c2ecf20Sopenharmony_ci			break;
33018c2ecf20Sopenharmony_ci		default:
33028c2ecf20Sopenharmony_ci			/* sanity check - No SFP+ devices here */
33038c2ecf20Sopenharmony_ci			sfp_cage_full = false;
33048c2ecf20Sopenharmony_ci			break;
33058c2ecf20Sopenharmony_ci		}
33068c2ecf20Sopenharmony_ci
33078c2ecf20Sopenharmony_ci		if (!sfp_cage_full) {
33088c2ecf20Sopenharmony_ci			*link_up = false;
33098c2ecf20Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_UNKNOWN;
33108c2ecf20Sopenharmony_ci			return 0;
33118c2ecf20Sopenharmony_ci		}
33128c2ecf20Sopenharmony_ci	}
33138c2ecf20Sopenharmony_ci
33148c2ecf20Sopenharmony_ci	/* clear the old state */
33158c2ecf20Sopenharmony_ci	links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS);
33168c2ecf20Sopenharmony_ci
33178c2ecf20Sopenharmony_ci	links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
33188c2ecf20Sopenharmony_ci
33198c2ecf20Sopenharmony_ci	if (links_orig != links_reg) {
33208c2ecf20Sopenharmony_ci		hw_dbg(hw, "LINKS changed from %08X to %08X\n",
33218c2ecf20Sopenharmony_ci		       links_orig, links_reg);
33228c2ecf20Sopenharmony_ci	}
33238c2ecf20Sopenharmony_ci
33248c2ecf20Sopenharmony_ci	if (link_up_wait_to_complete) {
33258c2ecf20Sopenharmony_ci		for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
33268c2ecf20Sopenharmony_ci			if (links_reg & IXGBE_LINKS_UP) {
33278c2ecf20Sopenharmony_ci				*link_up = true;
33288c2ecf20Sopenharmony_ci				break;
33298c2ecf20Sopenharmony_ci			} else {
33308c2ecf20Sopenharmony_ci				*link_up = false;
33318c2ecf20Sopenharmony_ci			}
33328c2ecf20Sopenharmony_ci			msleep(100);
33338c2ecf20Sopenharmony_ci			links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
33348c2ecf20Sopenharmony_ci		}
33358c2ecf20Sopenharmony_ci	} else {
33368c2ecf20Sopenharmony_ci		if (links_reg & IXGBE_LINKS_UP)
33378c2ecf20Sopenharmony_ci			*link_up = true;
33388c2ecf20Sopenharmony_ci		else
33398c2ecf20Sopenharmony_ci			*link_up = false;
33408c2ecf20Sopenharmony_ci	}
33418c2ecf20Sopenharmony_ci
33428c2ecf20Sopenharmony_ci	switch (links_reg & IXGBE_LINKS_SPEED_82599) {
33438c2ecf20Sopenharmony_ci	case IXGBE_LINKS_SPEED_10G_82599:
33448c2ecf20Sopenharmony_ci		if ((hw->mac.type >= ixgbe_mac_X550) &&
33458c2ecf20Sopenharmony_ci		    (links_reg & IXGBE_LINKS_SPEED_NON_STD))
33468c2ecf20Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_2_5GB_FULL;
33478c2ecf20Sopenharmony_ci		else
33488c2ecf20Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_10GB_FULL;
33498c2ecf20Sopenharmony_ci		break;
33508c2ecf20Sopenharmony_ci	case IXGBE_LINKS_SPEED_1G_82599:
33518c2ecf20Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_1GB_FULL;
33528c2ecf20Sopenharmony_ci		break;
33538c2ecf20Sopenharmony_ci	case IXGBE_LINKS_SPEED_100_82599:
33548c2ecf20Sopenharmony_ci		if ((hw->mac.type >= ixgbe_mac_X550) &&
33558c2ecf20Sopenharmony_ci		    (links_reg & IXGBE_LINKS_SPEED_NON_STD))
33568c2ecf20Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_5GB_FULL;
33578c2ecf20Sopenharmony_ci		else
33588c2ecf20Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_100_FULL;
33598c2ecf20Sopenharmony_ci		break;
33608c2ecf20Sopenharmony_ci	case IXGBE_LINKS_SPEED_10_X550EM_A:
33618c2ecf20Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_UNKNOWN;
33628c2ecf20Sopenharmony_ci		if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
33638c2ecf20Sopenharmony_ci		    hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) {
33648c2ecf20Sopenharmony_ci			*speed = IXGBE_LINK_SPEED_10_FULL;
33658c2ecf20Sopenharmony_ci		}
33668c2ecf20Sopenharmony_ci		break;
33678c2ecf20Sopenharmony_ci	default:
33688c2ecf20Sopenharmony_ci		*speed = IXGBE_LINK_SPEED_UNKNOWN;
33698c2ecf20Sopenharmony_ci	}
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_ci	return 0;
33728c2ecf20Sopenharmony_ci}
33738c2ecf20Sopenharmony_ci
33748c2ecf20Sopenharmony_ci/**
33758c2ecf20Sopenharmony_ci *  ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from
33768c2ecf20Sopenharmony_ci *  the EEPROM
33778c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
33788c2ecf20Sopenharmony_ci *  @wwnn_prefix: the alternative WWNN prefix
33798c2ecf20Sopenharmony_ci *  @wwpn_prefix: the alternative WWPN prefix
33808c2ecf20Sopenharmony_ci *
33818c2ecf20Sopenharmony_ci *  This function will read the EEPROM from the alternative SAN MAC address
33828c2ecf20Sopenharmony_ci *  block to check the support for the alternative WWNN/WWPN prefix support.
33838c2ecf20Sopenharmony_ci **/
33848c2ecf20Sopenharmony_cis32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
33858c2ecf20Sopenharmony_ci					u16 *wwpn_prefix)
33868c2ecf20Sopenharmony_ci{
33878c2ecf20Sopenharmony_ci	u16 offset, caps;
33888c2ecf20Sopenharmony_ci	u16 alt_san_mac_blk_offset;
33898c2ecf20Sopenharmony_ci
33908c2ecf20Sopenharmony_ci	/* clear output first */
33918c2ecf20Sopenharmony_ci	*wwnn_prefix = 0xFFFF;
33928c2ecf20Sopenharmony_ci	*wwpn_prefix = 0xFFFF;
33938c2ecf20Sopenharmony_ci
33948c2ecf20Sopenharmony_ci	/* check if alternative SAN MAC is supported */
33958c2ecf20Sopenharmony_ci	offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR;
33968c2ecf20Sopenharmony_ci	if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset))
33978c2ecf20Sopenharmony_ci		goto wwn_prefix_err;
33988c2ecf20Sopenharmony_ci
33998c2ecf20Sopenharmony_ci	if ((alt_san_mac_blk_offset == 0) ||
34008c2ecf20Sopenharmony_ci	    (alt_san_mac_blk_offset == 0xFFFF))
34018c2ecf20Sopenharmony_ci		return 0;
34028c2ecf20Sopenharmony_ci
34038c2ecf20Sopenharmony_ci	/* check capability in alternative san mac address block */
34048c2ecf20Sopenharmony_ci	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
34058c2ecf20Sopenharmony_ci	if (hw->eeprom.ops.read(hw, offset, &caps))
34068c2ecf20Sopenharmony_ci		goto wwn_prefix_err;
34078c2ecf20Sopenharmony_ci	if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
34088c2ecf20Sopenharmony_ci		return 0;
34098c2ecf20Sopenharmony_ci
34108c2ecf20Sopenharmony_ci	/* get the corresponding prefix for WWNN/WWPN */
34118c2ecf20Sopenharmony_ci	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
34128c2ecf20Sopenharmony_ci	if (hw->eeprom.ops.read(hw, offset, wwnn_prefix))
34138c2ecf20Sopenharmony_ci		hw_err(hw, "eeprom read at offset %d failed\n", offset);
34148c2ecf20Sopenharmony_ci
34158c2ecf20Sopenharmony_ci	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET;
34168c2ecf20Sopenharmony_ci	if (hw->eeprom.ops.read(hw, offset, wwpn_prefix))
34178c2ecf20Sopenharmony_ci		goto wwn_prefix_err;
34188c2ecf20Sopenharmony_ci
34198c2ecf20Sopenharmony_ci	return 0;
34208c2ecf20Sopenharmony_ci
34218c2ecf20Sopenharmony_ciwwn_prefix_err:
34228c2ecf20Sopenharmony_ci	hw_err(hw, "eeprom read at offset %d failed\n", offset);
34238c2ecf20Sopenharmony_ci	return 0;
34248c2ecf20Sopenharmony_ci}
34258c2ecf20Sopenharmony_ci
34268c2ecf20Sopenharmony_ci/**
34278c2ecf20Sopenharmony_ci *  ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing
34288c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
34298c2ecf20Sopenharmony_ci *  @enable: enable or disable switch for MAC anti-spoofing
34308c2ecf20Sopenharmony_ci *  @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing
34318c2ecf20Sopenharmony_ci *
34328c2ecf20Sopenharmony_ci **/
34338c2ecf20Sopenharmony_civoid ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
34348c2ecf20Sopenharmony_ci{
34358c2ecf20Sopenharmony_ci	int vf_target_reg = vf >> 3;
34368c2ecf20Sopenharmony_ci	int vf_target_shift = vf % 8;
34378c2ecf20Sopenharmony_ci	u32 pfvfspoof;
34388c2ecf20Sopenharmony_ci
34398c2ecf20Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_82598EB)
34408c2ecf20Sopenharmony_ci		return;
34418c2ecf20Sopenharmony_ci
34428c2ecf20Sopenharmony_ci	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
34438c2ecf20Sopenharmony_ci	if (enable)
34448c2ecf20Sopenharmony_ci		pfvfspoof |= BIT(vf_target_shift);
34458c2ecf20Sopenharmony_ci	else
34468c2ecf20Sopenharmony_ci		pfvfspoof &= ~BIT(vf_target_shift);
34478c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
34488c2ecf20Sopenharmony_ci}
34498c2ecf20Sopenharmony_ci
34508c2ecf20Sopenharmony_ci/**
34518c2ecf20Sopenharmony_ci *  ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing
34528c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
34538c2ecf20Sopenharmony_ci *  @enable: enable or disable switch for VLAN anti-spoofing
34548c2ecf20Sopenharmony_ci *  @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing
34558c2ecf20Sopenharmony_ci *
34568c2ecf20Sopenharmony_ci **/
34578c2ecf20Sopenharmony_civoid ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
34588c2ecf20Sopenharmony_ci{
34598c2ecf20Sopenharmony_ci	int vf_target_reg = vf >> 3;
34608c2ecf20Sopenharmony_ci	int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT;
34618c2ecf20Sopenharmony_ci	u32 pfvfspoof;
34628c2ecf20Sopenharmony_ci
34638c2ecf20Sopenharmony_ci	if (hw->mac.type == ixgbe_mac_82598EB)
34648c2ecf20Sopenharmony_ci		return;
34658c2ecf20Sopenharmony_ci
34668c2ecf20Sopenharmony_ci	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
34678c2ecf20Sopenharmony_ci	if (enable)
34688c2ecf20Sopenharmony_ci		pfvfspoof |= BIT(vf_target_shift);
34698c2ecf20Sopenharmony_ci	else
34708c2ecf20Sopenharmony_ci		pfvfspoof &= ~BIT(vf_target_shift);
34718c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
34728c2ecf20Sopenharmony_ci}
34738c2ecf20Sopenharmony_ci
34748c2ecf20Sopenharmony_ci/**
34758c2ecf20Sopenharmony_ci *  ixgbe_get_device_caps_generic - Get additional device capabilities
34768c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
34778c2ecf20Sopenharmony_ci *  @device_caps: the EEPROM word with the extra device capabilities
34788c2ecf20Sopenharmony_ci *
34798c2ecf20Sopenharmony_ci *  This function will read the EEPROM location for the device capabilities,
34808c2ecf20Sopenharmony_ci *  and return the word through device_caps.
34818c2ecf20Sopenharmony_ci **/
34828c2ecf20Sopenharmony_cis32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps)
34838c2ecf20Sopenharmony_ci{
34848c2ecf20Sopenharmony_ci	hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps);
34858c2ecf20Sopenharmony_ci
34868c2ecf20Sopenharmony_ci	return 0;
34878c2ecf20Sopenharmony_ci}
34888c2ecf20Sopenharmony_ci
34898c2ecf20Sopenharmony_ci/**
34908c2ecf20Sopenharmony_ci * ixgbe_set_rxpba_generic - Initialize RX packet buffer
34918c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure
34928c2ecf20Sopenharmony_ci * @num_pb: number of packet buffers to allocate
34938c2ecf20Sopenharmony_ci * @headroom: reserve n KB of headroom
34948c2ecf20Sopenharmony_ci * @strategy: packet buffer allocation strategy
34958c2ecf20Sopenharmony_ci **/
34968c2ecf20Sopenharmony_civoid ixgbe_set_rxpba_generic(struct ixgbe_hw *hw,
34978c2ecf20Sopenharmony_ci			     int num_pb,
34988c2ecf20Sopenharmony_ci			     u32 headroom,
34998c2ecf20Sopenharmony_ci			     int strategy)
35008c2ecf20Sopenharmony_ci{
35018c2ecf20Sopenharmony_ci	u32 pbsize = hw->mac.rx_pb_size;
35028c2ecf20Sopenharmony_ci	int i = 0;
35038c2ecf20Sopenharmony_ci	u32 rxpktsize, txpktsize, txpbthresh;
35048c2ecf20Sopenharmony_ci
35058c2ecf20Sopenharmony_ci	/* Reserve headroom */
35068c2ecf20Sopenharmony_ci	pbsize -= headroom;
35078c2ecf20Sopenharmony_ci
35088c2ecf20Sopenharmony_ci	if (!num_pb)
35098c2ecf20Sopenharmony_ci		num_pb = 1;
35108c2ecf20Sopenharmony_ci
35118c2ecf20Sopenharmony_ci	/* Divide remaining packet buffer space amongst the number
35128c2ecf20Sopenharmony_ci	 * of packet buffers requested using supplied strategy.
35138c2ecf20Sopenharmony_ci	 */
35148c2ecf20Sopenharmony_ci	switch (strategy) {
35158c2ecf20Sopenharmony_ci	case (PBA_STRATEGY_WEIGHTED):
35168c2ecf20Sopenharmony_ci		/* pba_80_48 strategy weight first half of packet buffer with
35178c2ecf20Sopenharmony_ci		 * 5/8 of the packet buffer space.
35188c2ecf20Sopenharmony_ci		 */
35198c2ecf20Sopenharmony_ci		rxpktsize = ((pbsize * 5 * 2) / (num_pb * 8));
35208c2ecf20Sopenharmony_ci		pbsize -= rxpktsize * (num_pb / 2);
35218c2ecf20Sopenharmony_ci		rxpktsize <<= IXGBE_RXPBSIZE_SHIFT;
35228c2ecf20Sopenharmony_ci		for (; i < (num_pb / 2); i++)
35238c2ecf20Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
35248c2ecf20Sopenharmony_ci		fallthrough; /* configure remaining packet buffers */
35258c2ecf20Sopenharmony_ci	case (PBA_STRATEGY_EQUAL):
35268c2ecf20Sopenharmony_ci		/* Divide the remaining Rx packet buffer evenly among the TCs */
35278c2ecf20Sopenharmony_ci		rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT;
35288c2ecf20Sopenharmony_ci		for (; i < num_pb; i++)
35298c2ecf20Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
35308c2ecf20Sopenharmony_ci		break;
35318c2ecf20Sopenharmony_ci	default:
35328c2ecf20Sopenharmony_ci		break;
35338c2ecf20Sopenharmony_ci	}
35348c2ecf20Sopenharmony_ci
35358c2ecf20Sopenharmony_ci	/*
35368c2ecf20Sopenharmony_ci	 * Setup Tx packet buffer and threshold equally for all TCs
35378c2ecf20Sopenharmony_ci	 * TXPBTHRESH register is set in K so divide by 1024 and subtract
35388c2ecf20Sopenharmony_ci	 * 10 since the largest packet we support is just over 9K.
35398c2ecf20Sopenharmony_ci	 */
35408c2ecf20Sopenharmony_ci	txpktsize = IXGBE_TXPBSIZE_MAX / num_pb;
35418c2ecf20Sopenharmony_ci	txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX;
35428c2ecf20Sopenharmony_ci	for (i = 0; i < num_pb; i++) {
35438c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize);
35448c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh);
35458c2ecf20Sopenharmony_ci	}
35468c2ecf20Sopenharmony_ci
35478c2ecf20Sopenharmony_ci	/* Clear unused TCs, if any, to zero buffer size*/
35488c2ecf20Sopenharmony_ci	for (; i < IXGBE_MAX_PB; i++) {
35498c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
35508c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0);
35518c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0);
35528c2ecf20Sopenharmony_ci	}
35538c2ecf20Sopenharmony_ci}
35548c2ecf20Sopenharmony_ci
35558c2ecf20Sopenharmony_ci/**
35568c2ecf20Sopenharmony_ci *  ixgbe_calculate_checksum - Calculate checksum for buffer
35578c2ecf20Sopenharmony_ci *  @buffer: pointer to EEPROM
35588c2ecf20Sopenharmony_ci *  @length: size of EEPROM to calculate a checksum for
35598c2ecf20Sopenharmony_ci *
35608c2ecf20Sopenharmony_ci *  Calculates the checksum for some buffer on a specified length.  The
35618c2ecf20Sopenharmony_ci *  checksum calculated is returned.
35628c2ecf20Sopenharmony_ci **/
35638c2ecf20Sopenharmony_ciu8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
35648c2ecf20Sopenharmony_ci{
35658c2ecf20Sopenharmony_ci	u32 i;
35668c2ecf20Sopenharmony_ci	u8 sum = 0;
35678c2ecf20Sopenharmony_ci
35688c2ecf20Sopenharmony_ci	if (!buffer)
35698c2ecf20Sopenharmony_ci		return 0;
35708c2ecf20Sopenharmony_ci
35718c2ecf20Sopenharmony_ci	for (i = 0; i < length; i++)
35728c2ecf20Sopenharmony_ci		sum += buffer[i];
35738c2ecf20Sopenharmony_ci
35748c2ecf20Sopenharmony_ci	return (u8) (0 - sum);
35758c2ecf20Sopenharmony_ci}
35768c2ecf20Sopenharmony_ci
35778c2ecf20Sopenharmony_ci/**
35788c2ecf20Sopenharmony_ci *  ixgbe_hic_unlocked - Issue command to manageability block unlocked
35798c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
35808c2ecf20Sopenharmony_ci *  @buffer: command to write and where the return status will be placed
35818c2ecf20Sopenharmony_ci *  @length: length of buffer, must be multiple of 4 bytes
35828c2ecf20Sopenharmony_ci *  @timeout: time in ms to wait for command completion
35838c2ecf20Sopenharmony_ci *
35848c2ecf20Sopenharmony_ci *  Communicates with the manageability block. On success return 0
35858c2ecf20Sopenharmony_ci *  else returns semaphore error when encountering an error acquiring
35868c2ecf20Sopenharmony_ci *  semaphore, -EINVAL when incorrect parameters passed or -EIO when
35878c2ecf20Sopenharmony_ci *  command fails.
35888c2ecf20Sopenharmony_ci *
35898c2ecf20Sopenharmony_ci *  This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held
35908c2ecf20Sopenharmony_ci *  by the caller.
35918c2ecf20Sopenharmony_ci **/
35928c2ecf20Sopenharmony_cis32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length,
35938c2ecf20Sopenharmony_ci		       u32 timeout)
35948c2ecf20Sopenharmony_ci{
35958c2ecf20Sopenharmony_ci	u32 hicr, i, fwsts;
35968c2ecf20Sopenharmony_ci	u16 dword_len;
35978c2ecf20Sopenharmony_ci
35988c2ecf20Sopenharmony_ci	if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
35998c2ecf20Sopenharmony_ci		hw_dbg(hw, "Buffer length failure buffersize-%d.\n", length);
36008c2ecf20Sopenharmony_ci		return -EINVAL;
36018c2ecf20Sopenharmony_ci	}
36028c2ecf20Sopenharmony_ci
36038c2ecf20Sopenharmony_ci	/* Set bit 9 of FWSTS clearing FW reset indication */
36048c2ecf20Sopenharmony_ci	fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS);
36058c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI);
36068c2ecf20Sopenharmony_ci
36078c2ecf20Sopenharmony_ci	/* Check that the host interface is enabled. */
36088c2ecf20Sopenharmony_ci	hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
36098c2ecf20Sopenharmony_ci	if (!(hicr & IXGBE_HICR_EN)) {
36108c2ecf20Sopenharmony_ci		hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n");
36118c2ecf20Sopenharmony_ci		return -EIO;
36128c2ecf20Sopenharmony_ci	}
36138c2ecf20Sopenharmony_ci
36148c2ecf20Sopenharmony_ci	/* Calculate length in DWORDs. We must be DWORD aligned */
36158c2ecf20Sopenharmony_ci	if (length % sizeof(u32)) {
36168c2ecf20Sopenharmony_ci		hw_dbg(hw, "Buffer length failure, not aligned to dword");
36178c2ecf20Sopenharmony_ci		return -EINVAL;
36188c2ecf20Sopenharmony_ci	}
36198c2ecf20Sopenharmony_ci
36208c2ecf20Sopenharmony_ci	dword_len = length >> 2;
36218c2ecf20Sopenharmony_ci
36228c2ecf20Sopenharmony_ci	/* The device driver writes the relevant command block
36238c2ecf20Sopenharmony_ci	 * into the ram area.
36248c2ecf20Sopenharmony_ci	 */
36258c2ecf20Sopenharmony_ci	for (i = 0; i < dword_len; i++)
36268c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG,
36278c2ecf20Sopenharmony_ci				      i, (__force u32)cpu_to_le32(buffer[i]));
36288c2ecf20Sopenharmony_ci
36298c2ecf20Sopenharmony_ci	/* Setting this bit tells the ARC that a new command is pending. */
36308c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C);
36318c2ecf20Sopenharmony_ci
36328c2ecf20Sopenharmony_ci	for (i = 0; i < timeout; i++) {
36338c2ecf20Sopenharmony_ci		hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
36348c2ecf20Sopenharmony_ci		if (!(hicr & IXGBE_HICR_C))
36358c2ecf20Sopenharmony_ci			break;
36368c2ecf20Sopenharmony_ci		usleep_range(1000, 2000);
36378c2ecf20Sopenharmony_ci	}
36388c2ecf20Sopenharmony_ci
36398c2ecf20Sopenharmony_ci	/* Check command successful completion. */
36408c2ecf20Sopenharmony_ci	if ((timeout && i == timeout) ||
36418c2ecf20Sopenharmony_ci	    !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))
36428c2ecf20Sopenharmony_ci		return -EIO;
36438c2ecf20Sopenharmony_ci
36448c2ecf20Sopenharmony_ci	return 0;
36458c2ecf20Sopenharmony_ci}
36468c2ecf20Sopenharmony_ci
36478c2ecf20Sopenharmony_ci/**
36488c2ecf20Sopenharmony_ci *  ixgbe_host_interface_command - Issue command to manageability block
36498c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
36508c2ecf20Sopenharmony_ci *  @buffer: contains the command to write and where the return status will
36518c2ecf20Sopenharmony_ci *           be placed
36528c2ecf20Sopenharmony_ci *  @length: length of buffer, must be multiple of 4 bytes
36538c2ecf20Sopenharmony_ci *  @timeout: time in ms to wait for command completion
36548c2ecf20Sopenharmony_ci *  @return_data: read and return data from the buffer (true) or not (false)
36558c2ecf20Sopenharmony_ci *  Needed because FW structures are big endian and decoding of
36568c2ecf20Sopenharmony_ci *  these fields can be 8 bit or 16 bit based on command. Decoding
36578c2ecf20Sopenharmony_ci *  is not easily understood without making a table of commands.
36588c2ecf20Sopenharmony_ci *  So we will leave this up to the caller to read back the data
36598c2ecf20Sopenharmony_ci *  in these cases.
36608c2ecf20Sopenharmony_ci *
36618c2ecf20Sopenharmony_ci *  Communicates with the manageability block.  On success return 0
36628c2ecf20Sopenharmony_ci *  else return -EIO or -EINVAL.
36638c2ecf20Sopenharmony_ci **/
36648c2ecf20Sopenharmony_cis32 ixgbe_host_interface_command(struct ixgbe_hw *hw, void *buffer,
36658c2ecf20Sopenharmony_ci				 u32 length, u32 timeout,
36668c2ecf20Sopenharmony_ci				 bool return_data)
36678c2ecf20Sopenharmony_ci{
36688c2ecf20Sopenharmony_ci	u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
36698c2ecf20Sopenharmony_ci	union {
36708c2ecf20Sopenharmony_ci		struct ixgbe_hic_hdr hdr;
36718c2ecf20Sopenharmony_ci		u32 u32arr[1];
36728c2ecf20Sopenharmony_ci	} *bp = buffer;
36738c2ecf20Sopenharmony_ci	u16 buf_len, dword_len;
36748c2ecf20Sopenharmony_ci	s32 status;
36758c2ecf20Sopenharmony_ci	u32 bi;
36768c2ecf20Sopenharmony_ci
36778c2ecf20Sopenharmony_ci	if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
36788c2ecf20Sopenharmony_ci		hw_dbg(hw, "Buffer length failure buffersize-%d.\n", length);
36798c2ecf20Sopenharmony_ci		return -EINVAL;
36808c2ecf20Sopenharmony_ci	}
36818c2ecf20Sopenharmony_ci	/* Take management host interface semaphore */
36828c2ecf20Sopenharmony_ci	status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
36838c2ecf20Sopenharmony_ci	if (status)
36848c2ecf20Sopenharmony_ci		return status;
36858c2ecf20Sopenharmony_ci
36868c2ecf20Sopenharmony_ci	status = ixgbe_hic_unlocked(hw, buffer, length, timeout);
36878c2ecf20Sopenharmony_ci	if (status)
36888c2ecf20Sopenharmony_ci		goto rel_out;
36898c2ecf20Sopenharmony_ci
36908c2ecf20Sopenharmony_ci	if (!return_data)
36918c2ecf20Sopenharmony_ci		goto rel_out;
36928c2ecf20Sopenharmony_ci
36938c2ecf20Sopenharmony_ci	/* Calculate length in DWORDs */
36948c2ecf20Sopenharmony_ci	dword_len = hdr_size >> 2;
36958c2ecf20Sopenharmony_ci
36968c2ecf20Sopenharmony_ci	/* first pull in the header so we know the buffer length */
36978c2ecf20Sopenharmony_ci	for (bi = 0; bi < dword_len; bi++) {
36988c2ecf20Sopenharmony_ci		bp->u32arr[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi);
36998c2ecf20Sopenharmony_ci		le32_to_cpus(&bp->u32arr[bi]);
37008c2ecf20Sopenharmony_ci	}
37018c2ecf20Sopenharmony_ci
37028c2ecf20Sopenharmony_ci	/* If there is any thing in data position pull it in */
37038c2ecf20Sopenharmony_ci	buf_len = bp->hdr.buf_len;
37048c2ecf20Sopenharmony_ci	if (!buf_len)
37058c2ecf20Sopenharmony_ci		goto rel_out;
37068c2ecf20Sopenharmony_ci
37078c2ecf20Sopenharmony_ci	if (length < round_up(buf_len, 4) + hdr_size) {
37088c2ecf20Sopenharmony_ci		hw_dbg(hw, "Buffer not large enough for reply message.\n");
37098c2ecf20Sopenharmony_ci		status = -EIO;
37108c2ecf20Sopenharmony_ci		goto rel_out;
37118c2ecf20Sopenharmony_ci	}
37128c2ecf20Sopenharmony_ci
37138c2ecf20Sopenharmony_ci	/* Calculate length in DWORDs, add 3 for odd lengths */
37148c2ecf20Sopenharmony_ci	dword_len = (buf_len + 3) >> 2;
37158c2ecf20Sopenharmony_ci
37168c2ecf20Sopenharmony_ci	/* Pull in the rest of the buffer (bi is where we left off) */
37178c2ecf20Sopenharmony_ci	for (; bi <= dword_len; bi++) {
37188c2ecf20Sopenharmony_ci		bp->u32arr[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi);
37198c2ecf20Sopenharmony_ci		le32_to_cpus(&bp->u32arr[bi]);
37208c2ecf20Sopenharmony_ci	}
37218c2ecf20Sopenharmony_ci
37228c2ecf20Sopenharmony_cirel_out:
37238c2ecf20Sopenharmony_ci	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
37248c2ecf20Sopenharmony_ci
37258c2ecf20Sopenharmony_ci	return status;
37268c2ecf20Sopenharmony_ci}
37278c2ecf20Sopenharmony_ci
37288c2ecf20Sopenharmony_ci/**
37298c2ecf20Sopenharmony_ci *  ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware
37308c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
37318c2ecf20Sopenharmony_ci *  @maj: driver version major number
37328c2ecf20Sopenharmony_ci *  @min: driver version minor number
37338c2ecf20Sopenharmony_ci *  @build: driver version build number
37348c2ecf20Sopenharmony_ci *  @sub: driver version sub build number
37358c2ecf20Sopenharmony_ci *  @len: length of driver_ver string
37368c2ecf20Sopenharmony_ci *  @driver_ver: driver string
37378c2ecf20Sopenharmony_ci *
37388c2ecf20Sopenharmony_ci *  Sends driver version number to firmware through the manageability
37398c2ecf20Sopenharmony_ci *  block.  On success return 0
37408c2ecf20Sopenharmony_ci *  else returns -EBUSY when encountering an error acquiring
37418c2ecf20Sopenharmony_ci *  semaphore or -EIO when command fails.
37428c2ecf20Sopenharmony_ci **/
37438c2ecf20Sopenharmony_cis32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
37448c2ecf20Sopenharmony_ci				 u8 build, u8 sub, __always_unused u16 len,
37458c2ecf20Sopenharmony_ci				 __always_unused const char *driver_ver)
37468c2ecf20Sopenharmony_ci{
37478c2ecf20Sopenharmony_ci	struct ixgbe_hic_drv_info fw_cmd;
37488c2ecf20Sopenharmony_ci	int i;
37498c2ecf20Sopenharmony_ci	s32 ret_val;
37508c2ecf20Sopenharmony_ci
37518c2ecf20Sopenharmony_ci	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
37528c2ecf20Sopenharmony_ci	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
37538c2ecf20Sopenharmony_ci	fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
37548c2ecf20Sopenharmony_ci	fw_cmd.port_num = hw->bus.func;
37558c2ecf20Sopenharmony_ci	fw_cmd.ver_maj = maj;
37568c2ecf20Sopenharmony_ci	fw_cmd.ver_min = min;
37578c2ecf20Sopenharmony_ci	fw_cmd.ver_build = build;
37588c2ecf20Sopenharmony_ci	fw_cmd.ver_sub = sub;
37598c2ecf20Sopenharmony_ci	fw_cmd.hdr.checksum = 0;
37608c2ecf20Sopenharmony_ci	fw_cmd.pad = 0;
37618c2ecf20Sopenharmony_ci	fw_cmd.pad2 = 0;
37628c2ecf20Sopenharmony_ci	fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
37638c2ecf20Sopenharmony_ci				(FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
37648c2ecf20Sopenharmony_ci
37658c2ecf20Sopenharmony_ci	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
37668c2ecf20Sopenharmony_ci		ret_val = ixgbe_host_interface_command(hw, &fw_cmd,
37678c2ecf20Sopenharmony_ci						       sizeof(fw_cmd),
37688c2ecf20Sopenharmony_ci						       IXGBE_HI_COMMAND_TIMEOUT,
37698c2ecf20Sopenharmony_ci						       true);
37708c2ecf20Sopenharmony_ci		if (ret_val != 0)
37718c2ecf20Sopenharmony_ci			continue;
37728c2ecf20Sopenharmony_ci
37738c2ecf20Sopenharmony_ci		if (fw_cmd.hdr.cmd_or_resp.ret_status ==
37748c2ecf20Sopenharmony_ci		    FW_CEM_RESP_STATUS_SUCCESS)
37758c2ecf20Sopenharmony_ci			ret_val = 0;
37768c2ecf20Sopenharmony_ci		else
37778c2ecf20Sopenharmony_ci			ret_val = -EIO;
37788c2ecf20Sopenharmony_ci
37798c2ecf20Sopenharmony_ci		break;
37808c2ecf20Sopenharmony_ci	}
37818c2ecf20Sopenharmony_ci
37828c2ecf20Sopenharmony_ci	return ret_val;
37838c2ecf20Sopenharmony_ci}
37848c2ecf20Sopenharmony_ci
37858c2ecf20Sopenharmony_ci/**
37868c2ecf20Sopenharmony_ci * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo
37878c2ecf20Sopenharmony_ci * @hw: pointer to the hardware structure
37888c2ecf20Sopenharmony_ci *
37898c2ecf20Sopenharmony_ci * The 82599 and x540 MACs can experience issues if TX work is still pending
37908c2ecf20Sopenharmony_ci * when a reset occurs.  This function prevents this by flushing the PCIe
37918c2ecf20Sopenharmony_ci * buffers on the system.
37928c2ecf20Sopenharmony_ci **/
37938c2ecf20Sopenharmony_civoid ixgbe_clear_tx_pending(struct ixgbe_hw *hw)
37948c2ecf20Sopenharmony_ci{
37958c2ecf20Sopenharmony_ci	u32 gcr_ext, hlreg0, i, poll;
37968c2ecf20Sopenharmony_ci	u16 value;
37978c2ecf20Sopenharmony_ci
37988c2ecf20Sopenharmony_ci	/*
37998c2ecf20Sopenharmony_ci	 * If double reset is not requested then all transactions should
38008c2ecf20Sopenharmony_ci	 * already be clear and as such there is no work to do
38018c2ecf20Sopenharmony_ci	 */
38028c2ecf20Sopenharmony_ci	if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED))
38038c2ecf20Sopenharmony_ci		return;
38048c2ecf20Sopenharmony_ci
38058c2ecf20Sopenharmony_ci	/*
38068c2ecf20Sopenharmony_ci	 * Set loopback enable to prevent any transmits from being sent
38078c2ecf20Sopenharmony_ci	 * should the link come up.  This assumes that the RXCTRL.RXEN bit
38088c2ecf20Sopenharmony_ci	 * has already been cleared.
38098c2ecf20Sopenharmony_ci	 */
38108c2ecf20Sopenharmony_ci	hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
38118c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK);
38128c2ecf20Sopenharmony_ci
38138c2ecf20Sopenharmony_ci	/* wait for a last completion before clearing buffers */
38148c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
38158c2ecf20Sopenharmony_ci	usleep_range(3000, 6000);
38168c2ecf20Sopenharmony_ci
38178c2ecf20Sopenharmony_ci	/* Before proceeding, make sure that the PCIe block does not have
38188c2ecf20Sopenharmony_ci	 * transactions pending.
38198c2ecf20Sopenharmony_ci	 */
38208c2ecf20Sopenharmony_ci	poll = ixgbe_pcie_timeout_poll(hw);
38218c2ecf20Sopenharmony_ci	for (i = 0; i < poll; i++) {
38228c2ecf20Sopenharmony_ci		usleep_range(100, 200);
38238c2ecf20Sopenharmony_ci		value = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_STATUS);
38248c2ecf20Sopenharmony_ci		if (ixgbe_removed(hw->hw_addr))
38258c2ecf20Sopenharmony_ci			break;
38268c2ecf20Sopenharmony_ci		if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
38278c2ecf20Sopenharmony_ci			break;
38288c2ecf20Sopenharmony_ci	}
38298c2ecf20Sopenharmony_ci
38308c2ecf20Sopenharmony_ci	/* initiate cleaning flow for buffers in the PCIe transaction layer */
38318c2ecf20Sopenharmony_ci	gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
38328c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT,
38338c2ecf20Sopenharmony_ci			gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR);
38348c2ecf20Sopenharmony_ci
38358c2ecf20Sopenharmony_ci	/* Flush all writes and allow 20usec for all transactions to clear */
38368c2ecf20Sopenharmony_ci	IXGBE_WRITE_FLUSH(hw);
38378c2ecf20Sopenharmony_ci	udelay(20);
38388c2ecf20Sopenharmony_ci
38398c2ecf20Sopenharmony_ci	/* restore previous register values */
38408c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
38418c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
38428c2ecf20Sopenharmony_ci}
38438c2ecf20Sopenharmony_ci
38448c2ecf20Sopenharmony_cistatic const u8 ixgbe_emc_temp_data[4] = {
38458c2ecf20Sopenharmony_ci	IXGBE_EMC_INTERNAL_DATA,
38468c2ecf20Sopenharmony_ci	IXGBE_EMC_DIODE1_DATA,
38478c2ecf20Sopenharmony_ci	IXGBE_EMC_DIODE2_DATA,
38488c2ecf20Sopenharmony_ci	IXGBE_EMC_DIODE3_DATA
38498c2ecf20Sopenharmony_ci};
38508c2ecf20Sopenharmony_cistatic const u8 ixgbe_emc_therm_limit[4] = {
38518c2ecf20Sopenharmony_ci	IXGBE_EMC_INTERNAL_THERM_LIMIT,
38528c2ecf20Sopenharmony_ci	IXGBE_EMC_DIODE1_THERM_LIMIT,
38538c2ecf20Sopenharmony_ci	IXGBE_EMC_DIODE2_THERM_LIMIT,
38548c2ecf20Sopenharmony_ci	IXGBE_EMC_DIODE3_THERM_LIMIT
38558c2ecf20Sopenharmony_ci};
38568c2ecf20Sopenharmony_ci
38578c2ecf20Sopenharmony_ci/**
38588c2ecf20Sopenharmony_ci *  ixgbe_get_ets_data - Extracts the ETS bit data
38598c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
38608c2ecf20Sopenharmony_ci *  @ets_cfg: extected ETS data
38618c2ecf20Sopenharmony_ci *  @ets_offset: offset of ETS data
38628c2ecf20Sopenharmony_ci *
38638c2ecf20Sopenharmony_ci *  Returns error code.
38648c2ecf20Sopenharmony_ci **/
38658c2ecf20Sopenharmony_cistatic s32 ixgbe_get_ets_data(struct ixgbe_hw *hw, u16 *ets_cfg,
38668c2ecf20Sopenharmony_ci			      u16 *ets_offset)
38678c2ecf20Sopenharmony_ci{
38688c2ecf20Sopenharmony_ci	s32 status;
38698c2ecf20Sopenharmony_ci
38708c2ecf20Sopenharmony_ci	status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, ets_offset);
38718c2ecf20Sopenharmony_ci	if (status)
38728c2ecf20Sopenharmony_ci		return status;
38738c2ecf20Sopenharmony_ci
38748c2ecf20Sopenharmony_ci	if ((*ets_offset == 0x0000) || (*ets_offset == 0xFFFF))
38758c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
38768c2ecf20Sopenharmony_ci
38778c2ecf20Sopenharmony_ci	status = hw->eeprom.ops.read(hw, *ets_offset, ets_cfg);
38788c2ecf20Sopenharmony_ci	if (status)
38798c2ecf20Sopenharmony_ci		return status;
38808c2ecf20Sopenharmony_ci
38818c2ecf20Sopenharmony_ci	if ((*ets_cfg & IXGBE_ETS_TYPE_MASK) != IXGBE_ETS_TYPE_EMC_SHIFTED)
38828c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
38838c2ecf20Sopenharmony_ci
38848c2ecf20Sopenharmony_ci	return 0;
38858c2ecf20Sopenharmony_ci}
38868c2ecf20Sopenharmony_ci
38878c2ecf20Sopenharmony_ci/**
38888c2ecf20Sopenharmony_ci *  ixgbe_get_thermal_sensor_data - Gathers thermal sensor data
38898c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
38908c2ecf20Sopenharmony_ci *
38918c2ecf20Sopenharmony_ci *  Returns the thermal sensor data structure
38928c2ecf20Sopenharmony_ci **/
38938c2ecf20Sopenharmony_cis32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw)
38948c2ecf20Sopenharmony_ci{
38958c2ecf20Sopenharmony_ci	s32 status;
38968c2ecf20Sopenharmony_ci	u16 ets_offset;
38978c2ecf20Sopenharmony_ci	u16 ets_cfg;
38988c2ecf20Sopenharmony_ci	u16 ets_sensor;
38998c2ecf20Sopenharmony_ci	u8  num_sensors;
39008c2ecf20Sopenharmony_ci	u8  i;
39018c2ecf20Sopenharmony_ci	struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
39028c2ecf20Sopenharmony_ci
39038c2ecf20Sopenharmony_ci	/* Only support thermal sensors attached to physical port 0 */
39048c2ecf20Sopenharmony_ci	if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1))
39058c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
39068c2ecf20Sopenharmony_ci
39078c2ecf20Sopenharmony_ci	status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
39088c2ecf20Sopenharmony_ci	if (status)
39098c2ecf20Sopenharmony_ci		return status;
39108c2ecf20Sopenharmony_ci
39118c2ecf20Sopenharmony_ci	num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK);
39128c2ecf20Sopenharmony_ci	if (num_sensors > IXGBE_MAX_SENSORS)
39138c2ecf20Sopenharmony_ci		num_sensors = IXGBE_MAX_SENSORS;
39148c2ecf20Sopenharmony_ci
39158c2ecf20Sopenharmony_ci	for (i = 0; i < num_sensors; i++) {
39168c2ecf20Sopenharmony_ci		u8  sensor_index;
39178c2ecf20Sopenharmony_ci		u8  sensor_location;
39188c2ecf20Sopenharmony_ci
39198c2ecf20Sopenharmony_ci		status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i),
39208c2ecf20Sopenharmony_ci					     &ets_sensor);
39218c2ecf20Sopenharmony_ci		if (status)
39228c2ecf20Sopenharmony_ci			return status;
39238c2ecf20Sopenharmony_ci
39248c2ecf20Sopenharmony_ci		sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
39258c2ecf20Sopenharmony_ci				IXGBE_ETS_DATA_INDEX_SHIFT);
39268c2ecf20Sopenharmony_ci		sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >>
39278c2ecf20Sopenharmony_ci				   IXGBE_ETS_DATA_LOC_SHIFT);
39288c2ecf20Sopenharmony_ci
39298c2ecf20Sopenharmony_ci		if (sensor_location != 0) {
39308c2ecf20Sopenharmony_ci			status = hw->phy.ops.read_i2c_byte(hw,
39318c2ecf20Sopenharmony_ci					ixgbe_emc_temp_data[sensor_index],
39328c2ecf20Sopenharmony_ci					IXGBE_I2C_THERMAL_SENSOR_ADDR,
39338c2ecf20Sopenharmony_ci					&data->sensor[i].temp);
39348c2ecf20Sopenharmony_ci			if (status)
39358c2ecf20Sopenharmony_ci				return status;
39368c2ecf20Sopenharmony_ci		}
39378c2ecf20Sopenharmony_ci	}
39388c2ecf20Sopenharmony_ci
39398c2ecf20Sopenharmony_ci	return 0;
39408c2ecf20Sopenharmony_ci}
39418c2ecf20Sopenharmony_ci
39428c2ecf20Sopenharmony_ci/**
39438c2ecf20Sopenharmony_ci * ixgbe_init_thermal_sensor_thresh_generic - Inits thermal sensor thresholds
39448c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure
39458c2ecf20Sopenharmony_ci *
39468c2ecf20Sopenharmony_ci * Inits the thermal sensor thresholds according to the NVM map
39478c2ecf20Sopenharmony_ci * and save off the threshold and location values into mac.thermal_sensor_data
39488c2ecf20Sopenharmony_ci **/
39498c2ecf20Sopenharmony_cis32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
39508c2ecf20Sopenharmony_ci{
39518c2ecf20Sopenharmony_ci	s32 status;
39528c2ecf20Sopenharmony_ci	u16 ets_offset;
39538c2ecf20Sopenharmony_ci	u16 ets_cfg;
39548c2ecf20Sopenharmony_ci	u16 ets_sensor;
39558c2ecf20Sopenharmony_ci	u8  low_thresh_delta;
39568c2ecf20Sopenharmony_ci	u8  num_sensors;
39578c2ecf20Sopenharmony_ci	u8  therm_limit;
39588c2ecf20Sopenharmony_ci	u8  i;
39598c2ecf20Sopenharmony_ci	struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
39608c2ecf20Sopenharmony_ci
39618c2ecf20Sopenharmony_ci	memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data));
39628c2ecf20Sopenharmony_ci
39638c2ecf20Sopenharmony_ci	/* Only support thermal sensors attached to physical port 0 */
39648c2ecf20Sopenharmony_ci	if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1))
39658c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
39668c2ecf20Sopenharmony_ci
39678c2ecf20Sopenharmony_ci	status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
39688c2ecf20Sopenharmony_ci	if (status)
39698c2ecf20Sopenharmony_ci		return status;
39708c2ecf20Sopenharmony_ci
39718c2ecf20Sopenharmony_ci	low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >>
39728c2ecf20Sopenharmony_ci			     IXGBE_ETS_LTHRES_DELTA_SHIFT);
39738c2ecf20Sopenharmony_ci	num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK);
39748c2ecf20Sopenharmony_ci	if (num_sensors > IXGBE_MAX_SENSORS)
39758c2ecf20Sopenharmony_ci		num_sensors = IXGBE_MAX_SENSORS;
39768c2ecf20Sopenharmony_ci
39778c2ecf20Sopenharmony_ci	for (i = 0; i < num_sensors; i++) {
39788c2ecf20Sopenharmony_ci		u8  sensor_index;
39798c2ecf20Sopenharmony_ci		u8  sensor_location;
39808c2ecf20Sopenharmony_ci
39818c2ecf20Sopenharmony_ci		if (hw->eeprom.ops.read(hw, ets_offset + 1 + i, &ets_sensor)) {
39828c2ecf20Sopenharmony_ci			hw_err(hw, "eeprom read at offset %d failed\n",
39838c2ecf20Sopenharmony_ci			       ets_offset + 1 + i);
39848c2ecf20Sopenharmony_ci			continue;
39858c2ecf20Sopenharmony_ci		}
39868c2ecf20Sopenharmony_ci		sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
39878c2ecf20Sopenharmony_ci				IXGBE_ETS_DATA_INDEX_SHIFT);
39888c2ecf20Sopenharmony_ci		sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >>
39898c2ecf20Sopenharmony_ci				   IXGBE_ETS_DATA_LOC_SHIFT);
39908c2ecf20Sopenharmony_ci		therm_limit = ets_sensor & IXGBE_ETS_DATA_HTHRESH_MASK;
39918c2ecf20Sopenharmony_ci
39928c2ecf20Sopenharmony_ci		hw->phy.ops.write_i2c_byte(hw,
39938c2ecf20Sopenharmony_ci			ixgbe_emc_therm_limit[sensor_index],
39948c2ecf20Sopenharmony_ci			IXGBE_I2C_THERMAL_SENSOR_ADDR, therm_limit);
39958c2ecf20Sopenharmony_ci
39968c2ecf20Sopenharmony_ci		if (sensor_location == 0)
39978c2ecf20Sopenharmony_ci			continue;
39988c2ecf20Sopenharmony_ci
39998c2ecf20Sopenharmony_ci		data->sensor[i].location = sensor_location;
40008c2ecf20Sopenharmony_ci		data->sensor[i].caution_thresh = therm_limit;
40018c2ecf20Sopenharmony_ci		data->sensor[i].max_op_thresh = therm_limit - low_thresh_delta;
40028c2ecf20Sopenharmony_ci	}
40038c2ecf20Sopenharmony_ci
40048c2ecf20Sopenharmony_ci	return 0;
40058c2ecf20Sopenharmony_ci}
40068c2ecf20Sopenharmony_ci
40078c2ecf20Sopenharmony_ci/**
40088c2ecf20Sopenharmony_ci *  ixgbe_get_orom_version - Return option ROM from EEPROM
40098c2ecf20Sopenharmony_ci *
40108c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
40118c2ecf20Sopenharmony_ci *  @nvm_ver: pointer to output structure
40128c2ecf20Sopenharmony_ci *
40138c2ecf20Sopenharmony_ci *  if valid option ROM version, nvm_ver->or_valid set to true
40148c2ecf20Sopenharmony_ci *  else nvm_ver->or_valid is false.
40158c2ecf20Sopenharmony_ci **/
40168c2ecf20Sopenharmony_civoid ixgbe_get_orom_version(struct ixgbe_hw *hw,
40178c2ecf20Sopenharmony_ci			    struct ixgbe_nvm_version *nvm_ver)
40188c2ecf20Sopenharmony_ci{
40198c2ecf20Sopenharmony_ci	u16 offset, eeprom_cfg_blkh, eeprom_cfg_blkl;
40208c2ecf20Sopenharmony_ci
40218c2ecf20Sopenharmony_ci	nvm_ver->or_valid = false;
40228c2ecf20Sopenharmony_ci	/* Option Rom may or may not be present.  Start with pointer */
40238c2ecf20Sopenharmony_ci	hw->eeprom.ops.read(hw, NVM_OROM_OFFSET, &offset);
40248c2ecf20Sopenharmony_ci
40258c2ecf20Sopenharmony_ci	/* make sure offset is valid */
40268c2ecf20Sopenharmony_ci	if (offset == 0x0 || offset == NVM_INVALID_PTR)
40278c2ecf20Sopenharmony_ci		return;
40288c2ecf20Sopenharmony_ci
40298c2ecf20Sopenharmony_ci	hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_HI, &eeprom_cfg_blkh);
40308c2ecf20Sopenharmony_ci	hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_LOW, &eeprom_cfg_blkl);
40318c2ecf20Sopenharmony_ci
40328c2ecf20Sopenharmony_ci	/* option rom exists and is valid */
40338c2ecf20Sopenharmony_ci	if ((eeprom_cfg_blkl | eeprom_cfg_blkh) == 0x0 ||
40348c2ecf20Sopenharmony_ci	    eeprom_cfg_blkl == NVM_VER_INVALID ||
40358c2ecf20Sopenharmony_ci	    eeprom_cfg_blkh == NVM_VER_INVALID)
40368c2ecf20Sopenharmony_ci		return;
40378c2ecf20Sopenharmony_ci
40388c2ecf20Sopenharmony_ci	nvm_ver->or_valid = true;
40398c2ecf20Sopenharmony_ci	nvm_ver->or_major = eeprom_cfg_blkl >> NVM_OROM_SHIFT;
40408c2ecf20Sopenharmony_ci	nvm_ver->or_build = (eeprom_cfg_blkl << NVM_OROM_SHIFT) |
40418c2ecf20Sopenharmony_ci			    (eeprom_cfg_blkh >> NVM_OROM_SHIFT);
40428c2ecf20Sopenharmony_ci	nvm_ver->or_patch = eeprom_cfg_blkh & NVM_OROM_PATCH_MASK;
40438c2ecf20Sopenharmony_ci}
40448c2ecf20Sopenharmony_ci
40458c2ecf20Sopenharmony_ci/**
40468c2ecf20Sopenharmony_ci *  ixgbe_get_oem_prod_version Etrack ID from EEPROM
40478c2ecf20Sopenharmony_ci *
40488c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
40498c2ecf20Sopenharmony_ci *  @nvm_ver: pointer to output structure
40508c2ecf20Sopenharmony_ci *
40518c2ecf20Sopenharmony_ci *  if valid OEM product version, nvm_ver->oem_valid set to true
40528c2ecf20Sopenharmony_ci *  else nvm_ver->oem_valid is false.
40538c2ecf20Sopenharmony_ci **/
40548c2ecf20Sopenharmony_civoid ixgbe_get_oem_prod_version(struct ixgbe_hw *hw,
40558c2ecf20Sopenharmony_ci				struct ixgbe_nvm_version *nvm_ver)
40568c2ecf20Sopenharmony_ci{
40578c2ecf20Sopenharmony_ci	u16 rel_num, prod_ver, mod_len, cap, offset;
40588c2ecf20Sopenharmony_ci
40598c2ecf20Sopenharmony_ci	nvm_ver->oem_valid = false;
40608c2ecf20Sopenharmony_ci	hw->eeprom.ops.read(hw, NVM_OEM_PROD_VER_PTR, &offset);
40618c2ecf20Sopenharmony_ci
40628c2ecf20Sopenharmony_ci	/* Return is offset to OEM Product Version block is invalid */
40638c2ecf20Sopenharmony_ci	if (offset == 0x0 || offset == NVM_INVALID_PTR)
40648c2ecf20Sopenharmony_ci		return;
40658c2ecf20Sopenharmony_ci
40668c2ecf20Sopenharmony_ci	/* Read product version block */
40678c2ecf20Sopenharmony_ci	hw->eeprom.ops.read(hw, offset, &mod_len);
40688c2ecf20Sopenharmony_ci	hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_CAP_OFF, &cap);
40698c2ecf20Sopenharmony_ci
40708c2ecf20Sopenharmony_ci	/* Return if OEM product version block is invalid */
40718c2ecf20Sopenharmony_ci	if (mod_len != NVM_OEM_PROD_VER_MOD_LEN ||
40728c2ecf20Sopenharmony_ci	    (cap & NVM_OEM_PROD_VER_CAP_MASK) != 0x0)
40738c2ecf20Sopenharmony_ci		return;
40748c2ecf20Sopenharmony_ci
40758c2ecf20Sopenharmony_ci	hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_L, &prod_ver);
40768c2ecf20Sopenharmony_ci	hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_H, &rel_num);
40778c2ecf20Sopenharmony_ci
40788c2ecf20Sopenharmony_ci	/* Return if version is invalid */
40798c2ecf20Sopenharmony_ci	if ((rel_num | prod_ver) == 0x0 ||
40808c2ecf20Sopenharmony_ci	    rel_num == NVM_VER_INVALID || prod_ver == NVM_VER_INVALID)
40818c2ecf20Sopenharmony_ci		return;
40828c2ecf20Sopenharmony_ci
40838c2ecf20Sopenharmony_ci	nvm_ver->oem_major = prod_ver >> NVM_VER_SHIFT;
40848c2ecf20Sopenharmony_ci	nvm_ver->oem_minor = prod_ver & NVM_VER_MASK;
40858c2ecf20Sopenharmony_ci	nvm_ver->oem_release = rel_num;
40868c2ecf20Sopenharmony_ci	nvm_ver->oem_valid = true;
40878c2ecf20Sopenharmony_ci}
40888c2ecf20Sopenharmony_ci
40898c2ecf20Sopenharmony_ci/**
40908c2ecf20Sopenharmony_ci *  ixgbe_get_etk_id - Return Etrack ID from EEPROM
40918c2ecf20Sopenharmony_ci *
40928c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
40938c2ecf20Sopenharmony_ci *  @nvm_ver: pointer to output structure
40948c2ecf20Sopenharmony_ci *
40958c2ecf20Sopenharmony_ci *  word read errors will return 0xFFFF
40968c2ecf20Sopenharmony_ci **/
40978c2ecf20Sopenharmony_civoid ixgbe_get_etk_id(struct ixgbe_hw *hw,
40988c2ecf20Sopenharmony_ci		      struct ixgbe_nvm_version *nvm_ver)
40998c2ecf20Sopenharmony_ci{
41008c2ecf20Sopenharmony_ci	u16 etk_id_l, etk_id_h;
41018c2ecf20Sopenharmony_ci
41028c2ecf20Sopenharmony_ci	if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_LOW, &etk_id_l))
41038c2ecf20Sopenharmony_ci		etk_id_l = NVM_VER_INVALID;
41048c2ecf20Sopenharmony_ci	if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_HI, &etk_id_h))
41058c2ecf20Sopenharmony_ci		etk_id_h = NVM_VER_INVALID;
41068c2ecf20Sopenharmony_ci
41078c2ecf20Sopenharmony_ci	/* The word order for the version format is determined by high order
41088c2ecf20Sopenharmony_ci	 * word bit 15.
41098c2ecf20Sopenharmony_ci	 */
41108c2ecf20Sopenharmony_ci	if ((etk_id_h & NVM_ETK_VALID) == 0) {
41118c2ecf20Sopenharmony_ci		nvm_ver->etk_id = etk_id_h;
41128c2ecf20Sopenharmony_ci		nvm_ver->etk_id |= (etk_id_l << NVM_ETK_SHIFT);
41138c2ecf20Sopenharmony_ci	} else {
41148c2ecf20Sopenharmony_ci		nvm_ver->etk_id = etk_id_l;
41158c2ecf20Sopenharmony_ci		nvm_ver->etk_id |= (etk_id_h << NVM_ETK_SHIFT);
41168c2ecf20Sopenharmony_ci	}
41178c2ecf20Sopenharmony_ci}
41188c2ecf20Sopenharmony_ci
41198c2ecf20Sopenharmony_civoid ixgbe_disable_rx_generic(struct ixgbe_hw *hw)
41208c2ecf20Sopenharmony_ci{
41218c2ecf20Sopenharmony_ci	u32 rxctrl;
41228c2ecf20Sopenharmony_ci
41238c2ecf20Sopenharmony_ci	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
41248c2ecf20Sopenharmony_ci	if (rxctrl & IXGBE_RXCTRL_RXEN) {
41258c2ecf20Sopenharmony_ci		if (hw->mac.type != ixgbe_mac_82598EB) {
41268c2ecf20Sopenharmony_ci			u32 pfdtxgswc;
41278c2ecf20Sopenharmony_ci
41288c2ecf20Sopenharmony_ci			pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
41298c2ecf20Sopenharmony_ci			if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
41308c2ecf20Sopenharmony_ci				pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
41318c2ecf20Sopenharmony_ci				IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
41328c2ecf20Sopenharmony_ci				hw->mac.set_lben = true;
41338c2ecf20Sopenharmony_ci			} else {
41348c2ecf20Sopenharmony_ci				hw->mac.set_lben = false;
41358c2ecf20Sopenharmony_ci			}
41368c2ecf20Sopenharmony_ci		}
41378c2ecf20Sopenharmony_ci		rxctrl &= ~IXGBE_RXCTRL_RXEN;
41388c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
41398c2ecf20Sopenharmony_ci	}
41408c2ecf20Sopenharmony_ci}
41418c2ecf20Sopenharmony_ci
41428c2ecf20Sopenharmony_civoid ixgbe_enable_rx_generic(struct ixgbe_hw *hw)
41438c2ecf20Sopenharmony_ci{
41448c2ecf20Sopenharmony_ci	u32 rxctrl;
41458c2ecf20Sopenharmony_ci
41468c2ecf20Sopenharmony_ci	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
41478c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN));
41488c2ecf20Sopenharmony_ci
41498c2ecf20Sopenharmony_ci	if (hw->mac.type != ixgbe_mac_82598EB) {
41508c2ecf20Sopenharmony_ci		if (hw->mac.set_lben) {
41518c2ecf20Sopenharmony_ci			u32 pfdtxgswc;
41528c2ecf20Sopenharmony_ci
41538c2ecf20Sopenharmony_ci			pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
41548c2ecf20Sopenharmony_ci			pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN;
41558c2ecf20Sopenharmony_ci			IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
41568c2ecf20Sopenharmony_ci			hw->mac.set_lben = false;
41578c2ecf20Sopenharmony_ci		}
41588c2ecf20Sopenharmony_ci	}
41598c2ecf20Sopenharmony_ci}
41608c2ecf20Sopenharmony_ci
41618c2ecf20Sopenharmony_ci/** ixgbe_mng_present - returns true when management capability is present
41628c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure
41638c2ecf20Sopenharmony_ci **/
41648c2ecf20Sopenharmony_cibool ixgbe_mng_present(struct ixgbe_hw *hw)
41658c2ecf20Sopenharmony_ci{
41668c2ecf20Sopenharmony_ci	u32 fwsm;
41678c2ecf20Sopenharmony_ci
41688c2ecf20Sopenharmony_ci	if (hw->mac.type < ixgbe_mac_82599EB)
41698c2ecf20Sopenharmony_ci		return false;
41708c2ecf20Sopenharmony_ci
41718c2ecf20Sopenharmony_ci	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
41728c2ecf20Sopenharmony_ci
41738c2ecf20Sopenharmony_ci	return !!(fwsm & IXGBE_FWSM_FW_MODE_PT);
41748c2ecf20Sopenharmony_ci}
41758c2ecf20Sopenharmony_ci
41768c2ecf20Sopenharmony_ci/**
41778c2ecf20Sopenharmony_ci *  ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
41788c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
41798c2ecf20Sopenharmony_ci *  @speed: new link speed
41808c2ecf20Sopenharmony_ci *  @autoneg_wait_to_complete: true when waiting for completion is needed
41818c2ecf20Sopenharmony_ci *
41828c2ecf20Sopenharmony_ci *  Set the link speed in the MAC and/or PHY register and restarts link.
41838c2ecf20Sopenharmony_ci */
41848c2ecf20Sopenharmony_cis32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
41858c2ecf20Sopenharmony_ci					  ixgbe_link_speed speed,
41868c2ecf20Sopenharmony_ci					  bool autoneg_wait_to_complete)
41878c2ecf20Sopenharmony_ci{
41888c2ecf20Sopenharmony_ci	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
41898c2ecf20Sopenharmony_ci	ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
41908c2ecf20Sopenharmony_ci	s32 status = 0;
41918c2ecf20Sopenharmony_ci	u32 speedcnt = 0;
41928c2ecf20Sopenharmony_ci	u32 i = 0;
41938c2ecf20Sopenharmony_ci	bool autoneg, link_up = false;
41948c2ecf20Sopenharmony_ci
41958c2ecf20Sopenharmony_ci	/* Mask off requested but non-supported speeds */
41968c2ecf20Sopenharmony_ci	status = hw->mac.ops.get_link_capabilities(hw, &link_speed, &autoneg);
41978c2ecf20Sopenharmony_ci	if (status)
41988c2ecf20Sopenharmony_ci		return status;
41998c2ecf20Sopenharmony_ci
42008c2ecf20Sopenharmony_ci	speed &= link_speed;
42018c2ecf20Sopenharmony_ci
42028c2ecf20Sopenharmony_ci	/* Try each speed one by one, highest priority first.  We do this in
42038c2ecf20Sopenharmony_ci	 * software because 10Gb fiber doesn't support speed autonegotiation.
42048c2ecf20Sopenharmony_ci	 */
42058c2ecf20Sopenharmony_ci	if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
42068c2ecf20Sopenharmony_ci		speedcnt++;
42078c2ecf20Sopenharmony_ci		highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
42088c2ecf20Sopenharmony_ci
42098c2ecf20Sopenharmony_ci		/* Set the module link speed */
42108c2ecf20Sopenharmony_ci		switch (hw->phy.media_type) {
42118c2ecf20Sopenharmony_ci		case ixgbe_media_type_fiber:
42128c2ecf20Sopenharmony_ci			hw->mac.ops.set_rate_select_speed(hw,
42138c2ecf20Sopenharmony_ci						    IXGBE_LINK_SPEED_10GB_FULL);
42148c2ecf20Sopenharmony_ci			break;
42158c2ecf20Sopenharmony_ci		case ixgbe_media_type_fiber_qsfp:
42168c2ecf20Sopenharmony_ci			/* QSFP module automatically detects MAC link speed */
42178c2ecf20Sopenharmony_ci			break;
42188c2ecf20Sopenharmony_ci		default:
42198c2ecf20Sopenharmony_ci			hw_dbg(hw, "Unexpected media type\n");
42208c2ecf20Sopenharmony_ci			break;
42218c2ecf20Sopenharmony_ci		}
42228c2ecf20Sopenharmony_ci
42238c2ecf20Sopenharmony_ci		/* Allow module to change analog characteristics (1G->10G) */
42248c2ecf20Sopenharmony_ci		msleep(40);
42258c2ecf20Sopenharmony_ci
42268c2ecf20Sopenharmony_ci		status = hw->mac.ops.setup_mac_link(hw,
42278c2ecf20Sopenharmony_ci						    IXGBE_LINK_SPEED_10GB_FULL,
42288c2ecf20Sopenharmony_ci						    autoneg_wait_to_complete);
42298c2ecf20Sopenharmony_ci		if (status)
42308c2ecf20Sopenharmony_ci			return status;
42318c2ecf20Sopenharmony_ci
42328c2ecf20Sopenharmony_ci		/* Flap the Tx laser if it has not already been done */
42338c2ecf20Sopenharmony_ci		if (hw->mac.ops.flap_tx_laser)
42348c2ecf20Sopenharmony_ci			hw->mac.ops.flap_tx_laser(hw);
42358c2ecf20Sopenharmony_ci
42368c2ecf20Sopenharmony_ci		/* Wait for the controller to acquire link.  Per IEEE 802.3ap,
42378c2ecf20Sopenharmony_ci		 * Section 73.10.2, we may have to wait up to 500ms if KR is
42388c2ecf20Sopenharmony_ci		 * attempted.  82599 uses the same timing for 10g SFI.
42398c2ecf20Sopenharmony_ci		 */
42408c2ecf20Sopenharmony_ci		for (i = 0; i < 5; i++) {
42418c2ecf20Sopenharmony_ci			/* Wait for the link partner to also set speed */
42428c2ecf20Sopenharmony_ci			msleep(100);
42438c2ecf20Sopenharmony_ci
42448c2ecf20Sopenharmony_ci			/* If we have link, just jump out */
42458c2ecf20Sopenharmony_ci			status = hw->mac.ops.check_link(hw, &link_speed,
42468c2ecf20Sopenharmony_ci							&link_up, false);
42478c2ecf20Sopenharmony_ci			if (status)
42488c2ecf20Sopenharmony_ci				return status;
42498c2ecf20Sopenharmony_ci
42508c2ecf20Sopenharmony_ci			if (link_up)
42518c2ecf20Sopenharmony_ci				goto out;
42528c2ecf20Sopenharmony_ci		}
42538c2ecf20Sopenharmony_ci	}
42548c2ecf20Sopenharmony_ci
42558c2ecf20Sopenharmony_ci	if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
42568c2ecf20Sopenharmony_ci		speedcnt++;
42578c2ecf20Sopenharmony_ci		if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
42588c2ecf20Sopenharmony_ci			highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
42598c2ecf20Sopenharmony_ci
42608c2ecf20Sopenharmony_ci		/* Set the module link speed */
42618c2ecf20Sopenharmony_ci		switch (hw->phy.media_type) {
42628c2ecf20Sopenharmony_ci		case ixgbe_media_type_fiber:
42638c2ecf20Sopenharmony_ci			hw->mac.ops.set_rate_select_speed(hw,
42648c2ecf20Sopenharmony_ci						     IXGBE_LINK_SPEED_1GB_FULL);
42658c2ecf20Sopenharmony_ci			break;
42668c2ecf20Sopenharmony_ci		case ixgbe_media_type_fiber_qsfp:
42678c2ecf20Sopenharmony_ci			/* QSFP module automatically detects link speed */
42688c2ecf20Sopenharmony_ci			break;
42698c2ecf20Sopenharmony_ci		default:
42708c2ecf20Sopenharmony_ci			hw_dbg(hw, "Unexpected media type\n");
42718c2ecf20Sopenharmony_ci			break;
42728c2ecf20Sopenharmony_ci		}
42738c2ecf20Sopenharmony_ci
42748c2ecf20Sopenharmony_ci		/* Allow module to change analog characteristics (10G->1G) */
42758c2ecf20Sopenharmony_ci		msleep(40);
42768c2ecf20Sopenharmony_ci
42778c2ecf20Sopenharmony_ci		status = hw->mac.ops.setup_mac_link(hw,
42788c2ecf20Sopenharmony_ci						    IXGBE_LINK_SPEED_1GB_FULL,
42798c2ecf20Sopenharmony_ci						    autoneg_wait_to_complete);
42808c2ecf20Sopenharmony_ci		if (status)
42818c2ecf20Sopenharmony_ci			return status;
42828c2ecf20Sopenharmony_ci
42838c2ecf20Sopenharmony_ci		/* Flap the Tx laser if it has not already been done */
42848c2ecf20Sopenharmony_ci		if (hw->mac.ops.flap_tx_laser)
42858c2ecf20Sopenharmony_ci			hw->mac.ops.flap_tx_laser(hw);
42868c2ecf20Sopenharmony_ci
42878c2ecf20Sopenharmony_ci		/* Wait for the link partner to also set speed */
42888c2ecf20Sopenharmony_ci		msleep(100);
42898c2ecf20Sopenharmony_ci
42908c2ecf20Sopenharmony_ci		/* If we have link, just jump out */
42918c2ecf20Sopenharmony_ci		status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
42928c2ecf20Sopenharmony_ci						false);
42938c2ecf20Sopenharmony_ci		if (status)
42948c2ecf20Sopenharmony_ci			return status;
42958c2ecf20Sopenharmony_ci
42968c2ecf20Sopenharmony_ci		if (link_up)
42978c2ecf20Sopenharmony_ci			goto out;
42988c2ecf20Sopenharmony_ci	}
42998c2ecf20Sopenharmony_ci
43008c2ecf20Sopenharmony_ci	/* We didn't get link.  Configure back to the highest speed we tried,
43018c2ecf20Sopenharmony_ci	 * (if there was more than one).  We call ourselves back with just the
43028c2ecf20Sopenharmony_ci	 * single highest speed that the user requested.
43038c2ecf20Sopenharmony_ci	 */
43048c2ecf20Sopenharmony_ci	if (speedcnt > 1)
43058c2ecf20Sopenharmony_ci		status = ixgbe_setup_mac_link_multispeed_fiber(hw,
43068c2ecf20Sopenharmony_ci						      highest_link_speed,
43078c2ecf20Sopenharmony_ci						      autoneg_wait_to_complete);
43088c2ecf20Sopenharmony_ci
43098c2ecf20Sopenharmony_ciout:
43108c2ecf20Sopenharmony_ci	/* Set autoneg_advertised value based on input link speed */
43118c2ecf20Sopenharmony_ci	hw->phy.autoneg_advertised = 0;
43128c2ecf20Sopenharmony_ci
43138c2ecf20Sopenharmony_ci	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
43148c2ecf20Sopenharmony_ci		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
43158c2ecf20Sopenharmony_ci
43168c2ecf20Sopenharmony_ci	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
43178c2ecf20Sopenharmony_ci		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
43188c2ecf20Sopenharmony_ci
43198c2ecf20Sopenharmony_ci	return status;
43208c2ecf20Sopenharmony_ci}
43218c2ecf20Sopenharmony_ci
43228c2ecf20Sopenharmony_ci/**
43238c2ecf20Sopenharmony_ci *  ixgbe_set_soft_rate_select_speed - Set module link speed
43248c2ecf20Sopenharmony_ci *  @hw: pointer to hardware structure
43258c2ecf20Sopenharmony_ci *  @speed: link speed to set
43268c2ecf20Sopenharmony_ci *
43278c2ecf20Sopenharmony_ci *  Set module link speed via the soft rate select.
43288c2ecf20Sopenharmony_ci */
43298c2ecf20Sopenharmony_civoid ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw,
43308c2ecf20Sopenharmony_ci				      ixgbe_link_speed speed)
43318c2ecf20Sopenharmony_ci{
43328c2ecf20Sopenharmony_ci	s32 status;
43338c2ecf20Sopenharmony_ci	u8 rs, eeprom_data;
43348c2ecf20Sopenharmony_ci
43358c2ecf20Sopenharmony_ci	switch (speed) {
43368c2ecf20Sopenharmony_ci	case IXGBE_LINK_SPEED_10GB_FULL:
43378c2ecf20Sopenharmony_ci		/* one bit mask same as setting on */
43388c2ecf20Sopenharmony_ci		rs = IXGBE_SFF_SOFT_RS_SELECT_10G;
43398c2ecf20Sopenharmony_ci		break;
43408c2ecf20Sopenharmony_ci	case IXGBE_LINK_SPEED_1GB_FULL:
43418c2ecf20Sopenharmony_ci		rs = IXGBE_SFF_SOFT_RS_SELECT_1G;
43428c2ecf20Sopenharmony_ci		break;
43438c2ecf20Sopenharmony_ci	default:
43448c2ecf20Sopenharmony_ci		hw_dbg(hw, "Invalid fixed module speed\n");
43458c2ecf20Sopenharmony_ci		return;
43468c2ecf20Sopenharmony_ci	}
43478c2ecf20Sopenharmony_ci
43488c2ecf20Sopenharmony_ci	/* Set RS0 */
43498c2ecf20Sopenharmony_ci	status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
43508c2ecf20Sopenharmony_ci					   IXGBE_I2C_EEPROM_DEV_ADDR2,
43518c2ecf20Sopenharmony_ci					   &eeprom_data);
43528c2ecf20Sopenharmony_ci	if (status) {
43538c2ecf20Sopenharmony_ci		hw_dbg(hw, "Failed to read Rx Rate Select RS0\n");
43548c2ecf20Sopenharmony_ci		return;
43558c2ecf20Sopenharmony_ci	}
43568c2ecf20Sopenharmony_ci
43578c2ecf20Sopenharmony_ci	eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs;
43588c2ecf20Sopenharmony_ci
43598c2ecf20Sopenharmony_ci	status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
43608c2ecf20Sopenharmony_ci					    IXGBE_I2C_EEPROM_DEV_ADDR2,
43618c2ecf20Sopenharmony_ci					    eeprom_data);
43628c2ecf20Sopenharmony_ci	if (status) {
43638c2ecf20Sopenharmony_ci		hw_dbg(hw, "Failed to write Rx Rate Select RS0\n");
43648c2ecf20Sopenharmony_ci		return;
43658c2ecf20Sopenharmony_ci	}
43668c2ecf20Sopenharmony_ci
43678c2ecf20Sopenharmony_ci	/* Set RS1 */
43688c2ecf20Sopenharmony_ci	status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
43698c2ecf20Sopenharmony_ci					   IXGBE_I2C_EEPROM_DEV_ADDR2,
43708c2ecf20Sopenharmony_ci					   &eeprom_data);
43718c2ecf20Sopenharmony_ci	if (status) {
43728c2ecf20Sopenharmony_ci		hw_dbg(hw, "Failed to read Rx Rate Select RS1\n");
43738c2ecf20Sopenharmony_ci		return;
43748c2ecf20Sopenharmony_ci	}
43758c2ecf20Sopenharmony_ci
43768c2ecf20Sopenharmony_ci	eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs;
43778c2ecf20Sopenharmony_ci
43788c2ecf20Sopenharmony_ci	status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
43798c2ecf20Sopenharmony_ci					    IXGBE_I2C_EEPROM_DEV_ADDR2,
43808c2ecf20Sopenharmony_ci					    eeprom_data);
43818c2ecf20Sopenharmony_ci	if (status) {
43828c2ecf20Sopenharmony_ci		hw_dbg(hw, "Failed to write Rx Rate Select RS1\n");
43838c2ecf20Sopenharmony_ci		return;
43848c2ecf20Sopenharmony_ci	}
43858c2ecf20Sopenharmony_ci}
4386