169b5a878SDan McDonald /******************************************************************************
2*48ed61a7SRobert Mustacchi   SPDX-License-Identifier: BSD-3-Clause
369b5a878SDan McDonald 
4*48ed61a7SRobert Mustacchi   Copyright (c) 2001-2017, Intel Corporation
569b5a878SDan McDonald   All rights reserved.
6*48ed61a7SRobert Mustacchi 
7*48ed61a7SRobert Mustacchi   Redistribution and use in source and binary forms, with or without
869b5a878SDan McDonald   modification, are permitted provided that the following conditions are met:
9*48ed61a7SRobert Mustacchi 
10*48ed61a7SRobert Mustacchi    1. Redistributions of source code must retain the above copyright notice,
1169b5a878SDan McDonald       this list of conditions and the following disclaimer.
12*48ed61a7SRobert Mustacchi 
13*48ed61a7SRobert Mustacchi    2. Redistributions in binary form must reproduce the above copyright
14*48ed61a7SRobert Mustacchi       notice, this list of conditions and the following disclaimer in the
1569b5a878SDan McDonald       documentation and/or other materials provided with the distribution.
16*48ed61a7SRobert Mustacchi 
17*48ed61a7SRobert Mustacchi    3. Neither the name of the Intel Corporation nor the names of its
18*48ed61a7SRobert Mustacchi       contributors may be used to endorse or promote products derived from
1969b5a878SDan McDonald       this software without specific prior written permission.
20*48ed61a7SRobert Mustacchi 
2169b5a878SDan McDonald   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22*48ed61a7SRobert Mustacchi   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*48ed61a7SRobert Mustacchi   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*48ed61a7SRobert Mustacchi   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25*48ed61a7SRobert Mustacchi   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26*48ed61a7SRobert Mustacchi   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27*48ed61a7SRobert Mustacchi   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*48ed61a7SRobert Mustacchi   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29*48ed61a7SRobert Mustacchi   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3069b5a878SDan McDonald   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3169b5a878SDan McDonald   POSSIBILITY OF SUCH DAMAGE.
3269b5a878SDan McDonald 
3369b5a878SDan McDonald ******************************************************************************/
34dc0cb1cdSDale Ghent /*$FreeBSD$*/
3569b5a878SDan McDonald 
3669b5a878SDan McDonald #include "ixgbe_x540.h"
3769b5a878SDan McDonald #include "ixgbe_type.h"
3869b5a878SDan McDonald #include "ixgbe_api.h"
3969b5a878SDan McDonald #include "ixgbe_common.h"
4069b5a878SDan McDonald #include "ixgbe_phy.h"
4169b5a878SDan McDonald 
42dc0cb1cdSDale Ghent #define IXGBE_X540_MAX_TX_QUEUES	128
43dc0cb1cdSDale Ghent #define IXGBE_X540_MAX_RX_QUEUES	128
44dc0cb1cdSDale Ghent #define IXGBE_X540_RAR_ENTRIES		128
45dc0cb1cdSDale Ghent #define IXGBE_X540_MC_TBL_SIZE		128
46dc0cb1cdSDale Ghent #define IXGBE_X540_VFT_TBL_SIZE		128
47dc0cb1cdSDale Ghent #define IXGBE_X540_RX_PB_SIZE		384
48dc0cb1cdSDale Ghent 
4969b5a878SDan McDonald static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw);
5069b5a878SDan McDonald static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw);
5169b5a878SDan McDonald static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw);
5269b5a878SDan McDonald 
5369b5a878SDan McDonald /**
5469b5a878SDan McDonald  *  ixgbe_init_ops_X540 - Inits func ptrs and MAC type
5569b5a878SDan McDonald  *  @hw: pointer to hardware structure
5669b5a878SDan McDonald  *
5769b5a878SDan McDonald  *  Initialize the function pointers and assign the MAC type for X540.
5869b5a878SDan McDonald  *  Does not touch the hardware.
5969b5a878SDan McDonald  **/
ixgbe_init_ops_X540(struct ixgbe_hw * hw)6069b5a878SDan McDonald s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw)
6169b5a878SDan McDonald {
6269b5a878SDan McDonald 	struct ixgbe_mac_info *mac = &hw->mac;
6369b5a878SDan McDonald 	struct ixgbe_phy_info *phy = &hw->phy;
6469b5a878SDan McDonald 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
6569b5a878SDan McDonald 	s32 ret_val;
6669b5a878SDan McDonald 
6769b5a878SDan McDonald 	DEBUGFUNC("ixgbe_init_ops_X540");
6869b5a878SDan McDonald 
6969b5a878SDan McDonald 	ret_val = ixgbe_init_phy_ops_generic(hw);
7069b5a878SDan McDonald 	ret_val = ixgbe_init_ops_generic(hw);
7169b5a878SDan McDonald 
7269b5a878SDan McDonald 
7369b5a878SDan McDonald 	/* EEPROM */
74dc0cb1cdSDale Ghent 	eeprom->ops.init_params = ixgbe_init_eeprom_params_X540;
75dc0cb1cdSDale Ghent 	eeprom->ops.read = ixgbe_read_eerd_X540;
76dc0cb1cdSDale Ghent 	eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_X540;
77dc0cb1cdSDale Ghent 	eeprom->ops.write = ixgbe_write_eewr_X540;
78dc0cb1cdSDale Ghent 	eeprom->ops.write_buffer = ixgbe_write_eewr_buffer_X540;
79dc0cb1cdSDale Ghent 	eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X540;
80dc0cb1cdSDale Ghent 	eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X540;
81dc0cb1cdSDale Ghent 	eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X540;
8269b5a878SDan McDonald 
8369b5a878SDan McDonald 	/* PHY */
84dc0cb1cdSDale Ghent 	phy->ops.init = ixgbe_init_phy_ops_generic;
8569b5a878SDan McDonald 	phy->ops.reset = NULL;
86dc0cb1cdSDale Ghent 	phy->ops.set_phy_power = ixgbe_set_copper_phy_power;
8769b5a878SDan McDonald 
8869b5a878SDan McDonald 	/* MAC */
89dc0cb1cdSDale Ghent 	mac->ops.reset_hw = ixgbe_reset_hw_X540;
90dc0cb1cdSDale Ghent 	mac->ops.enable_relaxed_ordering = ixgbe_enable_relaxed_ordering_gen2;
91dc0cb1cdSDale Ghent 	mac->ops.get_media_type = ixgbe_get_media_type_X540;
9269b5a878SDan McDonald 	mac->ops.get_supported_physical_layer =
93dc0cb1cdSDale Ghent 				    ixgbe_get_supported_physical_layer_X540;
9469b5a878SDan McDonald 	mac->ops.read_analog_reg8 = NULL;
9569b5a878SDan McDonald 	mac->ops.write_analog_reg8 = NULL;
96dc0cb1cdSDale Ghent 	mac->ops.start_hw = ixgbe_start_hw_X540;
97dc0cb1cdSDale Ghent 	mac->ops.get_san_mac_addr = ixgbe_get_san_mac_addr_generic;
98dc0cb1cdSDale Ghent 	mac->ops.set_san_mac_addr = ixgbe_set_san_mac_addr_generic;
99dc0cb1cdSDale Ghent 	mac->ops.get_device_caps = ixgbe_get_device_caps_generic;
100dc0cb1cdSDale Ghent 	mac->ops.get_wwn_prefix = ixgbe_get_wwn_prefix_generic;
101dc0cb1cdSDale Ghent 	mac->ops.get_fcoe_boot_status = ixgbe_get_fcoe_boot_status_generic;
102dc0cb1cdSDale Ghent 	mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X540;
103dc0cb1cdSDale Ghent 	mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X540;
104*48ed61a7SRobert Mustacchi 	mac->ops.init_swfw_sync = ixgbe_init_swfw_sync_X540;
105dc0cb1cdSDale Ghent 	mac->ops.disable_sec_rx_path = ixgbe_disable_sec_rx_path_generic;
106dc0cb1cdSDale Ghent 	mac->ops.enable_sec_rx_path = ixgbe_enable_sec_rx_path_generic;
10769b5a878SDan McDonald 
10869b5a878SDan McDonald 	/* RAR, Multicast, VLAN */
109dc0cb1cdSDale Ghent 	mac->ops.set_vmdq = ixgbe_set_vmdq_generic;
110dc0cb1cdSDale Ghent 	mac->ops.set_vmdq_san_mac = ixgbe_set_vmdq_san_mac_generic;
111dc0cb1cdSDale Ghent 	mac->ops.clear_vmdq = ixgbe_clear_vmdq_generic;
112dc0cb1cdSDale Ghent 	mac->ops.insert_mac_addr = ixgbe_insert_mac_addr_generic;
11369b5a878SDan McDonald 	mac->rar_highwater = 1;
114dc0cb1cdSDale Ghent 	mac->ops.set_vfta = ixgbe_set_vfta_generic;
115dc0cb1cdSDale Ghent 	mac->ops.set_vlvf = ixgbe_set_vlvf_generic;
116dc0cb1cdSDale Ghent 	mac->ops.clear_vfta = ixgbe_clear_vfta_generic;
117dc0cb1cdSDale Ghent 	mac->ops.init_uta_tables = ixgbe_init_uta_tables_generic;
118dc0cb1cdSDale Ghent 	mac->ops.set_mac_anti_spoofing = ixgbe_set_mac_anti_spoofing;
119dc0cb1cdSDale Ghent 	mac->ops.set_vlan_anti_spoofing = ixgbe_set_vlan_anti_spoofing;
12069b5a878SDan McDonald 
12169b5a878SDan McDonald 	/* Link */
12269b5a878SDan McDonald 	mac->ops.get_link_capabilities =
123dc0cb1cdSDale Ghent 				ixgbe_get_copper_link_capabilities_generic;
124dc0cb1cdSDale Ghent 	mac->ops.setup_link = ixgbe_setup_mac_link_X540;
125dc0cb1cdSDale Ghent 	mac->ops.setup_rxpba = ixgbe_set_rxpba_generic;
126dc0cb1cdSDale Ghent 	mac->ops.check_link = ixgbe_check_mac_link_generic;
127*48ed61a7SRobert Mustacchi 	mac->ops.bypass_rw = ixgbe_bypass_rw_generic;
128*48ed61a7SRobert Mustacchi 	mac->ops.bypass_valid_rd = ixgbe_bypass_valid_rd_generic;
129*48ed61a7SRobert Mustacchi 	mac->ops.bypass_set = ixgbe_bypass_set_generic;
130*48ed61a7SRobert Mustacchi 	mac->ops.bypass_rd_eep = ixgbe_bypass_rd_eep_generic;
131dc0cb1cdSDale Ghent 
132dc0cb1cdSDale Ghent 
133dc0cb1cdSDale Ghent 	mac->mcft_size		= IXGBE_X540_MC_TBL_SIZE;
134dc0cb1cdSDale Ghent 	mac->vft_size		= IXGBE_X540_VFT_TBL_SIZE;
135dc0cb1cdSDale Ghent 	mac->num_rar_entries	= IXGBE_X540_RAR_ENTRIES;
136dc0cb1cdSDale Ghent 	mac->rx_pb_size		= IXGBE_X540_RX_PB_SIZE;
137dc0cb1cdSDale Ghent 	mac->max_rx_queues	= IXGBE_X540_MAX_RX_QUEUES;
138dc0cb1cdSDale Ghent 	mac->max_tx_queues	= IXGBE_X540_MAX_TX_QUEUES;
13969b5a878SDan McDonald 	mac->max_msix_vectors	= ixgbe_get_pcie_msix_count_generic(hw);
14069b5a878SDan McDonald 
14169b5a878SDan McDonald 	/*
14269b5a878SDan McDonald 	 * FWSM register
14369b5a878SDan McDonald 	 * ARC supported; valid only if manageability features are
14469b5a878SDan McDonald 	 * enabled.
14569b5a878SDan McDonald 	 */
146dc0cb1cdSDale Ghent 	mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
147dc0cb1cdSDale Ghent 				     & IXGBE_FWSM_MODE_MASK);
14869b5a878SDan McDonald 
14969b5a878SDan McDonald 	hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
15069b5a878SDan McDonald 
15169b5a878SDan McDonald 	/* LEDs */
15269b5a878SDan McDonald 	mac->ops.blink_led_start = ixgbe_blink_led_start_X540;
15369b5a878SDan McDonald 	mac->ops.blink_led_stop = ixgbe_blink_led_stop_X540;
15469b5a878SDan McDonald 
15569b5a878SDan McDonald 	/* Manageability interface */
156dc0cb1cdSDale Ghent 	mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_generic;
157dc0cb1cdSDale Ghent 
158dc0cb1cdSDale Ghent 	mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
15969b5a878SDan McDonald 
16069b5a878SDan McDonald 	return ret_val;
16169b5a878SDan McDonald }
16269b5a878SDan McDonald 
16369b5a878SDan McDonald /**
16469b5a878SDan McDonald  *  ixgbe_get_link_capabilities_X540 - Determines link capabilities
16569b5a878SDan McDonald  *  @hw: pointer to hardware structure
16669b5a878SDan McDonald  *  @speed: pointer to link speed
16769b5a878SDan McDonald  *  @autoneg: TRUE when autoneg or autotry is enabled
16869b5a878SDan McDonald  *
16969b5a878SDan McDonald  *  Determines the link capabilities by reading the AUTOC register.
17069b5a878SDan McDonald  **/
ixgbe_get_link_capabilities_X540(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * autoneg)17169b5a878SDan McDonald s32 ixgbe_get_link_capabilities_X540(struct ixgbe_hw *hw,
17269b5a878SDan McDonald 				     ixgbe_link_speed *speed,
17369b5a878SDan McDonald 				     bool *autoneg)
17469b5a878SDan McDonald {
175dc0cb1cdSDale Ghent 	ixgbe_get_copper_link_capabilities_generic(hw, speed, autoneg);
176dc0cb1cdSDale Ghent 
177dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
17869b5a878SDan McDonald }
17969b5a878SDan McDonald 
18069b5a878SDan McDonald /**
18169b5a878SDan McDonald  *  ixgbe_get_media_type_X540 - Get media type
18269b5a878SDan McDonald  *  @hw: pointer to hardware structure
18369b5a878SDan McDonald  *
18469b5a878SDan McDonald  *  Returns the media type (fiber, copper, backplane)
18569b5a878SDan McDonald  **/
ixgbe_get_media_type_X540(struct ixgbe_hw * hw)18669b5a878SDan McDonald enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw)
18769b5a878SDan McDonald {
18869b5a878SDan McDonald 	UNREFERENCED_1PARAMETER(hw);
18969b5a878SDan McDonald 	return ixgbe_media_type_copper;
19069b5a878SDan McDonald }
19169b5a878SDan McDonald 
19269b5a878SDan McDonald /**
19369b5a878SDan McDonald  *  ixgbe_setup_mac_link_X540 - Sets the auto advertised capabilities
19469b5a878SDan McDonald  *  @hw: pointer to hardware structure
19569b5a878SDan McDonald  *  @speed: new link speed
19669b5a878SDan McDonald  *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
19769b5a878SDan McDonald  **/
ixgbe_setup_mac_link_X540(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)19869b5a878SDan McDonald s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw,
199dc0cb1cdSDale Ghent 			      ixgbe_link_speed speed,
20069b5a878SDan McDonald 			      bool autoneg_wait_to_complete)
20169b5a878SDan McDonald {
20269b5a878SDan McDonald 	DEBUGFUNC("ixgbe_setup_mac_link_X540");
203dc0cb1cdSDale Ghent 	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete);
20469b5a878SDan McDonald }
20569b5a878SDan McDonald 
20669b5a878SDan McDonald /**
20769b5a878SDan McDonald  *  ixgbe_reset_hw_X540 - Perform hardware reset
20869b5a878SDan McDonald  *  @hw: pointer to hardware structure
20969b5a878SDan McDonald  *
21069b5a878SDan McDonald  *  Resets the hardware by resetting the transmit and receive units, masks
21169b5a878SDan McDonald  *  and clears all interrupts, and perform a reset.
21269b5a878SDan McDonald  **/
ixgbe_reset_hw_X540(struct ixgbe_hw * hw)21369b5a878SDan McDonald s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
21469b5a878SDan McDonald {
21569b5a878SDan McDonald 	s32 status;
21669b5a878SDan McDonald 	u32 ctrl, i;
217*48ed61a7SRobert Mustacchi 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
21869b5a878SDan McDonald 
21969b5a878SDan McDonald 	DEBUGFUNC("ixgbe_reset_hw_X540");
22069b5a878SDan McDonald 
22169b5a878SDan McDonald 	/* Call adapter stop to disable tx/rx and clear interrupts */
22269b5a878SDan McDonald 	status = hw->mac.ops.stop_adapter(hw);
22369b5a878SDan McDonald 	if (status != IXGBE_SUCCESS)
22469b5a878SDan McDonald 		goto reset_hw_out;
22569b5a878SDan McDonald 
22669b5a878SDan McDonald 	/* flush pending Tx transactions */
22769b5a878SDan McDonald 	ixgbe_clear_tx_pending(hw);
22869b5a878SDan McDonald 
22969b5a878SDan McDonald mac_reset_top:
230*48ed61a7SRobert Mustacchi 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
231*48ed61a7SRobert Mustacchi 	if (status != IXGBE_SUCCESS) {
232*48ed61a7SRobert Mustacchi 		ERROR_REPORT2(IXGBE_ERROR_CAUTION,
233*48ed61a7SRobert Mustacchi 			"semaphore failed with %d", status);
234*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_SWFW_SYNC;
235*48ed61a7SRobert Mustacchi 	}
23669b5a878SDan McDonald 	ctrl = IXGBE_CTRL_RST;
23769b5a878SDan McDonald 	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
23869b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
23969b5a878SDan McDonald 	IXGBE_WRITE_FLUSH(hw);
240*48ed61a7SRobert Mustacchi 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
24169b5a878SDan McDonald 
24269b5a878SDan McDonald 	/* Poll for reset bit to self-clear indicating reset is complete */
24369b5a878SDan McDonald 	for (i = 0; i < 10; i++) {
24469b5a878SDan McDonald 		usec_delay(1);
24569b5a878SDan McDonald 		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
24669b5a878SDan McDonald 		if (!(ctrl & IXGBE_CTRL_RST_MASK))
24769b5a878SDan McDonald 			break;
24869b5a878SDan McDonald 	}
24969b5a878SDan McDonald 
25069b5a878SDan McDonald 	if (ctrl & IXGBE_CTRL_RST_MASK) {
25169b5a878SDan McDonald 		status = IXGBE_ERR_RESET_FAILED;
252dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_POLLING,
253dc0cb1cdSDale Ghent 			     "Reset polling failed to complete.\n");
25469b5a878SDan McDonald 	}
25569b5a878SDan McDonald 	msec_delay(100);
25669b5a878SDan McDonald 
25769b5a878SDan McDonald 	/*
25869b5a878SDan McDonald 	 * Double resets are required for recovery from certain error
25969b5a878SDan McDonald 	 * conditions.  Between resets, it is necessary to stall to allow time
26069b5a878SDan McDonald 	 * for any pending HW events to complete.
26169b5a878SDan McDonald 	 */
26269b5a878SDan McDonald 	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
26369b5a878SDan McDonald 		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
26469b5a878SDan McDonald 		goto mac_reset_top;
26569b5a878SDan McDonald 	}
26669b5a878SDan McDonald 
26769b5a878SDan McDonald 	/* Set the Rx packet buffer size. */
26869b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT);
26969b5a878SDan McDonald 
27069b5a878SDan McDonald 	/* Store the permanent mac address */
27169b5a878SDan McDonald 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
27269b5a878SDan McDonald 
27369b5a878SDan McDonald 	/*
27469b5a878SDan McDonald 	 * Store MAC address from RAR0, clear receive address registers, and
27569b5a878SDan McDonald 	 * clear the multicast table.  Also reset num_rar_entries to 128,
27669b5a878SDan McDonald 	 * since we modify this value when programming the SAN MAC address.
27769b5a878SDan McDonald 	 */
27869b5a878SDan McDonald 	hw->mac.num_rar_entries = 128;
27969b5a878SDan McDonald 	hw->mac.ops.init_rx_addrs(hw);
28069b5a878SDan McDonald 
28169b5a878SDan McDonald 	/* Store the permanent SAN mac address */
28269b5a878SDan McDonald 	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
28369b5a878SDan McDonald 
28469b5a878SDan McDonald 	/* Add the SAN MAC address to the RAR only if it's a valid address */
28569b5a878SDan McDonald 	if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
28669b5a878SDan McDonald 		/* Save the SAN MAC RAR index */
28769b5a878SDan McDonald 		hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
28869b5a878SDan McDonald 
289*48ed61a7SRobert Mustacchi 		hw->mac.ops.set_rar(hw, hw->mac.san_mac_rar_index,
290*48ed61a7SRobert Mustacchi 				    hw->mac.san_addr, 0, IXGBE_RAH_AV);
291*48ed61a7SRobert Mustacchi 
292*48ed61a7SRobert Mustacchi 		/* clear VMDq pool/queue selection for this RAR */
293*48ed61a7SRobert Mustacchi 		hw->mac.ops.clear_vmdq(hw, hw->mac.san_mac_rar_index,
294*48ed61a7SRobert Mustacchi 				       IXGBE_CLEAR_VMDQ_ALL);
295*48ed61a7SRobert Mustacchi 
29669b5a878SDan McDonald 		/* Reserve the last RAR for the SAN MAC address */
29769b5a878SDan McDonald 		hw->mac.num_rar_entries--;
29869b5a878SDan McDonald 	}
29969b5a878SDan McDonald 
30069b5a878SDan McDonald 	/* Store the alternative WWNN/WWPN prefix */
30169b5a878SDan McDonald 	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
30269b5a878SDan McDonald 				   &hw->mac.wwpn_prefix);
30369b5a878SDan McDonald 
30469b5a878SDan McDonald reset_hw_out:
30569b5a878SDan McDonald 	return status;
30669b5a878SDan McDonald }
30769b5a878SDan McDonald 
30869b5a878SDan McDonald /**
30969b5a878SDan McDonald  *  ixgbe_start_hw_X540 - Prepare hardware for Tx/Rx
31069b5a878SDan McDonald  *  @hw: pointer to hardware structure
31169b5a878SDan McDonald  *
31269b5a878SDan McDonald  *  Starts the hardware using the generic start_hw function
31369b5a878SDan McDonald  *  and the generation start_hw function.
31469b5a878SDan McDonald  *  Then performs revision-specific operations, if any.
31569b5a878SDan McDonald  **/
ixgbe_start_hw_X540(struct ixgbe_hw * hw)31669b5a878SDan McDonald s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw)
31769b5a878SDan McDonald {
31869b5a878SDan McDonald 	s32 ret_val = IXGBE_SUCCESS;
31969b5a878SDan McDonald 
32069b5a878SDan McDonald 	DEBUGFUNC("ixgbe_start_hw_X540");
32169b5a878SDan McDonald 
32269b5a878SDan McDonald 	ret_val = ixgbe_start_hw_generic(hw);
32369b5a878SDan McDonald 	if (ret_val != IXGBE_SUCCESS)
32469b5a878SDan McDonald 		goto out;
32569b5a878SDan McDonald 
32669b5a878SDan McDonald 	ret_val = ixgbe_start_hw_gen2(hw);
32769b5a878SDan McDonald 
32869b5a878SDan McDonald out:
32969b5a878SDan McDonald 	return ret_val;
33069b5a878SDan McDonald }
33169b5a878SDan McDonald 
33269b5a878SDan McDonald /**
33369b5a878SDan McDonald  *  ixgbe_get_supported_physical_layer_X540 - Returns physical layer type
33469b5a878SDan McDonald  *  @hw: pointer to hardware structure
33569b5a878SDan McDonald  *
33669b5a878SDan McDonald  *  Determines physical layer capabilities of the current configuration.
33769b5a878SDan McDonald  **/
ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw * hw)338*48ed61a7SRobert Mustacchi u64 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
33969b5a878SDan McDonald {
340*48ed61a7SRobert Mustacchi 	u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
34169b5a878SDan McDonald 	u16 ext_ability = 0;
34269b5a878SDan McDonald 
34369b5a878SDan McDonald 	DEBUGFUNC("ixgbe_get_supported_physical_layer_X540");
34469b5a878SDan McDonald 
34569b5a878SDan McDonald 	hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
34669b5a878SDan McDonald 	IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
34769b5a878SDan McDonald 	if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
34869b5a878SDan McDonald 		physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
34969b5a878SDan McDonald 	if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
35069b5a878SDan McDonald 		physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
35169b5a878SDan McDonald 	if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
35269b5a878SDan McDonald 		physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
35369b5a878SDan McDonald 
35469b5a878SDan McDonald 	return physical_layer;
35569b5a878SDan McDonald }
35669b5a878SDan McDonald 
35769b5a878SDan McDonald /**
35869b5a878SDan McDonald  *  ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
35969b5a878SDan McDonald  *  @hw: pointer to hardware structure
36069b5a878SDan McDonald  *
36169b5a878SDan McDonald  *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
36269b5a878SDan McDonald  *  ixgbe_hw struct in order to set up EEPROM access.
36369b5a878SDan McDonald  **/
ixgbe_init_eeprom_params_X540(struct ixgbe_hw * hw)36469b5a878SDan McDonald s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
36569b5a878SDan McDonald {
36669b5a878SDan McDonald 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
36769b5a878SDan McDonald 	u32 eec;
36869b5a878SDan McDonald 	u16 eeprom_size;
36969b5a878SDan McDonald 
37069b5a878SDan McDonald 	DEBUGFUNC("ixgbe_init_eeprom_params_X540");
37169b5a878SDan McDonald 
37269b5a878SDan McDonald 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
37369b5a878SDan McDonald 		eeprom->semaphore_delay = 10;
37469b5a878SDan McDonald 		eeprom->type = ixgbe_flash;
37569b5a878SDan McDonald 
376dc0cb1cdSDale Ghent 		eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
37769b5a878SDan McDonald 		eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
37869b5a878SDan McDonald 				    IXGBE_EEC_SIZE_SHIFT);
37969b5a878SDan McDonald 		eeprom->word_size = 1 << (eeprom_size +
38069b5a878SDan McDonald 					  IXGBE_EEPROM_WORD_SIZE_SHIFT);
38169b5a878SDan McDonald 
38269b5a878SDan McDonald 		DEBUGOUT2("Eeprom params: type = %d, size = %d\n",
38369b5a878SDan McDonald 			  eeprom->type, eeprom->word_size);
38469b5a878SDan McDonald 	}
38569b5a878SDan McDonald 
38669b5a878SDan McDonald 	return IXGBE_SUCCESS;
38769b5a878SDan McDonald }
38869b5a878SDan McDonald 
38969b5a878SDan McDonald /**
39069b5a878SDan McDonald  *  ixgbe_read_eerd_X540- Read EEPROM word using EERD
39169b5a878SDan McDonald  *  @hw: pointer to hardware structure
39269b5a878SDan McDonald  *  @offset: offset of  word in the EEPROM to read
39369b5a878SDan McDonald  *  @data: word read from the EEPROM
39469b5a878SDan McDonald  *
39569b5a878SDan McDonald  *  Reads a 16 bit word from the EEPROM using the EERD register.
39669b5a878SDan McDonald  **/
ixgbe_read_eerd_X540(struct ixgbe_hw * hw,u16 offset,u16 * data)39769b5a878SDan McDonald s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
39869b5a878SDan McDonald {
39969b5a878SDan McDonald 	s32 status = IXGBE_SUCCESS;
40069b5a878SDan McDonald 
40169b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_eerd_X540");
40269b5a878SDan McDonald 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
403dc0cb1cdSDale Ghent 	    IXGBE_SUCCESS) {
40469b5a878SDan McDonald 		status = ixgbe_read_eerd_generic(hw, offset, data);
405dc0cb1cdSDale Ghent 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
406dc0cb1cdSDale Ghent 	} else {
40769b5a878SDan McDonald 		status = IXGBE_ERR_SWFW_SYNC;
408dc0cb1cdSDale Ghent 	}
40969b5a878SDan McDonald 
41069b5a878SDan McDonald 	return status;
41169b5a878SDan McDonald }
41269b5a878SDan McDonald 
41369b5a878SDan McDonald /**
41469b5a878SDan McDonald  *  ixgbe_read_eerd_buffer_X540- Read EEPROM word(s) using EERD
41569b5a878SDan McDonald  *  @hw: pointer to hardware structure
41669b5a878SDan McDonald  *  @offset: offset of  word in the EEPROM to read
41769b5a878SDan McDonald  *  @words: number of words
41869b5a878SDan McDonald  *  @data: word(s) read from the EEPROM
41969b5a878SDan McDonald  *
42069b5a878SDan McDonald  *  Reads a 16 bit word(s) from the EEPROM using the EERD register.
42169b5a878SDan McDonald  **/
ixgbe_read_eerd_buffer_X540(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)42269b5a878SDan McDonald s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw,
42369b5a878SDan McDonald 				u16 offset, u16 words, u16 *data)
42469b5a878SDan McDonald {
42569b5a878SDan McDonald 	s32 status = IXGBE_SUCCESS;
42669b5a878SDan McDonald 
42769b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_eerd_buffer_X540");
42869b5a878SDan McDonald 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
429dc0cb1cdSDale Ghent 	    IXGBE_SUCCESS) {
43069b5a878SDan McDonald 		status = ixgbe_read_eerd_buffer_generic(hw, offset,
43169b5a878SDan McDonald 							words, data);
432dc0cb1cdSDale Ghent 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
433dc0cb1cdSDale Ghent 	} else {
43469b5a878SDan McDonald 		status = IXGBE_ERR_SWFW_SYNC;
435dc0cb1cdSDale Ghent 	}
43669b5a878SDan McDonald 
43769b5a878SDan McDonald 	return status;
43869b5a878SDan McDonald }
43969b5a878SDan McDonald 
44069b5a878SDan McDonald /**
44169b5a878SDan McDonald  *  ixgbe_write_eewr_X540 - Write EEPROM word using EEWR
44269b5a878SDan McDonald  *  @hw: pointer to hardware structure
44369b5a878SDan McDonald  *  @offset: offset of  word in the EEPROM to write
44469b5a878SDan McDonald  *  @data: word write to the EEPROM
44569b5a878SDan McDonald  *
44669b5a878SDan McDonald  *  Write a 16 bit word to the EEPROM using the EEWR register.
44769b5a878SDan McDonald  **/
ixgbe_write_eewr_X540(struct ixgbe_hw * hw,u16 offset,u16 data)44869b5a878SDan McDonald s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
44969b5a878SDan McDonald {
45069b5a878SDan McDonald 	s32 status = IXGBE_SUCCESS;
45169b5a878SDan McDonald 
45269b5a878SDan McDonald 	DEBUGFUNC("ixgbe_write_eewr_X540");
45369b5a878SDan McDonald 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
454dc0cb1cdSDale Ghent 	    IXGBE_SUCCESS) {
45569b5a878SDan McDonald 		status = ixgbe_write_eewr_generic(hw, offset, data);
456dc0cb1cdSDale Ghent 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
457dc0cb1cdSDale Ghent 	} else {
45869b5a878SDan McDonald 		status = IXGBE_ERR_SWFW_SYNC;
459dc0cb1cdSDale Ghent 	}
46069b5a878SDan McDonald 
46169b5a878SDan McDonald 	return status;
46269b5a878SDan McDonald }
46369b5a878SDan McDonald 
46469b5a878SDan McDonald /**
46569b5a878SDan McDonald  *  ixgbe_write_eewr_buffer_X540 - Write EEPROM word(s) using EEWR
46669b5a878SDan McDonald  *  @hw: pointer to hardware structure
46769b5a878SDan McDonald  *  @offset: offset of  word in the EEPROM to write
46869b5a878SDan McDonald  *  @words: number of words
46969b5a878SDan McDonald  *  @data: word(s) write to the EEPROM
47069b5a878SDan McDonald  *
47169b5a878SDan McDonald  *  Write a 16 bit word(s) to the EEPROM using the EEWR register.
47269b5a878SDan McDonald  **/
ixgbe_write_eewr_buffer_X540(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)47369b5a878SDan McDonald s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
47469b5a878SDan McDonald 				 u16 offset, u16 words, u16 *data)
47569b5a878SDan McDonald {
47669b5a878SDan McDonald 	s32 status = IXGBE_SUCCESS;
47769b5a878SDan McDonald 
47869b5a878SDan McDonald 	DEBUGFUNC("ixgbe_write_eewr_buffer_X540");
47969b5a878SDan McDonald 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
480dc0cb1cdSDale Ghent 	    IXGBE_SUCCESS) {
48169b5a878SDan McDonald 		status = ixgbe_write_eewr_buffer_generic(hw, offset,
48269b5a878SDan McDonald 							 words, data);
483dc0cb1cdSDale Ghent 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
484dc0cb1cdSDale Ghent 	} else {
48569b5a878SDan McDonald 		status = IXGBE_ERR_SWFW_SYNC;
486dc0cb1cdSDale Ghent 	}
48769b5a878SDan McDonald 
48869b5a878SDan McDonald 	return status;
48969b5a878SDan McDonald }
49069b5a878SDan McDonald 
49169b5a878SDan McDonald /**
49269b5a878SDan McDonald  *  ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum
49369b5a878SDan McDonald  *
49469b5a878SDan McDonald  *  This function does not use synchronization for EERD and EEWR. It can
49569b5a878SDan McDonald  *  be used internally by function which utilize ixgbe_acquire_swfw_sync_X540.
49669b5a878SDan McDonald  *
49769b5a878SDan McDonald  *  @hw: pointer to hardware structure
498dc0cb1cdSDale Ghent  *
499dc0cb1cdSDale Ghent  *  Returns a negative error code on error, or the 16-bit checksum
50069b5a878SDan McDonald  **/
ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw * hw)501dc0cb1cdSDale Ghent s32 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
50269b5a878SDan McDonald {
503dc0cb1cdSDale Ghent 	u16 i, j;
50469b5a878SDan McDonald 	u16 checksum = 0;
50569b5a878SDan McDonald 	u16 length = 0;
50669b5a878SDan McDonald 	u16 pointer = 0;
50769b5a878SDan McDonald 	u16 word = 0;
508dc0cb1cdSDale Ghent 	u16 ptr_start = IXGBE_PCIE_ANALOG_PTR;
50969b5a878SDan McDonald 
510dc0cb1cdSDale Ghent 	/* Do not use hw->eeprom.ops.read because we do not want to take
51169b5a878SDan McDonald 	 * the synchronization semaphores here. Instead use
51269b5a878SDan McDonald 	 * ixgbe_read_eerd_generic
51369b5a878SDan McDonald 	 */
51469b5a878SDan McDonald 
51569b5a878SDan McDonald 	DEBUGFUNC("ixgbe_calc_eeprom_checksum_X540");
51669b5a878SDan McDonald 
517*48ed61a7SRobert Mustacchi 	/* Include 0x0 up to IXGBE_EEPROM_CHECKSUM; do not include the
518*48ed61a7SRobert Mustacchi 	 * checksum itself
519*48ed61a7SRobert Mustacchi 	 */
520*48ed61a7SRobert Mustacchi 	for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
521dc0cb1cdSDale Ghent 		if (ixgbe_read_eerd_generic(hw, i, &word)) {
52269b5a878SDan McDonald 			DEBUGOUT("EEPROM read failed\n");
523dc0cb1cdSDale Ghent 			return IXGBE_ERR_EEPROM;
52469b5a878SDan McDonald 		}
525*48ed61a7SRobert Mustacchi 		checksum += word;
52669b5a878SDan McDonald 	}
52769b5a878SDan McDonald 
528dc0cb1cdSDale Ghent 	/* Include all data from pointers 0x3, 0x6-0xE.  This excludes the
52969b5a878SDan McDonald 	 * FW, PHY module, and PCIe Expansion/Option ROM pointers.
53069b5a878SDan McDonald 	 */
531dc0cb1cdSDale Ghent 	for (i = ptr_start; i < IXGBE_FW_PTR; i++) {
53269b5a878SDan McDonald 		if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
53369b5a878SDan McDonald 			continue;
53469b5a878SDan McDonald 
535dc0cb1cdSDale Ghent 		if (ixgbe_read_eerd_generic(hw, i, &pointer)) {
53669b5a878SDan McDonald 			DEBUGOUT("EEPROM read failed\n");
537dc0cb1cdSDale Ghent 			return IXGBE_ERR_EEPROM;
53869b5a878SDan McDonald 		}
53969b5a878SDan McDonald 
54069b5a878SDan McDonald 		/* Skip pointer section if the pointer is invalid. */
54169b5a878SDan McDonald 		if (pointer == 0xFFFF || pointer == 0 ||
54269b5a878SDan McDonald 		    pointer >= hw->eeprom.word_size)
54369b5a878SDan McDonald 			continue;
54469b5a878SDan McDonald 
545dc0cb1cdSDale Ghent 		if (ixgbe_read_eerd_generic(hw, pointer, &length)) {
54669b5a878SDan McDonald 			DEBUGOUT("EEPROM read failed\n");
547dc0cb1cdSDale Ghent 			return IXGBE_ERR_EEPROM;
54869b5a878SDan McDonald 		}
54969b5a878SDan McDonald 
55069b5a878SDan McDonald 		/* Skip pointer section if length is invalid. */
55169b5a878SDan McDonald 		if (length == 0xFFFF || length == 0 ||
55269b5a878SDan McDonald 		    (pointer + length) >= hw->eeprom.word_size)
55369b5a878SDan McDonald 			continue;
55469b5a878SDan McDonald 
555dc0cb1cdSDale Ghent 		for (j = pointer + 1; j <= pointer + length; j++) {
556dc0cb1cdSDale Ghent 			if (ixgbe_read_eerd_generic(hw, j, &word)) {
55769b5a878SDan McDonald 				DEBUGOUT("EEPROM read failed\n");
558dc0cb1cdSDale Ghent 				return IXGBE_ERR_EEPROM;
55969b5a878SDan McDonald 			}
56069b5a878SDan McDonald 			checksum += word;
56169b5a878SDan McDonald 		}
56269b5a878SDan McDonald 	}
56369b5a878SDan McDonald 
56469b5a878SDan McDonald 	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
56569b5a878SDan McDonald 
566dc0cb1cdSDale Ghent 	return (s32)checksum;
56769b5a878SDan McDonald }
56869b5a878SDan McDonald 
56969b5a878SDan McDonald /**
57069b5a878SDan McDonald  *  ixgbe_validate_eeprom_checksum_X540 - Validate EEPROM checksum
57169b5a878SDan McDonald  *  @hw: pointer to hardware structure
57269b5a878SDan McDonald  *  @checksum_val: calculated checksum
57369b5a878SDan McDonald  *
57469b5a878SDan McDonald  *  Performs checksum calculation and validates the EEPROM checksum.  If the
57569b5a878SDan McDonald  *  caller does not need checksum_val, the value can be NULL.
57669b5a878SDan McDonald  **/
ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw * hw,u16 * checksum_val)57769b5a878SDan McDonald s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw,
57869b5a878SDan McDonald 					u16 *checksum_val)
57969b5a878SDan McDonald {
58069b5a878SDan McDonald 	s32 status;
58169b5a878SDan McDonald 	u16 checksum;
58269b5a878SDan McDonald 	u16 read_checksum = 0;
58369b5a878SDan McDonald 
58469b5a878SDan McDonald 	DEBUGFUNC("ixgbe_validate_eeprom_checksum_X540");
58569b5a878SDan McDonald 
586dc0cb1cdSDale Ghent 	/* Read the first word from the EEPROM. If this times out or fails, do
58769b5a878SDan McDonald 	 * not continue or we could be in for a very long wait while every
58869b5a878SDan McDonald 	 * EEPROM read fails
58969b5a878SDan McDonald 	 */
59069b5a878SDan McDonald 	status = hw->eeprom.ops.read(hw, 0, &checksum);
591dc0cb1cdSDale Ghent 	if (status) {
59269b5a878SDan McDonald 		DEBUGOUT("EEPROM read failed\n");
593dc0cb1cdSDale Ghent 		return status;
59469b5a878SDan McDonald 	}
59569b5a878SDan McDonald 
596dc0cb1cdSDale Ghent 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
597dc0cb1cdSDale Ghent 		return IXGBE_ERR_SWFW_SYNC;
59869b5a878SDan McDonald 
599dc0cb1cdSDale Ghent 	status = hw->eeprom.ops.calc_checksum(hw);
600dc0cb1cdSDale Ghent 	if (status < 0)
601dc0cb1cdSDale Ghent 		goto out;
602dc0cb1cdSDale Ghent 
603dc0cb1cdSDale Ghent 	checksum = (u16)(status & 0xffff);
604dc0cb1cdSDale Ghent 
605dc0cb1cdSDale Ghent 	/* Do not use hw->eeprom.ops.read because we do not want to take
606dc0cb1cdSDale Ghent 	 * the synchronization semaphores twice here.
607dc0cb1cdSDale Ghent 	 */
608dc0cb1cdSDale Ghent 	status = ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
609dc0cb1cdSDale Ghent 					 &read_checksum);
610dc0cb1cdSDale Ghent 	if (status)
611dc0cb1cdSDale Ghent 		goto out;
612dc0cb1cdSDale Ghent 
613dc0cb1cdSDale Ghent 	/* Verify read checksum from EEPROM is the same as
614dc0cb1cdSDale Ghent 	 * calculated checksum
615dc0cb1cdSDale Ghent 	 */
616dc0cb1cdSDale Ghent 	if (read_checksum != checksum) {
617dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
618dc0cb1cdSDale Ghent 			     "Invalid EEPROM checksum");
619dc0cb1cdSDale Ghent 		status = IXGBE_ERR_EEPROM_CHECKSUM;
62069b5a878SDan McDonald 	}
62169b5a878SDan McDonald 
622dc0cb1cdSDale Ghent 	/* If the user cares, return the calculated checksum */
623dc0cb1cdSDale Ghent 	if (checksum_val)
624dc0cb1cdSDale Ghent 		*checksum_val = checksum;
625dc0cb1cdSDale Ghent 
62669b5a878SDan McDonald out:
627dc0cb1cdSDale Ghent 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
628dc0cb1cdSDale Ghent 
62969b5a878SDan McDonald 	return status;
63069b5a878SDan McDonald }
63169b5a878SDan McDonald 
63269b5a878SDan McDonald /**
63369b5a878SDan McDonald  * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash
63469b5a878SDan McDonald  * @hw: pointer to hardware structure
63569b5a878SDan McDonald  *
63669b5a878SDan McDonald  * After writing EEPROM to shadow RAM using EEWR register, software calculates
63769b5a878SDan McDonald  * checksum and updates the EEPROM and instructs the hardware to update
63869b5a878SDan McDonald  * the flash.
63969b5a878SDan McDonald  **/
ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw * hw)64069b5a878SDan McDonald s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
64169b5a878SDan McDonald {
64269b5a878SDan McDonald 	s32 status;
64369b5a878SDan McDonald 	u16 checksum;
64469b5a878SDan McDonald 
64569b5a878SDan McDonald 	DEBUGFUNC("ixgbe_update_eeprom_checksum_X540");
64669b5a878SDan McDonald 
647dc0cb1cdSDale Ghent 	/* Read the first word from the EEPROM. If this times out or fails, do
64869b5a878SDan McDonald 	 * not continue or we could be in for a very long wait while every
64969b5a878SDan McDonald 	 * EEPROM read fails
65069b5a878SDan McDonald 	 */
65169b5a878SDan McDonald 	status = hw->eeprom.ops.read(hw, 0, &checksum);
652dc0cb1cdSDale Ghent 	if (status) {
65369b5a878SDan McDonald 		DEBUGOUT("EEPROM read failed\n");
654dc0cb1cdSDale Ghent 		return status;
655dc0cb1cdSDale Ghent 	}
65669b5a878SDan McDonald 
657dc0cb1cdSDale Ghent 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
658dc0cb1cdSDale Ghent 		return IXGBE_ERR_SWFW_SYNC;
65969b5a878SDan McDonald 
660dc0cb1cdSDale Ghent 	status = hw->eeprom.ops.calc_checksum(hw);
661dc0cb1cdSDale Ghent 	if (status < 0)
662dc0cb1cdSDale Ghent 		goto out;
66369b5a878SDan McDonald 
664dc0cb1cdSDale Ghent 	checksum = (u16)(status & 0xffff);
66569b5a878SDan McDonald 
666dc0cb1cdSDale Ghent 	/* Do not use hw->eeprom.ops.write because we do not want to
667dc0cb1cdSDale Ghent 	 * take the synchronization semaphores twice here.
668dc0cb1cdSDale Ghent 	 */
669dc0cb1cdSDale Ghent 	status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, checksum);
670dc0cb1cdSDale Ghent 	if (status)
671dc0cb1cdSDale Ghent 		goto out;
672dc0cb1cdSDale Ghent 
673dc0cb1cdSDale Ghent 	status = ixgbe_update_flash_X540(hw);
674dc0cb1cdSDale Ghent 
675dc0cb1cdSDale Ghent out:
67669b5a878SDan McDonald 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
67769b5a878SDan McDonald 
67869b5a878SDan McDonald 	return status;
67969b5a878SDan McDonald }
68069b5a878SDan McDonald 
68169b5a878SDan McDonald /**
68269b5a878SDan McDonald  *  ixgbe_update_flash_X540 - Instruct HW to copy EEPROM to Flash device
68369b5a878SDan McDonald  *  @hw: pointer to hardware structure
68469b5a878SDan McDonald  *
68569b5a878SDan McDonald  *  Set FLUP (bit 23) of the EEC register to instruct Hardware to copy
68669b5a878SDan McDonald  *  EEPROM from shadow RAM to the flash device.
68769b5a878SDan McDonald  **/
ixgbe_update_flash_X540(struct ixgbe_hw * hw)688dc0cb1cdSDale Ghent s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
68969b5a878SDan McDonald {
69069b5a878SDan McDonald 	u32 flup;
691dc0cb1cdSDale Ghent 	s32 status;
69269b5a878SDan McDonald 
69369b5a878SDan McDonald 	DEBUGFUNC("ixgbe_update_flash_X540");
69469b5a878SDan McDonald 
69569b5a878SDan McDonald 	status = ixgbe_poll_flash_update_done_X540(hw);
69669b5a878SDan McDonald 	if (status == IXGBE_ERR_EEPROM) {
69769b5a878SDan McDonald 		DEBUGOUT("Flash update time out\n");
69869b5a878SDan McDonald 		goto out;
69969b5a878SDan McDonald 	}
70069b5a878SDan McDonald 
701dc0cb1cdSDale Ghent 	flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)) | IXGBE_EEC_FLUP;
702dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup);
70369b5a878SDan McDonald 
70469b5a878SDan McDonald 	status = ixgbe_poll_flash_update_done_X540(hw);
70569b5a878SDan McDonald 	if (status == IXGBE_SUCCESS)
70669b5a878SDan McDonald 		DEBUGOUT("Flash update complete\n");
70769b5a878SDan McDonald 	else
70869b5a878SDan McDonald 		DEBUGOUT("Flash update time out\n");
70969b5a878SDan McDonald 
710dc0cb1cdSDale Ghent 	if (hw->mac.type == ixgbe_mac_X540 && hw->revision_id == 0) {
711dc0cb1cdSDale Ghent 		flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
71269b5a878SDan McDonald 
71369b5a878SDan McDonald 		if (flup & IXGBE_EEC_SEC1VAL) {
71469b5a878SDan McDonald 			flup |= IXGBE_EEC_FLUP;
715dc0cb1cdSDale Ghent 			IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup);
71669b5a878SDan McDonald 		}
71769b5a878SDan McDonald 
71869b5a878SDan McDonald 		status = ixgbe_poll_flash_update_done_X540(hw);
71969b5a878SDan McDonald 		if (status == IXGBE_SUCCESS)
72069b5a878SDan McDonald 			DEBUGOUT("Flash update complete\n");
72169b5a878SDan McDonald 		else
72269b5a878SDan McDonald 			DEBUGOUT("Flash update time out\n");
72369b5a878SDan McDonald 	}
72469b5a878SDan McDonald out:
72569b5a878SDan McDonald 	return status;
72669b5a878SDan McDonald }
72769b5a878SDan McDonald 
72869b5a878SDan McDonald /**
72969b5a878SDan McDonald  *  ixgbe_poll_flash_update_done_X540 - Poll flash update status
73069b5a878SDan McDonald  *  @hw: pointer to hardware structure
73169b5a878SDan McDonald  *
73269b5a878SDan McDonald  *  Polls the FLUDONE (bit 26) of the EEC Register to determine when the
73369b5a878SDan McDonald  *  flash update is done.
73469b5a878SDan McDonald  **/
ixgbe_poll_flash_update_done_X540(struct ixgbe_hw * hw)73569b5a878SDan McDonald static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
73669b5a878SDan McDonald {
73769b5a878SDan McDonald 	u32 i;
73869b5a878SDan McDonald 	u32 reg;
73969b5a878SDan McDonald 	s32 status = IXGBE_ERR_EEPROM;
74069b5a878SDan McDonald 
74169b5a878SDan McDonald 	DEBUGFUNC("ixgbe_poll_flash_update_done_X540");
74269b5a878SDan McDonald 
74369b5a878SDan McDonald 	for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
744dc0cb1cdSDale Ghent 		reg = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
74569b5a878SDan McDonald 		if (reg & IXGBE_EEC_FLUDONE) {
74669b5a878SDan McDonald 			status = IXGBE_SUCCESS;
74769b5a878SDan McDonald 			break;
74869b5a878SDan McDonald 		}
749dc0cb1cdSDale Ghent 		msec_delay(5);
75069b5a878SDan McDonald 	}
751dc0cb1cdSDale Ghent 
752dc0cb1cdSDale Ghent 	if (i == IXGBE_FLUDONE_ATTEMPTS)
753dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_POLLING,
754dc0cb1cdSDale Ghent 			     "Flash update status polling timed out");
755dc0cb1cdSDale Ghent 
75669b5a878SDan McDonald 	return status;
75769b5a878SDan McDonald }
75869b5a878SDan McDonald 
75969b5a878SDan McDonald /**
76069b5a878SDan McDonald  *  ixgbe_acquire_swfw_sync_X540 - Acquire SWFW semaphore
76169b5a878SDan McDonald  *  @hw: pointer to hardware structure
76269b5a878SDan McDonald  *  @mask: Mask to specify which semaphore to acquire
76369b5a878SDan McDonald  *
76469b5a878SDan McDonald  *  Acquires the SWFW semaphore thought the SW_FW_SYNC register for
76569b5a878SDan McDonald  *  the specified function (CSR, PHY0, PHY1, NVM, Flash)
76669b5a878SDan McDonald  **/
ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw * hw,u32 mask)767dc0cb1cdSDale Ghent s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
76869b5a878SDan McDonald {
769dc0cb1cdSDale Ghent 	u32 swmask = mask & IXGBE_GSSR_NVM_PHY_MASK;
770dc0cb1cdSDale Ghent 	u32 fwmask = swmask << 5;
771dc0cb1cdSDale Ghent 	u32 swi2c_mask = mask & IXGBE_GSSR_I2C_MASK;
77269b5a878SDan McDonald 	u32 timeout = 200;
773dc0cb1cdSDale Ghent 	u32 hwmask = 0;
774dc0cb1cdSDale Ghent 	u32 swfw_sync;
77569b5a878SDan McDonald 	u32 i;
77669b5a878SDan McDonald 
77769b5a878SDan McDonald 	DEBUGFUNC("ixgbe_acquire_swfw_sync_X540");
77869b5a878SDan McDonald 
779dc0cb1cdSDale Ghent 	if (swmask & IXGBE_GSSR_EEP_SM)
780dc0cb1cdSDale Ghent 		hwmask |= IXGBE_GSSR_FLASH_SM;
78169b5a878SDan McDonald 
78269b5a878SDan McDonald 	/* SW only mask doesn't have FW bit pair */
783dc0cb1cdSDale Ghent 	if (mask & IXGBE_GSSR_SW_MNG_SM)
784dc0cb1cdSDale Ghent 		swmask |= IXGBE_GSSR_SW_MNG_SM;
78569b5a878SDan McDonald 
786dc0cb1cdSDale Ghent 	swmask |= swi2c_mask;
787dc0cb1cdSDale Ghent 	fwmask |= swi2c_mask << 2;
788*48ed61a7SRobert Mustacchi 	if (hw->mac.type >= ixgbe_mac_X550)
789*48ed61a7SRobert Mustacchi 		timeout = 1000;
790*48ed61a7SRobert Mustacchi 
79169b5a878SDan McDonald 	for (i = 0; i < timeout; i++) {
792dc0cb1cdSDale Ghent 		/* SW NVM semaphore bit is used for access to all
79369b5a878SDan McDonald 		 * SW_FW_SYNC bits (not just NVM)
79469b5a878SDan McDonald 		 */
795*48ed61a7SRobert Mustacchi 		if (ixgbe_get_swfw_sync_semaphore(hw)) {
796*48ed61a7SRobert Mustacchi 			DEBUGOUT("Failed to get NVM access and register semaphore, returning IXGBE_ERR_SWFW_SYNC\n");
797dc0cb1cdSDale Ghent 			return IXGBE_ERR_SWFW_SYNC;
798*48ed61a7SRobert Mustacchi 		}
79969b5a878SDan McDonald 
800dc0cb1cdSDale Ghent 		swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
80169b5a878SDan McDonald 		if (!(swfw_sync & (fwmask | swmask | hwmask))) {
80269b5a878SDan McDonald 			swfw_sync |= swmask;
803dc0cb1cdSDale Ghent 			IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw),
804dc0cb1cdSDale Ghent 					swfw_sync);
80569b5a878SDan McDonald 			ixgbe_release_swfw_sync_semaphore(hw);
806dc0cb1cdSDale Ghent 			return IXGBE_SUCCESS;
80769b5a878SDan McDonald 		}
808dc0cb1cdSDale Ghent 		/* Firmware currently using resource (fwmask), hardware
809dc0cb1cdSDale Ghent 		 * currently using resource (hwmask), or other software
810dc0cb1cdSDale Ghent 		 * thread currently using resource (swmask)
811dc0cb1cdSDale Ghent 		 */
812dc0cb1cdSDale Ghent 		ixgbe_release_swfw_sync_semaphore(hw);
813dc0cb1cdSDale Ghent 		msec_delay(5);
81469b5a878SDan McDonald 	}
81569b5a878SDan McDonald 
81669b5a878SDan McDonald 	/* If the resource is not released by the FW/HW the SW can assume that
817dc0cb1cdSDale Ghent 	 * the FW/HW malfunctions. In that case the SW should set the SW bit(s)
81869b5a878SDan McDonald 	 * of the requested resource(s) while ignoring the corresponding FW/HW
81969b5a878SDan McDonald 	 * bits in the SW_FW_SYNC register.
82069b5a878SDan McDonald 	 */
821*48ed61a7SRobert Mustacchi 	if (ixgbe_get_swfw_sync_semaphore(hw)) {
822*48ed61a7SRobert Mustacchi 		DEBUGOUT("Failed to get NVM sempahore and register semaphore while forcefully ignoring FW sempahore bit(s) and setting SW semaphore bit(s), returning IXGBE_ERR_SWFW_SYNC\n");
823dc0cb1cdSDale Ghent 		return IXGBE_ERR_SWFW_SYNC;
824*48ed61a7SRobert Mustacchi 	}
825dc0cb1cdSDale Ghent 	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
82669b5a878SDan McDonald 	if (swfw_sync & (fwmask | hwmask)) {
82769b5a878SDan McDonald 		swfw_sync |= swmask;
828dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
82969b5a878SDan McDonald 		ixgbe_release_swfw_sync_semaphore(hw);
83069b5a878SDan McDonald 		msec_delay(5);
831dc0cb1cdSDale Ghent 		return IXGBE_SUCCESS;
83269b5a878SDan McDonald 	}
833dc0cb1cdSDale Ghent 	/* If the resource is not released by other SW the SW can assume that
834dc0cb1cdSDale Ghent 	 * the other SW malfunctions. In that case the SW should clear all SW
835dc0cb1cdSDale Ghent 	 * flags that it does not own and then repeat the whole process once
836dc0cb1cdSDale Ghent 	 * again.
837dc0cb1cdSDale Ghent 	 */
838dc0cb1cdSDale Ghent 	if (swfw_sync & swmask) {
839dc0cb1cdSDale Ghent 		u32 rmask = IXGBE_GSSR_EEP_SM | IXGBE_GSSR_PHY0_SM |
840*48ed61a7SRobert Mustacchi 			    IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_MAC_CSR_SM |
841*48ed61a7SRobert Mustacchi 			    IXGBE_GSSR_SW_MNG_SM;
84269b5a878SDan McDonald 
843dc0cb1cdSDale Ghent 		if (swi2c_mask)
844dc0cb1cdSDale Ghent 			rmask |= IXGBE_GSSR_I2C_MASK;
845dc0cb1cdSDale Ghent 		ixgbe_release_swfw_sync_X540(hw, rmask);
846dc0cb1cdSDale Ghent 		ixgbe_release_swfw_sync_semaphore(hw);
847*48ed61a7SRobert Mustacchi 		DEBUGOUT("Resource not released by other SW, returning IXGBE_ERR_SWFW_SYNC\n");
848dc0cb1cdSDale Ghent 		return IXGBE_ERR_SWFW_SYNC;
849dc0cb1cdSDale Ghent 	}
850dc0cb1cdSDale Ghent 	ixgbe_release_swfw_sync_semaphore(hw);
851*48ed61a7SRobert Mustacchi 	DEBUGOUT("Returning error IXGBE_ERR_SWFW_SYNC\n");
852dc0cb1cdSDale Ghent 
853dc0cb1cdSDale Ghent 	return IXGBE_ERR_SWFW_SYNC;
85469b5a878SDan McDonald }
85569b5a878SDan McDonald 
85669b5a878SDan McDonald /**
85769b5a878SDan McDonald  *  ixgbe_release_swfw_sync_X540 - Release SWFW semaphore
85869b5a878SDan McDonald  *  @hw: pointer to hardware structure
85969b5a878SDan McDonald  *  @mask: Mask to specify which semaphore to release
86069b5a878SDan McDonald  *
86169b5a878SDan McDonald  *  Releases the SWFW semaphore through the SW_FW_SYNC register
86269b5a878SDan McDonald  *  for the specified function (CSR, PHY0, PHY1, EVM, Flash)
86369b5a878SDan McDonald  **/
ixgbe_release_swfw_sync_X540(struct ixgbe_hw * hw,u32 mask)864dc0cb1cdSDale Ghent void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
86569b5a878SDan McDonald {
866dc0cb1cdSDale Ghent 	u32 swmask = mask & (IXGBE_GSSR_NVM_PHY_MASK | IXGBE_GSSR_SW_MNG_SM);
86769b5a878SDan McDonald 	u32 swfw_sync;
86869b5a878SDan McDonald 
86969b5a878SDan McDonald 	DEBUGFUNC("ixgbe_release_swfw_sync_X540");
87069b5a878SDan McDonald 
871dc0cb1cdSDale Ghent 	if (mask & IXGBE_GSSR_I2C_MASK)
872dc0cb1cdSDale Ghent 		swmask |= mask & IXGBE_GSSR_I2C_MASK;
873dc0cb1cdSDale Ghent 	ixgbe_get_swfw_sync_semaphore(hw);
87469b5a878SDan McDonald 
875dc0cb1cdSDale Ghent 	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
87669b5a878SDan McDonald 	swfw_sync &= ~swmask;
877dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
87869b5a878SDan McDonald 
87969b5a878SDan McDonald 	ixgbe_release_swfw_sync_semaphore(hw);
880*48ed61a7SRobert Mustacchi 	msec_delay(2);
88169b5a878SDan McDonald }
88269b5a878SDan McDonald 
88369b5a878SDan McDonald /**
884dc0cb1cdSDale Ghent  *  ixgbe_get_swfw_sync_semaphore - Get hardware semaphore
88569b5a878SDan McDonald  *  @hw: pointer to hardware structure
88669b5a878SDan McDonald  *
88769b5a878SDan McDonald  *  Sets the hardware semaphores so SW/FW can gain control of shared resources
88869b5a878SDan McDonald  **/
ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw * hw)88969b5a878SDan McDonald static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
89069b5a878SDan McDonald {
89169b5a878SDan McDonald 	s32 status = IXGBE_ERR_EEPROM;
89269b5a878SDan McDonald 	u32 timeout = 2000;
89369b5a878SDan McDonald 	u32 i;
89469b5a878SDan McDonald 	u32 swsm;
89569b5a878SDan McDonald 
89669b5a878SDan McDonald 	DEBUGFUNC("ixgbe_get_swfw_sync_semaphore");
89769b5a878SDan McDonald 
89869b5a878SDan McDonald 	/* Get SMBI software semaphore between device drivers first */
89969b5a878SDan McDonald 	for (i = 0; i < timeout; i++) {
90069b5a878SDan McDonald 		/*
90169b5a878SDan McDonald 		 * If the SMBI bit is 0 when we read it, then the bit will be
90269b5a878SDan McDonald 		 * set and we have the semaphore
90369b5a878SDan McDonald 		 */
904dc0cb1cdSDale Ghent 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
90569b5a878SDan McDonald 		if (!(swsm & IXGBE_SWSM_SMBI)) {
90669b5a878SDan McDonald 			status = IXGBE_SUCCESS;
90769b5a878SDan McDonald 			break;
90869b5a878SDan McDonald 		}
90969b5a878SDan McDonald 		usec_delay(50);
91069b5a878SDan McDonald 	}
91169b5a878SDan McDonald 
91269b5a878SDan McDonald 	/* Now get the semaphore between SW/FW through the REGSMP bit */
91369b5a878SDan McDonald 	if (status == IXGBE_SUCCESS) {
91469b5a878SDan McDonald 		for (i = 0; i < timeout; i++) {
915dc0cb1cdSDale Ghent 			swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
91669b5a878SDan McDonald 			if (!(swsm & IXGBE_SWFW_REGSMP))
91769b5a878SDan McDonald 				break;
91869b5a878SDan McDonald 
91969b5a878SDan McDonald 			usec_delay(50);
92069b5a878SDan McDonald 		}
92169b5a878SDan McDonald 
92269b5a878SDan McDonald 		/*
92369b5a878SDan McDonald 		 * Release semaphores and return error if SW NVM semaphore
92469b5a878SDan McDonald 		 * was not granted because we don't have access to the EEPROM
92569b5a878SDan McDonald 		 */
92669b5a878SDan McDonald 		if (i >= timeout) {
927dc0cb1cdSDale Ghent 			ERROR_REPORT1(IXGBE_ERROR_POLLING,
928dc0cb1cdSDale Ghent 				"REGSMP Software NVM semaphore not granted.\n");
92969b5a878SDan McDonald 			ixgbe_release_swfw_sync_semaphore(hw);
93069b5a878SDan McDonald 			status = IXGBE_ERR_EEPROM;
93169b5a878SDan McDonald 		}
93269b5a878SDan McDonald 	} else {
933dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_POLLING,
934dc0cb1cdSDale Ghent 			     "Software semaphore SMBI between device drivers "
935dc0cb1cdSDale Ghent 			     "not granted.\n");
93669b5a878SDan McDonald 	}
93769b5a878SDan McDonald 
93869b5a878SDan McDonald 	return status;
93969b5a878SDan McDonald }
94069b5a878SDan McDonald 
94169b5a878SDan McDonald /**
942dc0cb1cdSDale Ghent  *  ixgbe_release_swfw_sync_semaphore - Release hardware semaphore
94369b5a878SDan McDonald  *  @hw: pointer to hardware structure
94469b5a878SDan McDonald  *
94569b5a878SDan McDonald  *  This function clears hardware semaphore bits.
94669b5a878SDan McDonald  **/
ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw * hw)94769b5a878SDan McDonald static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw)
94869b5a878SDan McDonald {
94969b5a878SDan McDonald 	u32 swsm;
95069b5a878SDan McDonald 
95169b5a878SDan McDonald 	DEBUGFUNC("ixgbe_release_swfw_sync_semaphore");
95269b5a878SDan McDonald 
95369b5a878SDan McDonald 	/* Release both semaphores by writing 0 to the bits REGSMP and SMBI */
95469b5a878SDan McDonald 
955dc0cb1cdSDale Ghent 	swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
95669b5a878SDan McDonald 	swsm &= ~IXGBE_SWFW_REGSMP;
957dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swsm);
958dc0cb1cdSDale Ghent 
959dc0cb1cdSDale Ghent 	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
960dc0cb1cdSDale Ghent 	swsm &= ~IXGBE_SWSM_SMBI;
961dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm);
96269b5a878SDan McDonald 
96369b5a878SDan McDonald 	IXGBE_WRITE_FLUSH(hw);
96469b5a878SDan McDonald }
96569b5a878SDan McDonald 
966*48ed61a7SRobert Mustacchi /**
967*48ed61a7SRobert Mustacchi  *  ixgbe_init_swfw_sync_X540 - Release hardware semaphore
968*48ed61a7SRobert Mustacchi  *  @hw: pointer to hardware structure
969*48ed61a7SRobert Mustacchi  *
970*48ed61a7SRobert Mustacchi  *  This function reset hardware semaphore bits for a semaphore that may
971*48ed61a7SRobert Mustacchi  *  have be left locked due to a catastrophic failure.
972*48ed61a7SRobert Mustacchi  **/
ixgbe_init_swfw_sync_X540(struct ixgbe_hw * hw)973*48ed61a7SRobert Mustacchi void ixgbe_init_swfw_sync_X540(struct ixgbe_hw *hw)
974*48ed61a7SRobert Mustacchi {
975*48ed61a7SRobert Mustacchi 	u32 rmask;
976*48ed61a7SRobert Mustacchi 
977*48ed61a7SRobert Mustacchi 	/* First try to grab the semaphore but we don't need to bother
978*48ed61a7SRobert Mustacchi 	 * looking to see whether we got the lock or not since we do
979*48ed61a7SRobert Mustacchi 	 * the same thing regardless of whether we got the lock or not.
980*48ed61a7SRobert Mustacchi 	 * We got the lock - we release it.
981*48ed61a7SRobert Mustacchi 	 * We timeout trying to get the lock - we force its release.
982*48ed61a7SRobert Mustacchi 	 */
983*48ed61a7SRobert Mustacchi 	ixgbe_get_swfw_sync_semaphore(hw);
984*48ed61a7SRobert Mustacchi 	ixgbe_release_swfw_sync_semaphore(hw);
985*48ed61a7SRobert Mustacchi 
986*48ed61a7SRobert Mustacchi 	/* Acquire and release all software resources. */
987*48ed61a7SRobert Mustacchi 	rmask = IXGBE_GSSR_EEP_SM | IXGBE_GSSR_PHY0_SM |
988*48ed61a7SRobert Mustacchi 		IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_MAC_CSR_SM |
989*48ed61a7SRobert Mustacchi 		IXGBE_GSSR_SW_MNG_SM;
990*48ed61a7SRobert Mustacchi 
991*48ed61a7SRobert Mustacchi 	rmask |= IXGBE_GSSR_I2C_MASK;
992*48ed61a7SRobert Mustacchi 	ixgbe_acquire_swfw_sync_X540(hw, rmask);
993*48ed61a7SRobert Mustacchi 	ixgbe_release_swfw_sync_X540(hw, rmask);
994*48ed61a7SRobert Mustacchi }
995*48ed61a7SRobert Mustacchi 
99669b5a878SDan McDonald /**
99769b5a878SDan McDonald  * ixgbe_blink_led_start_X540 - Blink LED based on index.
99869b5a878SDan McDonald  * @hw: pointer to hardware structure
99969b5a878SDan McDonald  * @index: led number to blink
100069b5a878SDan McDonald  *
100169b5a878SDan McDonald  * Devices that implement the version 2 interface:
100269b5a878SDan McDonald  *   X540
100369b5a878SDan McDonald  **/
ixgbe_blink_led_start_X540(struct ixgbe_hw * hw,u32 index)100469b5a878SDan McDonald s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index)
100569b5a878SDan McDonald {
100669b5a878SDan McDonald 	u32 macc_reg;
100769b5a878SDan McDonald 	u32 ledctl_reg;
100869b5a878SDan McDonald 	ixgbe_link_speed speed;
100969b5a878SDan McDonald 	bool link_up;
101069b5a878SDan McDonald 
101169b5a878SDan McDonald 	DEBUGFUNC("ixgbe_blink_led_start_X540");
101269b5a878SDan McDonald 
1013*48ed61a7SRobert Mustacchi 	if (index > 3)
1014*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_PARAM;
1015*48ed61a7SRobert Mustacchi 
101669b5a878SDan McDonald 	/*
101769b5a878SDan McDonald 	 * Link should be up in order for the blink bit in the LED control
101869b5a878SDan McDonald 	 * register to work. Force link and speed in the MAC if link is down.
101969b5a878SDan McDonald 	 * This will be reversed when we stop the blinking.
102069b5a878SDan McDonald 	 */
102169b5a878SDan McDonald 	hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
102269b5a878SDan McDonald 	if (link_up == FALSE) {
102369b5a878SDan McDonald 		macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
102469b5a878SDan McDonald 		macc_reg |= IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS;
102569b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
102669b5a878SDan McDonald 	}
102769b5a878SDan McDonald 	/* Set the LED to LINK_UP + BLINK. */
102869b5a878SDan McDonald 	ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
102969b5a878SDan McDonald 	ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
103069b5a878SDan McDonald 	ledctl_reg |= IXGBE_LED_BLINK(index);
103169b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
103269b5a878SDan McDonald 	IXGBE_WRITE_FLUSH(hw);
103369b5a878SDan McDonald 
103469b5a878SDan McDonald 	return IXGBE_SUCCESS;
103569b5a878SDan McDonald }
103669b5a878SDan McDonald 
103769b5a878SDan McDonald /**
103869b5a878SDan McDonald  * ixgbe_blink_led_stop_X540 - Stop blinking LED based on index.
103969b5a878SDan McDonald  * @hw: pointer to hardware structure
104069b5a878SDan McDonald  * @index: led number to stop blinking
104169b5a878SDan McDonald  *
104269b5a878SDan McDonald  * Devices that implement the version 2 interface:
104369b5a878SDan McDonald  *   X540
104469b5a878SDan McDonald  **/
ixgbe_blink_led_stop_X540(struct ixgbe_hw * hw,u32 index)104569b5a878SDan McDonald s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index)
104669b5a878SDan McDonald {
104769b5a878SDan McDonald 	u32 macc_reg;
104869b5a878SDan McDonald 	u32 ledctl_reg;
104969b5a878SDan McDonald 
1050*48ed61a7SRobert Mustacchi 	if (index > 3)
1051*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_PARAM;
1052*48ed61a7SRobert Mustacchi 
105369b5a878SDan McDonald 	DEBUGFUNC("ixgbe_blink_led_stop_X540");
105469b5a878SDan McDonald 
105569b5a878SDan McDonald 	/* Restore the LED to its default value. */
105669b5a878SDan McDonald 	ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
105769b5a878SDan McDonald 	ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
105869b5a878SDan McDonald 	ledctl_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
105969b5a878SDan McDonald 	ledctl_reg &= ~IXGBE_LED_BLINK(index);
106069b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
106169b5a878SDan McDonald 
106269b5a878SDan McDonald 	/* Unforce link and speed in the MAC. */
106369b5a878SDan McDonald 	macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
106469b5a878SDan McDonald 	macc_reg &= ~(IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS);
106569b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
106669b5a878SDan McDonald 	IXGBE_WRITE_FLUSH(hw);
106769b5a878SDan McDonald 
106869b5a878SDan McDonald 	return IXGBE_SUCCESS;
106969b5a878SDan McDonald }
1070