1230775Sjfv/******************************************************************************
2230775Sjfv
3315333Serj  Copyright (c) 2001-2017, Intel Corporation
4230775Sjfv  All rights reserved.
5315333Serj
6315333Serj  Redistribution and use in source and binary forms, with or without
7230775Sjfv  modification, are permitted provided that the following conditions are met:
8315333Serj
9315333Serj   1. Redistributions of source code must retain the above copyright notice,
10230775Sjfv      this list of conditions and the following disclaimer.
11315333Serj
12315333Serj   2. Redistributions in binary form must reproduce the above copyright
13315333Serj      notice, this list of conditions and the following disclaimer in the
14230775Sjfv      documentation and/or other materials provided with the distribution.
15315333Serj
16315333Serj   3. Neither the name of the Intel Corporation nor the names of its
17315333Serj      contributors may be used to endorse or promote products derived from
18230775Sjfv      this software without specific prior written permission.
19315333Serj
20230775Sjfv  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21315333Serj  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22315333Serj  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23315333Serj  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24315333Serj  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25315333Serj  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26315333Serj  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27315333Serj  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28315333Serj  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 315333 2017-03-15 21:20:17Z erj $*/
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;
85295528Ssmh	phy->ops.set_phy_power = ixgbe_set_copper_phy_power;
86230775Sjfv
87230775Sjfv	/* MAC */
88283620Serj	mac->ops.reset_hw = ixgbe_reset_hw_X540;
89283620Serj	mac->ops.enable_relaxed_ordering = ixgbe_enable_relaxed_ordering_gen2;
90283620Serj	mac->ops.get_media_type = ixgbe_get_media_type_X540;
91230775Sjfv	mac->ops.get_supported_physical_layer =
92283620Serj				    ixgbe_get_supported_physical_layer_X540;
93230775Sjfv	mac->ops.read_analog_reg8 = NULL;
94230775Sjfv	mac->ops.write_analog_reg8 = NULL;
95283620Serj	mac->ops.start_hw = ixgbe_start_hw_X540;
96283620Serj	mac->ops.get_san_mac_addr = ixgbe_get_san_mac_addr_generic;
97283620Serj	mac->ops.set_san_mac_addr = ixgbe_set_san_mac_addr_generic;
98283620Serj	mac->ops.get_device_caps = ixgbe_get_device_caps_generic;
99283620Serj	mac->ops.get_wwn_prefix = ixgbe_get_wwn_prefix_generic;
100283620Serj	mac->ops.get_fcoe_boot_status = ixgbe_get_fcoe_boot_status_generic;
101283620Serj	mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X540;
102283620Serj	mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X540;
103315333Serj	mac->ops.init_swfw_sync = ixgbe_init_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;
126315333Serj	mac->ops.bypass_rw = ixgbe_bypass_rw_generic;
127315333Serj	mac->ops.bypass_valid_rd = ixgbe_bypass_valid_rd_generic;
128315333Serj	mac->ops.bypass_set = ixgbe_bypass_set_generic;
129315333Serj	mac->ops.bypass_rd_eep = ixgbe_bypass_rd_eep_generic;
130230775Sjfv
131247822Sjfv
132283620Serj	mac->mcft_size		= IXGBE_X540_MC_TBL_SIZE;
133283620Serj	mac->vft_size		= IXGBE_X540_VFT_TBL_SIZE;
134283620Serj	mac->num_rar_entries	= IXGBE_X540_RAR_ENTRIES;
135283620Serj	mac->rx_pb_size		= IXGBE_X540_RX_PB_SIZE;
136283620Serj	mac->max_rx_queues	= IXGBE_X540_MAX_RX_QUEUES;
137283620Serj	mac->max_tx_queues	= IXGBE_X540_MAX_TX_QUEUES;
138230775Sjfv	mac->max_msix_vectors	= ixgbe_get_pcie_msix_count_generic(hw);
139230775Sjfv
140230775Sjfv	/*
141230775Sjfv	 * FWSM register
142230775Sjfv	 * ARC supported; valid only if manageability features are
143230775Sjfv	 * enabled.
144230775Sjfv	 */
145295524Ssbruno	mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
146295524Ssbruno				     & IXGBE_FWSM_MODE_MASK);
147230775Sjfv
148230775Sjfv	hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
149230775Sjfv
150230775Sjfv	/* LEDs */
151230775Sjfv	mac->ops.blink_led_start = ixgbe_blink_led_start_X540;
152230775Sjfv	mac->ops.blink_led_stop = ixgbe_blink_led_stop_X540;
153230775Sjfv
154230775Sjfv	/* Manageability interface */
155283620Serj	mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_generic;
156230775Sjfv
157283620Serj	mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
158251964Sjfv
159230775Sjfv	return ret_val;
160230775Sjfv}
161230775Sjfv
162230775Sjfv/**
163230775Sjfv *  ixgbe_get_link_capabilities_X540 - Determines link capabilities
164230775Sjfv *  @hw: pointer to hardware structure
165230775Sjfv *  @speed: pointer to link speed
166230775Sjfv *  @autoneg: TRUE when autoneg or autotry is enabled
167230775Sjfv *
168230775Sjfv *  Determines the link capabilities by reading the AUTOC register.
169230775Sjfv **/
170230775Sjfvs32 ixgbe_get_link_capabilities_X540(struct ixgbe_hw *hw,
171230775Sjfv				     ixgbe_link_speed *speed,
172230775Sjfv				     bool *autoneg)
173230775Sjfv{
174230775Sjfv	ixgbe_get_copper_link_capabilities_generic(hw, speed, autoneg);
175230775Sjfv
176230775Sjfv	return IXGBE_SUCCESS;
177230775Sjfv}
178230775Sjfv
179230775Sjfv/**
180230775Sjfv *  ixgbe_get_media_type_X540 - Get media type
181230775Sjfv *  @hw: pointer to hardware structure
182230775Sjfv *
183230775Sjfv *  Returns the media type (fiber, copper, backplane)
184230775Sjfv **/
185230775Sjfvenum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw)
186230775Sjfv{
187230775Sjfv	UNREFERENCED_1PARAMETER(hw);
188230775Sjfv	return ixgbe_media_type_copper;
189230775Sjfv}
190230775Sjfv
191230775Sjfv/**
192230775Sjfv *  ixgbe_setup_mac_link_X540 - Sets the auto advertised capabilities
193230775Sjfv *  @hw: pointer to hardware structure
194230775Sjfv *  @speed: new link speed
195230775Sjfv *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
196230775Sjfv **/
197230775Sjfvs32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw,
198247822Sjfv			      ixgbe_link_speed speed,
199230775Sjfv			      bool autoneg_wait_to_complete)
200230775Sjfv{
201230775Sjfv	DEBUGFUNC("ixgbe_setup_mac_link_X540");
202247822Sjfv	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete);
203230775Sjfv}
204230775Sjfv
205230775Sjfv/**
206230775Sjfv *  ixgbe_reset_hw_X540 - Perform hardware reset
207230775Sjfv *  @hw: pointer to hardware structure
208230775Sjfv *
209230775Sjfv *  Resets the hardware by resetting the transmit and receive units, masks
210230775Sjfv *  and clears all interrupts, and perform a reset.
211230775Sjfv **/
212230775Sjfvs32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
213230775Sjfv{
214230775Sjfv	s32 status;
215230775Sjfv	u32 ctrl, i;
216230775Sjfv
217230775Sjfv	DEBUGFUNC("ixgbe_reset_hw_X540");
218230775Sjfv
219230775Sjfv	/* Call adapter stop to disable tx/rx and clear interrupts */
220230775Sjfv	status = hw->mac.ops.stop_adapter(hw);
221230775Sjfv	if (status != IXGBE_SUCCESS)
222230775Sjfv		goto reset_hw_out;
223230775Sjfv
224230775Sjfv	/* flush pending Tx transactions */
225230775Sjfv	ixgbe_clear_tx_pending(hw);
226230775Sjfv
227230775Sjfvmac_reset_top:
228230775Sjfv	ctrl = IXGBE_CTRL_RST;
229230775Sjfv	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
230230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
231230775Sjfv	IXGBE_WRITE_FLUSH(hw);
232230775Sjfv
233230775Sjfv	/* Poll for reset bit to self-clear indicating reset is complete */
234230775Sjfv	for (i = 0; i < 10; i++) {
235230775Sjfv		usec_delay(1);
236230775Sjfv		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
237230775Sjfv		if (!(ctrl & IXGBE_CTRL_RST_MASK))
238230775Sjfv			break;
239230775Sjfv	}
240230775Sjfv
241230775Sjfv	if (ctrl & IXGBE_CTRL_RST_MASK) {
242230775Sjfv		status = IXGBE_ERR_RESET_FAILED;
243251964Sjfv		ERROR_REPORT1(IXGBE_ERROR_POLLING,
244251964Sjfv			     "Reset polling failed to complete.\n");
245230775Sjfv	}
246230775Sjfv	msec_delay(100);
247230775Sjfv
248230775Sjfv	/*
249230775Sjfv	 * Double resets are required for recovery from certain error
250230775Sjfv	 * conditions.  Between resets, it is necessary to stall to allow time
251230775Sjfv	 * for any pending HW events to complete.
252230775Sjfv	 */
253230775Sjfv	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
254230775Sjfv		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
255230775Sjfv		goto mac_reset_top;
256230775Sjfv	}
257230775Sjfv
258230775Sjfv	/* Set the Rx packet buffer size. */
259230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT);
260230775Sjfv
261230775Sjfv	/* Store the permanent mac address */
262230775Sjfv	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
263230775Sjfv
264230775Sjfv	/*
265230775Sjfv	 * Store MAC address from RAR0, clear receive address registers, and
266230775Sjfv	 * clear the multicast table.  Also reset num_rar_entries to 128,
267230775Sjfv	 * since we modify this value when programming the SAN MAC address.
268230775Sjfv	 */
269230775Sjfv	hw->mac.num_rar_entries = 128;
270230775Sjfv	hw->mac.ops.init_rx_addrs(hw);
271230775Sjfv
272230775Sjfv	/* Store the permanent SAN mac address */
273230775Sjfv	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
274230775Sjfv
275230775Sjfv	/* Add the SAN MAC address to the RAR only if it's a valid address */
276230775Sjfv	if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
277238149Sjfv		/* Save the SAN MAC RAR index */
278238149Sjfv		hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
279238149Sjfv
280315333Serj		hw->mac.ops.set_rar(hw, hw->mac.san_mac_rar_index,
281315333Serj				    hw->mac.san_addr, 0, IXGBE_RAH_AV);
282315333Serj
283315333Serj		/* clear VMDq pool/queue selection for this RAR */
284315333Serj		hw->mac.ops.clear_vmdq(hw, hw->mac.san_mac_rar_index,
285315333Serj				       IXGBE_CLEAR_VMDQ_ALL);
286315333Serj
287230775Sjfv		/* Reserve the last RAR for the SAN MAC address */
288230775Sjfv		hw->mac.num_rar_entries--;
289230775Sjfv	}
290230775Sjfv
291230775Sjfv	/* Store the alternative WWNN/WWPN prefix */
292230775Sjfv	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
293230775Sjfv				   &hw->mac.wwpn_prefix);
294230775Sjfv
295230775Sjfvreset_hw_out:
296230775Sjfv	return status;
297230775Sjfv}
298230775Sjfv
299230775Sjfv/**
300230775Sjfv *  ixgbe_start_hw_X540 - Prepare hardware for Tx/Rx
301230775Sjfv *  @hw: pointer to hardware structure
302230775Sjfv *
303230775Sjfv *  Starts the hardware using the generic start_hw function
304230775Sjfv *  and the generation start_hw function.
305230775Sjfv *  Then performs revision-specific operations, if any.
306230775Sjfv **/
307230775Sjfvs32 ixgbe_start_hw_X540(struct ixgbe_hw *hw)
308230775Sjfv{
309230775Sjfv	s32 ret_val = IXGBE_SUCCESS;
310230775Sjfv
311230775Sjfv	DEBUGFUNC("ixgbe_start_hw_X540");
312230775Sjfv
313230775Sjfv	ret_val = ixgbe_start_hw_generic(hw);
314230775Sjfv	if (ret_val != IXGBE_SUCCESS)
315230775Sjfv		goto out;
316230775Sjfv
317230775Sjfv	ret_val = ixgbe_start_hw_gen2(hw);
318230775Sjfv
319230775Sjfvout:
320230775Sjfv	return ret_val;
321230775Sjfv}
322230775Sjfv
323230775Sjfv/**
324230775Sjfv *  ixgbe_get_supported_physical_layer_X540 - Returns physical layer type
325230775Sjfv *  @hw: pointer to hardware structure
326230775Sjfv *
327230775Sjfv *  Determines physical layer capabilities of the current configuration.
328230775Sjfv **/
329230775Sjfvu32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
330230775Sjfv{
331230775Sjfv	u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
332230775Sjfv	u16 ext_ability = 0;
333230775Sjfv
334230775Sjfv	DEBUGFUNC("ixgbe_get_supported_physical_layer_X540");
335230775Sjfv
336230775Sjfv	hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
337230775Sjfv	IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
338230775Sjfv	if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
339230775Sjfv		physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
340230775Sjfv	if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
341230775Sjfv		physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
342230775Sjfv	if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
343230775Sjfv		physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
344230775Sjfv
345230775Sjfv	return physical_layer;
346230775Sjfv}
347230775Sjfv
348230775Sjfv/**
349230775Sjfv *  ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
350230775Sjfv *  @hw: pointer to hardware structure
351230775Sjfv *
352230775Sjfv *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
353230775Sjfv *  ixgbe_hw struct in order to set up EEPROM access.
354230775Sjfv **/
355230775Sjfvs32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
356230775Sjfv{
357230775Sjfv	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
358230775Sjfv	u32 eec;
359230775Sjfv	u16 eeprom_size;
360230775Sjfv
361230775Sjfv	DEBUGFUNC("ixgbe_init_eeprom_params_X540");
362230775Sjfv
363230775Sjfv	if (eeprom->type == ixgbe_eeprom_uninitialized) {
364230775Sjfv		eeprom->semaphore_delay = 10;
365230775Sjfv		eeprom->type = ixgbe_flash;
366230775Sjfv
367295524Ssbruno		eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
368230775Sjfv		eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
369230775Sjfv				    IXGBE_EEC_SIZE_SHIFT);
370230775Sjfv		eeprom->word_size = 1 << (eeprom_size +
371230775Sjfv					  IXGBE_EEPROM_WORD_SIZE_SHIFT);
372230775Sjfv
373230775Sjfv		DEBUGOUT2("Eeprom params: type = %d, size = %d\n",
374230775Sjfv			  eeprom->type, eeprom->word_size);
375230775Sjfv	}
376230775Sjfv
377230775Sjfv	return IXGBE_SUCCESS;
378230775Sjfv}
379230775Sjfv
380230775Sjfv/**
381230775Sjfv *  ixgbe_read_eerd_X540- Read EEPROM word using EERD
382230775Sjfv *  @hw: pointer to hardware structure
383230775Sjfv *  @offset: offset of  word in the EEPROM to read
384230775Sjfv *  @data: word read from the EEPROM
385230775Sjfv *
386230775Sjfv *  Reads a 16 bit word from the EEPROM using the EERD register.
387230775Sjfv **/
388230775Sjfvs32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
389230775Sjfv{
390230775Sjfv	s32 status = IXGBE_SUCCESS;
391230775Sjfv
392230775Sjfv	DEBUGFUNC("ixgbe_read_eerd_X540");
393230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
394251964Sjfv	    IXGBE_SUCCESS) {
395230775Sjfv		status = ixgbe_read_eerd_generic(hw, offset, data);
396251964Sjfv		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
397251964Sjfv	} else {
398230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
399251964Sjfv	}
400230775Sjfv
401230775Sjfv	return status;
402230775Sjfv}
403230775Sjfv
404230775Sjfv/**
405230775Sjfv *  ixgbe_read_eerd_buffer_X540- Read EEPROM word(s) using EERD
406230775Sjfv *  @hw: pointer to hardware structure
407230775Sjfv *  @offset: offset of  word in the EEPROM to read
408230775Sjfv *  @words: number of words
409230775Sjfv *  @data: word(s) read from the EEPROM
410230775Sjfv *
411230775Sjfv *  Reads a 16 bit word(s) from the EEPROM using the EERD register.
412230775Sjfv **/
413230775Sjfvs32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw,
414230775Sjfv				u16 offset, u16 words, u16 *data)
415230775Sjfv{
416230775Sjfv	s32 status = IXGBE_SUCCESS;
417230775Sjfv
418230775Sjfv	DEBUGFUNC("ixgbe_read_eerd_buffer_X540");
419230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
420251964Sjfv	    IXGBE_SUCCESS) {
421230775Sjfv		status = ixgbe_read_eerd_buffer_generic(hw, offset,
422230775Sjfv							words, data);
423251964Sjfv		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
424251964Sjfv	} else {
425230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
426251964Sjfv	}
427230775Sjfv
428230775Sjfv	return status;
429230775Sjfv}
430230775Sjfv
431230775Sjfv/**
432230775Sjfv *  ixgbe_write_eewr_X540 - Write EEPROM word using EEWR
433230775Sjfv *  @hw: pointer to hardware structure
434230775Sjfv *  @offset: offset of  word in the EEPROM to write
435230775Sjfv *  @data: word write to the EEPROM
436230775Sjfv *
437230775Sjfv *  Write a 16 bit word to the EEPROM using the EEWR register.
438230775Sjfv **/
439230775Sjfvs32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
440230775Sjfv{
441230775Sjfv	s32 status = IXGBE_SUCCESS;
442230775Sjfv
443230775Sjfv	DEBUGFUNC("ixgbe_write_eewr_X540");
444230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
445251964Sjfv	    IXGBE_SUCCESS) {
446230775Sjfv		status = ixgbe_write_eewr_generic(hw, offset, data);
447251964Sjfv		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
448251964Sjfv	} else {
449230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
450251964Sjfv	}
451230775Sjfv
452230775Sjfv	return status;
453230775Sjfv}
454230775Sjfv
455230775Sjfv/**
456230775Sjfv *  ixgbe_write_eewr_buffer_X540 - Write EEPROM word(s) using EEWR
457230775Sjfv *  @hw: pointer to hardware structure
458230775Sjfv *  @offset: offset of  word in the EEPROM to write
459230775Sjfv *  @words: number of words
460230775Sjfv *  @data: word(s) write to the EEPROM
461230775Sjfv *
462230775Sjfv *  Write a 16 bit word(s) to the EEPROM using the EEWR register.
463230775Sjfv **/
464230775Sjfvs32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
465230775Sjfv				 u16 offset, u16 words, u16 *data)
466230775Sjfv{
467230775Sjfv	s32 status = IXGBE_SUCCESS;
468230775Sjfv
469230775Sjfv	DEBUGFUNC("ixgbe_write_eewr_buffer_X540");
470230775Sjfv	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
471251964Sjfv	    IXGBE_SUCCESS) {
472230775Sjfv		status = ixgbe_write_eewr_buffer_generic(hw, offset,
473230775Sjfv							 words, data);
474251964Sjfv		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
475251964Sjfv	} else {
476230775Sjfv		status = IXGBE_ERR_SWFW_SYNC;
477251964Sjfv	}
478230775Sjfv
479230775Sjfv	return status;
480230775Sjfv}
481230775Sjfv
482230775Sjfv/**
483230775Sjfv *  ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum
484230775Sjfv *
485230775Sjfv *  This function does not use synchronization for EERD and EEWR. It can
486230775Sjfv *  be used internally by function which utilize ixgbe_acquire_swfw_sync_X540.
487230775Sjfv *
488230775Sjfv *  @hw: pointer to hardware structure
489283620Serj *
490283620Serj *  Returns a negative error code on error, or the 16-bit checksum
491230775Sjfv **/
492283620Serjs32 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
493230775Sjfv{
494283620Serj	u16 i, j;
495230775Sjfv	u16 checksum = 0;
496230775Sjfv	u16 length = 0;
497230775Sjfv	u16 pointer = 0;
498230775Sjfv	u16 word = 0;
499283620Serj	u16 ptr_start = IXGBE_PCIE_ANALOG_PTR;
500230775Sjfv
501283620Serj	/* Do not use hw->eeprom.ops.read because we do not want to take
502230775Sjfv	 * the synchronization semaphores here. Instead use
503230775Sjfv	 * ixgbe_read_eerd_generic
504230775Sjfv	 */
505230775Sjfv
506230775Sjfv	DEBUGFUNC("ixgbe_calc_eeprom_checksum_X540");
507230775Sjfv
508315333Serj	/* Include 0x0 up to IXGBE_EEPROM_CHECKSUM; do not include the
509315333Serj	 * checksum itself
510315333Serj	 */
511315333Serj	for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
512283620Serj		if (ixgbe_read_eerd_generic(hw, i, &word)) {
513230775Sjfv			DEBUGOUT("EEPROM read failed\n");
514283620Serj			return IXGBE_ERR_EEPROM;
515230775Sjfv		}
516315333Serj		checksum += word;
517230775Sjfv	}
518230775Sjfv
519283620Serj	/* Include all data from pointers 0x3, 0x6-0xE.  This excludes the
520230775Sjfv	 * FW, PHY module, and PCIe Expansion/Option ROM pointers.
521230775Sjfv	 */
522283620Serj	for (i = ptr_start; i < IXGBE_FW_PTR; i++) {
523230775Sjfv		if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
524230775Sjfv			continue;
525230775Sjfv
526283620Serj		if (ixgbe_read_eerd_generic(hw, i, &pointer)) {
527230775Sjfv			DEBUGOUT("EEPROM read failed\n");
528283620Serj			return IXGBE_ERR_EEPROM;
529230775Sjfv		}
530230775Sjfv
531230775Sjfv		/* Skip pointer section if the pointer is invalid. */
532230775Sjfv		if (pointer == 0xFFFF || pointer == 0 ||
533230775Sjfv		    pointer >= hw->eeprom.word_size)
534230775Sjfv			continue;
535230775Sjfv
536283620Serj		if (ixgbe_read_eerd_generic(hw, pointer, &length)) {
537230775Sjfv			DEBUGOUT("EEPROM read failed\n");
538283620Serj			return IXGBE_ERR_EEPROM;
539230775Sjfv		}
540230775Sjfv
541230775Sjfv		/* Skip pointer section if length is invalid. */
542230775Sjfv		if (length == 0xFFFF || length == 0 ||
543230775Sjfv		    (pointer + length) >= hw->eeprom.word_size)
544230775Sjfv			continue;
545230775Sjfv
546283620Serj		for (j = pointer + 1; j <= pointer + length; j++) {
547283620Serj			if (ixgbe_read_eerd_generic(hw, j, &word)) {
548230775Sjfv				DEBUGOUT("EEPROM read failed\n");
549283620Serj				return IXGBE_ERR_EEPROM;
550230775Sjfv			}
551230775Sjfv			checksum += word;
552230775Sjfv		}
553230775Sjfv	}
554230775Sjfv
555230775Sjfv	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
556230775Sjfv
557283620Serj	return (s32)checksum;
558230775Sjfv}
559230775Sjfv
560230775Sjfv/**
561230775Sjfv *  ixgbe_validate_eeprom_checksum_X540 - Validate EEPROM checksum
562230775Sjfv *  @hw: pointer to hardware structure
563230775Sjfv *  @checksum_val: calculated checksum
564230775Sjfv *
565230775Sjfv *  Performs checksum calculation and validates the EEPROM checksum.  If the
566230775Sjfv *  caller does not need checksum_val, the value can be NULL.
567230775Sjfv **/
568230775Sjfvs32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw,
569230775Sjfv					u16 *checksum_val)
570230775Sjfv{
571230775Sjfv	s32 status;
572230775Sjfv	u16 checksum;
573230775Sjfv	u16 read_checksum = 0;
574230775Sjfv
575230775Sjfv	DEBUGFUNC("ixgbe_validate_eeprom_checksum_X540");
576230775Sjfv
577283620Serj	/* Read the first word from the EEPROM. If this times out or fails, do
578230775Sjfv	 * not continue or we could be in for a very long wait while every
579230775Sjfv	 * EEPROM read fails
580230775Sjfv	 */
581230775Sjfv	status = hw->eeprom.ops.read(hw, 0, &checksum);
582283620Serj	if (status) {
583230775Sjfv		DEBUGOUT("EEPROM read failed\n");
584283620Serj		return status;
585230775Sjfv	}
586230775Sjfv
587283620Serj	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
588283620Serj		return IXGBE_ERR_SWFW_SYNC;
589230775Sjfv
590283620Serj	status = hw->eeprom.ops.calc_checksum(hw);
591283620Serj	if (status < 0)
592283620Serj		goto out;
593230775Sjfv
594283620Serj	checksum = (u16)(status & 0xffff);
595230775Sjfv
596283620Serj	/* Do not use hw->eeprom.ops.read because we do not want to take
597283620Serj	 * the synchronization semaphores twice here.
598283620Serj	 */
599283620Serj	status = ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
600283620Serj					 &read_checksum);
601283620Serj	if (status)
602283620Serj		goto out;
603283620Serj
604283620Serj	/* Verify read checksum from EEPROM is the same as
605283620Serj	 * calculated checksum
606283620Serj	 */
607283620Serj	if (read_checksum != checksum) {
608283620Serj		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
609283620Serj			     "Invalid EEPROM checksum");
610283620Serj		status = IXGBE_ERR_EEPROM_CHECKSUM;
611230775Sjfv	}
612230775Sjfv
613283620Serj	/* If the user cares, return the calculated checksum */
614283620Serj	if (checksum_val)
615283620Serj		*checksum_val = checksum;
616283620Serj
617230775Sjfvout:
618283620Serj	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
619283620Serj
620230775Sjfv	return status;
621230775Sjfv}
622230775Sjfv
623230775Sjfv/**
624230775Sjfv * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash
625230775Sjfv * @hw: pointer to hardware structure
626230775Sjfv *
627230775Sjfv * After writing EEPROM to shadow RAM using EEWR register, software calculates
628230775Sjfv * checksum and updates the EEPROM and instructs the hardware to update
629230775Sjfv * the flash.
630230775Sjfv **/
631230775Sjfvs32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
632230775Sjfv{
633230775Sjfv	s32 status;
634230775Sjfv	u16 checksum;
635230775Sjfv
636230775Sjfv	DEBUGFUNC("ixgbe_update_eeprom_checksum_X540");
637230775Sjfv
638283620Serj	/* Read the first word from the EEPROM. If this times out or fails, do
639230775Sjfv	 * not continue or we could be in for a very long wait while every
640230775Sjfv	 * EEPROM read fails
641230775Sjfv	 */
642230775Sjfv	status = hw->eeprom.ops.read(hw, 0, &checksum);
643283620Serj	if (status) {
644230775Sjfv		DEBUGOUT("EEPROM read failed\n");
645283620Serj		return status;
646283620Serj	}
647230775Sjfv
648283620Serj	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
649283620Serj		return IXGBE_ERR_SWFW_SYNC;
650230775Sjfv
651283620Serj	status = hw->eeprom.ops.calc_checksum(hw);
652283620Serj	if (status < 0)
653283620Serj		goto out;
654230775Sjfv
655283620Serj	checksum = (u16)(status & 0xffff);
656230775Sjfv
657283620Serj	/* Do not use hw->eeprom.ops.write because we do not want to
658283620Serj	 * take the synchronization semaphores twice here.
659283620Serj	 */
660283620Serj	status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, checksum);
661283620Serj	if (status)
662283620Serj		goto out;
663283620Serj
664283620Serj	status = ixgbe_update_flash_X540(hw);
665283620Serj
666283620Serjout:
667283620Serj	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
668283620Serj
669230775Sjfv	return status;
670230775Sjfv}
671230775Sjfv
672230775Sjfv/**
673230775Sjfv *  ixgbe_update_flash_X540 - Instruct HW to copy EEPROM to Flash device
674230775Sjfv *  @hw: pointer to hardware structure
675230775Sjfv *
676230775Sjfv *  Set FLUP (bit 23) of the EEC register to instruct Hardware to copy
677230775Sjfv *  EEPROM from shadow RAM to the flash device.
678230775Sjfv **/
679251964Sjfvs32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
680230775Sjfv{
681230775Sjfv	u32 flup;
682283620Serj	s32 status;
683230775Sjfv
684230775Sjfv	DEBUGFUNC("ixgbe_update_flash_X540");
685230775Sjfv
686230775Sjfv	status = ixgbe_poll_flash_update_done_X540(hw);
687230775Sjfv	if (status == IXGBE_ERR_EEPROM) {
688230775Sjfv		DEBUGOUT("Flash update time out\n");
689230775Sjfv		goto out;
690230775Sjfv	}
691230775Sjfv
692295524Ssbruno	flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)) | IXGBE_EEC_FLUP;
693295524Ssbruno	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup);
694230775Sjfv
695230775Sjfv	status = ixgbe_poll_flash_update_done_X540(hw);
696230775Sjfv	if (status == IXGBE_SUCCESS)
697230775Sjfv		DEBUGOUT("Flash update complete\n");
698230775Sjfv	else
699230775Sjfv		DEBUGOUT("Flash update time out\n");
700230775Sjfv
701251964Sjfv	if (hw->mac.type == ixgbe_mac_X540 && hw->revision_id == 0) {
702295524Ssbruno		flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
703230775Sjfv
704230775Sjfv		if (flup & IXGBE_EEC_SEC1VAL) {
705230775Sjfv			flup |= IXGBE_EEC_FLUP;
706295524Ssbruno			IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup);
707230775Sjfv		}
708230775Sjfv
709230775Sjfv		status = ixgbe_poll_flash_update_done_X540(hw);
710230775Sjfv		if (status == IXGBE_SUCCESS)
711230775Sjfv			DEBUGOUT("Flash update complete\n");
712230775Sjfv		else
713230775Sjfv			DEBUGOUT("Flash update time out\n");
714230775Sjfv	}
715230775Sjfvout:
716230775Sjfv	return status;
717230775Sjfv}
718230775Sjfv
719230775Sjfv/**
720230775Sjfv *  ixgbe_poll_flash_update_done_X540 - Poll flash update status
721230775Sjfv *  @hw: pointer to hardware structure
722230775Sjfv *
723230775Sjfv *  Polls the FLUDONE (bit 26) of the EEC Register to determine when the
724230775Sjfv *  flash update is done.
725230775Sjfv **/
726230775Sjfvstatic s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
727230775Sjfv{
728230775Sjfv	u32 i;
729230775Sjfv	u32 reg;
730230775Sjfv	s32 status = IXGBE_ERR_EEPROM;
731230775Sjfv
732230775Sjfv	DEBUGFUNC("ixgbe_poll_flash_update_done_X540");
733230775Sjfv
734230775Sjfv	for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
735295524Ssbruno		reg = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
736230775Sjfv		if (reg & IXGBE_EEC_FLUDONE) {
737230775Sjfv			status = IXGBE_SUCCESS;
738230775Sjfv			break;
739230775Sjfv		}
740283620Serj		msec_delay(5);
741230775Sjfv	}
742251964Sjfv
743251964Sjfv	if (i == IXGBE_FLUDONE_ATTEMPTS)
744251964Sjfv		ERROR_REPORT1(IXGBE_ERROR_POLLING,
745251964Sjfv			     "Flash update status polling timed out");
746251964Sjfv
747230775Sjfv	return status;
748230775Sjfv}
749230775Sjfv
750230775Sjfv/**
751230775Sjfv *  ixgbe_acquire_swfw_sync_X540 - Acquire SWFW semaphore
752230775Sjfv *  @hw: pointer to hardware structure
753230775Sjfv *  @mask: Mask to specify which semaphore to acquire
754230775Sjfv *
755230775Sjfv *  Acquires the SWFW semaphore thought the SW_FW_SYNC register for
756230775Sjfv *  the specified function (CSR, PHY0, PHY1, NVM, Flash)
757230775Sjfv **/
758283620Serjs32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
759230775Sjfv{
760283620Serj	u32 swmask = mask & IXGBE_GSSR_NVM_PHY_MASK;
761283620Serj	u32 fwmask = swmask << 5;
762283620Serj	u32 swi2c_mask = mask & IXGBE_GSSR_I2C_MASK;
763283620Serj	u32 timeout = 200;
764283620Serj	u32 hwmask = 0;
765230775Sjfv	u32 swfw_sync;
766230775Sjfv	u32 i;
767230775Sjfv
768230775Sjfv	DEBUGFUNC("ixgbe_acquire_swfw_sync_X540");
769230775Sjfv
770283620Serj	if (swmask & IXGBE_GSSR_EEP_SM)
771283620Serj		hwmask |= IXGBE_GSSR_FLASH_SM;
772230775Sjfv
773230775Sjfv	/* SW only mask doesn't have FW bit pair */
774283620Serj	if (mask & IXGBE_GSSR_SW_MNG_SM)
775283620Serj		swmask |= IXGBE_GSSR_SW_MNG_SM;
776230775Sjfv
777283620Serj	swmask |= swi2c_mask;
778283620Serj	fwmask |= swi2c_mask << 2;
779230775Sjfv	for (i = 0; i < timeout; i++) {
780283620Serj		/* SW NVM semaphore bit is used for access to all
781230775Sjfv		 * SW_FW_SYNC bits (not just NVM)
782230775Sjfv		 */
783315333Serj		if (ixgbe_get_swfw_sync_semaphore(hw)) {
784315333Serj			DEBUGOUT("Failed to get NVM access and register semaphore, returning IXGBE_ERR_SWFW_SYNC\n");
785283620Serj			return IXGBE_ERR_SWFW_SYNC;
786315333Serj		}
787230775Sjfv
788295524Ssbruno		swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
789230775Sjfv		if (!(swfw_sync & (fwmask | swmask | hwmask))) {
790230775Sjfv			swfw_sync |= swmask;
791295524Ssbruno			IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw),
792295524Ssbruno					swfw_sync);
793230775Sjfv			ixgbe_release_swfw_sync_semaphore(hw);
794283620Serj			return IXGBE_SUCCESS;
795230775Sjfv		}
796283620Serj		/* Firmware currently using resource (fwmask), hardware
797283620Serj		 * currently using resource (hwmask), or other software
798283620Serj		 * thread currently using resource (swmask)
799283620Serj		 */
800283620Serj		ixgbe_release_swfw_sync_semaphore(hw);
801283620Serj		msec_delay(5);
802230775Sjfv	}
803230775Sjfv
804230775Sjfv	/* Failed to get SW only semaphore */
805230775Sjfv	if (swmask == IXGBE_GSSR_SW_MNG_SM) {
806251964Sjfv		ERROR_REPORT1(IXGBE_ERROR_POLLING,
807251964Sjfv			     "Failed to get SW only semaphore");
808315333Serj		DEBUGOUT("Failed to get SW only semaphore, returning IXGBE_ERR_SWFW_SYNC\n");
809283620Serj		return IXGBE_ERR_SWFW_SYNC;
810230775Sjfv	}
811230775Sjfv
812230775Sjfv	/* If the resource is not released by the FW/HW the SW can assume that
813251964Sjfv	 * the FW/HW malfunctions. In that case the SW should set the SW bit(s)
814230775Sjfv	 * of the requested resource(s) while ignoring the corresponding FW/HW
815230775Sjfv	 * bits in the SW_FW_SYNC register.
816230775Sjfv	 */
817315333Serj	if (ixgbe_get_swfw_sync_semaphore(hw)) {
818315333Serj		DEBUGOUT("Failed to get NVM sempahore and register semaphore while forcefully ignoring FW sempahore bit(s) and setting SW semaphore bit(s), returning IXGBE_ERR_SWFW_SYNC\n");
819283620Serj		return IXGBE_ERR_SWFW_SYNC;
820315333Serj	}
821295524Ssbruno	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
822230775Sjfv	if (swfw_sync & (fwmask | hwmask)) {
823230775Sjfv		swfw_sync |= swmask;
824295524Ssbruno		IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
825230775Sjfv		ixgbe_release_swfw_sync_semaphore(hw);
826230775Sjfv		msec_delay(5);
827283620Serj		return IXGBE_SUCCESS;
828230775Sjfv	}
829251964Sjfv	/* If the resource is not released by other SW the SW can assume that
830251964Sjfv	 * the other SW malfunctions. In that case the SW should clear all SW
831251964Sjfv	 * flags that it does not own and then repeat the whole process once
832251964Sjfv	 * again.
833251964Sjfv	 */
834283620Serj	if (swfw_sync & swmask) {
835283620Serj		u32 rmask = IXGBE_GSSR_EEP_SM | IXGBE_GSSR_PHY0_SM |
836283620Serj			    IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_MAC_CSR_SM;
837283620Serj
838283620Serj		if (swi2c_mask)
839283620Serj			rmask |= IXGBE_GSSR_I2C_MASK;
840283620Serj		ixgbe_release_swfw_sync_X540(hw, rmask);
841283620Serj		ixgbe_release_swfw_sync_semaphore(hw);
842315333Serj		DEBUGOUT("Resource not released by other SW, returning IXGBE_ERR_SWFW_SYNC\n");
843283620Serj		return IXGBE_ERR_SWFW_SYNC;
844251964Sjfv	}
845283620Serj	ixgbe_release_swfw_sync_semaphore(hw);
846315333Serj	DEBUGOUT("Returning error IXGBE_ERR_SWFW_SYNC\n");
847230775Sjfv
848283620Serj	return IXGBE_ERR_SWFW_SYNC;
849230775Sjfv}
850230775Sjfv
851230775Sjfv/**
852230775Sjfv *  ixgbe_release_swfw_sync_X540 - Release SWFW semaphore
853230775Sjfv *  @hw: pointer to hardware structure
854230775Sjfv *  @mask: Mask to specify which semaphore to release
855230775Sjfv *
856238149Sjfv *  Releases the SWFW semaphore through the SW_FW_SYNC register
857230775Sjfv *  for the specified function (CSR, PHY0, PHY1, EVM, Flash)
858230775Sjfv **/
859283620Serjvoid ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
860230775Sjfv{
861283620Serj	u32 swmask = mask & (IXGBE_GSSR_NVM_PHY_MASK | IXGBE_GSSR_SW_MNG_SM);
862230775Sjfv	u32 swfw_sync;
863230775Sjfv
864230775Sjfv	DEBUGFUNC("ixgbe_release_swfw_sync_X540");
865230775Sjfv
866283620Serj	if (mask & IXGBE_GSSR_I2C_MASK)
867283620Serj		swmask |= mask & IXGBE_GSSR_I2C_MASK;
868230775Sjfv	ixgbe_get_swfw_sync_semaphore(hw);
869230775Sjfv
870295524Ssbruno	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
871230775Sjfv	swfw_sync &= ~swmask;
872295524Ssbruno	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
873230775Sjfv
874230775Sjfv	ixgbe_release_swfw_sync_semaphore(hw);
875315333Serj	msec_delay(2);
876230775Sjfv}
877230775Sjfv
878230775Sjfv/**
879283620Serj *  ixgbe_get_swfw_sync_semaphore - Get hardware semaphore
880230775Sjfv *  @hw: pointer to hardware structure
881230775Sjfv *
882230775Sjfv *  Sets the hardware semaphores so SW/FW can gain control of shared resources
883230775Sjfv **/
884230775Sjfvstatic s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
885230775Sjfv{
886230775Sjfv	s32 status = IXGBE_ERR_EEPROM;
887230775Sjfv	u32 timeout = 2000;
888230775Sjfv	u32 i;
889230775Sjfv	u32 swsm;
890230775Sjfv
891230775Sjfv	DEBUGFUNC("ixgbe_get_swfw_sync_semaphore");
892230775Sjfv
893230775Sjfv	/* Get SMBI software semaphore between device drivers first */
894230775Sjfv	for (i = 0; i < timeout; i++) {
895230775Sjfv		/*
896230775Sjfv		 * If the SMBI bit is 0 when we read it, then the bit will be
897230775Sjfv		 * set and we have the semaphore
898230775Sjfv		 */
899295524Ssbruno		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
900230775Sjfv		if (!(swsm & IXGBE_SWSM_SMBI)) {
901230775Sjfv			status = IXGBE_SUCCESS;
902230775Sjfv			break;
903230775Sjfv		}
904230775Sjfv		usec_delay(50);
905230775Sjfv	}
906230775Sjfv
907230775Sjfv	/* Now get the semaphore between SW/FW through the REGSMP bit */
908230775Sjfv	if (status == IXGBE_SUCCESS) {
909230775Sjfv		for (i = 0; i < timeout; i++) {
910295524Ssbruno			swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
911230775Sjfv			if (!(swsm & IXGBE_SWFW_REGSMP))
912230775Sjfv				break;
913230775Sjfv
914230775Sjfv			usec_delay(50);
915230775Sjfv		}
916230775Sjfv
917230775Sjfv		/*
918230775Sjfv		 * Release semaphores and return error if SW NVM semaphore
919230775Sjfv		 * was not granted because we don't have access to the EEPROM
920230775Sjfv		 */
921230775Sjfv		if (i >= timeout) {
922251964Sjfv			ERROR_REPORT1(IXGBE_ERROR_POLLING,
923251964Sjfv				"REGSMP Software NVM semaphore not granted.\n");
924230775Sjfv			ixgbe_release_swfw_sync_semaphore(hw);
925230775Sjfv			status = IXGBE_ERR_EEPROM;
926230775Sjfv		}
927230775Sjfv	} else {
928251964Sjfv		ERROR_REPORT1(IXGBE_ERROR_POLLING,
929251964Sjfv			     "Software semaphore SMBI between device drivers "
930251964Sjfv			     "not granted.\n");
931230775Sjfv	}
932230775Sjfv
933230775Sjfv	return status;
934230775Sjfv}
935230775Sjfv
936230775Sjfv/**
937283620Serj *  ixgbe_release_swfw_sync_semaphore - Release hardware semaphore
938230775Sjfv *  @hw: pointer to hardware structure
939230775Sjfv *
940230775Sjfv *  This function clears hardware semaphore bits.
941230775Sjfv **/
942230775Sjfvstatic void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw)
943230775Sjfv{
944230775Sjfv	u32 swsm;
945230775Sjfv
946230775Sjfv	DEBUGFUNC("ixgbe_release_swfw_sync_semaphore");
947230775Sjfv
948230775Sjfv	/* Release both semaphores by writing 0 to the bits REGSMP and SMBI */
949230775Sjfv
950295524Ssbruno	swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
951283620Serj	swsm &= ~IXGBE_SWFW_REGSMP;
952295524Ssbruno	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swsm);
953283620Serj
954295524Ssbruno	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
955230775Sjfv	swsm &= ~IXGBE_SWSM_SMBI;
956295524Ssbruno	IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm);
957230775Sjfv
958230775Sjfv	IXGBE_WRITE_FLUSH(hw);
959230775Sjfv}
960230775Sjfv
961230775Sjfv/**
962315333Serj *  ixgbe_init_swfw_sync_X540 - Release hardware semaphore
963315333Serj *  @hw: pointer to hardware structure
964315333Serj *
965315333Serj *  This function reset hardware semaphore bits for a semaphore that may
966315333Serj *  have be left locked due to a catastrophic failure.
967315333Serj **/
968315333Serjvoid ixgbe_init_swfw_sync_X540(struct ixgbe_hw *hw)
969315333Serj{
970315333Serj	/* First try to grab the semaphore but we don't need to bother
971315333Serj	 * looking to see whether we got the lock or  not since we do
972315333Serj	 * the same thing regardless of whether we got the lock or not.
973315333Serj	 * We got the lock - we release it.
974315333Serj	 * We timeout trying to get the lock - we force its release.
975315333Serj	 */
976315333Serj	ixgbe_get_swfw_sync_semaphore(hw);
977315333Serj	ixgbe_release_swfw_sync_semaphore(hw);
978315333Serj}
979315333Serj
980315333Serj/**
981230775Sjfv * ixgbe_blink_led_start_X540 - Blink LED based on index.
982230775Sjfv * @hw: pointer to hardware structure
983230775Sjfv * @index: led number to blink
984230775Sjfv *
985230775Sjfv * Devices that implement the version 2 interface:
986230775Sjfv *   X540
987230775Sjfv **/
988230775Sjfvs32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index)
989230775Sjfv{
990230775Sjfv	u32 macc_reg;
991230775Sjfv	u32 ledctl_reg;
992230775Sjfv	ixgbe_link_speed speed;
993230775Sjfv	bool link_up;
994230775Sjfv
995230775Sjfv	DEBUGFUNC("ixgbe_blink_led_start_X540");
996230775Sjfv
997315333Serj	if (index > 3)
998315333Serj		return IXGBE_ERR_PARAM;
999315333Serj
1000230775Sjfv	/*
1001230775Sjfv	 * Link should be up in order for the blink bit in the LED control
1002230775Sjfv	 * register to work. Force link and speed in the MAC if link is down.
1003230775Sjfv	 * This will be reversed when we stop the blinking.
1004230775Sjfv	 */
1005230775Sjfv	hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
1006230775Sjfv	if (link_up == FALSE) {
1007230775Sjfv		macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
1008230775Sjfv		macc_reg |= IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS;
1009230775Sjfv		IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
1010230775Sjfv	}
1011230775Sjfv	/* Set the LED to LINK_UP + BLINK. */
1012230775Sjfv	ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
1013230775Sjfv	ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
1014230775Sjfv	ledctl_reg |= IXGBE_LED_BLINK(index);
1015230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
1016230775Sjfv	IXGBE_WRITE_FLUSH(hw);
1017230775Sjfv
1018230775Sjfv	return IXGBE_SUCCESS;
1019230775Sjfv}
1020230775Sjfv
1021230775Sjfv/**
1022230775Sjfv * ixgbe_blink_led_stop_X540 - Stop blinking LED based on index.
1023230775Sjfv * @hw: pointer to hardware structure
1024230775Sjfv * @index: led number to stop blinking
1025230775Sjfv *
1026230775Sjfv * Devices that implement the version 2 interface:
1027230775Sjfv *   X540
1028230775Sjfv **/
1029230775Sjfvs32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index)
1030230775Sjfv{
1031230775Sjfv	u32 macc_reg;
1032230775Sjfv	u32 ledctl_reg;
1033230775Sjfv
1034315333Serj	if (index > 3)
1035315333Serj		return IXGBE_ERR_PARAM;
1036315333Serj
1037230775Sjfv	DEBUGFUNC("ixgbe_blink_led_stop_X540");
1038230775Sjfv
1039230775Sjfv	/* Restore the LED to its default value. */
1040230775Sjfv	ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
1041230775Sjfv	ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
1042230775Sjfv	ledctl_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
1043230775Sjfv	ledctl_reg &= ~IXGBE_LED_BLINK(index);
1044230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
1045230775Sjfv
1046230775Sjfv	/* Unforce link and speed in the MAC. */
1047230775Sjfv	macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
1048230775Sjfv	macc_reg &= ~(IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS);
1049230775Sjfv	IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
1050230775Sjfv	IXGBE_WRITE_FLUSH(hw);
1051230775Sjfv
1052230775Sjfv	return IXGBE_SUCCESS;
1053230775Sjfv}
1054