xref: /freebsd/sys/dev/ixgbe/ixgbe_x550.c (revision 183621655613bcc97e4ec7d22adbc829347ed426)
16f37f232SEric Joyner /******************************************************************************
26f37f232SEric Joyner 
38455e365SKevin Bowling   Copyright (c) 2001-2020, Intel Corporation
46f37f232SEric Joyner   All rights reserved.
56f37f232SEric Joyner 
66f37f232SEric Joyner   Redistribution and use in source and binary forms, with or without
76f37f232SEric Joyner   modification, are permitted provided that the following conditions are met:
86f37f232SEric Joyner 
96f37f232SEric Joyner    1. Redistributions of source code must retain the above copyright notice,
106f37f232SEric Joyner       this list of conditions and the following disclaimer.
116f37f232SEric Joyner 
126f37f232SEric Joyner    2. Redistributions in binary form must reproduce the above copyright
136f37f232SEric Joyner       notice, this list of conditions and the following disclaimer in the
146f37f232SEric Joyner       documentation and/or other materials provided with the distribution.
156f37f232SEric Joyner 
166f37f232SEric Joyner    3. Neither the name of the Intel Corporation nor the names of its
176f37f232SEric Joyner       contributors may be used to endorse or promote products derived from
186f37f232SEric Joyner       this software without specific prior written permission.
196f37f232SEric Joyner 
206f37f232SEric Joyner   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
216f37f232SEric Joyner   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226f37f232SEric Joyner   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236f37f232SEric Joyner   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
246f37f232SEric Joyner   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
256f37f232SEric Joyner   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
266f37f232SEric Joyner   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
276f37f232SEric Joyner   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
286f37f232SEric Joyner   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
296f37f232SEric Joyner   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
306f37f232SEric Joyner   POSSIBILITY OF SUCH DAMAGE.
316f37f232SEric Joyner 
326f37f232SEric Joyner ******************************************************************************/
336f37f232SEric Joyner 
346f37f232SEric Joyner #include "ixgbe_x550.h"
356f37f232SEric Joyner #include "ixgbe_x540.h"
366f37f232SEric Joyner #include "ixgbe_type.h"
376f37f232SEric Joyner #include "ixgbe_api.h"
386f37f232SEric Joyner #include "ixgbe_common.h"
396f37f232SEric Joyner #include "ixgbe_phy.h"
406f37f232SEric Joyner 
416f37f232SEric Joyner static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed);
428eb6488eSEric Joyner static s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
438eb6488eSEric Joyner static void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
448eb6488eSEric Joyner static s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw);
456f37f232SEric Joyner 
466f37f232SEric Joyner /**
476f37f232SEric Joyner  * ixgbe_init_ops_X550 - Inits func ptrs and MAC type
486f37f232SEric Joyner  * @hw: pointer to hardware structure
496f37f232SEric Joyner  *
506f37f232SEric Joyner  * Initialize the function pointers and assign the MAC type for X550.
516f37f232SEric Joyner  * Does not touch the hardware.
526f37f232SEric Joyner  **/
ixgbe_init_ops_X550(struct ixgbe_hw * hw)536f37f232SEric Joyner s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw)
546f37f232SEric Joyner {
556f37f232SEric Joyner 	struct ixgbe_mac_info *mac = &hw->mac;
566f37f232SEric Joyner 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
576f37f232SEric Joyner 	s32 ret_val;
586f37f232SEric Joyner 
596f37f232SEric Joyner 	DEBUGFUNC("ixgbe_init_ops_X550");
606f37f232SEric Joyner 
616f37f232SEric Joyner 	ret_val = ixgbe_init_ops_X540(hw);
626f37f232SEric Joyner 	mac->ops.dmac_config = ixgbe_dmac_config_X550;
636f37f232SEric Joyner 	mac->ops.dmac_config_tcs = ixgbe_dmac_config_tcs_X550;
646f37f232SEric Joyner 	mac->ops.dmac_update_tcs = ixgbe_dmac_update_tcs_X550;
658eb6488eSEric Joyner 	mac->ops.setup_eee = NULL;
666f37f232SEric Joyner 	mac->ops.set_source_address_pruning =
676f37f232SEric Joyner 			ixgbe_set_source_address_pruning_X550;
686f37f232SEric Joyner 	mac->ops.set_ethertype_anti_spoofing =
696f37f232SEric Joyner 			ixgbe_set_ethertype_anti_spoofing_X550;
706f37f232SEric Joyner 
716f37f232SEric Joyner 	mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
726f37f232SEric Joyner 	eeprom->ops.init_params = ixgbe_init_eeprom_params_X550;
736f37f232SEric Joyner 	eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
746f37f232SEric Joyner 	eeprom->ops.read = ixgbe_read_ee_hostif_X550;
756f37f232SEric Joyner 	eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550;
766f37f232SEric Joyner 	eeprom->ops.write = ixgbe_write_ee_hostif_X550;
776f37f232SEric Joyner 	eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550;
786f37f232SEric Joyner 	eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
796f37f232SEric Joyner 	eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
806f37f232SEric Joyner 
816f37f232SEric Joyner 	mac->ops.disable_mdd = ixgbe_disable_mdd_X550;
826f37f232SEric Joyner 	mac->ops.enable_mdd = ixgbe_enable_mdd_X550;
836f37f232SEric Joyner 	mac->ops.mdd_event = ixgbe_mdd_event_X550;
846f37f232SEric Joyner 	mac->ops.restore_mdd_vf = ixgbe_restore_mdd_vf_X550;
85b622bdb4SXiaoyun Li 	mac->ops.fw_recovery_mode = ixgbe_fw_recovery_mode_X550;
866f37f232SEric Joyner 	mac->ops.disable_rx = ixgbe_disable_rx_x550;
878eb6488eSEric Joyner 	/* Manageability interface */
888eb6488eSEric Joyner 	mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_x550;
898eb6488eSEric Joyner 	switch (hw->device_id) {
908eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_1G_T:
918eb6488eSEric Joyner 		hw->mac.ops.led_on = NULL;
928eb6488eSEric Joyner 		hw->mac.ops.led_off = NULL;
938eb6488eSEric Joyner 		break;
948eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_10G_T:
958eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_10G_T:
966f37f232SEric Joyner 		hw->mac.ops.led_on = ixgbe_led_on_t_X550em;
976f37f232SEric Joyner 		hw->mac.ops.led_off = ixgbe_led_off_t_X550em;
988eb6488eSEric Joyner 		break;
998eb6488eSEric Joyner 	default:
1008eb6488eSEric Joyner 		break;
1016f37f232SEric Joyner 	}
1026f37f232SEric Joyner 	return ret_val;
1036f37f232SEric Joyner }
1046f37f232SEric Joyner 
1056f37f232SEric Joyner /**
1066f37f232SEric Joyner  * ixgbe_read_cs4227 - Read CS4227 register
1076f37f232SEric Joyner  * @hw: pointer to hardware structure
1086f37f232SEric Joyner  * @reg: register number to write
1096f37f232SEric Joyner  * @value: pointer to receive value read
1106f37f232SEric Joyner  *
1116f37f232SEric Joyner  * Returns status code
1126f37f232SEric Joyner  **/
ixgbe_read_cs4227(struct ixgbe_hw * hw,u16 reg,u16 * value)1136f37f232SEric Joyner static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
1146f37f232SEric Joyner {
1158eb6488eSEric Joyner 	return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);
1166f37f232SEric Joyner }
1176f37f232SEric Joyner 
1186f37f232SEric Joyner /**
1196f37f232SEric Joyner  * ixgbe_write_cs4227 - Write CS4227 register
1206f37f232SEric Joyner  * @hw: pointer to hardware structure
1216f37f232SEric Joyner  * @reg: register number to write
1226f37f232SEric Joyner  * @value: value to write to register
1236f37f232SEric Joyner  *
1246f37f232SEric Joyner  * Returns status code
1256f37f232SEric Joyner  **/
ixgbe_write_cs4227(struct ixgbe_hw * hw,u16 reg,u16 value)1266f37f232SEric Joyner static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
1276f37f232SEric Joyner {
1288eb6488eSEric Joyner 	return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);
1296f37f232SEric Joyner }
1306f37f232SEric Joyner 
1316f37f232SEric Joyner /**
1326f37f232SEric Joyner  * ixgbe_read_pe - Read register from port expander
1336f37f232SEric Joyner  * @hw: pointer to hardware structure
1346f37f232SEric Joyner  * @reg: register number to read
1356f37f232SEric Joyner  * @value: pointer to receive read value
1366f37f232SEric Joyner  *
1376f37f232SEric Joyner  * Returns status code
1386f37f232SEric Joyner  **/
ixgbe_read_pe(struct ixgbe_hw * hw,u8 reg,u8 * value)1396f37f232SEric Joyner static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value)
1406f37f232SEric Joyner {
1416f37f232SEric Joyner 	s32 status;
1426f37f232SEric Joyner 
1436f37f232SEric Joyner 	status = ixgbe_read_i2c_byte_unlocked(hw, reg, IXGBE_PE, value);
1446f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
1456f37f232SEric Joyner 		ERROR_REPORT2(IXGBE_ERROR_CAUTION,
1466f37f232SEric Joyner 			      "port expander access failed with %d\n", status);
1476f37f232SEric Joyner 	return status;
1486f37f232SEric Joyner }
1496f37f232SEric Joyner 
1506f37f232SEric Joyner /**
1516f37f232SEric Joyner  * ixgbe_write_pe - Write register to port expander
1526f37f232SEric Joyner  * @hw: pointer to hardware structure
1536f37f232SEric Joyner  * @reg: register number to write
1546f37f232SEric Joyner  * @value: value to write
1556f37f232SEric Joyner  *
1566f37f232SEric Joyner  * Returns status code
1576f37f232SEric Joyner  **/
ixgbe_write_pe(struct ixgbe_hw * hw,u8 reg,u8 value)1586f37f232SEric Joyner static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value)
1596f37f232SEric Joyner {
1606f37f232SEric Joyner 	s32 status;
1616f37f232SEric Joyner 
1626f37f232SEric Joyner 	status = ixgbe_write_i2c_byte_unlocked(hw, reg, IXGBE_PE, value);
1636f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
1646f37f232SEric Joyner 		ERROR_REPORT2(IXGBE_ERROR_CAUTION,
1656f37f232SEric Joyner 			      "port expander access failed with %d\n", status);
1666f37f232SEric Joyner 	return status;
1676f37f232SEric Joyner }
1686f37f232SEric Joyner 
1696f37f232SEric Joyner /**
1706f37f232SEric Joyner  * ixgbe_reset_cs4227 - Reset CS4227 using port expander
1716f37f232SEric Joyner  * @hw: pointer to hardware structure
1726f37f232SEric Joyner  *
173a9ca1c79SSean Bruno  * This function assumes that the caller has acquired the proper semaphore.
1746f37f232SEric Joyner  * Returns error code
1756f37f232SEric Joyner  **/
ixgbe_reset_cs4227(struct ixgbe_hw * hw)1766f37f232SEric Joyner static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
1776f37f232SEric Joyner {
1786f37f232SEric Joyner 	s32 status;
179a9ca1c79SSean Bruno 	u32 retry;
180a9ca1c79SSean Bruno 	u16 value;
1816f37f232SEric Joyner 	u8 reg;
1826f37f232SEric Joyner 
183a9ca1c79SSean Bruno 	/* Trigger hard reset. */
1846f37f232SEric Joyner 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
1856f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
1866f37f232SEric Joyner 		return status;
1876f37f232SEric Joyner 	reg |= IXGBE_PE_BIT1;
1886f37f232SEric Joyner 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
1896f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
1906f37f232SEric Joyner 		return status;
1916f37f232SEric Joyner 
1926f37f232SEric Joyner 	status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, &reg);
1936f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
1946f37f232SEric Joyner 		return status;
1956f37f232SEric Joyner 	reg &= ~IXGBE_PE_BIT1;
1966f37f232SEric Joyner 	status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg);
1976f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
1986f37f232SEric Joyner 		return status;
1996f37f232SEric Joyner 
2006f37f232SEric Joyner 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
2016f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
2026f37f232SEric Joyner 		return status;
2036f37f232SEric Joyner 	reg &= ~IXGBE_PE_BIT1;
2046f37f232SEric Joyner 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
2056f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
2066f37f232SEric Joyner 		return status;
2076f37f232SEric Joyner 
2086f37f232SEric Joyner 	usec_delay(IXGBE_CS4227_RESET_HOLD);
2096f37f232SEric Joyner 
2106f37f232SEric Joyner 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
2116f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
2126f37f232SEric Joyner 		return status;
2136f37f232SEric Joyner 	reg |= IXGBE_PE_BIT1;
2146f37f232SEric Joyner 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
2156f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
2166f37f232SEric Joyner 		return status;
2176f37f232SEric Joyner 
218a9ca1c79SSean Bruno 	/* Wait for the reset to complete. */
2196f37f232SEric Joyner 	msec_delay(IXGBE_CS4227_RESET_DELAY);
220a9ca1c79SSean Bruno 	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
221a9ca1c79SSean Bruno 		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
222a9ca1c79SSean Bruno 					   &value);
223a9ca1c79SSean Bruno 		if (status == IXGBE_SUCCESS &&
224a9ca1c79SSean Bruno 		    value == IXGBE_CS4227_EEPROM_LOAD_OK)
225a9ca1c79SSean Bruno 			break;
226a9ca1c79SSean Bruno 		msec_delay(IXGBE_CS4227_CHECK_DELAY);
227a9ca1c79SSean Bruno 	}
228a9ca1c79SSean Bruno 	if (retry == IXGBE_CS4227_RETRIES) {
229a9ca1c79SSean Bruno 		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
230a9ca1c79SSean Bruno 			"CS4227 reset did not complete.");
231a9ca1c79SSean Bruno 		return IXGBE_ERR_PHY;
232a9ca1c79SSean Bruno 	}
233a9ca1c79SSean Bruno 
234a9ca1c79SSean Bruno 	status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
235a9ca1c79SSean Bruno 	if (status != IXGBE_SUCCESS ||
236a9ca1c79SSean Bruno 	    !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
237a9ca1c79SSean Bruno 		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
238a9ca1c79SSean Bruno 			"CS4227 EEPROM did not load successfully.");
239a9ca1c79SSean Bruno 		return IXGBE_ERR_PHY;
240a9ca1c79SSean Bruno 	}
2416f37f232SEric Joyner 
2426f37f232SEric Joyner 	return IXGBE_SUCCESS;
2436f37f232SEric Joyner }
2446f37f232SEric Joyner 
2456f37f232SEric Joyner /**
2466f37f232SEric Joyner  * ixgbe_check_cs4227 - Check CS4227 and reset as needed
2476f37f232SEric Joyner  * @hw: pointer to hardware structure
2486f37f232SEric Joyner  **/
ixgbe_check_cs4227(struct ixgbe_hw * hw)2496f37f232SEric Joyner static void ixgbe_check_cs4227(struct ixgbe_hw *hw)
2506f37f232SEric Joyner {
251a9ca1c79SSean Bruno 	s32 status = IXGBE_SUCCESS;
2526f37f232SEric Joyner 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
253a9ca1c79SSean Bruno 	u16 value = 0;
2546f37f232SEric Joyner 	u8 retry;
2556f37f232SEric Joyner 
2566f37f232SEric Joyner 	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
2576f37f232SEric Joyner 		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
2586f37f232SEric Joyner 		if (status != IXGBE_SUCCESS) {
2596f37f232SEric Joyner 			ERROR_REPORT2(IXGBE_ERROR_CAUTION,
260a9ca1c79SSean Bruno 				"semaphore failed with %d", status);
261a9ca1c79SSean Bruno 			msec_delay(IXGBE_CS4227_CHECK_DELAY);
262a9ca1c79SSean Bruno 			continue;
2636f37f232SEric Joyner 		}
264a9ca1c79SSean Bruno 
265a9ca1c79SSean Bruno 		/* Get status of reset flow. */
266a9ca1c79SSean Bruno 		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
267a9ca1c79SSean Bruno 
268a9ca1c79SSean Bruno 		if (status == IXGBE_SUCCESS &&
269a9ca1c79SSean Bruno 		    value == IXGBE_CS4227_RESET_COMPLETE)
270a9ca1c79SSean Bruno 			goto out;
271a9ca1c79SSean Bruno 
272a9ca1c79SSean Bruno 		if (status != IXGBE_SUCCESS ||
273a9ca1c79SSean Bruno 		    value != IXGBE_CS4227_RESET_PENDING)
274a9ca1c79SSean Bruno 			break;
275a9ca1c79SSean Bruno 
276a9ca1c79SSean Bruno 		/* Reset is pending. Wait and check again. */
2776f37f232SEric Joyner 		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
278a9ca1c79SSean Bruno 		msec_delay(IXGBE_CS4227_CHECK_DELAY);
2796f37f232SEric Joyner 	}
280a9ca1c79SSean Bruno 
281a9ca1c79SSean Bruno 	/* If still pending, assume other instance failed. */
282a9ca1c79SSean Bruno 	if (retry == IXGBE_CS4227_RETRIES) {
283a9ca1c79SSean Bruno 		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
284a9ca1c79SSean Bruno 		if (status != IXGBE_SUCCESS) {
2856f37f232SEric Joyner 			ERROR_REPORT2(IXGBE_ERROR_CAUTION,
286a9ca1c79SSean Bruno 				      "semaphore failed with %d", status);
287a9ca1c79SSean Bruno 			return;
288a9ca1c79SSean Bruno 		}
289a9ca1c79SSean Bruno 	}
290a9ca1c79SSean Bruno 
291a9ca1c79SSean Bruno 	/* Reset the CS4227. */
292a9ca1c79SSean Bruno 	status = ixgbe_reset_cs4227(hw);
293a9ca1c79SSean Bruno 	if (status != IXGBE_SUCCESS) {
294a9ca1c79SSean Bruno 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
295a9ca1c79SSean Bruno 			"CS4227 reset failed: %d", status);
296a9ca1c79SSean Bruno 		goto out;
297a9ca1c79SSean Bruno 	}
298a9ca1c79SSean Bruno 
299a9ca1c79SSean Bruno 	/* Reset takes so long, temporarily release semaphore in case the
300a9ca1c79SSean Bruno 	 * other driver instance is waiting for the reset indication.
301a9ca1c79SSean Bruno 	 */
302a9ca1c79SSean Bruno 	ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
303a9ca1c79SSean Bruno 			   IXGBE_CS4227_RESET_PENDING);
304a9ca1c79SSean Bruno 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
305a9ca1c79SSean Bruno 	msec_delay(10);
306a9ca1c79SSean Bruno 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
307a9ca1c79SSean Bruno 	if (status != IXGBE_SUCCESS) {
308a9ca1c79SSean Bruno 		ERROR_REPORT2(IXGBE_ERROR_CAUTION,
309a9ca1c79SSean Bruno 			"semaphore failed with %d", status);
310a9ca1c79SSean Bruno 		return;
311a9ca1c79SSean Bruno 	}
312a9ca1c79SSean Bruno 
313a9ca1c79SSean Bruno 	/* Record completion for next time. */
314a9ca1c79SSean Bruno 	status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
315a9ca1c79SSean Bruno 		IXGBE_CS4227_RESET_COMPLETE);
316a9ca1c79SSean Bruno 
317a9ca1c79SSean Bruno out:
318a9ca1c79SSean Bruno 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
319a9ca1c79SSean Bruno 	msec_delay(hw->eeprom.semaphore_delay);
3206f37f232SEric Joyner }
3216f37f232SEric Joyner 
3226f37f232SEric Joyner /**
3236f37f232SEric Joyner  * ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control
3246f37f232SEric Joyner  * @hw: pointer to hardware structure
3256f37f232SEric Joyner  **/
ixgbe_setup_mux_ctl(struct ixgbe_hw * hw)3266f37f232SEric Joyner static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
3276f37f232SEric Joyner {
3286f37f232SEric Joyner 	u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
3296f37f232SEric Joyner 
3306f37f232SEric Joyner 	if (hw->bus.lan_id) {
3316f37f232SEric Joyner 		esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
3326f37f232SEric Joyner 		esdp |= IXGBE_ESDP_SDP1_DIR;
3336f37f232SEric Joyner 	}
3346f37f232SEric Joyner 	esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
3356f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
3366f37f232SEric Joyner 	IXGBE_WRITE_FLUSH(hw);
3376f37f232SEric Joyner }
3386f37f232SEric Joyner 
3396f37f232SEric Joyner /**
3406f37f232SEric Joyner  * ixgbe_identify_phy_x550em - Get PHY type based on device id
3416f37f232SEric Joyner  * @hw: pointer to hardware structure
3426f37f232SEric Joyner  *
3436f37f232SEric Joyner  * Returns error code
3446f37f232SEric Joyner  */
ixgbe_identify_phy_x550em(struct ixgbe_hw * hw)3456f37f232SEric Joyner static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
3466f37f232SEric Joyner {
3478eb6488eSEric Joyner 	hw->mac.ops.set_lan_id(hw);
3488eb6488eSEric Joyner 
3498eb6488eSEric Joyner 	ixgbe_read_mng_if_sel_x550em(hw);
3508eb6488eSEric Joyner 
3516f37f232SEric Joyner 	switch (hw->device_id) {
3528eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_SFP:
3530a4f0befSXiaoyun Li 		return ixgbe_identify_sfp_module_X550em(hw);
3546f37f232SEric Joyner 	case IXGBE_DEV_ID_X550EM_X_SFP:
3556f37f232SEric Joyner 		/* set up for CS4227 usage */
3566f37f232SEric Joyner 		ixgbe_setup_mux_ctl(hw);
3576f37f232SEric Joyner 		ixgbe_check_cs4227(hw);
35850455f73SPiotr Skajewski 		return ixgbe_identify_sfp_module_X550em(hw);
3598eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_SFP_N:
3600a4f0befSXiaoyun Li 		return ixgbe_identify_sfp_module_X550em(hw);
3616f37f232SEric Joyner 		break;
3626f37f232SEric Joyner 	case IXGBE_DEV_ID_X550EM_X_KX4:
3636f37f232SEric Joyner 		hw->phy.type = ixgbe_phy_x550em_kx4;
3646f37f232SEric Joyner 		break;
3658eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_XFI:
3668eb6488eSEric Joyner 		hw->phy.type = ixgbe_phy_x550em_xfi;
3678eb6488eSEric Joyner 		break;
3686f37f232SEric Joyner 	case IXGBE_DEV_ID_X550EM_X_KR:
3698eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_KR:
3708eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_KR_L:
3716f37f232SEric Joyner 		hw->phy.type = ixgbe_phy_x550em_kr;
3726f37f232SEric Joyner 		break;
3738eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_10G_T:
3746f37f232SEric Joyner 	case IXGBE_DEV_ID_X550EM_X_10G_T:
3756f37f232SEric Joyner 		return ixgbe_identify_phy_generic(hw);
3768eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_1G_T:
3778eb6488eSEric Joyner 		hw->phy.type = ixgbe_phy_ext_1g_t;
3788eb6488eSEric Joyner 		break;
3798eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T:
3808eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
3818eb6488eSEric Joyner 		hw->phy.type = ixgbe_phy_fw;
3828eb6488eSEric Joyner 		if (hw->bus.lan_id)
3838eb6488eSEric Joyner 			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
3848eb6488eSEric Joyner 		else
3858eb6488eSEric Joyner 			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
3868eb6488eSEric Joyner 		break;
3876f37f232SEric Joyner 	default:
3886f37f232SEric Joyner 		break;
3896f37f232SEric Joyner 	}
3906f37f232SEric Joyner 	return IXGBE_SUCCESS;
3916f37f232SEric Joyner }
3926f37f232SEric Joyner 
3938eb6488eSEric Joyner /**
3948eb6488eSEric Joyner  * ixgbe_fw_phy_activity - Perform an activity on a PHY
3958eb6488eSEric Joyner  * @hw: pointer to hardware structure
3968eb6488eSEric Joyner  * @activity: activity to perform
3978eb6488eSEric Joyner  * @data: Pointer to 4 32-bit words of data
3988eb6488eSEric Joyner  */
ixgbe_fw_phy_activity(struct ixgbe_hw * hw,u16 activity,u32 (* data)[FW_PHY_ACT_DATA_COUNT])3998eb6488eSEric Joyner s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity,
4008eb6488eSEric Joyner 			  u32 (*data)[FW_PHY_ACT_DATA_COUNT])
4018eb6488eSEric Joyner {
4028eb6488eSEric Joyner 	union {
4038eb6488eSEric Joyner 		struct ixgbe_hic_phy_activity_req cmd;
4048eb6488eSEric Joyner 		struct ixgbe_hic_phy_activity_resp rsp;
4058eb6488eSEric Joyner 	} hic;
4068eb6488eSEric Joyner 	u16 retries = FW_PHY_ACT_RETRIES;
4078eb6488eSEric Joyner 	s32 rc;
4088eb6488eSEric Joyner 	u16 i;
4098eb6488eSEric Joyner 
4108eb6488eSEric Joyner 	do {
4118eb6488eSEric Joyner 		memset(&hic, 0, sizeof(hic));
4128eb6488eSEric Joyner 		hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD;
4138eb6488eSEric Joyner 		hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN;
4148eb6488eSEric Joyner 		hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
4158eb6488eSEric Joyner 		hic.cmd.port_number = hw->bus.lan_id;
4168eb6488eSEric Joyner 		hic.cmd.activity_id = IXGBE_CPU_TO_LE16(activity);
4178eb6488eSEric Joyner 		for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
4188eb6488eSEric Joyner 			hic.cmd.data[i] = IXGBE_CPU_TO_BE32((*data)[i]);
4198eb6488eSEric Joyner 
4208eb6488eSEric Joyner 		rc = ixgbe_host_interface_command(hw, (u32 *)&hic.cmd,
4218eb6488eSEric Joyner 						  sizeof(hic.cmd),
4228eb6488eSEric Joyner 						  IXGBE_HI_COMMAND_TIMEOUT,
42379b36ec9SKevin Bowling 						  true);
4248eb6488eSEric Joyner 		if (rc != IXGBE_SUCCESS)
4258eb6488eSEric Joyner 			return rc;
4268eb6488eSEric Joyner 		if (hic.rsp.hdr.cmd_or_resp.ret_status ==
4278eb6488eSEric Joyner 		    FW_CEM_RESP_STATUS_SUCCESS) {
4288eb6488eSEric Joyner 			for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
4298eb6488eSEric Joyner 				(*data)[i] = IXGBE_BE32_TO_CPU(hic.rsp.data[i]);
4308eb6488eSEric Joyner 			return IXGBE_SUCCESS;
4318eb6488eSEric Joyner 		}
4328eb6488eSEric Joyner 		usec_delay(20);
4338eb6488eSEric Joyner 		--retries;
4348eb6488eSEric Joyner 	} while (retries > 0);
4358eb6488eSEric Joyner 
4368eb6488eSEric Joyner 	return IXGBE_ERR_HOST_INTERFACE_COMMAND;
4378eb6488eSEric Joyner }
4388eb6488eSEric Joyner 
4398eb6488eSEric Joyner static const struct {
4408eb6488eSEric Joyner 	u16 fw_speed;
4418eb6488eSEric Joyner 	ixgbe_link_speed phy_speed;
4428eb6488eSEric Joyner } ixgbe_fw_map[] = {
4438eb6488eSEric Joyner 	{ FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL },
4448eb6488eSEric Joyner 	{ FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL },
4458eb6488eSEric Joyner 	{ FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL },
4468eb6488eSEric Joyner 	{ FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL },
4478eb6488eSEric Joyner 	{ FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL },
4488eb6488eSEric Joyner 	{ FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL },
4498eb6488eSEric Joyner };
4508eb6488eSEric Joyner 
4518eb6488eSEric Joyner /**
4528eb6488eSEric Joyner  * ixgbe_get_phy_id_fw - Get the phy ID via firmware command
4538eb6488eSEric Joyner  * @hw: pointer to hardware structure
4548eb6488eSEric Joyner  *
4558eb6488eSEric Joyner  * Returns error code
4568eb6488eSEric Joyner  */
ixgbe_get_phy_id_fw(struct ixgbe_hw * hw)4578eb6488eSEric Joyner static s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw)
4588eb6488eSEric Joyner {
4598eb6488eSEric Joyner 	u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
4608eb6488eSEric Joyner 	u16 phy_speeds;
4618eb6488eSEric Joyner 	u16 phy_id_lo;
4628eb6488eSEric Joyner 	s32 rc;
4638eb6488eSEric Joyner 	u16 i;
4648eb6488eSEric Joyner 
4658eb6488eSEric Joyner 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info);
4668eb6488eSEric Joyner 	if (rc)
4678eb6488eSEric Joyner 		return rc;
4688eb6488eSEric Joyner 
4698eb6488eSEric Joyner 	hw->phy.speeds_supported = 0;
4708eb6488eSEric Joyner 	phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK;
4718eb6488eSEric Joyner 	for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) {
4728eb6488eSEric Joyner 		if (phy_speeds & ixgbe_fw_map[i].fw_speed)
4738eb6488eSEric Joyner 			hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed;
4748eb6488eSEric Joyner 	}
4758eb6488eSEric Joyner 	if (!hw->phy.autoneg_advertised)
4768eb6488eSEric Joyner 		hw->phy.autoneg_advertised = hw->phy.speeds_supported;
4778eb6488eSEric Joyner 
4788eb6488eSEric Joyner 	hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK;
4798eb6488eSEric Joyner 	phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK;
4808eb6488eSEric Joyner 	hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK;
4818eb6488eSEric Joyner 	hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK;
4828eb6488eSEric Joyner 	if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK)
4838eb6488eSEric Joyner 		return IXGBE_ERR_PHY_ADDR_INVALID;
4848eb6488eSEric Joyner 	return IXGBE_SUCCESS;
4858eb6488eSEric Joyner }
4868eb6488eSEric Joyner 
4878eb6488eSEric Joyner /**
4888eb6488eSEric Joyner  * ixgbe_identify_phy_fw - Get PHY type based on firmware command
4898eb6488eSEric Joyner  * @hw: pointer to hardware structure
4908eb6488eSEric Joyner  *
4918eb6488eSEric Joyner  * Returns error code
4928eb6488eSEric Joyner  */
ixgbe_identify_phy_fw(struct ixgbe_hw * hw)4938eb6488eSEric Joyner static s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw)
4948eb6488eSEric Joyner {
4958eb6488eSEric Joyner 	if (hw->bus.lan_id)
4968eb6488eSEric Joyner 		hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
4978eb6488eSEric Joyner 	else
4988eb6488eSEric Joyner 		hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
4998eb6488eSEric Joyner 
5008eb6488eSEric Joyner 	hw->phy.type = ixgbe_phy_fw;
5018eb6488eSEric Joyner 	hw->phy.ops.read_reg = NULL;
5028eb6488eSEric Joyner 	hw->phy.ops.write_reg = NULL;
5038eb6488eSEric Joyner 	return ixgbe_get_phy_id_fw(hw);
5048eb6488eSEric Joyner }
5058eb6488eSEric Joyner 
5068eb6488eSEric Joyner /**
5078eb6488eSEric Joyner  * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY
5088eb6488eSEric Joyner  * @hw: pointer to hardware structure
5098eb6488eSEric Joyner  *
5108eb6488eSEric Joyner  * Returns error code
5118eb6488eSEric Joyner  */
ixgbe_shutdown_fw_phy(struct ixgbe_hw * hw)5128eb6488eSEric Joyner s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw)
5138eb6488eSEric Joyner {
5148eb6488eSEric Joyner 	u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
5158eb6488eSEric Joyner 
5168eb6488eSEric Joyner 	setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF;
5178eb6488eSEric Joyner 	return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup);
5188eb6488eSEric Joyner }
5198eb6488eSEric Joyner 
ixgbe_read_phy_reg_x550em(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)5206f37f232SEric Joyner static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
5216f37f232SEric Joyner 				     u32 device_type, u16 *phy_data)
5226f37f232SEric Joyner {
5236f37f232SEric Joyner 	UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, *phy_data);
5246f37f232SEric Joyner 	return IXGBE_NOT_IMPLEMENTED;
5256f37f232SEric Joyner }
5266f37f232SEric Joyner 
ixgbe_write_phy_reg_x550em(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)5276f37f232SEric Joyner static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
5286f37f232SEric Joyner 				      u32 device_type, u16 phy_data)
5296f37f232SEric Joyner {
5306f37f232SEric Joyner 	UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, phy_data);
5316f37f232SEric Joyner 	return IXGBE_NOT_IMPLEMENTED;
5326f37f232SEric Joyner }
5336f37f232SEric Joyner 
5346f37f232SEric Joyner /**
5358eb6488eSEric Joyner  * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
5368eb6488eSEric Joyner  * @hw: pointer to the hardware structure
5378eb6488eSEric Joyner  * @addr: I2C bus address to read from
5388eb6488eSEric Joyner  * @reg: I2C device register to read from
5398eb6488eSEric Joyner  * @val: pointer to location to receive read value
5408eb6488eSEric Joyner  *
5418eb6488eSEric Joyner  * Returns an error code on error.
5428eb6488eSEric Joyner  **/
ixgbe_read_i2c_combined_generic(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 * val)5438eb6488eSEric Joyner static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
5448eb6488eSEric Joyner 					   u16 reg, u16 *val)
5458eb6488eSEric Joyner {
54679b36ec9SKevin Bowling 	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true);
5478eb6488eSEric Joyner }
5488eb6488eSEric Joyner 
5498eb6488eSEric Joyner /**
5508eb6488eSEric Joyner  * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
5518eb6488eSEric Joyner  * @hw: pointer to the hardware structure
5528eb6488eSEric Joyner  * @addr: I2C bus address to read from
5538eb6488eSEric Joyner  * @reg: I2C device register to read from
5548eb6488eSEric Joyner  * @val: pointer to location to receive read value
5558eb6488eSEric Joyner  *
5568eb6488eSEric Joyner  * Returns an error code on error.
5578eb6488eSEric Joyner  **/
5588eb6488eSEric Joyner static s32
ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 * val)5598eb6488eSEric Joyner ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
5608eb6488eSEric Joyner 					 u16 reg, u16 *val)
5618eb6488eSEric Joyner {
56279b36ec9SKevin Bowling 	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false);
5638eb6488eSEric Joyner }
5648eb6488eSEric Joyner 
5658eb6488eSEric Joyner /**
5668eb6488eSEric Joyner  * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
5678eb6488eSEric Joyner  * @hw: pointer to the hardware structure
5688eb6488eSEric Joyner  * @addr: I2C bus address to write to
5698eb6488eSEric Joyner  * @reg: I2C device register to write to
5708eb6488eSEric Joyner  * @val: value to write
5718eb6488eSEric Joyner  *
5728eb6488eSEric Joyner  * Returns an error code on error.
5738eb6488eSEric Joyner  **/
ixgbe_write_i2c_combined_generic(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 val)5748eb6488eSEric Joyner static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
5758eb6488eSEric Joyner 					    u8 addr, u16 reg, u16 val)
5768eb6488eSEric Joyner {
57779b36ec9SKevin Bowling 	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
5788eb6488eSEric Joyner }
5798eb6488eSEric Joyner 
5808eb6488eSEric Joyner /**
5818eb6488eSEric Joyner  * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
5828eb6488eSEric Joyner  * @hw: pointer to the hardware structure
5838eb6488eSEric Joyner  * @addr: I2C bus address to write to
5848eb6488eSEric Joyner  * @reg: I2C device register to write to
5858eb6488eSEric Joyner  * @val: value to write
5868eb6488eSEric Joyner  *
5878eb6488eSEric Joyner  * Returns an error code on error.
5888eb6488eSEric Joyner  **/
5898eb6488eSEric Joyner static s32
ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 val)5908eb6488eSEric Joyner ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
5918eb6488eSEric Joyner 					  u8 addr, u16 reg, u16 val)
5928eb6488eSEric Joyner {
59379b36ec9SKevin Bowling 	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false);
5948eb6488eSEric Joyner }
5958eb6488eSEric Joyner 
5968eb6488eSEric Joyner /**
5976f37f232SEric Joyner *  ixgbe_init_ops_X550EM - Inits func ptrs and MAC type
5986f37f232SEric Joyner *  @hw: pointer to hardware structure
5996f37f232SEric Joyner *
6006f37f232SEric Joyner *  Initialize the function pointers and for MAC type X550EM.
6016f37f232SEric Joyner *  Does not touch the hardware.
6026f37f232SEric Joyner **/
ixgbe_init_ops_X550EM(struct ixgbe_hw * hw)6036f37f232SEric Joyner s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw)
6046f37f232SEric Joyner {
6056f37f232SEric Joyner 	struct ixgbe_mac_info *mac = &hw->mac;
6066f37f232SEric Joyner 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
6076f37f232SEric Joyner 	struct ixgbe_phy_info *phy = &hw->phy;
6086f37f232SEric Joyner 	s32 ret_val;
6096f37f232SEric Joyner 
6106f37f232SEric Joyner 	DEBUGFUNC("ixgbe_init_ops_X550EM");
6116f37f232SEric Joyner 
6126f37f232SEric Joyner 	/* Similar to X550 so start there. */
6136f37f232SEric Joyner 	ret_val = ixgbe_init_ops_X550(hw);
6146f37f232SEric Joyner 
6156f37f232SEric Joyner 	/* Since this function eventually calls
6166f37f232SEric Joyner 	 * ixgbe_init_ops_540 by design, we are setting
6176f37f232SEric Joyner 	 * the pointers to NULL explicitly here to overwrite
6186f37f232SEric Joyner 	 * the values being set in the x540 function.
6196f37f232SEric Joyner 	 */
6203f66b96dSKevin Bowling 	/* Thermal sensor not supported in x550EM */
6213f66b96dSKevin Bowling 	mac->ops.get_thermal_sensor_data = NULL;
6223f66b96dSKevin Bowling 	mac->ops.init_thermal_sensor_thresh = NULL;
6233f66b96dSKevin Bowling 	mac->thermal_sensor_enabled = false;
6246f37f232SEric Joyner 
6258eb6488eSEric Joyner 	/* Bypass not supported in x550EM */
6268eb6488eSEric Joyner 	mac->ops.bypass_rw = NULL;
6278eb6488eSEric Joyner 	mac->ops.bypass_valid_rd = NULL;
6288eb6488eSEric Joyner 	mac->ops.bypass_set = NULL;
6298eb6488eSEric Joyner 	mac->ops.bypass_rd_eep = NULL;
6308eb6488eSEric Joyner 
6316f37f232SEric Joyner 	/* FCOE not supported in x550EM */
6326f37f232SEric Joyner 	mac->ops.get_san_mac_addr = NULL;
6336f37f232SEric Joyner 	mac->ops.set_san_mac_addr = NULL;
6346f37f232SEric Joyner 	mac->ops.get_wwn_prefix = NULL;
6356f37f232SEric Joyner 	mac->ops.get_fcoe_boot_status = NULL;
6366f37f232SEric Joyner 
6376f37f232SEric Joyner 	/* IPsec not supported in x550EM */
6386f37f232SEric Joyner 	mac->ops.disable_sec_rx_path = NULL;
6396f37f232SEric Joyner 	mac->ops.enable_sec_rx_path = NULL;
6406f37f232SEric Joyner 
6416f37f232SEric Joyner 	/* AUTOC register is not present in x550EM. */
6426f37f232SEric Joyner 	mac->ops.prot_autoc_read = NULL;
6436f37f232SEric Joyner 	mac->ops.prot_autoc_write = NULL;
6446f37f232SEric Joyner 
6456f37f232SEric Joyner 	/* X550EM bus type is internal*/
6466f37f232SEric Joyner 	hw->bus.type = ixgbe_bus_type_internal;
6476f37f232SEric Joyner 	mac->ops.get_bus_info = ixgbe_get_bus_info_X550em;
6486f37f232SEric Joyner 
649a9ca1c79SSean Bruno 
6506f37f232SEric Joyner 	mac->ops.get_media_type = ixgbe_get_media_type_X550em;
6516f37f232SEric Joyner 	mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em;
6526f37f232SEric Joyner 	mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em;
6536f37f232SEric Joyner 	mac->ops.reset_hw = ixgbe_reset_hw_X550em;
6546f37f232SEric Joyner 	mac->ops.get_supported_physical_layer =
6556f37f232SEric Joyner 				    ixgbe_get_supported_physical_layer_X550em;
6566f37f232SEric Joyner 
6576f37f232SEric Joyner 	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper)
6586f37f232SEric Joyner 		mac->ops.setup_fc = ixgbe_setup_fc_generic;
6596f37f232SEric Joyner 	else
6606f37f232SEric Joyner 		mac->ops.setup_fc = ixgbe_setup_fc_X550em;
6616f37f232SEric Joyner 
6626f37f232SEric Joyner 	/* PHY */
6636f37f232SEric Joyner 	phy->ops.init = ixgbe_init_phy_ops_X550em;
6648eb6488eSEric Joyner 	switch (hw->device_id) {
6658eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T:
6668eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
6678eb6488eSEric Joyner 		mac->ops.setup_fc = NULL;
6688eb6488eSEric Joyner 		phy->ops.identify = ixgbe_identify_phy_fw;
6698eb6488eSEric Joyner 		phy->ops.set_phy_power = NULL;
6708eb6488eSEric Joyner 		phy->ops.get_firmware_version = NULL;
6718eb6488eSEric Joyner 		break;
6728eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_1G_T:
6738eb6488eSEric Joyner 		mac->ops.setup_fc = NULL;
6746f37f232SEric Joyner 		phy->ops.identify = ixgbe_identify_phy_x550em;
6758eb6488eSEric Joyner 		phy->ops.set_phy_power = NULL;
6768eb6488eSEric Joyner 		break;
6778eb6488eSEric Joyner 	default:
6788eb6488eSEric Joyner 		phy->ops.identify = ixgbe_identify_phy_x550em;
6798eb6488eSEric Joyner 	}
6808eb6488eSEric Joyner 
6816f37f232SEric Joyner 	if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
6826f37f232SEric Joyner 		phy->ops.set_phy_power = NULL;
6836f37f232SEric Joyner 
6846f37f232SEric Joyner 
6856f37f232SEric Joyner 	/* EEPROM */
6866f37f232SEric Joyner 	eeprom->ops.init_params = ixgbe_init_eeprom_params_X540;
6876f37f232SEric Joyner 	eeprom->ops.read = ixgbe_read_ee_hostif_X550;
6886f37f232SEric Joyner 	eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550;
6896f37f232SEric Joyner 	eeprom->ops.write = ixgbe_write_ee_hostif_X550;
6906f37f232SEric Joyner 	eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550;
6916f37f232SEric Joyner 	eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
6926f37f232SEric Joyner 	eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
6936f37f232SEric Joyner 	eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
6946f37f232SEric Joyner 
6956f37f232SEric Joyner 	return ret_val;
6966f37f232SEric Joyner }
6976f37f232SEric Joyner 
6986f37f232SEric Joyner /**
6998eb6488eSEric Joyner  * ixgbe_setup_fw_link - Setup firmware-controlled PHYs
7008eb6488eSEric Joyner  * @hw: pointer to hardware structure
7018eb6488eSEric Joyner  */
ixgbe_setup_fw_link(struct ixgbe_hw * hw)7028eb6488eSEric Joyner static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw)
7038eb6488eSEric Joyner {
7048eb6488eSEric Joyner 	u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
7058eb6488eSEric Joyner 	s32 rc;
7068eb6488eSEric Joyner 	u16 i;
7078eb6488eSEric Joyner 
7088eb6488eSEric Joyner 	if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
7098eb6488eSEric Joyner 		return 0;
7108eb6488eSEric Joyner 
7118eb6488eSEric Joyner 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
7128eb6488eSEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
7138eb6488eSEric Joyner 			      "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
7148eb6488eSEric Joyner 		return IXGBE_ERR_INVALID_LINK_SETTINGS;
7158eb6488eSEric Joyner 	}
7168eb6488eSEric Joyner 
7178eb6488eSEric Joyner 	switch (hw->fc.requested_mode) {
7188eb6488eSEric Joyner 	case ixgbe_fc_full:
7198eb6488eSEric Joyner 		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX <<
7208eb6488eSEric Joyner 			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
7218eb6488eSEric Joyner 		break;
7228eb6488eSEric Joyner 	case ixgbe_fc_rx_pause:
7238eb6488eSEric Joyner 		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX <<
7248eb6488eSEric Joyner 			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
7258eb6488eSEric Joyner 		break;
7268eb6488eSEric Joyner 	case ixgbe_fc_tx_pause:
7278eb6488eSEric Joyner 		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX <<
7288eb6488eSEric Joyner 			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
7298eb6488eSEric Joyner 		break;
7308eb6488eSEric Joyner 	default:
7318eb6488eSEric Joyner 		break;
7328eb6488eSEric Joyner 	}
7338eb6488eSEric Joyner 
7348eb6488eSEric Joyner 	for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) {
7358eb6488eSEric Joyner 		if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed)
736994dd632SGuinan Sun 			setup[0] |= (u32)(ixgbe_fw_map[i].fw_speed);
7378eb6488eSEric Joyner 	}
7388eb6488eSEric Joyner 	setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN;
7398eb6488eSEric Joyner 
7408eb6488eSEric Joyner 	if (hw->phy.eee_speeds_advertised)
7418eb6488eSEric Joyner 		setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE;
7428eb6488eSEric Joyner 
7438eb6488eSEric Joyner 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);
7448eb6488eSEric Joyner 	if (rc)
7458eb6488eSEric Joyner 		return rc;
7468eb6488eSEric Joyner 	if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
7478eb6488eSEric Joyner 		return IXGBE_ERR_OVERTEMP;
7488eb6488eSEric Joyner 	return IXGBE_SUCCESS;
7498eb6488eSEric Joyner }
7508eb6488eSEric Joyner 
7518eb6488eSEric Joyner /**
752edef2769SRadoslaw Tyl  * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs
7538eb6488eSEric Joyner  * @hw: pointer to hardware structure
7548eb6488eSEric Joyner  *
7558eb6488eSEric Joyner  * Called at init time to set up flow control.
7568eb6488eSEric Joyner  */
ixgbe_fc_autoneg_fw(struct ixgbe_hw * hw)7578eb6488eSEric Joyner static s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw)
7588eb6488eSEric Joyner {
7598eb6488eSEric Joyner 	if (hw->fc.requested_mode == ixgbe_fc_default)
7608eb6488eSEric Joyner 		hw->fc.requested_mode = ixgbe_fc_full;
7618eb6488eSEric Joyner 
7628eb6488eSEric Joyner 	return ixgbe_setup_fw_link(hw);
7638eb6488eSEric Joyner }
7648eb6488eSEric Joyner 
7658eb6488eSEric Joyner /**
7668eb6488eSEric Joyner  * ixgbe_setup_eee_fw - Enable/disable EEE support
7678eb6488eSEric Joyner  * @hw: pointer to the HW structure
7688eb6488eSEric Joyner  * @enable_eee: boolean flag to enable EEE
7698eb6488eSEric Joyner  *
7708eb6488eSEric Joyner  * Enable/disable EEE based on enable_eee flag.
7718eb6488eSEric Joyner  * This function controls EEE for firmware-based PHY implementations.
7728eb6488eSEric Joyner  */
ixgbe_setup_eee_fw(struct ixgbe_hw * hw,bool enable_eee)7738eb6488eSEric Joyner static s32 ixgbe_setup_eee_fw(struct ixgbe_hw *hw, bool enable_eee)
7748eb6488eSEric Joyner {
7758eb6488eSEric Joyner 	if (!!hw->phy.eee_speeds_advertised == enable_eee)
7768eb6488eSEric Joyner 		return IXGBE_SUCCESS;
7778eb6488eSEric Joyner 	if (enable_eee)
7788eb6488eSEric Joyner 		hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
7798eb6488eSEric Joyner 	else
7808eb6488eSEric Joyner 		hw->phy.eee_speeds_advertised = 0;
7818eb6488eSEric Joyner 	return hw->phy.ops.setup_link(hw);
7828eb6488eSEric Joyner }
7838eb6488eSEric Joyner 
7848eb6488eSEric Joyner /**
7858eb6488eSEric Joyner *  ixgbe_init_ops_X550EM_a - Inits func ptrs and MAC type
7868eb6488eSEric Joyner *  @hw: pointer to hardware structure
7878eb6488eSEric Joyner *
7888eb6488eSEric Joyner *  Initialize the function pointers and for MAC type X550EM_a.
7898eb6488eSEric Joyner *  Does not touch the hardware.
7908eb6488eSEric Joyner **/
ixgbe_init_ops_X550EM_a(struct ixgbe_hw * hw)7918eb6488eSEric Joyner s32 ixgbe_init_ops_X550EM_a(struct ixgbe_hw *hw)
7928eb6488eSEric Joyner {
7938eb6488eSEric Joyner 	struct ixgbe_mac_info *mac = &hw->mac;
7948eb6488eSEric Joyner 	s32 ret_val;
7958eb6488eSEric Joyner 
7968eb6488eSEric Joyner 	DEBUGFUNC("ixgbe_init_ops_X550EM_a");
7978eb6488eSEric Joyner 
7988eb6488eSEric Joyner 	/* Start with generic X550EM init */
7998eb6488eSEric Joyner 	ret_val = ixgbe_init_ops_X550EM(hw);
8008eb6488eSEric Joyner 
8018eb6488eSEric Joyner 	mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
8028eb6488eSEric Joyner 	mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
8038eb6488eSEric Joyner 	mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550a;
8048eb6488eSEric Joyner 	mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550a;
8058eb6488eSEric Joyner 
8068eb6488eSEric Joyner 	switch (mac->ops.get_media_type(hw)) {
8078eb6488eSEric Joyner 	case ixgbe_media_type_fiber:
8088eb6488eSEric Joyner 		mac->ops.setup_fc = NULL;
8098eb6488eSEric Joyner 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;
8108eb6488eSEric Joyner 		break;
8118eb6488eSEric Joyner 	case ixgbe_media_type_backplane:
8128eb6488eSEric Joyner 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;
8138eb6488eSEric Joyner 		mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;
8148eb6488eSEric Joyner 		break;
8158eb6488eSEric Joyner 	default:
8168eb6488eSEric Joyner 		break;
8178eb6488eSEric Joyner 	}
8188eb6488eSEric Joyner 
8198eb6488eSEric Joyner 	switch (hw->device_id) {
8208eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T:
8218eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
8228eb6488eSEric Joyner 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a;
8238eb6488eSEric Joyner 		mac->ops.setup_fc = ixgbe_fc_autoneg_fw;
8248eb6488eSEric Joyner 		mac->ops.setup_eee = ixgbe_setup_eee_fw;
8258eb6488eSEric Joyner 		hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL |
8268eb6488eSEric Joyner 					       IXGBE_LINK_SPEED_1GB_FULL;
8278eb6488eSEric Joyner 		hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
8288eb6488eSEric Joyner 		break;
8298eb6488eSEric Joyner 	default:
8308eb6488eSEric Joyner 		break;
8318eb6488eSEric Joyner 	}
8328eb6488eSEric Joyner 
8338eb6488eSEric Joyner 	return ret_val;
8348eb6488eSEric Joyner }
8358eb6488eSEric Joyner 
8368eb6488eSEric Joyner /**
8378eb6488eSEric Joyner *  ixgbe_init_ops_X550EM_x - Inits func ptrs and MAC type
8388eb6488eSEric Joyner *  @hw: pointer to hardware structure
8398eb6488eSEric Joyner *
8408eb6488eSEric Joyner *  Initialize the function pointers and for MAC type X550EM_x.
8418eb6488eSEric Joyner *  Does not touch the hardware.
8428eb6488eSEric Joyner **/
ixgbe_init_ops_X550EM_x(struct ixgbe_hw * hw)8438eb6488eSEric Joyner s32 ixgbe_init_ops_X550EM_x(struct ixgbe_hw *hw)
8448eb6488eSEric Joyner {
8458eb6488eSEric Joyner 	struct ixgbe_mac_info *mac = &hw->mac;
8468eb6488eSEric Joyner 	struct ixgbe_link_info *link = &hw->link;
8478eb6488eSEric Joyner 	s32 ret_val;
8488eb6488eSEric Joyner 
8498eb6488eSEric Joyner 	DEBUGFUNC("ixgbe_init_ops_X550EM_x");
8508eb6488eSEric Joyner 
8518eb6488eSEric Joyner 	/* Start with generic X550EM init */
8528eb6488eSEric Joyner 	ret_val = ixgbe_init_ops_X550EM(hw);
8538eb6488eSEric Joyner 
8548eb6488eSEric Joyner 	mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
8558eb6488eSEric Joyner 	mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
8568eb6488eSEric Joyner 	mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550em;
8578eb6488eSEric Joyner 	mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550em;
8588eb6488eSEric Joyner 	link->ops.read_link = ixgbe_read_i2c_combined_generic;
8598eb6488eSEric Joyner 	link->ops.read_link_unlocked = ixgbe_read_i2c_combined_generic_unlocked;
8608eb6488eSEric Joyner 	link->ops.write_link = ixgbe_write_i2c_combined_generic;
8618eb6488eSEric Joyner 	link->ops.write_link_unlocked =
8628eb6488eSEric Joyner 				      ixgbe_write_i2c_combined_generic_unlocked;
8638eb6488eSEric Joyner 	link->addr = IXGBE_CS4227;
8648eb6488eSEric Joyner 
8658eb6488eSEric Joyner 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T) {
8668eb6488eSEric Joyner 		mac->ops.setup_fc = NULL;
8678eb6488eSEric Joyner 		mac->ops.setup_eee = NULL;
8688eb6488eSEric Joyner 		mac->ops.init_led_link_act = NULL;
8698eb6488eSEric Joyner 	}
8708eb6488eSEric Joyner 
8718eb6488eSEric Joyner 	return ret_val;
8728eb6488eSEric Joyner }
8738eb6488eSEric Joyner 
8748eb6488eSEric Joyner /**
8756f37f232SEric Joyner  * ixgbe_dmac_config_X550
8766f37f232SEric Joyner  * @hw: pointer to hardware structure
8776f37f232SEric Joyner  *
8786f37f232SEric Joyner  * Configure DMA coalescing. If enabling dmac, dmac is activated.
8796f37f232SEric Joyner  * When disabling dmac, dmac enable dmac bit is cleared.
8806f37f232SEric Joyner  **/
ixgbe_dmac_config_X550(struct ixgbe_hw * hw)8816f37f232SEric Joyner s32 ixgbe_dmac_config_X550(struct ixgbe_hw *hw)
8826f37f232SEric Joyner {
8836f37f232SEric Joyner 	u32 reg, high_pri_tc;
8846f37f232SEric Joyner 
8856f37f232SEric Joyner 	DEBUGFUNC("ixgbe_dmac_config_X550");
8866f37f232SEric Joyner 
8876f37f232SEric Joyner 	/* Disable DMA coalescing before configuring */
8886f37f232SEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
8896f37f232SEric Joyner 	reg &= ~IXGBE_DMACR_DMAC_EN;
8906f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
8916f37f232SEric Joyner 
8926f37f232SEric Joyner 	/* Disable DMA Coalescing if the watchdog timer is 0 */
8936f37f232SEric Joyner 	if (!hw->mac.dmac_config.watchdog_timer)
8946f37f232SEric Joyner 		goto out;
8956f37f232SEric Joyner 
8966f37f232SEric Joyner 	ixgbe_dmac_config_tcs_X550(hw);
8976f37f232SEric Joyner 
8986f37f232SEric Joyner 	/* Configure DMA Coalescing Control Register */
8996f37f232SEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
9006f37f232SEric Joyner 
9016f37f232SEric Joyner 	/* Set the watchdog timer in units of 40.96 usec */
9026f37f232SEric Joyner 	reg &= ~IXGBE_DMACR_DMACWT_MASK;
9036f37f232SEric Joyner 	reg |= (hw->mac.dmac_config.watchdog_timer * 100) / 4096;
9046f37f232SEric Joyner 
9056f37f232SEric Joyner 	reg &= ~IXGBE_DMACR_HIGH_PRI_TC_MASK;
9066f37f232SEric Joyner 	/* If fcoe is enabled, set high priority traffic class */
9076f37f232SEric Joyner 	if (hw->mac.dmac_config.fcoe_en) {
9086f37f232SEric Joyner 		high_pri_tc = 1 << hw->mac.dmac_config.fcoe_tc;
9096f37f232SEric Joyner 		reg |= ((high_pri_tc << IXGBE_DMACR_HIGH_PRI_TC_SHIFT) &
9106f37f232SEric Joyner 			IXGBE_DMACR_HIGH_PRI_TC_MASK);
9116f37f232SEric Joyner 	}
9126f37f232SEric Joyner 	reg |= IXGBE_DMACR_EN_MNG_IND;
9136f37f232SEric Joyner 
9146f37f232SEric Joyner 	/* Enable DMA coalescing after configuration */
9156f37f232SEric Joyner 	reg |= IXGBE_DMACR_DMAC_EN;
9166f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
9176f37f232SEric Joyner 
9186f37f232SEric Joyner out:
9196f37f232SEric Joyner 	return IXGBE_SUCCESS;
9206f37f232SEric Joyner }
9216f37f232SEric Joyner 
9226f37f232SEric Joyner /**
9236f37f232SEric Joyner  * ixgbe_dmac_config_tcs_X550
9246f37f232SEric Joyner  * @hw: pointer to hardware structure
9256f37f232SEric Joyner  *
9266f37f232SEric Joyner  * Configure DMA coalescing threshold per TC. The dmac enable bit must
9276f37f232SEric Joyner  * be cleared before configuring.
9286f37f232SEric Joyner  **/
ixgbe_dmac_config_tcs_X550(struct ixgbe_hw * hw)9296f37f232SEric Joyner s32 ixgbe_dmac_config_tcs_X550(struct ixgbe_hw *hw)
9306f37f232SEric Joyner {
9316f37f232SEric Joyner 	u32 tc, reg, pb_headroom, rx_pb_size, maxframe_size_kb;
9326f37f232SEric Joyner 
9336f37f232SEric Joyner 	DEBUGFUNC("ixgbe_dmac_config_tcs_X550");
9346f37f232SEric Joyner 
9356f37f232SEric Joyner 	/* Configure DMA coalescing enabled */
9366f37f232SEric Joyner 	switch (hw->mac.dmac_config.link_speed) {
9378eb6488eSEric Joyner 	case IXGBE_LINK_SPEED_10_FULL:
9386f37f232SEric Joyner 	case IXGBE_LINK_SPEED_100_FULL:
9396f37f232SEric Joyner 		pb_headroom = IXGBE_DMACRXT_100M;
9406f37f232SEric Joyner 		break;
9416f37f232SEric Joyner 	case IXGBE_LINK_SPEED_1GB_FULL:
9426f37f232SEric Joyner 		pb_headroom = IXGBE_DMACRXT_1G;
9436f37f232SEric Joyner 		break;
9446f37f232SEric Joyner 	default:
9456f37f232SEric Joyner 		pb_headroom = IXGBE_DMACRXT_10G;
9466f37f232SEric Joyner 		break;
9476f37f232SEric Joyner 	}
9486f37f232SEric Joyner 
9496f37f232SEric Joyner 	maxframe_size_kb = ((IXGBE_READ_REG(hw, IXGBE_MAXFRS) >>
9506f37f232SEric Joyner 			     IXGBE_MHADD_MFS_SHIFT) / 1024);
9516f37f232SEric Joyner 
9526f37f232SEric Joyner 	/* Set the per Rx packet buffer receive threshold */
9536f37f232SEric Joyner 	for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) {
9546f37f232SEric Joyner 		reg = IXGBE_READ_REG(hw, IXGBE_DMCTH(tc));
9556f37f232SEric Joyner 		reg &= ~IXGBE_DMCTH_DMACRXT_MASK;
9566f37f232SEric Joyner 
9576f37f232SEric Joyner 		if (tc < hw->mac.dmac_config.num_tcs) {
9586f37f232SEric Joyner 			/* Get Rx PB size */
9596f37f232SEric Joyner 			rx_pb_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(tc));
9606f37f232SEric Joyner 			rx_pb_size = (rx_pb_size & IXGBE_RXPBSIZE_MASK) >>
9616f37f232SEric Joyner 				IXGBE_RXPBSIZE_SHIFT;
9626f37f232SEric Joyner 
9636f37f232SEric Joyner 			/* Calculate receive buffer threshold in kilobytes */
9646f37f232SEric Joyner 			if (rx_pb_size > pb_headroom)
9656f37f232SEric Joyner 				rx_pb_size = rx_pb_size - pb_headroom;
9666f37f232SEric Joyner 			else
9676f37f232SEric Joyner 				rx_pb_size = 0;
9686f37f232SEric Joyner 
9696f37f232SEric Joyner 			/* Minimum of MFS shall be set for DMCTH */
9706f37f232SEric Joyner 			reg |= (rx_pb_size > maxframe_size_kb) ?
9716f37f232SEric Joyner 				rx_pb_size : maxframe_size_kb;
9726f37f232SEric Joyner 		}
9736f37f232SEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_DMCTH(tc), reg);
9746f37f232SEric Joyner 	}
9756f37f232SEric Joyner 	return IXGBE_SUCCESS;
9766f37f232SEric Joyner }
9776f37f232SEric Joyner 
9786f37f232SEric Joyner /**
9796f37f232SEric Joyner  * ixgbe_dmac_update_tcs_X550
9806f37f232SEric Joyner  * @hw: pointer to hardware structure
9816f37f232SEric Joyner  *
9826f37f232SEric Joyner  * Disables dmac, updates per TC settings, and then enables dmac.
9836f37f232SEric Joyner  **/
ixgbe_dmac_update_tcs_X550(struct ixgbe_hw * hw)9846f37f232SEric Joyner s32 ixgbe_dmac_update_tcs_X550(struct ixgbe_hw *hw)
9856f37f232SEric Joyner {
9866f37f232SEric Joyner 	u32 reg;
9876f37f232SEric Joyner 
9886f37f232SEric Joyner 	DEBUGFUNC("ixgbe_dmac_update_tcs_X550");
9896f37f232SEric Joyner 
9906f37f232SEric Joyner 	/* Disable DMA coalescing before configuring */
9916f37f232SEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
9926f37f232SEric Joyner 	reg &= ~IXGBE_DMACR_DMAC_EN;
9936f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
9946f37f232SEric Joyner 
9956f37f232SEric Joyner 	ixgbe_dmac_config_tcs_X550(hw);
9966f37f232SEric Joyner 
9976f37f232SEric Joyner 	/* Enable DMA coalescing after configuration */
9986f37f232SEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
9996f37f232SEric Joyner 	reg |= IXGBE_DMACR_DMAC_EN;
10006f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
10016f37f232SEric Joyner 
10026f37f232SEric Joyner 	return IXGBE_SUCCESS;
10036f37f232SEric Joyner }
10046f37f232SEric Joyner 
10056f37f232SEric Joyner /**
10066f37f232SEric Joyner  * ixgbe_init_eeprom_params_X550 - Initialize EEPROM params
10076f37f232SEric Joyner  * @hw: pointer to hardware structure
10086f37f232SEric Joyner  *
10096f37f232SEric Joyner  * Initializes the EEPROM parameters ixgbe_eeprom_info within the
10106f37f232SEric Joyner  * ixgbe_hw struct in order to set up EEPROM access.
10116f37f232SEric Joyner  **/
ixgbe_init_eeprom_params_X550(struct ixgbe_hw * hw)10126f37f232SEric Joyner s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
10136f37f232SEric Joyner {
10146f37f232SEric Joyner 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
10156f37f232SEric Joyner 	u32 eec;
10166f37f232SEric Joyner 	u16 eeprom_size;
10176f37f232SEric Joyner 
10186f37f232SEric Joyner 	DEBUGFUNC("ixgbe_init_eeprom_params_X550");
10196f37f232SEric Joyner 
10206f37f232SEric Joyner 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
10216f37f232SEric Joyner 		eeprom->semaphore_delay = 10;
10226f37f232SEric Joyner 		eeprom->type = ixgbe_flash;
10236f37f232SEric Joyner 
10246f37f232SEric Joyner 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
10256f37f232SEric Joyner 		eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
10266f37f232SEric Joyner 				    IXGBE_EEC_SIZE_SHIFT);
10276f37f232SEric Joyner 		eeprom->word_size = 1 << (eeprom_size +
10286f37f232SEric Joyner 					  IXGBE_EEPROM_WORD_SIZE_SHIFT);
10296f37f232SEric Joyner 
10306f37f232SEric Joyner 		DEBUGOUT2("Eeprom params: type = %d, size = %d\n",
10316f37f232SEric Joyner 			  eeprom->type, eeprom->word_size);
10326f37f232SEric Joyner 	}
10336f37f232SEric Joyner 
10346f37f232SEric Joyner 	return IXGBE_SUCCESS;
10356f37f232SEric Joyner }
10366f37f232SEric Joyner 
10376f37f232SEric Joyner /**
10386f37f232SEric Joyner  * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning
10396f37f232SEric Joyner  * @hw: pointer to hardware structure
10406f37f232SEric Joyner  * @enable: enable or disable source address pruning
10416f37f232SEric Joyner  * @pool: Rx pool to set source address pruning for
10426f37f232SEric Joyner  **/
ixgbe_set_source_address_pruning_X550(struct ixgbe_hw * hw,bool enable,unsigned int pool)10436f37f232SEric Joyner void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable,
10446f37f232SEric Joyner 					   unsigned int pool)
10456f37f232SEric Joyner {
10466f37f232SEric Joyner 	u64 pfflp;
10476f37f232SEric Joyner 
10486f37f232SEric Joyner 	/* max rx pool is 63 */
10496f37f232SEric Joyner 	if (pool > 63)
10506f37f232SEric Joyner 		return;
10516f37f232SEric Joyner 
10526f37f232SEric Joyner 	pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL);
10536f37f232SEric Joyner 	pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32;
10546f37f232SEric Joyner 
10556f37f232SEric Joyner 	if (enable)
10566f37f232SEric Joyner 		pfflp |= (1ULL << pool);
10576f37f232SEric Joyner 	else
10586f37f232SEric Joyner 		pfflp &= ~(1ULL << pool);
10596f37f232SEric Joyner 
10606f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp);
10616f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32));
10626f37f232SEric Joyner }
10636f37f232SEric Joyner 
10646f37f232SEric Joyner /**
106546981e90SGuinan Sun  * ixgbe_set_ethertype_anti_spoofing_X550 - Configure Ethertype anti-spoofing
10666f37f232SEric Joyner  * @hw: pointer to hardware structure
10676f37f232SEric Joyner  * @enable: enable or disable switch for Ethertype anti-spoofing
10686f37f232SEric Joyner  * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing
10696f37f232SEric Joyner  *
10706f37f232SEric Joyner  **/
ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw * hw,bool enable,int vf)10716f37f232SEric Joyner void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
10726f37f232SEric Joyner 		bool enable, int vf)
10736f37f232SEric Joyner {
10746f37f232SEric Joyner 	int vf_target_reg = vf >> 3;
10756f37f232SEric Joyner 	int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT;
10766f37f232SEric Joyner 	u32 pfvfspoof;
10776f37f232SEric Joyner 
10786f37f232SEric Joyner 	DEBUGFUNC("ixgbe_set_ethertype_anti_spoofing_X550");
10796f37f232SEric Joyner 
10806f37f232SEric Joyner 	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
10816f37f232SEric Joyner 	if (enable)
10826f37f232SEric Joyner 		pfvfspoof |= (1 << vf_target_shift);
10836f37f232SEric Joyner 	else
10846f37f232SEric Joyner 		pfvfspoof &= ~(1 << vf_target_shift);
10856f37f232SEric Joyner 
10866f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
10876f37f232SEric Joyner }
10886f37f232SEric Joyner 
10896f37f232SEric Joyner /**
10906f37f232SEric Joyner  * ixgbe_iosf_wait - Wait for IOSF command completion
10916f37f232SEric Joyner  * @hw: pointer to hardware structure
10926f37f232SEric Joyner  * @ctrl: pointer to location to receive final IOSF control value
10936f37f232SEric Joyner  *
10946f37f232SEric Joyner  * Returns failing status on timeout
10956f37f232SEric Joyner  *
10966f37f232SEric Joyner  * Note: ctrl can be NULL if the IOSF control register value is not needed
10976f37f232SEric Joyner  **/
ixgbe_iosf_wait(struct ixgbe_hw * hw,u32 * ctrl)10986f37f232SEric Joyner static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl)
10996f37f232SEric Joyner {
1100a9ca1c79SSean Bruno 	u32 i, command = 0;
11016f37f232SEric Joyner 
11026f37f232SEric Joyner 	/* Check every 10 usec to see if the address cycle completed.
11036f37f232SEric Joyner 	 * The SB IOSF BUSY bit will clear when the operation is
11046f37f232SEric Joyner 	 * complete
11056f37f232SEric Joyner 	 */
11066f37f232SEric Joyner 	for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
11076f37f232SEric Joyner 		command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
11086f37f232SEric Joyner 		if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0)
11096f37f232SEric Joyner 			break;
11106f37f232SEric Joyner 		usec_delay(10);
11116f37f232SEric Joyner 	}
11126f37f232SEric Joyner 	if (ctrl)
11136f37f232SEric Joyner 		*ctrl = command;
11146f37f232SEric Joyner 	if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
11156f37f232SEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_POLLING, "Wait timed out\n");
11166f37f232SEric Joyner 		return IXGBE_ERR_PHY;
11176f37f232SEric Joyner 	}
11186f37f232SEric Joyner 
11196f37f232SEric Joyner 	return IXGBE_SUCCESS;
11206f37f232SEric Joyner }
11216f37f232SEric Joyner 
11226f37f232SEric Joyner /**
11238eb6488eSEric Joyner  * ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register
11248eb6488eSEric Joyner  * of the IOSF device
11256f37f232SEric Joyner  * @hw: pointer to hardware structure
11266f37f232SEric Joyner  * @reg_addr: 32 bit PHY register to write
11276f37f232SEric Joyner  * @device_type: 3 bit device type
11286f37f232SEric Joyner  * @data: Data to write to the register
11296f37f232SEric Joyner  **/
ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u32 data)11306f37f232SEric Joyner s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
11316f37f232SEric Joyner 			    u32 device_type, u32 data)
11326f37f232SEric Joyner {
11336f37f232SEric Joyner 	u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
1134c1710eafSJohn Baldwin 	u32 command, error __unused;
11356f37f232SEric Joyner 	s32 ret;
11366f37f232SEric Joyner 
11376f37f232SEric Joyner 	ret = ixgbe_acquire_swfw_semaphore(hw, gssr);
11386f37f232SEric Joyner 	if (ret != IXGBE_SUCCESS)
11396f37f232SEric Joyner 		return ret;
11406f37f232SEric Joyner 
11416f37f232SEric Joyner 	ret = ixgbe_iosf_wait(hw, NULL);
11426f37f232SEric Joyner 	if (ret != IXGBE_SUCCESS)
11436f37f232SEric Joyner 		goto out;
11446f37f232SEric Joyner 
11456f37f232SEric Joyner 	command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
11466f37f232SEric Joyner 		   (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
11476f37f232SEric Joyner 
11486f37f232SEric Joyner 	/* Write IOSF control register */
11496f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
11506f37f232SEric Joyner 
11516f37f232SEric Joyner 	/* Write IOSF data register */
11526f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data);
11536f37f232SEric Joyner 
11546f37f232SEric Joyner 	ret = ixgbe_iosf_wait(hw, &command);
11556f37f232SEric Joyner 
11566f37f232SEric Joyner 	if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
11576f37f232SEric Joyner 		error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
11586f37f232SEric Joyner 			 IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
11596f37f232SEric Joyner 		ERROR_REPORT2(IXGBE_ERROR_POLLING,
11606f37f232SEric Joyner 			      "Failed to write, error %x\n", error);
11616f37f232SEric Joyner 		ret = IXGBE_ERR_PHY;
11626f37f232SEric Joyner 	}
11636f37f232SEric Joyner 
11646f37f232SEric Joyner out:
11656f37f232SEric Joyner 	ixgbe_release_swfw_semaphore(hw, gssr);
11666f37f232SEric Joyner 	return ret;
11676f37f232SEric Joyner }
11686f37f232SEric Joyner 
11696f37f232SEric Joyner /**
11708eb6488eSEric Joyner  * ixgbe_read_iosf_sb_reg_x550 - Reads specified register of the IOSF device
11716f37f232SEric Joyner  * @hw: pointer to hardware structure
11726f37f232SEric Joyner  * @reg_addr: 32 bit PHY register to write
11736f37f232SEric Joyner  * @device_type: 3 bit device type
11748eb6488eSEric Joyner  * @data: Pointer to read data from the register
11756f37f232SEric Joyner  **/
ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u32 * data)11766f37f232SEric Joyner s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
11776f37f232SEric Joyner 			   u32 device_type, u32 *data)
11786f37f232SEric Joyner {
11796f37f232SEric Joyner 	u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
1180c1710eafSJohn Baldwin 	u32 command, error __unused;
11816f37f232SEric Joyner 	s32 ret;
11826f37f232SEric Joyner 
11836f37f232SEric Joyner 	ret = ixgbe_acquire_swfw_semaphore(hw, gssr);
11846f37f232SEric Joyner 	if (ret != IXGBE_SUCCESS)
11856f37f232SEric Joyner 		return ret;
11866f37f232SEric Joyner 
11876f37f232SEric Joyner 	ret = ixgbe_iosf_wait(hw, NULL);
11886f37f232SEric Joyner 	if (ret != IXGBE_SUCCESS)
11896f37f232SEric Joyner 		goto out;
11906f37f232SEric Joyner 
11916f37f232SEric Joyner 	command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
11926f37f232SEric Joyner 		   (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
11936f37f232SEric Joyner 
11946f37f232SEric Joyner 	/* Write IOSF control register */
11956f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
11966f37f232SEric Joyner 
11976f37f232SEric Joyner 	ret = ixgbe_iosf_wait(hw, &command);
11986f37f232SEric Joyner 
11996f37f232SEric Joyner 	if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
12006f37f232SEric Joyner 		error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
12016f37f232SEric Joyner 			 IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
12026f37f232SEric Joyner 		ERROR_REPORT2(IXGBE_ERROR_POLLING,
12036f37f232SEric Joyner 				"Failed to read, error %x\n", error);
12046f37f232SEric Joyner 		ret = IXGBE_ERR_PHY;
12056f37f232SEric Joyner 	}
12066f37f232SEric Joyner 
12076f37f232SEric Joyner 	if (ret == IXGBE_SUCCESS)
12086f37f232SEric Joyner 		*data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
12096f37f232SEric Joyner 
12106f37f232SEric Joyner out:
12116f37f232SEric Joyner 	ixgbe_release_swfw_semaphore(hw, gssr);
12126f37f232SEric Joyner 	return ret;
12136f37f232SEric Joyner }
12146f37f232SEric Joyner 
12156f37f232SEric Joyner /**
12168eb6488eSEric Joyner  * ixgbe_get_phy_token - Get the token for shared phy access
12178eb6488eSEric Joyner  * @hw: Pointer to hardware structure
12188eb6488eSEric Joyner  */
12198eb6488eSEric Joyner 
ixgbe_get_phy_token(struct ixgbe_hw * hw)12208eb6488eSEric Joyner s32 ixgbe_get_phy_token(struct ixgbe_hw *hw)
12218eb6488eSEric Joyner {
12228eb6488eSEric Joyner 	struct ixgbe_hic_phy_token_req token_cmd;
12238eb6488eSEric Joyner 	s32 status;
12248eb6488eSEric Joyner 
12258eb6488eSEric Joyner 	token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
12268eb6488eSEric Joyner 	token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
12278eb6488eSEric Joyner 	token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
12288eb6488eSEric Joyner 	token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
12298eb6488eSEric Joyner 	token_cmd.port_number = hw->bus.lan_id;
12308eb6488eSEric Joyner 	token_cmd.command_type = FW_PHY_TOKEN_REQ;
12318eb6488eSEric Joyner 	token_cmd.pad = 0;
12328eb6488eSEric Joyner 	status = ixgbe_host_interface_command(hw, (u32 *)&token_cmd,
12338eb6488eSEric Joyner 					      sizeof(token_cmd),
12348eb6488eSEric Joyner 					      IXGBE_HI_COMMAND_TIMEOUT,
123579b36ec9SKevin Bowling 					      true);
12368eb6488eSEric Joyner 	if (status) {
12378eb6488eSEric Joyner 		DEBUGOUT1("Issuing host interface command failed with Status = %d\n",
12388eb6488eSEric Joyner 			  status);
12398eb6488eSEric Joyner 		return status;
12408eb6488eSEric Joyner 	}
12418eb6488eSEric Joyner 	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
12428eb6488eSEric Joyner 		return IXGBE_SUCCESS;
12438eb6488eSEric Joyner 	if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) {
12448eb6488eSEric Joyner 		DEBUGOUT1("Host interface command returned 0x%08x , returning IXGBE_ERR_FW_RESP_INVALID\n",
12458eb6488eSEric Joyner 			  token_cmd.hdr.cmd_or_resp.ret_status);
12468eb6488eSEric Joyner 		return IXGBE_ERR_FW_RESP_INVALID;
12478eb6488eSEric Joyner 	}
12488eb6488eSEric Joyner 
12498eb6488eSEric Joyner 	DEBUGOUT("Returning  IXGBE_ERR_TOKEN_RETRY\n");
12508eb6488eSEric Joyner 	return IXGBE_ERR_TOKEN_RETRY;
12518eb6488eSEric Joyner }
12528eb6488eSEric Joyner 
12538eb6488eSEric Joyner /**
12548eb6488eSEric Joyner  * ixgbe_put_phy_token - Put the token for shared phy access
12558eb6488eSEric Joyner  * @hw: Pointer to hardware structure
12568eb6488eSEric Joyner  */
12578eb6488eSEric Joyner 
ixgbe_put_phy_token(struct ixgbe_hw * hw)12588eb6488eSEric Joyner s32 ixgbe_put_phy_token(struct ixgbe_hw *hw)
12598eb6488eSEric Joyner {
12608eb6488eSEric Joyner 	struct ixgbe_hic_phy_token_req token_cmd;
12618eb6488eSEric Joyner 	s32 status;
12628eb6488eSEric Joyner 
12638eb6488eSEric Joyner 	token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
12648eb6488eSEric Joyner 	token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
12658eb6488eSEric Joyner 	token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
12668eb6488eSEric Joyner 	token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
12678eb6488eSEric Joyner 	token_cmd.port_number = hw->bus.lan_id;
12688eb6488eSEric Joyner 	token_cmd.command_type = FW_PHY_TOKEN_REL;
12698eb6488eSEric Joyner 	token_cmd.pad = 0;
12708eb6488eSEric Joyner 	status = ixgbe_host_interface_command(hw, (u32 *)&token_cmd,
12718eb6488eSEric Joyner 					      sizeof(token_cmd),
12728eb6488eSEric Joyner 					      IXGBE_HI_COMMAND_TIMEOUT,
127379b36ec9SKevin Bowling 					      true);
12748eb6488eSEric Joyner 	if (status)
12758eb6488eSEric Joyner 		return status;
12768eb6488eSEric Joyner 	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
12778eb6488eSEric Joyner 		return IXGBE_SUCCESS;
12788eb6488eSEric Joyner 
12798eb6488eSEric Joyner 	DEBUGOUT("Put PHY Token host interface command failed");
12808eb6488eSEric Joyner 	return IXGBE_ERR_FW_RESP_INVALID;
12818eb6488eSEric Joyner }
12828eb6488eSEric Joyner 
12838eb6488eSEric Joyner /**
12846f37f232SEric Joyner  * ixgbe_disable_mdd_X550
12856f37f232SEric Joyner  * @hw: pointer to hardware structure
12866f37f232SEric Joyner  *
12876f37f232SEric Joyner  * Disable malicious driver detection
12886f37f232SEric Joyner  **/
ixgbe_disable_mdd_X550(struct ixgbe_hw * hw)12896f37f232SEric Joyner void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw)
12906f37f232SEric Joyner {
12916f37f232SEric Joyner 	u32 reg;
12926f37f232SEric Joyner 
12936f37f232SEric Joyner 	DEBUGFUNC("ixgbe_disable_mdd_X550");
12946f37f232SEric Joyner 
12956f37f232SEric Joyner 	/* Disable MDD for TX DMA and interrupt */
12966f37f232SEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
12976f37f232SEric Joyner 	reg &= ~(IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN);
12986f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg);
12996f37f232SEric Joyner 
13006f37f232SEric Joyner 	/* Disable MDD for RX and interrupt */
13016f37f232SEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
13026f37f232SEric Joyner 	reg &= ~(IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN);
13036f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg);
13046f37f232SEric Joyner }
13056f37f232SEric Joyner 
13066f37f232SEric Joyner /**
13076f37f232SEric Joyner  * ixgbe_enable_mdd_X550
13086f37f232SEric Joyner  * @hw: pointer to hardware structure
13096f37f232SEric Joyner  *
13106f37f232SEric Joyner  * Enable malicious driver detection
13116f37f232SEric Joyner  **/
ixgbe_enable_mdd_X550(struct ixgbe_hw * hw)13126f37f232SEric Joyner void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw)
13136f37f232SEric Joyner {
13146f37f232SEric Joyner 	u32 reg;
13156f37f232SEric Joyner 
13166f37f232SEric Joyner 	DEBUGFUNC("ixgbe_enable_mdd_X550");
13176f37f232SEric Joyner 
13186f37f232SEric Joyner 	/* Enable MDD for TX DMA and interrupt */
13196f37f232SEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
13206f37f232SEric Joyner 	reg |= (IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN);
13216f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg);
13226f37f232SEric Joyner 
13236f37f232SEric Joyner 	/* Enable MDD for RX and interrupt */
13246f37f232SEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
13256f37f232SEric Joyner 	reg |= (IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN);
13266f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg);
13276f37f232SEric Joyner }
13286f37f232SEric Joyner 
13296f37f232SEric Joyner /**
13306f37f232SEric Joyner  * ixgbe_restore_mdd_vf_X550
13316f37f232SEric Joyner  * @hw: pointer to hardware structure
13326f37f232SEric Joyner  * @vf: vf index
13336f37f232SEric Joyner  *
13346f37f232SEric Joyner  * Restore VF that was disabled during malicious driver detection event
13356f37f232SEric Joyner  **/
ixgbe_restore_mdd_vf_X550(struct ixgbe_hw * hw,u32 vf)13366f37f232SEric Joyner void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf)
13376f37f232SEric Joyner {
13386f37f232SEric Joyner 	u32 idx, reg, num_qs, start_q, bitmask;
13396f37f232SEric Joyner 
13406f37f232SEric Joyner 	DEBUGFUNC("ixgbe_restore_mdd_vf_X550");
13416f37f232SEric Joyner 
13426f37f232SEric Joyner 	/* Map VF to queues */
13436f37f232SEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_MRQC);
13446f37f232SEric Joyner 	switch (reg & IXGBE_MRQC_MRQE_MASK) {
13456f37f232SEric Joyner 	case IXGBE_MRQC_VMDQRT8TCEN:
13466f37f232SEric Joyner 		num_qs = 8;  /* 16 VFs / pools */
13476f37f232SEric Joyner 		bitmask = 0x000000FF;
13486f37f232SEric Joyner 		break;
13496f37f232SEric Joyner 	case IXGBE_MRQC_VMDQRSS32EN:
13506f37f232SEric Joyner 	case IXGBE_MRQC_VMDQRT4TCEN:
13516f37f232SEric Joyner 		num_qs = 4;  /* 32 VFs / pools */
13526f37f232SEric Joyner 		bitmask = 0x0000000F;
13536f37f232SEric Joyner 		break;
13546f37f232SEric Joyner 	default:            /* 64 VFs / pools */
13556f37f232SEric Joyner 		num_qs = 2;
13566f37f232SEric Joyner 		bitmask = 0x00000003;
13576f37f232SEric Joyner 		break;
13586f37f232SEric Joyner 	}
13596f37f232SEric Joyner 	start_q = vf * num_qs;
13606f37f232SEric Joyner 
13616f37f232SEric Joyner 	/* Release vf's queues by clearing WQBR_TX and WQBR_RX (RW1C) */
13626f37f232SEric Joyner 	idx = start_q / 32;
13636f37f232SEric Joyner 	reg = 0;
13646f37f232SEric Joyner 	reg |= (bitmask << (start_q % 32));
13656f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_WQBR_TX(idx), reg);
13666f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_WQBR_RX(idx), reg);
13676f37f232SEric Joyner }
13686f37f232SEric Joyner 
13696f37f232SEric Joyner /**
13706f37f232SEric Joyner  * ixgbe_mdd_event_X550
13716f37f232SEric Joyner  * @hw: pointer to hardware structure
13726f37f232SEric Joyner  * @vf_bitmap: vf bitmap of malicious vfs
13736f37f232SEric Joyner  *
13746f37f232SEric Joyner  * Handle malicious driver detection event.
13756f37f232SEric Joyner  **/
ixgbe_mdd_event_X550(struct ixgbe_hw * hw,u32 * vf_bitmap)13766f37f232SEric Joyner void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap)
13776f37f232SEric Joyner {
13786f37f232SEric Joyner 	u32 wqbr;
13796f37f232SEric Joyner 	u32 i, j, reg, q, shift, vf, idx;
13806f37f232SEric Joyner 
13816f37f232SEric Joyner 	DEBUGFUNC("ixgbe_mdd_event_X550");
13826f37f232SEric Joyner 
13836f37f232SEric Joyner 	/* figure out pool size for mapping to vf's */
13846f37f232SEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_MRQC);
13856f37f232SEric Joyner 	switch (reg & IXGBE_MRQC_MRQE_MASK) {
13866f37f232SEric Joyner 	case IXGBE_MRQC_VMDQRT8TCEN:
13876f37f232SEric Joyner 		shift = 3;  /* 16 VFs / pools */
13886f37f232SEric Joyner 		break;
13896f37f232SEric Joyner 	case IXGBE_MRQC_VMDQRSS32EN:
13906f37f232SEric Joyner 	case IXGBE_MRQC_VMDQRT4TCEN:
13916f37f232SEric Joyner 		shift = 2;  /* 32 VFs / pools */
13926f37f232SEric Joyner 		break;
13936f37f232SEric Joyner 	default:
13946f37f232SEric Joyner 		shift = 1;  /* 64 VFs / pools */
13956f37f232SEric Joyner 		break;
13966f37f232SEric Joyner 	}
13976f37f232SEric Joyner 
13986f37f232SEric Joyner 	/* Read WQBR_TX and WQBR_RX and check for malicious queues */
13996f37f232SEric Joyner 	for (i = 0; i < 4; i++) {
14006f37f232SEric Joyner 		wqbr = IXGBE_READ_REG(hw, IXGBE_WQBR_TX(i));
14016f37f232SEric Joyner 		wqbr |= IXGBE_READ_REG(hw, IXGBE_WQBR_RX(i));
14026f37f232SEric Joyner 
14036f37f232SEric Joyner 		if (!wqbr)
14046f37f232SEric Joyner 			continue;
14056f37f232SEric Joyner 
14066f37f232SEric Joyner 		/* Get malicious queue */
14076f37f232SEric Joyner 		for (j = 0; j < 32 && wqbr; j++) {
14086f37f232SEric Joyner 
14096f37f232SEric Joyner 			if (!(wqbr & (1 << j)))
14106f37f232SEric Joyner 				continue;
14116f37f232SEric Joyner 
14126f37f232SEric Joyner 			/* Get queue from bitmask */
14136f37f232SEric Joyner 			q = j + (i * 32);
14146f37f232SEric Joyner 
14156f37f232SEric Joyner 			/* Map queue to vf */
14166f37f232SEric Joyner 			vf = (q >> shift);
14176f37f232SEric Joyner 
14186f37f232SEric Joyner 			/* Set vf bit in vf_bitmap */
14196f37f232SEric Joyner 			idx = vf / 32;
14206f37f232SEric Joyner 			vf_bitmap[idx] |= (1 << (vf % 32));
14216f37f232SEric Joyner 			wqbr &= ~(1 << j);
14226f37f232SEric Joyner 		}
14236f37f232SEric Joyner 	}
14246f37f232SEric Joyner }
14256f37f232SEric Joyner 
14266f37f232SEric Joyner /**
14276f37f232SEric Joyner  * ixgbe_get_media_type_X550em - Get media type
14286f37f232SEric Joyner  * @hw: pointer to hardware structure
14296f37f232SEric Joyner  *
14306f37f232SEric Joyner  * Returns the media type (fiber, copper, backplane)
14316f37f232SEric Joyner  */
ixgbe_get_media_type_X550em(struct ixgbe_hw * hw)14326f37f232SEric Joyner enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
14336f37f232SEric Joyner {
14346f37f232SEric Joyner 	enum ixgbe_media_type media_type;
14356f37f232SEric Joyner 
14366f37f232SEric Joyner 	DEBUGFUNC("ixgbe_get_media_type_X550em");
14376f37f232SEric Joyner 
14386f37f232SEric Joyner 	/* Detect if there is a copper PHY attached. */
14396f37f232SEric Joyner 	switch (hw->device_id) {
14406f37f232SEric Joyner 	case IXGBE_DEV_ID_X550EM_X_KR:
14416f37f232SEric Joyner 	case IXGBE_DEV_ID_X550EM_X_KX4:
14428eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_XFI:
14438eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_KR:
14448eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_KR_L:
14456f37f232SEric Joyner 		media_type = ixgbe_media_type_backplane;
14466f37f232SEric Joyner 		break;
14476f37f232SEric Joyner 	case IXGBE_DEV_ID_X550EM_X_SFP:
14488eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_SFP:
14498eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_SFP_N:
14508eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_QSFP:
14518eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_QSFP_N:
14526f37f232SEric Joyner 		media_type = ixgbe_media_type_fiber;
14536f37f232SEric Joyner 		break;
14546f37f232SEric Joyner 	case IXGBE_DEV_ID_X550EM_X_1G_T:
14556f37f232SEric Joyner 	case IXGBE_DEV_ID_X550EM_X_10G_T:
14568eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_10G_T:
14578eb6488eSEric Joyner 		media_type = ixgbe_media_type_copper;
14588eb6488eSEric Joyner 		break;
14598eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_SGMII:
14608eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_SGMII_L:
14618eb6488eSEric Joyner 		media_type = ixgbe_media_type_backplane;
14628eb6488eSEric Joyner 		hw->phy.type = ixgbe_phy_sgmii;
14638eb6488eSEric Joyner 		break;
14648eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T:
14658eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
14666f37f232SEric Joyner 		media_type = ixgbe_media_type_copper;
14676f37f232SEric Joyner 		break;
14686f37f232SEric Joyner 	default:
14696f37f232SEric Joyner 		media_type = ixgbe_media_type_unknown;
14706f37f232SEric Joyner 		break;
14716f37f232SEric Joyner 	}
14726f37f232SEric Joyner 	return media_type;
14736f37f232SEric Joyner }
14746f37f232SEric Joyner 
14756f37f232SEric Joyner /**
14766f37f232SEric Joyner  * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported
14776f37f232SEric Joyner  * @hw: pointer to hardware structure
147879b36ec9SKevin Bowling  * @linear: true if SFP module is linear
14796f37f232SEric Joyner  */
ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw * hw,bool * linear)14806f37f232SEric Joyner static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear)
14816f37f232SEric Joyner {
14826f37f232SEric Joyner 	DEBUGFUNC("ixgbe_supported_sfp_modules_X550em");
14836f37f232SEric Joyner 
14846f37f232SEric Joyner 	switch (hw->phy.sfp_type) {
14856f37f232SEric Joyner 	case ixgbe_sfp_type_not_present:
14866f37f232SEric Joyner 		return IXGBE_ERR_SFP_NOT_PRESENT;
14876f37f232SEric Joyner 	case ixgbe_sfp_type_da_cu_core0:
14886f37f232SEric Joyner 	case ixgbe_sfp_type_da_cu_core1:
148979b36ec9SKevin Bowling 		*linear = true;
14906f37f232SEric Joyner 		break;
14916f37f232SEric Joyner 	case ixgbe_sfp_type_srlr_core0:
14926f37f232SEric Joyner 	case ixgbe_sfp_type_srlr_core1:
14936f37f232SEric Joyner 	case ixgbe_sfp_type_da_act_lmt_core0:
14946f37f232SEric Joyner 	case ixgbe_sfp_type_da_act_lmt_core1:
14956f37f232SEric Joyner 	case ixgbe_sfp_type_1g_sx_core0:
14966f37f232SEric Joyner 	case ixgbe_sfp_type_1g_sx_core1:
14976f37f232SEric Joyner 	case ixgbe_sfp_type_1g_lx_core0:
14986f37f232SEric Joyner 	case ixgbe_sfp_type_1g_lx_core1:
1499*18362165SKevin Bowling 	case ixgbe_sfp_type_1g_bx_core0:
1500*18362165SKevin Bowling 	case ixgbe_sfp_type_1g_bx_core1:
150179b36ec9SKevin Bowling 		*linear = false;
15026f37f232SEric Joyner 		break;
15036f37f232SEric Joyner 	case ixgbe_sfp_type_unknown:
15046f37f232SEric Joyner 	case ixgbe_sfp_type_1g_cu_core0:
15056f37f232SEric Joyner 	case ixgbe_sfp_type_1g_cu_core1:
15066f37f232SEric Joyner 	default:
15076f37f232SEric Joyner 		return IXGBE_ERR_SFP_NOT_SUPPORTED;
15086f37f232SEric Joyner 	}
15096f37f232SEric Joyner 
15106f37f232SEric Joyner 	return IXGBE_SUCCESS;
15116f37f232SEric Joyner }
15126f37f232SEric Joyner 
15136f37f232SEric Joyner /**
15146f37f232SEric Joyner  * ixgbe_identify_sfp_module_X550em - Identifies SFP modules
15156f37f232SEric Joyner  * @hw: pointer to hardware structure
15166f37f232SEric Joyner  *
15176f37f232SEric Joyner  * Searches for and identifies the SFP module and assigns appropriate PHY type.
15186f37f232SEric Joyner  **/
ixgbe_identify_sfp_module_X550em(struct ixgbe_hw * hw)15196f37f232SEric Joyner s32 ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw)
15206f37f232SEric Joyner {
15216f37f232SEric Joyner 	s32 status;
15226f37f232SEric Joyner 	bool linear;
15236f37f232SEric Joyner 
15246f37f232SEric Joyner 	DEBUGFUNC("ixgbe_identify_sfp_module_X550em");
15256f37f232SEric Joyner 
15266f37f232SEric Joyner 	status = ixgbe_identify_module_generic(hw);
15276f37f232SEric Joyner 
15286f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
15296f37f232SEric Joyner 		return status;
15306f37f232SEric Joyner 
15316f37f232SEric Joyner 	/* Check if SFP module is supported */
15326f37f232SEric Joyner 	status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
15336f37f232SEric Joyner 
15346f37f232SEric Joyner 	return status;
15356f37f232SEric Joyner }
15366f37f232SEric Joyner 
15376f37f232SEric Joyner /**
15386f37f232SEric Joyner  * ixgbe_setup_sfp_modules_X550em - Setup MAC link ops
15396f37f232SEric Joyner  * @hw: pointer to hardware structure
15406f37f232SEric Joyner  */
ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw * hw)15416f37f232SEric Joyner s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
15426f37f232SEric Joyner {
15436f37f232SEric Joyner 	s32 status;
15446f37f232SEric Joyner 	bool linear;
15456f37f232SEric Joyner 
15466f37f232SEric Joyner 	DEBUGFUNC("ixgbe_setup_sfp_modules_X550em");
15476f37f232SEric Joyner 
15486f37f232SEric Joyner 	/* Check if SFP module is supported */
15496f37f232SEric Joyner 	status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
15506f37f232SEric Joyner 
15516f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
15526f37f232SEric Joyner 		return status;
15536f37f232SEric Joyner 
15546f37f232SEric Joyner 	ixgbe_init_mac_link_ops_X550em(hw);
15556f37f232SEric Joyner 	hw->phy.ops.reset = NULL;
15566f37f232SEric Joyner 
15576f37f232SEric Joyner 	return IXGBE_SUCCESS;
15586f37f232SEric Joyner }
15596f37f232SEric Joyner 
15606f37f232SEric Joyner /**
15618eb6488eSEric Joyner *  ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the
15628eb6488eSEric Joyner *  internal PHY
15638eb6488eSEric Joyner *  @hw: pointer to hardware structure
15648eb6488eSEric Joyner **/
ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw * hw)15658eb6488eSEric Joyner static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
15668eb6488eSEric Joyner {
15678eb6488eSEric Joyner 	s32 status;
15688eb6488eSEric Joyner 	u32 link_ctrl;
15698eb6488eSEric Joyner 
15708eb6488eSEric Joyner 	/* Restart auto-negotiation. */
15718eb6488eSEric Joyner 	status = hw->mac.ops.read_iosf_sb_reg(hw,
15728eb6488eSEric Joyner 				       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
15738eb6488eSEric Joyner 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl);
15748eb6488eSEric Joyner 
15758eb6488eSEric Joyner 	if (status) {
15768eb6488eSEric Joyner 		DEBUGOUT("Auto-negotiation did not complete\n");
15778eb6488eSEric Joyner 		return status;
15788eb6488eSEric Joyner 	}
15798eb6488eSEric Joyner 
15808eb6488eSEric Joyner 	link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
15818eb6488eSEric Joyner 	status = hw->mac.ops.write_iosf_sb_reg(hw,
15828eb6488eSEric Joyner 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
15838eb6488eSEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl);
15848eb6488eSEric Joyner 
15858eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_X550EM_a) {
15868eb6488eSEric Joyner 		u32 flx_mask_st20;
15878eb6488eSEric Joyner 
15888eb6488eSEric Joyner 		/* Indicate to FW that AN restart has been asserted */
15898eb6488eSEric Joyner 		status = hw->mac.ops.read_iosf_sb_reg(hw,
15908eb6488eSEric Joyner 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
15918eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20);
15928eb6488eSEric Joyner 
15938eb6488eSEric Joyner 		if (status) {
15948eb6488eSEric Joyner 			DEBUGOUT("Auto-negotiation did not complete\n");
15958eb6488eSEric Joyner 			return status;
15968eb6488eSEric Joyner 		}
15978eb6488eSEric Joyner 
15988eb6488eSEric Joyner 		flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART;
15998eb6488eSEric Joyner 		status = hw->mac.ops.write_iosf_sb_reg(hw,
16008eb6488eSEric Joyner 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
16018eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20);
16028eb6488eSEric Joyner 	}
16038eb6488eSEric Joyner 
16048eb6488eSEric Joyner 	return status;
16058eb6488eSEric Joyner }
16068eb6488eSEric Joyner 
16078eb6488eSEric Joyner /**
16088eb6488eSEric Joyner  * ixgbe_setup_sgmii - Set up link for sgmii
16098eb6488eSEric Joyner  * @hw: pointer to hardware structure
16107d48aa4cSEric Joyner  * @speed: new link speed
161179b36ec9SKevin Bowling  * @autoneg_wait: true when waiting for completion is needed
16128eb6488eSEric Joyner  */
ixgbe_setup_sgmii(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait)16138eb6488eSEric Joyner static s32 ixgbe_setup_sgmii(struct ixgbe_hw *hw, ixgbe_link_speed speed,
16148eb6488eSEric Joyner 			     bool autoneg_wait)
16158eb6488eSEric Joyner {
16168eb6488eSEric Joyner 	struct ixgbe_mac_info *mac = &hw->mac;
16178eb6488eSEric Joyner 	u32 lval, sval, flx_val;
16188eb6488eSEric Joyner 	s32 rc;
16198eb6488eSEric Joyner 
16208eb6488eSEric Joyner 	rc = mac->ops.read_iosf_sb_reg(hw,
16218eb6488eSEric Joyner 				       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
16228eb6488eSEric Joyner 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
16238eb6488eSEric Joyner 	if (rc)
16248eb6488eSEric Joyner 		return rc;
16258eb6488eSEric Joyner 
16268eb6488eSEric Joyner 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
16278eb6488eSEric Joyner 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
16288eb6488eSEric Joyner 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
16298eb6488eSEric Joyner 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
16308eb6488eSEric Joyner 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
16318eb6488eSEric Joyner 	rc = mac->ops.write_iosf_sb_reg(hw,
16328eb6488eSEric Joyner 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
16338eb6488eSEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
16348eb6488eSEric Joyner 	if (rc)
16358eb6488eSEric Joyner 		return rc;
16368eb6488eSEric Joyner 
16378eb6488eSEric Joyner 	rc = mac->ops.read_iosf_sb_reg(hw,
16388eb6488eSEric Joyner 				       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
16398eb6488eSEric Joyner 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
16408eb6488eSEric Joyner 	if (rc)
16418eb6488eSEric Joyner 		return rc;
16428eb6488eSEric Joyner 
16438eb6488eSEric Joyner 	sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
16448eb6488eSEric Joyner 	sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
16458eb6488eSEric Joyner 	rc = mac->ops.write_iosf_sb_reg(hw,
16468eb6488eSEric Joyner 					IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
16478eb6488eSEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
16488eb6488eSEric Joyner 	if (rc)
16498eb6488eSEric Joyner 		return rc;
16508eb6488eSEric Joyner 
16518eb6488eSEric Joyner 	rc = mac->ops.read_iosf_sb_reg(hw,
16528eb6488eSEric Joyner 				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
16538eb6488eSEric Joyner 				    IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
16548eb6488eSEric Joyner 	if (rc)
16558eb6488eSEric Joyner 		return rc;
16568eb6488eSEric Joyner 
16578eb6488eSEric Joyner 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
16588eb6488eSEric Joyner 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
16598eb6488eSEric Joyner 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
16608eb6488eSEric Joyner 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
16618eb6488eSEric Joyner 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
16628eb6488eSEric Joyner 
16638eb6488eSEric Joyner 	rc = mac->ops.write_iosf_sb_reg(hw,
16648eb6488eSEric Joyner 				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
16658eb6488eSEric Joyner 				    IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
16668eb6488eSEric Joyner 	if (rc)
16678eb6488eSEric Joyner 		return rc;
16688eb6488eSEric Joyner 
16698eb6488eSEric Joyner 	rc = ixgbe_restart_an_internal_phy_x550em(hw);
16708eb6488eSEric Joyner 	if (rc)
16718eb6488eSEric Joyner 		return rc;
16728eb6488eSEric Joyner 
16738eb6488eSEric Joyner 	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
16748eb6488eSEric Joyner }
16758eb6488eSEric Joyner 
16768eb6488eSEric Joyner /**
16777d48aa4cSEric Joyner  * ixgbe_setup_sgmii_fw - Set up link for internal PHY SGMII auto-negotiation
16788eb6488eSEric Joyner  * @hw: pointer to hardware structure
16797d48aa4cSEric Joyner  * @speed: new link speed
168079b36ec9SKevin Bowling  * @autoneg_wait: true when waiting for completion is needed
16818eb6488eSEric Joyner  */
ixgbe_setup_sgmii_fw(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait)16828eb6488eSEric Joyner static s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed,
16838eb6488eSEric Joyner 				bool autoneg_wait)
16848eb6488eSEric Joyner {
16858eb6488eSEric Joyner 	struct ixgbe_mac_info *mac = &hw->mac;
16868eb6488eSEric Joyner 	u32 lval, sval, flx_val;
16878eb6488eSEric Joyner 	s32 rc;
16888eb6488eSEric Joyner 
16898eb6488eSEric Joyner 	rc = mac->ops.read_iosf_sb_reg(hw,
16908eb6488eSEric Joyner 				       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
16918eb6488eSEric Joyner 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
16928eb6488eSEric Joyner 	if (rc)
16938eb6488eSEric Joyner 		return rc;
16948eb6488eSEric Joyner 
16958eb6488eSEric Joyner 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
16968eb6488eSEric Joyner 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
16978eb6488eSEric Joyner 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
16988eb6488eSEric Joyner 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
16998eb6488eSEric Joyner 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
17008eb6488eSEric Joyner 	rc = mac->ops.write_iosf_sb_reg(hw,
17018eb6488eSEric Joyner 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
17028eb6488eSEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
17038eb6488eSEric Joyner 	if (rc)
17048eb6488eSEric Joyner 		return rc;
17058eb6488eSEric Joyner 
17068eb6488eSEric Joyner 	rc = mac->ops.read_iosf_sb_reg(hw,
17078eb6488eSEric Joyner 				       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
17088eb6488eSEric Joyner 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
17098eb6488eSEric Joyner 	if (rc)
17108eb6488eSEric Joyner 		return rc;
17118eb6488eSEric Joyner 
17128eb6488eSEric Joyner 	sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
17138eb6488eSEric Joyner 	sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
17148eb6488eSEric Joyner 	rc = mac->ops.write_iosf_sb_reg(hw,
17158eb6488eSEric Joyner 					IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
17168eb6488eSEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
17178eb6488eSEric Joyner 	if (rc)
17188eb6488eSEric Joyner 		return rc;
17198eb6488eSEric Joyner 
17208eb6488eSEric Joyner 	rc = mac->ops.write_iosf_sb_reg(hw,
17218eb6488eSEric Joyner 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
17228eb6488eSEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
17238eb6488eSEric Joyner 	if (rc)
17248eb6488eSEric Joyner 		return rc;
17258eb6488eSEric Joyner 
17268eb6488eSEric Joyner 	rc = mac->ops.read_iosf_sb_reg(hw,
17278eb6488eSEric Joyner 				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
17288eb6488eSEric Joyner 				    IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
17298eb6488eSEric Joyner 	if (rc)
17308eb6488eSEric Joyner 		return rc;
17318eb6488eSEric Joyner 
17328eb6488eSEric Joyner 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
17338eb6488eSEric Joyner 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
17348eb6488eSEric Joyner 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
17358eb6488eSEric Joyner 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
17368eb6488eSEric Joyner 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
17378eb6488eSEric Joyner 
17388eb6488eSEric Joyner 	rc = mac->ops.write_iosf_sb_reg(hw,
17398eb6488eSEric Joyner 				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
17408eb6488eSEric Joyner 				    IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
17418eb6488eSEric Joyner 	if (rc)
17428eb6488eSEric Joyner 		return rc;
17438eb6488eSEric Joyner 
17448eb6488eSEric Joyner 	rc = ixgbe_restart_an_internal_phy_x550em(hw);
17458eb6488eSEric Joyner 
17468eb6488eSEric Joyner 	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
17478eb6488eSEric Joyner }
17488eb6488eSEric Joyner 
17498eb6488eSEric Joyner /**
17506f37f232SEric Joyner  * ixgbe_init_mac_link_ops_X550em - init mac link function pointers
17516f37f232SEric Joyner  * @hw: pointer to hardware structure
17526f37f232SEric Joyner  */
ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw * hw)17536f37f232SEric Joyner void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
17546f37f232SEric Joyner {
17556f37f232SEric Joyner 	struct ixgbe_mac_info *mac = &hw->mac;
17566f37f232SEric Joyner 
17576f37f232SEric Joyner 	DEBUGFUNC("ixgbe_init_mac_link_ops_X550em");
17586f37f232SEric Joyner 
17596f37f232SEric Joyner 	switch (hw->mac.ops.get_media_type(hw)) {
17606f37f232SEric Joyner 	case ixgbe_media_type_fiber:
17616f37f232SEric Joyner 		/* CS4227 does not support autoneg, so disable the laser control
17626f37f232SEric Joyner 		 * functions for SFP+ fiber
17636f37f232SEric Joyner 		 */
17646f37f232SEric Joyner 		mac->ops.disable_tx_laser = NULL;
17656f37f232SEric Joyner 		mac->ops.enable_tx_laser = NULL;
17666f37f232SEric Joyner 		mac->ops.flap_tx_laser = NULL;
17676f37f232SEric Joyner 		mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
17686f37f232SEric Joyner 		mac->ops.set_rate_select_speed =
17696f37f232SEric Joyner 					ixgbe_set_soft_rate_select_speed;
17708eb6488eSEric Joyner 
17718eb6488eSEric Joyner 		if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) ||
17728eb6488eSEric Joyner 		    (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP))
17738eb6488eSEric Joyner 			mac->ops.setup_mac_link =
17748eb6488eSEric Joyner 						ixgbe_setup_mac_link_sfp_x550a;
17758eb6488eSEric Joyner 		else
17768eb6488eSEric Joyner 			mac->ops.setup_mac_link =
17778eb6488eSEric Joyner 						ixgbe_setup_mac_link_sfp_x550em;
17786f37f232SEric Joyner 		break;
17796f37f232SEric Joyner 	case ixgbe_media_type_copper:
17808eb6488eSEric Joyner 		if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T)
17818eb6488eSEric Joyner 			break;
17828eb6488eSEric Joyner 		if (hw->mac.type == ixgbe_mac_X550EM_a) {
17838eb6488eSEric Joyner 			if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
17848eb6488eSEric Joyner 			    hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) {
17858eb6488eSEric Joyner 				mac->ops.setup_link = ixgbe_setup_sgmii_fw;
17868eb6488eSEric Joyner 				mac->ops.check_link =
17878eb6488eSEric Joyner 						   ixgbe_check_mac_link_generic;
17888eb6488eSEric Joyner 			} else {
17898eb6488eSEric Joyner 				mac->ops.setup_link =
17908eb6488eSEric Joyner 						  ixgbe_setup_mac_link_t_X550em;
17918eb6488eSEric Joyner 			}
17928eb6488eSEric Joyner 		} else {
17936f37f232SEric Joyner 			mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
17946f37f232SEric Joyner 			mac->ops.check_link = ixgbe_check_link_t_X550em;
17958eb6488eSEric Joyner 		}
17968eb6488eSEric Joyner 		break;
17978eb6488eSEric Joyner 	case ixgbe_media_type_backplane:
17988eb6488eSEric Joyner 		if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
17998eb6488eSEric Joyner 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)
18008eb6488eSEric Joyner 			mac->ops.setup_link = ixgbe_setup_sgmii;
18016f37f232SEric Joyner 		break;
18026f37f232SEric Joyner 	default:
18036f37f232SEric Joyner 		break;
18046f37f232SEric Joyner 	}
18056f37f232SEric Joyner }
18066f37f232SEric Joyner 
18076f37f232SEric Joyner /**
1808edef2769SRadoslaw Tyl  * ixgbe_get_link_capabilities_X550em - Determines link capabilities
18096f37f232SEric Joyner  * @hw: pointer to hardware structure
18106f37f232SEric Joyner  * @speed: pointer to link speed
181179b36ec9SKevin Bowling  * @autoneg: true when autoneg or autotry is enabled
18126f37f232SEric Joyner  */
ixgbe_get_link_capabilities_X550em(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * autoneg)18136f37f232SEric Joyner s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
18146f37f232SEric Joyner 				       ixgbe_link_speed *speed,
18156f37f232SEric Joyner 				       bool *autoneg)
18166f37f232SEric Joyner {
18176f37f232SEric Joyner 	DEBUGFUNC("ixgbe_get_link_capabilities_X550em");
18186f37f232SEric Joyner 
18198eb6488eSEric Joyner 
18208eb6488eSEric Joyner 	if (hw->phy.type == ixgbe_phy_fw) {
182179b36ec9SKevin Bowling 		*autoneg = true;
18228eb6488eSEric Joyner 		*speed = hw->phy.speeds_supported;
18238eb6488eSEric Joyner 		return 0;
18248eb6488eSEric Joyner 	}
18258eb6488eSEric Joyner 
18266f37f232SEric Joyner 	/* SFP */
18276f37f232SEric Joyner 	if (hw->phy.media_type == ixgbe_media_type_fiber) {
18286f37f232SEric Joyner 
18296f37f232SEric Joyner 		/* CS4227 SFP must not enable auto-negotiation */
183079b36ec9SKevin Bowling 		*autoneg = false;
18316f37f232SEric Joyner 
18326f37f232SEric Joyner 		/* Check if 1G SFP module. */
18336f37f232SEric Joyner 		if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
1834*18362165SKevin Bowling 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
1835*18362165SKevin Bowling 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
1836*18362165SKevin Bowling 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
1837*18362165SKevin Bowling 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core0 ||
1838*18362165SKevin Bowling 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core1) {
18396f37f232SEric Joyner 			*speed = IXGBE_LINK_SPEED_1GB_FULL;
18406f37f232SEric Joyner 			return IXGBE_SUCCESS;
18416f37f232SEric Joyner 		}
18426f37f232SEric Joyner 
18436f37f232SEric Joyner 		/* Link capabilities are based on SFP */
18446f37f232SEric Joyner 		if (hw->phy.multispeed_fiber)
18456f37f232SEric Joyner 			*speed = IXGBE_LINK_SPEED_10GB_FULL |
18466f37f232SEric Joyner 				 IXGBE_LINK_SPEED_1GB_FULL;
18476f37f232SEric Joyner 		else
18486f37f232SEric Joyner 			*speed = IXGBE_LINK_SPEED_10GB_FULL;
18496f37f232SEric Joyner 	} else {
18508e9f1b23SGuinan Sun 		*autoneg = true;
18518e9f1b23SGuinan Sun 
18528eb6488eSEric Joyner 		switch (hw->phy.type) {
18538e9f1b23SGuinan Sun 		case ixgbe_phy_x550em_xfi:
18548e9f1b23SGuinan Sun 			*speed = IXGBE_LINK_SPEED_1GB_FULL |
18558e9f1b23SGuinan Sun 					 IXGBE_LINK_SPEED_10GB_FULL;
18568e9f1b23SGuinan Sun 			*autoneg = false;
18578e9f1b23SGuinan Sun 			break;
18588eb6488eSEric Joyner 		case ixgbe_phy_ext_1g_t:
18598eb6488eSEric Joyner 		case ixgbe_phy_sgmii:
18608eb6488eSEric Joyner 			*speed = IXGBE_LINK_SPEED_1GB_FULL;
18618eb6488eSEric Joyner 			break;
18628eb6488eSEric Joyner 		case ixgbe_phy_x550em_kr:
18638eb6488eSEric Joyner 			if (hw->mac.type == ixgbe_mac_X550EM_a) {
18648eb6488eSEric Joyner 				/* check different backplane modes */
18658eb6488eSEric Joyner 				if (hw->phy.nw_mng_if_sel &
18668eb6488eSEric Joyner 					   IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
18678eb6488eSEric Joyner 					*speed = IXGBE_LINK_SPEED_2_5GB_FULL;
18688eb6488eSEric Joyner 					break;
18698eb6488eSEric Joyner 				} else if (hw->device_id ==
18708eb6488eSEric Joyner 						   IXGBE_DEV_ID_X550EM_A_KR_L) {
18718eb6488eSEric Joyner 					*speed = IXGBE_LINK_SPEED_1GB_FULL;
18728eb6488eSEric Joyner 					break;
18738eb6488eSEric Joyner 				}
18748eb6488eSEric Joyner 			}
187550455f73SPiotr Skajewski 			*speed = IXGBE_LINK_SPEED_10GB_FULL |
187650455f73SPiotr Skajewski 				 IXGBE_LINK_SPEED_1GB_FULL;
187750455f73SPiotr Skajewski 			break;
18788eb6488eSEric Joyner 		default:
18796f37f232SEric Joyner 			*speed = IXGBE_LINK_SPEED_10GB_FULL |
18806f37f232SEric Joyner 				 IXGBE_LINK_SPEED_1GB_FULL;
18818eb6488eSEric Joyner 			break;
18828eb6488eSEric Joyner 		}
18836f37f232SEric Joyner 	}
18846f37f232SEric Joyner 
18856f37f232SEric Joyner 	return IXGBE_SUCCESS;
18866f37f232SEric Joyner }
18876f37f232SEric Joyner 
18886f37f232SEric Joyner /**
18896f37f232SEric Joyner  * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause
18906f37f232SEric Joyner  * @hw: pointer to hardware structure
18916f37f232SEric Joyner  * @lsc: pointer to boolean flag which indicates whether external Base T
18926f37f232SEric Joyner  *      PHY interrupt is lsc
18936f37f232SEric Joyner  *
18946f37f232SEric Joyner  * Determime if external Base T PHY interrupt cause is high temperature
18956f37f232SEric Joyner  * failure alarm or link status change.
18966f37f232SEric Joyner  *
18976f37f232SEric Joyner  * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
18986f37f232SEric Joyner  * failure alarm, else return PHY access status.
18996f37f232SEric Joyner  */
ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw * hw,bool * lsc)19006f37f232SEric Joyner static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
19016f37f232SEric Joyner {
19026f37f232SEric Joyner 	u32 status;
19036f37f232SEric Joyner 	u16 reg;
19046f37f232SEric Joyner 
190579b36ec9SKevin Bowling 	*lsc = false;
19066f37f232SEric Joyner 
19076f37f232SEric Joyner 	/* Vendor alarm triggered */
19086f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
19096f37f232SEric Joyner 				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
19106f37f232SEric Joyner 				      &reg);
19116f37f232SEric Joyner 
19126f37f232SEric Joyner 	if (status != IXGBE_SUCCESS ||
19136f37f232SEric Joyner 	    !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
19146f37f232SEric Joyner 		return status;
19156f37f232SEric Joyner 
19166f37f232SEric Joyner 	/* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
19176f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
19186f37f232SEric Joyner 				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
19196f37f232SEric Joyner 				      &reg);
19206f37f232SEric Joyner 
19216f37f232SEric Joyner 	if (status != IXGBE_SUCCESS ||
19226f37f232SEric Joyner 	    !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
19236f37f232SEric Joyner 	    IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
19246f37f232SEric Joyner 		return status;
19256f37f232SEric Joyner 
19261ebf555bSSteven Hartland 	/* Global alarm triggered */
19276f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
19286f37f232SEric Joyner 				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
19296f37f232SEric Joyner 				      &reg);
19306f37f232SEric Joyner 
19316f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
19326f37f232SEric Joyner 		return status;
19336f37f232SEric Joyner 
19346f37f232SEric Joyner 	/* If high temperature failure, then return over temp error and exit */
19356f37f232SEric Joyner 	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
19366f37f232SEric Joyner 		/* power down the PHY in case the PHY FW didn't already */
193779b36ec9SKevin Bowling 		ixgbe_set_copper_phy_power(hw, false);
19386f37f232SEric Joyner 		return IXGBE_ERR_OVERTEMP;
19391ebf555bSSteven Hartland 	} else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
19401ebf555bSSteven Hartland 		/*  device fault alarm triggered */
19411ebf555bSSteven Hartland 		status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
19421ebf555bSSteven Hartland 					  IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
19431ebf555bSSteven Hartland 					  &reg);
19441ebf555bSSteven Hartland 
19451ebf555bSSteven Hartland 		if (status != IXGBE_SUCCESS)
19461ebf555bSSteven Hartland 			return status;
19471ebf555bSSteven Hartland 
19481ebf555bSSteven Hartland 		/* if device fault was due to high temp alarm handle and exit */
19491ebf555bSSteven Hartland 		if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
19501ebf555bSSteven Hartland 			/* power down the PHY in case the PHY FW didn't */
195179b36ec9SKevin Bowling 			ixgbe_set_copper_phy_power(hw, false);
19521ebf555bSSteven Hartland 			return IXGBE_ERR_OVERTEMP;
19531ebf555bSSteven Hartland 		}
19546f37f232SEric Joyner 	}
19556f37f232SEric Joyner 
19566f37f232SEric Joyner 	/* Vendor alarm 2 triggered */
19576f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
19586f37f232SEric Joyner 				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
19596f37f232SEric Joyner 
19606f37f232SEric Joyner 	if (status != IXGBE_SUCCESS ||
19616f37f232SEric Joyner 	    !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
19626f37f232SEric Joyner 		return status;
19636f37f232SEric Joyner 
19646f37f232SEric Joyner 	/* link connect/disconnect event occurred */
19656f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
19666f37f232SEric Joyner 				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
19676f37f232SEric Joyner 
19686f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
19696f37f232SEric Joyner 		return status;
19706f37f232SEric Joyner 
19716f37f232SEric Joyner 	/* Indicate LSC */
19726f37f232SEric Joyner 	if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC)
197379b36ec9SKevin Bowling 		*lsc = true;
19746f37f232SEric Joyner 
19756f37f232SEric Joyner 	return IXGBE_SUCCESS;
19766f37f232SEric Joyner }
19776f37f232SEric Joyner 
19786f37f232SEric Joyner /**
19796f37f232SEric Joyner  * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts
19806f37f232SEric Joyner  * @hw: pointer to hardware structure
19816f37f232SEric Joyner  *
19826f37f232SEric Joyner  * Enable link status change and temperature failure alarm for the external
19836f37f232SEric Joyner  * Base T PHY
19846f37f232SEric Joyner  *
19856f37f232SEric Joyner  * Returns PHY access status
19866f37f232SEric Joyner  */
ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw * hw)19876f37f232SEric Joyner static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
19886f37f232SEric Joyner {
19896f37f232SEric Joyner 	u32 status;
19906f37f232SEric Joyner 	u16 reg;
19916f37f232SEric Joyner 	bool lsc;
19926f37f232SEric Joyner 
19936f37f232SEric Joyner 	/* Clear interrupt flags */
19946f37f232SEric Joyner 	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
19956f37f232SEric Joyner 
19966f37f232SEric Joyner 	/* Enable link status change alarm */
19978eb6488eSEric Joyner 
19988eb6488eSEric Joyner 	/* Enable the LASI interrupts on X552 devices to receive notifications
19998eb6488eSEric Joyner 	 * of the link configurations of the external PHY and correspondingly
20008eb6488eSEric Joyner 	 * support the configuration of the internal iXFI link, since iXFI does
20018eb6488eSEric Joyner 	 * not support auto-negotiation. This is not required for X553 devices
20028eb6488eSEric Joyner 	 * having KR support, which performs auto-negotiations and which is used
20038eb6488eSEric Joyner 	 * as the internal link to the external PHY. Hence adding a check here
20048eb6488eSEric Joyner 	 * to avoid enabling LASI interrupts for X553 devices.
20058eb6488eSEric Joyner 	 */
20068eb6488eSEric Joyner 	if (hw->mac.type != ixgbe_mac_X550EM_a) {
20078eb6488eSEric Joyner 		status = hw->phy.ops.read_reg(hw,
20088eb6488eSEric Joyner 					IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
20096f37f232SEric Joyner 					IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
20106f37f232SEric Joyner 
20116f37f232SEric Joyner 		if (status != IXGBE_SUCCESS)
20126f37f232SEric Joyner 			return status;
20136f37f232SEric Joyner 
20146f37f232SEric Joyner 		reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
20156f37f232SEric Joyner 
20168eb6488eSEric Joyner 		status = hw->phy.ops.write_reg(hw,
20178eb6488eSEric Joyner 					IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
20186f37f232SEric Joyner 					IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg);
20196f37f232SEric Joyner 
20206f37f232SEric Joyner 		if (status != IXGBE_SUCCESS)
20216f37f232SEric Joyner 			return status;
20228eb6488eSEric Joyner 	}
20236f37f232SEric Joyner 
20248eb6488eSEric Joyner 	/* Enable high temperature failure and global fault alarms */
20256f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
20266f37f232SEric Joyner 				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20276f37f232SEric Joyner 				      &reg);
20286f37f232SEric Joyner 
20296f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
20306f37f232SEric Joyner 		return status;
20316f37f232SEric Joyner 
20328eb6488eSEric Joyner 	reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN |
20338eb6488eSEric Joyner 		IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);
20346f37f232SEric Joyner 
20356f37f232SEric Joyner 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
20366f37f232SEric Joyner 				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20376f37f232SEric Joyner 				       reg);
20386f37f232SEric Joyner 
20396f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
20406f37f232SEric Joyner 		return status;
20416f37f232SEric Joyner 
20426f37f232SEric Joyner 	/* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
20436f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
20446f37f232SEric Joyner 				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20456f37f232SEric Joyner 				      &reg);
20466f37f232SEric Joyner 
20476f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
20486f37f232SEric Joyner 		return status;
20496f37f232SEric Joyner 
20506f37f232SEric Joyner 	reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
20516f37f232SEric Joyner 		IXGBE_MDIO_GLOBAL_ALARM_1_INT);
20526f37f232SEric Joyner 
20536f37f232SEric Joyner 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
20546f37f232SEric Joyner 				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20556f37f232SEric Joyner 				       reg);
20566f37f232SEric Joyner 
20576f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
20586f37f232SEric Joyner 		return status;
20596f37f232SEric Joyner 
20606f37f232SEric Joyner 	/* Enable chip-wide vendor alarm */
20616f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
20626f37f232SEric Joyner 				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20636f37f232SEric Joyner 				      &reg);
20646f37f232SEric Joyner 
20656f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
20666f37f232SEric Joyner 		return status;
20676f37f232SEric Joyner 
20686f37f232SEric Joyner 	reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
20696f37f232SEric Joyner 
20706f37f232SEric Joyner 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
20716f37f232SEric Joyner 				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20726f37f232SEric Joyner 				       reg);
20736f37f232SEric Joyner 
20746f37f232SEric Joyner 	return status;
20756f37f232SEric Joyner }
20766f37f232SEric Joyner 
20776f37f232SEric Joyner /**
20786f37f232SEric Joyner  * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed.
20796f37f232SEric Joyner  * @hw: pointer to hardware structure
20806f37f232SEric Joyner  * @speed: link speed
20816f37f232SEric Joyner  *
20826f37f232SEric Joyner  * Configures the integrated KR PHY.
20836f37f232SEric Joyner  **/
ixgbe_setup_kr_speed_x550em(struct ixgbe_hw * hw,ixgbe_link_speed speed)20846f37f232SEric Joyner static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
20856f37f232SEric Joyner 				       ixgbe_link_speed speed)
20866f37f232SEric Joyner {
20876f37f232SEric Joyner 	s32 status;
20886f37f232SEric Joyner 	u32 reg_val;
20896f37f232SEric Joyner 
20908eb6488eSEric Joyner 	status = hw->mac.ops.read_iosf_sb_reg(hw,
20916f37f232SEric Joyner 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
20926f37f232SEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
20936f37f232SEric Joyner 	if (status)
20946f37f232SEric Joyner 		return status;
20956f37f232SEric Joyner 
20966f37f232SEric Joyner 	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
20976f37f232SEric Joyner 	reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
20986f37f232SEric Joyner 		     IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
20996f37f232SEric Joyner 
21006f37f232SEric Joyner 	/* Advertise 10G support. */
21016f37f232SEric Joyner 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
21026f37f232SEric Joyner 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR;
21036f37f232SEric Joyner 
21046f37f232SEric Joyner 	/* Advertise 1G support. */
21056f37f232SEric Joyner 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
21066f37f232SEric Joyner 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
21076f37f232SEric Joyner 
21088eb6488eSEric Joyner 	status = hw->mac.ops.write_iosf_sb_reg(hw,
21096f37f232SEric Joyner 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
21106f37f232SEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
21116f37f232SEric Joyner 
21128eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_X550EM_a) {
21138eb6488eSEric Joyner 		/* Set lane mode  to KR auto negotiation */
21148eb6488eSEric Joyner 		status = hw->mac.ops.read_iosf_sb_reg(hw,
21158eb6488eSEric Joyner 				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
21168eb6488eSEric Joyner 				    IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
21178eb6488eSEric Joyner 
21188eb6488eSEric Joyner 		if (status)
21196f37f232SEric Joyner 			return status;
21208eb6488eSEric Joyner 
21218eb6488eSEric Joyner 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
21228eb6488eSEric Joyner 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
21238eb6488eSEric Joyner 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
21248eb6488eSEric Joyner 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
21258eb6488eSEric Joyner 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
21268eb6488eSEric Joyner 
21278eb6488eSEric Joyner 		status = hw->mac.ops.write_iosf_sb_reg(hw,
21288eb6488eSEric Joyner 				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
21298eb6488eSEric Joyner 				    IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
21308eb6488eSEric Joyner 	}
21318eb6488eSEric Joyner 
21328eb6488eSEric Joyner 	return ixgbe_restart_an_internal_phy_x550em(hw);
21338eb6488eSEric Joyner }
21348eb6488eSEric Joyner 
21358eb6488eSEric Joyner /**
21368eb6488eSEric Joyner  * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs
21378eb6488eSEric Joyner  * @hw: pointer to hardware structure
21388eb6488eSEric Joyner  */
ixgbe_reset_phy_fw(struct ixgbe_hw * hw)21398eb6488eSEric Joyner static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw)
21408eb6488eSEric Joyner {
21418eb6488eSEric Joyner 	u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
21428eb6488eSEric Joyner 	s32 rc;
21438eb6488eSEric Joyner 
21448eb6488eSEric Joyner 	if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
21458eb6488eSEric Joyner 		return IXGBE_SUCCESS;
21468eb6488eSEric Joyner 
21478eb6488eSEric Joyner 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store);
21488eb6488eSEric Joyner 	if (rc)
21498eb6488eSEric Joyner 		return rc;
21508eb6488eSEric Joyner 	memset(store, 0, sizeof(store));
21518eb6488eSEric Joyner 
21528eb6488eSEric Joyner 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store);
21538eb6488eSEric Joyner 	if (rc)
21548eb6488eSEric Joyner 		return rc;
21558eb6488eSEric Joyner 
21568eb6488eSEric Joyner 	return ixgbe_setup_fw_link(hw);
21578eb6488eSEric Joyner }
21588eb6488eSEric Joyner 
21598eb6488eSEric Joyner /**
21608eb6488eSEric Joyner  * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp
21618eb6488eSEric Joyner  * @hw: pointer to hardware structure
21628eb6488eSEric Joyner  */
ixgbe_check_overtemp_fw(struct ixgbe_hw * hw)21638eb6488eSEric Joyner static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
21648eb6488eSEric Joyner {
21658eb6488eSEric Joyner 	u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
21668eb6488eSEric Joyner 	s32 rc;
21678eb6488eSEric Joyner 
21688eb6488eSEric Joyner 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);
21698eb6488eSEric Joyner 	if (rc)
21708eb6488eSEric Joyner 		return rc;
21718eb6488eSEric Joyner 
21728eb6488eSEric Joyner 	if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {
21738eb6488eSEric Joyner 		ixgbe_shutdown_fw_phy(hw);
21748eb6488eSEric Joyner 		return IXGBE_ERR_OVERTEMP;
21758eb6488eSEric Joyner 	}
21768eb6488eSEric Joyner 	return IXGBE_SUCCESS;
21778eb6488eSEric Joyner }
21788eb6488eSEric Joyner 
21798eb6488eSEric Joyner /**
21808eb6488eSEric Joyner  * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register
21818eb6488eSEric Joyner  * @hw: pointer to hardware structure
21828eb6488eSEric Joyner  *
21838eb6488eSEric Joyner  * Read NW_MNG_IF_SEL register and save field values, and check for valid field
21848eb6488eSEric Joyner  * values.
21858eb6488eSEric Joyner  **/
ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw * hw)21868eb6488eSEric Joyner static s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw)
21878eb6488eSEric Joyner {
21888eb6488eSEric Joyner 	/* Save NW management interface connected on board. This is used
21898eb6488eSEric Joyner 	 * to determine internal PHY mode.
21908eb6488eSEric Joyner 	 */
21918eb6488eSEric Joyner 	hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
21928eb6488eSEric Joyner 
21938eb6488eSEric Joyner 	/* If X552 (X550EM_a) and MDIO is connected to external PHY, then set
21948eb6488eSEric Joyner 	 * PHY address. This register field was has only been used for X552.
21958eb6488eSEric Joyner 	 */
21968eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_X550EM_a &&
21978eb6488eSEric Joyner 	    hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) {
21988eb6488eSEric Joyner 		hw->phy.addr = (hw->phy.nw_mng_if_sel &
21998eb6488eSEric Joyner 				IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
22008eb6488eSEric Joyner 			       IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
22018eb6488eSEric Joyner 	}
22028eb6488eSEric Joyner 
22038eb6488eSEric Joyner 	return IXGBE_SUCCESS;
22046f37f232SEric Joyner }
22056f37f232SEric Joyner 
22066f37f232SEric Joyner /**
22076f37f232SEric Joyner  * ixgbe_init_phy_ops_X550em - PHY/SFP specific init
22086f37f232SEric Joyner  * @hw: pointer to hardware structure
22096f37f232SEric Joyner  *
22106f37f232SEric Joyner  * Initialize any function pointers that were not able to be
22116f37f232SEric Joyner  * set during init_shared_code because the PHY/SFP type was
22126f37f232SEric Joyner  * not known.  Perform the SFP init if necessary.
22136f37f232SEric Joyner  */
ixgbe_init_phy_ops_X550em(struct ixgbe_hw * hw)22146f37f232SEric Joyner s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
22156f37f232SEric Joyner {
22166f37f232SEric Joyner 	struct ixgbe_phy_info *phy = &hw->phy;
22176f37f232SEric Joyner 	s32 ret_val;
22186f37f232SEric Joyner 
22196f37f232SEric Joyner 	DEBUGFUNC("ixgbe_init_phy_ops_X550em");
22206f37f232SEric Joyner 
22216f37f232SEric Joyner 	hw->mac.ops.set_lan_id(hw);
22228eb6488eSEric Joyner 	ixgbe_read_mng_if_sel_x550em(hw);
22236f37f232SEric Joyner 
22246f37f232SEric Joyner 	if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) {
22256f37f232SEric Joyner 		phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
22266f37f232SEric Joyner 		ixgbe_setup_mux_ctl(hw);
22276f37f232SEric Joyner 		phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em;
22286f37f232SEric Joyner 	}
22296f37f232SEric Joyner 
22308eb6488eSEric Joyner 	switch (hw->device_id) {
22318eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T:
22328eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
22337d48aa4cSEric Joyner 		phy->ops.read_reg_mdi = NULL;
22347d48aa4cSEric Joyner 		phy->ops.write_reg_mdi = NULL;
22357d48aa4cSEric Joyner 		hw->phy.ops.read_reg = NULL;
22367d48aa4cSEric Joyner 		hw->phy.ops.write_reg = NULL;
22378eb6488eSEric Joyner 		phy->ops.check_overtemp = ixgbe_check_overtemp_fw;
22388eb6488eSEric Joyner 		if (hw->bus.lan_id)
22398eb6488eSEric Joyner 			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
22408eb6488eSEric Joyner 		else
22418eb6488eSEric Joyner 			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
22428eb6488eSEric Joyner 
22438eb6488eSEric Joyner 		break;
22448eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_10G_T:
22458eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_SFP:
22468eb6488eSEric Joyner 		hw->phy.ops.read_reg = ixgbe_read_phy_reg_x550a;
22478eb6488eSEric Joyner 		hw->phy.ops.write_reg = ixgbe_write_phy_reg_x550a;
22488eb6488eSEric Joyner 		if (hw->bus.lan_id)
22498eb6488eSEric Joyner 			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
22508eb6488eSEric Joyner 		else
22518eb6488eSEric Joyner 			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
22528eb6488eSEric Joyner 		break;
22538eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_SFP:
22548eb6488eSEric Joyner 		/* set up for CS4227 usage */
22558eb6488eSEric Joyner 		hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
22568eb6488eSEric Joyner 		break;
22577d48aa4cSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_1G_T:
22587d48aa4cSEric Joyner 		phy->ops.read_reg_mdi = NULL;
22597d48aa4cSEric Joyner 		phy->ops.write_reg_mdi = NULL;
22608eb6488eSEric Joyner 	default:
22618eb6488eSEric Joyner 		break;
22628eb6488eSEric Joyner 	}
22638eb6488eSEric Joyner 
22646f37f232SEric Joyner 	/* Identify the PHY or SFP module */
22656f37f232SEric Joyner 	ret_val = phy->ops.identify(hw);
22668eb6488eSEric Joyner 	if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED ||
22678eb6488eSEric Joyner 	    ret_val == IXGBE_ERR_PHY_ADDR_INVALID)
22686f37f232SEric Joyner 		return ret_val;
22696f37f232SEric Joyner 
22706f37f232SEric Joyner 	/* Setup function pointers based on detected hardware */
22716f37f232SEric Joyner 	ixgbe_init_mac_link_ops_X550em(hw);
22726f37f232SEric Joyner 	if (phy->sfp_type != ixgbe_sfp_type_unknown)
22736f37f232SEric Joyner 		phy->ops.reset = NULL;
22746f37f232SEric Joyner 
22756f37f232SEric Joyner 	/* Set functions pointers based on phy type */
22766f37f232SEric Joyner 	switch (hw->phy.type) {
22776f37f232SEric Joyner 	case ixgbe_phy_x550em_kx4:
2278a9ca1c79SSean Bruno 		phy->ops.setup_link = NULL;
22796f37f232SEric Joyner 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
22806f37f232SEric Joyner 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
22816f37f232SEric Joyner 		break;
22826f37f232SEric Joyner 	case ixgbe_phy_x550em_kr:
22836f37f232SEric Joyner 		phy->ops.setup_link = ixgbe_setup_kr_x550em;
22846f37f232SEric Joyner 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
22856f37f232SEric Joyner 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
22866f37f232SEric Joyner 		break;
22878eb6488eSEric Joyner 	case ixgbe_phy_ext_1g_t:
22888eb6488eSEric Joyner 		/* link is managed by FW */
22898eb6488eSEric Joyner 		phy->ops.setup_link = NULL;
22908eb6488eSEric Joyner 		phy->ops.reset = NULL;
22918eb6488eSEric Joyner 		break;
22928eb6488eSEric Joyner 	case ixgbe_phy_x550em_xfi:
22938eb6488eSEric Joyner 		/* link is managed by HW */
22948eb6488eSEric Joyner 		phy->ops.setup_link = NULL;
22958eb6488eSEric Joyner 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
22968eb6488eSEric Joyner 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
22978eb6488eSEric Joyner 		break;
22986f37f232SEric Joyner 	case ixgbe_phy_x550em_ext_t:
22996f37f232SEric Joyner 		/* If internal link mode is XFI, then setup iXFI internal link,
23006f37f232SEric Joyner 		 * else setup KR now.
23016f37f232SEric Joyner 		 */
23026f37f232SEric Joyner 		phy->ops.setup_internal_link =
23036f37f232SEric Joyner 					      ixgbe_setup_internal_phy_t_x550em;
23046f37f232SEric Joyner 
23058eb6488eSEric Joyner 		/* setup SW LPLU only for first revision of X550EM_x */
23068eb6488eSEric Joyner 		if ((hw->mac.type == ixgbe_mac_X550EM_x) &&
23078eb6488eSEric Joyner 		    !(IXGBE_FUSES0_REV_MASK &
23088eb6488eSEric Joyner 		      IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))))
23096f37f232SEric Joyner 			phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
2310a9ca1c79SSean Bruno 
23116f37f232SEric Joyner 		phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
23126f37f232SEric Joyner 		phy->ops.reset = ixgbe_reset_phy_t_X550em;
23136f37f232SEric Joyner 		break;
23148eb6488eSEric Joyner 	case ixgbe_phy_sgmii:
23158eb6488eSEric Joyner 		phy->ops.setup_link = NULL;
23168eb6488eSEric Joyner 		break;
23178eb6488eSEric Joyner 	case ixgbe_phy_fw:
23188eb6488eSEric Joyner 		phy->ops.setup_link = ixgbe_setup_fw_link;
23198eb6488eSEric Joyner 		phy->ops.reset = ixgbe_reset_phy_fw;
23208eb6488eSEric Joyner 		break;
23216f37f232SEric Joyner 	default:
23226f37f232SEric Joyner 		break;
23236f37f232SEric Joyner 	}
23246f37f232SEric Joyner 	return ret_val;
23256f37f232SEric Joyner }
23266f37f232SEric Joyner 
23276f37f232SEric Joyner /**
23288eb6488eSEric Joyner  * ixgbe_set_mdio_speed - Set MDIO clock speed
23298eb6488eSEric Joyner  * @hw: pointer to hardware structure
23308eb6488eSEric Joyner  */
ixgbe_set_mdio_speed(struct ixgbe_hw * hw)23318eb6488eSEric Joyner static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw)
23328eb6488eSEric Joyner {
23338eb6488eSEric Joyner 	u32 hlreg0;
23348eb6488eSEric Joyner 
23358eb6488eSEric Joyner 	switch (hw->device_id) {
23368eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_10G_T:
23378eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_SGMII:
23388eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_SGMII_L:
23398eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_10G_T:
23408eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_SFP:
23418eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_QSFP:
23428eb6488eSEric Joyner 		/* Config MDIO clock speed before the first MDIO PHY access */
23438eb6488eSEric Joyner 		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
23448eb6488eSEric Joyner 		hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
23458eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
23468eb6488eSEric Joyner 		break;
23478eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T:
23488eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
23498eb6488eSEric Joyner 		/* Select fast MDIO clock speed for these devices */
23508eb6488eSEric Joyner 		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
23518eb6488eSEric Joyner 		hlreg0 |= IXGBE_HLREG0_MDCSPD;
23528eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
23538eb6488eSEric Joyner 		break;
23548eb6488eSEric Joyner 	default:
23558eb6488eSEric Joyner 		break;
23568eb6488eSEric Joyner 	}
23578eb6488eSEric Joyner }
23588eb6488eSEric Joyner 
23598eb6488eSEric Joyner /**
23606f37f232SEric Joyner  * ixgbe_reset_hw_X550em - Perform hardware reset
23616f37f232SEric Joyner  * @hw: pointer to hardware structure
23626f37f232SEric Joyner  *
23636f37f232SEric Joyner  * Resets the hardware by resetting the transmit and receive units, masks
23646f37f232SEric Joyner  * and clears all interrupts, perform a PHY reset, and perform a link (MAC)
23656f37f232SEric Joyner  * reset.
23666f37f232SEric Joyner  */
ixgbe_reset_hw_X550em(struct ixgbe_hw * hw)23676f37f232SEric Joyner s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
23686f37f232SEric Joyner {
23696f37f232SEric Joyner 	ixgbe_link_speed link_speed;
23706f37f232SEric Joyner 	s32 status;
23716f37f232SEric Joyner 	u32 ctrl = 0;
23726f37f232SEric Joyner 	u32 i;
237379b36ec9SKevin Bowling 	bool link_up = false;
23748eb6488eSEric Joyner 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
23756f37f232SEric Joyner 
23766f37f232SEric Joyner 	DEBUGFUNC("ixgbe_reset_hw_X550em");
23776f37f232SEric Joyner 
23786f37f232SEric Joyner 	/* Call adapter stop to disable Tx/Rx and clear interrupts */
23796f37f232SEric Joyner 	status = hw->mac.ops.stop_adapter(hw);
23808eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS) {
23818eb6488eSEric Joyner 		DEBUGOUT1("Failed to stop adapter, STATUS = %d\n", status);
23826f37f232SEric Joyner 		return status;
23838eb6488eSEric Joyner 	}
23846f37f232SEric Joyner 	/* flush pending Tx transactions */
23856f37f232SEric Joyner 	ixgbe_clear_tx_pending(hw);
23866f37f232SEric Joyner 
23878eb6488eSEric Joyner 	ixgbe_set_mdio_speed(hw);
23886f37f232SEric Joyner 
2389a9ca1c79SSean Bruno 	/* PHY ops must be identified and initialized prior to reset */
23906f37f232SEric Joyner 	status = hw->phy.ops.init(hw);
23916f37f232SEric Joyner 
23928eb6488eSEric Joyner 	if (status)
23938eb6488eSEric Joyner 		DEBUGOUT1("Failed to initialize PHY ops, STATUS = %d\n",
23948eb6488eSEric Joyner 			  status);
23958eb6488eSEric Joyner 
23967d48aa4cSEric Joyner 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED ||
23977d48aa4cSEric Joyner 	    status == IXGBE_ERR_PHY_ADDR_INVALID) {
23988eb6488eSEric Joyner 		DEBUGOUT("Returning from reset HW due to PHY init failure\n");
23996f37f232SEric Joyner 		return status;
24008eb6488eSEric Joyner 	}
24016f37f232SEric Joyner 
24026f37f232SEric Joyner 	/* start the external PHY */
24036f37f232SEric Joyner 	if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
24046f37f232SEric Joyner 		status = ixgbe_init_ext_t_x550em(hw);
24058eb6488eSEric Joyner 		if (status) {
24068eb6488eSEric Joyner 			DEBUGOUT1("Failed to start the external PHY, STATUS = %d\n",
24078eb6488eSEric Joyner 				  status);
24086f37f232SEric Joyner 			return status;
24096f37f232SEric Joyner 		}
24108eb6488eSEric Joyner 	}
24116f37f232SEric Joyner 
24126f37f232SEric Joyner 	/* Setup SFP module if there is one present. */
24136f37f232SEric Joyner 	if (hw->phy.sfp_setup_needed) {
24146f37f232SEric Joyner 		status = hw->mac.ops.setup_sfp(hw);
241579b36ec9SKevin Bowling 		hw->phy.sfp_setup_needed = false;
24166f37f232SEric Joyner 	}
24176f37f232SEric Joyner 
24186f37f232SEric Joyner 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
24196f37f232SEric Joyner 		return status;
24206f37f232SEric Joyner 
24216f37f232SEric Joyner 	/* Reset PHY */
24228eb6488eSEric Joyner 	if (!hw->phy.reset_disable && hw->phy.ops.reset) {
24238eb6488eSEric Joyner 		if (hw->phy.ops.reset(hw) == IXGBE_ERR_OVERTEMP)
24248eb6488eSEric Joyner 			return IXGBE_ERR_OVERTEMP;
24258eb6488eSEric Joyner 	}
24266f37f232SEric Joyner 
24276f37f232SEric Joyner mac_reset_top:
24286f37f232SEric Joyner 	/* Issue global reset to the MAC.  Needs to be SW reset if link is up.
24296f37f232SEric Joyner 	 * If link reset is used when link is up, it might reset the PHY when
24306f37f232SEric Joyner 	 * mng is using it.  If link is down or the flag to force full link
24316f37f232SEric Joyner 	 * reset is set, then perform link reset.
24326f37f232SEric Joyner 	 */
24336f37f232SEric Joyner 	ctrl = IXGBE_CTRL_LNK_RST;
24346f37f232SEric Joyner 	if (!hw->force_full_reset) {
243579b36ec9SKevin Bowling 		hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
24366f37f232SEric Joyner 		if (link_up)
24376f37f232SEric Joyner 			ctrl = IXGBE_CTRL_RST;
24386f37f232SEric Joyner 	}
24396f37f232SEric Joyner 
24408eb6488eSEric Joyner 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
24418eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS) {
24428eb6488eSEric Joyner 		ERROR_REPORT2(IXGBE_ERROR_CAUTION,
24438eb6488eSEric Joyner 			"semaphore failed with %d", status);
24448eb6488eSEric Joyner 		return IXGBE_ERR_SWFW_SYNC;
24458eb6488eSEric Joyner 	}
24466f37f232SEric Joyner 	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
24476f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
24486f37f232SEric Joyner 	IXGBE_WRITE_FLUSH(hw);
24498eb6488eSEric Joyner 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
24506f37f232SEric Joyner 
24516f37f232SEric Joyner 	/* Poll for reset bit to self-clear meaning reset is complete */
24526f37f232SEric Joyner 	for (i = 0; i < 10; i++) {
24536f37f232SEric Joyner 		usec_delay(1);
24546f37f232SEric Joyner 		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
24556f37f232SEric Joyner 		if (!(ctrl & IXGBE_CTRL_RST_MASK))
24566f37f232SEric Joyner 			break;
24576f37f232SEric Joyner 	}
24586f37f232SEric Joyner 
24596f37f232SEric Joyner 	if (ctrl & IXGBE_CTRL_RST_MASK) {
24606f37f232SEric Joyner 		status = IXGBE_ERR_RESET_FAILED;
24616f37f232SEric Joyner 		DEBUGOUT("Reset polling failed to complete.\n");
24626f37f232SEric Joyner 	}
24636f37f232SEric Joyner 
24646f37f232SEric Joyner 	msec_delay(50);
24656f37f232SEric Joyner 
24666f37f232SEric Joyner 	/* Double resets are required for recovery from certain error
24676f37f232SEric Joyner 	 * conditions.  Between resets, it is necessary to stall to
24686f37f232SEric Joyner 	 * allow time for any pending HW events to complete.
24696f37f232SEric Joyner 	 */
24706f37f232SEric Joyner 	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
24716f37f232SEric Joyner 		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
24726f37f232SEric Joyner 		goto mac_reset_top;
24736f37f232SEric Joyner 	}
24746f37f232SEric Joyner 
24756f37f232SEric Joyner 	/* Store the permanent mac address */
24766f37f232SEric Joyner 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
24776f37f232SEric Joyner 
24786f37f232SEric Joyner 	/* Store MAC address from RAR0, clear receive address registers, and
24796f37f232SEric Joyner 	 * clear the multicast table.  Also reset num_rar_entries to 128,
24806f37f232SEric Joyner 	 * since we modify this value when programming the SAN MAC address.
24816f37f232SEric Joyner 	 */
24826f37f232SEric Joyner 	hw->mac.num_rar_entries = 128;
24836f37f232SEric Joyner 	hw->mac.ops.init_rx_addrs(hw);
24846f37f232SEric Joyner 
24858eb6488eSEric Joyner 	ixgbe_set_mdio_speed(hw);
24868eb6488eSEric Joyner 
24876f37f232SEric Joyner 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
24886f37f232SEric Joyner 		ixgbe_setup_mux_ctl(hw);
24896f37f232SEric Joyner 
24908eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS)
24918eb6488eSEric Joyner 		DEBUGOUT1("Reset HW failed, STATUS = %d\n", status);
24928eb6488eSEric Joyner 
24936f37f232SEric Joyner 	return status;
24946f37f232SEric Joyner }
24956f37f232SEric Joyner 
24966f37f232SEric Joyner /**
24976f37f232SEric Joyner  * ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY.
24986f37f232SEric Joyner  * @hw: pointer to hardware structure
24996f37f232SEric Joyner  */
ixgbe_init_ext_t_x550em(struct ixgbe_hw * hw)25006f37f232SEric Joyner s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
25016f37f232SEric Joyner {
25026f37f232SEric Joyner 	u32 status;
25036f37f232SEric Joyner 	u16 reg;
25046f37f232SEric Joyner 
25056f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw,
25066f37f232SEric Joyner 				      IXGBE_MDIO_TX_VENDOR_ALARMS_3,
25076f37f232SEric Joyner 				      IXGBE_MDIO_PMA_PMD_DEV_TYPE,
25086f37f232SEric Joyner 				      &reg);
25096f37f232SEric Joyner 
25106f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
25116f37f232SEric Joyner 		return status;
25126f37f232SEric Joyner 
25136f37f232SEric Joyner 	/* If PHY FW reset completed bit is set then this is the first
25146f37f232SEric Joyner 	 * SW instance after a power on so the PHY FW must be un-stalled.
25156f37f232SEric Joyner 	 */
25166f37f232SEric Joyner 	if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
25176f37f232SEric Joyner 		status = hw->phy.ops.read_reg(hw,
25186f37f232SEric Joyner 					IXGBE_MDIO_GLOBAL_RES_PR_10,
25196f37f232SEric Joyner 					IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
25206f37f232SEric Joyner 					&reg);
25216f37f232SEric Joyner 
25226f37f232SEric Joyner 		if (status != IXGBE_SUCCESS)
25236f37f232SEric Joyner 			return status;
25246f37f232SEric Joyner 
25256f37f232SEric Joyner 		reg &= ~IXGBE_MDIO_POWER_UP_STALL;
25266f37f232SEric Joyner 
25276f37f232SEric Joyner 		status = hw->phy.ops.write_reg(hw,
25286f37f232SEric Joyner 					IXGBE_MDIO_GLOBAL_RES_PR_10,
25296f37f232SEric Joyner 					IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
25306f37f232SEric Joyner 					reg);
25316f37f232SEric Joyner 
25326f37f232SEric Joyner 		if (status != IXGBE_SUCCESS)
25336f37f232SEric Joyner 			return status;
25346f37f232SEric Joyner 	}
25356f37f232SEric Joyner 
25366f37f232SEric Joyner 	return status;
25376f37f232SEric Joyner }
25386f37f232SEric Joyner 
25396f37f232SEric Joyner /**
25406f37f232SEric Joyner  * ixgbe_setup_kr_x550em - Configure the KR PHY.
25416f37f232SEric Joyner  * @hw: pointer to hardware structure
25426f37f232SEric Joyner  **/
ixgbe_setup_kr_x550em(struct ixgbe_hw * hw)25436f37f232SEric Joyner s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
25446f37f232SEric Joyner {
25458eb6488eSEric Joyner 	/* leave link alone for 2.5G */
25468eb6488eSEric Joyner 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
25478eb6488eSEric Joyner 		return IXGBE_SUCCESS;
25488eb6488eSEric Joyner 
25498eb6488eSEric Joyner 	if (ixgbe_check_reset_blocked(hw))
25508eb6488eSEric Joyner 		return 0;
25518eb6488eSEric Joyner 
25526f37f232SEric Joyner 	return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised);
25536f37f232SEric Joyner }
25546f37f232SEric Joyner 
25556f37f232SEric Joyner /**
25566f37f232SEric Joyner  * ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP
25576f37f232SEric Joyner  * @hw: pointer to hardware structure
25587d48aa4cSEric Joyner  * @speed: new link speed
25597d48aa4cSEric Joyner  * @autoneg_wait_to_complete: unused
25606f37f232SEric Joyner  *
25616f37f232SEric Joyner  * Configure the external PHY and the integrated KR PHY for SFP support.
25626f37f232SEric Joyner  **/
ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)25636f37f232SEric Joyner s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
25646f37f232SEric Joyner 				    ixgbe_link_speed speed,
25656f37f232SEric Joyner 				    bool autoneg_wait_to_complete)
25666f37f232SEric Joyner {
25676f37f232SEric Joyner 	s32 ret_val;
25686f37f232SEric Joyner 	u16 reg_slice, reg_val;
256979b36ec9SKevin Bowling 	bool setup_linear = false;
25706f37f232SEric Joyner 	UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
25716f37f232SEric Joyner 
25726f37f232SEric Joyner 	/* Check if SFP module is supported and linear */
25736f37f232SEric Joyner 	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
25746f37f232SEric Joyner 
25756f37f232SEric Joyner 	/* If no SFP module present, then return success. Return success since
25766f37f232SEric Joyner 	 * there is no reason to configure CS4227 and SFP not present error is
25776f37f232SEric Joyner 	 * not excepted in the setup MAC link flow.
25786f37f232SEric Joyner 	 */
25796f37f232SEric Joyner 	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
25806f37f232SEric Joyner 		return IXGBE_SUCCESS;
25816f37f232SEric Joyner 
25826f37f232SEric Joyner 	if (ret_val != IXGBE_SUCCESS)
25836f37f232SEric Joyner 		return ret_val;
25846f37f232SEric Joyner 
2585a9ca1c79SSean Bruno 	/* Configure internal PHY for KR/KX. */
2586a9ca1c79SSean Bruno 	ixgbe_setup_kr_speed_x550em(hw, speed);
25876f37f232SEric Joyner 
2588a9ca1c79SSean Bruno 	/* Configure CS4227 LINE side to proper mode. */
2589a9ca1c79SSean Bruno 	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
2590a9ca1c79SSean Bruno 		    (hw->bus.lan_id << 12);
2591a9ca1c79SSean Bruno 	if (setup_linear)
2592a9ca1c79SSean Bruno 		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
2593a9ca1c79SSean Bruno 	else
2594a9ca1c79SSean Bruno 		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
25958eb6488eSEric Joyner 	ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice,
2596a9ca1c79SSean Bruno 					  reg_val);
25978eb6488eSEric Joyner 	return ret_val;
25988eb6488eSEric Joyner }
25998eb6488eSEric Joyner 
26008eb6488eSEric Joyner /**
26018eb6488eSEric Joyner  * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode
26028eb6488eSEric Joyner  * @hw: pointer to hardware structure
26038eb6488eSEric Joyner  * @speed: the link speed to force
26048eb6488eSEric Joyner  *
26058eb6488eSEric Joyner  * Configures the integrated PHY for native SFI mode. Used to connect the
26068eb6488eSEric Joyner  * internal PHY directly to an SFP cage, without autonegotiation.
26078eb6488eSEric Joyner  **/
ixgbe_setup_sfi_x550a(struct ixgbe_hw * hw,ixgbe_link_speed * speed)26088eb6488eSEric Joyner static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
26098eb6488eSEric Joyner {
26108eb6488eSEric Joyner 	struct ixgbe_mac_info *mac = &hw->mac;
26118eb6488eSEric Joyner 	s32 status;
26128eb6488eSEric Joyner 	u32 reg_val;
26138eb6488eSEric Joyner 
26148eb6488eSEric Joyner 	/* Disable all AN and force speed to 10G Serial. */
26158eb6488eSEric Joyner 	status = mac->ops.read_iosf_sb_reg(hw,
26168eb6488eSEric Joyner 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
26178eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
26188eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS)
26198eb6488eSEric Joyner 		return status;
26208eb6488eSEric Joyner 
26218eb6488eSEric Joyner 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
26228eb6488eSEric Joyner 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
26238eb6488eSEric Joyner 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
26248eb6488eSEric Joyner 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
26258eb6488eSEric Joyner 
26268eb6488eSEric Joyner 	/* Select forced link speed for internal PHY. */
26278eb6488eSEric Joyner 	switch (*speed) {
26288eb6488eSEric Joyner 	case IXGBE_LINK_SPEED_10GB_FULL:
26298eb6488eSEric Joyner 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G;
26308eb6488eSEric Joyner 		break;
26318eb6488eSEric Joyner 	case IXGBE_LINK_SPEED_1GB_FULL:
26328eb6488eSEric Joyner 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
26338eb6488eSEric Joyner 		break;
26348eb6488eSEric Joyner 	default:
26358eb6488eSEric Joyner 		/* Other link speeds are not supported by internal PHY. */
26368eb6488eSEric Joyner 		return IXGBE_ERR_LINK_SETUP;
26378eb6488eSEric Joyner 	}
26388eb6488eSEric Joyner 
26398eb6488eSEric Joyner 	status = mac->ops.write_iosf_sb_reg(hw,
26408eb6488eSEric Joyner 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
26418eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
26428eb6488eSEric Joyner 
26438eb6488eSEric Joyner 	/* Toggle port SW reset by AN reset. */
26448eb6488eSEric Joyner 	status = ixgbe_restart_an_internal_phy_x550em(hw);
26458eb6488eSEric Joyner 
26468eb6488eSEric Joyner 	return status;
26478eb6488eSEric Joyner }
26488eb6488eSEric Joyner 
26498eb6488eSEric Joyner /**
26508eb6488eSEric Joyner  * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP
26518eb6488eSEric Joyner  * @hw: pointer to hardware structure
26527d48aa4cSEric Joyner  * @speed: new link speed
26537d48aa4cSEric Joyner  * @autoneg_wait_to_complete: unused
26548eb6488eSEric Joyner  *
26553f66b96dSKevin Bowling  * Configure the integrated PHY for SFP support.
26568eb6488eSEric Joyner  **/
ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)26578eb6488eSEric Joyner s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
26588eb6488eSEric Joyner 				    ixgbe_link_speed speed,
26598eb6488eSEric Joyner 				    bool autoneg_wait_to_complete)
26608eb6488eSEric Joyner {
26618eb6488eSEric Joyner 	s32 ret_val;
26628eb6488eSEric Joyner 	u16 reg_phy_ext;
266379b36ec9SKevin Bowling 	bool setup_linear = false;
26648eb6488eSEric Joyner 	u32 reg_slice, reg_phy_int, slice_offset;
26658eb6488eSEric Joyner 
26668eb6488eSEric Joyner 	UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
26678eb6488eSEric Joyner 
26688eb6488eSEric Joyner 	/* Check if SFP module is supported and linear */
26698eb6488eSEric Joyner 	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
26708eb6488eSEric Joyner 
26718eb6488eSEric Joyner 	/* If no SFP module present, then return success. Return success since
26728eb6488eSEric Joyner 	 * SFP not present error is not excepted in the setup MAC link flow.
26738eb6488eSEric Joyner 	 */
26748eb6488eSEric Joyner 	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
26758eb6488eSEric Joyner 		return IXGBE_SUCCESS;
26768eb6488eSEric Joyner 
26778eb6488eSEric Joyner 	if (ret_val != IXGBE_SUCCESS)
26788eb6488eSEric Joyner 		return ret_val;
26798eb6488eSEric Joyner 
26808eb6488eSEric Joyner 	if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) {
26818eb6488eSEric Joyner 		/* Configure internal PHY for native SFI based on module type */
26828eb6488eSEric Joyner 		ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
26838eb6488eSEric Joyner 				   IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
26848eb6488eSEric Joyner 				   IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
26858eb6488eSEric Joyner 
26868eb6488eSEric Joyner 		if (ret_val != IXGBE_SUCCESS)
26878eb6488eSEric Joyner 			return ret_val;
26888eb6488eSEric Joyner 
26898eb6488eSEric Joyner 		reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA;
26908eb6488eSEric Joyner 		if (!setup_linear)
26918eb6488eSEric Joyner 			reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR;
26928eb6488eSEric Joyner 
26938eb6488eSEric Joyner 		ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
26948eb6488eSEric Joyner 				   IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
26958eb6488eSEric Joyner 				   IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
26968eb6488eSEric Joyner 
26978eb6488eSEric Joyner 		if (ret_val != IXGBE_SUCCESS)
26988eb6488eSEric Joyner 			return ret_val;
26998eb6488eSEric Joyner 
27008eb6488eSEric Joyner 		/* Setup SFI internal link. */
27018eb6488eSEric Joyner 		ret_val = ixgbe_setup_sfi_x550a(hw, &speed);
27028eb6488eSEric Joyner 	} else {
27038eb6488eSEric Joyner 		/* Configure internal PHY for KR/KX. */
27048eb6488eSEric Joyner 		ixgbe_setup_kr_speed_x550em(hw, speed);
27058eb6488eSEric Joyner 
27068eb6488eSEric Joyner 		if (hw->phy.addr == 0x0 || hw->phy.addr == 0xFFFF) {
27078eb6488eSEric Joyner 			/* Find Address */
27088eb6488eSEric Joyner 			DEBUGOUT("Invalid NW_MNG_IF_SEL.MDIO_PHY_ADD value\n");
27098eb6488eSEric Joyner 			return IXGBE_ERR_PHY_ADDR_INVALID;
27108eb6488eSEric Joyner 		}
27118eb6488eSEric Joyner 
27128eb6488eSEric Joyner 		/* Get external PHY SKU id */
27138eb6488eSEric Joyner 		ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU,
27148eb6488eSEric Joyner 					IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
27158eb6488eSEric Joyner 
27168eb6488eSEric Joyner 		if (ret_val != IXGBE_SUCCESS)
27178eb6488eSEric Joyner 			return ret_val;
27188eb6488eSEric Joyner 
27198eb6488eSEric Joyner 		/* When configuring quad port CS4223, the MAC instance is part
27208eb6488eSEric Joyner 		 * of the slice offset.
27218eb6488eSEric Joyner 		 */
27228eb6488eSEric Joyner 		if (reg_phy_ext == IXGBE_CS4223_SKU_ID)
27238eb6488eSEric Joyner 			slice_offset = (hw->bus.lan_id +
27248eb6488eSEric Joyner 					(hw->bus.instance_id << 1)) << 12;
27258eb6488eSEric Joyner 		else
27268eb6488eSEric Joyner 			slice_offset = hw->bus.lan_id << 12;
27278eb6488eSEric Joyner 
27288eb6488eSEric Joyner 		/* Configure CS4227/CS4223 LINE side to proper mode. */
27298eb6488eSEric Joyner 		reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
27308eb6488eSEric Joyner 
27318eb6488eSEric Joyner 		ret_val = hw->phy.ops.read_reg(hw, reg_slice,
27328eb6488eSEric Joyner 					IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
27338eb6488eSEric Joyner 
27348eb6488eSEric Joyner 		if (ret_val != IXGBE_SUCCESS)
27358eb6488eSEric Joyner 			return ret_val;
27368eb6488eSEric Joyner 
27378eb6488eSEric Joyner 		reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) |
27388eb6488eSEric Joyner 				 (IXGBE_CS4227_EDC_MODE_SR << 1));
27398eb6488eSEric Joyner 
27408eb6488eSEric Joyner 		if (setup_linear)
2741c85b6f29SXiaoyun Li 			reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
27428eb6488eSEric Joyner 		else
2743c85b6f29SXiaoyun Li 			reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
27448eb6488eSEric Joyner 		ret_val = hw->phy.ops.write_reg(hw, reg_slice,
27458eb6488eSEric Joyner 					 IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
27468eb6488eSEric Joyner 
27478eb6488eSEric Joyner 		/* Flush previous write with a read */
27488eb6488eSEric Joyner 		ret_val = hw->phy.ops.read_reg(hw, reg_slice,
27498eb6488eSEric Joyner 					IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
2750a9ca1c79SSean Bruno 	}
27516f37f232SEric Joyner 	return ret_val;
27526f37f232SEric Joyner }
27536f37f232SEric Joyner 
27546f37f232SEric Joyner /**
27558eb6488eSEric Joyner  * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration
27568eb6488eSEric Joyner  * @hw: pointer to hardware structure
27578eb6488eSEric Joyner  *
27588eb6488eSEric Joyner  * iXfI configuration needed for ixgbe_mac_X550EM_x devices.
27598eb6488eSEric Joyner  **/
ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw * hw)27608eb6488eSEric Joyner static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)
27618eb6488eSEric Joyner {
27628eb6488eSEric Joyner 	struct ixgbe_mac_info *mac = &hw->mac;
27638eb6488eSEric Joyner 	s32 status;
27648eb6488eSEric Joyner 	u32 reg_val;
27658eb6488eSEric Joyner 
27668eb6488eSEric Joyner 	/* Disable training protocol FSM. */
27678eb6488eSEric Joyner 	status = mac->ops.read_iosf_sb_reg(hw,
27688eb6488eSEric Joyner 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
27698eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
27708eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS)
27718eb6488eSEric Joyner 		return status;
27728eb6488eSEric Joyner 	reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL;
27738eb6488eSEric Joyner 	status = mac->ops.write_iosf_sb_reg(hw,
27748eb6488eSEric Joyner 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
27758eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
27768eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS)
27778eb6488eSEric Joyner 		return status;
27788eb6488eSEric Joyner 
27798eb6488eSEric Joyner 	/* Disable Flex from training TXFFE. */
27808eb6488eSEric Joyner 	status = mac->ops.read_iosf_sb_reg(hw,
27818eb6488eSEric Joyner 				IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
27828eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
27838eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS)
27848eb6488eSEric Joyner 		return status;
27858eb6488eSEric Joyner 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
27868eb6488eSEric Joyner 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
27878eb6488eSEric Joyner 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
27888eb6488eSEric Joyner 	status = mac->ops.write_iosf_sb_reg(hw,
27898eb6488eSEric Joyner 				IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
27908eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
27918eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS)
27928eb6488eSEric Joyner 		return status;
27938eb6488eSEric Joyner 	status = mac->ops.read_iosf_sb_reg(hw,
27948eb6488eSEric Joyner 				IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
27958eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
27968eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS)
27978eb6488eSEric Joyner 		return status;
27988eb6488eSEric Joyner 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
27998eb6488eSEric Joyner 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
28008eb6488eSEric Joyner 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
28018eb6488eSEric Joyner 	status = mac->ops.write_iosf_sb_reg(hw,
28028eb6488eSEric Joyner 				IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
28038eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
28048eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS)
28058eb6488eSEric Joyner 		return status;
28068eb6488eSEric Joyner 
28078eb6488eSEric Joyner 	/* Enable override for coefficients. */
28088eb6488eSEric Joyner 	status = mac->ops.read_iosf_sb_reg(hw,
28098eb6488eSEric Joyner 				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
28108eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
28118eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS)
28128eb6488eSEric Joyner 		return status;
28138eb6488eSEric Joyner 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN;
28148eb6488eSEric Joyner 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN;
28158eb6488eSEric Joyner 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN;
28168eb6488eSEric Joyner 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN;
28178eb6488eSEric Joyner 	status = mac->ops.write_iosf_sb_reg(hw,
28188eb6488eSEric Joyner 				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
28198eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
28208eb6488eSEric Joyner 	return status;
28218eb6488eSEric Joyner }
28228eb6488eSEric Joyner 
28238eb6488eSEric Joyner /**
28246f37f232SEric Joyner  * ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
28256f37f232SEric Joyner  * @hw: pointer to hardware structure
28266f37f232SEric Joyner  * @speed: the link speed to force
28276f37f232SEric Joyner  *
28286f37f232SEric Joyner  * Configures the integrated KR PHY to use iXFI mode. Used to connect an
28296f37f232SEric Joyner  * internal and external PHY at a specific speed, without autonegotiation.
28306f37f232SEric Joyner  **/
ixgbe_setup_ixfi_x550em(struct ixgbe_hw * hw,ixgbe_link_speed * speed)28316f37f232SEric Joyner static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
28326f37f232SEric Joyner {
28338eb6488eSEric Joyner 	struct ixgbe_mac_info *mac = &hw->mac;
28346f37f232SEric Joyner 	s32 status;
28356f37f232SEric Joyner 	u32 reg_val;
28366f37f232SEric Joyner 
28378eb6488eSEric Joyner 	/* iXFI is only supported with X552 */
28388eb6488eSEric Joyner 	if (mac->type != ixgbe_mac_X550EM_x)
28398eb6488eSEric Joyner 		return IXGBE_ERR_LINK_SETUP;
28408eb6488eSEric Joyner 
28416f37f232SEric Joyner 	/* Disable AN and force speed to 10G Serial. */
28428eb6488eSEric Joyner 	status = mac->ops.read_iosf_sb_reg(hw,
28436f37f232SEric Joyner 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
28446f37f232SEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
28456f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
28466f37f232SEric Joyner 		return status;
28476f37f232SEric Joyner 
28486f37f232SEric Joyner 	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
28496f37f232SEric Joyner 	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
28506f37f232SEric Joyner 
28516f37f232SEric Joyner 	/* Select forced link speed for internal PHY. */
28526f37f232SEric Joyner 	switch (*speed) {
28536f37f232SEric Joyner 	case IXGBE_LINK_SPEED_10GB_FULL:
28546f37f232SEric Joyner 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
28556f37f232SEric Joyner 		break;
28566f37f232SEric Joyner 	case IXGBE_LINK_SPEED_1GB_FULL:
28576f37f232SEric Joyner 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
28586f37f232SEric Joyner 		break;
28596f37f232SEric Joyner 	default:
28606f37f232SEric Joyner 		/* Other link speeds are not supported by internal KR PHY. */
28616f37f232SEric Joyner 		return IXGBE_ERR_LINK_SETUP;
28626f37f232SEric Joyner 	}
28636f37f232SEric Joyner 
28648eb6488eSEric Joyner 	status = mac->ops.write_iosf_sb_reg(hw,
28656f37f232SEric Joyner 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
28666f37f232SEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
28676f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
28686f37f232SEric Joyner 		return status;
28696f37f232SEric Joyner 
28708eb6488eSEric Joyner 	/* Additional configuration needed for x550em_x */
28718eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_X550EM_x) {
28728eb6488eSEric Joyner 		status = ixgbe_setup_ixfi_x550em_x(hw);
28736f37f232SEric Joyner 		if (status != IXGBE_SUCCESS)
28746f37f232SEric Joyner 			return status;
28758eb6488eSEric Joyner 	}
28766f37f232SEric Joyner 
28776f37f232SEric Joyner 	/* Toggle port SW reset by AN reset. */
28788eb6488eSEric Joyner 	status = ixgbe_restart_an_internal_phy_x550em(hw);
28796f37f232SEric Joyner 
28806f37f232SEric Joyner 	return status;
28816f37f232SEric Joyner }
28826f37f232SEric Joyner 
28836f37f232SEric Joyner /**
28846f37f232SEric Joyner  * ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status
28856f37f232SEric Joyner  * @hw: address of hardware structure
28866f37f232SEric Joyner  * @link_up: address of boolean to indicate link status
28876f37f232SEric Joyner  *
28886f37f232SEric Joyner  * Returns error code if unable to get link status.
28896f37f232SEric Joyner  */
ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw * hw,bool * link_up)28906f37f232SEric Joyner static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
28916f37f232SEric Joyner {
28926f37f232SEric Joyner 	u32 ret;
28936f37f232SEric Joyner 	u16 autoneg_status;
28946f37f232SEric Joyner 
289579b36ec9SKevin Bowling 	*link_up = false;
28966f37f232SEric Joyner 
28976f37f232SEric Joyner 	/* read this twice back to back to indicate current status */
28986f37f232SEric Joyner 	ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
28996f37f232SEric Joyner 				   IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
29006f37f232SEric Joyner 				   &autoneg_status);
29016f37f232SEric Joyner 	if (ret != IXGBE_SUCCESS)
29026f37f232SEric Joyner 		return ret;
29036f37f232SEric Joyner 
29046f37f232SEric Joyner 	ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
29056f37f232SEric Joyner 				   IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
29066f37f232SEric Joyner 				   &autoneg_status);
29076f37f232SEric Joyner 	if (ret != IXGBE_SUCCESS)
29086f37f232SEric Joyner 		return ret;
29096f37f232SEric Joyner 
29106f37f232SEric Joyner 	*link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS);
29116f37f232SEric Joyner 
29126f37f232SEric Joyner 	return IXGBE_SUCCESS;
29136f37f232SEric Joyner }
29146f37f232SEric Joyner 
29156f37f232SEric Joyner /**
29166f37f232SEric Joyner  * ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link
29176f37f232SEric Joyner  * @hw: point to hardware structure
29186f37f232SEric Joyner  *
29196f37f232SEric Joyner  * Configures the link between the integrated KR PHY and the external X557 PHY
29206f37f232SEric Joyner  * The driver will call this function when it gets a link status change
29216f37f232SEric Joyner  * interrupt from the X557 PHY. This function configures the link speed
29226f37f232SEric Joyner  * between the PHYs to match the link speed of the BASE-T link.
29236f37f232SEric Joyner  *
29246f37f232SEric Joyner  * A return of a non-zero value indicates an error, and the base driver should
29256f37f232SEric Joyner  * not report link up.
29266f37f232SEric Joyner  */
ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw * hw)29276f37f232SEric Joyner s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
29286f37f232SEric Joyner {
29296f37f232SEric Joyner 	ixgbe_link_speed force_speed;
29306f37f232SEric Joyner 	bool link_up;
29316f37f232SEric Joyner 	u32 status;
29326f37f232SEric Joyner 	u16 speed;
29336f37f232SEric Joyner 
29346f37f232SEric Joyner 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
29356f37f232SEric Joyner 		return IXGBE_ERR_CONFIG;
29366f37f232SEric Joyner 
29378eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_X550EM_x &&
29388eb6488eSEric Joyner 	    !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
29398eb6488eSEric Joyner 		/* If link is down, there is no setup necessary so return  */
29406f37f232SEric Joyner 		status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
29416f37f232SEric Joyner 		if (status != IXGBE_SUCCESS)
29426f37f232SEric Joyner 			return status;
29436f37f232SEric Joyner 
29446f37f232SEric Joyner 		if (!link_up)
29456f37f232SEric Joyner 			return IXGBE_SUCCESS;
29466f37f232SEric Joyner 
29478eb6488eSEric Joyner 		status = hw->phy.ops.read_reg(hw,
29488eb6488eSEric Joyner 					      IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
29496f37f232SEric Joyner 					      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
29506f37f232SEric Joyner 					      &speed);
29516f37f232SEric Joyner 		if (status != IXGBE_SUCCESS)
29526f37f232SEric Joyner 			return status;
29536f37f232SEric Joyner 
29548eb6488eSEric Joyner 		/* If link is still down - no setup is required so return */
29556f37f232SEric Joyner 		status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
29566f37f232SEric Joyner 		if (status != IXGBE_SUCCESS)
29576f37f232SEric Joyner 			return status;
29586f37f232SEric Joyner 		if (!link_up)
29596f37f232SEric Joyner 			return IXGBE_SUCCESS;
29606f37f232SEric Joyner 
29616f37f232SEric Joyner 		/* clear everything but the speed and duplex bits */
29626f37f232SEric Joyner 		speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
29636f37f232SEric Joyner 
29646f37f232SEric Joyner 		switch (speed) {
29656f37f232SEric Joyner 		case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
29666f37f232SEric Joyner 			force_speed = IXGBE_LINK_SPEED_10GB_FULL;
29676f37f232SEric Joyner 			break;
29686f37f232SEric Joyner 		case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
29696f37f232SEric Joyner 			force_speed = IXGBE_LINK_SPEED_1GB_FULL;
29706f37f232SEric Joyner 			break;
29716f37f232SEric Joyner 		default:
29726f37f232SEric Joyner 			/* Internal PHY does not support anything else */
29736f37f232SEric Joyner 			return IXGBE_ERR_INVALID_LINK_SETTINGS;
29746f37f232SEric Joyner 		}
29756f37f232SEric Joyner 
29766f37f232SEric Joyner 		return ixgbe_setup_ixfi_x550em(hw, &force_speed);
29778eb6488eSEric Joyner 	} else {
29788eb6488eSEric Joyner 		speed = IXGBE_LINK_SPEED_10GB_FULL |
29798eb6488eSEric Joyner 			IXGBE_LINK_SPEED_1GB_FULL;
29808eb6488eSEric Joyner 		return ixgbe_setup_kr_speed_x550em(hw, speed);
29818eb6488eSEric Joyner 	}
29826f37f232SEric Joyner }
29836f37f232SEric Joyner 
29846f37f232SEric Joyner /**
29856f37f232SEric Joyner  * ixgbe_setup_phy_loopback_x550em - Configure the KR PHY for loopback.
29866f37f232SEric Joyner  * @hw: pointer to hardware structure
29876f37f232SEric Joyner  *
29886f37f232SEric Joyner  * Configures the integrated KR PHY to use internal loopback mode.
29896f37f232SEric Joyner  **/
ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw * hw)29906f37f232SEric Joyner s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw)
29916f37f232SEric Joyner {
29926f37f232SEric Joyner 	s32 status;
29936f37f232SEric Joyner 	u32 reg_val;
29946f37f232SEric Joyner 
29956f37f232SEric Joyner 	/* Disable AN and force speed to 10G Serial. */
29968eb6488eSEric Joyner 	status = hw->mac.ops.read_iosf_sb_reg(hw,
29976f37f232SEric Joyner 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
29986f37f232SEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
29996f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
30006f37f232SEric Joyner 		return status;
30016f37f232SEric Joyner 	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
30026f37f232SEric Joyner 	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
30036f37f232SEric Joyner 	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
30048eb6488eSEric Joyner 	status = hw->mac.ops.write_iosf_sb_reg(hw,
30056f37f232SEric Joyner 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
30066f37f232SEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
30076f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
30086f37f232SEric Joyner 		return status;
30096f37f232SEric Joyner 
30106f37f232SEric Joyner 	/* Set near-end loopback clocks. */
30118eb6488eSEric Joyner 	status = hw->mac.ops.read_iosf_sb_reg(hw,
30126f37f232SEric Joyner 				IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
30136f37f232SEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
30146f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
30156f37f232SEric Joyner 		return status;
30166f37f232SEric Joyner 	reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B;
30176f37f232SEric Joyner 	reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS;
30188eb6488eSEric Joyner 	status = hw->mac.ops.write_iosf_sb_reg(hw,
30196f37f232SEric Joyner 				IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
30206f37f232SEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
30216f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
30226f37f232SEric Joyner 		return status;
30236f37f232SEric Joyner 
30246f37f232SEric Joyner 	/* Set loopback enable. */
30258eb6488eSEric Joyner 	status = hw->mac.ops.read_iosf_sb_reg(hw,
30266f37f232SEric Joyner 				IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
30276f37f232SEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
30286f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
30296f37f232SEric Joyner 		return status;
30306f37f232SEric Joyner 	reg_val |= IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK;
30318eb6488eSEric Joyner 	status = hw->mac.ops.write_iosf_sb_reg(hw,
30326f37f232SEric Joyner 				IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
30336f37f232SEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
30346f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
30356f37f232SEric Joyner 		return status;
30366f37f232SEric Joyner 
30376f37f232SEric Joyner 	/* Training bypass. */
30388eb6488eSEric Joyner 	status = hw->mac.ops.read_iosf_sb_reg(hw,
30396f37f232SEric Joyner 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
30406f37f232SEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
30416f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
30426f37f232SEric Joyner 		return status;
30436f37f232SEric Joyner 	reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS;
30448eb6488eSEric Joyner 	status = hw->mac.ops.write_iosf_sb_reg(hw,
30456f37f232SEric Joyner 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
30466f37f232SEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
30476f37f232SEric Joyner 
30486f37f232SEric Joyner 	return status;
30496f37f232SEric Joyner }
30506f37f232SEric Joyner 
30516f37f232SEric Joyner /**
30526f37f232SEric Joyner  * ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command
30536f37f232SEric Joyner  * assuming that the semaphore is already obtained.
30546f37f232SEric Joyner  * @hw: pointer to hardware structure
30556f37f232SEric Joyner  * @offset: offset of  word in the EEPROM to read
30566f37f232SEric Joyner  * @data: word read from the EEPROM
30576f37f232SEric Joyner  *
30586f37f232SEric Joyner  * Reads a 16 bit word from the EEPROM using the hostif.
30596f37f232SEric Joyner  **/
ixgbe_read_ee_hostif_X550(struct ixgbe_hw * hw,u16 offset,u16 * data)30608eb6488eSEric Joyner s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data)
30616f37f232SEric Joyner {
30628eb6488eSEric Joyner 	const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
30636f37f232SEric Joyner 	struct ixgbe_hic_read_shadow_ram buffer;
30648eb6488eSEric Joyner 	s32 status;
30656f37f232SEric Joyner 
30668eb6488eSEric Joyner 	DEBUGFUNC("ixgbe_read_ee_hostif_X550");
30676f37f232SEric Joyner 	buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
30686f37f232SEric Joyner 	buffer.hdr.req.buf_lenh = 0;
30696f37f232SEric Joyner 	buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
30706f37f232SEric Joyner 	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
30716f37f232SEric Joyner 
30726f37f232SEric Joyner 	/* convert offset from words to bytes */
30736f37f232SEric Joyner 	buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
30746f37f232SEric Joyner 	/* one word */
30756f37f232SEric Joyner 	buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
30767d48aa4cSEric Joyner 	buffer.pad2 = 0;
3077b3ebe337SGuinan Sun 	buffer.data = 0;
30787d48aa4cSEric Joyner 	buffer.pad3 = 0;
30796f37f232SEric Joyner 
30808eb6488eSEric Joyner 	status = hw->mac.ops.acquire_swfw_sync(hw, mask);
30816f37f232SEric Joyner 	if (status)
30826f37f232SEric Joyner 		return status;
30836f37f232SEric Joyner 
30848eb6488eSEric Joyner 	status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
30858eb6488eSEric Joyner 				    IXGBE_HI_COMMAND_TIMEOUT);
30868eb6488eSEric Joyner 	if (!status) {
30876f37f232SEric Joyner 		*data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
30886f37f232SEric Joyner 						  FW_NVM_DATA_OFFSET);
30896f37f232SEric Joyner 	}
30906f37f232SEric Joyner 
30918eb6488eSEric Joyner 	hw->mac.ops.release_swfw_sync(hw, mask);
30926f37f232SEric Joyner 	return status;
30936f37f232SEric Joyner }
30946f37f232SEric Joyner 
30956f37f232SEric Joyner /**
30966f37f232SEric Joyner  * ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif
30976f37f232SEric Joyner  * @hw: pointer to hardware structure
30986f37f232SEric Joyner  * @offset: offset of  word in the EEPROM to read
30996f37f232SEric Joyner  * @words: number of words
31006f37f232SEric Joyner  * @data: word(s) read from the EEPROM
31016f37f232SEric Joyner  *
31026f37f232SEric Joyner  * Reads a 16 bit word(s) from the EEPROM using the hostif.
31036f37f232SEric Joyner  **/
ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)31046f37f232SEric Joyner s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
31056f37f232SEric Joyner 				     u16 offset, u16 words, u16 *data)
31066f37f232SEric Joyner {
31078eb6488eSEric Joyner 	const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
31086f37f232SEric Joyner 	struct ixgbe_hic_read_shadow_ram buffer;
31096f37f232SEric Joyner 	u32 current_word = 0;
31106f37f232SEric Joyner 	u16 words_to_read;
31116f37f232SEric Joyner 	s32 status;
31126f37f232SEric Joyner 	u32 i;
31136f37f232SEric Joyner 
31146f37f232SEric Joyner 	DEBUGFUNC("ixgbe_read_ee_hostif_buffer_X550");
31156f37f232SEric Joyner 
31166f37f232SEric Joyner 	/* Take semaphore for the entire operation. */
31178eb6488eSEric Joyner 	status = hw->mac.ops.acquire_swfw_sync(hw, mask);
31186f37f232SEric Joyner 	if (status) {
31196f37f232SEric Joyner 		DEBUGOUT("EEPROM read buffer - semaphore failed\n");
31206f37f232SEric Joyner 		return status;
31216f37f232SEric Joyner 	}
31228eb6488eSEric Joyner 
31236f37f232SEric Joyner 	while (words) {
31246f37f232SEric Joyner 		if (words > FW_MAX_READ_BUFFER_SIZE / 2)
31256f37f232SEric Joyner 			words_to_read = FW_MAX_READ_BUFFER_SIZE / 2;
31266f37f232SEric Joyner 		else
31276f37f232SEric Joyner 			words_to_read = words;
31286f37f232SEric Joyner 
31296f37f232SEric Joyner 		buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
31306f37f232SEric Joyner 		buffer.hdr.req.buf_lenh = 0;
31316f37f232SEric Joyner 		buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
31326f37f232SEric Joyner 		buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
31336f37f232SEric Joyner 
31346f37f232SEric Joyner 		/* convert offset from words to bytes */
31356f37f232SEric Joyner 		buffer.address = IXGBE_CPU_TO_BE32((offset + current_word) * 2);
31366f37f232SEric Joyner 		buffer.length = IXGBE_CPU_TO_BE16(words_to_read * 2);
31377d48aa4cSEric Joyner 		buffer.pad2 = 0;
3138b3ebe337SGuinan Sun 		buffer.data = 0;
31397d48aa4cSEric Joyner 		buffer.pad3 = 0;
31406f37f232SEric Joyner 
31418eb6488eSEric Joyner 		status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
31428eb6488eSEric Joyner 					    IXGBE_HI_COMMAND_TIMEOUT);
31436f37f232SEric Joyner 
31446f37f232SEric Joyner 		if (status) {
31456f37f232SEric Joyner 			DEBUGOUT("Host interface command failed\n");
31466f37f232SEric Joyner 			goto out;
31476f37f232SEric Joyner 		}
31486f37f232SEric Joyner 
31496f37f232SEric Joyner 		for (i = 0; i < words_to_read; i++) {
31506f37f232SEric Joyner 			u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) +
31516f37f232SEric Joyner 				  2 * i;
31526f37f232SEric Joyner 			u32 value = IXGBE_READ_REG(hw, reg);
31536f37f232SEric Joyner 
31546f37f232SEric Joyner 			data[current_word] = (u16)(value & 0xffff);
31556f37f232SEric Joyner 			current_word++;
31566f37f232SEric Joyner 			i++;
31576f37f232SEric Joyner 			if (i < words_to_read) {
31586f37f232SEric Joyner 				value >>= 16;
31596f37f232SEric Joyner 				data[current_word] = (u16)(value & 0xffff);
31606f37f232SEric Joyner 				current_word++;
31616f37f232SEric Joyner 			}
31626f37f232SEric Joyner 		}
31636f37f232SEric Joyner 		words -= words_to_read;
31646f37f232SEric Joyner 	}
31656f37f232SEric Joyner 
31666f37f232SEric Joyner out:
31678eb6488eSEric Joyner 	hw->mac.ops.release_swfw_sync(hw, mask);
31686f37f232SEric Joyner 	return status;
31696f37f232SEric Joyner }
31706f37f232SEric Joyner 
31716f37f232SEric Joyner /**
3172edef2769SRadoslaw Tyl  * ixgbe_write_ee_hostif_data_X550 - Write EEPROM word using hostif
31736f37f232SEric Joyner  * @hw: pointer to hardware structure
31746f37f232SEric Joyner  * @offset: offset of  word in the EEPROM to write
31756f37f232SEric Joyner  * @data: word write to the EEPROM
31766f37f232SEric Joyner  *
31776f37f232SEric Joyner  * Write a 16 bit word to the EEPROM using the hostif.
31786f37f232SEric Joyner  **/
ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw * hw,u16 offset,u16 data)31796f37f232SEric Joyner s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
31806f37f232SEric Joyner 				    u16 data)
31816f37f232SEric Joyner {
31826f37f232SEric Joyner 	s32 status;
31836f37f232SEric Joyner 	struct ixgbe_hic_write_shadow_ram buffer;
31846f37f232SEric Joyner 
31856f37f232SEric Joyner 	DEBUGFUNC("ixgbe_write_ee_hostif_data_X550");
31866f37f232SEric Joyner 
31876f37f232SEric Joyner 	buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
31886f37f232SEric Joyner 	buffer.hdr.req.buf_lenh = 0;
31896f37f232SEric Joyner 	buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
31906f37f232SEric Joyner 	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
31916f37f232SEric Joyner 
31926f37f232SEric Joyner 	 /* one word */
31936f37f232SEric Joyner 	buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
31946f37f232SEric Joyner 	buffer.data = data;
31956f37f232SEric Joyner 	buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
31966f37f232SEric Joyner 
31976f37f232SEric Joyner 	status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
31986f37f232SEric Joyner 					      sizeof(buffer),
319979b36ec9SKevin Bowling 					      IXGBE_HI_COMMAND_TIMEOUT, true);
3200c1a56b6fSGuinan Sun 	if (status != IXGBE_SUCCESS) {
3201c1a56b6fSGuinan Sun 		DEBUGOUT2("for offset %04x failed with status %d\n",
3202c1a56b6fSGuinan Sun 				  offset, status);
3203c1a56b6fSGuinan Sun 		return status;
3204c1a56b6fSGuinan Sun 	}
3205c1a56b6fSGuinan Sun 
3206c1a56b6fSGuinan Sun 	if (buffer.hdr.rsp.buf_lenh_status != FW_CEM_RESP_STATUS_SUCCESS) {
3207c1a56b6fSGuinan Sun 		DEBUGOUT2("for offset %04x host interface return status %02x\n",
3208c1a56b6fSGuinan Sun 				  offset, buffer.hdr.rsp.buf_lenh_status);
3209c1a56b6fSGuinan Sun 		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
3210c1a56b6fSGuinan Sun 	}
32116f37f232SEric Joyner 
32126f37f232SEric Joyner 	return status;
32136f37f232SEric Joyner }
32146f37f232SEric Joyner 
32156f37f232SEric Joyner /**
32166f37f232SEric Joyner  * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
32176f37f232SEric Joyner  * @hw: pointer to hardware structure
32186f37f232SEric Joyner  * @offset: offset of  word in the EEPROM to write
32196f37f232SEric Joyner  * @data: word write to the EEPROM
32206f37f232SEric Joyner  *
32216f37f232SEric Joyner  * Write a 16 bit word to the EEPROM using the hostif.
32226f37f232SEric Joyner  **/
ixgbe_write_ee_hostif_X550(struct ixgbe_hw * hw,u16 offset,u16 data)32236f37f232SEric Joyner s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset,
32246f37f232SEric Joyner 			       u16 data)
32256f37f232SEric Joyner {
32266f37f232SEric Joyner 	s32 status = IXGBE_SUCCESS;
32276f37f232SEric Joyner 
32286f37f232SEric Joyner 	DEBUGFUNC("ixgbe_write_ee_hostif_X550");
32296f37f232SEric Joyner 
32306f37f232SEric Joyner 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
32316f37f232SEric Joyner 	    IXGBE_SUCCESS) {
32326f37f232SEric Joyner 		status = ixgbe_write_ee_hostif_data_X550(hw, offset, data);
32336f37f232SEric Joyner 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
32346f37f232SEric Joyner 	} else {
32356f37f232SEric Joyner 		DEBUGOUT("write ee hostif failed to get semaphore");
32366f37f232SEric Joyner 		status = IXGBE_ERR_SWFW_SYNC;
32376f37f232SEric Joyner 	}
32386f37f232SEric Joyner 
32396f37f232SEric Joyner 	return status;
32406f37f232SEric Joyner }
32416f37f232SEric Joyner 
32426f37f232SEric Joyner /**
32436f37f232SEric Joyner  * ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif
32446f37f232SEric Joyner  * @hw: pointer to hardware structure
32456f37f232SEric Joyner  * @offset: offset of  word in the EEPROM to write
32466f37f232SEric Joyner  * @words: number of words
32476f37f232SEric Joyner  * @data: word(s) write to the EEPROM
32486f37f232SEric Joyner  *
32496f37f232SEric Joyner  * Write a 16 bit word(s) to the EEPROM using the hostif.
32506f37f232SEric Joyner  **/
ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)32516f37f232SEric Joyner s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
32526f37f232SEric Joyner 				      u16 offset, u16 words, u16 *data)
32536f37f232SEric Joyner {
32546f37f232SEric Joyner 	s32 status = IXGBE_SUCCESS;
32556f37f232SEric Joyner 	u32 i = 0;
32566f37f232SEric Joyner 
32576f37f232SEric Joyner 	DEBUGFUNC("ixgbe_write_ee_hostif_buffer_X550");
32586f37f232SEric Joyner 
32596f37f232SEric Joyner 	/* Take semaphore for the entire operation. */
32606f37f232SEric Joyner 	status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
32616f37f232SEric Joyner 	if (status != IXGBE_SUCCESS) {
32626f37f232SEric Joyner 		DEBUGOUT("EEPROM write buffer - semaphore failed\n");
32636f37f232SEric Joyner 		goto out;
32646f37f232SEric Joyner 	}
32656f37f232SEric Joyner 
32666f37f232SEric Joyner 	for (i = 0; i < words; i++) {
32676f37f232SEric Joyner 		status = ixgbe_write_ee_hostif_data_X550(hw, offset + i,
32686f37f232SEric Joyner 							 data[i]);
32696f37f232SEric Joyner 
32706f37f232SEric Joyner 		if (status != IXGBE_SUCCESS) {
32716f37f232SEric Joyner 			DEBUGOUT("Eeprom buffered write failed\n");
32726f37f232SEric Joyner 			break;
32736f37f232SEric Joyner 		}
32746f37f232SEric Joyner 	}
32756f37f232SEric Joyner 
32766f37f232SEric Joyner 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
32776f37f232SEric Joyner out:
32786f37f232SEric Joyner 
32796f37f232SEric Joyner 	return status;
32806f37f232SEric Joyner }
32816f37f232SEric Joyner 
32826f37f232SEric Joyner /**
32836f37f232SEric Joyner  * ixgbe_checksum_ptr_x550 - Checksum one pointer region
32846f37f232SEric Joyner  * @hw: pointer to hardware structure
32856f37f232SEric Joyner  * @ptr: pointer offset in eeprom
32866f37f232SEric Joyner  * @size: size of section pointed by ptr, if 0 first word will be used as size
32876f37f232SEric Joyner  * @csum: address of checksum to update
32887d48aa4cSEric Joyner  * @buffer: pointer to buffer containing calculated checksum
32897d48aa4cSEric Joyner  * @buffer_size: size of buffer
32906f37f232SEric Joyner  *
32916f37f232SEric Joyner  * Returns error status for any failure
32926f37f232SEric Joyner  */
ixgbe_checksum_ptr_x550(struct ixgbe_hw * hw,u16 ptr,u16 size,u16 * csum,u16 * buffer,u32 buffer_size)32936f37f232SEric Joyner static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
32946f37f232SEric Joyner 				   u16 size, u16 *csum, u16 *buffer,
32956f37f232SEric Joyner 				   u32 buffer_size)
32966f37f232SEric Joyner {
32976f37f232SEric Joyner 	u16 buf[256];
32986f37f232SEric Joyner 	s32 status;
32996f37f232SEric Joyner 	u16 length, bufsz, i, start;
33006f37f232SEric Joyner 	u16 *local_buffer;
33016f37f232SEric Joyner 
33026f37f232SEric Joyner 	bufsz = sizeof(buf) / sizeof(buf[0]);
33036f37f232SEric Joyner 
33046f37f232SEric Joyner 	/* Read a chunk at the pointer location */
33056f37f232SEric Joyner 	if (!buffer) {
33066f37f232SEric Joyner 		status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf);
33076f37f232SEric Joyner 		if (status) {
33086f37f232SEric Joyner 			DEBUGOUT("Failed to read EEPROM image\n");
33096f37f232SEric Joyner 			return status;
33106f37f232SEric Joyner 		}
33116f37f232SEric Joyner 		local_buffer = buf;
33126f37f232SEric Joyner 	} else {
33136f37f232SEric Joyner 		if (buffer_size < ptr)
33146f37f232SEric Joyner 			return  IXGBE_ERR_PARAM;
33156f37f232SEric Joyner 		local_buffer = &buffer[ptr];
33166f37f232SEric Joyner 	}
33176f37f232SEric Joyner 
33186f37f232SEric Joyner 	if (size) {
33196f37f232SEric Joyner 		start = 0;
33206f37f232SEric Joyner 		length = size;
33216f37f232SEric Joyner 	} else {
33226f37f232SEric Joyner 		start = 1;
33236f37f232SEric Joyner 		length = local_buffer[0];
33246f37f232SEric Joyner 
33256f37f232SEric Joyner 		/* Skip pointer section if length is invalid. */
33266f37f232SEric Joyner 		if (length == 0xFFFF || length == 0 ||
33276f37f232SEric Joyner 		    (ptr + length) >= hw->eeprom.word_size)
33286f37f232SEric Joyner 			return IXGBE_SUCCESS;
33296f37f232SEric Joyner 	}
33306f37f232SEric Joyner 
33316f37f232SEric Joyner 	if (buffer && ((u32)start + (u32)length > buffer_size))
33326f37f232SEric Joyner 		return IXGBE_ERR_PARAM;
33336f37f232SEric Joyner 
33346f37f232SEric Joyner 	for (i = start; length; i++, length--) {
33356f37f232SEric Joyner 		if (i == bufsz && !buffer) {
33366f37f232SEric Joyner 			ptr += bufsz;
33376f37f232SEric Joyner 			i = 0;
33386f37f232SEric Joyner 			if (length < bufsz)
33396f37f232SEric Joyner 				bufsz = length;
33406f37f232SEric Joyner 
33416f37f232SEric Joyner 			/* Read a chunk at the pointer location */
33426f37f232SEric Joyner 			status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr,
33436f37f232SEric Joyner 								  bufsz, buf);
33446f37f232SEric Joyner 			if (status) {
33456f37f232SEric Joyner 				DEBUGOUT("Failed to read EEPROM image\n");
33466f37f232SEric Joyner 				return status;
33476f37f232SEric Joyner 			}
33486f37f232SEric Joyner 		}
33496f37f232SEric Joyner 		*csum += local_buffer[i];
33506f37f232SEric Joyner 	}
33516f37f232SEric Joyner 	return IXGBE_SUCCESS;
33526f37f232SEric Joyner }
33536f37f232SEric Joyner 
33546f37f232SEric Joyner /**
33556f37f232SEric Joyner  * ixgbe_calc_checksum_X550 - Calculates and returns the checksum
33566f37f232SEric Joyner  * @hw: pointer to hardware structure
33576f37f232SEric Joyner  * @buffer: pointer to buffer containing calculated checksum
33586f37f232SEric Joyner  * @buffer_size: size of buffer
33596f37f232SEric Joyner  *
33606f37f232SEric Joyner  * Returns a negative error code on error, or the 16-bit checksum
33616f37f232SEric Joyner  **/
ixgbe_calc_checksum_X550(struct ixgbe_hw * hw,u16 * buffer,u32 buffer_size)33626f37f232SEric Joyner s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, u32 buffer_size)
33636f37f232SEric Joyner {
33646f37f232SEric Joyner 	u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1];
33656f37f232SEric Joyner 	u16 *local_buffer;
33666f37f232SEric Joyner 	s32 status;
33676f37f232SEric Joyner 	u16 checksum = 0;
33686f37f232SEric Joyner 	u16 pointer, i, size;
33696f37f232SEric Joyner 
33706f37f232SEric Joyner 	DEBUGFUNC("ixgbe_calc_eeprom_checksum_X550");
33716f37f232SEric Joyner 
33726f37f232SEric Joyner 	hw->eeprom.ops.init_params(hw);
33736f37f232SEric Joyner 
33746f37f232SEric Joyner 	if (!buffer) {
33756f37f232SEric Joyner 		/* Read pointer area */
33766f37f232SEric Joyner 		status = ixgbe_read_ee_hostif_buffer_X550(hw, 0,
33776f37f232SEric Joyner 						     IXGBE_EEPROM_LAST_WORD + 1,
33786f37f232SEric Joyner 						     eeprom_ptrs);
33796f37f232SEric Joyner 		if (status) {
33806f37f232SEric Joyner 			DEBUGOUT("Failed to read EEPROM image\n");
33816f37f232SEric Joyner 			return status;
33826f37f232SEric Joyner 		}
33836f37f232SEric Joyner 		local_buffer = eeprom_ptrs;
33846f37f232SEric Joyner 	} else {
33856f37f232SEric Joyner 		if (buffer_size < IXGBE_EEPROM_LAST_WORD)
33866f37f232SEric Joyner 			return IXGBE_ERR_PARAM;
33876f37f232SEric Joyner 		local_buffer = buffer;
33886f37f232SEric Joyner 	}
33896f37f232SEric Joyner 
33906f37f232SEric Joyner 	/*
33916f37f232SEric Joyner 	 * For X550 hardware include 0x0-0x41 in the checksum, skip the
33926f37f232SEric Joyner 	 * checksum word itself
33936f37f232SEric Joyner 	 */
33946f37f232SEric Joyner 	for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++)
33956f37f232SEric Joyner 		if (i != IXGBE_EEPROM_CHECKSUM)
33966f37f232SEric Joyner 			checksum += local_buffer[i];
33976f37f232SEric Joyner 
33986f37f232SEric Joyner 	/*
33996f37f232SEric Joyner 	 * Include all data from pointers 0x3, 0x6-0xE.  This excludes the
34006f37f232SEric Joyner 	 * FW, PHY module, and PCIe Expansion/Option ROM pointers.
34016f37f232SEric Joyner 	 */
34026f37f232SEric Joyner 	for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) {
34036f37f232SEric Joyner 		if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
34046f37f232SEric Joyner 			continue;
34056f37f232SEric Joyner 
34066f37f232SEric Joyner 		pointer = local_buffer[i];
34076f37f232SEric Joyner 
34086f37f232SEric Joyner 		/* Skip pointer section if the pointer is invalid. */
34096f37f232SEric Joyner 		if (pointer == 0xFFFF || pointer == 0 ||
34106f37f232SEric Joyner 		    pointer >= hw->eeprom.word_size)
34116f37f232SEric Joyner 			continue;
34126f37f232SEric Joyner 
34136f37f232SEric Joyner 		switch (i) {
34146f37f232SEric Joyner 		case IXGBE_PCIE_GENERAL_PTR:
34156f37f232SEric Joyner 			size = IXGBE_IXGBE_PCIE_GENERAL_SIZE;
34166f37f232SEric Joyner 			break;
34176f37f232SEric Joyner 		case IXGBE_PCIE_CONFIG0_PTR:
34186f37f232SEric Joyner 		case IXGBE_PCIE_CONFIG1_PTR:
34196f37f232SEric Joyner 			size = IXGBE_PCIE_CONFIG_SIZE;
34206f37f232SEric Joyner 			break;
34216f37f232SEric Joyner 		default:
34226f37f232SEric Joyner 			size = 0;
34236f37f232SEric Joyner 			break;
34246f37f232SEric Joyner 		}
34256f37f232SEric Joyner 
34266f37f232SEric Joyner 		status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum,
34276f37f232SEric Joyner 						buffer, buffer_size);
34286f37f232SEric Joyner 		if (status)
34296f37f232SEric Joyner 			return status;
34306f37f232SEric Joyner 	}
34316f37f232SEric Joyner 
34326f37f232SEric Joyner 	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
34336f37f232SEric Joyner 
34346f37f232SEric Joyner 	return (s32)checksum;
34356f37f232SEric Joyner }
34366f37f232SEric Joyner 
34376f37f232SEric Joyner /**
34386f37f232SEric Joyner  * ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum
34396f37f232SEric Joyner  * @hw: pointer to hardware structure
34406f37f232SEric Joyner  *
34416f37f232SEric Joyner  * Returns a negative error code on error, or the 16-bit checksum
34426f37f232SEric Joyner  **/
ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw * hw)34436f37f232SEric Joyner s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
34446f37f232SEric Joyner {
34456f37f232SEric Joyner 	return ixgbe_calc_checksum_X550(hw, NULL, 0);
34466f37f232SEric Joyner }
34476f37f232SEric Joyner 
34486f37f232SEric Joyner /**
34496f37f232SEric Joyner  * ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum
34506f37f232SEric Joyner  * @hw: pointer to hardware structure
34516f37f232SEric Joyner  * @checksum_val: calculated checksum
34526f37f232SEric Joyner  *
34536f37f232SEric Joyner  * Performs checksum calculation and validates the EEPROM checksum.  If the
34546f37f232SEric Joyner  * caller does not need checksum_val, the value can be NULL.
34556f37f232SEric Joyner  **/
ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw * hw,u16 * checksum_val)34566f37f232SEric Joyner s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, u16 *checksum_val)
34576f37f232SEric Joyner {
34586f37f232SEric Joyner 	s32 status;
34596f37f232SEric Joyner 	u16 checksum;
34606f37f232SEric Joyner 	u16 read_checksum = 0;
34616f37f232SEric Joyner 
34626f37f232SEric Joyner 	DEBUGFUNC("ixgbe_validate_eeprom_checksum_X550");
34636f37f232SEric Joyner 
34646f37f232SEric Joyner 	/* Read the first word from the EEPROM. If this times out or fails, do
34656f37f232SEric Joyner 	 * not continue or we could be in for a very long wait while every
34666f37f232SEric Joyner 	 * EEPROM read fails
34676f37f232SEric Joyner 	 */
34686f37f232SEric Joyner 	status = hw->eeprom.ops.read(hw, 0, &checksum);
34696f37f232SEric Joyner 	if (status) {
34706f37f232SEric Joyner 		DEBUGOUT("EEPROM read failed\n");
34716f37f232SEric Joyner 		return status;
34726f37f232SEric Joyner 	}
34736f37f232SEric Joyner 
34746f37f232SEric Joyner 	status = hw->eeprom.ops.calc_checksum(hw);
34756f37f232SEric Joyner 	if (status < 0)
34766f37f232SEric Joyner 		return status;
34776f37f232SEric Joyner 
34786f37f232SEric Joyner 	checksum = (u16)(status & 0xffff);
34796f37f232SEric Joyner 
34806f37f232SEric Joyner 	status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
34816f37f232SEric Joyner 					   &read_checksum);
34826f37f232SEric Joyner 	if (status)
34836f37f232SEric Joyner 		return status;
34846f37f232SEric Joyner 
34856f37f232SEric Joyner 	/* Verify read checksum from EEPROM is the same as
34866f37f232SEric Joyner 	 * calculated checksum
34876f37f232SEric Joyner 	 */
34886f37f232SEric Joyner 	if (read_checksum != checksum) {
34896f37f232SEric Joyner 		status = IXGBE_ERR_EEPROM_CHECKSUM;
34906f37f232SEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
34916f37f232SEric Joyner 			     "Invalid EEPROM checksum");
34926f37f232SEric Joyner 	}
34936f37f232SEric Joyner 
34946f37f232SEric Joyner 	/* If the user cares, return the calculated checksum */
34956f37f232SEric Joyner 	if (checksum_val)
34966f37f232SEric Joyner 		*checksum_val = checksum;
34976f37f232SEric Joyner 
34986f37f232SEric Joyner 	return status;
34996f37f232SEric Joyner }
35006f37f232SEric Joyner 
35016f37f232SEric Joyner /**
35026f37f232SEric Joyner  * ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash
35036f37f232SEric Joyner  * @hw: pointer to hardware structure
35046f37f232SEric Joyner  *
35056f37f232SEric Joyner  * After writing EEPROM to shadow RAM using EEWR register, software calculates
35066f37f232SEric Joyner  * checksum and updates the EEPROM and instructs the hardware to update
35076f37f232SEric Joyner  * the flash.
35086f37f232SEric Joyner  **/
ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw * hw)35096f37f232SEric Joyner s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw)
35106f37f232SEric Joyner {
35116f37f232SEric Joyner 	s32 status;
35126f37f232SEric Joyner 	u16 checksum = 0;
35136f37f232SEric Joyner 
35146f37f232SEric Joyner 	DEBUGFUNC("ixgbe_update_eeprom_checksum_X550");
35156f37f232SEric Joyner 
35166f37f232SEric Joyner 	/* Read the first word from the EEPROM. If this times out or fails, do
35176f37f232SEric Joyner 	 * not continue or we could be in for a very long wait while every
35186f37f232SEric Joyner 	 * EEPROM read fails
35196f37f232SEric Joyner 	 */
35206f37f232SEric Joyner 	status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum);
35216f37f232SEric Joyner 	if (status) {
35226f37f232SEric Joyner 		DEBUGOUT("EEPROM read failed\n");
35236f37f232SEric Joyner 		return status;
35246f37f232SEric Joyner 	}
35256f37f232SEric Joyner 
35266f37f232SEric Joyner 	status = ixgbe_calc_eeprom_checksum_X550(hw);
35276f37f232SEric Joyner 	if (status < 0)
35286f37f232SEric Joyner 		return status;
35296f37f232SEric Joyner 
35306f37f232SEric Joyner 	checksum = (u16)(status & 0xffff);
35316f37f232SEric Joyner 
35326f37f232SEric Joyner 	status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
35336f37f232SEric Joyner 					    checksum);
35346f37f232SEric Joyner 	if (status)
35356f37f232SEric Joyner 		return status;
35366f37f232SEric Joyner 
35376f37f232SEric Joyner 	status = ixgbe_update_flash_X550(hw);
35386f37f232SEric Joyner 
35396f37f232SEric Joyner 	return status;
35406f37f232SEric Joyner }
35416f37f232SEric Joyner 
35426f37f232SEric Joyner /**
35436f37f232SEric Joyner  * ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device
35446f37f232SEric Joyner  * @hw: pointer to hardware structure
35456f37f232SEric Joyner  *
35466f37f232SEric Joyner  * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash.
35476f37f232SEric Joyner  **/
ixgbe_update_flash_X550(struct ixgbe_hw * hw)35486f37f232SEric Joyner s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw)
35496f37f232SEric Joyner {
35506f37f232SEric Joyner 	s32 status = IXGBE_SUCCESS;
35516f37f232SEric Joyner 	union ixgbe_hic_hdr2 buffer;
35526f37f232SEric Joyner 
35536f37f232SEric Joyner 	DEBUGFUNC("ixgbe_update_flash_X550");
35546f37f232SEric Joyner 
35556f37f232SEric Joyner 	buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD;
35566f37f232SEric Joyner 	buffer.req.buf_lenh = 0;
35576f37f232SEric Joyner 	buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN;
35586f37f232SEric Joyner 	buffer.req.checksum = FW_DEFAULT_CHECKSUM;
35596f37f232SEric Joyner 
35606f37f232SEric Joyner 	status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
35616f37f232SEric Joyner 					      sizeof(buffer),
356279b36ec9SKevin Bowling 					      IXGBE_HI_COMMAND_TIMEOUT, false);
35636f37f232SEric Joyner 
35646f37f232SEric Joyner 	return status;
35656f37f232SEric Joyner }
35666f37f232SEric Joyner 
35676f37f232SEric Joyner /**
35686f37f232SEric Joyner  * ixgbe_get_supported_physical_layer_X550em - Returns physical layer type
35696f37f232SEric Joyner  * @hw: pointer to hardware structure
35706f37f232SEric Joyner  *
35716f37f232SEric Joyner  * Determines physical layer capabilities of the current configuration.
35726f37f232SEric Joyner  **/
ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw * hw)35738eb6488eSEric Joyner u64 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
35746f37f232SEric Joyner {
35758eb6488eSEric Joyner 	u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
35766f37f232SEric Joyner 	u16 ext_ability = 0;
35776f37f232SEric Joyner 
35786f37f232SEric Joyner 	DEBUGFUNC("ixgbe_get_supported_physical_layer_X550em");
35796f37f232SEric Joyner 
35806f37f232SEric Joyner 	hw->phy.ops.identify(hw);
35816f37f232SEric Joyner 
35826f37f232SEric Joyner 	switch (hw->phy.type) {
35836f37f232SEric Joyner 	case ixgbe_phy_x550em_kr:
35848eb6488eSEric Joyner 		if (hw->mac.type == ixgbe_mac_X550EM_a) {
35858eb6488eSEric Joyner 			if (hw->phy.nw_mng_if_sel &
35868eb6488eSEric Joyner 			    IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
35878eb6488eSEric Joyner 				physical_layer =
35888eb6488eSEric Joyner 					IXGBE_PHYSICAL_LAYER_2500BASE_KX;
35898eb6488eSEric Joyner 				break;
35908eb6488eSEric Joyner 			} else if (hw->device_id ==
35918eb6488eSEric Joyner 				   IXGBE_DEV_ID_X550EM_A_KR_L) {
35928eb6488eSEric Joyner 				physical_layer =
35938eb6488eSEric Joyner 					IXGBE_PHYSICAL_LAYER_1000BASE_KX;
35948eb6488eSEric Joyner 				break;
35958eb6488eSEric Joyner 			}
35968eb6488eSEric Joyner 		}
359750455f73SPiotr Skajewski 		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR |
359850455f73SPiotr Skajewski 				 IXGBE_PHYSICAL_LAYER_1000BASE_KX;
359950455f73SPiotr Skajewski 		break;
36008eb6488eSEric Joyner 	case ixgbe_phy_x550em_xfi:
36016f37f232SEric Joyner 		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR |
36026f37f232SEric Joyner 				 IXGBE_PHYSICAL_LAYER_1000BASE_KX;
36036f37f232SEric Joyner 		break;
36046f37f232SEric Joyner 	case ixgbe_phy_x550em_kx4:
36056f37f232SEric Joyner 		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
36066f37f232SEric Joyner 				 IXGBE_PHYSICAL_LAYER_1000BASE_KX;
36076f37f232SEric Joyner 		break;
36086f37f232SEric Joyner 	case ixgbe_phy_x550em_ext_t:
36096f37f232SEric Joyner 		hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
36106f37f232SEric Joyner 				     IXGBE_MDIO_PMA_PMD_DEV_TYPE,
36116f37f232SEric Joyner 				     &ext_ability);
36126f37f232SEric Joyner 		if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
36136f37f232SEric Joyner 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
36146f37f232SEric Joyner 		if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
36156f37f232SEric Joyner 			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
36166f37f232SEric Joyner 		break;
36178eb6488eSEric Joyner 	case ixgbe_phy_fw:
36188eb6488eSEric Joyner 		if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_1GB_FULL)
36198eb6488eSEric Joyner 			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
36208eb6488eSEric Joyner 		if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_100_FULL)
36218eb6488eSEric Joyner 			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
36228eb6488eSEric Joyner 		if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_10_FULL)
36238eb6488eSEric Joyner 			physical_layer |= IXGBE_PHYSICAL_LAYER_10BASE_T;
36248eb6488eSEric Joyner 		break;
36258eb6488eSEric Joyner 	case ixgbe_phy_sgmii:
36268eb6488eSEric Joyner 		physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
36278eb6488eSEric Joyner 		break;
36288eb6488eSEric Joyner 	case ixgbe_phy_ext_1g_t:
36293f66b96dSKevin Bowling 		physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
36308eb6488eSEric Joyner 		break;
36316f37f232SEric Joyner 	default:
36326f37f232SEric Joyner 		break;
36336f37f232SEric Joyner 	}
36346f37f232SEric Joyner 
36356f37f232SEric Joyner 	if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber)
36366f37f232SEric Joyner 		physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw);
36376f37f232SEric Joyner 
36386f37f232SEric Joyner 	return physical_layer;
36396f37f232SEric Joyner }
36406f37f232SEric Joyner 
36416f37f232SEric Joyner /**
3642edef2769SRadoslaw Tyl  * ixgbe_get_bus_info_X550em - Set PCI bus info
36436f37f232SEric Joyner  * @hw: pointer to hardware structure
36446f37f232SEric Joyner  *
36456f37f232SEric Joyner  * Sets bus link width and speed to unknown because X550em is
36466f37f232SEric Joyner  * not a PCI device.
36476f37f232SEric Joyner  **/
ixgbe_get_bus_info_X550em(struct ixgbe_hw * hw)36486f37f232SEric Joyner s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
36496f37f232SEric Joyner {
36506f37f232SEric Joyner 
36516f37f232SEric Joyner 	DEBUGFUNC("ixgbe_get_bus_info_x550em");
36526f37f232SEric Joyner 
36536f37f232SEric Joyner 	hw->bus.width = ixgbe_bus_width_unknown;
36546f37f232SEric Joyner 	hw->bus.speed = ixgbe_bus_speed_unknown;
36556f37f232SEric Joyner 
36566f37f232SEric Joyner 	hw->mac.ops.set_lan_id(hw);
36576f37f232SEric Joyner 
36586f37f232SEric Joyner 	return IXGBE_SUCCESS;
36596f37f232SEric Joyner }
36606f37f232SEric Joyner 
36616f37f232SEric Joyner /**
36626f37f232SEric Joyner  * ixgbe_disable_rx_x550 - Disable RX unit
36637d48aa4cSEric Joyner  * @hw: pointer to hardware structure
36646f37f232SEric Joyner  *
36656f37f232SEric Joyner  * Enables the Rx DMA unit for x550
36666f37f232SEric Joyner  **/
ixgbe_disable_rx_x550(struct ixgbe_hw * hw)36676f37f232SEric Joyner void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
36686f37f232SEric Joyner {
36696f37f232SEric Joyner 	u32 rxctrl, pfdtxgswc;
36706f37f232SEric Joyner 	s32 status;
36716f37f232SEric Joyner 	struct ixgbe_hic_disable_rxen fw_cmd;
36726f37f232SEric Joyner 
36736f37f232SEric Joyner 	DEBUGFUNC("ixgbe_enable_rx_dma_x550");
36746f37f232SEric Joyner 
36756f37f232SEric Joyner 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
36766f37f232SEric Joyner 	if (rxctrl & IXGBE_RXCTRL_RXEN) {
36776f37f232SEric Joyner 		pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
36786f37f232SEric Joyner 		if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
36796f37f232SEric Joyner 			pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
36806f37f232SEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
368179b36ec9SKevin Bowling 			hw->mac.set_lben = true;
36826f37f232SEric Joyner 		} else {
368379b36ec9SKevin Bowling 			hw->mac.set_lben = false;
36846f37f232SEric Joyner 		}
36856f37f232SEric Joyner 
36866f37f232SEric Joyner 		fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD;
36876f37f232SEric Joyner 		fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN;
36886f37f232SEric Joyner 		fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
36896f37f232SEric Joyner 		fw_cmd.port_number = (u8)hw->bus.lan_id;
36906f37f232SEric Joyner 
36916f37f232SEric Joyner 		status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
36926f37f232SEric Joyner 					sizeof(struct ixgbe_hic_disable_rxen),
369379b36ec9SKevin Bowling 					IXGBE_HI_COMMAND_TIMEOUT, true);
36946f37f232SEric Joyner 
36956f37f232SEric Joyner 		/* If we fail - disable RX using register write */
36966f37f232SEric Joyner 		if (status) {
36976f37f232SEric Joyner 			rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
36986f37f232SEric Joyner 			if (rxctrl & IXGBE_RXCTRL_RXEN) {
36996f37f232SEric Joyner 				rxctrl &= ~IXGBE_RXCTRL_RXEN;
37006f37f232SEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
37016f37f232SEric Joyner 			}
37026f37f232SEric Joyner 		}
37036f37f232SEric Joyner 	}
37046f37f232SEric Joyner }
37056f37f232SEric Joyner 
37066f37f232SEric Joyner /**
3707edef2769SRadoslaw Tyl  * ixgbe_enter_lplu_t_x550em - Transition to low power states
37086f37f232SEric Joyner  * @hw: pointer to hardware structure
37096f37f232SEric Joyner  *
37106f37f232SEric Joyner  * Configures Low Power Link Up on transition to low power states
37116f37f232SEric Joyner  * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting the
37126f37f232SEric Joyner  * X557 PHY immediately prior to entering LPLU.
37136f37f232SEric Joyner  **/
ixgbe_enter_lplu_t_x550em(struct ixgbe_hw * hw)37146f37f232SEric Joyner s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
37156f37f232SEric Joyner {
37166f37f232SEric Joyner 	u16 an_10g_cntl_reg, autoneg_reg, speed;
37176f37f232SEric Joyner 	s32 status;
37186f37f232SEric Joyner 	ixgbe_link_speed lcd_speed;
37196f37f232SEric Joyner 	u32 save_autoneg;
37206f37f232SEric Joyner 	bool link_up;
37216f37f232SEric Joyner 
3722a9ca1c79SSean Bruno 	/* SW LPLU not required on later HW revisions. */
37238eb6488eSEric Joyner 	if ((hw->mac.type == ixgbe_mac_X550EM_x) &&
37248eb6488eSEric Joyner 	    (IXGBE_FUSES0_REV_MASK &
37258eb6488eSEric Joyner 	     IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))))
3726a9ca1c79SSean Bruno 		return IXGBE_SUCCESS;
3727a9ca1c79SSean Bruno 
37286f37f232SEric Joyner 	/* If blocked by MNG FW, then don't restart AN */
37296f37f232SEric Joyner 	if (ixgbe_check_reset_blocked(hw))
37306f37f232SEric Joyner 		return IXGBE_SUCCESS;
37316f37f232SEric Joyner 
37326f37f232SEric Joyner 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
37336f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
37346f37f232SEric Joyner 		return status;
37356f37f232SEric Joyner 
37366f37f232SEric Joyner 	status = ixgbe_read_eeprom(hw, NVM_INIT_CTRL_3, &hw->eeprom.ctrl_word_3);
37376f37f232SEric Joyner 
37386f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
37396f37f232SEric Joyner 		return status;
37406f37f232SEric Joyner 
37416f37f232SEric Joyner 	/* If link is down, LPLU disabled in NVM, WoL disabled, or manageability
37426f37f232SEric Joyner 	 * disabled, then force link down by entering low power mode.
37436f37f232SEric Joyner 	 */
37446f37f232SEric Joyner 	if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
37456f37f232SEric Joyner 	    !(hw->wol_enabled || ixgbe_mng_present(hw)))
374679b36ec9SKevin Bowling 		return ixgbe_set_copper_phy_power(hw, false);
37476f37f232SEric Joyner 
37486f37f232SEric Joyner 	/* Determine LCD */
37496f37f232SEric Joyner 	status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed);
37506f37f232SEric Joyner 
37516f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
37526f37f232SEric Joyner 		return status;
37536f37f232SEric Joyner 
37546f37f232SEric Joyner 	/* If no valid LCD link speed, then force link down and exit. */
37556f37f232SEric Joyner 	if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN)
375679b36ec9SKevin Bowling 		return ixgbe_set_copper_phy_power(hw, false);
37576f37f232SEric Joyner 
37586f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
37596f37f232SEric Joyner 				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
37606f37f232SEric Joyner 				      &speed);
37616f37f232SEric Joyner 
37626f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
37636f37f232SEric Joyner 		return status;
37646f37f232SEric Joyner 
37656f37f232SEric Joyner 	/* If no link now, speed is invalid so take link down */
37666f37f232SEric Joyner 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
37676f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
376879b36ec9SKevin Bowling 		return ixgbe_set_copper_phy_power(hw, false);
37696f37f232SEric Joyner 
37706f37f232SEric Joyner 	/* clear everything but the speed bits */
37716f37f232SEric Joyner 	speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK;
37726f37f232SEric Joyner 
37736f37f232SEric Joyner 	/* If current speed is already LCD, then exit. */
37746f37f232SEric Joyner 	if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) &&
37756f37f232SEric Joyner 	     (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) ||
37766f37f232SEric Joyner 	    ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) &&
37776f37f232SEric Joyner 	     (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL)))
37786f37f232SEric Joyner 		return status;
37796f37f232SEric Joyner 
37806f37f232SEric Joyner 	/* Clear AN completed indication */
37816f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
37826f37f232SEric Joyner 				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
37836f37f232SEric Joyner 				      &autoneg_reg);
37846f37f232SEric Joyner 
37856f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
37866f37f232SEric Joyner 		return status;
37876f37f232SEric Joyner 
37886f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
37896f37f232SEric Joyner 			     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
37906f37f232SEric Joyner 			     &an_10g_cntl_reg);
37916f37f232SEric Joyner 
37926f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
37936f37f232SEric Joyner 		return status;
37946f37f232SEric Joyner 
37956f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw,
37966f37f232SEric Joyner 			     IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
37976f37f232SEric Joyner 			     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
37986f37f232SEric Joyner 			     &autoneg_reg);
37996f37f232SEric Joyner 
38006f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
38016f37f232SEric Joyner 		return status;
38026f37f232SEric Joyner 
38036f37f232SEric Joyner 	save_autoneg = hw->phy.autoneg_advertised;
38046f37f232SEric Joyner 
38056f37f232SEric Joyner 	/* Setup link at least common link speed */
380679b36ec9SKevin Bowling 	status = hw->mac.ops.setup_link(hw, lcd_speed, false);
38076f37f232SEric Joyner 
38086f37f232SEric Joyner 	/* restore autoneg from before setting lplu speed */
38096f37f232SEric Joyner 	hw->phy.autoneg_advertised = save_autoneg;
38106f37f232SEric Joyner 
38116f37f232SEric Joyner 	return status;
38126f37f232SEric Joyner }
38136f37f232SEric Joyner 
38146f37f232SEric Joyner /**
3815edef2769SRadoslaw Tyl  * ixgbe_get_lcd_t_x550em - Determine lowest common denominator
38166f37f232SEric Joyner  * @hw: pointer to hardware structure
38176f37f232SEric Joyner  * @lcd_speed: pointer to lowest common link speed
38186f37f232SEric Joyner  *
38196f37f232SEric Joyner  * Determine lowest common link speed with link partner.
38206f37f232SEric Joyner  **/
ixgbe_get_lcd_t_x550em(struct ixgbe_hw * hw,ixgbe_link_speed * lcd_speed)38216f37f232SEric Joyner s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed)
38226f37f232SEric Joyner {
38236f37f232SEric Joyner 	u16 an_lp_status;
38246f37f232SEric Joyner 	s32 status;
38256f37f232SEric Joyner 	u16 word = hw->eeprom.ctrl_word_3;
38266f37f232SEric Joyner 
38276f37f232SEric Joyner 	*lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
38286f37f232SEric Joyner 
38296f37f232SEric Joyner 	status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
38306f37f232SEric Joyner 				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
38316f37f232SEric Joyner 				      &an_lp_status);
38326f37f232SEric Joyner 
38336f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
38346f37f232SEric Joyner 		return status;
38356f37f232SEric Joyner 
38366f37f232SEric Joyner 	/* If link partner advertised 1G, return 1G */
38376f37f232SEric Joyner 	if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) {
38386f37f232SEric Joyner 		*lcd_speed = IXGBE_LINK_SPEED_1GB_FULL;
38396f37f232SEric Joyner 		return status;
38406f37f232SEric Joyner 	}
38416f37f232SEric Joyner 
38426f37f232SEric Joyner 	/* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */
38436f37f232SEric Joyner 	if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) ||
38446f37f232SEric Joyner 	    (word & NVM_INIT_CTRL_3_D10GMP_PORT0))
38456f37f232SEric Joyner 		return status;
38466f37f232SEric Joyner 
38476f37f232SEric Joyner 	/* Link partner not capable of lower speeds, return 10G */
38486f37f232SEric Joyner 	*lcd_speed = IXGBE_LINK_SPEED_10GB_FULL;
38496f37f232SEric Joyner 	return status;
38506f37f232SEric Joyner }
38516f37f232SEric Joyner 
38526f37f232SEric Joyner /**
38536f37f232SEric Joyner  * ixgbe_setup_fc_X550em - Set up flow control
38546f37f232SEric Joyner  * @hw: pointer to hardware structure
38556f37f232SEric Joyner  *
38566f37f232SEric Joyner  * Called at init time to set up flow control.
38576f37f232SEric Joyner  **/
ixgbe_setup_fc_X550em(struct ixgbe_hw * hw)38586f37f232SEric Joyner s32 ixgbe_setup_fc_X550em(struct ixgbe_hw *hw)
38596f37f232SEric Joyner {
38606f37f232SEric Joyner 	s32 ret_val = IXGBE_SUCCESS;
38616f37f232SEric Joyner 	u32 pause, asm_dir, reg_val;
38626f37f232SEric Joyner 
38636f37f232SEric Joyner 	DEBUGFUNC("ixgbe_setup_fc_X550em");
38646f37f232SEric Joyner 
38656f37f232SEric Joyner 	/* Validate the requested mode */
38666f37f232SEric Joyner 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
38676f37f232SEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
38686f37f232SEric Joyner 			"ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
38696f37f232SEric Joyner 		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
38706f37f232SEric Joyner 		goto out;
38716f37f232SEric Joyner 	}
38726f37f232SEric Joyner 
38736f37f232SEric Joyner 	/* 10gig parts do not have a word in the EEPROM to determine the
38746f37f232SEric Joyner 	 * default flow control setting, so we explicitly set it to full.
38756f37f232SEric Joyner 	 */
38766f37f232SEric Joyner 	if (hw->fc.requested_mode == ixgbe_fc_default)
38776f37f232SEric Joyner 		hw->fc.requested_mode = ixgbe_fc_full;
38786f37f232SEric Joyner 
38796f37f232SEric Joyner 	/* Determine PAUSE and ASM_DIR bits. */
38806f37f232SEric Joyner 	switch (hw->fc.requested_mode) {
38816f37f232SEric Joyner 	case ixgbe_fc_none:
38826f37f232SEric Joyner 		pause = 0;
38836f37f232SEric Joyner 		asm_dir = 0;
38846f37f232SEric Joyner 		break;
38856f37f232SEric Joyner 	case ixgbe_fc_tx_pause:
38866f37f232SEric Joyner 		pause = 0;
38876f37f232SEric Joyner 		asm_dir = 1;
38886f37f232SEric Joyner 		break;
38896f37f232SEric Joyner 	case ixgbe_fc_rx_pause:
38906f37f232SEric Joyner 		/* Rx Flow control is enabled and Tx Flow control is
38916f37f232SEric Joyner 		 * disabled by software override. Since there really
38926f37f232SEric Joyner 		 * isn't a way to advertise that we are capable of RX
38936f37f232SEric Joyner 		 * Pause ONLY, we will advertise that we support both
38946f37f232SEric Joyner 		 * symmetric and asymmetric Rx PAUSE, as such we fall
38956f37f232SEric Joyner 		 * through to the fc_full statement.  Later, we will
38966f37f232SEric Joyner 		 * disable the adapter's ability to send PAUSE frames.
38976f37f232SEric Joyner 		 */
38986f37f232SEric Joyner 	case ixgbe_fc_full:
38996f37f232SEric Joyner 		pause = 1;
39006f37f232SEric Joyner 		asm_dir = 1;
39016f37f232SEric Joyner 		break;
39026f37f232SEric Joyner 	default:
39036f37f232SEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_ARGUMENT,
39046f37f232SEric Joyner 			"Flow control param set incorrectly\n");
39056f37f232SEric Joyner 		ret_val = IXGBE_ERR_CONFIG;
39066f37f232SEric Joyner 		goto out;
39076f37f232SEric Joyner 	}
39086f37f232SEric Joyner 
39098eb6488eSEric Joyner 	switch (hw->device_id) {
39108eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_KR:
39118eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_KR:
39128eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_KR_L:
39138eb6488eSEric Joyner 		ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
39146f37f232SEric Joyner 					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
39156f37f232SEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
39166f37f232SEric Joyner 		if (ret_val != IXGBE_SUCCESS)
39176f37f232SEric Joyner 			goto out;
39186f37f232SEric Joyner 		reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
39196f37f232SEric Joyner 			IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
39206f37f232SEric Joyner 		if (pause)
39216f37f232SEric Joyner 			reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
39226f37f232SEric Joyner 		if (asm_dir)
39236f37f232SEric Joyner 			reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
39248eb6488eSEric Joyner 		ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
39256f37f232SEric Joyner 					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
39266f37f232SEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
39276f37f232SEric Joyner 
3928a9ca1c79SSean Bruno 		/* This device does not fully support AN. */
392979b36ec9SKevin Bowling 		hw->fc.disable_fc_autoneg = true;
39308eb6488eSEric Joyner 		break;
39318eb6488eSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_XFI:
393279b36ec9SKevin Bowling 		hw->fc.disable_fc_autoneg = true;
39338eb6488eSEric Joyner 		break;
39348eb6488eSEric Joyner 	default:
39358eb6488eSEric Joyner 		break;
39366f37f232SEric Joyner 	}
39376f37f232SEric Joyner 
39386f37f232SEric Joyner out:
39396f37f232SEric Joyner 	return ret_val;
39406f37f232SEric Joyner }
39416f37f232SEric Joyner 
39426f37f232SEric Joyner /**
39438eb6488eSEric Joyner  * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37
39448eb6488eSEric Joyner  * @hw: pointer to hardware structure
39458eb6488eSEric Joyner  *
39468eb6488eSEric Joyner  * Enable flow control according to IEEE clause 37.
39478eb6488eSEric Joyner  **/
ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw * hw)39488eb6488eSEric Joyner void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
39498eb6488eSEric Joyner {
39508eb6488eSEric Joyner 	u32 link_s1, lp_an_page_low, an_cntl_1;
39518eb6488eSEric Joyner 	s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
39528eb6488eSEric Joyner 	ixgbe_link_speed speed;
39538eb6488eSEric Joyner 	bool link_up;
39548eb6488eSEric Joyner 
39558eb6488eSEric Joyner 	/* AN should have completed when the cable was plugged in.
39568eb6488eSEric Joyner 	 * Look for reasons to bail out.  Bail out if:
39578eb6488eSEric Joyner 	 * - FC autoneg is disabled, or if
39588eb6488eSEric Joyner 	 * - link is not up.
39598eb6488eSEric Joyner 	 */
39608eb6488eSEric Joyner 	if (hw->fc.disable_fc_autoneg) {
39618eb6488eSEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
39628eb6488eSEric Joyner 			     "Flow control autoneg is disabled");
39638eb6488eSEric Joyner 		goto out;
39648eb6488eSEric Joyner 	}
39658eb6488eSEric Joyner 
396679b36ec9SKevin Bowling 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
39678eb6488eSEric Joyner 	if (!link_up) {
39688eb6488eSEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down");
39698eb6488eSEric Joyner 		goto out;
39708eb6488eSEric Joyner 	}
39718eb6488eSEric Joyner 
39728eb6488eSEric Joyner 	/* Check at auto-negotiation has completed */
39738eb6488eSEric Joyner 	status = hw->mac.ops.read_iosf_sb_reg(hw,
39748eb6488eSEric Joyner 					IXGBE_KRM_LINK_S1(hw->bus.lan_id),
39758eb6488eSEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1);
39768eb6488eSEric Joyner 
39778eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS ||
39788eb6488eSEric Joyner 	    (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
39798eb6488eSEric Joyner 		DEBUGOUT("Auto-Negotiation did not complete\n");
39808eb6488eSEric Joyner 		status = IXGBE_ERR_FC_NOT_NEGOTIATED;
39818eb6488eSEric Joyner 		goto out;
39828eb6488eSEric Joyner 	}
39838eb6488eSEric Joyner 
39848eb6488eSEric Joyner 	/* Read the 10g AN autoc and LP ability registers and resolve
39858eb6488eSEric Joyner 	 * local flow control settings accordingly
39868eb6488eSEric Joyner 	 */
39878eb6488eSEric Joyner 	status = hw->mac.ops.read_iosf_sb_reg(hw,
39888eb6488eSEric Joyner 				IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
39898eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1);
39908eb6488eSEric Joyner 
39918eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS) {
39928eb6488eSEric Joyner 		DEBUGOUT("Auto-Negotiation did not complete\n");
39938eb6488eSEric Joyner 		goto out;
39948eb6488eSEric Joyner 	}
39958eb6488eSEric Joyner 
39968eb6488eSEric Joyner 	status = hw->mac.ops.read_iosf_sb_reg(hw,
39978eb6488eSEric Joyner 				IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id),
39988eb6488eSEric Joyner 				IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low);
39998eb6488eSEric Joyner 
40008eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS) {
40018eb6488eSEric Joyner 		DEBUGOUT("Auto-Negotiation did not complete\n");
40028eb6488eSEric Joyner 		goto out;
40038eb6488eSEric Joyner 	}
40048eb6488eSEric Joyner 
40058eb6488eSEric Joyner 	status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low,
40068eb6488eSEric Joyner 				    IXGBE_KRM_AN_CNTL_1_SYM_PAUSE,
40078eb6488eSEric Joyner 				    IXGBE_KRM_AN_CNTL_1_ASM_PAUSE,
40088eb6488eSEric Joyner 				    IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE,
40098eb6488eSEric Joyner 				    IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE);
40108eb6488eSEric Joyner 
40118eb6488eSEric Joyner out:
40128eb6488eSEric Joyner 	if (status == IXGBE_SUCCESS) {
401379b36ec9SKevin Bowling 		hw->fc.fc_was_autonegged = true;
40148eb6488eSEric Joyner 	} else {
401579b36ec9SKevin Bowling 		hw->fc.fc_was_autonegged = false;
40168eb6488eSEric Joyner 		hw->fc.current_mode = hw->fc.requested_mode;
40178eb6488eSEric Joyner 	}
40188eb6488eSEric Joyner }
40198eb6488eSEric Joyner 
40208eb6488eSEric Joyner /**
40218eb6488eSEric Joyner  * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings
40228eb6488eSEric Joyner  * @hw: pointer to hardware structure
40238eb6488eSEric Joyner  *
40248eb6488eSEric Joyner  **/
ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw * hw)40258eb6488eSEric Joyner void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw)
40268eb6488eSEric Joyner {
402779b36ec9SKevin Bowling 	hw->fc.fc_was_autonegged = false;
40288eb6488eSEric Joyner 	hw->fc.current_mode = hw->fc.requested_mode;
40298eb6488eSEric Joyner }
40308eb6488eSEric Joyner 
40318eb6488eSEric Joyner /**
40328eb6488eSEric Joyner  * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37
40338eb6488eSEric Joyner  * @hw: pointer to hardware structure
40348eb6488eSEric Joyner  *
40358eb6488eSEric Joyner  * Enable flow control according to IEEE clause 37.
40368eb6488eSEric Joyner  **/
ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw * hw)40378eb6488eSEric Joyner void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)
40388eb6488eSEric Joyner {
40398eb6488eSEric Joyner 	s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
40408eb6488eSEric Joyner 	u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
40418eb6488eSEric Joyner 	ixgbe_link_speed speed;
40428eb6488eSEric Joyner 	bool link_up;
40438eb6488eSEric Joyner 
40448eb6488eSEric Joyner 	/* AN should have completed when the cable was plugged in.
40458eb6488eSEric Joyner 	 * Look for reasons to bail out.  Bail out if:
40468eb6488eSEric Joyner 	 * - FC autoneg is disabled, or if
40478eb6488eSEric Joyner 	 * - link is not up.
40488eb6488eSEric Joyner 	 */
40498eb6488eSEric Joyner 	if (hw->fc.disable_fc_autoneg) {
40508eb6488eSEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
40518eb6488eSEric Joyner 			     "Flow control autoneg is disabled");
40528eb6488eSEric Joyner 		goto out;
40538eb6488eSEric Joyner 	}
40548eb6488eSEric Joyner 
405579b36ec9SKevin Bowling 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
40568eb6488eSEric Joyner 	if (!link_up) {
40578eb6488eSEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down");
40588eb6488eSEric Joyner 		goto out;
40598eb6488eSEric Joyner 	}
40608eb6488eSEric Joyner 
40618eb6488eSEric Joyner 	/* Check if auto-negotiation has completed */
40628eb6488eSEric Joyner 	status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info);
40638eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS ||
40648eb6488eSEric Joyner 	    !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) {
40658eb6488eSEric Joyner 		DEBUGOUT("Auto-Negotiation did not complete\n");
40668eb6488eSEric Joyner 		status = IXGBE_ERR_FC_NOT_NEGOTIATED;
40678eb6488eSEric Joyner 		goto out;
40688eb6488eSEric Joyner 	}
40698eb6488eSEric Joyner 
40708eb6488eSEric Joyner 	/* Negotiate the flow control */
40718eb6488eSEric Joyner 	status = ixgbe_negotiate_fc(hw, info[0], info[0],
40728eb6488eSEric Joyner 				    FW_PHY_ACT_GET_LINK_INFO_FC_RX,
40738eb6488eSEric Joyner 				    FW_PHY_ACT_GET_LINK_INFO_FC_TX,
40748eb6488eSEric Joyner 				    FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX,
40758eb6488eSEric Joyner 				    FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX);
40768eb6488eSEric Joyner 
40778eb6488eSEric Joyner out:
40788eb6488eSEric Joyner 	if (status == IXGBE_SUCCESS) {
407979b36ec9SKevin Bowling 		hw->fc.fc_was_autonegged = true;
40808eb6488eSEric Joyner 	} else {
408179b36ec9SKevin Bowling 		hw->fc.fc_was_autonegged = false;
40828eb6488eSEric Joyner 		hw->fc.current_mode = hw->fc.requested_mode;
40838eb6488eSEric Joyner 	}
40848eb6488eSEric Joyner }
40858eb6488eSEric Joyner 
40868eb6488eSEric Joyner /**
40878eb6488eSEric Joyner  * ixgbe_setup_fc_backplane_x550em_a - Set up flow control
40888eb6488eSEric Joyner  * @hw: pointer to hardware structure
40898eb6488eSEric Joyner  *
40908eb6488eSEric Joyner  * Called at init time to set up flow control.
40918eb6488eSEric Joyner  **/
ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw * hw)40928eb6488eSEric Joyner s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw)
40938eb6488eSEric Joyner {
40948eb6488eSEric Joyner 	s32 status = IXGBE_SUCCESS;
40958eb6488eSEric Joyner 	u32 an_cntl = 0;
40968eb6488eSEric Joyner 
40978eb6488eSEric Joyner 	DEBUGFUNC("ixgbe_setup_fc_backplane_x550em_a");
40988eb6488eSEric Joyner 
40998eb6488eSEric Joyner 	/* Validate the requested mode */
41008eb6488eSEric Joyner 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
41018eb6488eSEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
41028eb6488eSEric Joyner 			      "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
41038eb6488eSEric Joyner 		return IXGBE_ERR_INVALID_LINK_SETTINGS;
41048eb6488eSEric Joyner 	}
41058eb6488eSEric Joyner 
41068eb6488eSEric Joyner 	if (hw->fc.requested_mode == ixgbe_fc_default)
41078eb6488eSEric Joyner 		hw->fc.requested_mode = ixgbe_fc_full;
41088eb6488eSEric Joyner 
41098eb6488eSEric Joyner 	/* Set up the 1G and 10G flow control advertisement registers so the
41108eb6488eSEric Joyner 	 * HW will be able to do FC autoneg once the cable is plugged in.  If
41118eb6488eSEric Joyner 	 * we link at 10G, the 1G advertisement is harmless and vice versa.
41128eb6488eSEric Joyner 	 */
41138eb6488eSEric Joyner 	status = hw->mac.ops.read_iosf_sb_reg(hw,
41148eb6488eSEric Joyner 					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
41158eb6488eSEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl);
41168eb6488eSEric Joyner 
41178eb6488eSEric Joyner 	if (status != IXGBE_SUCCESS) {
41188eb6488eSEric Joyner 		DEBUGOUT("Auto-Negotiation did not complete\n");
41198eb6488eSEric Joyner 		return status;
41208eb6488eSEric Joyner 	}
41218eb6488eSEric Joyner 
41228eb6488eSEric Joyner 	/* The possible values of fc.requested_mode are:
41238eb6488eSEric Joyner 	 * 0: Flow control is completely disabled
41248eb6488eSEric Joyner 	 * 1: Rx flow control is enabled (we can receive pause frames,
41258eb6488eSEric Joyner 	 *    but not send pause frames).
41268eb6488eSEric Joyner 	 * 2: Tx flow control is enabled (we can send pause frames but
41278eb6488eSEric Joyner 	 *    we do not support receiving pause frames).
41288eb6488eSEric Joyner 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
41298eb6488eSEric Joyner 	 * other: Invalid.
41308eb6488eSEric Joyner 	 */
41318eb6488eSEric Joyner 	switch (hw->fc.requested_mode) {
41328eb6488eSEric Joyner 	case ixgbe_fc_none:
41338eb6488eSEric Joyner 		/* Flow control completely disabled by software override. */
41348eb6488eSEric Joyner 		an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
41358eb6488eSEric Joyner 			     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
41368eb6488eSEric Joyner 		break;
41378eb6488eSEric Joyner 	case ixgbe_fc_tx_pause:
41388eb6488eSEric Joyner 		/* Tx Flow control is enabled, and Rx Flow control is
41398eb6488eSEric Joyner 		 * disabled by software override.
41408eb6488eSEric Joyner 		 */
41418eb6488eSEric Joyner 		an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
41428eb6488eSEric Joyner 		an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
41438eb6488eSEric Joyner 		break;
41448eb6488eSEric Joyner 	case ixgbe_fc_rx_pause:
41458eb6488eSEric Joyner 		/* Rx Flow control is enabled and Tx Flow control is
41468eb6488eSEric Joyner 		 * disabled by software override. Since there really
41478eb6488eSEric Joyner 		 * isn't a way to advertise that we are capable of RX
41488eb6488eSEric Joyner 		 * Pause ONLY, we will advertise that we support both
41498eb6488eSEric Joyner 		 * symmetric and asymmetric Rx PAUSE, as such we fall
41508eb6488eSEric Joyner 		 * through to the fc_full statement.  Later, we will
41518eb6488eSEric Joyner 		 * disable the adapter's ability to send PAUSE frames.
41528eb6488eSEric Joyner 		 */
41538eb6488eSEric Joyner 	case ixgbe_fc_full:
41548eb6488eSEric Joyner 		/* Flow control (both Rx and Tx) is enabled by SW override. */
41558eb6488eSEric Joyner 		an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
41568eb6488eSEric Joyner 			   IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
41578eb6488eSEric Joyner 		break;
41588eb6488eSEric Joyner 	default:
41598eb6488eSEric Joyner 		ERROR_REPORT1(IXGBE_ERROR_ARGUMENT,
41608eb6488eSEric Joyner 			      "Flow control param set incorrectly\n");
41618eb6488eSEric Joyner 		return IXGBE_ERR_CONFIG;
41628eb6488eSEric Joyner 	}
41638eb6488eSEric Joyner 
41648eb6488eSEric Joyner 	status = hw->mac.ops.write_iosf_sb_reg(hw,
41658eb6488eSEric Joyner 					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
41668eb6488eSEric Joyner 					IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl);
41678eb6488eSEric Joyner 
41688eb6488eSEric Joyner 	/* Restart auto-negotiation. */
41698eb6488eSEric Joyner 	status = ixgbe_restart_an_internal_phy_x550em(hw);
41708eb6488eSEric Joyner 
41718eb6488eSEric Joyner 	return status;
41728eb6488eSEric Joyner }
41738eb6488eSEric Joyner 
41748eb6488eSEric Joyner /**
41756f37f232SEric Joyner  * ixgbe_set_mux - Set mux for port 1 access with CS4227
41766f37f232SEric Joyner  * @hw: pointer to hardware structure
41776f37f232SEric Joyner  * @state: set mux if 1, clear if 0
41786f37f232SEric Joyner  */
ixgbe_set_mux(struct ixgbe_hw * hw,u8 state)41796f37f232SEric Joyner static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state)
41806f37f232SEric Joyner {
41816f37f232SEric Joyner 	u32 esdp;
41826f37f232SEric Joyner 
41836f37f232SEric Joyner 	if (!hw->bus.lan_id)
41846f37f232SEric Joyner 		return;
41856f37f232SEric Joyner 	esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
41866f37f232SEric Joyner 	if (state)
41876f37f232SEric Joyner 		esdp |= IXGBE_ESDP_SDP1;
41886f37f232SEric Joyner 	else
41896f37f232SEric Joyner 		esdp &= ~IXGBE_ESDP_SDP1;
41906f37f232SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
41916f37f232SEric Joyner 	IXGBE_WRITE_FLUSH(hw);
41926f37f232SEric Joyner }
41936f37f232SEric Joyner 
41946f37f232SEric Joyner /**
41956f37f232SEric Joyner  * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore
41966f37f232SEric Joyner  * @hw: pointer to hardware structure
41976f37f232SEric Joyner  * @mask: Mask to specify which semaphore to acquire
41986f37f232SEric Joyner  *
41996f37f232SEric Joyner  * Acquires the SWFW semaphore and sets the I2C MUX
42006f37f232SEric Joyner  **/
ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw * hw,u32 mask)42016f37f232SEric Joyner s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
42026f37f232SEric Joyner {
42036f37f232SEric Joyner 	s32 status;
42046f37f232SEric Joyner 
42056f37f232SEric Joyner 	DEBUGFUNC("ixgbe_acquire_swfw_sync_X550em");
42066f37f232SEric Joyner 
42076f37f232SEric Joyner 	status = ixgbe_acquire_swfw_sync_X540(hw, mask);
42086f37f232SEric Joyner 	if (status)
42096f37f232SEric Joyner 		return status;
42106f37f232SEric Joyner 
42116f37f232SEric Joyner 	if (mask & IXGBE_GSSR_I2C_MASK)
42126f37f232SEric Joyner 		ixgbe_set_mux(hw, 1);
42136f37f232SEric Joyner 
42146f37f232SEric Joyner 	return IXGBE_SUCCESS;
42156f37f232SEric Joyner }
42166f37f232SEric Joyner 
42176f37f232SEric Joyner /**
42186f37f232SEric Joyner  * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore
42196f37f232SEric Joyner  * @hw: pointer to hardware structure
42206f37f232SEric Joyner  * @mask: Mask to specify which semaphore to release
42216f37f232SEric Joyner  *
42226f37f232SEric Joyner  * Releases the SWFW semaphore and sets the I2C MUX
42236f37f232SEric Joyner  **/
ixgbe_release_swfw_sync_X550em(struct ixgbe_hw * hw,u32 mask)42246f37f232SEric Joyner void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
42256f37f232SEric Joyner {
42266f37f232SEric Joyner 	DEBUGFUNC("ixgbe_release_swfw_sync_X550em");
42276f37f232SEric Joyner 
42286f37f232SEric Joyner 	if (mask & IXGBE_GSSR_I2C_MASK)
42296f37f232SEric Joyner 		ixgbe_set_mux(hw, 0);
42306f37f232SEric Joyner 
42316f37f232SEric Joyner 	ixgbe_release_swfw_sync_X540(hw, mask);
42326f37f232SEric Joyner }
42336f37f232SEric Joyner 
42346f37f232SEric Joyner /**
42358eb6488eSEric Joyner  * ixgbe_acquire_swfw_sync_X550a - Acquire SWFW semaphore
42368eb6488eSEric Joyner  * @hw: pointer to hardware structure
42378eb6488eSEric Joyner  * @mask: Mask to specify which semaphore to acquire
42388eb6488eSEric Joyner  *
42398eb6488eSEric Joyner  * Acquires the SWFW semaphore and get the shared phy token as needed
42408eb6488eSEric Joyner  */
ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw * hw,u32 mask)42418eb6488eSEric Joyner static s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *hw, u32 mask)
42428eb6488eSEric Joyner {
42438eb6488eSEric Joyner 	u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
42448eb6488eSEric Joyner 	int retries = FW_PHY_TOKEN_RETRIES;
42458eb6488eSEric Joyner 	s32 status = IXGBE_SUCCESS;
42468eb6488eSEric Joyner 
42478eb6488eSEric Joyner 	DEBUGFUNC("ixgbe_acquire_swfw_sync_X550a");
42488eb6488eSEric Joyner 
42498eb6488eSEric Joyner 	status = IXGBE_SUCCESS;
42508eb6488eSEric Joyner 	if (hmask)
42518eb6488eSEric Joyner 		status = ixgbe_acquire_swfw_sync_X540(hw, hmask);
4252cc994418SBarbara Skobiej 
42538eb6488eSEric Joyner 	if (status) {
4254cc994418SBarbara Skobiej 		DEBUGOUT1("Could not acquire SWFW semaphore, Status = %d\n", status);
42558eb6488eSEric Joyner 		return status;
42568eb6488eSEric Joyner 	}
4257cc994418SBarbara Skobiej 
42588eb6488eSEric Joyner 	if (!(mask & IXGBE_GSSR_TOKEN_SM))
42598eb6488eSEric Joyner 		return IXGBE_SUCCESS;
42608eb6488eSEric Joyner 
4261cc994418SBarbara Skobiej 	while (--retries) {
42628eb6488eSEric Joyner 		status = ixgbe_get_phy_token(hw);
42638eb6488eSEric Joyner 
42648eb6488eSEric Joyner 		if (status == IXGBE_SUCCESS)
42658eb6488eSEric Joyner 			return IXGBE_SUCCESS;
42668eb6488eSEric Joyner 
4267cc994418SBarbara Skobiej 		if (status != IXGBE_ERR_TOKEN_RETRY) {
4268cc994418SBarbara Skobiej 			DEBUGOUT1("Retry acquiring the PHY token failed, Status = %d\n", status);
42698eb6488eSEric Joyner 			if (hmask)
42708eb6488eSEric Joyner 				ixgbe_release_swfw_sync_X540(hw, hmask);
42718eb6488eSEric Joyner 			return status;
42728eb6488eSEric Joyner 		}
4273cc994418SBarbara Skobiej 
4274cc994418SBarbara Skobiej 		if (status == IXGBE_ERR_TOKEN_RETRY)
4275cc994418SBarbara Skobiej 			DEBUGOUT1("Could not acquire PHY token, Status = %d\n",
4276cc994418SBarbara Skobiej 				  status);
42778eb6488eSEric Joyner 	}
42788eb6488eSEric Joyner 
4279cc994418SBarbara Skobiej 	if (hmask)
4280cc994418SBarbara Skobiej 		ixgbe_release_swfw_sync_X540(hw, hmask);
4281cc994418SBarbara Skobiej 
42828eb6488eSEric Joyner 	DEBUGOUT1("Semaphore acquisition retries failed!: PHY ID = 0x%08X\n",
42838eb6488eSEric Joyner 		  hw->phy.id);
42848eb6488eSEric Joyner 	return status;
42858eb6488eSEric Joyner }
42868eb6488eSEric Joyner 
42878eb6488eSEric Joyner /**
42888eb6488eSEric Joyner  * ixgbe_release_swfw_sync_X550a - Release SWFW semaphore
42898eb6488eSEric Joyner  * @hw: pointer to hardware structure
42908eb6488eSEric Joyner  * @mask: Mask to specify which semaphore to release
42918eb6488eSEric Joyner  *
42928eb6488eSEric Joyner  * Releases the SWFW semaphore and puts the shared phy token as needed
42938eb6488eSEric Joyner  */
ixgbe_release_swfw_sync_X550a(struct ixgbe_hw * hw,u32 mask)42948eb6488eSEric Joyner static void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *hw, u32 mask)
42958eb6488eSEric Joyner {
42968eb6488eSEric Joyner 	u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
42978eb6488eSEric Joyner 
42988eb6488eSEric Joyner 	DEBUGFUNC("ixgbe_release_swfw_sync_X550a");
42998eb6488eSEric Joyner 
43008eb6488eSEric Joyner 	if (mask & IXGBE_GSSR_TOKEN_SM)
43018eb6488eSEric Joyner 		ixgbe_put_phy_token(hw);
43028eb6488eSEric Joyner 
43038eb6488eSEric Joyner 	if (hmask)
43048eb6488eSEric Joyner 		ixgbe_release_swfw_sync_X540(hw, hmask);
43058eb6488eSEric Joyner }
43068eb6488eSEric Joyner 
43078eb6488eSEric Joyner /**
43088eb6488eSEric Joyner  * ixgbe_read_phy_reg_x550a  - Reads specified PHY register
43098eb6488eSEric Joyner  * @hw: pointer to hardware structure
43108eb6488eSEric Joyner  * @reg_addr: 32 bit address of PHY register to read
43117d48aa4cSEric Joyner  * @device_type: 5 bit device type
43128eb6488eSEric Joyner  * @phy_data: Pointer to read data from PHY register
43138eb6488eSEric Joyner  *
43148eb6488eSEric Joyner  * Reads a value from a specified PHY register using the SWFW lock and PHY
43158eb6488eSEric Joyner  * Token. The PHY Token is needed since the MDIO is shared between to MAC
43168eb6488eSEric Joyner  * instances.
43178eb6488eSEric Joyner  **/
ixgbe_read_phy_reg_x550a(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)43188eb6488eSEric Joyner s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
43198eb6488eSEric Joyner 			       u32 device_type, u16 *phy_data)
43208eb6488eSEric Joyner {
43218eb6488eSEric Joyner 	s32 status;
43228eb6488eSEric Joyner 	u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
43238eb6488eSEric Joyner 
43248eb6488eSEric Joyner 	DEBUGFUNC("ixgbe_read_phy_reg_x550a");
43258eb6488eSEric Joyner 
43268eb6488eSEric Joyner 	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
43278eb6488eSEric Joyner 		return IXGBE_ERR_SWFW_SYNC;
43288eb6488eSEric Joyner 
43298eb6488eSEric Joyner 	status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data);
43308eb6488eSEric Joyner 
43318eb6488eSEric Joyner 	hw->mac.ops.release_swfw_sync(hw, mask);
43328eb6488eSEric Joyner 
43338eb6488eSEric Joyner 	return status;
43348eb6488eSEric Joyner }
43358eb6488eSEric Joyner 
43368eb6488eSEric Joyner /**
43378eb6488eSEric Joyner  * ixgbe_write_phy_reg_x550a - Writes specified PHY register
43388eb6488eSEric Joyner  * @hw: pointer to hardware structure
43398eb6488eSEric Joyner  * @reg_addr: 32 bit PHY register to write
43408eb6488eSEric Joyner  * @device_type: 5 bit device type
43418eb6488eSEric Joyner  * @phy_data: Data to write to the PHY register
43428eb6488eSEric Joyner  *
43438eb6488eSEric Joyner  * Writes a value to specified PHY register using the SWFW lock and PHY Token.
43448eb6488eSEric Joyner  * The PHY Token is needed since the MDIO is shared between to MAC instances.
43458eb6488eSEric Joyner  **/
ixgbe_write_phy_reg_x550a(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)43468eb6488eSEric Joyner s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
43478eb6488eSEric Joyner 				u32 device_type, u16 phy_data)
43488eb6488eSEric Joyner {
43498eb6488eSEric Joyner 	s32 status;
43508eb6488eSEric Joyner 	u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
43518eb6488eSEric Joyner 
43528eb6488eSEric Joyner 	DEBUGFUNC("ixgbe_write_phy_reg_x550a");
43538eb6488eSEric Joyner 
43548eb6488eSEric Joyner 	if (hw->mac.ops.acquire_swfw_sync(hw, mask) == IXGBE_SUCCESS) {
43558eb6488eSEric Joyner 		status = hw->phy.ops.write_reg_mdi(hw, reg_addr, device_type,
43568eb6488eSEric Joyner 						 phy_data);
43578eb6488eSEric Joyner 		hw->mac.ops.release_swfw_sync(hw, mask);
43588eb6488eSEric Joyner 	} else {
43598eb6488eSEric Joyner 		status = IXGBE_ERR_SWFW_SYNC;
43608eb6488eSEric Joyner 	}
43618eb6488eSEric Joyner 
43628eb6488eSEric Joyner 	return status;
43638eb6488eSEric Joyner }
43648eb6488eSEric Joyner 
43658eb6488eSEric Joyner /**
43666f37f232SEric Joyner  * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
43676f37f232SEric Joyner  * @hw: pointer to hardware structure
43686f37f232SEric Joyner  *
43696f37f232SEric Joyner  * Handle external Base T PHY interrupt. If high temperature
43706f37f232SEric Joyner  * failure alarm then return error, else if link status change
43716f37f232SEric Joyner  * then setup internal/external PHY link
43726f37f232SEric Joyner  *
43736f37f232SEric Joyner  * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
43746f37f232SEric Joyner  * failure alarm, else return PHY access status.
43756f37f232SEric Joyner  */
ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw * hw)43766f37f232SEric Joyner s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
43776f37f232SEric Joyner {
43786f37f232SEric Joyner 	bool lsc;
43796f37f232SEric Joyner 	u32 status;
43806f37f232SEric Joyner 
43816f37f232SEric Joyner 	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
43826f37f232SEric Joyner 
43836f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
43846f37f232SEric Joyner 		return status;
43856f37f232SEric Joyner 
43866f37f232SEric Joyner 	if (lsc)
43876f37f232SEric Joyner 		return ixgbe_setup_internal_phy(hw);
43886f37f232SEric Joyner 
43896f37f232SEric Joyner 	return IXGBE_SUCCESS;
43906f37f232SEric Joyner }
43916f37f232SEric Joyner 
43926f37f232SEric Joyner /**
43936f37f232SEric Joyner  * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
43946f37f232SEric Joyner  * @hw: pointer to hardware structure
43956f37f232SEric Joyner  * @speed: new link speed
439679b36ec9SKevin Bowling  * @autoneg_wait_to_complete: true when waiting for completion is needed
43976f37f232SEric Joyner  *
43986f37f232SEric Joyner  * Setup internal/external PHY link speed based on link speed, then set
43996f37f232SEric Joyner  * external PHY auto advertised link speed.
44006f37f232SEric Joyner  *
44016f37f232SEric Joyner  * Returns error status for any failure
44026f37f232SEric Joyner  **/
ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)44036f37f232SEric Joyner s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
44046f37f232SEric Joyner 				  ixgbe_link_speed speed,
44056f37f232SEric Joyner 				  bool autoneg_wait_to_complete)
44066f37f232SEric Joyner {
44076f37f232SEric Joyner 	s32 status;
44086f37f232SEric Joyner 	ixgbe_link_speed force_speed;
4409d5bbb550SAshijeet Acharya 	u32 i;
4410d5bbb550SAshijeet Acharya 	bool link_up = false;
44116f37f232SEric Joyner 
44126f37f232SEric Joyner 	DEBUGFUNC("ixgbe_setup_mac_link_t_X550em");
44136f37f232SEric Joyner 
44146f37f232SEric Joyner 	/* Setup internal/external PHY link speed to iXFI (10G), unless
44156f37f232SEric Joyner 	 * only 1G is auto advertised then setup KX link.
44166f37f232SEric Joyner 	 */
44176f37f232SEric Joyner 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
44186f37f232SEric Joyner 		force_speed = IXGBE_LINK_SPEED_10GB_FULL;
44196f37f232SEric Joyner 	else
44206f37f232SEric Joyner 		force_speed = IXGBE_LINK_SPEED_1GB_FULL;
44216f37f232SEric Joyner 
44228eb6488eSEric Joyner 	/* If X552 and internal link mode is XFI, then setup XFI internal link.
44238eb6488eSEric Joyner 	 */
44248eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_X550EM_x &&
44258eb6488eSEric Joyner 	    !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
44266f37f232SEric Joyner 		status = ixgbe_setup_ixfi_x550em(hw, &force_speed);
44276f37f232SEric Joyner 
44286f37f232SEric Joyner 		if (status != IXGBE_SUCCESS)
44296f37f232SEric Joyner 			return status;
4430d5bbb550SAshijeet Acharya 
4431d5bbb550SAshijeet Acharya 		/* Wait for the controller to acquire link */
4432d5bbb550SAshijeet Acharya 		for (i = 0; i < 10; i++) {
4433d5bbb550SAshijeet Acharya 			msec_delay(100);
4434d5bbb550SAshijeet Acharya 
4435d5bbb550SAshijeet Acharya 			status = ixgbe_check_link(hw, &force_speed, &link_up,
4436d5bbb550SAshijeet Acharya 						  false);
4437d5bbb550SAshijeet Acharya 			if (status != IXGBE_SUCCESS)
4438d5bbb550SAshijeet Acharya 				return status;
4439d5bbb550SAshijeet Acharya 
4440d5bbb550SAshijeet Acharya 			if (link_up)
4441d5bbb550SAshijeet Acharya 				break;
4442d5bbb550SAshijeet Acharya 		}
44436f37f232SEric Joyner 	}
44446f37f232SEric Joyner 
44456f37f232SEric Joyner 	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete);
44466f37f232SEric Joyner }
44476f37f232SEric Joyner 
44486f37f232SEric Joyner /**
44496f37f232SEric Joyner  * ixgbe_check_link_t_X550em - Determine link and speed status
44506f37f232SEric Joyner  * @hw: pointer to hardware structure
44516f37f232SEric Joyner  * @speed: pointer to link speed
445279b36ec9SKevin Bowling  * @link_up: true when link is up
44536f37f232SEric Joyner  * @link_up_wait_to_complete: bool used to wait for link up or not
44546f37f232SEric Joyner  *
44556f37f232SEric Joyner  * Check that both the MAC and X557 external PHY have link.
44566f37f232SEric Joyner  **/
ixgbe_check_link_t_X550em(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * link_up,bool link_up_wait_to_complete)44576f37f232SEric Joyner s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
44586f37f232SEric Joyner 			      bool *link_up, bool link_up_wait_to_complete)
44596f37f232SEric Joyner {
44606f37f232SEric Joyner 	u32 status;
44618eb6488eSEric Joyner 	u16 i, autoneg_status = 0;
44626f37f232SEric Joyner 
44636f37f232SEric Joyner 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
44646f37f232SEric Joyner 		return IXGBE_ERR_CONFIG;
44656f37f232SEric Joyner 
44666f37f232SEric Joyner 	status = ixgbe_check_mac_link_generic(hw, speed, link_up,
44676f37f232SEric Joyner 					      link_up_wait_to_complete);
44686f37f232SEric Joyner 
44696f37f232SEric Joyner 	/* If check link fails or MAC link is not up, then return */
44706f37f232SEric Joyner 	if (status != IXGBE_SUCCESS || !(*link_up))
44716f37f232SEric Joyner 		return status;
44726f37f232SEric Joyner 
44736f37f232SEric Joyner 	/* MAC link is up, so check external PHY link.
44748eb6488eSEric Joyner 	 * X557 PHY. Link status is latching low, and can only be used to detect
44758eb6488eSEric Joyner 	 * link drop, and not the current status of the link without performing
44768eb6488eSEric Joyner 	 * back-to-back reads.
44776f37f232SEric Joyner 	 */
44788eb6488eSEric Joyner 	for (i = 0; i < 2; i++) {
44796f37f232SEric Joyner 		status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
44806f37f232SEric Joyner 					      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
44816f37f232SEric Joyner 					      &autoneg_status);
44826f37f232SEric Joyner 
44836f37f232SEric Joyner 		if (status != IXGBE_SUCCESS)
44846f37f232SEric Joyner 			return status;
44858eb6488eSEric Joyner 	}
44866f37f232SEric Joyner 
44876f37f232SEric Joyner 	/* If external PHY link is not up, then indicate link not up */
44886f37f232SEric Joyner 	if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
448979b36ec9SKevin Bowling 		*link_up = false;
44906f37f232SEric Joyner 
44916f37f232SEric Joyner 	return IXGBE_SUCCESS;
44926f37f232SEric Joyner }
44936f37f232SEric Joyner 
44946f37f232SEric Joyner /**
44956f37f232SEric Joyner  * ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI
44966f37f232SEric Joyner  * @hw: pointer to hardware structure
44976f37f232SEric Joyner  **/
ixgbe_reset_phy_t_X550em(struct ixgbe_hw * hw)44986f37f232SEric Joyner s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw)
44996f37f232SEric Joyner {
45006f37f232SEric Joyner 	s32 status;
45016f37f232SEric Joyner 
45026f37f232SEric Joyner 	status = ixgbe_reset_phy_generic(hw);
45036f37f232SEric Joyner 
45046f37f232SEric Joyner 	if (status != IXGBE_SUCCESS)
45056f37f232SEric Joyner 		return status;
45066f37f232SEric Joyner 
45076f37f232SEric Joyner 	/* Configure Link Status Alarm and Temperature Threshold interrupts */
45086f37f232SEric Joyner 	return ixgbe_enable_lasi_ext_t_x550em(hw);
45096f37f232SEric Joyner }
45106f37f232SEric Joyner 
45116f37f232SEric Joyner /**
45126f37f232SEric Joyner  * ixgbe_led_on_t_X550em - Turns on the software controllable LEDs.
45136f37f232SEric Joyner  * @hw: pointer to hardware structure
45146f37f232SEric Joyner  * @led_idx: led number to turn on
45156f37f232SEric Joyner  **/
ixgbe_led_on_t_X550em(struct ixgbe_hw * hw,u32 led_idx)45166f37f232SEric Joyner s32 ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, u32 led_idx)
45176f37f232SEric Joyner {
45186f37f232SEric Joyner 	u16 phy_data;
45196f37f232SEric Joyner 
45206f37f232SEric Joyner 	DEBUGFUNC("ixgbe_led_on_t_X550em");
45216f37f232SEric Joyner 
45226f37f232SEric Joyner 	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
45236f37f232SEric Joyner 		return IXGBE_ERR_PARAM;
45246f37f232SEric Joyner 
45256f37f232SEric Joyner 	/* To turn on the LED, set mode to ON. */
45266f37f232SEric Joyner 	ixgbe_read_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
45276f37f232SEric Joyner 			   IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
45286f37f232SEric Joyner 	phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;
45296f37f232SEric Joyner 	ixgbe_write_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
45306f37f232SEric Joyner 			    IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
45316f37f232SEric Joyner 
45328eb6488eSEric Joyner 	/* Some designs have the LEDs wired to the MAC */
45338eb6488eSEric Joyner 	return ixgbe_led_on_generic(hw, led_idx);
45346f37f232SEric Joyner }
45356f37f232SEric Joyner 
45366f37f232SEric Joyner /**
45376f37f232SEric Joyner  * ixgbe_led_off_t_X550em - Turns off the software controllable LEDs.
45386f37f232SEric Joyner  * @hw: pointer to hardware structure
45396f37f232SEric Joyner  * @led_idx: led number to turn off
45406f37f232SEric Joyner  **/
ixgbe_led_off_t_X550em(struct ixgbe_hw * hw,u32 led_idx)45416f37f232SEric Joyner s32 ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, u32 led_idx)
45426f37f232SEric Joyner {
45436f37f232SEric Joyner 	u16 phy_data;
45446f37f232SEric Joyner 
45456f37f232SEric Joyner 	DEBUGFUNC("ixgbe_led_off_t_X550em");
45466f37f232SEric Joyner 
45476f37f232SEric Joyner 	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
45486f37f232SEric Joyner 		return IXGBE_ERR_PARAM;
45496f37f232SEric Joyner 
45506f37f232SEric Joyner 	/* To turn on the LED, set mode to ON. */
45516f37f232SEric Joyner 	ixgbe_read_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
45526f37f232SEric Joyner 			   IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
45536f37f232SEric Joyner 	phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;
45546f37f232SEric Joyner 	ixgbe_write_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
45556f37f232SEric Joyner 			    IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
45566f37f232SEric Joyner 
45578eb6488eSEric Joyner 	/* Some designs have the LEDs wired to the MAC */
45588eb6488eSEric Joyner 	return ixgbe_led_off_generic(hw, led_idx);
45596f37f232SEric Joyner }
45606f37f232SEric Joyner 
45618eb6488eSEric Joyner /**
45628eb6488eSEric Joyner  * ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware
45638eb6488eSEric Joyner  * @hw: pointer to the HW structure
45648eb6488eSEric Joyner  * @maj: driver version major number
45658eb6488eSEric Joyner  * @min: driver version minor number
45668eb6488eSEric Joyner  * @build: driver version build number
45678eb6488eSEric Joyner  * @sub: driver version sub build number
45688eb6488eSEric Joyner  * @len: length of driver_ver string
45698eb6488eSEric Joyner  * @driver_ver: driver string
45708eb6488eSEric Joyner  *
45718eb6488eSEric Joyner  * Sends driver version number to firmware through the manageability
45728eb6488eSEric Joyner  * block.  On success return IXGBE_SUCCESS
45738eb6488eSEric Joyner  * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
45748eb6488eSEric Joyner  * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
45758eb6488eSEric Joyner  **/
ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw * hw,u8 maj,u8 min,u8 build,u8 sub,u16 len,const char * driver_ver)45768eb6488eSEric Joyner s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
45778eb6488eSEric Joyner 			      u8 build, u8 sub, u16 len, const char *driver_ver)
45788eb6488eSEric Joyner {
45798eb6488eSEric Joyner 	struct ixgbe_hic_drv_info2 fw_cmd;
45808eb6488eSEric Joyner 	s32 ret_val = IXGBE_SUCCESS;
45818eb6488eSEric Joyner 	int i;
45828eb6488eSEric Joyner 
45838eb6488eSEric Joyner 	DEBUGFUNC("ixgbe_set_fw_drv_ver_x550");
45848eb6488eSEric Joyner 
45858eb6488eSEric Joyner 	if ((len == 0) || (driver_ver == NULL) ||
45868eb6488eSEric Joyner 	   (len > sizeof(fw_cmd.driver_string)))
45878eb6488eSEric Joyner 		return IXGBE_ERR_INVALID_ARGUMENT;
45888eb6488eSEric Joyner 
45898eb6488eSEric Joyner 	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
45908eb6488eSEric Joyner 	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len;
45918eb6488eSEric Joyner 	fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
45928eb6488eSEric Joyner 	fw_cmd.port_num = (u8)hw->bus.func;
45938eb6488eSEric Joyner 	fw_cmd.ver_maj = maj;
45948eb6488eSEric Joyner 	fw_cmd.ver_min = min;
45958eb6488eSEric Joyner 	fw_cmd.ver_build = build;
45968eb6488eSEric Joyner 	fw_cmd.ver_sub = sub;
45978eb6488eSEric Joyner 	fw_cmd.hdr.checksum = 0;
45988eb6488eSEric Joyner 	memcpy(fw_cmd.driver_string, driver_ver, len);
45998eb6488eSEric Joyner 	fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
46008eb6488eSEric Joyner 				(FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
46018eb6488eSEric Joyner 
46028eb6488eSEric Joyner 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
46038eb6488eSEric Joyner 		ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
46048eb6488eSEric Joyner 						       sizeof(fw_cmd),
46058eb6488eSEric Joyner 						       IXGBE_HI_COMMAND_TIMEOUT,
460679b36ec9SKevin Bowling 						       true);
46078eb6488eSEric Joyner 		if (ret_val != IXGBE_SUCCESS)
46088eb6488eSEric Joyner 			continue;
46098eb6488eSEric Joyner 
46108eb6488eSEric Joyner 		if (fw_cmd.hdr.cmd_or_resp.ret_status ==
46118eb6488eSEric Joyner 		    FW_CEM_RESP_STATUS_SUCCESS)
46128eb6488eSEric Joyner 			ret_val = IXGBE_SUCCESS;
46138eb6488eSEric Joyner 		else
46148eb6488eSEric Joyner 			ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
46158eb6488eSEric Joyner 
46168eb6488eSEric Joyner 		break;
46178eb6488eSEric Joyner 	}
46188eb6488eSEric Joyner 
46198eb6488eSEric Joyner 	return ret_val;
46208eb6488eSEric Joyner }
4621b622bdb4SXiaoyun Li 
4622b622bdb4SXiaoyun Li /**
4623b622bdb4SXiaoyun Li  * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode
4624b622bdb4SXiaoyun Li  * @hw: pointer t hardware structure
4625b622bdb4SXiaoyun Li  *
4626b622bdb4SXiaoyun Li  * Returns true if in FW NVM recovery mode.
4627b622bdb4SXiaoyun Li  **/
ixgbe_fw_recovery_mode_X550(struct ixgbe_hw * hw)4628b622bdb4SXiaoyun Li bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw)
4629b622bdb4SXiaoyun Li {
4630b622bdb4SXiaoyun Li 	u32 fwsm;
4631b622bdb4SXiaoyun Li 
4632b622bdb4SXiaoyun Li 	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
4633b622bdb4SXiaoyun Li 
4634b622bdb4SXiaoyun Li 	return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE);
4635b622bdb4SXiaoyun Li }
4636