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