ixgbe_x540.c revision 295524
1230775Sjfv/******************************************************************************
2230775Sjfv
3283620Serj  Copyright (c) 2001-2015, Intel Corporation
4230775Sjfv  All rights reserved.
5230775Sjfv
6230775Sjfv  Redistribution and use in source and binary forms, with or without
7230775Sjfv  modification, are permitted provided that the following conditions are met:
8230775Sjfv
9230775Sjfv   1. Redistributions of source code must retain the above copyright notice,
10230775Sjfv      this list of conditions and the following disclaimer.
11230775Sjfv
12230775Sjfv   2. Redistributions in binary form must reproduce the above copyright
13230775Sjfv      notice, this list of conditions and the following disclaimer in the
14230775Sjfv      documentation and/or other materials provided with the distribution.
15230775Sjfv
16230775Sjfv   3. Neither the name of the Intel Corporation nor the names of its
17230775Sjfv      contributors may be used to endorse or promote products derived from
18230775Sjfv      this software without specific prior written permission.
19230775Sjfv
20230775Sjfv  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21230775Sjfv  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22230775Sjfv  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23230775Sjfv  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24230775Sjfv  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25230775Sjfv  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26230775Sjfv  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27230775Sjfv  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28230775Sjfv  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29230775Sjfv  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30230775Sjfv  POSSIBILITY OF SUCH DAMAGE.
31230775Sjfv
32230775Sjfv******************************************************************************/
33230775Sjfv/*$FreeBSD: stable/10/sys/dev/ixgbe/ixgbe_x540.c 295524 2016-02-11 16:16:10Z sbruno $*/
34230775Sjfv
35230775Sjfv#include "ixgbe_x540.h"
36230775Sjfv#include "ixgbe_type.h"
37230775Sjfv#include "ixgbe_api.h"
38230775Sjfv#include "ixgbe_common.h"
39230775Sjfv#include "ixgbe_phy.h"
40230775Sjfv
41283620Serj#define IXGBE_X540_MAX_TX_QUEUES	128
42283620Serj#define IXGBE_X540_MAX_RX_QUEUES	128
43283620Serj#define IXGBE_X540_RAR_ENTRIES		128
44283620Serj#define IXGBE_X540_MC_TBL_SIZE		128
45283620Serj#define IXGBE_X540_VFT_TBL_SIZE		128
46283620Serj#define IXGBE_X540_RX_PB_SIZE		384
47283620Serj
48230775Sjfvstatic s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw);
49230775Sjfvstatic s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw);
50230775Sjfvstatic void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw);
51230775Sjfv
52230775Sjfv/**
53230775Sjfv *  ixgbe_init_ops_X540 - Inits func ptrs and MAC type
54230775Sjfv *  @hw: pointer to hardware structure
55230775Sjfv *
56230775Sjfv *  Initialize the function pointers and assign the MAC type for X540.
57230775Sjfv *  Does not touch the hardware.
58230775Sjfv **/
59230775Sjfvs32 ixgbe_init_ops_X540(struct ixgbe_hw *hw)
60230775Sjfv{
61230775Sjfv	struct ixgbe_mac_info *mac = &hw->mac;
62230775Sjfv	struct ixgbe_phy_info *phy = &hw->phy;
63230775Sjfv	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
64230775Sjfv	s32 ret_val;
65230775Sjfv
66230775Sjfv	DEBUGFUNC("ixgbe_init_ops_X540");
67230775Sjfv
68230775Sjfv	ret_val = ixgbe_init_phy_ops_generic(hw);
69230775Sjfv	ret_val = ixgbe_init_ops_generic(hw);
70230775Sjfv
71230775Sjfv
72230775Sjfv	/* EEPROM */
73283620Serj	eeprom->ops.init_params = ixgbe_init_eeprom_params_X540;
74283620Serj	eeprom->ops.read = ixgbe_read_eerd_X540;
75283620Serj	eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_X540;
76283620Serj	eeprom->ops.write = ixgbe_write_eewr_X540;
77283620Serj	eeprom->ops.write_buffer = ixgbe_write_eewr_buffer_X540;
78283620Serj	eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X540;
79283620Serj	eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X540;
80283620Serj	eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X540;
81230775Sjfv
82230775Sjfv	/* PHY */
83283620Serj	phy->ops.init = ixgbe_init_phy_ops_generic;
84230775Sjfv	phy->ops.reset = NULL;
85283620Serj	if (!ixgbe_mng_present(hw))
86283620Serj		phy->ops.set_phy_power = ixgbe_set_copper_phy_power;
87230775Sjfv
88230775Sjfv	/* MAC */
89283620Serj	mac->ops.reset_hw = ixgbe_reset_hw_X540;
90283620Serj	mac->ops.enable_relaxed_ordering = ixgbe_enable_relaxed_ordering_gen2;
91283620Serj	mac->ops.get_media_type = ixgbe_get_media_type_X540;
92230775Sjfv	mac->ops.get_supported_physical_layer =
93283620Serj				    ixgbe_get_supported_physical_layer_X540;
94230775Sjfv	mac->ops.read_analog_reg8 = NULL;
95230775Sjfv	mac->ops.write_analog_reg8 = NULL;
96283620Serj	mac->ops.start_hw = ixgbe_start_hw_X540;
97283620Serj	mac->ops.get_san_mac_addr = ixgbe_get_san_mac_addr_generic;
98283620Serj	mac->ops.set_san_mac_addr = ixgbe_set_san_mac_addr_generic;
99283620Serj	mac->ops.get_device_caps = ixgbe_get_device_caps_generic;
100283620Serj	mac->ops.get_wwn_prefix = ixgbe_get_wwn_prefix_generic;
101283620Serj	mac->ops.get_fcoe_boot_status = ixgbe_get_fcoe_boot_status_generic;
102283620Serj	mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X540;
103283620Serj	mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X540;
104283620Serj	mac->ops.disable_sec_rx_path = ixgbe_disable_sec_rx_path_generic;
105283620Serj	mac->ops.enable_sec_rx_path = ixgbe_enable_sec_rx_path_generic;
106230775Sjfv
107230775Sjfv	/* RAR, Multicast, VLAN */
108283620Serj	mac->ops.set_vmdq = ixgbe_set_vmdq_generic;
109283620Serj	mac->ops.set_vmdq_san_mac = ixgbe_set_vmdq_san_mac_generic;
110283620Serj	mac->ops.clear_vmdq = ixgbe_clear_vmdq_generic;
111283620Serj	mac->ops.insert_mac_addr = ixgbe_insert_mac_addr_generic;
112230775Sjfv	mac->rar_highwater = 1;
113283620Serj	mac->ops.set_vfta = ixgbe_set_vfta_generic;
114283620Serj	mac->ops.set_vlvf = ixgbe_set_vlvf_generic;
115283620Serj	mac->ops.clear_vfta = ixgbe_clear_vfta_generic;
116283620Serj	mac->ops.init_uta_tables = ixgbe_init_uta_tables_generic;
117283620Serj	mac->ops.set_mac_anti_spoofing = ixgbe_set_mac_anti_spoofing;
118283620Serj	mac->ops.set_vlan_anti_spoofing = ixgbe_set_vlan_anti_spoofing;
119230775Sjfv
120230775Sjfv	/* Link */
121230775Sjfv	mac->ops.get_link_capabilities =
122283620Serj				ixgbe_get_copper_link_capabilities_generic;
123283620Serj	mac->ops.setup_link = ixgbe_setup_mac_link_X540;
124283620Serj	mac->ops.setup_rxpba = ixgbe_set_rxpba_generic;
125283620Serj	mac->ops.check_link = ixgbe_check_mac_link_generic;
126230775Sjfv
127247822Sjfv
128283620Serj	mac->mcft_size		= IXGBE_X540_MC_TBL_SIZE;
129283620Serj	mac->vft_size		= IXGBE_X540_VFT_TBL_SIZE;
130283620Serj	mac->num_rar_entries	= IXGBE_X540_RAR_ENTRIES;
131283620Serj	mac->rx_pb_size		= IXGBE_X540_RX_PB_SIZE;
132283620Serj	mac->max_rx_queues	= IXGBE_X540_MAX_RX_QUEUES;
133283620Serj	mac->max_tx_queues	= IXGBE_X540_MAX_TX_QUEUES;
134230775Sjfv	mac->max_msix_vectors	= ixgbe_get_pcie_msix_count_generic(hw);
135230775Sjfv
136230775Sjfv	/*
137230775Sjfv	 * FWSM register
138230775Sjfv	 * ARC supported; valid only if manageability features are
139230775Sjfv	 * enabled.
140230775Sjfv	 */
141295524Ssbruno	mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
142295524Ssbruno				     & IXGBE_FWSM_MODE_MASK);
143230775Sjfv
144230775Sjfv	hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
145230775Sjfv
146230775Sjfv	/* LEDs */
147230775Sjfv	mac->ops.blink_led_start = ixgbe_blink_led_start_X540;
148230775Sjfv	mac->ops.blink_led_stop = ixgbe_blink_led_stop_X540;
149230775Sjfv
150230775Sjfv	/* Manageability interface */
151283620Serj	mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_generic;
152230775Sjfv
153283620Serj	mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
154251964Sjfv
155230775Sjfv	return ret_val;
156230775Sjfv}
157230775Sjfv
158230775Sjfv/**
159230775Sjfv *  ixgbe_get_link_capabilities_X540 - Determines link capabilities
160230775Sjfv *  @hw: pointer to hardware structure
161230775Sjfv *  @speed: pointer to link speed
162230775Sjfv *  @autoneg: TRUE when autoneg or autotry is enabled
163230775Sjfv *
164230775Sjfv *  Determines the link capabilities by reading the AUTOC register.
165230775Sjfv **/
166230775Sjfvs32 ixgbe_get_link_capabilities_X540(struct ixgbe_hw *hw,
167230775Sjfv				     ixgbe_link_speed *speed,
168230775Sjfv				     bool *autoneg)
169230775Sjfv{
170230775Sjfv	ixgbe_get_copper_link_capabilities_generic(hw, speed, autoneg);
171230775Sjfv
172230775Sjfv	return IXGBE_SUCCESS;
173230775Sjfv}
174230775Sjfv
175230775Sjfv/**
176230775Sjfv *  ixgbe_get_media_type_X540 - Get media type
177230775Sjfv *  @hw: pointer to hardware structure
178230775Sjfv *
179230775Sjfv *  Returns the media type (fiber, copper, backplane)
180230775Sjfv **/
181230775Sjfvenum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw)
182230775Sjfv{
183230775Sjfv	UNREFERENCED_1PARAMETER(hw);
184230775Sjfv	return ixgbe_media_type_copper;
185230775Sjfv}
186230775Sjfv
187230775Sjfv/**
188230775Sjfv *  ixgbe_setup_mac_link_X540 - Sets the auto advertised capabilities
189230775Sjfv *  @hw: pointer to hardware structure
190230775Sjfv *  @speed: new link speed
191230775Sjfv *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
192230775Sjfv **/
193230775Sjfvs32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw,
194247822Sjfv			      ixgbe_link_speed speed,
195230775Sjfv			      bool autoneg_wait_to_complete)
196230775Sjfv{
197230775Sjfv	DEBUGFUNC("ixgbe_setup_mac_link_X540");
198247822Sjfv	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete);
199230775Sjfv}
200230775Sjfv
201230775Sjfv/**
202230775Sjfv *  ixgbe_reset_hw_X540 - Perform hardware reset
203230775Sjfv *  @hw: pointer to hardware structure
204230775Sjfv *
205230775Sjfv *  Resets the hardware by resetting the transmit and receive units, masks
206230775Sjfv *  and clears all interrupts, and perform a reset.
207230775Sjfv **/
208230775Sjfvs32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
209230775Sjfv{
210230775Sjfv	s32 status;
211230775Sjfv	u32 ctrl, i;
212230775Sjfv
213230775Sjfv	DEBUGFUNC("ixgbe_reset_hw_X540");
214230775Sjfv
215230775Sjfv	/* Call adapter stop to disable tx/rx and clear interrupts */
216230775Sjfv	status = hw->mac.ops.stop_adapter(hw);
217230775Sjfv	if (status != IXGBE_SUCCESS)
218230775Sjfv		goto reset_hw_out;
219230775Sjfv
220230775Sjfv	/* flush pending Tx transactions */
221230775Sjfv	ixgbe_clear_tx_pending(hw);
222230775Sjfv
223230775Sjfvmac_reset_top:
224230775Sjfv	ctrl = IXGBE_CTRL_RST;
225230775Sjfv	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
226230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
227230775Sjfv	IXGBE_WRITE_FLUSH(hw);
228230775Sjfv
229230775Sjfv	/* Poll for reset bit to self-clear indicating reset is complete */
230230775Sjfv	for (i = 0; i < 10; i++) {
231230775Sjfv		usec_delay(1);
232230775Sjfv		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
233230775Sjfv		if (!(ctrl & IXGBE_CTRL_RST_MASK))
234230775Sjfv			break;
235230775Sjfv	}
236230775Sjfv
237230775Sjfv	if (ctrl & IXGBE_CTRL_RST_MASK) {
238230775Sjfv		status = IXGBE_ERR_RESET_FAILED;
239251964Sjfv		ERROR_REPORT1(IXGBE_ERROR_POLLING,
240251964Sjfv			     "Reset polling failed to complete.\n");
241230775Sjfv	}
242230775Sjfv	msec_delay(100);
243230775Sjfv
244230775Sjfv	/*
245230775Sjfv	 * Double resets are required for recovery from certain error
246230775Sjfv	 * conditions.  Between resets, it is necessary to stall to allow time
247230775Sjfv	 * for any pending HW events to complete.
248230775Sjfv	 */
249230775Sjfv	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
250230775Sjfv		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
251230775Sjfv		goto mac_reset_top;
252230775Sjfv	}
253230775Sjfv
254230775Sjfv	/* Set the Rx packet buffer size. */
255230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT);
256230775Sjfv
257230775Sjfv	/* Store the permanent mac address */
258230775Sjfv	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
259230775Sjfv
260230775Sjfv	/*
261230775Sjfv	 * Store MAC address from RAR0, clear receive address registers, and
262230775Sjfv	 * clear the multicast table.  Also reset num_rar_entries to 128,
263230775Sjfv	 * since we modify this value when programming the SAN MAC address.
264230775Sjfv	 */
265230775Sjfv	hw->mac.num_rar_entries = 128;
266230775Sjfv	hw->mac.ops.init_rx_addrs(hw);
267230775Sjfv
268230775Sjfv	/* Store the permanent SAN mac address */
269230775Sjfv	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
270230775Sjfv
271230775Sjfv	/* Add the SAN MAC address to the RAR only if it's a valid address */
272230775Sjfv	if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
273230775Sjfv		hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
274230775Sjfv				    hw->mac.san_addr, 0, IXGBE_RAH_AV);
275230775Sjfv
276238149Sjfv		/* Save the SAN MAC RAR index */
277238149Sjfv		hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
278238149Sjfv
279230775Sjfv		/* Reserve the last RAR for the SAN MAC address */
280230775Sjfv		hw->mac.num_rar_entries--;
281230775Sjfv	}
282230775Sjfv
283230775Sjfv	/* Store the alternative WWNN/WWPN prefix */
284230775Sjfv	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
285230775Sjfv				   &hw->mac.wwpn_prefix);
286230775Sjfv
287230775Sjfvreset_hw_out:
288230775Sjfv	return status;
289230775Sjfv}
290230775Sjfv
291230775Sjfv/**
292230775Sjfv *  ixgbe_start_hw_X540 - Prepare hardware for Tx/Rx
293230775Sjfv *  @hw: pointer to hardware structure
294230775Sjfv *
295230775Sjfv *  Starts the hardware using the generic start_hw function
296230775Sjfv *  and the generation start_hw function.
297230775Sjfv *  Then performs revision-specific operations, if any.
298230775Sjfv **/
299230775Sjfvs32 ixgbe_start_hw_X540(struct ixgbe_hw *hw)
300230775Sjfv{
301230775Sjfv	s32 ret_val = IXGBE_SUCCESS;
302230775Sjfv
303230775Sjfv	DEBUGFUNC("ixgbe_start_hw_X540");
304230775Sjfv
305230775Sjfv	ret_val = ixgbe_start_hw_generic(hw);
306230775Sjfv	if (ret_val != IXGBE_SUCCESS)
307230775Sjfv		goto out;
308230775Sjfv
309230775Sjfv	ret_val = ixgbe_start_hw_gen2(hw);
310230775Sjfv
311230775Sjfvout:
312230775Sjfv	return ret_val;
313230775Sjfv}
314230775Sjfv
315230775Sjfv/**
316230775Sjfv *  ixgbe_get_supported_physical_layer_X540 - Returns physical layer type
317230775Sjfv *  @hw: pointer to hardware structure
318230775Sjfv *
319230775Sjfv *  Determines physical layer capabilities of the current configuration.
320230775Sjfv **/
321230775Sjfvu32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
322230775Sjfv{
323230775Sjfv	u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
324230775Sjfv	u16 ext_ability = 0;
325230775Sjfv
326230775Sjfv	DEBUGFUNC("ixgbe_get_supported_physical_layer_X540");
327230775Sjfv
328230775Sjfv	hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
329230775Sjfv	IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
330230775Sjfv	if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
331230775Sjfv		physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
332230775Sjfv	if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
333230775Sjfv		physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
334230775Sjfv	if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
335230775Sjfv		physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
336230775Sjfv
337230775Sjfv	return physical_layer;
338230775Sjfv}
339230775Sjfv
340230775Sjfv/**
341230775Sjfv *  ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
342230775Sjfv *  @hw: pointer to hardware structure
343230775Sjfv *
344230775Sjfv *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
345230775Sjfv *  ixgbe_hw struct in order to set up EEPROM access.
346230775Sjfv **/
347230775Sjfvs32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
348230775Sjfv{
349230775Sjfv	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
350230775Sjfv	u32 eec;
351230775Sjfv	u16 eeprom_size;
352230775Sjfv
353230775Sjfv	DEBUGFUNC("ixgbe_init_eeprom_params_X540");
354230775Sjfv
355230775Sjfv	if (eeprom->type == ixgbe_eeprom_uninitialized) {
356230775Sjfv		eeprom->semaphore_delay = 10;
357230775Sjfv		eeprom->type = ixgbe_flash;
358230775Sjfv
359295524Ssbruno		eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
360230775Sjfv		eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
361230775Sjfv				    IXGBE_EEC_SIZE_SHIFT);
362230775Sjfv		eeprom->word_size = 1 << (eeprom_size +
363230775Sjfv					  IXGBE_EEPROM_WORD_SIZE_SHIFT);
364230775Sjfv
365230775Sjfv		DEBUGOUT2("Eeprom params: type = %d, size = %d\n",
366230775Sjfv			  eeprom->type, eeprom->word_size);
367230775Sjfv	}
368230775Sjfv
369230775Sjfv	return IXGBE_SUCCESS;
370230775Sjfv}
371230775Sjfv
372230775Sjfv/**
373230775Sjfv *  ixgbe_read_eerd_X540- Read EEPROM word using EERD
374230775Sjfv *  @hw: pointer to hardware structure
375230775Sjfv *  @offset: offset of  word in the EEPROM to read
376230775Sjfv *  @data: word read from the EEPROM
377230775Sjfv *
378230775Sjfv *  Reads a 16 bit word from the EEPROM using the EERD register.
379230775Sjfv **/
380230775Sjfvs32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
381230775Sjfv{
382230775Sjfv	s32 status = IXGBE_SUCCESS;
383230775Sjfv
384230775Sjfv	DEBUGFUNC("ixgbe_read_eerd_X540");
385230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
386251964Sjfv	    IXGBE_SUCCESS) {
387230775Sjfv		status = ixgbe_read_eerd_generic(hw, offset, data);
388251964Sjfv		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
389251964Sjfv	} else {
390230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
391251964Sjfv	}
392230775Sjfv
393230775Sjfv	return status;
394230775Sjfv}
395230775Sjfv
396230775Sjfv/**
397230775Sjfv *  ixgbe_read_eerd_buffer_X540- Read EEPROM word(s) using EERD
398230775Sjfv *  @hw: pointer to hardware structure
399230775Sjfv *  @offset: offset of  word in the EEPROM to read
400230775Sjfv *  @words: number of words
401230775Sjfv *  @data: word(s) read from the EEPROM
402230775Sjfv *
403230775Sjfv *  Reads a 16 bit word(s) from the EEPROM using the EERD register.
404230775Sjfv **/
405230775Sjfvs32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw,
406230775Sjfv				u16 offset, u16 words, u16 *data)
407230775Sjfv{
408230775Sjfv	s32 status = IXGBE_SUCCESS;
409230775Sjfv
410230775Sjfv	DEBUGFUNC("ixgbe_read_eerd_buffer_X540");
411230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
412251964Sjfv	    IXGBE_SUCCESS) {
413230775Sjfv		status = ixgbe_read_eerd_buffer_generic(hw, offset,
414230775Sjfv							words, data);
415251964Sjfv		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
416251964Sjfv	} else {
417230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
418251964Sjfv	}
419230775Sjfv
420230775Sjfv	return status;
421230775Sjfv}
422230775Sjfv
423230775Sjfv/**
424230775Sjfv *  ixgbe_write_eewr_X540 - Write EEPROM word using EEWR
425230775Sjfv *  @hw: pointer to hardware structure
426230775Sjfv *  @offset: offset of  word in the EEPROM to write
427230775Sjfv *  @data: word write to the EEPROM
428230775Sjfv *
429230775Sjfv *  Write a 16 bit word to the EEPROM using the EEWR register.
430230775Sjfv **/
431230775Sjfvs32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
432230775Sjfv{
433230775Sjfv	s32 status = IXGBE_SUCCESS;
434230775Sjfv
435230775Sjfv	DEBUGFUNC("ixgbe_write_eewr_X540");
436230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
437251964Sjfv	    IXGBE_SUCCESS) {
438230775Sjfv		status = ixgbe_write_eewr_generic(hw, offset, data);
439251964Sjfv		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
440251964Sjfv	} else {
441230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
442251964Sjfv	}
443230775Sjfv
444230775Sjfv	return status;
445230775Sjfv}
446230775Sjfv
447230775Sjfv/**
448230775Sjfv *  ixgbe_write_eewr_buffer_X540 - Write EEPROM word(s) using EEWR
449230775Sjfv *  @hw: pointer to hardware structure
450230775Sjfv *  @offset: offset of  word in the EEPROM to write
451230775Sjfv *  @words: number of words
452230775Sjfv *  @data: word(s) write to the EEPROM
453230775Sjfv *
454230775Sjfv *  Write a 16 bit word(s) to the EEPROM using the EEWR register.
455230775Sjfv **/
456230775Sjfvs32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
457230775Sjfv				 u16 offset, u16 words, u16 *data)
458230775Sjfv{
459230775Sjfv	s32 status = IXGBE_SUCCESS;
460230775Sjfv
461230775Sjfv	DEBUGFUNC("ixgbe_write_eewr_buffer_X540");
462230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
463251964Sjfv	    IXGBE_SUCCESS) {
464230775Sjfv		status = ixgbe_write_eewr_buffer_generic(hw, offset,
465230775Sjfv							 words, data);
466251964Sjfv		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
467251964Sjfv	} else {
468230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
469251964Sjfv	}
470230775Sjfv
471230775Sjfv	return status;
472230775Sjfv}
473230775Sjfv
474230775Sjfv/**
475230775Sjfv *  ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum
476230775Sjfv *
477230775Sjfv *  This function does not use synchronization for EERD and EEWR. It can
478230775Sjfv *  be used internally by function which utilize ixgbe_acquire_swfw_sync_X540.
479230775Sjfv *
480230775Sjfv *  @hw: pointer to hardware structure
481283620Serj *
482283620Serj *  Returns a negative error code on error, or the 16-bit checksum
483230775Sjfv **/
484283620Serjs32 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
485230775Sjfv{
486283620Serj	u16 i, j;
487230775Sjfv	u16 checksum = 0;
488230775Sjfv	u16 length = 0;
489230775Sjfv	u16 pointer = 0;
490230775Sjfv	u16 word = 0;
491283620Serj	u16 checksum_last_word = IXGBE_EEPROM_CHECKSUM;
492283620Serj	u16 ptr_start = IXGBE_PCIE_ANALOG_PTR;
493230775Sjfv
494283620Serj	/* Do not use hw->eeprom.ops.read because we do not want to take
495230775Sjfv	 * the synchronization semaphores here. Instead use
496230775Sjfv	 * ixgbe_read_eerd_generic
497230775Sjfv	 */
498230775Sjfv
499230775Sjfv	DEBUGFUNC("ixgbe_calc_eeprom_checksum_X540");
500230775Sjfv
501230775Sjfv	/* Include 0x0-0x3F in the checksum */
502283620Serj	for (i = 0; i <= checksum_last_word; i++) {
503283620Serj		if (ixgbe_read_eerd_generic(hw, i, &word)) {
504230775Sjfv			DEBUGOUT("EEPROM read failed\n");
505283620Serj			return IXGBE_ERR_EEPROM;
506230775Sjfv		}
507283620Serj		if (i != IXGBE_EEPROM_CHECKSUM)
508283620Serj			checksum += word;
509230775Sjfv	}
510230775Sjfv
511283620Serj	/* Include all data from pointers 0x3, 0x6-0xE.  This excludes the
512230775Sjfv	 * FW, PHY module, and PCIe Expansion/Option ROM pointers.
513230775Sjfv	 */
514283620Serj	for (i = ptr_start; i < IXGBE_FW_PTR; i++) {
515230775Sjfv		if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
516230775Sjfv			continue;
517230775Sjfv
518283620Serj		if (ixgbe_read_eerd_generic(hw, i, &pointer)) {
519230775Sjfv			DEBUGOUT("EEPROM read failed\n");
520283620Serj			return IXGBE_ERR_EEPROM;
521230775Sjfv		}
522230775Sjfv
523230775Sjfv		/* Skip pointer section if the pointer is invalid. */
524230775Sjfv		if (pointer == 0xFFFF || pointer == 0 ||
525230775Sjfv		    pointer >= hw->eeprom.word_size)
526230775Sjfv			continue;
527230775Sjfv
528283620Serj		if (ixgbe_read_eerd_generic(hw, pointer, &length)) {
529230775Sjfv			DEBUGOUT("EEPROM read failed\n");
530283620Serj			return IXGBE_ERR_EEPROM;
531230775Sjfv		}
532230775Sjfv
533230775Sjfv		/* Skip pointer section if length is invalid. */
534230775Sjfv		if (length == 0xFFFF || length == 0 ||
535230775Sjfv		    (pointer + length) >= hw->eeprom.word_size)
536230775Sjfv			continue;
537230775Sjfv
538283620Serj		for (j = pointer + 1; j <= pointer + length; j++) {
539283620Serj			if (ixgbe_read_eerd_generic(hw, j, &word)) {
540230775Sjfv				DEBUGOUT("EEPROM read failed\n");
541283620Serj				return IXGBE_ERR_EEPROM;
542230775Sjfv			}
543230775Sjfv			checksum += word;
544230775Sjfv		}
545230775Sjfv	}
546230775Sjfv
547230775Sjfv	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
548230775Sjfv
549283620Serj	return (s32)checksum;
550230775Sjfv}
551230775Sjfv
552230775Sjfv/**
553230775Sjfv *  ixgbe_validate_eeprom_checksum_X540 - Validate EEPROM checksum
554230775Sjfv *  @hw: pointer to hardware structure
555230775Sjfv *  @checksum_val: calculated checksum
556230775Sjfv *
557230775Sjfv *  Performs checksum calculation and validates the EEPROM checksum.  If the
558230775Sjfv *  caller does not need checksum_val, the value can be NULL.
559230775Sjfv **/
560230775Sjfvs32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw,
561230775Sjfv					u16 *checksum_val)
562230775Sjfv{
563230775Sjfv	s32 status;
564230775Sjfv	u16 checksum;
565230775Sjfv	u16 read_checksum = 0;
566230775Sjfv
567230775Sjfv	DEBUGFUNC("ixgbe_validate_eeprom_checksum_X540");
568230775Sjfv
569283620Serj	/* Read the first word from the EEPROM. If this times out or fails, do
570230775Sjfv	 * not continue or we could be in for a very long wait while every
571230775Sjfv	 * EEPROM read fails
572230775Sjfv	 */
573230775Sjfv	status = hw->eeprom.ops.read(hw, 0, &checksum);
574283620Serj	if (status) {
575230775Sjfv		DEBUGOUT("EEPROM read failed\n");
576283620Serj		return status;
577230775Sjfv	}
578230775Sjfv
579283620Serj	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
580283620Serj		return IXGBE_ERR_SWFW_SYNC;
581230775Sjfv
582283620Serj	status = hw->eeprom.ops.calc_checksum(hw);
583283620Serj	if (status < 0)
584283620Serj		goto out;
585230775Sjfv
586283620Serj	checksum = (u16)(status & 0xffff);
587230775Sjfv
588283620Serj	/* Do not use hw->eeprom.ops.read because we do not want to take
589283620Serj	 * the synchronization semaphores twice here.
590283620Serj	 */
591283620Serj	status = ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
592283620Serj					 &read_checksum);
593283620Serj	if (status)
594283620Serj		goto out;
595283620Serj
596283620Serj	/* Verify read checksum from EEPROM is the same as
597283620Serj	 * calculated checksum
598283620Serj	 */
599283620Serj	if (read_checksum != checksum) {
600283620Serj		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
601283620Serj			     "Invalid EEPROM checksum");
602283620Serj		status = IXGBE_ERR_EEPROM_CHECKSUM;
603230775Sjfv	}
604230775Sjfv
605283620Serj	/* If the user cares, return the calculated checksum */
606283620Serj	if (checksum_val)
607283620Serj		*checksum_val = checksum;
608283620Serj
609230775Sjfvout:
610283620Serj	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
611283620Serj
612230775Sjfv	return status;
613230775Sjfv}
614230775Sjfv
615230775Sjfv/**
616230775Sjfv * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash
617230775Sjfv * @hw: pointer to hardware structure
618230775Sjfv *
619230775Sjfv * After writing EEPROM to shadow RAM using EEWR register, software calculates
620230775Sjfv * checksum and updates the EEPROM and instructs the hardware to update
621230775Sjfv * the flash.
622230775Sjfv **/
623230775Sjfvs32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
624230775Sjfv{
625230775Sjfv	s32 status;
626230775Sjfv	u16 checksum;
627230775Sjfv
628230775Sjfv	DEBUGFUNC("ixgbe_update_eeprom_checksum_X540");
629230775Sjfv
630283620Serj	/* Read the first word from the EEPROM. If this times out or fails, do
631230775Sjfv	 * not continue or we could be in for a very long wait while every
632230775Sjfv	 * EEPROM read fails
633230775Sjfv	 */
634230775Sjfv	status = hw->eeprom.ops.read(hw, 0, &checksum);
635283620Serj	if (status) {
636230775Sjfv		DEBUGOUT("EEPROM read failed\n");
637283620Serj		return status;
638283620Serj	}
639230775Sjfv
640283620Serj	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
641283620Serj		return IXGBE_ERR_SWFW_SYNC;
642230775Sjfv
643283620Serj	status = hw->eeprom.ops.calc_checksum(hw);
644283620Serj	if (status < 0)
645283620Serj		goto out;
646230775Sjfv
647283620Serj	checksum = (u16)(status & 0xffff);
648230775Sjfv
649283620Serj	/* Do not use hw->eeprom.ops.write because we do not want to
650283620Serj	 * take the synchronization semaphores twice here.
651283620Serj	 */
652283620Serj	status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, checksum);
653283620Serj	if (status)
654283620Serj		goto out;
655283620Serj
656283620Serj	status = ixgbe_update_flash_X540(hw);
657283620Serj
658283620Serjout:
659283620Serj	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
660283620Serj
661230775Sjfv	return status;
662230775Sjfv}
663230775Sjfv
664230775Sjfv/**
665230775Sjfv *  ixgbe_update_flash_X540 - Instruct HW to copy EEPROM to Flash device
666230775Sjfv *  @hw: pointer to hardware structure
667230775Sjfv *
668230775Sjfv *  Set FLUP (bit 23) of the EEC register to instruct Hardware to copy
669230775Sjfv *  EEPROM from shadow RAM to the flash device.
670230775Sjfv **/
671251964Sjfvs32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
672230775Sjfv{
673230775Sjfv	u32 flup;
674283620Serj	s32 status;
675230775Sjfv
676230775Sjfv	DEBUGFUNC("ixgbe_update_flash_X540");
677230775Sjfv
678230775Sjfv	status = ixgbe_poll_flash_update_done_X540(hw);
679230775Sjfv	if (status == IXGBE_ERR_EEPROM) {
680230775Sjfv		DEBUGOUT("Flash update time out\n");
681230775Sjfv		goto out;
682230775Sjfv	}
683230775Sjfv
684295524Ssbruno	flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)) | IXGBE_EEC_FLUP;
685295524Ssbruno	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup);
686230775Sjfv
687230775Sjfv	status = ixgbe_poll_flash_update_done_X540(hw);
688230775Sjfv	if (status == IXGBE_SUCCESS)
689230775Sjfv		DEBUGOUT("Flash update complete\n");
690230775Sjfv	else
691230775Sjfv		DEBUGOUT("Flash update time out\n");
692230775Sjfv
693251964Sjfv	if (hw->mac.type == ixgbe_mac_X540 && hw->revision_id == 0) {
694295524Ssbruno		flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
695230775Sjfv
696230775Sjfv		if (flup & IXGBE_EEC_SEC1VAL) {
697230775Sjfv			flup |= IXGBE_EEC_FLUP;
698295524Ssbruno			IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup);
699230775Sjfv		}
700230775Sjfv
701230775Sjfv		status = ixgbe_poll_flash_update_done_X540(hw);
702230775Sjfv		if (status == IXGBE_SUCCESS)
703230775Sjfv			DEBUGOUT("Flash update complete\n");
704230775Sjfv		else
705230775Sjfv			DEBUGOUT("Flash update time out\n");
706230775Sjfv	}
707230775Sjfvout:
708230775Sjfv	return status;
709230775Sjfv}
710230775Sjfv
711230775Sjfv/**
712230775Sjfv *  ixgbe_poll_flash_update_done_X540 - Poll flash update status
713230775Sjfv *  @hw: pointer to hardware structure
714230775Sjfv *
715230775Sjfv *  Polls the FLUDONE (bit 26) of the EEC Register to determine when the
716230775Sjfv *  flash update is done.
717230775Sjfv **/
718230775Sjfvstatic s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
719230775Sjfv{
720230775Sjfv	u32 i;
721230775Sjfv	u32 reg;
722230775Sjfv	s32 status = IXGBE_ERR_EEPROM;
723230775Sjfv
724230775Sjfv	DEBUGFUNC("ixgbe_poll_flash_update_done_X540");
725230775Sjfv
726230775Sjfv	for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
727295524Ssbruno		reg = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
728230775Sjfv		if (reg & IXGBE_EEC_FLUDONE) {
729230775Sjfv			status = IXGBE_SUCCESS;
730230775Sjfv			break;
731230775Sjfv		}
732283620Serj		msec_delay(5);
733230775Sjfv	}
734251964Sjfv
735251964Sjfv	if (i == IXGBE_FLUDONE_ATTEMPTS)
736251964Sjfv		ERROR_REPORT1(IXGBE_ERROR_POLLING,
737251964Sjfv			     "Flash update status polling timed out");
738251964Sjfv
739230775Sjfv	return status;
740230775Sjfv}
741230775Sjfv
742230775Sjfv/**
743230775Sjfv *  ixgbe_acquire_swfw_sync_X540 - Acquire SWFW semaphore
744230775Sjfv *  @hw: pointer to hardware structure
745230775Sjfv *  @mask: Mask to specify which semaphore to acquire
746230775Sjfv *
747230775Sjfv *  Acquires the SWFW semaphore thought the SW_FW_SYNC register for
748230775Sjfv *  the specified function (CSR, PHY0, PHY1, NVM, Flash)
749230775Sjfv **/
750283620Serjs32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
751230775Sjfv{
752283620Serj	u32 swmask = mask & IXGBE_GSSR_NVM_PHY_MASK;
753283620Serj	u32 fwmask = swmask << 5;
754283620Serj	u32 swi2c_mask = mask & IXGBE_GSSR_I2C_MASK;
755283620Serj	u32 timeout = 200;
756283620Serj	u32 hwmask = 0;
757230775Sjfv	u32 swfw_sync;
758230775Sjfv	u32 i;
759230775Sjfv
760230775Sjfv	DEBUGFUNC("ixgbe_acquire_swfw_sync_X540");
761230775Sjfv
762283620Serj	if (swmask & IXGBE_GSSR_EEP_SM)
763283620Serj		hwmask |= IXGBE_GSSR_FLASH_SM;
764230775Sjfv
765230775Sjfv	/* SW only mask doesn't have FW bit pair */
766283620Serj	if (mask & IXGBE_GSSR_SW_MNG_SM)
767283620Serj		swmask |= IXGBE_GSSR_SW_MNG_SM;
768230775Sjfv
769283620Serj	swmask |= swi2c_mask;
770283620Serj	fwmask |= swi2c_mask << 2;
771230775Sjfv	for (i = 0; i < timeout; i++) {
772283620Serj		/* SW NVM semaphore bit is used for access to all
773230775Sjfv		 * SW_FW_SYNC bits (not just NVM)
774230775Sjfv		 */
775283620Serj		if (ixgbe_get_swfw_sync_semaphore(hw))
776283620Serj			return IXGBE_ERR_SWFW_SYNC;
777230775Sjfv
778295524Ssbruno		swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
779230775Sjfv		if (!(swfw_sync & (fwmask | swmask | hwmask))) {
780230775Sjfv			swfw_sync |= swmask;
781295524Ssbruno			IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw),
782295524Ssbruno					swfw_sync);
783230775Sjfv			ixgbe_release_swfw_sync_semaphore(hw);
784230775Sjfv			msec_delay(5);
785283620Serj			return IXGBE_SUCCESS;
786230775Sjfv		}
787283620Serj		/* Firmware currently using resource (fwmask), hardware
788283620Serj		 * currently using resource (hwmask), or other software
789283620Serj		 * thread currently using resource (swmask)
790283620Serj		 */
791283620Serj		ixgbe_release_swfw_sync_semaphore(hw);
792283620Serj		msec_delay(5);
793230775Sjfv	}
794230775Sjfv
795230775Sjfv	/* Failed to get SW only semaphore */
796230775Sjfv	if (swmask == IXGBE_GSSR_SW_MNG_SM) {
797251964Sjfv		ERROR_REPORT1(IXGBE_ERROR_POLLING,
798251964Sjfv			     "Failed to get SW only semaphore");
799283620Serj		return IXGBE_ERR_SWFW_SYNC;
800230775Sjfv	}
801230775Sjfv
802230775Sjfv	/* If the resource is not released by the FW/HW the SW can assume that
803251964Sjfv	 * the FW/HW malfunctions. In that case the SW should set the SW bit(s)
804230775Sjfv	 * of the requested resource(s) while ignoring the corresponding FW/HW
805230775Sjfv	 * bits in the SW_FW_SYNC register.
806230775Sjfv	 */
807283620Serj	if (ixgbe_get_swfw_sync_semaphore(hw))
808283620Serj		return IXGBE_ERR_SWFW_SYNC;
809295524Ssbruno	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
810230775Sjfv	if (swfw_sync & (fwmask | hwmask)) {
811230775Sjfv		swfw_sync |= swmask;
812295524Ssbruno		IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
813230775Sjfv		ixgbe_release_swfw_sync_semaphore(hw);
814230775Sjfv		msec_delay(5);
815283620Serj		return IXGBE_SUCCESS;
816230775Sjfv	}
817251964Sjfv	/* If the resource is not released by other SW the SW can assume that
818251964Sjfv	 * the other SW malfunctions. In that case the SW should clear all SW
819251964Sjfv	 * flags that it does not own and then repeat the whole process once
820251964Sjfv	 * again.
821251964Sjfv	 */
822283620Serj	if (swfw_sync & swmask) {
823283620Serj		u32 rmask = IXGBE_GSSR_EEP_SM | IXGBE_GSSR_PHY0_SM |
824283620Serj			    IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_MAC_CSR_SM;
825283620Serj
826283620Serj		if (swi2c_mask)
827283620Serj			rmask |= IXGBE_GSSR_I2C_MASK;
828283620Serj		ixgbe_release_swfw_sync_X540(hw, rmask);
829283620Serj		ixgbe_release_swfw_sync_semaphore(hw);
830283620Serj		return IXGBE_ERR_SWFW_SYNC;
831251964Sjfv	}
832283620Serj	ixgbe_release_swfw_sync_semaphore(hw);
833230775Sjfv
834283620Serj	return IXGBE_ERR_SWFW_SYNC;
835230775Sjfv}
836230775Sjfv
837230775Sjfv/**
838230775Sjfv *  ixgbe_release_swfw_sync_X540 - Release SWFW semaphore
839230775Sjfv *  @hw: pointer to hardware structure
840230775Sjfv *  @mask: Mask to specify which semaphore to release
841230775Sjfv *
842238149Sjfv *  Releases the SWFW semaphore through the SW_FW_SYNC register
843230775Sjfv *  for the specified function (CSR, PHY0, PHY1, EVM, Flash)
844230775Sjfv **/
845283620Serjvoid ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
846230775Sjfv{
847283620Serj	u32 swmask = mask & (IXGBE_GSSR_NVM_PHY_MASK | IXGBE_GSSR_SW_MNG_SM);
848230775Sjfv	u32 swfw_sync;
849230775Sjfv
850230775Sjfv	DEBUGFUNC("ixgbe_release_swfw_sync_X540");
851230775Sjfv
852283620Serj	if (mask & IXGBE_GSSR_I2C_MASK)
853283620Serj		swmask |= mask & IXGBE_GSSR_I2C_MASK;
854230775Sjfv	ixgbe_get_swfw_sync_semaphore(hw);
855230775Sjfv
856295524Ssbruno	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
857230775Sjfv	swfw_sync &= ~swmask;
858295524Ssbruno	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
859230775Sjfv
860230775Sjfv	ixgbe_release_swfw_sync_semaphore(hw);
861283620Serj	msec_delay(5);
862230775Sjfv}
863230775Sjfv
864230775Sjfv/**
865283620Serj *  ixgbe_get_swfw_sync_semaphore - Get hardware semaphore
866230775Sjfv *  @hw: pointer to hardware structure
867230775Sjfv *
868230775Sjfv *  Sets the hardware semaphores so SW/FW can gain control of shared resources
869230775Sjfv **/
870230775Sjfvstatic s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
871230775Sjfv{
872230775Sjfv	s32 status = IXGBE_ERR_EEPROM;
873230775Sjfv	u32 timeout = 2000;
874230775Sjfv	u32 i;
875230775Sjfv	u32 swsm;
876230775Sjfv
877230775Sjfv	DEBUGFUNC("ixgbe_get_swfw_sync_semaphore");
878230775Sjfv
879230775Sjfv	/* Get SMBI software semaphore between device drivers first */
880230775Sjfv	for (i = 0; i < timeout; i++) {
881230775Sjfv		/*
882230775Sjfv		 * If the SMBI bit is 0 when we read it, then the bit will be
883230775Sjfv		 * set and we have the semaphore
884230775Sjfv		 */
885295524Ssbruno		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
886230775Sjfv		if (!(swsm & IXGBE_SWSM_SMBI)) {
887230775Sjfv			status = IXGBE_SUCCESS;
888230775Sjfv			break;
889230775Sjfv		}
890230775Sjfv		usec_delay(50);
891230775Sjfv	}
892230775Sjfv
893230775Sjfv	/* Now get the semaphore between SW/FW through the REGSMP bit */
894230775Sjfv	if (status == IXGBE_SUCCESS) {
895230775Sjfv		for (i = 0; i < timeout; i++) {
896295524Ssbruno			swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
897230775Sjfv			if (!(swsm & IXGBE_SWFW_REGSMP))
898230775Sjfv				break;
899230775Sjfv
900230775Sjfv			usec_delay(50);
901230775Sjfv		}
902230775Sjfv
903230775Sjfv		/*
904230775Sjfv		 * Release semaphores and return error if SW NVM semaphore
905230775Sjfv		 * was not granted because we don't have access to the EEPROM
906230775Sjfv		 */
907230775Sjfv		if (i >= timeout) {
908251964Sjfv			ERROR_REPORT1(IXGBE_ERROR_POLLING,
909251964Sjfv				"REGSMP Software NVM semaphore not granted.\n");
910230775Sjfv			ixgbe_release_swfw_sync_semaphore(hw);
911230775Sjfv			status = IXGBE_ERR_EEPROM;
912230775Sjfv		}
913230775Sjfv	} else {
914251964Sjfv		ERROR_REPORT1(IXGBE_ERROR_POLLING,
915251964Sjfv			     "Software semaphore SMBI between device drivers "
916251964Sjfv			     "not granted.\n");
917230775Sjfv	}
918230775Sjfv
919230775Sjfv	return status;
920230775Sjfv}
921230775Sjfv
922230775Sjfv/**
923283620Serj *  ixgbe_release_swfw_sync_semaphore - Release hardware semaphore
924230775Sjfv *  @hw: pointer to hardware structure
925230775Sjfv *
926230775Sjfv *  This function clears hardware semaphore bits.
927230775Sjfv **/
928230775Sjfvstatic void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw)
929230775Sjfv{
930230775Sjfv	u32 swsm;
931230775Sjfv
932230775Sjfv	DEBUGFUNC("ixgbe_release_swfw_sync_semaphore");
933230775Sjfv
934230775Sjfv	/* Release both semaphores by writing 0 to the bits REGSMP and SMBI */
935230775Sjfv
936295524Ssbruno	swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
937283620Serj	swsm &= ~IXGBE_SWFW_REGSMP;
938295524Ssbruno	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swsm);
939283620Serj
940295524Ssbruno	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
941230775Sjfv	swsm &= ~IXGBE_SWSM_SMBI;
942295524Ssbruno	IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm);
943230775Sjfv
944230775Sjfv	IXGBE_WRITE_FLUSH(hw);
945230775Sjfv}
946230775Sjfv
947230775Sjfv/**
948230775Sjfv * ixgbe_blink_led_start_X540 - Blink LED based on index.
949230775Sjfv * @hw: pointer to hardware structure
950230775Sjfv * @index: led number to blink
951230775Sjfv *
952230775Sjfv * Devices that implement the version 2 interface:
953230775Sjfv *   X540
954230775Sjfv **/
955230775Sjfvs32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index)
956230775Sjfv{
957230775Sjfv	u32 macc_reg;
958230775Sjfv	u32 ledctl_reg;
959230775Sjfv	ixgbe_link_speed speed;
960230775Sjfv	bool link_up;
961230775Sjfv
962230775Sjfv	DEBUGFUNC("ixgbe_blink_led_start_X540");
963230775Sjfv
964230775Sjfv	/*
965230775Sjfv	 * Link should be up in order for the blink bit in the LED control
966230775Sjfv	 * register to work. Force link and speed in the MAC if link is down.
967230775Sjfv	 * This will be reversed when we stop the blinking.
968230775Sjfv	 */
969230775Sjfv	hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
970230775Sjfv	if (link_up == FALSE) {
971230775Sjfv		macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
972230775Sjfv		macc_reg |= IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS;
973230775Sjfv		IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
974230775Sjfv	}
975230775Sjfv	/* Set the LED to LINK_UP + BLINK. */
976230775Sjfv	ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
977230775Sjfv	ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
978230775Sjfv	ledctl_reg |= IXGBE_LED_BLINK(index);
979230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
980230775Sjfv	IXGBE_WRITE_FLUSH(hw);
981230775Sjfv
982230775Sjfv	return IXGBE_SUCCESS;
983230775Sjfv}
984230775Sjfv
985230775Sjfv/**
986230775Sjfv * ixgbe_blink_led_stop_X540 - Stop blinking LED based on index.
987230775Sjfv * @hw: pointer to hardware structure
988230775Sjfv * @index: led number to stop blinking
989230775Sjfv *
990230775Sjfv * Devices that implement the version 2 interface:
991230775Sjfv *   X540
992230775Sjfv **/
993230775Sjfvs32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index)
994230775Sjfv{
995230775Sjfv	u32 macc_reg;
996230775Sjfv	u32 ledctl_reg;
997230775Sjfv
998230775Sjfv	DEBUGFUNC("ixgbe_blink_led_stop_X540");
999230775Sjfv
1000230775Sjfv	/* Restore the LED to its default value. */
1001230775Sjfv	ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
1002230775Sjfv	ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
1003230775Sjfv	ledctl_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
1004230775Sjfv	ledctl_reg &= ~IXGBE_LED_BLINK(index);
1005230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
1006230775Sjfv
1007230775Sjfv	/* Unforce link and speed in the MAC. */
1008230775Sjfv	macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
1009230775Sjfv	macc_reg &= ~(IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS);
1010230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
1011230775Sjfv	IXGBE_WRITE_FLUSH(hw);
1012230775Sjfv
1013230775Sjfv	return IXGBE_SUCCESS;
1014230775Sjfv}
1015