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 
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;
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. */
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) {
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)
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) {
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 {
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 }