ixgbe_x540.c revision 238149
1230775Sjfv/******************************************************************************
2230775Sjfv
3230775Sjfv  Copyright (c) 2001-2012, 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: head/sys/dev/ixgbe/ixgbe_x540.c 238149 2012-07-05 20:51:44Z jfv $*/
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
41230775Sjfvstatic s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw);
42230775Sjfvstatic s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw);
43230775Sjfvstatic s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw);
44230775Sjfvstatic void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw);
45230775Sjfv
46230775Sjfv/**
47230775Sjfv *  ixgbe_init_ops_X540 - Inits func ptrs and MAC type
48230775Sjfv *  @hw: pointer to hardware structure
49230775Sjfv *
50230775Sjfv *  Initialize the function pointers and assign the MAC type for X540.
51230775Sjfv *  Does not touch the hardware.
52230775Sjfv **/
53230775Sjfvs32 ixgbe_init_ops_X540(struct ixgbe_hw *hw)
54230775Sjfv{
55230775Sjfv	struct ixgbe_mac_info *mac = &hw->mac;
56230775Sjfv	struct ixgbe_phy_info *phy = &hw->phy;
57230775Sjfv	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
58230775Sjfv	s32 ret_val;
59230775Sjfv
60230775Sjfv	DEBUGFUNC("ixgbe_init_ops_X540");
61230775Sjfv
62230775Sjfv	ret_val = ixgbe_init_phy_ops_generic(hw);
63230775Sjfv	ret_val = ixgbe_init_ops_generic(hw);
64230775Sjfv
65230775Sjfv
66230775Sjfv	/* EEPROM */
67230775Sjfv	eeprom->ops.init_params = &ixgbe_init_eeprom_params_X540;
68230775Sjfv	eeprom->ops.read = &ixgbe_read_eerd_X540;
69230775Sjfv	eeprom->ops.read_buffer = &ixgbe_read_eerd_buffer_X540;
70230775Sjfv	eeprom->ops.write = &ixgbe_write_eewr_X540;
71230775Sjfv	eeprom->ops.write_buffer = &ixgbe_write_eewr_buffer_X540;
72230775Sjfv	eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_X540;
73230775Sjfv	eeprom->ops.validate_checksum = &ixgbe_validate_eeprom_checksum_X540;
74230775Sjfv	eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_X540;
75230775Sjfv
76230775Sjfv	/* PHY */
77230775Sjfv	phy->ops.init = &ixgbe_init_phy_ops_generic;
78230775Sjfv	phy->ops.reset = NULL;
79230775Sjfv
80230775Sjfv	/* MAC */
81230775Sjfv	mac->ops.reset_hw = &ixgbe_reset_hw_X540;
82230775Sjfv	mac->ops.enable_relaxed_ordering = &ixgbe_enable_relaxed_ordering_gen2;
83230775Sjfv	mac->ops.get_media_type = &ixgbe_get_media_type_X540;
84230775Sjfv	mac->ops.get_supported_physical_layer =
85230775Sjfv				    &ixgbe_get_supported_physical_layer_X540;
86230775Sjfv	mac->ops.read_analog_reg8 = NULL;
87230775Sjfv	mac->ops.write_analog_reg8 = NULL;
88230775Sjfv	mac->ops.start_hw = &ixgbe_start_hw_X540;
89230775Sjfv	mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic;
90230775Sjfv	mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_generic;
91230775Sjfv	mac->ops.get_device_caps = &ixgbe_get_device_caps_generic;
92230775Sjfv	mac->ops.get_wwn_prefix = &ixgbe_get_wwn_prefix_generic;
93230775Sjfv	mac->ops.get_fcoe_boot_status = &ixgbe_get_fcoe_boot_status_generic;
94230775Sjfv	mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540;
95230775Sjfv	mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync_X540;
96230775Sjfv	mac->ops.disable_sec_rx_path = &ixgbe_disable_sec_rx_path_generic;
97230775Sjfv	mac->ops.enable_sec_rx_path = &ixgbe_enable_sec_rx_path_generic;
98230775Sjfv
99230775Sjfv	/* RAR, Multicast, VLAN */
100230775Sjfv	mac->ops.set_vmdq = &ixgbe_set_vmdq_generic;
101238149Sjfv	mac->ops.set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic;
102230775Sjfv	mac->ops.clear_vmdq = &ixgbe_clear_vmdq_generic;
103230775Sjfv	mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic;
104230775Sjfv	mac->rar_highwater = 1;
105230775Sjfv	mac->ops.set_vfta = &ixgbe_set_vfta_generic;
106230775Sjfv	mac->ops.set_vlvf = &ixgbe_set_vlvf_generic;
107230775Sjfv	mac->ops.clear_vfta = &ixgbe_clear_vfta_generic;
108230775Sjfv	mac->ops.init_uta_tables = &ixgbe_init_uta_tables_generic;
109230775Sjfv	mac->ops.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing;
110230775Sjfv	mac->ops.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing;
111230775Sjfv
112230775Sjfv	/* Link */
113230775Sjfv	mac->ops.get_link_capabilities =
114230775Sjfv				&ixgbe_get_copper_link_capabilities_generic;
115230775Sjfv	mac->ops.setup_link = &ixgbe_setup_mac_link_X540;
116230775Sjfv	mac->ops.setup_rxpba = &ixgbe_set_rxpba_generic;
117230775Sjfv	mac->ops.check_link = &ixgbe_check_mac_link_generic;
118230775Sjfv
119230775Sjfv	mac->mcft_size		= 128;
120230775Sjfv	mac->vft_size		= 128;
121230775Sjfv	mac->num_rar_entries	= 128;
122230775Sjfv	mac->rx_pb_size		= 384;
123230775Sjfv	mac->max_tx_queues	= 128;
124230775Sjfv	mac->max_rx_queues	= 128;
125230775Sjfv	mac->max_msix_vectors	= ixgbe_get_pcie_msix_count_generic(hw);
126230775Sjfv
127230775Sjfv	/*
128230775Sjfv	 * FWSM register
129230775Sjfv	 * ARC supported; valid only if manageability features are
130230775Sjfv	 * enabled.
131230775Sjfv	 */
132230775Sjfv	mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) &
133230775Sjfv				   IXGBE_FWSM_MODE_MASK) ? TRUE : FALSE;
134230775Sjfv
135230775Sjfv	hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
136230775Sjfv
137230775Sjfv	/* LEDs */
138230775Sjfv	mac->ops.blink_led_start = ixgbe_blink_led_start_X540;
139230775Sjfv	mac->ops.blink_led_stop = ixgbe_blink_led_stop_X540;
140230775Sjfv
141230775Sjfv	/* Manageability interface */
142230775Sjfv	mac->ops.set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic;
143230775Sjfv
144230775Sjfv	return ret_val;
145230775Sjfv}
146230775Sjfv
147230775Sjfv/**
148230775Sjfv *  ixgbe_get_link_capabilities_X540 - Determines link capabilities
149230775Sjfv *  @hw: pointer to hardware structure
150230775Sjfv *  @speed: pointer to link speed
151230775Sjfv *  @autoneg: TRUE when autoneg or autotry is enabled
152230775Sjfv *
153230775Sjfv *  Determines the link capabilities by reading the AUTOC register.
154230775Sjfv **/
155230775Sjfvs32 ixgbe_get_link_capabilities_X540(struct ixgbe_hw *hw,
156230775Sjfv				     ixgbe_link_speed *speed,
157230775Sjfv				     bool *autoneg)
158230775Sjfv{
159230775Sjfv	ixgbe_get_copper_link_capabilities_generic(hw, speed, autoneg);
160230775Sjfv
161230775Sjfv	return IXGBE_SUCCESS;
162230775Sjfv}
163230775Sjfv
164230775Sjfv/**
165230775Sjfv *  ixgbe_get_media_type_X540 - Get media type
166230775Sjfv *  @hw: pointer to hardware structure
167230775Sjfv *
168230775Sjfv *  Returns the media type (fiber, copper, backplane)
169230775Sjfv **/
170230775Sjfvenum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw)
171230775Sjfv{
172230775Sjfv	UNREFERENCED_1PARAMETER(hw);
173230775Sjfv	return ixgbe_media_type_copper;
174230775Sjfv}
175230775Sjfv
176230775Sjfv/**
177230775Sjfv *  ixgbe_setup_mac_link_X540 - Sets the auto advertised capabilities
178230775Sjfv *  @hw: pointer to hardware structure
179230775Sjfv *  @speed: new link speed
180230775Sjfv *  @autoneg: TRUE if autonegotiation enabled
181230775Sjfv *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
182230775Sjfv **/
183230775Sjfvs32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw,
184230775Sjfv			      ixgbe_link_speed speed, bool autoneg,
185230775Sjfv			      bool autoneg_wait_to_complete)
186230775Sjfv{
187230775Sjfv	DEBUGFUNC("ixgbe_setup_mac_link_X540");
188230775Sjfv	return hw->phy.ops.setup_link_speed(hw, speed, autoneg,
189230775Sjfv					    autoneg_wait_to_complete);
190230775Sjfv}
191230775Sjfv
192230775Sjfv/**
193230775Sjfv *  ixgbe_reset_hw_X540 - Perform hardware reset
194230775Sjfv *  @hw: pointer to hardware structure
195230775Sjfv *
196230775Sjfv *  Resets the hardware by resetting the transmit and receive units, masks
197230775Sjfv *  and clears all interrupts, and perform a reset.
198230775Sjfv **/
199230775Sjfvs32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
200230775Sjfv{
201230775Sjfv	s32 status;
202230775Sjfv	u32 ctrl, i;
203230775Sjfv
204230775Sjfv	DEBUGFUNC("ixgbe_reset_hw_X540");
205230775Sjfv
206230775Sjfv	/* Call adapter stop to disable tx/rx and clear interrupts */
207230775Sjfv	status = hw->mac.ops.stop_adapter(hw);
208230775Sjfv	if (status != IXGBE_SUCCESS)
209230775Sjfv		goto reset_hw_out;
210230775Sjfv
211230775Sjfv	/* flush pending Tx transactions */
212230775Sjfv	ixgbe_clear_tx_pending(hw);
213230775Sjfv
214230775Sjfvmac_reset_top:
215230775Sjfv	ctrl = IXGBE_CTRL_RST;
216230775Sjfv	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
217230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
218230775Sjfv	IXGBE_WRITE_FLUSH(hw);
219230775Sjfv
220230775Sjfv	/* Poll for reset bit to self-clear indicating reset is complete */
221230775Sjfv	for (i = 0; i < 10; i++) {
222230775Sjfv		usec_delay(1);
223230775Sjfv		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
224230775Sjfv		if (!(ctrl & IXGBE_CTRL_RST_MASK))
225230775Sjfv			break;
226230775Sjfv	}
227230775Sjfv
228230775Sjfv	if (ctrl & IXGBE_CTRL_RST_MASK) {
229230775Sjfv		status = IXGBE_ERR_RESET_FAILED;
230230775Sjfv		DEBUGOUT("Reset polling failed to complete.\n");
231230775Sjfv	}
232230775Sjfv	msec_delay(100);
233230775Sjfv
234230775Sjfv	/*
235230775Sjfv	 * Double resets are required for recovery from certain error
236230775Sjfv	 * conditions.  Between resets, it is necessary to stall to allow time
237230775Sjfv	 * for any pending HW events to complete.
238230775Sjfv	 */
239230775Sjfv	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
240230775Sjfv		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
241230775Sjfv		goto mac_reset_top;
242230775Sjfv	}
243230775Sjfv
244230775Sjfv	/* Set the Rx packet buffer size. */
245230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT);
246230775Sjfv
247230775Sjfv	/* Store the permanent mac address */
248230775Sjfv	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
249230775Sjfv
250230775Sjfv	/*
251230775Sjfv	 * Store MAC address from RAR0, clear receive address registers, and
252230775Sjfv	 * clear the multicast table.  Also reset num_rar_entries to 128,
253230775Sjfv	 * since we modify this value when programming the SAN MAC address.
254230775Sjfv	 */
255230775Sjfv	hw->mac.num_rar_entries = 128;
256230775Sjfv	hw->mac.ops.init_rx_addrs(hw);
257230775Sjfv
258230775Sjfv	/* Store the permanent SAN mac address */
259230775Sjfv	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
260230775Sjfv
261230775Sjfv	/* Add the SAN MAC address to the RAR only if it's a valid address */
262230775Sjfv	if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
263230775Sjfv		hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
264230775Sjfv				    hw->mac.san_addr, 0, IXGBE_RAH_AV);
265230775Sjfv
266238149Sjfv		/* Save the SAN MAC RAR index */
267238149Sjfv		hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
268238149Sjfv
269230775Sjfv		/* Reserve the last RAR for the SAN MAC address */
270230775Sjfv		hw->mac.num_rar_entries--;
271230775Sjfv	}
272230775Sjfv
273230775Sjfv	/* Store the alternative WWNN/WWPN prefix */
274230775Sjfv	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
275230775Sjfv				   &hw->mac.wwpn_prefix);
276230775Sjfv
277230775Sjfvreset_hw_out:
278230775Sjfv	return status;
279230775Sjfv}
280230775Sjfv
281230775Sjfv/**
282230775Sjfv *  ixgbe_start_hw_X540 - Prepare hardware for Tx/Rx
283230775Sjfv *  @hw: pointer to hardware structure
284230775Sjfv *
285230775Sjfv *  Starts the hardware using the generic start_hw function
286230775Sjfv *  and the generation start_hw function.
287230775Sjfv *  Then performs revision-specific operations, if any.
288230775Sjfv **/
289230775Sjfvs32 ixgbe_start_hw_X540(struct ixgbe_hw *hw)
290230775Sjfv{
291230775Sjfv	s32 ret_val = IXGBE_SUCCESS;
292230775Sjfv
293230775Sjfv	DEBUGFUNC("ixgbe_start_hw_X540");
294230775Sjfv
295230775Sjfv	ret_val = ixgbe_start_hw_generic(hw);
296230775Sjfv	if (ret_val != IXGBE_SUCCESS)
297230775Sjfv		goto out;
298230775Sjfv
299230775Sjfv	ret_val = ixgbe_start_hw_gen2(hw);
300230775Sjfv
301230775Sjfvout:
302230775Sjfv	return ret_val;
303230775Sjfv}
304230775Sjfv
305230775Sjfv/**
306230775Sjfv *  ixgbe_get_supported_physical_layer_X540 - Returns physical layer type
307230775Sjfv *  @hw: pointer to hardware structure
308230775Sjfv *
309230775Sjfv *  Determines physical layer capabilities of the current configuration.
310230775Sjfv **/
311230775Sjfvu32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
312230775Sjfv{
313230775Sjfv	u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
314230775Sjfv	u16 ext_ability = 0;
315230775Sjfv
316230775Sjfv	DEBUGFUNC("ixgbe_get_supported_physical_layer_X540");
317230775Sjfv
318230775Sjfv	hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
319230775Sjfv	IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
320230775Sjfv	if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
321230775Sjfv		physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
322230775Sjfv	if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
323230775Sjfv		physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
324230775Sjfv	if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
325230775Sjfv		physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
326230775Sjfv
327230775Sjfv	return physical_layer;
328230775Sjfv}
329230775Sjfv
330230775Sjfv/**
331230775Sjfv *  ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
332230775Sjfv *  @hw: pointer to hardware structure
333230775Sjfv *
334230775Sjfv *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
335230775Sjfv *  ixgbe_hw struct in order to set up EEPROM access.
336230775Sjfv **/
337230775Sjfvs32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
338230775Sjfv{
339230775Sjfv	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
340230775Sjfv	u32 eec;
341230775Sjfv	u16 eeprom_size;
342230775Sjfv
343230775Sjfv	DEBUGFUNC("ixgbe_init_eeprom_params_X540");
344230775Sjfv
345230775Sjfv	if (eeprom->type == ixgbe_eeprom_uninitialized) {
346230775Sjfv		eeprom->semaphore_delay = 10;
347230775Sjfv		eeprom->type = ixgbe_flash;
348230775Sjfv
349230775Sjfv		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
350230775Sjfv		eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
351230775Sjfv				    IXGBE_EEC_SIZE_SHIFT);
352230775Sjfv		eeprom->word_size = 1 << (eeprom_size +
353230775Sjfv					  IXGBE_EEPROM_WORD_SIZE_SHIFT);
354230775Sjfv
355230775Sjfv		DEBUGOUT2("Eeprom params: type = %d, size = %d\n",
356230775Sjfv			  eeprom->type, eeprom->word_size);
357230775Sjfv	}
358230775Sjfv
359230775Sjfv	return IXGBE_SUCCESS;
360230775Sjfv}
361230775Sjfv
362230775Sjfv/**
363230775Sjfv *  ixgbe_read_eerd_X540- Read EEPROM word using EERD
364230775Sjfv *  @hw: pointer to hardware structure
365230775Sjfv *  @offset: offset of  word in the EEPROM to read
366230775Sjfv *  @data: word read from the EEPROM
367230775Sjfv *
368230775Sjfv *  Reads a 16 bit word from the EEPROM using the EERD register.
369230775Sjfv **/
370230775Sjfvs32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
371230775Sjfv{
372230775Sjfv	s32 status = IXGBE_SUCCESS;
373230775Sjfv
374230775Sjfv	DEBUGFUNC("ixgbe_read_eerd_X540");
375230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
376230775Sjfv	    IXGBE_SUCCESS)
377230775Sjfv		status = ixgbe_read_eerd_generic(hw, offset, data);
378230775Sjfv	else
379230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
380230775Sjfv
381230775Sjfv	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
382230775Sjfv	return status;
383230775Sjfv}
384230775Sjfv
385230775Sjfv/**
386230775Sjfv *  ixgbe_read_eerd_buffer_X540- Read EEPROM word(s) using EERD
387230775Sjfv *  @hw: pointer to hardware structure
388230775Sjfv *  @offset: offset of  word in the EEPROM to read
389230775Sjfv *  @words: number of words
390230775Sjfv *  @data: word(s) read from the EEPROM
391230775Sjfv *
392230775Sjfv *  Reads a 16 bit word(s) from the EEPROM using the EERD register.
393230775Sjfv **/
394230775Sjfvs32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw,
395230775Sjfv				u16 offset, u16 words, u16 *data)
396230775Sjfv{
397230775Sjfv	s32 status = IXGBE_SUCCESS;
398230775Sjfv
399230775Sjfv	DEBUGFUNC("ixgbe_read_eerd_buffer_X540");
400230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
401230775Sjfv	    IXGBE_SUCCESS)
402230775Sjfv		status = ixgbe_read_eerd_buffer_generic(hw, offset,
403230775Sjfv							words, data);
404230775Sjfv	else
405230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
406230775Sjfv
407230775Sjfv	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
408230775Sjfv	return status;
409230775Sjfv}
410230775Sjfv
411230775Sjfv/**
412230775Sjfv *  ixgbe_write_eewr_X540 - Write EEPROM word using EEWR
413230775Sjfv *  @hw: pointer to hardware structure
414230775Sjfv *  @offset: offset of  word in the EEPROM to write
415230775Sjfv *  @data: word write to the EEPROM
416230775Sjfv *
417230775Sjfv *  Write a 16 bit word to the EEPROM using the EEWR register.
418230775Sjfv **/
419230775Sjfvs32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
420230775Sjfv{
421230775Sjfv	s32 status = IXGBE_SUCCESS;
422230775Sjfv
423230775Sjfv	DEBUGFUNC("ixgbe_write_eewr_X540");
424230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
425230775Sjfv	    IXGBE_SUCCESS)
426230775Sjfv		status = ixgbe_write_eewr_generic(hw, offset, data);
427230775Sjfv	else
428230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
429230775Sjfv
430230775Sjfv	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
431230775Sjfv	return status;
432230775Sjfv}
433230775Sjfv
434230775Sjfv/**
435230775Sjfv *  ixgbe_write_eewr_buffer_X540 - Write EEPROM word(s) using EEWR
436230775Sjfv *  @hw: pointer to hardware structure
437230775Sjfv *  @offset: offset of  word in the EEPROM to write
438230775Sjfv *  @words: number of words
439230775Sjfv *  @data: word(s) write to the EEPROM
440230775Sjfv *
441230775Sjfv *  Write a 16 bit word(s) to the EEPROM using the EEWR register.
442230775Sjfv **/
443230775Sjfvs32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
444230775Sjfv				 u16 offset, u16 words, u16 *data)
445230775Sjfv{
446230775Sjfv	s32 status = IXGBE_SUCCESS;
447230775Sjfv
448230775Sjfv	DEBUGFUNC("ixgbe_write_eewr_buffer_X540");
449230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
450230775Sjfv	    IXGBE_SUCCESS)
451230775Sjfv		status = ixgbe_write_eewr_buffer_generic(hw, offset,
452230775Sjfv							 words, data);
453230775Sjfv	else
454230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
455230775Sjfv
456230775Sjfv	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
457230775Sjfv	return status;
458230775Sjfv}
459230775Sjfv
460230775Sjfv/**
461230775Sjfv *  ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum
462230775Sjfv *
463230775Sjfv *  This function does not use synchronization for EERD and EEWR. It can
464230775Sjfv *  be used internally by function which utilize ixgbe_acquire_swfw_sync_X540.
465230775Sjfv *
466230775Sjfv *  @hw: pointer to hardware structure
467230775Sjfv **/
468230775Sjfvu16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
469230775Sjfv{
470230775Sjfv	u16 i;
471230775Sjfv	u16 j;
472230775Sjfv	u16 checksum = 0;
473230775Sjfv	u16 length = 0;
474230775Sjfv	u16 pointer = 0;
475230775Sjfv	u16 word = 0;
476230775Sjfv
477230775Sjfv	/*
478230775Sjfv	 * Do not use hw->eeprom.ops.read because we do not want to take
479230775Sjfv	 * the synchronization semaphores here. Instead use
480230775Sjfv	 * ixgbe_read_eerd_generic
481230775Sjfv	 */
482230775Sjfv
483230775Sjfv	DEBUGFUNC("ixgbe_calc_eeprom_checksum_X540");
484230775Sjfv
485230775Sjfv	/* Include 0x0-0x3F in the checksum */
486230775Sjfv	for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
487230775Sjfv		if (ixgbe_read_eerd_generic(hw, i, &word) != IXGBE_SUCCESS) {
488230775Sjfv			DEBUGOUT("EEPROM read failed\n");
489230775Sjfv			break;
490230775Sjfv		}
491230775Sjfv		checksum += word;
492230775Sjfv	}
493230775Sjfv
494230775Sjfv	/*
495230775Sjfv	 * Include all data from pointers 0x3, 0x6-0xE.  This excludes the
496230775Sjfv	 * FW, PHY module, and PCIe Expansion/Option ROM pointers.
497230775Sjfv	 */
498230775Sjfv	for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
499230775Sjfv		if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
500230775Sjfv			continue;
501230775Sjfv
502230775Sjfv		if (ixgbe_read_eerd_generic(hw, i, &pointer) != IXGBE_SUCCESS) {
503230775Sjfv			DEBUGOUT("EEPROM read failed\n");
504230775Sjfv			break;
505230775Sjfv		}
506230775Sjfv
507230775Sjfv		/* Skip pointer section if the pointer is invalid. */
508230775Sjfv		if (pointer == 0xFFFF || pointer == 0 ||
509230775Sjfv		    pointer >= hw->eeprom.word_size)
510230775Sjfv			continue;
511230775Sjfv
512230775Sjfv		if (ixgbe_read_eerd_generic(hw, pointer, &length) !=
513230775Sjfv		    IXGBE_SUCCESS) {
514230775Sjfv			DEBUGOUT("EEPROM read failed\n");
515230775Sjfv			break;
516230775Sjfv		}
517230775Sjfv
518230775Sjfv		/* Skip pointer section if length is invalid. */
519230775Sjfv		if (length == 0xFFFF || length == 0 ||
520230775Sjfv		    (pointer + length) >= hw->eeprom.word_size)
521230775Sjfv			continue;
522230775Sjfv
523230775Sjfv		for (j = pointer+1; j <= pointer+length; j++) {
524230775Sjfv			if (ixgbe_read_eerd_generic(hw, j, &word) !=
525230775Sjfv			    IXGBE_SUCCESS) {
526230775Sjfv				DEBUGOUT("EEPROM read failed\n");
527230775Sjfv				break;
528230775Sjfv			}
529230775Sjfv			checksum += word;
530230775Sjfv		}
531230775Sjfv	}
532230775Sjfv
533230775Sjfv	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
534230775Sjfv
535230775Sjfv	return checksum;
536230775Sjfv}
537230775Sjfv
538230775Sjfv/**
539230775Sjfv *  ixgbe_validate_eeprom_checksum_X540 - Validate EEPROM checksum
540230775Sjfv *  @hw: pointer to hardware structure
541230775Sjfv *  @checksum_val: calculated checksum
542230775Sjfv *
543230775Sjfv *  Performs checksum calculation and validates the EEPROM checksum.  If the
544230775Sjfv *  caller does not need checksum_val, the value can be NULL.
545230775Sjfv **/
546230775Sjfvs32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw,
547230775Sjfv					u16 *checksum_val)
548230775Sjfv{
549230775Sjfv	s32 status;
550230775Sjfv	u16 checksum;
551230775Sjfv	u16 read_checksum = 0;
552230775Sjfv
553230775Sjfv	DEBUGFUNC("ixgbe_validate_eeprom_checksum_X540");
554230775Sjfv
555230775Sjfv	/*
556230775Sjfv	 * Read the first word from the EEPROM. If this times out or fails, do
557230775Sjfv	 * not continue or we could be in for a very long wait while every
558230775Sjfv	 * EEPROM read fails
559230775Sjfv	 */
560230775Sjfv	status = hw->eeprom.ops.read(hw, 0, &checksum);
561230775Sjfv
562230775Sjfv	if (status != IXGBE_SUCCESS) {
563230775Sjfv		DEBUGOUT("EEPROM read failed\n");
564230775Sjfv		goto out;
565230775Sjfv	}
566230775Sjfv
567230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
568230775Sjfv	    IXGBE_SUCCESS) {
569230775Sjfv		checksum = hw->eeprom.ops.calc_checksum(hw);
570230775Sjfv
571230775Sjfv		/*
572230775Sjfv		 * Do not use hw->eeprom.ops.read because we do not want to take
573230775Sjfv		 * the synchronization semaphores twice here.
574230775Sjfv		*/
575230775Sjfv		ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
576230775Sjfv					&read_checksum);
577230775Sjfv
578230775Sjfv		/*
579230775Sjfv		 * Verify read checksum from EEPROM is the same as
580230775Sjfv		 * calculated checksum
581230775Sjfv		 */
582230775Sjfv		if (read_checksum != checksum)
583230775Sjfv			status = IXGBE_ERR_EEPROM_CHECKSUM;
584230775Sjfv
585230775Sjfv		/* If the user cares, return the calculated checksum */
586230775Sjfv		if (checksum_val)
587230775Sjfv			*checksum_val = checksum;
588230775Sjfv	} else {
589230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
590230775Sjfv	}
591230775Sjfv
592230775Sjfv	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
593230775Sjfvout:
594230775Sjfv	return status;
595230775Sjfv}
596230775Sjfv
597230775Sjfv/**
598230775Sjfv * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash
599230775Sjfv * @hw: pointer to hardware structure
600230775Sjfv *
601230775Sjfv * After writing EEPROM to shadow RAM using EEWR register, software calculates
602230775Sjfv * checksum and updates the EEPROM and instructs the hardware to update
603230775Sjfv * the flash.
604230775Sjfv **/
605230775Sjfvs32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
606230775Sjfv{
607230775Sjfv	s32 status;
608230775Sjfv	u16 checksum;
609230775Sjfv
610230775Sjfv	DEBUGFUNC("ixgbe_update_eeprom_checksum_X540");
611230775Sjfv
612230775Sjfv	/*
613230775Sjfv	 * Read the first word from the EEPROM. If this times out or fails, do
614230775Sjfv	 * not continue or we could be in for a very long wait while every
615230775Sjfv	 * EEPROM read fails
616230775Sjfv	 */
617230775Sjfv	status = hw->eeprom.ops.read(hw, 0, &checksum);
618230775Sjfv
619230775Sjfv	if (status != IXGBE_SUCCESS)
620230775Sjfv		DEBUGOUT("EEPROM read failed\n");
621230775Sjfv
622230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
623230775Sjfv	    IXGBE_SUCCESS) {
624230775Sjfv		checksum = hw->eeprom.ops.calc_checksum(hw);
625230775Sjfv
626230775Sjfv		/*
627230775Sjfv		 * Do not use hw->eeprom.ops.write because we do not want to
628230775Sjfv		 * take the synchronization semaphores twice here.
629230775Sjfv		*/
630230775Sjfv		status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM,
631230775Sjfv						  checksum);
632230775Sjfv
633230775Sjfv	if (status == IXGBE_SUCCESS)
634230775Sjfv		status = ixgbe_update_flash_X540(hw);
635230775Sjfv	else
636230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
637230775Sjfv	}
638230775Sjfv
639230775Sjfv	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
640230775Sjfv
641230775Sjfv	return status;
642230775Sjfv}
643230775Sjfv
644230775Sjfv/**
645230775Sjfv *  ixgbe_update_flash_X540 - Instruct HW to copy EEPROM to Flash device
646230775Sjfv *  @hw: pointer to hardware structure
647230775Sjfv *
648230775Sjfv *  Set FLUP (bit 23) of the EEC register to instruct Hardware to copy
649230775Sjfv *  EEPROM from shadow RAM to the flash device.
650230775Sjfv **/
651230775Sjfvstatic s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
652230775Sjfv{
653230775Sjfv	u32 flup;
654230775Sjfv	s32 status = IXGBE_ERR_EEPROM;
655230775Sjfv
656230775Sjfv	DEBUGFUNC("ixgbe_update_flash_X540");
657230775Sjfv
658230775Sjfv	status = ixgbe_poll_flash_update_done_X540(hw);
659230775Sjfv	if (status == IXGBE_ERR_EEPROM) {
660230775Sjfv		DEBUGOUT("Flash update time out\n");
661230775Sjfv		goto out;
662230775Sjfv	}
663230775Sjfv
664230775Sjfv	flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP;
665230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
666230775Sjfv
667230775Sjfv	status = ixgbe_poll_flash_update_done_X540(hw);
668230775Sjfv	if (status == IXGBE_SUCCESS)
669230775Sjfv		DEBUGOUT("Flash update complete\n");
670230775Sjfv	else
671230775Sjfv		DEBUGOUT("Flash update time out\n");
672230775Sjfv
673230775Sjfv	if (hw->revision_id == 0) {
674230775Sjfv		flup = IXGBE_READ_REG(hw, IXGBE_EEC);
675230775Sjfv
676230775Sjfv		if (flup & IXGBE_EEC_SEC1VAL) {
677230775Sjfv			flup |= IXGBE_EEC_FLUP;
678230775Sjfv			IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
679230775Sjfv		}
680230775Sjfv
681230775Sjfv		status = ixgbe_poll_flash_update_done_X540(hw);
682230775Sjfv		if (status == IXGBE_SUCCESS)
683230775Sjfv			DEBUGOUT("Flash update complete\n");
684230775Sjfv		else
685230775Sjfv			DEBUGOUT("Flash update time out\n");
686230775Sjfv	}
687230775Sjfvout:
688230775Sjfv	return status;
689230775Sjfv}
690230775Sjfv
691230775Sjfv/**
692230775Sjfv *  ixgbe_poll_flash_update_done_X540 - Poll flash update status
693230775Sjfv *  @hw: pointer to hardware structure
694230775Sjfv *
695230775Sjfv *  Polls the FLUDONE (bit 26) of the EEC Register to determine when the
696230775Sjfv *  flash update is done.
697230775Sjfv **/
698230775Sjfvstatic s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
699230775Sjfv{
700230775Sjfv	u32 i;
701230775Sjfv	u32 reg;
702230775Sjfv	s32 status = IXGBE_ERR_EEPROM;
703230775Sjfv
704230775Sjfv	DEBUGFUNC("ixgbe_poll_flash_update_done_X540");
705230775Sjfv
706230775Sjfv	for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
707230775Sjfv		reg = IXGBE_READ_REG(hw, IXGBE_EEC);
708230775Sjfv		if (reg & IXGBE_EEC_FLUDONE) {
709230775Sjfv			status = IXGBE_SUCCESS;
710230775Sjfv			break;
711230775Sjfv		}
712230775Sjfv		usec_delay(5);
713230775Sjfv	}
714230775Sjfv	return status;
715230775Sjfv}
716230775Sjfv
717230775Sjfv/**
718230775Sjfv *  ixgbe_acquire_swfw_sync_X540 - Acquire SWFW semaphore
719230775Sjfv *  @hw: pointer to hardware structure
720230775Sjfv *  @mask: Mask to specify which semaphore to acquire
721230775Sjfv *
722230775Sjfv *  Acquires the SWFW semaphore thought the SW_FW_SYNC register for
723230775Sjfv *  the specified function (CSR, PHY0, PHY1, NVM, Flash)
724230775Sjfv **/
725230775Sjfvs32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask)
726230775Sjfv{
727230775Sjfv	u32 swfw_sync;
728230775Sjfv	u32 swmask = mask;
729230775Sjfv	u32 fwmask = mask << 5;
730230775Sjfv	u32 hwmask = 0;
731230775Sjfv	u32 timeout = 200;
732230775Sjfv	u32 i;
733230775Sjfv	s32 ret_val = IXGBE_SUCCESS;
734230775Sjfv
735230775Sjfv	DEBUGFUNC("ixgbe_acquire_swfw_sync_X540");
736230775Sjfv
737230775Sjfv	if (swmask == IXGBE_GSSR_EEP_SM)
738230775Sjfv		hwmask = IXGBE_GSSR_FLASH_SM;
739230775Sjfv
740230775Sjfv	/* SW only mask doesn't have FW bit pair */
741230775Sjfv	if (swmask == IXGBE_GSSR_SW_MNG_SM)
742230775Sjfv		fwmask = 0;
743230775Sjfv
744230775Sjfv	for (i = 0; i < timeout; i++) {
745230775Sjfv		/*
746230775Sjfv		 * SW NVM semaphore bit is used for access to all
747230775Sjfv		 * SW_FW_SYNC bits (not just NVM)
748230775Sjfv		 */
749230775Sjfv		if (ixgbe_get_swfw_sync_semaphore(hw)) {
750230775Sjfv			ret_val = IXGBE_ERR_SWFW_SYNC;
751230775Sjfv			goto out;
752230775Sjfv		}
753230775Sjfv
754230775Sjfv		swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
755230775Sjfv		if (!(swfw_sync & (fwmask | swmask | hwmask))) {
756230775Sjfv			swfw_sync |= swmask;
757230775Sjfv			IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
758230775Sjfv			ixgbe_release_swfw_sync_semaphore(hw);
759230775Sjfv			msec_delay(5);
760230775Sjfv			goto out;
761230775Sjfv		} else {
762230775Sjfv			/*
763230775Sjfv			 * Firmware currently using resource (fwmask), hardware
764230775Sjfv			 * currently using resource (hwmask), or other software
765230775Sjfv			 * thread currently using resource (swmask)
766230775Sjfv			 */
767230775Sjfv			ixgbe_release_swfw_sync_semaphore(hw);
768230775Sjfv			msec_delay(5);
769230775Sjfv		}
770230775Sjfv	}
771230775Sjfv
772230775Sjfv	/* Failed to get SW only semaphore */
773230775Sjfv	if (swmask == IXGBE_GSSR_SW_MNG_SM) {
774230775Sjfv		ret_val = IXGBE_ERR_SWFW_SYNC;
775230775Sjfv		goto out;
776230775Sjfv	}
777230775Sjfv
778230775Sjfv	/* If the resource is not released by the FW/HW the SW can assume that
779230775Sjfv	 * the FW/HW malfunctions. In that case the SW should sets the SW bit(s)
780230775Sjfv	 * of the requested resource(s) while ignoring the corresponding FW/HW
781230775Sjfv	 * bits in the SW_FW_SYNC register.
782230775Sjfv	 */
783230775Sjfv	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
784230775Sjfv	if (swfw_sync & (fwmask | hwmask)) {
785230775Sjfv		if (ixgbe_get_swfw_sync_semaphore(hw)) {
786230775Sjfv			ret_val = IXGBE_ERR_SWFW_SYNC;
787230775Sjfv			goto out;
788230775Sjfv		}
789230775Sjfv
790230775Sjfv		swfw_sync |= swmask;
791230775Sjfv		IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
792230775Sjfv		ixgbe_release_swfw_sync_semaphore(hw);
793230775Sjfv		msec_delay(5);
794230775Sjfv	}
795230775Sjfv
796230775Sjfvout:
797230775Sjfv	return ret_val;
798230775Sjfv}
799230775Sjfv
800230775Sjfv/**
801230775Sjfv *  ixgbe_release_swfw_sync_X540 - Release SWFW semaphore
802230775Sjfv *  @hw: pointer to hardware structure
803230775Sjfv *  @mask: Mask to specify which semaphore to release
804230775Sjfv *
805238149Sjfv *  Releases the SWFW semaphore through the SW_FW_SYNC register
806230775Sjfv *  for the specified function (CSR, PHY0, PHY1, EVM, Flash)
807230775Sjfv **/
808230775Sjfvvoid ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask)
809230775Sjfv{
810230775Sjfv	u32 swfw_sync;
811230775Sjfv	u32 swmask = mask;
812230775Sjfv
813230775Sjfv	DEBUGFUNC("ixgbe_release_swfw_sync_X540");
814230775Sjfv
815230775Sjfv	ixgbe_get_swfw_sync_semaphore(hw);
816230775Sjfv
817230775Sjfv	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
818230775Sjfv	swfw_sync &= ~swmask;
819230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
820230775Sjfv
821230775Sjfv	ixgbe_release_swfw_sync_semaphore(hw);
822230775Sjfv	msec_delay(5);
823230775Sjfv}
824230775Sjfv
825230775Sjfv/**
826230775Sjfv *  ixgbe_get_nvm_semaphore - Get hardware semaphore
827230775Sjfv *  @hw: pointer to hardware structure
828230775Sjfv *
829230775Sjfv *  Sets the hardware semaphores so SW/FW can gain control of shared resources
830230775Sjfv **/
831230775Sjfvstatic s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
832230775Sjfv{
833230775Sjfv	s32 status = IXGBE_ERR_EEPROM;
834230775Sjfv	u32 timeout = 2000;
835230775Sjfv	u32 i;
836230775Sjfv	u32 swsm;
837230775Sjfv
838230775Sjfv	DEBUGFUNC("ixgbe_get_swfw_sync_semaphore");
839230775Sjfv
840230775Sjfv	/* Get SMBI software semaphore between device drivers first */
841230775Sjfv	for (i = 0; i < timeout; i++) {
842230775Sjfv		/*
843230775Sjfv		 * If the SMBI bit is 0 when we read it, then the bit will be
844230775Sjfv		 * set and we have the semaphore
845230775Sjfv		 */
846230775Sjfv		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
847230775Sjfv		if (!(swsm & IXGBE_SWSM_SMBI)) {
848230775Sjfv			status = IXGBE_SUCCESS;
849230775Sjfv			break;
850230775Sjfv		}
851230775Sjfv		usec_delay(50);
852230775Sjfv	}
853230775Sjfv
854230775Sjfv	/* Now get the semaphore between SW/FW through the REGSMP bit */
855230775Sjfv	if (status == IXGBE_SUCCESS) {
856230775Sjfv		for (i = 0; i < timeout; i++) {
857230775Sjfv			swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
858230775Sjfv			if (!(swsm & IXGBE_SWFW_REGSMP))
859230775Sjfv				break;
860230775Sjfv
861230775Sjfv			usec_delay(50);
862230775Sjfv		}
863230775Sjfv
864230775Sjfv		/*
865230775Sjfv		 * Release semaphores and return error if SW NVM semaphore
866230775Sjfv		 * was not granted because we don't have access to the EEPROM
867230775Sjfv		 */
868230775Sjfv		if (i >= timeout) {
869230775Sjfv			DEBUGOUT("REGSMP Software NVM semaphore not "
870230775Sjfv				 "granted.\n");
871230775Sjfv			ixgbe_release_swfw_sync_semaphore(hw);
872230775Sjfv			status = IXGBE_ERR_EEPROM;
873230775Sjfv		}
874230775Sjfv	} else {
875230775Sjfv		DEBUGOUT("Software semaphore SMBI between device drivers "
876230775Sjfv			 "not granted.\n");
877230775Sjfv	}
878230775Sjfv
879230775Sjfv	return status;
880230775Sjfv}
881230775Sjfv
882230775Sjfv/**
883230775Sjfv *  ixgbe_release_nvm_semaphore - Release hardware semaphore
884230775Sjfv *  @hw: pointer to hardware structure
885230775Sjfv *
886230775Sjfv *  This function clears hardware semaphore bits.
887230775Sjfv **/
888230775Sjfvstatic void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw)
889230775Sjfv{
890230775Sjfv	u32 swsm;
891230775Sjfv
892230775Sjfv	DEBUGFUNC("ixgbe_release_swfw_sync_semaphore");
893230775Sjfv
894230775Sjfv	/* Release both semaphores by writing 0 to the bits REGSMP and SMBI */
895230775Sjfv
896230775Sjfv	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
897230775Sjfv	swsm &= ~IXGBE_SWSM_SMBI;
898230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
899230775Sjfv
900230775Sjfv	swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
901230775Sjfv	swsm &= ~IXGBE_SWFW_REGSMP;
902230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm);
903230775Sjfv
904230775Sjfv	IXGBE_WRITE_FLUSH(hw);
905230775Sjfv}
906230775Sjfv
907230775Sjfv/**
908230775Sjfv * ixgbe_blink_led_start_X540 - Blink LED based on index.
909230775Sjfv * @hw: pointer to hardware structure
910230775Sjfv * @index: led number to blink
911230775Sjfv *
912230775Sjfv * Devices that implement the version 2 interface:
913230775Sjfv *   X540
914230775Sjfv **/
915230775Sjfvs32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index)
916230775Sjfv{
917230775Sjfv	u32 macc_reg;
918230775Sjfv	u32 ledctl_reg;
919230775Sjfv	ixgbe_link_speed speed;
920230775Sjfv	bool link_up;
921230775Sjfv
922230775Sjfv	DEBUGFUNC("ixgbe_blink_led_start_X540");
923230775Sjfv
924230775Sjfv	/*
925230775Sjfv	 * Link should be up in order for the blink bit in the LED control
926230775Sjfv	 * register to work. Force link and speed in the MAC if link is down.
927230775Sjfv	 * This will be reversed when we stop the blinking.
928230775Sjfv	 */
929230775Sjfv	hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
930230775Sjfv	if (link_up == FALSE) {
931230775Sjfv		macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
932230775Sjfv		macc_reg |= IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS;
933230775Sjfv		IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
934230775Sjfv	}
935230775Sjfv	/* Set the LED to LINK_UP + BLINK. */
936230775Sjfv	ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
937230775Sjfv	ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
938230775Sjfv	ledctl_reg |= IXGBE_LED_BLINK(index);
939230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
940230775Sjfv	IXGBE_WRITE_FLUSH(hw);
941230775Sjfv
942230775Sjfv	return IXGBE_SUCCESS;
943230775Sjfv}
944230775Sjfv
945230775Sjfv/**
946230775Sjfv * ixgbe_blink_led_stop_X540 - Stop blinking LED based on index.
947230775Sjfv * @hw: pointer to hardware structure
948230775Sjfv * @index: led number to stop blinking
949230775Sjfv *
950230775Sjfv * Devices that implement the version 2 interface:
951230775Sjfv *   X540
952230775Sjfv **/
953230775Sjfvs32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index)
954230775Sjfv{
955230775Sjfv	u32 macc_reg;
956230775Sjfv	u32 ledctl_reg;
957230775Sjfv
958230775Sjfv	DEBUGFUNC("ixgbe_blink_led_stop_X540");
959230775Sjfv
960230775Sjfv	/* Restore the LED to its default value. */
961230775Sjfv	ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
962230775Sjfv	ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
963230775Sjfv	ledctl_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
964230775Sjfv	ledctl_reg &= ~IXGBE_LED_BLINK(index);
965230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
966230775Sjfv
967230775Sjfv	/* Unforce link and speed in the MAC. */
968230775Sjfv	macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
969230775Sjfv	macc_reg &= ~(IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS);
970230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
971230775Sjfv	IXGBE_WRITE_FLUSH(hw);
972230775Sjfv
973230775Sjfv	return IXGBE_SUCCESS;
974230775Sjfv}
975230775Sjfv
976