151dce24bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0
251dce24bSJeff Kirsher /* Copyright(c) 1999 - 2018 Intel Corporation. */
351dce24bSJeff Kirsher 
46a14ee0cSDon Skidmore #include "ixgbe_x540.h"
56a14ee0cSDon Skidmore #include "ixgbe_type.h"
66a14ee0cSDon Skidmore #include "ixgbe_common.h"
76a14ee0cSDon Skidmore #include "ixgbe_phy.h"
86a14ee0cSDon Skidmore 
9d91e3a7dSMark Rustad static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed);
10afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *);
112916500dSDon Skidmore static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *);
122916500dSDon Skidmore static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *);
132916500dSDon Skidmore static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *);
14d91e3a7dSMark Rustad 
15b5529ef5SDon Skidmore static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw)
16b5529ef5SDon Skidmore {
17b5529ef5SDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
18b5529ef5SDon Skidmore 	struct ixgbe_phy_info *phy = &hw->phy;
19b71f6c40SEmil Tantilov 	struct ixgbe_link_info *link = &hw->link;
20b71f6c40SEmil Tantilov 
21b71f6c40SEmil Tantilov 	/* Start with X540 invariants, since so simular */
22b71f6c40SEmil Tantilov 	ixgbe_get_invariants_X540(hw);
23b71f6c40SEmil Tantilov 
24b71f6c40SEmil Tantilov 	if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
25b71f6c40SEmil Tantilov 		phy->ops.set_phy_power = NULL;
26b71f6c40SEmil Tantilov 
27b71f6c40SEmil Tantilov 	link->addr = IXGBE_CS4227;
28b71f6c40SEmil Tantilov 
29b71f6c40SEmil Tantilov 	return 0;
30b71f6c40SEmil Tantilov }
31b71f6c40SEmil Tantilov 
328dc963e1SPaul Greenwalt static s32 ixgbe_get_invariants_X550_x_fw(struct ixgbe_hw *hw)
338dc963e1SPaul Greenwalt {
348dc963e1SPaul Greenwalt 	struct ixgbe_phy_info *phy = &hw->phy;
358dc963e1SPaul Greenwalt 
368dc963e1SPaul Greenwalt 	/* Start with X540 invariants, since so similar */
378dc963e1SPaul Greenwalt 	ixgbe_get_invariants_X540(hw);
388dc963e1SPaul Greenwalt 
398dc963e1SPaul Greenwalt 	phy->ops.set_phy_power = NULL;
408dc963e1SPaul Greenwalt 
418dc963e1SPaul Greenwalt 	return 0;
428dc963e1SPaul Greenwalt }
438dc963e1SPaul Greenwalt 
44b71f6c40SEmil Tantilov static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw)
45b71f6c40SEmil Tantilov {
46b71f6c40SEmil Tantilov 	struct ixgbe_mac_info *mac = &hw->mac;
47b71f6c40SEmil Tantilov 	struct ixgbe_phy_info *phy = &hw->phy;
48b5529ef5SDon Skidmore 
49b5529ef5SDon Skidmore 	/* Start with X540 invariants, since so simular */
50b5529ef5SDon Skidmore 	ixgbe_get_invariants_X540(hw);
51b5529ef5SDon Skidmore 
52b5529ef5SDon Skidmore 	if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
53b5529ef5SDon Skidmore 		phy->ops.set_phy_power = NULL;
54b5529ef5SDon Skidmore 
55b5529ef5SDon Skidmore 	return 0;
56b5529ef5SDon Skidmore }
57b5529ef5SDon Skidmore 
58b3eb4e18SMark Rustad static s32 ixgbe_get_invariants_X550_a_fw(struct ixgbe_hw *hw)
59b3eb4e18SMark Rustad {
60b3eb4e18SMark Rustad 	struct ixgbe_phy_info *phy = &hw->phy;
61b3eb4e18SMark Rustad 
62b3eb4e18SMark Rustad 	/* Start with X540 invariants, since so similar */
63b3eb4e18SMark Rustad 	ixgbe_get_invariants_X540(hw);
64b3eb4e18SMark Rustad 
65b3eb4e18SMark Rustad 	phy->ops.set_phy_power = NULL;
66b3eb4e18SMark Rustad 
67b3eb4e18SMark Rustad 	return 0;
68b3eb4e18SMark Rustad }
69b3eb4e18SMark Rustad 
70ab5fe0c5SDon Skidmore /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control
71ab5fe0c5SDon Skidmore  *  @hw: pointer to hardware structure
72ab5fe0c5SDon Skidmore  **/
73ab5fe0c5SDon Skidmore static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
74ab5fe0c5SDon Skidmore {
75ab5fe0c5SDon Skidmore 	u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
76ab5fe0c5SDon Skidmore 
77ab5fe0c5SDon Skidmore 	if (hw->bus.lan_id) {
78ab5fe0c5SDon Skidmore 		esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
79ab5fe0c5SDon Skidmore 		esdp |= IXGBE_ESDP_SDP1_DIR;
80ab5fe0c5SDon Skidmore 	}
81ab5fe0c5SDon Skidmore 	esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
82ab5fe0c5SDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
83ab5fe0c5SDon Skidmore 	IXGBE_WRITE_FLUSH(hw);
84ab5fe0c5SDon Skidmore }
85ab5fe0c5SDon Skidmore 
86542b6eecSMark Rustad /**
87542b6eecSMark Rustad  * ixgbe_read_cs4227 - Read CS4227 register
88542b6eecSMark Rustad  * @hw: pointer to hardware structure
89542b6eecSMark Rustad  * @reg: register number to write
90542b6eecSMark Rustad  * @value: pointer to receive value read
91542b6eecSMark Rustad  *
92542b6eecSMark Rustad  * Returns status code
93542b6eecSMark Rustad  */
94542b6eecSMark Rustad static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
95542b6eecSMark Rustad {
96b71f6c40SEmil Tantilov 	return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);
97542b6eecSMark Rustad }
98542b6eecSMark Rustad 
99542b6eecSMark Rustad /**
100542b6eecSMark Rustad  * ixgbe_write_cs4227 - Write CS4227 register
101542b6eecSMark Rustad  * @hw: pointer to hardware structure
102542b6eecSMark Rustad  * @reg: register number to write
103542b6eecSMark Rustad  * @value: value to write to register
104542b6eecSMark Rustad  *
105542b6eecSMark Rustad  * Returns status code
106542b6eecSMark Rustad  */
107542b6eecSMark Rustad static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
108542b6eecSMark Rustad {
109b71f6c40SEmil Tantilov 	return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);
110542b6eecSMark Rustad }
111542b6eecSMark Rustad 
112542b6eecSMark Rustad /**
113542b6eecSMark Rustad  * ixgbe_read_pe - Read register from port expander
114542b6eecSMark Rustad  * @hw: pointer to hardware structure
115542b6eecSMark Rustad  * @reg: register number to read
116542b6eecSMark Rustad  * @value: pointer to receive read value
117542b6eecSMark Rustad  *
118542b6eecSMark Rustad  * Returns status code
119542b6eecSMark Rustad  */
120542b6eecSMark Rustad static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value)
121542b6eecSMark Rustad {
122542b6eecSMark Rustad 	s32 status;
123542b6eecSMark Rustad 
124542b6eecSMark Rustad 	status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, value);
125542b6eecSMark Rustad 	if (status)
126542b6eecSMark Rustad 		hw_err(hw, "port expander access failed with %d\n", status);
127542b6eecSMark Rustad 	return status;
128542b6eecSMark Rustad }
129542b6eecSMark Rustad 
130542b6eecSMark Rustad /**
131542b6eecSMark Rustad  * ixgbe_write_pe - Write register to port expander
132542b6eecSMark Rustad  * @hw: pointer to hardware structure
133542b6eecSMark Rustad  * @reg: register number to write
134542b6eecSMark Rustad  * @value: value to write
135542b6eecSMark Rustad  *
136542b6eecSMark Rustad  * Returns status code
137542b6eecSMark Rustad  */
138542b6eecSMark Rustad static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value)
139542b6eecSMark Rustad {
140542b6eecSMark Rustad 	s32 status;
141542b6eecSMark Rustad 
142542b6eecSMark Rustad 	status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE,
143542b6eecSMark Rustad 						       value);
144542b6eecSMark Rustad 	if (status)
145542b6eecSMark Rustad 		hw_err(hw, "port expander access failed with %d\n", status);
146542b6eecSMark Rustad 	return status;
147542b6eecSMark Rustad }
148542b6eecSMark Rustad 
149542b6eecSMark Rustad /**
150542b6eecSMark Rustad  * ixgbe_reset_cs4227 - Reset CS4227 using port expander
151542b6eecSMark Rustad  * @hw: pointer to hardware structure
152542b6eecSMark Rustad  *
1538bf7a7b8SMark Rustad  * This function assumes that the caller has acquired the proper semaphore.
154542b6eecSMark Rustad  * Returns error code
155542b6eecSMark Rustad  */
156542b6eecSMark Rustad static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
157542b6eecSMark Rustad {
158542b6eecSMark Rustad 	s32 status;
159542b6eecSMark Rustad 	u32 retry;
160542b6eecSMark Rustad 	u16 value;
161542b6eecSMark Rustad 	u8 reg;
162542b6eecSMark Rustad 
163542b6eecSMark Rustad 	/* Trigger hard reset. */
164542b6eecSMark Rustad 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
165542b6eecSMark Rustad 	if (status)
166542b6eecSMark Rustad 		return status;
167542b6eecSMark Rustad 	reg |= IXGBE_PE_BIT1;
168542b6eecSMark Rustad 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
169542b6eecSMark Rustad 	if (status)
170542b6eecSMark Rustad 		return status;
171542b6eecSMark Rustad 
172542b6eecSMark Rustad 	status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, &reg);
173542b6eecSMark Rustad 	if (status)
174542b6eecSMark Rustad 		return status;
175542b6eecSMark Rustad 	reg &= ~IXGBE_PE_BIT1;
176542b6eecSMark Rustad 	status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg);
177542b6eecSMark Rustad 	if (status)
178542b6eecSMark Rustad 		return status;
179542b6eecSMark Rustad 
180542b6eecSMark Rustad 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
181542b6eecSMark Rustad 	if (status)
182542b6eecSMark Rustad 		return status;
183542b6eecSMark Rustad 	reg &= ~IXGBE_PE_BIT1;
184542b6eecSMark Rustad 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
185542b6eecSMark Rustad 	if (status)
186542b6eecSMark Rustad 		return status;
187542b6eecSMark Rustad 
188542b6eecSMark Rustad 	usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100);
189542b6eecSMark Rustad 
190542b6eecSMark Rustad 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
191542b6eecSMark Rustad 	if (status)
192542b6eecSMark Rustad 		return status;
193542b6eecSMark Rustad 	reg |= IXGBE_PE_BIT1;
194542b6eecSMark Rustad 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
195542b6eecSMark Rustad 	if (status)
196542b6eecSMark Rustad 		return status;
197542b6eecSMark Rustad 
198542b6eecSMark Rustad 	/* Wait for the reset to complete. */
199542b6eecSMark Rustad 	msleep(IXGBE_CS4227_RESET_DELAY);
200542b6eecSMark Rustad 	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
201542b6eecSMark Rustad 		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
202542b6eecSMark Rustad 					   &value);
203542b6eecSMark Rustad 		if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK)
204542b6eecSMark Rustad 			break;
205542b6eecSMark Rustad 		msleep(IXGBE_CS4227_CHECK_DELAY);
206542b6eecSMark Rustad 	}
207542b6eecSMark Rustad 	if (retry == IXGBE_CS4227_RETRIES) {
208542b6eecSMark Rustad 		hw_err(hw, "CS4227 reset did not complete\n");
209542b6eecSMark Rustad 		return IXGBE_ERR_PHY;
210542b6eecSMark Rustad 	}
211542b6eecSMark Rustad 
212542b6eecSMark Rustad 	status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
213542b6eecSMark Rustad 	if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
214542b6eecSMark Rustad 		hw_err(hw, "CS4227 EEPROM did not load successfully\n");
215542b6eecSMark Rustad 		return IXGBE_ERR_PHY;
216542b6eecSMark Rustad 	}
217542b6eecSMark Rustad 
218542b6eecSMark Rustad 	return 0;
219542b6eecSMark Rustad }
220542b6eecSMark Rustad 
221542b6eecSMark Rustad /**
222542b6eecSMark Rustad  * ixgbe_check_cs4227 - Check CS4227 and reset as needed
223542b6eecSMark Rustad  * @hw: pointer to hardware structure
224542b6eecSMark Rustad  */
225542b6eecSMark Rustad static void ixgbe_check_cs4227(struct ixgbe_hw *hw)
226542b6eecSMark Rustad {
227542b6eecSMark Rustad 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
228542b6eecSMark Rustad 	s32 status;
229542b6eecSMark Rustad 	u16 value;
230542b6eecSMark Rustad 	u8 retry;
231542b6eecSMark Rustad 
232542b6eecSMark Rustad 	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
233542b6eecSMark Rustad 		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
234542b6eecSMark Rustad 		if (status) {
235542b6eecSMark Rustad 			hw_err(hw, "semaphore failed with %d\n", status);
236542b6eecSMark Rustad 			msleep(IXGBE_CS4227_CHECK_DELAY);
237542b6eecSMark Rustad 			continue;
238542b6eecSMark Rustad 		}
239542b6eecSMark Rustad 
240542b6eecSMark Rustad 		/* Get status of reset flow. */
241542b6eecSMark Rustad 		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
242542b6eecSMark Rustad 		if (!status && value == IXGBE_CS4227_RESET_COMPLETE)
243542b6eecSMark Rustad 			goto out;
244542b6eecSMark Rustad 
245542b6eecSMark Rustad 		if (status || value != IXGBE_CS4227_RESET_PENDING)
246542b6eecSMark Rustad 			break;
247542b6eecSMark Rustad 
248542b6eecSMark Rustad 		/* Reset is pending. Wait and check again. */
249542b6eecSMark Rustad 		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
250542b6eecSMark Rustad 		msleep(IXGBE_CS4227_CHECK_DELAY);
251542b6eecSMark Rustad 	}
2528bf7a7b8SMark Rustad 	/* If still pending, assume other instance failed. */
2538bf7a7b8SMark Rustad 	if (retry == IXGBE_CS4227_RETRIES) {
2548bf7a7b8SMark Rustad 		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
2558bf7a7b8SMark Rustad 		if (status) {
2568bf7a7b8SMark Rustad 			hw_err(hw, "semaphore failed with %d\n", status);
2578bf7a7b8SMark Rustad 			return;
2588bf7a7b8SMark Rustad 		}
2598bf7a7b8SMark Rustad 	}
260542b6eecSMark Rustad 
261542b6eecSMark Rustad 	/* Reset the CS4227. */
262542b6eecSMark Rustad 	status = ixgbe_reset_cs4227(hw);
263542b6eecSMark Rustad 	if (status) {
264542b6eecSMark Rustad 		hw_err(hw, "CS4227 reset failed: %d", status);
265542b6eecSMark Rustad 		goto out;
266542b6eecSMark Rustad 	}
267542b6eecSMark Rustad 
268542b6eecSMark Rustad 	/* Reset takes so long, temporarily release semaphore in case the
269542b6eecSMark Rustad 	 * other driver instance is waiting for the reset indication.
270542b6eecSMark Rustad 	 */
271542b6eecSMark Rustad 	ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
272542b6eecSMark Rustad 			   IXGBE_CS4227_RESET_PENDING);
273542b6eecSMark Rustad 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
274542b6eecSMark Rustad 	usleep_range(10000, 12000);
275542b6eecSMark Rustad 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
276542b6eecSMark Rustad 	if (status) {
277542b6eecSMark Rustad 		hw_err(hw, "semaphore failed with %d", status);
278542b6eecSMark Rustad 		return;
279542b6eecSMark Rustad 	}
280542b6eecSMark Rustad 
281542b6eecSMark Rustad 	/* Record completion for next time. */
282542b6eecSMark Rustad 	status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
283542b6eecSMark Rustad 				    IXGBE_CS4227_RESET_COMPLETE);
284542b6eecSMark Rustad 
285542b6eecSMark Rustad out:
286542b6eecSMark Rustad 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
287542b6eecSMark Rustad 	msleep(hw->eeprom.semaphore_delay);
288542b6eecSMark Rustad }
289542b6eecSMark Rustad 
2906a14ee0cSDon Skidmore /** ixgbe_identify_phy_x550em - Get PHY type based on device id
2916a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
2926a14ee0cSDon Skidmore  *
2936a14ee0cSDon Skidmore  *  Returns error code
2946a14ee0cSDon Skidmore  */
2956a14ee0cSDon Skidmore static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
2966a14ee0cSDon Skidmore {
2976a14ee0cSDon Skidmore 	switch (hw->device_id) {
2982d40cd17SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP:
2992d40cd17SMark Rustad 		if (hw->bus.lan_id)
3002d40cd17SMark Rustad 			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
3012d40cd17SMark Rustad 		else
3022d40cd17SMark Rustad 			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
3032d40cd17SMark Rustad 		return ixgbe_identify_module_generic(hw);
3046a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_SFP:
3056a14ee0cSDon Skidmore 		/* set up for CS4227 usage */
3066a14ee0cSDon Skidmore 		hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
307ab5fe0c5SDon Skidmore 		ixgbe_setup_mux_ctl(hw);
308542b6eecSMark Rustad 		ixgbe_check_cs4227(hw);
3095463fce6SJeff Kirsher 		fallthrough;
31049425dfcSMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP_N:
3116a14ee0cSDon Skidmore 		return ixgbe_identify_module_generic(hw);
3126a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_KX4:
3136a14ee0cSDon Skidmore 		hw->phy.type = ixgbe_phy_x550em_kx4;
3146a14ee0cSDon Skidmore 		break;
31518e01ee7SDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_XFI:
31618e01ee7SDon Skidmore 		hw->phy.type = ixgbe_phy_x550em_xfi;
31718e01ee7SDon Skidmore 		break;
3186a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_KR:
319f572b2c4SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_KR:
320f572b2c4SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_KR_L:
3216a14ee0cSDon Skidmore 		hw->phy.type = ixgbe_phy_x550em_kr;
3226a14ee0cSDon Skidmore 		break;
32392ed8430SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_10G_T:
32492ed8430SDon Skidmore 		if (hw->bus.lan_id)
32592ed8430SDon Skidmore 			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
32692ed8430SDon Skidmore 		else
32792ed8430SDon Skidmore 			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
3285463fce6SJeff Kirsher 		fallthrough;
3296a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_10G_T:
3306a14ee0cSDon Skidmore 		return ixgbe_identify_phy_generic(hw);
3318dc963e1SPaul Greenwalt 	case IXGBE_DEV_ID_X550EM_X_1G_T:
3328dc963e1SPaul Greenwalt 		hw->phy.type = ixgbe_phy_ext_1g_t;
3338dc963e1SPaul Greenwalt 		break;
33418bda0d9SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_1G_T:
33518bda0d9SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
33618bda0d9SDon Skidmore 		hw->phy.type = ixgbe_phy_fw;
33718bda0d9SDon Skidmore 		hw->phy.ops.read_reg = NULL;
33818bda0d9SDon Skidmore 		hw->phy.ops.write_reg = NULL;
33918bda0d9SDon Skidmore 		if (hw->bus.lan_id)
34018bda0d9SDon Skidmore 			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
34118bda0d9SDon Skidmore 		else
34218bda0d9SDon Skidmore 			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
34318bda0d9SDon Skidmore 		break;
3446a14ee0cSDon Skidmore 	default:
3456a14ee0cSDon Skidmore 		break;
3466a14ee0cSDon Skidmore 	}
3476a14ee0cSDon Skidmore 	return 0;
3486a14ee0cSDon Skidmore }
3496a14ee0cSDon Skidmore 
3506a14ee0cSDon Skidmore static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
3516a14ee0cSDon Skidmore 				     u32 device_type, u16 *phy_data)
3526a14ee0cSDon Skidmore {
3536a14ee0cSDon Skidmore 	return IXGBE_NOT_IMPLEMENTED;
3546a14ee0cSDon Skidmore }
3556a14ee0cSDon Skidmore 
3566a14ee0cSDon Skidmore static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
3576a14ee0cSDon Skidmore 				      u32 device_type, u16 phy_data)
3586a14ee0cSDon Skidmore {
3596a14ee0cSDon Skidmore 	return IXGBE_NOT_IMPLEMENTED;
3606a14ee0cSDon Skidmore }
3616a14ee0cSDon Skidmore 
362b71f6c40SEmil Tantilov /**
363b71f6c40SEmil Tantilov  * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
364b71f6c40SEmil Tantilov  * @hw: pointer to the hardware structure
365b71f6c40SEmil Tantilov  * @addr: I2C bus address to read from
366b71f6c40SEmil Tantilov  * @reg: I2C device register to read from
367b71f6c40SEmil Tantilov  * @val: pointer to location to receive read value
368b71f6c40SEmil Tantilov  *
369b71f6c40SEmil Tantilov  * Returns an error code on error.
370b71f6c40SEmil Tantilov  **/
371b71f6c40SEmil Tantilov static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
372b71f6c40SEmil Tantilov 					   u16 reg, u16 *val)
373b71f6c40SEmil Tantilov {
374b71f6c40SEmil Tantilov 	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true);
375b71f6c40SEmil Tantilov }
376b71f6c40SEmil Tantilov 
377b71f6c40SEmil Tantilov /**
378b71f6c40SEmil Tantilov  * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
379b71f6c40SEmil Tantilov  * @hw: pointer to the hardware structure
380b71f6c40SEmil Tantilov  * @addr: I2C bus address to read from
381b71f6c40SEmil Tantilov  * @reg: I2C device register to read from
382b71f6c40SEmil Tantilov  * @val: pointer to location to receive read value
383b71f6c40SEmil Tantilov  *
384b71f6c40SEmil Tantilov  * Returns an error code on error.
385b71f6c40SEmil Tantilov  **/
386b71f6c40SEmil Tantilov static s32
387b71f6c40SEmil Tantilov ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
388b71f6c40SEmil Tantilov 					 u16 reg, u16 *val)
389b71f6c40SEmil Tantilov {
390b71f6c40SEmil Tantilov 	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false);
391b71f6c40SEmil Tantilov }
392b71f6c40SEmil Tantilov 
393b71f6c40SEmil Tantilov /**
394b71f6c40SEmil Tantilov  * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
395b71f6c40SEmil Tantilov  * @hw: pointer to the hardware structure
396b71f6c40SEmil Tantilov  * @addr: I2C bus address to write to
397b71f6c40SEmil Tantilov  * @reg: I2C device register to write to
398b71f6c40SEmil Tantilov  * @val: value to write
399b71f6c40SEmil Tantilov  *
400b71f6c40SEmil Tantilov  * Returns an error code on error.
401b71f6c40SEmil Tantilov  **/
402b71f6c40SEmil Tantilov static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
403b71f6c40SEmil Tantilov 					    u8 addr, u16 reg, u16 val)
404b71f6c40SEmil Tantilov {
405b71f6c40SEmil Tantilov 	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
406b71f6c40SEmil Tantilov }
407b71f6c40SEmil Tantilov 
408b71f6c40SEmil Tantilov /**
409b71f6c40SEmil Tantilov  * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
410b71f6c40SEmil Tantilov  * @hw: pointer to the hardware structure
411b71f6c40SEmil Tantilov  * @addr: I2C bus address to write to
412b71f6c40SEmil Tantilov  * @reg: I2C device register to write to
413b71f6c40SEmil Tantilov  * @val: value to write
414b71f6c40SEmil Tantilov  *
415b71f6c40SEmil Tantilov  * Returns an error code on error.
416b71f6c40SEmil Tantilov  **/
417b71f6c40SEmil Tantilov static s32
418b71f6c40SEmil Tantilov ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
419b71f6c40SEmil Tantilov 					  u8 addr, u16 reg, u16 val)
420b71f6c40SEmil Tantilov {
421b71f6c40SEmil Tantilov 	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false);
422b71f6c40SEmil Tantilov }
423b71f6c40SEmil Tantilov 
42412c78ef0SMark Rustad /**
42512c78ef0SMark Rustad  * ixgbe_fw_phy_activity - Perform an activity on a PHY
42612c78ef0SMark Rustad  * @hw: pointer to hardware structure
42712c78ef0SMark Rustad  * @activity: activity to perform
42812c78ef0SMark Rustad  * @data: Pointer to 4 32-bit words of data
42912c78ef0SMark Rustad  */
43012c78ef0SMark Rustad s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity,
43112c78ef0SMark Rustad 			  u32 (*data)[FW_PHY_ACT_DATA_COUNT])
43212c78ef0SMark Rustad {
43312c78ef0SMark Rustad 	union {
43412c78ef0SMark Rustad 		struct ixgbe_hic_phy_activity_req cmd;
43512c78ef0SMark Rustad 		struct ixgbe_hic_phy_activity_resp rsp;
43612c78ef0SMark Rustad 	} hic;
43712c78ef0SMark Rustad 	u16 retries = FW_PHY_ACT_RETRIES;
43812c78ef0SMark Rustad 	s32 rc;
43912c78ef0SMark Rustad 	u32 i;
44012c78ef0SMark Rustad 
44112c78ef0SMark Rustad 	do {
44212c78ef0SMark Rustad 		memset(&hic, 0, sizeof(hic));
44312c78ef0SMark Rustad 		hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD;
44412c78ef0SMark Rustad 		hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN;
44512c78ef0SMark Rustad 		hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
44612c78ef0SMark Rustad 		hic.cmd.port_number = hw->bus.lan_id;
44712c78ef0SMark Rustad 		hic.cmd.activity_id = cpu_to_le16(activity);
44812c78ef0SMark Rustad 		for (i = 0; i < ARRAY_SIZE(hic.cmd.data); ++i)
44912c78ef0SMark Rustad 			hic.cmd.data[i] = cpu_to_be32((*data)[i]);
45012c78ef0SMark Rustad 
45112c78ef0SMark Rustad 		rc = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd),
45212c78ef0SMark Rustad 						  IXGBE_HI_COMMAND_TIMEOUT,
45312c78ef0SMark Rustad 						  true);
45412c78ef0SMark Rustad 		if (rc)
45512c78ef0SMark Rustad 			return rc;
45612c78ef0SMark Rustad 		if (hic.rsp.hdr.cmd_or_resp.ret_status ==
45712c78ef0SMark Rustad 		    FW_CEM_RESP_STATUS_SUCCESS) {
45812c78ef0SMark Rustad 			for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
45912c78ef0SMark Rustad 				(*data)[i] = be32_to_cpu(hic.rsp.data[i]);
46012c78ef0SMark Rustad 			return 0;
46112c78ef0SMark Rustad 		}
46212c78ef0SMark Rustad 		usleep_range(20, 30);
46312c78ef0SMark Rustad 		--retries;
46412c78ef0SMark Rustad 	} while (retries > 0);
46512c78ef0SMark Rustad 
46612c78ef0SMark Rustad 	return IXGBE_ERR_HOST_INTERFACE_COMMAND;
46712c78ef0SMark Rustad }
46812c78ef0SMark Rustad 
469b3eb4e18SMark Rustad static const struct {
470b3eb4e18SMark Rustad 	u16 fw_speed;
471b3eb4e18SMark Rustad 	ixgbe_link_speed phy_speed;
472b3eb4e18SMark Rustad } ixgbe_fw_map[] = {
473b3eb4e18SMark Rustad 	{ FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL },
474b3eb4e18SMark Rustad 	{ FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL },
475b3eb4e18SMark Rustad 	{ FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL },
476b3eb4e18SMark Rustad 	{ FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL },
477b3eb4e18SMark Rustad 	{ FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL },
478b3eb4e18SMark Rustad 	{ FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL },
479b3eb4e18SMark Rustad };
480b3eb4e18SMark Rustad 
481b3eb4e18SMark Rustad /**
482b3eb4e18SMark Rustad  * ixgbe_get_phy_id_fw - Get the phy ID via firmware command
483b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
484b3eb4e18SMark Rustad  *
485b3eb4e18SMark Rustad  * Returns error code
486b3eb4e18SMark Rustad  */
487b3eb4e18SMark Rustad static s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw)
488b3eb4e18SMark Rustad {
489b3eb4e18SMark Rustad 	u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
490b3eb4e18SMark Rustad 	u16 phy_speeds;
491b3eb4e18SMark Rustad 	u16 phy_id_lo;
492b3eb4e18SMark Rustad 	s32 rc;
493b3eb4e18SMark Rustad 	u16 i;
494b3eb4e18SMark Rustad 
495b3eb4e18SMark Rustad 	if (hw->phy.id)
496b3eb4e18SMark Rustad 		return 0;
497b3eb4e18SMark Rustad 
498b3eb4e18SMark Rustad 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info);
499b3eb4e18SMark Rustad 	if (rc)
500b3eb4e18SMark Rustad 		return rc;
501b3eb4e18SMark Rustad 
502b3eb4e18SMark Rustad 	hw->phy.speeds_supported = 0;
503b3eb4e18SMark Rustad 	phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK;
504b3eb4e18SMark Rustad 	for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) {
505b3eb4e18SMark Rustad 		if (phy_speeds & ixgbe_fw_map[i].fw_speed)
506b3eb4e18SMark Rustad 			hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed;
507b3eb4e18SMark Rustad 	}
508b3eb4e18SMark Rustad 
509b3eb4e18SMark Rustad 	hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK;
510b3eb4e18SMark Rustad 	phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK;
511b3eb4e18SMark Rustad 	hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK;
512b3eb4e18SMark Rustad 	hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK;
513b3eb4e18SMark Rustad 	if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK)
514b3eb4e18SMark Rustad 		return IXGBE_ERR_PHY_ADDR_INVALID;
515b3eb4e18SMark Rustad 
516b3eb4e18SMark Rustad 	hw->phy.autoneg_advertised = hw->phy.speeds_supported;
517b3eb4e18SMark Rustad 	hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL |
518b3eb4e18SMark Rustad 				       IXGBE_LINK_SPEED_1GB_FULL;
519b3eb4e18SMark Rustad 	hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
520b3eb4e18SMark Rustad 	return 0;
521b3eb4e18SMark Rustad }
522b3eb4e18SMark Rustad 
523b3eb4e18SMark Rustad /**
524b3eb4e18SMark Rustad  * ixgbe_identify_phy_fw - Get PHY type based on firmware command
525b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
526b3eb4e18SMark Rustad  *
527b3eb4e18SMark Rustad  * Returns error code
528b3eb4e18SMark Rustad  */
529b3eb4e18SMark Rustad static s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw)
530b3eb4e18SMark Rustad {
531b3eb4e18SMark Rustad 	if (hw->bus.lan_id)
532b3eb4e18SMark Rustad 		hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
533b3eb4e18SMark Rustad 	else
534b3eb4e18SMark Rustad 		hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
535b3eb4e18SMark Rustad 
536b3eb4e18SMark Rustad 	hw->phy.type = ixgbe_phy_fw;
537b3eb4e18SMark Rustad 	hw->phy.ops.read_reg = NULL;
538b3eb4e18SMark Rustad 	hw->phy.ops.write_reg = NULL;
539b3eb4e18SMark Rustad 	return ixgbe_get_phy_id_fw(hw);
540b3eb4e18SMark Rustad }
541b3eb4e18SMark Rustad 
542b3eb4e18SMark Rustad /**
543b3eb4e18SMark Rustad  * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY
544b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
545b3eb4e18SMark Rustad  *
546b3eb4e18SMark Rustad  * Returns error code
547b3eb4e18SMark Rustad  */
548b3eb4e18SMark Rustad static s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw)
549b3eb4e18SMark Rustad {
550b3eb4e18SMark Rustad 	u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
551b3eb4e18SMark Rustad 
552b3eb4e18SMark Rustad 	setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF;
553b3eb4e18SMark Rustad 	return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup);
554b3eb4e18SMark Rustad }
555b3eb4e18SMark Rustad 
556b3eb4e18SMark Rustad /**
557b3eb4e18SMark Rustad  * ixgbe_setup_fw_link - Setup firmware-controlled PHYs
558b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
559b3eb4e18SMark Rustad  */
560b3eb4e18SMark Rustad static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw)
561b3eb4e18SMark Rustad {
562b3eb4e18SMark Rustad 	u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
563b3eb4e18SMark Rustad 	s32 rc;
564b3eb4e18SMark Rustad 	u16 i;
565b3eb4e18SMark Rustad 
566b3eb4e18SMark Rustad 	if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
567b3eb4e18SMark Rustad 		return 0;
568b3eb4e18SMark Rustad 
569b3eb4e18SMark Rustad 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
570b3eb4e18SMark Rustad 		hw_err(hw, "rx_pause not valid in strict IEEE mode\n");
571b3eb4e18SMark Rustad 		return IXGBE_ERR_INVALID_LINK_SETTINGS;
572b3eb4e18SMark Rustad 	}
573b3eb4e18SMark Rustad 
574b3eb4e18SMark Rustad 	switch (hw->fc.requested_mode) {
575b3eb4e18SMark Rustad 	case ixgbe_fc_full:
576b3eb4e18SMark Rustad 		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX <<
577b3eb4e18SMark Rustad 			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
578b3eb4e18SMark Rustad 		break;
579b3eb4e18SMark Rustad 	case ixgbe_fc_rx_pause:
580b3eb4e18SMark Rustad 		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX <<
581b3eb4e18SMark Rustad 			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
582b3eb4e18SMark Rustad 		break;
583b3eb4e18SMark Rustad 	case ixgbe_fc_tx_pause:
584b3eb4e18SMark Rustad 		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX <<
585b3eb4e18SMark Rustad 			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
586b3eb4e18SMark Rustad 		break;
587b3eb4e18SMark Rustad 	default:
588b3eb4e18SMark Rustad 		break;
589b3eb4e18SMark Rustad 	}
590b3eb4e18SMark Rustad 
591b3eb4e18SMark Rustad 	for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) {
592b3eb4e18SMark Rustad 		if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed)
593b3eb4e18SMark Rustad 			setup[0] |= ixgbe_fw_map[i].fw_speed;
594b3eb4e18SMark Rustad 	}
595b3eb4e18SMark Rustad 	setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN;
596b3eb4e18SMark Rustad 
597b3eb4e18SMark Rustad 	if (hw->phy.eee_speeds_advertised)
598b3eb4e18SMark Rustad 		setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE;
599b3eb4e18SMark Rustad 
600b3eb4e18SMark Rustad 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);
601b3eb4e18SMark Rustad 	if (rc)
602b3eb4e18SMark Rustad 		return rc;
603b3eb4e18SMark Rustad 	if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
604b3eb4e18SMark Rustad 		return IXGBE_ERR_OVERTEMP;
605b3eb4e18SMark Rustad 	return 0;
606b3eb4e18SMark Rustad }
607b3eb4e18SMark Rustad 
608b3eb4e18SMark Rustad /**
609b3eb4e18SMark Rustad  * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs
610b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
611b3eb4e18SMark Rustad  *
612b3eb4e18SMark Rustad  * Called at init time to set up flow control.
613b3eb4e18SMark Rustad  */
614b3eb4e18SMark Rustad static s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw)
615b3eb4e18SMark Rustad {
616b3eb4e18SMark Rustad 	if (hw->fc.requested_mode == ixgbe_fc_default)
617b3eb4e18SMark Rustad 		hw->fc.requested_mode = ixgbe_fc_full;
618b3eb4e18SMark Rustad 
619b3eb4e18SMark Rustad 	return ixgbe_setup_fw_link(hw);
620b3eb4e18SMark Rustad }
621b3eb4e18SMark Rustad 
6226a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params
6236a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
6246a14ee0cSDon Skidmore  *
6256a14ee0cSDon Skidmore  *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
6266a14ee0cSDon Skidmore  *  ixgbe_hw struct in order to set up EEPROM access.
6276a14ee0cSDon Skidmore  **/
6287ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
6296a14ee0cSDon Skidmore {
6306a14ee0cSDon Skidmore 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
6316a14ee0cSDon Skidmore 	u32 eec;
6326a14ee0cSDon Skidmore 	u16 eeprom_size;
6336a14ee0cSDon Skidmore 
6346a14ee0cSDon Skidmore 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
6356a14ee0cSDon Skidmore 		eeprom->semaphore_delay = 10;
6366a14ee0cSDon Skidmore 		eeprom->type = ixgbe_flash;
6376a14ee0cSDon Skidmore 
6389a900ecaSDon Skidmore 		eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
6396a14ee0cSDon Skidmore 		eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
6406a14ee0cSDon Skidmore 				    IXGBE_EEC_SIZE_SHIFT);
641b4f47a48SJacob Keller 		eeprom->word_size = BIT(eeprom_size +
6426a14ee0cSDon Skidmore 					IXGBE_EEPROM_WORD_SIZE_SHIFT);
6436a14ee0cSDon Skidmore 
6446a14ee0cSDon Skidmore 		hw_dbg(hw, "Eeprom params: type = %d, size = %d\n",
6456a14ee0cSDon Skidmore 		       eeprom->type, eeprom->word_size);
6466a14ee0cSDon Skidmore 	}
6476a14ee0cSDon Skidmore 
6486a14ee0cSDon Skidmore 	return 0;
6496a14ee0cSDon Skidmore }
6506a14ee0cSDon Skidmore 
651ae14a1d8SMark Rustad /**
652ae14a1d8SMark Rustad  * ixgbe_iosf_wait - Wait for IOSF command completion
653ae14a1d8SMark Rustad  * @hw: pointer to hardware structure
654ae14a1d8SMark Rustad  * @ctrl: pointer to location to receive final IOSF control value
655ae14a1d8SMark Rustad  *
656ae14a1d8SMark Rustad  * Return: failing status on timeout
657ae14a1d8SMark Rustad  *
658ae14a1d8SMark Rustad  * Note: ctrl can be NULL if the IOSF control register value is not needed
659ae14a1d8SMark Rustad  */
660ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl)
661ae14a1d8SMark Rustad {
662ae14a1d8SMark Rustad 	u32 i, command;
663ae14a1d8SMark Rustad 
664ae14a1d8SMark Rustad 	/* Check every 10 usec to see if the address cycle completed.
665ae14a1d8SMark Rustad 	 * The SB IOSF BUSY bit will clear when the operation is
666ae14a1d8SMark Rustad 	 * complete.
667ae14a1d8SMark Rustad 	 */
668ae14a1d8SMark Rustad 	for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
669ae14a1d8SMark Rustad 		command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
670ae14a1d8SMark Rustad 		if (!(command & IXGBE_SB_IOSF_CTRL_BUSY))
671ae14a1d8SMark Rustad 			break;
672d90b5b0eSMark Rustad 		udelay(10);
673ae14a1d8SMark Rustad 	}
674ae14a1d8SMark Rustad 	if (ctrl)
675ae14a1d8SMark Rustad 		*ctrl = command;
676ae14a1d8SMark Rustad 	if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
677ae14a1d8SMark Rustad 		hw_dbg(hw, "IOSF wait timed out\n");
678ae14a1d8SMark Rustad 		return IXGBE_ERR_PHY;
679ae14a1d8SMark Rustad 	}
680ae14a1d8SMark Rustad 
681ae14a1d8SMark Rustad 	return 0;
682ae14a1d8SMark Rustad }
683ae14a1d8SMark Rustad 
6846a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the
6856a14ee0cSDon Skidmore  *  IOSF device
6866a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
6876a14ee0cSDon Skidmore  *  @reg_addr: 32 bit PHY register to write
6886a14ee0cSDon Skidmore  *  @device_type: 3 bit device type
6896a14ee0cSDon Skidmore  *  @phy_data: Pointer to read data from the register
6906a14ee0cSDon Skidmore  **/
6917ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
6926a14ee0cSDon Skidmore 				       u32 device_type, u32 *data)
6936a14ee0cSDon Skidmore {
694ae14a1d8SMark Rustad 	u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
695ae14a1d8SMark Rustad 	u32 command, error;
696ae14a1d8SMark Rustad 	s32 ret;
697ae14a1d8SMark Rustad 
698ae14a1d8SMark Rustad 	ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
699ae14a1d8SMark Rustad 	if (ret)
700ae14a1d8SMark Rustad 		return ret;
701ae14a1d8SMark Rustad 
702ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, NULL);
703ae14a1d8SMark Rustad 	if (ret)
704ae14a1d8SMark Rustad 		goto out;
7056a14ee0cSDon Skidmore 
7066a14ee0cSDon Skidmore 	command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
7076a14ee0cSDon Skidmore 		   (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
7086a14ee0cSDon Skidmore 
7096a14ee0cSDon Skidmore 	/* Write IOSF control register */
7106a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
7116a14ee0cSDon Skidmore 
712ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, &command);
7136a14ee0cSDon Skidmore 
7146a14ee0cSDon Skidmore 	if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
7156a14ee0cSDon Skidmore 		error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
7166a14ee0cSDon Skidmore 			 IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
7176a14ee0cSDon Skidmore 		hw_dbg(hw, "Failed to read, error %x\n", error);
7186a14ee0cSDon Skidmore 		return IXGBE_ERR_PHY;
7196a14ee0cSDon Skidmore 	}
7206a14ee0cSDon Skidmore 
721ae14a1d8SMark Rustad 	if (!ret)
7226a14ee0cSDon Skidmore 		*data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
7236a14ee0cSDon Skidmore 
724ae14a1d8SMark Rustad out:
725ae14a1d8SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, gssr);
726ae14a1d8SMark Rustad 	return ret;
7276a14ee0cSDon Skidmore }
7286a14ee0cSDon Skidmore 
72949425dfcSMark Rustad /**
73049425dfcSMark Rustad  * ixgbe_get_phy_token - Get the token for shared PHY access
73149425dfcSMark Rustad  * @hw: Pointer to hardware structure
73249425dfcSMark Rustad  */
73349425dfcSMark Rustad static s32 ixgbe_get_phy_token(struct ixgbe_hw *hw)
73449425dfcSMark Rustad {
73549425dfcSMark Rustad 	struct ixgbe_hic_phy_token_req token_cmd;
73649425dfcSMark Rustad 	s32 status;
73749425dfcSMark Rustad 
73849425dfcSMark Rustad 	token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
73949425dfcSMark Rustad 	token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
74049425dfcSMark Rustad 	token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
74149425dfcSMark Rustad 	token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
74249425dfcSMark Rustad 	token_cmd.port_number = hw->bus.lan_id;
74349425dfcSMark Rustad 	token_cmd.command_type = FW_PHY_TOKEN_REQ;
74449425dfcSMark Rustad 	token_cmd.pad = 0;
74549425dfcSMark Rustad 	status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd),
74649425dfcSMark Rustad 					      IXGBE_HI_COMMAND_TIMEOUT,
74749425dfcSMark Rustad 					      true);
74849425dfcSMark Rustad 	if (status)
74949425dfcSMark Rustad 		return status;
75049425dfcSMark Rustad 	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
75149425dfcSMark Rustad 		return 0;
75249425dfcSMark Rustad 	if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY)
75349425dfcSMark Rustad 		return IXGBE_ERR_FW_RESP_INVALID;
75449425dfcSMark Rustad 
75549425dfcSMark Rustad 	return IXGBE_ERR_TOKEN_RETRY;
75649425dfcSMark Rustad }
75749425dfcSMark Rustad 
75849425dfcSMark Rustad /**
75949425dfcSMark Rustad  * ixgbe_put_phy_token - Put the token for shared PHY access
76049425dfcSMark Rustad  * @hw: Pointer to hardware structure
76149425dfcSMark Rustad  */
76249425dfcSMark Rustad static s32 ixgbe_put_phy_token(struct ixgbe_hw *hw)
76349425dfcSMark Rustad {
76449425dfcSMark Rustad 	struct ixgbe_hic_phy_token_req token_cmd;
76549425dfcSMark Rustad 	s32 status;
76649425dfcSMark Rustad 
76749425dfcSMark Rustad 	token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
76849425dfcSMark Rustad 	token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
76949425dfcSMark Rustad 	token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
77049425dfcSMark Rustad 	token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
77149425dfcSMark Rustad 	token_cmd.port_number = hw->bus.lan_id;
77249425dfcSMark Rustad 	token_cmd.command_type = FW_PHY_TOKEN_REL;
77349425dfcSMark Rustad 	token_cmd.pad = 0;
77449425dfcSMark Rustad 	status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd),
77549425dfcSMark Rustad 					      IXGBE_HI_COMMAND_TIMEOUT,
77649425dfcSMark Rustad 					      true);
77749425dfcSMark Rustad 	if (status)
77849425dfcSMark Rustad 		return status;
77949425dfcSMark Rustad 	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
78049425dfcSMark Rustad 		return 0;
78149425dfcSMark Rustad 	return IXGBE_ERR_FW_RESP_INVALID;
78249425dfcSMark Rustad }
78349425dfcSMark Rustad 
78449425dfcSMark Rustad /**
78549425dfcSMark Rustad  *  ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register
78649425dfcSMark Rustad  *  @hw: pointer to hardware structure
78749425dfcSMark Rustad  *  @reg_addr: 32 bit PHY register to write
78849425dfcSMark Rustad  *  @device_type: 3 bit device type
78949425dfcSMark Rustad  *  @data: Data to write to the register
79049425dfcSMark Rustad  **/
79149425dfcSMark Rustad static s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
79249425dfcSMark Rustad 					 __always_unused u32 device_type,
79349425dfcSMark Rustad 					 u32 data)
79449425dfcSMark Rustad {
79549425dfcSMark Rustad 	struct ixgbe_hic_internal_phy_req write_cmd;
79649425dfcSMark Rustad 
79749425dfcSMark Rustad 	memset(&write_cmd, 0, sizeof(write_cmd));
79849425dfcSMark Rustad 	write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD;
79949425dfcSMark Rustad 	write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN;
80049425dfcSMark Rustad 	write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
80149425dfcSMark Rustad 	write_cmd.port_number = hw->bus.lan_id;
80249425dfcSMark Rustad 	write_cmd.command_type = FW_INT_PHY_REQ_WRITE;
80349425dfcSMark Rustad 	write_cmd.address = cpu_to_be16(reg_addr);
80449425dfcSMark Rustad 	write_cmd.write_data = cpu_to_be32(data);
80549425dfcSMark Rustad 
80649425dfcSMark Rustad 	return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd),
80749425dfcSMark Rustad 					    IXGBE_HI_COMMAND_TIMEOUT, false);
80849425dfcSMark Rustad }
80949425dfcSMark Rustad 
81049425dfcSMark Rustad /**
81149425dfcSMark Rustad  *  ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register
81249425dfcSMark Rustad  *  @hw: pointer to hardware structure
81349425dfcSMark Rustad  *  @reg_addr: 32 bit PHY register to write
81449425dfcSMark Rustad  *  @device_type: 3 bit device type
81549425dfcSMark Rustad  *  @data: Pointer to read data from the register
81649425dfcSMark Rustad  **/
81749425dfcSMark Rustad static s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
81849425dfcSMark Rustad 					__always_unused u32 device_type,
81949425dfcSMark Rustad 					u32 *data)
82049425dfcSMark Rustad {
82149425dfcSMark Rustad 	union {
82249425dfcSMark Rustad 		struct ixgbe_hic_internal_phy_req cmd;
82349425dfcSMark Rustad 		struct ixgbe_hic_internal_phy_resp rsp;
82449425dfcSMark Rustad 	} hic;
82549425dfcSMark Rustad 	s32 status;
82649425dfcSMark Rustad 
82749425dfcSMark Rustad 	memset(&hic, 0, sizeof(hic));
82849425dfcSMark Rustad 	hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD;
82949425dfcSMark Rustad 	hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN;
83049425dfcSMark Rustad 	hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
83149425dfcSMark Rustad 	hic.cmd.port_number = hw->bus.lan_id;
83249425dfcSMark Rustad 	hic.cmd.command_type = FW_INT_PHY_REQ_READ;
83349425dfcSMark Rustad 	hic.cmd.address = cpu_to_be16(reg_addr);
83449425dfcSMark Rustad 
83549425dfcSMark Rustad 	status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd),
83649425dfcSMark Rustad 					      IXGBE_HI_COMMAND_TIMEOUT, true);
83749425dfcSMark Rustad 
83849425dfcSMark Rustad 	/* Extract the register value from the response. */
83949425dfcSMark Rustad 	*data = be32_to_cpu(hic.rsp.read_data);
84049425dfcSMark Rustad 
84149425dfcSMark Rustad 	return status;
84249425dfcSMark Rustad }
84349425dfcSMark Rustad 
8446a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif
8456a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
8466a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to read
8476a14ee0cSDon Skidmore  *  @words: number of words
8486a14ee0cSDon Skidmore  *  @data: word(s) read from the EEPROM
8496a14ee0cSDon Skidmore  *
8506a14ee0cSDon Skidmore  *  Reads a 16 bit word(s) from the EEPROM using the hostif.
8516a14ee0cSDon Skidmore  **/
8527ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
8536a14ee0cSDon Skidmore 					    u16 offset, u16 words, u16 *data)
8546a14ee0cSDon Skidmore {
8553efa9ed2SMark Rustad 	const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
8566a14ee0cSDon Skidmore 	struct ixgbe_hic_read_shadow_ram buffer;
8576a14ee0cSDon Skidmore 	u32 current_word = 0;
8586a14ee0cSDon Skidmore 	u16 words_to_read;
8596a14ee0cSDon Skidmore 	s32 status;
8606a14ee0cSDon Skidmore 	u32 i;
8616a14ee0cSDon Skidmore 
8626a14ee0cSDon Skidmore 	/* Take semaphore for the entire operation. */
8633efa9ed2SMark Rustad 	status = hw->mac.ops.acquire_swfw_sync(hw, mask);
8646a14ee0cSDon Skidmore 	if (status) {
8656a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM read buffer - semaphore failed\n");
8666a14ee0cSDon Skidmore 		return status;
8676a14ee0cSDon Skidmore 	}
8686a14ee0cSDon Skidmore 
8696a14ee0cSDon Skidmore 	while (words) {
8706a14ee0cSDon Skidmore 		if (words > FW_MAX_READ_BUFFER_SIZE / 2)
8716a14ee0cSDon Skidmore 			words_to_read = FW_MAX_READ_BUFFER_SIZE / 2;
8726a14ee0cSDon Skidmore 		else
8736a14ee0cSDon Skidmore 			words_to_read = words;
8746a14ee0cSDon Skidmore 
8756a14ee0cSDon Skidmore 		buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
8766a14ee0cSDon Skidmore 		buffer.hdr.req.buf_lenh = 0;
8776a14ee0cSDon Skidmore 		buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
8786a14ee0cSDon Skidmore 		buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
8796a14ee0cSDon Skidmore 
8806a14ee0cSDon Skidmore 		/* convert offset from words to bytes */
8819cfbfa70SCathy Zhou 		buffer.address = (__force u32)cpu_to_be32((offset +
8829cfbfa70SCathy Zhou 							   current_word) * 2);
8839cfbfa70SCathy Zhou 		buffer.length = (__force u16)cpu_to_be16(words_to_read * 2);
884dcfd6b83SEmil Tantilov 		buffer.pad2 = 0;
885dcfd6b83SEmil Tantilov 		buffer.pad3 = 0;
8866a14ee0cSDon Skidmore 
8873efa9ed2SMark Rustad 		status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
8883efa9ed2SMark Rustad 					    IXGBE_HI_COMMAND_TIMEOUT);
8896a14ee0cSDon Skidmore 		if (status) {
8906a14ee0cSDon Skidmore 			hw_dbg(hw, "Host interface command failed\n");
8916a14ee0cSDon Skidmore 			goto out;
8926a14ee0cSDon Skidmore 		}
8936a14ee0cSDon Skidmore 
8946a14ee0cSDon Skidmore 		for (i = 0; i < words_to_read; i++) {
8956a14ee0cSDon Skidmore 			u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) +
8966a14ee0cSDon Skidmore 				  2 * i;
8976a14ee0cSDon Skidmore 			u32 value = IXGBE_READ_REG(hw, reg);
8986a14ee0cSDon Skidmore 
8996a14ee0cSDon Skidmore 			data[current_word] = (u16)(value & 0xffff);
9006a14ee0cSDon Skidmore 			current_word++;
9016a14ee0cSDon Skidmore 			i++;
9026a14ee0cSDon Skidmore 			if (i < words_to_read) {
9036a14ee0cSDon Skidmore 				value >>= 16;
9046a14ee0cSDon Skidmore 				data[current_word] = (u16)(value & 0xffff);
9056a14ee0cSDon Skidmore 				current_word++;
9066a14ee0cSDon Skidmore 			}
9076a14ee0cSDon Skidmore 		}
9086a14ee0cSDon Skidmore 		words -= words_to_read;
9096a14ee0cSDon Skidmore 	}
9106a14ee0cSDon Skidmore 
9116a14ee0cSDon Skidmore out:
9123efa9ed2SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
9136a14ee0cSDon Skidmore 	return status;
9146a14ee0cSDon Skidmore }
9156a14ee0cSDon Skidmore 
9166a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region
9176a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
9186a14ee0cSDon Skidmore  *  @ptr: pointer offset in eeprom
9196a14ee0cSDon Skidmore  *  @size: size of section pointed by ptr, if 0 first word will be used as size
9206a14ee0cSDon Skidmore  *  @csum: address of checksum to update
9216a14ee0cSDon Skidmore  *
9226a14ee0cSDon Skidmore  *  Returns error status for any failure
9236a14ee0cSDon Skidmore  **/
9246a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
9256a14ee0cSDon Skidmore 				   u16 size, u16 *csum, u16 *buffer,
9266a14ee0cSDon Skidmore 				   u32 buffer_size)
9276a14ee0cSDon Skidmore {
9286a14ee0cSDon Skidmore 	u16 buf[256];
9296a14ee0cSDon Skidmore 	s32 status;
9306a14ee0cSDon Skidmore 	u16 length, bufsz, i, start;
9316a14ee0cSDon Skidmore 	u16 *local_buffer;
9326a14ee0cSDon Skidmore 
933f0e49dc3SColin Ian King 	bufsz = ARRAY_SIZE(buf);
9346a14ee0cSDon Skidmore 
9356a14ee0cSDon Skidmore 	/* Read a chunk at the pointer location */
9366a14ee0cSDon Skidmore 	if (!buffer) {
9376a14ee0cSDon Skidmore 		status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf);
9386a14ee0cSDon Skidmore 		if (status) {
9396a14ee0cSDon Skidmore 			hw_dbg(hw, "Failed to read EEPROM image\n");
9406a14ee0cSDon Skidmore 			return status;
9416a14ee0cSDon Skidmore 		}
9426a14ee0cSDon Skidmore 		local_buffer = buf;
9436a14ee0cSDon Skidmore 	} else {
9446a14ee0cSDon Skidmore 		if (buffer_size < ptr)
9456a14ee0cSDon Skidmore 			return  IXGBE_ERR_PARAM;
9466a14ee0cSDon Skidmore 		local_buffer = &buffer[ptr];
9476a14ee0cSDon Skidmore 	}
9486a14ee0cSDon Skidmore 
9496a14ee0cSDon Skidmore 	if (size) {
9506a14ee0cSDon Skidmore 		start = 0;
9516a14ee0cSDon Skidmore 		length = size;
9526a14ee0cSDon Skidmore 	} else {
9536a14ee0cSDon Skidmore 		start = 1;
9546a14ee0cSDon Skidmore 		length = local_buffer[0];
9556a14ee0cSDon Skidmore 
9566a14ee0cSDon Skidmore 		/* Skip pointer section if length is invalid. */
9576a14ee0cSDon Skidmore 		if (length == 0xFFFF || length == 0 ||
9586a14ee0cSDon Skidmore 		    (ptr + length) >= hw->eeprom.word_size)
9596a14ee0cSDon Skidmore 			return 0;
9606a14ee0cSDon Skidmore 	}
9616a14ee0cSDon Skidmore 
9626a14ee0cSDon Skidmore 	if (buffer && ((u32)start + (u32)length > buffer_size))
9636a14ee0cSDon Skidmore 		return IXGBE_ERR_PARAM;
9646a14ee0cSDon Skidmore 
9656a14ee0cSDon Skidmore 	for (i = start; length; i++, length--) {
9666a14ee0cSDon Skidmore 		if (i == bufsz && !buffer) {
9676a14ee0cSDon Skidmore 			ptr += bufsz;
9686a14ee0cSDon Skidmore 			i = 0;
9696a14ee0cSDon Skidmore 			if (length < bufsz)
9706a14ee0cSDon Skidmore 				bufsz = length;
9716a14ee0cSDon Skidmore 
9726a14ee0cSDon Skidmore 			/* Read a chunk at the pointer location */
9736a14ee0cSDon Skidmore 			status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr,
9746a14ee0cSDon Skidmore 								  bufsz, buf);
9756a14ee0cSDon Skidmore 			if (status) {
9766a14ee0cSDon Skidmore 				hw_dbg(hw, "Failed to read EEPROM image\n");
9776a14ee0cSDon Skidmore 				return status;
9786a14ee0cSDon Skidmore 			}
9796a14ee0cSDon Skidmore 		}
9806a14ee0cSDon Skidmore 		*csum += local_buffer[i];
9816a14ee0cSDon Skidmore 	}
9826a14ee0cSDon Skidmore 	return 0;
9836a14ee0cSDon Skidmore }
9846a14ee0cSDon Skidmore 
9856a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum
9866a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
9876a14ee0cSDon Skidmore  *  @buffer: pointer to buffer containing calculated checksum
9886a14ee0cSDon Skidmore  *  @buffer_size: size of buffer
9896a14ee0cSDon Skidmore  *
9906a14ee0cSDon Skidmore  *  Returns a negative error code on error, or the 16-bit checksum
9916a14ee0cSDon Skidmore  **/
9927ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer,
9937ddbde3fSDon Skidmore 				    u32 buffer_size)
9946a14ee0cSDon Skidmore {
9956a14ee0cSDon Skidmore 	u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1];
9966a14ee0cSDon Skidmore 	u16 *local_buffer;
9976a14ee0cSDon Skidmore 	s32 status;
9986a14ee0cSDon Skidmore 	u16 checksum = 0;
9996a14ee0cSDon Skidmore 	u16 pointer, i, size;
10006a14ee0cSDon Skidmore 
10016a14ee0cSDon Skidmore 	hw->eeprom.ops.init_params(hw);
10026a14ee0cSDon Skidmore 
10036a14ee0cSDon Skidmore 	if (!buffer) {
10046a14ee0cSDon Skidmore 		/* Read pointer area */
10056a14ee0cSDon Skidmore 		status = ixgbe_read_ee_hostif_buffer_X550(hw, 0,
10066a14ee0cSDon Skidmore 						IXGBE_EEPROM_LAST_WORD + 1,
10076a14ee0cSDon Skidmore 						eeprom_ptrs);
10086a14ee0cSDon Skidmore 		if (status) {
10096a14ee0cSDon Skidmore 			hw_dbg(hw, "Failed to read EEPROM image\n");
10106a14ee0cSDon Skidmore 			return status;
10116a14ee0cSDon Skidmore 		}
10126a14ee0cSDon Skidmore 		local_buffer = eeprom_ptrs;
10136a14ee0cSDon Skidmore 	} else {
10146a14ee0cSDon Skidmore 		if (buffer_size < IXGBE_EEPROM_LAST_WORD)
10156a14ee0cSDon Skidmore 			return IXGBE_ERR_PARAM;
10166a14ee0cSDon Skidmore 		local_buffer = buffer;
10176a14ee0cSDon Skidmore 	}
10186a14ee0cSDon Skidmore 
10196a14ee0cSDon Skidmore 	/* For X550 hardware include 0x0-0x41 in the checksum, skip the
10206a14ee0cSDon Skidmore 	 * checksum word itself
10216a14ee0cSDon Skidmore 	 */
10226a14ee0cSDon Skidmore 	for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++)
10236a14ee0cSDon Skidmore 		if (i != IXGBE_EEPROM_CHECKSUM)
10246a14ee0cSDon Skidmore 			checksum += local_buffer[i];
10256a14ee0cSDon Skidmore 
10266a14ee0cSDon Skidmore 	/* Include all data from pointers 0x3, 0x6-0xE.  This excludes the
10276a14ee0cSDon Skidmore 	 * FW, PHY module, and PCIe Expansion/Option ROM pointers.
10286a14ee0cSDon Skidmore 	 */
10296a14ee0cSDon Skidmore 	for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) {
10306a14ee0cSDon Skidmore 		if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
10316a14ee0cSDon Skidmore 			continue;
10326a14ee0cSDon Skidmore 
10336a14ee0cSDon Skidmore 		pointer = local_buffer[i];
10346a14ee0cSDon Skidmore 
10356a14ee0cSDon Skidmore 		/* Skip pointer section if the pointer is invalid. */
10366a14ee0cSDon Skidmore 		if (pointer == 0xFFFF || pointer == 0 ||
10376a14ee0cSDon Skidmore 		    pointer >= hw->eeprom.word_size)
10386a14ee0cSDon Skidmore 			continue;
10396a14ee0cSDon Skidmore 
10406a14ee0cSDon Skidmore 		switch (i) {
10416a14ee0cSDon Skidmore 		case IXGBE_PCIE_GENERAL_PTR:
10426a14ee0cSDon Skidmore 			size = IXGBE_IXGBE_PCIE_GENERAL_SIZE;
10436a14ee0cSDon Skidmore 			break;
10446a14ee0cSDon Skidmore 		case IXGBE_PCIE_CONFIG0_PTR:
10456a14ee0cSDon Skidmore 		case IXGBE_PCIE_CONFIG1_PTR:
10466a14ee0cSDon Skidmore 			size = IXGBE_PCIE_CONFIG_SIZE;
10476a14ee0cSDon Skidmore 			break;
10486a14ee0cSDon Skidmore 		default:
10496a14ee0cSDon Skidmore 			size = 0;
10506a14ee0cSDon Skidmore 			break;
10516a14ee0cSDon Skidmore 		}
10526a14ee0cSDon Skidmore 
10536a14ee0cSDon Skidmore 		status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum,
10546a14ee0cSDon Skidmore 						 buffer, buffer_size);
10556a14ee0cSDon Skidmore 		if (status)
10566a14ee0cSDon Skidmore 			return status;
10576a14ee0cSDon Skidmore 	}
10586a14ee0cSDon Skidmore 
10596a14ee0cSDon Skidmore 	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
10606a14ee0cSDon Skidmore 
10616a14ee0cSDon Skidmore 	return (s32)checksum;
10626a14ee0cSDon Skidmore }
10636a14ee0cSDon Skidmore 
10646a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum
10656a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
10666a14ee0cSDon Skidmore  *
10676a14ee0cSDon Skidmore  *  Returns a negative error code on error, or the 16-bit checksum
10686a14ee0cSDon Skidmore  **/
10697ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
10706a14ee0cSDon Skidmore {
10716a14ee0cSDon Skidmore 	return ixgbe_calc_checksum_X550(hw, NULL, 0);
10726a14ee0cSDon Skidmore }
10736a14ee0cSDon Skidmore 
10746a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command
10756a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
10766a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to read
10776a14ee0cSDon Skidmore  *  @data: word read from the EEPROM
10786a14ee0cSDon Skidmore  *
10796a14ee0cSDon Skidmore  *   Reads a 16 bit word from the EEPROM using the hostif.
10806a14ee0cSDon Skidmore  **/
10817ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data)
10826a14ee0cSDon Skidmore {
10833efa9ed2SMark Rustad 	const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
10843efa9ed2SMark Rustad 	struct ixgbe_hic_read_shadow_ram buffer;
10853efa9ed2SMark Rustad 	s32 status;
10866a14ee0cSDon Skidmore 
10873efa9ed2SMark Rustad 	buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
10883efa9ed2SMark Rustad 	buffer.hdr.req.buf_lenh = 0;
10893efa9ed2SMark Rustad 	buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
10903efa9ed2SMark Rustad 	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
10913efa9ed2SMark Rustad 
10923efa9ed2SMark Rustad 	/* convert offset from words to bytes */
10939cfbfa70SCathy Zhou 	buffer.address = (__force u32)cpu_to_be32(offset * 2);
10943efa9ed2SMark Rustad 	/* one word */
10959cfbfa70SCathy Zhou 	buffer.length = (__force u16)cpu_to_be16(sizeof(u16));
10963efa9ed2SMark Rustad 
10973efa9ed2SMark Rustad 	status = hw->mac.ops.acquire_swfw_sync(hw, mask);
10983efa9ed2SMark Rustad 	if (status)
10993efa9ed2SMark Rustad 		return status;
11003efa9ed2SMark Rustad 
11013efa9ed2SMark Rustad 	status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
11023efa9ed2SMark Rustad 				    IXGBE_HI_COMMAND_TIMEOUT);
11033efa9ed2SMark Rustad 	if (!status) {
11043efa9ed2SMark Rustad 		*data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
11053efa9ed2SMark Rustad 						  FW_NVM_DATA_OFFSET);
11066a14ee0cSDon Skidmore 	}
11076a14ee0cSDon Skidmore 
11083efa9ed2SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
11096a14ee0cSDon Skidmore 	return status;
11106a14ee0cSDon Skidmore }
11116a14ee0cSDon Skidmore 
11126a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum
11136a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
11146a14ee0cSDon Skidmore  *  @checksum_val: calculated checksum
11156a14ee0cSDon Skidmore  *
11166a14ee0cSDon Skidmore  *  Performs checksum calculation and validates the EEPROM checksum.  If the
11176a14ee0cSDon Skidmore  *  caller does not need checksum_val, the value can be NULL.
11186a14ee0cSDon Skidmore  **/
11197ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw,
11207ddbde3fSDon Skidmore 					       u16 *checksum_val)
11216a14ee0cSDon Skidmore {
11226a14ee0cSDon Skidmore 	s32 status;
11236a14ee0cSDon Skidmore 	u16 checksum;
11246a14ee0cSDon Skidmore 	u16 read_checksum = 0;
11256a14ee0cSDon Skidmore 
11266a14ee0cSDon Skidmore 	/* Read the first word from the EEPROM. If this times out or fails, do
11276a14ee0cSDon Skidmore 	 * not continue or we could be in for a very long wait while every
11286a14ee0cSDon Skidmore 	 * EEPROM read fails
11296a14ee0cSDon Skidmore 	 */
11306a14ee0cSDon Skidmore 	status = hw->eeprom.ops.read(hw, 0, &checksum);
11316a14ee0cSDon Skidmore 	if (status) {
11326a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM read failed\n");
11336a14ee0cSDon Skidmore 		return status;
11346a14ee0cSDon Skidmore 	}
11356a14ee0cSDon Skidmore 
11366a14ee0cSDon Skidmore 	status = hw->eeprom.ops.calc_checksum(hw);
11376a14ee0cSDon Skidmore 	if (status < 0)
11386a14ee0cSDon Skidmore 		return status;
11396a14ee0cSDon Skidmore 
11406a14ee0cSDon Skidmore 	checksum = (u16)(status & 0xffff);
11416a14ee0cSDon Skidmore 
11426a14ee0cSDon Skidmore 	status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
11436a14ee0cSDon Skidmore 					   &read_checksum);
11446a14ee0cSDon Skidmore 	if (status)
11456a14ee0cSDon Skidmore 		return status;
11466a14ee0cSDon Skidmore 
11476a14ee0cSDon Skidmore 	/* Verify read checksum from EEPROM is the same as
11486a14ee0cSDon Skidmore 	 * calculated checksum
11496a14ee0cSDon Skidmore 	 */
11506a14ee0cSDon Skidmore 	if (read_checksum != checksum) {
11516a14ee0cSDon Skidmore 		status = IXGBE_ERR_EEPROM_CHECKSUM;
11526a14ee0cSDon Skidmore 		hw_dbg(hw, "Invalid EEPROM checksum");
11536a14ee0cSDon Skidmore 	}
11546a14ee0cSDon Skidmore 
11556a14ee0cSDon Skidmore 	/* If the user cares, return the calculated checksum */
11566a14ee0cSDon Skidmore 	if (checksum_val)
11576a14ee0cSDon Skidmore 		*checksum_val = checksum;
11586a14ee0cSDon Skidmore 
11596a14ee0cSDon Skidmore 	return status;
11606a14ee0cSDon Skidmore }
11616a14ee0cSDon Skidmore 
11626a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
11636a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
11646a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to write
11656a14ee0cSDon Skidmore  *  @data: word write to the EEPROM
11666a14ee0cSDon Skidmore  *
11676a14ee0cSDon Skidmore  *  Write a 16 bit word to the EEPROM using the hostif.
11686a14ee0cSDon Skidmore  **/
11697ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
11707ddbde3fSDon Skidmore 					   u16 data)
11716a14ee0cSDon Skidmore {
11726a14ee0cSDon Skidmore 	s32 status;
11736a14ee0cSDon Skidmore 	struct ixgbe_hic_write_shadow_ram buffer;
11746a14ee0cSDon Skidmore 
11756a14ee0cSDon Skidmore 	buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
11766a14ee0cSDon Skidmore 	buffer.hdr.req.buf_lenh = 0;
11776a14ee0cSDon Skidmore 	buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
11786a14ee0cSDon Skidmore 	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
11796a14ee0cSDon Skidmore 
11806a14ee0cSDon Skidmore 	/* one word */
11816a14ee0cSDon Skidmore 	buffer.length = cpu_to_be16(sizeof(u16));
11826a14ee0cSDon Skidmore 	buffer.data = data;
11836a14ee0cSDon Skidmore 	buffer.address = cpu_to_be32(offset * 2);
11846a14ee0cSDon Skidmore 
11855cffde30SMark Rustad 	status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer),
11866a14ee0cSDon Skidmore 					      IXGBE_HI_COMMAND_TIMEOUT, false);
11876a14ee0cSDon Skidmore 	return status;
11886a14ee0cSDon Skidmore }
11896a14ee0cSDon Skidmore 
11906a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
11916a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
11926a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to write
11936a14ee0cSDon Skidmore  *  @data: word write to the EEPROM
11946a14ee0cSDon Skidmore  *
11956a14ee0cSDon Skidmore  *  Write a 16 bit word to the EEPROM using the hostif.
11966a14ee0cSDon Skidmore  **/
11977ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data)
11986a14ee0cSDon Skidmore {
11996a14ee0cSDon Skidmore 	s32 status = 0;
12006a14ee0cSDon Skidmore 
12016a14ee0cSDon Skidmore 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
12026a14ee0cSDon Skidmore 		status = ixgbe_write_ee_hostif_data_X550(hw, offset, data);
12036a14ee0cSDon Skidmore 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
12046a14ee0cSDon Skidmore 	} else {
12056a14ee0cSDon Skidmore 		hw_dbg(hw, "write ee hostif failed to get semaphore");
12066a14ee0cSDon Skidmore 		status = IXGBE_ERR_SWFW_SYNC;
12076a14ee0cSDon Skidmore 	}
12086a14ee0cSDon Skidmore 
12096a14ee0cSDon Skidmore 	return status;
12106a14ee0cSDon Skidmore }
12116a14ee0cSDon Skidmore 
12126a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device
12136a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
12146a14ee0cSDon Skidmore  *
12156a14ee0cSDon Skidmore  *  Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash.
12166a14ee0cSDon Skidmore  **/
12177ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw)
12186a14ee0cSDon Skidmore {
12196a14ee0cSDon Skidmore 	s32 status = 0;
12206a14ee0cSDon Skidmore 	union ixgbe_hic_hdr2 buffer;
12216a14ee0cSDon Skidmore 
12226a14ee0cSDon Skidmore 	buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD;
12236a14ee0cSDon Skidmore 	buffer.req.buf_lenh = 0;
12246a14ee0cSDon Skidmore 	buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN;
12256a14ee0cSDon Skidmore 	buffer.req.checksum = FW_DEFAULT_CHECKSUM;
12266a14ee0cSDon Skidmore 
12275cffde30SMark Rustad 	status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer),
12286a14ee0cSDon Skidmore 					      IXGBE_HI_COMMAND_TIMEOUT, false);
12296a14ee0cSDon Skidmore 	return status;
12306a14ee0cSDon Skidmore }
12316a14ee0cSDon Skidmore 
1232454c65ddSDon Skidmore /**
1233454c65ddSDon Skidmore  * ixgbe_get_bus_info_X550em - Set PCI bus info
1234454c65ddSDon Skidmore  * @hw: pointer to hardware structure
1235454c65ddSDon Skidmore  *
1236454c65ddSDon Skidmore  * Sets bus link width and speed to unknown because X550em is
1237454c65ddSDon Skidmore  * not a PCI device.
1238454c65ddSDon Skidmore  **/
1239454c65ddSDon Skidmore static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
1240454c65ddSDon Skidmore {
1241f9328bc6SDon Skidmore 	hw->bus.type  = ixgbe_bus_type_internal;
1242454c65ddSDon Skidmore 	hw->bus.width = ixgbe_bus_width_unknown;
1243454c65ddSDon Skidmore 	hw->bus.speed = ixgbe_bus_speed_unknown;
1244454c65ddSDon Skidmore 
1245454c65ddSDon Skidmore 	hw->mac.ops.set_lan_id(hw);
1246454c65ddSDon Skidmore 
1247454c65ddSDon Skidmore 	return 0;
1248454c65ddSDon Skidmore }
1249454c65ddSDon Skidmore 
125059dd45d5SSebastian Basierski /**
1251262de08fSJesse Brandeburg  * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode
125259dd45d5SSebastian Basierski  * @hw: pointer t hardware structure
125359dd45d5SSebastian Basierski  *
125459dd45d5SSebastian Basierski  * Returns true if in FW NVM recovery mode.
125559dd45d5SSebastian Basierski  */
125659dd45d5SSebastian Basierski static bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw)
125759dd45d5SSebastian Basierski {
125859dd45d5SSebastian Basierski 	u32 fwsm;
125959dd45d5SSebastian Basierski 
126059dd45d5SSebastian Basierski 	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
126159dd45d5SSebastian Basierski 	return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE);
126259dd45d5SSebastian Basierski }
126359dd45d5SSebastian Basierski 
12641f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit
12651f9ac57cSDon Skidmore  *
12661f9ac57cSDon Skidmore  *  Enables the Rx DMA unit for x550
12671f9ac57cSDon Skidmore  **/
12681f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
12691f9ac57cSDon Skidmore {
12701f9ac57cSDon Skidmore 	u32 rxctrl, pfdtxgswc;
12711f9ac57cSDon Skidmore 	s32 status;
12721f9ac57cSDon Skidmore 	struct ixgbe_hic_disable_rxen fw_cmd;
12731f9ac57cSDon Skidmore 
12741f9ac57cSDon Skidmore 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
12751f9ac57cSDon Skidmore 	if (rxctrl & IXGBE_RXCTRL_RXEN) {
12761f9ac57cSDon Skidmore 		pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
12771f9ac57cSDon Skidmore 		if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
12781f9ac57cSDon Skidmore 			pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
12791f9ac57cSDon Skidmore 			IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
12801f9ac57cSDon Skidmore 			hw->mac.set_lben = true;
12811f9ac57cSDon Skidmore 		} else {
12821f9ac57cSDon Skidmore 			hw->mac.set_lben = false;
12831f9ac57cSDon Skidmore 		}
12841f9ac57cSDon Skidmore 
12851f9ac57cSDon Skidmore 		fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD;
12861f9ac57cSDon Skidmore 		fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN;
12871f9ac57cSDon Skidmore 		fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
12883775b814SMark Rustad 		fw_cmd.port_number = hw->bus.lan_id;
12891f9ac57cSDon Skidmore 
12905cffde30SMark Rustad 		status = ixgbe_host_interface_command(hw, &fw_cmd,
12911f9ac57cSDon Skidmore 					sizeof(struct ixgbe_hic_disable_rxen),
12921f9ac57cSDon Skidmore 					IXGBE_HI_COMMAND_TIMEOUT, true);
12931f9ac57cSDon Skidmore 
12941f9ac57cSDon Skidmore 		/* If we fail - disable RX using register write */
12951f9ac57cSDon Skidmore 		if (status) {
12961f9ac57cSDon Skidmore 			rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
12971f9ac57cSDon Skidmore 			if (rxctrl & IXGBE_RXCTRL_RXEN) {
12981f9ac57cSDon Skidmore 				rxctrl &= ~IXGBE_RXCTRL_RXEN;
12991f9ac57cSDon Skidmore 				IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
13001f9ac57cSDon Skidmore 			}
13011f9ac57cSDon Skidmore 		}
13021f9ac57cSDon Skidmore 	}
13031f9ac57cSDon Skidmore }
13041f9ac57cSDon Skidmore 
13056a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash
13066a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
13076a14ee0cSDon Skidmore  *
13086a14ee0cSDon Skidmore  *  After writing EEPROM to shadow RAM using EEWR register, software calculates
13096a14ee0cSDon Skidmore  *  checksum and updates the EEPROM and instructs the hardware to update
13106a14ee0cSDon Skidmore  *  the flash.
13116a14ee0cSDon Skidmore  **/
13127ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw)
13136a14ee0cSDon Skidmore {
13146a14ee0cSDon Skidmore 	s32 status;
13156a14ee0cSDon Skidmore 	u16 checksum = 0;
13166a14ee0cSDon Skidmore 
13176a14ee0cSDon Skidmore 	/* Read the first word from the EEPROM. If this times out or fails, do
13186a14ee0cSDon Skidmore 	 * not continue or we could be in for a very long wait while every
13196a14ee0cSDon Skidmore 	 * EEPROM read fails
13206a14ee0cSDon Skidmore 	 */
13216a14ee0cSDon Skidmore 	status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum);
13226a14ee0cSDon Skidmore 	if (status) {
13236a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM read failed\n");
13246a14ee0cSDon Skidmore 		return status;
13256a14ee0cSDon Skidmore 	}
13266a14ee0cSDon Skidmore 
13276a14ee0cSDon Skidmore 	status = ixgbe_calc_eeprom_checksum_X550(hw);
13286a14ee0cSDon Skidmore 	if (status < 0)
13296a14ee0cSDon Skidmore 		return status;
13306a14ee0cSDon Skidmore 
13316a14ee0cSDon Skidmore 	checksum = (u16)(status & 0xffff);
13326a14ee0cSDon Skidmore 
13336a14ee0cSDon Skidmore 	status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
13346a14ee0cSDon Skidmore 					    checksum);
13356a14ee0cSDon Skidmore 	if (status)
13366a14ee0cSDon Skidmore 		return status;
13376a14ee0cSDon Skidmore 
13386a14ee0cSDon Skidmore 	status = ixgbe_update_flash_X550(hw);
13396a14ee0cSDon Skidmore 
13406a14ee0cSDon Skidmore 	return status;
13416a14ee0cSDon Skidmore }
13426a14ee0cSDon Skidmore 
13436a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif
13446a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
13456a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to write
13466a14ee0cSDon Skidmore  *  @words: number of words
13476a14ee0cSDon Skidmore  *  @data: word(s) write to the EEPROM
13486a14ee0cSDon Skidmore  *
13496a14ee0cSDon Skidmore  *
13506a14ee0cSDon Skidmore  *  Write a 16 bit word(s) to the EEPROM using the hostif.
13516a14ee0cSDon Skidmore  **/
13527ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
13537ddbde3fSDon Skidmore 					     u16 offset, u16 words,
13547ddbde3fSDon Skidmore 					     u16 *data)
13556a14ee0cSDon Skidmore {
13566a14ee0cSDon Skidmore 	s32 status = 0;
13576a14ee0cSDon Skidmore 	u32 i = 0;
13586a14ee0cSDon Skidmore 
13596a14ee0cSDon Skidmore 	/* Take semaphore for the entire operation. */
13606a14ee0cSDon Skidmore 	status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
13616a14ee0cSDon Skidmore 	if (status) {
13626a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM write buffer - semaphore failed\n");
13636a14ee0cSDon Skidmore 		return status;
13646a14ee0cSDon Skidmore 	}
13656a14ee0cSDon Skidmore 
13666a14ee0cSDon Skidmore 	for (i = 0; i < words; i++) {
13676a14ee0cSDon Skidmore 		status = ixgbe_write_ee_hostif_data_X550(hw, offset + i,
13686a14ee0cSDon Skidmore 							 data[i]);
13696a14ee0cSDon Skidmore 		if (status) {
13706a14ee0cSDon Skidmore 			hw_dbg(hw, "Eeprom buffered write failed\n");
13716a14ee0cSDon Skidmore 			break;
13726a14ee0cSDon Skidmore 		}
13736a14ee0cSDon Skidmore 	}
13746a14ee0cSDon Skidmore 
13756a14ee0cSDon Skidmore 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
13766a14ee0cSDon Skidmore 
13776a14ee0cSDon Skidmore 	return status;
13786a14ee0cSDon Skidmore }
13796a14ee0cSDon Skidmore 
13806a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the
13816a14ee0cSDon Skidmore  *  IOSF device
13826a14ee0cSDon Skidmore  *
13836a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
13846a14ee0cSDon Skidmore  *  @reg_addr: 32 bit PHY register to write
13856a14ee0cSDon Skidmore  *  @device_type: 3 bit device type
13866a14ee0cSDon Skidmore  *  @data: Data to write to the register
13876a14ee0cSDon Skidmore  **/
13887ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
13896a14ee0cSDon Skidmore 					u32 device_type, u32 data)
13906a14ee0cSDon Skidmore {
1391ae14a1d8SMark Rustad 	u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
1392ae14a1d8SMark Rustad 	u32 command, error;
1393ae14a1d8SMark Rustad 	s32 ret;
1394ae14a1d8SMark Rustad 
1395ae14a1d8SMark Rustad 	ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
1396ae14a1d8SMark Rustad 	if (ret)
1397ae14a1d8SMark Rustad 		return ret;
1398ae14a1d8SMark Rustad 
1399ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, NULL);
1400ae14a1d8SMark Rustad 	if (ret)
1401ae14a1d8SMark Rustad 		goto out;
14026a14ee0cSDon Skidmore 
14036a14ee0cSDon Skidmore 	command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
14046a14ee0cSDon Skidmore 		   (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
14056a14ee0cSDon Skidmore 
14066a14ee0cSDon Skidmore 	/* Write IOSF control register */
14076a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
14086a14ee0cSDon Skidmore 
14096a14ee0cSDon Skidmore 	/* Write IOSF data register */
14106a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data);
14116a14ee0cSDon Skidmore 
1412ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, &command);
14136a14ee0cSDon Skidmore 
14146a14ee0cSDon Skidmore 	if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
14156a14ee0cSDon Skidmore 		error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
14166a14ee0cSDon Skidmore 			 IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
14176a14ee0cSDon Skidmore 		hw_dbg(hw, "Failed to write, error %x\n", error);
14186a14ee0cSDon Skidmore 		return IXGBE_ERR_PHY;
14196a14ee0cSDon Skidmore 	}
14206a14ee0cSDon Skidmore 
1421ae14a1d8SMark Rustad out:
1422ae14a1d8SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, gssr);
1423ae14a1d8SMark Rustad 	return ret;
14246a14ee0cSDon Skidmore }
14256a14ee0cSDon Skidmore 
14260c1b7de4SDon Skidmore /**
14270c1b7de4SDon Skidmore  *  ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration
14286a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
14296a14ee0cSDon Skidmore  *
14300c1b7de4SDon Skidmore  *  iXfI configuration needed for ixgbe_mac_X550EM_x devices.
14316a14ee0cSDon Skidmore  **/
14320c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)
14336a14ee0cSDon Skidmore {
14346a14ee0cSDon Skidmore 	s32 status;
14356a14ee0cSDon Skidmore 	u32 reg_val;
14366a14ee0cSDon Skidmore 
14376a14ee0cSDon Skidmore 	/* Disable training protocol FSM. */
14386a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
14396a14ee0cSDon Skidmore 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
14406a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
14416a14ee0cSDon Skidmore 	if (status)
14426a14ee0cSDon Skidmore 		return status;
14436a14ee0cSDon Skidmore 
14446a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL;
14456a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
14466a14ee0cSDon Skidmore 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
14476a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
14486a14ee0cSDon Skidmore 	if (status)
14496a14ee0cSDon Skidmore 		return status;
14506a14ee0cSDon Skidmore 
14516a14ee0cSDon Skidmore 	/* Disable Flex from training TXFFE. */
14526a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
14536a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
14546a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
14556a14ee0cSDon Skidmore 	if (status)
14566a14ee0cSDon Skidmore 		return status;
14576a14ee0cSDon Skidmore 
14586a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
14596a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
14606a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
14616a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
14626a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
14636a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
14646a14ee0cSDon Skidmore 	if (status)
14656a14ee0cSDon Skidmore 		return status;
14666a14ee0cSDon Skidmore 
14676a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
14686a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
14696a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
14706a14ee0cSDon Skidmore 	if (status)
14716a14ee0cSDon Skidmore 		return status;
14726a14ee0cSDon Skidmore 
14736a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
14746a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
14756a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
14766a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
14776a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
14786a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
14796a14ee0cSDon Skidmore 	if (status)
14806a14ee0cSDon Skidmore 		return status;
14816a14ee0cSDon Skidmore 
14826a14ee0cSDon Skidmore 	/* Enable override for coefficients. */
14836a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
14846a14ee0cSDon Skidmore 				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
14856a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
14866a14ee0cSDon Skidmore 	if (status)
14876a14ee0cSDon Skidmore 		return status;
14886a14ee0cSDon Skidmore 
14896a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN;
14906a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN;
14916a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN;
14926a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN;
14936a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
14946a14ee0cSDon Skidmore 				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
14956a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
14960c1b7de4SDon Skidmore 	return status;
14970c1b7de4SDon Skidmore }
14980c1b7de4SDon Skidmore 
1499470739b5SDon Skidmore /**
1500470739b5SDon Skidmore  *  ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the
1501470739b5SDon Skidmore  *  internal PHY
1502470739b5SDon Skidmore  *  @hw: pointer to hardware structure
1503470739b5SDon Skidmore  **/
1504470739b5SDon Skidmore static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
1505470739b5SDon Skidmore {
1506470739b5SDon Skidmore 	s32 status;
1507470739b5SDon Skidmore 	u32 link_ctrl;
1508470739b5SDon Skidmore 
1509470739b5SDon Skidmore 	/* Restart auto-negotiation. */
1510470739b5SDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
1511470739b5SDon Skidmore 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1512470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl);
1513470739b5SDon Skidmore 
1514470739b5SDon Skidmore 	if (status) {
1515470739b5SDon Skidmore 		hw_dbg(hw, "Auto-negotiation did not complete\n");
1516470739b5SDon Skidmore 		return status;
1517470739b5SDon Skidmore 	}
1518470739b5SDon Skidmore 
1519470739b5SDon Skidmore 	link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
1520470739b5SDon Skidmore 	status = hw->mac.ops.write_iosf_sb_reg(hw,
1521470739b5SDon Skidmore 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1522470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl);
1523470739b5SDon Skidmore 
1524470739b5SDon Skidmore 	if (hw->mac.type == ixgbe_mac_x550em_a) {
1525470739b5SDon Skidmore 		u32 flx_mask_st20;
1526470739b5SDon Skidmore 
1527470739b5SDon Skidmore 		/* Indicate to FW that AN restart has been asserted */
1528470739b5SDon Skidmore 		status = hw->mac.ops.read_iosf_sb_reg(hw,
1529470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1530470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20);
1531470739b5SDon Skidmore 
1532470739b5SDon Skidmore 		if (status) {
1533470739b5SDon Skidmore 			hw_dbg(hw, "Auto-negotiation did not complete\n");
1534470739b5SDon Skidmore 			return status;
1535470739b5SDon Skidmore 		}
1536470739b5SDon Skidmore 
1537470739b5SDon Skidmore 		flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART;
1538470739b5SDon Skidmore 		status = hw->mac.ops.write_iosf_sb_reg(hw,
1539470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1540470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20);
1541470739b5SDon Skidmore 	}
1542470739b5SDon Skidmore 
1543470739b5SDon Skidmore 	return status;
1544470739b5SDon Skidmore }
1545470739b5SDon Skidmore 
15460c1b7de4SDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
15470c1b7de4SDon Skidmore  *  @hw: pointer to hardware structure
15480c1b7de4SDon Skidmore  *  @speed: the link speed to force
15490c1b7de4SDon Skidmore  *
15500c1b7de4SDon Skidmore  *  Configures the integrated KR PHY to use iXFI mode. Used to connect an
15510c1b7de4SDon Skidmore  *  internal and external PHY at a specific speed, without autonegotiation.
15520c1b7de4SDon Skidmore  **/
15530c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
15540c1b7de4SDon Skidmore {
155548301cf2STony Nguyen 	struct ixgbe_mac_info *mac = &hw->mac;
15560c1b7de4SDon Skidmore 	s32 status;
15570c1b7de4SDon Skidmore 	u32 reg_val;
15580c1b7de4SDon Skidmore 
155948301cf2STony Nguyen 	/* iXFI is only supported with X552 */
156048301cf2STony Nguyen 	if (mac->type != ixgbe_mac_X550EM_x)
156148301cf2STony Nguyen 		return IXGBE_ERR_LINK_SETUP;
156248301cf2STony Nguyen 
15630c1b7de4SDon Skidmore 	/* Disable AN and force speed to 10G Serial. */
15640c1b7de4SDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
15650c1b7de4SDon Skidmore 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
15660c1b7de4SDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
15676a14ee0cSDon Skidmore 	if (status)
15686a14ee0cSDon Skidmore 		return status;
15696a14ee0cSDon Skidmore 
15700c1b7de4SDon Skidmore 	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
15710c1b7de4SDon Skidmore 	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
15720c1b7de4SDon Skidmore 
15730c1b7de4SDon Skidmore 	/* Select forced link speed for internal PHY. */
15740c1b7de4SDon Skidmore 	switch (*speed) {
15750c1b7de4SDon Skidmore 	case IXGBE_LINK_SPEED_10GB_FULL:
15760c1b7de4SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
15770c1b7de4SDon Skidmore 		break;
15780c1b7de4SDon Skidmore 	case IXGBE_LINK_SPEED_1GB_FULL:
15790c1b7de4SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
15800c1b7de4SDon Skidmore 		break;
15810c1b7de4SDon Skidmore 	default:
15820c1b7de4SDon Skidmore 		/* Other link speeds are not supported by internal KR PHY. */
15830c1b7de4SDon Skidmore 		return IXGBE_ERR_LINK_SETUP;
15840c1b7de4SDon Skidmore 	}
15850c1b7de4SDon Skidmore 
15860c1b7de4SDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
15870c1b7de4SDon Skidmore 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
15880c1b7de4SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
15890c1b7de4SDon Skidmore 	if (status)
15900c1b7de4SDon Skidmore 		return status;
15910c1b7de4SDon Skidmore 
15920c1b7de4SDon Skidmore 	/* Additional configuration needed for x550em_x */
15930c1b7de4SDon Skidmore 	if (hw->mac.type == ixgbe_mac_X550EM_x) {
15940c1b7de4SDon Skidmore 		status = ixgbe_setup_ixfi_x550em_x(hw);
15950c1b7de4SDon Skidmore 		if (status)
15960c1b7de4SDon Skidmore 			return status;
15970c1b7de4SDon Skidmore 	}
15980c1b7de4SDon Skidmore 
15996a14ee0cSDon Skidmore 	/* Toggle port SW reset by AN reset. */
1600470739b5SDon Skidmore 	status = ixgbe_restart_an_internal_phy_x550em(hw);
16016a14ee0cSDon Skidmore 
16026a14ee0cSDon Skidmore 	return status;
16036a14ee0cSDon Skidmore }
16046a14ee0cSDon Skidmore 
1605c3dc4c09SDon Skidmore /**
1606e23f3336SMark Rustad  *  ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported
1607e23f3336SMark Rustad  *  @hw: pointer to hardware structure
1608e23f3336SMark Rustad  *  @linear: true if SFP module is linear
1609e23f3336SMark Rustad  */
1610e23f3336SMark Rustad static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear)
1611e23f3336SMark Rustad {
1612e23f3336SMark Rustad 	switch (hw->phy.sfp_type) {
1613e23f3336SMark Rustad 	case ixgbe_sfp_type_not_present:
1614e23f3336SMark Rustad 		return IXGBE_ERR_SFP_NOT_PRESENT;
1615e23f3336SMark Rustad 	case ixgbe_sfp_type_da_cu_core0:
1616e23f3336SMark Rustad 	case ixgbe_sfp_type_da_cu_core1:
1617e23f3336SMark Rustad 		*linear = true;
1618e23f3336SMark Rustad 		break;
1619e23f3336SMark Rustad 	case ixgbe_sfp_type_srlr_core0:
1620e23f3336SMark Rustad 	case ixgbe_sfp_type_srlr_core1:
1621e23f3336SMark Rustad 	case ixgbe_sfp_type_da_act_lmt_core0:
1622e23f3336SMark Rustad 	case ixgbe_sfp_type_da_act_lmt_core1:
1623e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_sx_core0:
1624e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_sx_core1:
1625e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_lx_core0:
1626e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_lx_core1:
1627e23f3336SMark Rustad 		*linear = false;
1628e23f3336SMark Rustad 		break;
1629e23f3336SMark Rustad 	case ixgbe_sfp_type_unknown:
1630e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_cu_core0:
1631e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_cu_core1:
1632e23f3336SMark Rustad 	default:
1633e23f3336SMark Rustad 		return IXGBE_ERR_SFP_NOT_SUPPORTED;
1634e23f3336SMark Rustad 	}
1635e23f3336SMark Rustad 
1636e23f3336SMark Rustad 	return 0;
1637e23f3336SMark Rustad }
1638e23f3336SMark Rustad 
1639e23f3336SMark Rustad /**
16406d373a1bSMark Rustad  * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP.
16416d373a1bSMark Rustad  * @hw: pointer to hardware structure
16425ba643c6STony Nguyen  * @speed: the link speed to force
16435ba643c6STony Nguyen  * @autoneg_wait_to_complete: unused
16446d373a1bSMark Rustad  *
16456d373a1bSMark Rustad  * Configures the extern PHY and the integrated KR PHY for SFP support.
16466d373a1bSMark Rustad  */
16476d373a1bSMark Rustad static s32
16486d373a1bSMark Rustad ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
16496d373a1bSMark Rustad 				ixgbe_link_speed speed,
16506d373a1bSMark Rustad 				__always_unused bool autoneg_wait_to_complete)
16516d373a1bSMark Rustad {
1652e23f3336SMark Rustad 	s32 status;
1653812d7dffSEmil Tantilov 	u16 reg_slice, reg_val;
1654e23f3336SMark Rustad 	bool setup_linear = false;
1655e23f3336SMark Rustad 
1656e23f3336SMark Rustad 	/* Check if SFP module is supported and linear */
1657e23f3336SMark Rustad 	status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
1658e23f3336SMark Rustad 
1659e23f3336SMark Rustad 	/* If no SFP module present, then return success. Return success since
1660e23f3336SMark Rustad 	 * there is no reason to configure CS4227 and SFP not present error is
1661e23f3336SMark Rustad 	 * not accepted in the setup MAC link flow.
1662e23f3336SMark Rustad 	 */
1663e23f3336SMark Rustad 	if (status == IXGBE_ERR_SFP_NOT_PRESENT)
1664e23f3336SMark Rustad 		return 0;
1665e23f3336SMark Rustad 
1666e23f3336SMark Rustad 	if (status)
1667e23f3336SMark Rustad 		return status;
1668e23f3336SMark Rustad 
1669d91e3a7dSMark Rustad 	/* Configure internal PHY for KR/KX. */
1670812d7dffSEmil Tantilov 	ixgbe_setup_kr_speed_x550em(hw, speed);
1671e23f3336SMark Rustad 
1672d91e3a7dSMark Rustad 	/* Configure CS4227 LINE side to proper mode. */
1673812d7dffSEmil Tantilov 	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
1674d91e3a7dSMark Rustad 	if (setup_linear)
1675812d7dffSEmil Tantilov 		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
1676d91e3a7dSMark Rustad 	else
1677812d7dffSEmil Tantilov 		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
1678b71f6c40SEmil Tantilov 
1679b71f6c40SEmil Tantilov 	status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice,
1680b71f6c40SEmil Tantilov 					 reg_val);
1681b71f6c40SEmil Tantilov 
1682e23f3336SMark Rustad 	return status;
16836d373a1bSMark Rustad }
16846d373a1bSMark Rustad 
16856d373a1bSMark Rustad /**
1686470739b5SDon Skidmore  * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode
1687470739b5SDon Skidmore  * @hw: pointer to hardware structure
1688470739b5SDon Skidmore  * @speed: the link speed to force
1689470739b5SDon Skidmore  *
1690470739b5SDon Skidmore  * Configures the integrated PHY for native SFI mode. Used to connect the
1691470739b5SDon Skidmore  * internal PHY directly to an SFP cage, without autonegotiation.
1692470739b5SDon Skidmore  **/
1693470739b5SDon Skidmore static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
1694470739b5SDon Skidmore {
1695470739b5SDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
1696470739b5SDon Skidmore 	s32 status;
1697470739b5SDon Skidmore 	u32 reg_val;
1698470739b5SDon Skidmore 
1699470739b5SDon Skidmore 	/* Disable all AN and force speed to 10G Serial. */
1700470739b5SDon Skidmore 	status = mac->ops.read_iosf_sb_reg(hw,
1701470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1702470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
1703470739b5SDon Skidmore 	if (status)
1704470739b5SDon Skidmore 		return status;
1705470739b5SDon Skidmore 
1706470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
1707470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
1708470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
1709470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
1710470739b5SDon Skidmore 
1711470739b5SDon Skidmore 	/* Select forced link speed for internal PHY. */
1712470739b5SDon Skidmore 	switch (*speed) {
1713470739b5SDon Skidmore 	case IXGBE_LINK_SPEED_10GB_FULL:
1714470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G;
1715470739b5SDon Skidmore 		break;
1716470739b5SDon Skidmore 	case IXGBE_LINK_SPEED_1GB_FULL:
1717470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
1718470739b5SDon Skidmore 		break;
1719470739b5SDon Skidmore 	default:
1720470739b5SDon Skidmore 		/* Other link speeds are not supported by internal PHY. */
1721470739b5SDon Skidmore 		return IXGBE_ERR_LINK_SETUP;
1722470739b5SDon Skidmore 	}
1723470739b5SDon Skidmore 
1724470739b5SDon Skidmore 	status = mac->ops.write_iosf_sb_reg(hw,
1725470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1726470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
1727470739b5SDon Skidmore 
1728470739b5SDon Skidmore 	/* Toggle port SW reset by AN reset. */
1729470739b5SDon Skidmore 	status = ixgbe_restart_an_internal_phy_x550em(hw);
1730470739b5SDon Skidmore 
1731470739b5SDon Skidmore 	return status;
1732470739b5SDon Skidmore }
1733470739b5SDon Skidmore 
1734470739b5SDon Skidmore /**
17352d40cd17SMark Rustad  * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP
17362d40cd17SMark Rustad  * @hw: pointer to hardware structure
17375ba643c6STony Nguyen  * @speed: link speed
17385ba643c6STony Nguyen  * @autoneg_wait_to_complete: unused
17392d40cd17SMark Rustad  *
17402d40cd17SMark Rustad  * Configure the the integrated PHY for native SFP support.
17412d40cd17SMark Rustad  */
17422d40cd17SMark Rustad static s32
17432d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed,
17442d40cd17SMark Rustad 			   __always_unused bool autoneg_wait_to_complete)
17452d40cd17SMark Rustad {
17462d40cd17SMark Rustad 	bool setup_linear = false;
17472d40cd17SMark Rustad 	u32 reg_phy_int;
1748470739b5SDon Skidmore 	s32 ret_val;
17492d40cd17SMark Rustad 
17502d40cd17SMark Rustad 	/* Check if SFP module is supported and linear */
1751470739b5SDon Skidmore 	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
17522d40cd17SMark Rustad 
17532d40cd17SMark Rustad 	/* If no SFP module present, then return success. Return success since
17542d40cd17SMark Rustad 	 * SFP not present error is not excepted in the setup MAC link flow.
17552d40cd17SMark Rustad 	 */
1756470739b5SDon Skidmore 	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
17572d40cd17SMark Rustad 		return 0;
17582d40cd17SMark Rustad 
1759d9c23ff8SEmil Tantilov 	if (ret_val)
1760470739b5SDon Skidmore 		return ret_val;
17612d40cd17SMark Rustad 
1762470739b5SDon Skidmore 	/* Configure internal PHY for native SFI based on module type */
1763470739b5SDon Skidmore 	ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
1764470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1765470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
1766d9c23ff8SEmil Tantilov 	if (ret_val)
1767470739b5SDon Skidmore 		return ret_val;
17682d40cd17SMark Rustad 
1769470739b5SDon Skidmore 	reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA;
1770470739b5SDon Skidmore 	if (!setup_linear)
1771470739b5SDon Skidmore 		reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR;
17722d40cd17SMark Rustad 
1773470739b5SDon Skidmore 	ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
1774470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1775470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
1776d9c23ff8SEmil Tantilov 	if (ret_val)
1777470739b5SDon Skidmore 		return ret_val;
17782d40cd17SMark Rustad 
1779470739b5SDon Skidmore 	/* Setup SFI internal link. */
1780470739b5SDon Skidmore 	return ixgbe_setup_sfi_x550a(hw, &speed);
17812d40cd17SMark Rustad }
17822d40cd17SMark Rustad 
17832d40cd17SMark Rustad /**
17842d40cd17SMark Rustad  * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP
17852d40cd17SMark Rustad  * @hw: pointer to hardware structure
17865ba643c6STony Nguyen  * @speed: link speed
17875ba643c6STony Nguyen  * @autoneg_wait_to_complete: unused
17882d40cd17SMark Rustad  *
17892d40cd17SMark Rustad  * Configure the the integrated PHY for SFP support.
17902d40cd17SMark Rustad  */
17912d40cd17SMark Rustad static s32
17922d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed,
17932d40cd17SMark Rustad 			       __always_unused bool autoneg_wait_to_complete)
17942d40cd17SMark Rustad {
17952d40cd17SMark Rustad 	u32 reg_slice, slice_offset;
17962d40cd17SMark Rustad 	bool setup_linear = false;
17972d40cd17SMark Rustad 	u16 reg_phy_ext;
1798470739b5SDon Skidmore 	s32 ret_val;
17992d40cd17SMark Rustad 
18002d40cd17SMark Rustad 	/* Check if SFP module is supported and linear */
1801470739b5SDon Skidmore 	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
18022d40cd17SMark Rustad 
18032d40cd17SMark Rustad 	/* If no SFP module present, then return success. Return success since
18042d40cd17SMark Rustad 	 * SFP not present error is not excepted in the setup MAC link flow.
18052d40cd17SMark Rustad 	 */
1806470739b5SDon Skidmore 	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
18072d40cd17SMark Rustad 		return 0;
18082d40cd17SMark Rustad 
1809d9c23ff8SEmil Tantilov 	if (ret_val)
1810470739b5SDon Skidmore 		return ret_val;
18112d40cd17SMark Rustad 
18122d40cd17SMark Rustad 	/* Configure internal PHY for KR/KX. */
18132d40cd17SMark Rustad 	ixgbe_setup_kr_speed_x550em(hw, speed);
18142d40cd17SMark Rustad 
18157564a888SMark Rustad 	if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE)
18162d40cd17SMark Rustad 		return IXGBE_ERR_PHY_ADDR_INVALID;
18172d40cd17SMark Rustad 
1818cc1de78cSEmil Tantilov 	/* Get external PHY SKU id */
1819cc1de78cSEmil Tantilov 	ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU,
18202d40cd17SMark Rustad 				       IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
1821470739b5SDon Skidmore 	if (ret_val)
1822470739b5SDon Skidmore 		return ret_val;
18232d40cd17SMark Rustad 
18242d40cd17SMark Rustad 	/* When configuring quad port CS4223, the MAC instance is part
18252d40cd17SMark Rustad 	 * of the slice offset.
18262d40cd17SMark Rustad 	 */
1827cc1de78cSEmil Tantilov 	if (reg_phy_ext == IXGBE_CS4223_SKU_ID)
18282d40cd17SMark Rustad 		slice_offset = (hw->bus.lan_id +
18292d40cd17SMark Rustad 				(hw->bus.instance_id << 1)) << 12;
18302d40cd17SMark Rustad 	else
18312d40cd17SMark Rustad 		slice_offset = hw->bus.lan_id << 12;
18322d40cd17SMark Rustad 
18332d40cd17SMark Rustad 	/* Configure CS4227/CS4223 LINE side to proper mode. */
18342d40cd17SMark Rustad 	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
1835410a4949SEmil Tantilov 
1836410a4949SEmil Tantilov 	ret_val = hw->phy.ops.read_reg(hw, reg_slice,
1837410a4949SEmil Tantilov 				       IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
1838410a4949SEmil Tantilov 	if (ret_val)
1839410a4949SEmil Tantilov 		return ret_val;
1840410a4949SEmil Tantilov 
1841410a4949SEmil Tantilov 	reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) |
1842410a4949SEmil Tantilov 			 (IXGBE_CS4227_EDC_MODE_SR << 1));
1843410a4949SEmil Tantilov 
18442d40cd17SMark Rustad 	if (setup_linear)
18459bf1e20fSPaul Greenwalt 		reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1;
18462d40cd17SMark Rustad 	else
18479bf1e20fSPaul Greenwalt 		reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_SR << 1) | 1;
1848410a4949SEmil Tantilov 
1849410a4949SEmil Tantilov 	ret_val = hw->phy.ops.write_reg(hw, reg_slice,
1850410a4949SEmil Tantilov 					IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
1851410a4949SEmil Tantilov 	if (ret_val)
1852410a4949SEmil Tantilov 		return ret_val;
1853410a4949SEmil Tantilov 
1854410a4949SEmil Tantilov 	/* Flush previous write with a read */
1855410a4949SEmil Tantilov 	return hw->phy.ops.read_reg(hw, reg_slice,
1856410a4949SEmil Tantilov 				    IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
18572d40cd17SMark Rustad }
18582d40cd17SMark Rustad 
18592d40cd17SMark Rustad /**
1860c3dc4c09SDon Skidmore  * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
1861c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
1862c3dc4c09SDon Skidmore  * @speed: new link speed
18635ba643c6STony Nguyen  * @autoneg_wait: true when waiting for completion is needed
1864c3dc4c09SDon Skidmore  *
1865c3dc4c09SDon Skidmore  * Setup internal/external PHY link speed based on link speed, then set
1866c3dc4c09SDon Skidmore  * external PHY auto advertised link speed.
1867c3dc4c09SDon Skidmore  *
1868c3dc4c09SDon Skidmore  * Returns error status for any failure
1869c3dc4c09SDon Skidmore  **/
1870c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
1871c3dc4c09SDon Skidmore 					 ixgbe_link_speed speed,
1872c3dc4c09SDon Skidmore 					 bool autoneg_wait)
1873c3dc4c09SDon Skidmore {
1874c3dc4c09SDon Skidmore 	s32 status;
1875c3dc4c09SDon Skidmore 	ixgbe_link_speed force_speed;
1876c3dc4c09SDon Skidmore 
1877c3dc4c09SDon Skidmore 	/* Setup internal/external PHY link speed to iXFI (10G), unless
1878c3dc4c09SDon Skidmore 	 * only 1G is auto advertised then setup KX link.
1879c3dc4c09SDon Skidmore 	 */
1880c3dc4c09SDon Skidmore 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
1881c3dc4c09SDon Skidmore 		force_speed = IXGBE_LINK_SPEED_10GB_FULL;
1882c3dc4c09SDon Skidmore 	else
1883c3dc4c09SDon Skidmore 		force_speed = IXGBE_LINK_SPEED_1GB_FULL;
1884c3dc4c09SDon Skidmore 
188548301cf2STony Nguyen 	/* If X552 and internal link mode is XFI, then setup XFI internal link.
188648301cf2STony Nguyen 	 */
188748301cf2STony Nguyen 	if (hw->mac.type == ixgbe_mac_X550EM_x &&
188848301cf2STony Nguyen 	    !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
1889c3dc4c09SDon Skidmore 		status = ixgbe_setup_ixfi_x550em(hw, &force_speed);
1890c3dc4c09SDon Skidmore 
1891c3dc4c09SDon Skidmore 		if (status)
1892c3dc4c09SDon Skidmore 			return status;
1893c3dc4c09SDon Skidmore 	}
1894c3dc4c09SDon Skidmore 
1895c3dc4c09SDon Skidmore 	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
1896c3dc4c09SDon Skidmore }
1897c3dc4c09SDon Skidmore 
1898a4e293a5SDon Skidmore /** ixgbe_check_link_t_X550em - Determine link and speed status
1899a4e293a5SDon Skidmore   * @hw: pointer to hardware structure
1900a4e293a5SDon Skidmore   * @speed: pointer to link speed
1901a4e293a5SDon Skidmore   * @link_up: true when link is up
1902a4e293a5SDon Skidmore   * @link_up_wait_to_complete: bool used to wait for link up or not
1903a4e293a5SDon Skidmore   *
1904a4e293a5SDon Skidmore   * Check that both the MAC and X557 external PHY have link.
1905a4e293a5SDon Skidmore   **/
1906a4e293a5SDon Skidmore static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw,
1907a4e293a5SDon Skidmore 				     ixgbe_link_speed *speed,
1908a4e293a5SDon Skidmore 				     bool *link_up,
1909a4e293a5SDon Skidmore 				     bool link_up_wait_to_complete)
1910a4e293a5SDon Skidmore {
1911a4e293a5SDon Skidmore 	u32 status;
191221d882ebSEmil Tantilov 	u16 i, autoneg_status;
1913a4e293a5SDon Skidmore 
1914a4e293a5SDon Skidmore 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
1915a4e293a5SDon Skidmore 		return IXGBE_ERR_CONFIG;
1916a4e293a5SDon Skidmore 
1917a4e293a5SDon Skidmore 	status = ixgbe_check_mac_link_generic(hw, speed, link_up,
1918a4e293a5SDon Skidmore 					      link_up_wait_to_complete);
1919a4e293a5SDon Skidmore 
1920a4e293a5SDon Skidmore 	/* If check link fails or MAC link is not up, then return */
1921a4e293a5SDon Skidmore 	if (status || !(*link_up))
1922a4e293a5SDon Skidmore 		return status;
1923a4e293a5SDon Skidmore 
1924a4e293a5SDon Skidmore 	/* MAC link is up, so check external PHY link.
192521d882ebSEmil Tantilov 	 * Link status is latching low, and can only be used to detect link
192621d882ebSEmil Tantilov 	 * drop, and not the current status of the link without performing
192721d882ebSEmil Tantilov 	 * back-to-back reads.
1928a4e293a5SDon Skidmore 	 */
192921d882ebSEmil Tantilov 	for (i = 0; i < 2; i++) {
19304dc4000bSEmil Tantilov 		status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
1931a4e293a5SDon Skidmore 					      &autoneg_status);
193221d882ebSEmil Tantilov 
1933a4e293a5SDon Skidmore 		if (status)
1934a4e293a5SDon Skidmore 			return status;
193521d882ebSEmil Tantilov 	}
1936a4e293a5SDon Skidmore 
1937a4e293a5SDon Skidmore 	/* If external PHY link is not up, then indicate link not up */
1938a4e293a5SDon Skidmore 	if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
1939a4e293a5SDon Skidmore 		*link_up = false;
1940a4e293a5SDon Skidmore 
1941a4e293a5SDon Skidmore 	return 0;
1942a4e293a5SDon Skidmore }
1943a4e293a5SDon Skidmore 
1944200157c2SMark Rustad /**
1945200157c2SMark Rustad  * ixgbe_setup_sgmii - Set up link for sgmii
1946200157c2SMark Rustad  * @hw: pointer to hardware structure
19475ba643c6STony Nguyen  * @speed: unused
19485ba643c6STony Nguyen  * @autoneg_wait_to_complete: unused
1949200157c2SMark Rustad  */
1950200157c2SMark Rustad static s32
1951200157c2SMark Rustad ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed,
1952200157c2SMark Rustad 		  __always_unused bool autoneg_wait_to_complete)
1953200157c2SMark Rustad {
1954200157c2SMark Rustad 	struct ixgbe_mac_info *mac = &hw->mac;
1955470739b5SDon Skidmore 	u32 lval, sval, flx_val;
1956200157c2SMark Rustad 	s32 rc;
1957200157c2SMark Rustad 
1958200157c2SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
1959200157c2SMark Rustad 				       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1960200157c2SMark Rustad 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
1961200157c2SMark Rustad 	if (rc)
1962200157c2SMark Rustad 		return rc;
1963200157c2SMark Rustad 
1964200157c2SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
1965200157c2SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
1966200157c2SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
1967200157c2SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
1968200157c2SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
1969200157c2SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
1970200157c2SMark Rustad 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1971200157c2SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
1972200157c2SMark Rustad 	if (rc)
1973200157c2SMark Rustad 		return rc;
1974200157c2SMark Rustad 
1975200157c2SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
1976200157c2SMark Rustad 				       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
1977200157c2SMark Rustad 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
1978200157c2SMark Rustad 	if (rc)
1979200157c2SMark Rustad 		return rc;
1980200157c2SMark Rustad 
1981200157c2SMark Rustad 	sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
1982200157c2SMark Rustad 	sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
1983200157c2SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
1984200157c2SMark Rustad 					IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
1985200157c2SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
1986200157c2SMark Rustad 	if (rc)
1987200157c2SMark Rustad 		return rc;
1988200157c2SMark Rustad 
1989470739b5SDon Skidmore 	rc = mac->ops.read_iosf_sb_reg(hw,
1990470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1991470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
1992470739b5SDon Skidmore 	if (rc)
1993470739b5SDon Skidmore 		return rc;
1994200157c2SMark Rustad 
1995470739b5SDon Skidmore 	rc = mac->ops.read_iosf_sb_reg(hw,
1996470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1997470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
1998470739b5SDon Skidmore 	if (rc)
1999470739b5SDon Skidmore 		return rc;
2000470739b5SDon Skidmore 
2001470739b5SDon Skidmore 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
2002470739b5SDon Skidmore 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
2003470739b5SDon Skidmore 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
2004470739b5SDon Skidmore 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
2005470739b5SDon Skidmore 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
2006470739b5SDon Skidmore 
2007470739b5SDon Skidmore 	rc = mac->ops.write_iosf_sb_reg(hw,
2008470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2009470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
2010470739b5SDon Skidmore 	if (rc)
2011470739b5SDon Skidmore 		return rc;
2012470739b5SDon Skidmore 
2013470739b5SDon Skidmore 	rc = ixgbe_restart_an_internal_phy_x550em(hw);
2014200157c2SMark Rustad 	return rc;
2015200157c2SMark Rustad }
2016200157c2SMark Rustad 
2017b3eb4e18SMark Rustad /**
2018b3eb4e18SMark Rustad  * ixgbe_setup_sgmii_fw - Set up link for sgmii with firmware-controlled PHYs
2019b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
20205ba643c6STony Nguyen  * @speed: the link speed to force
20215ba643c6STony Nguyen  * @autoneg_wait: true when waiting for completion is needed
2022b3eb4e18SMark Rustad  */
2023b3eb4e18SMark Rustad static s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed,
2024b3eb4e18SMark Rustad 				bool autoneg_wait)
2025b3eb4e18SMark Rustad {
2026b3eb4e18SMark Rustad 	struct ixgbe_mac_info *mac = &hw->mac;
2027b3eb4e18SMark Rustad 	u32 lval, sval, flx_val;
2028b3eb4e18SMark Rustad 	s32 rc;
2029b3eb4e18SMark Rustad 
2030b3eb4e18SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
2031b3eb4e18SMark Rustad 				       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2032b3eb4e18SMark Rustad 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
2033b3eb4e18SMark Rustad 	if (rc)
2034b3eb4e18SMark Rustad 		return rc;
2035b3eb4e18SMark Rustad 
2036b3eb4e18SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
2037b3eb4e18SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
2038b3eb4e18SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
2039b3eb4e18SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
2040b3eb4e18SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
2041b3eb4e18SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
2042b3eb4e18SMark Rustad 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2043b3eb4e18SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
2044b3eb4e18SMark Rustad 	if (rc)
2045b3eb4e18SMark Rustad 		return rc;
2046b3eb4e18SMark Rustad 
2047b3eb4e18SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
2048b3eb4e18SMark Rustad 				       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
2049b3eb4e18SMark Rustad 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
2050b3eb4e18SMark Rustad 	if (rc)
2051b3eb4e18SMark Rustad 		return rc;
2052b3eb4e18SMark Rustad 
2053b3eb4e18SMark Rustad 	sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
2054b3eb4e18SMark Rustad 	sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
2055b3eb4e18SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
2056b3eb4e18SMark Rustad 					IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
2057b3eb4e18SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
2058b3eb4e18SMark Rustad 	if (rc)
2059b3eb4e18SMark Rustad 		return rc;
2060b3eb4e18SMark Rustad 
2061b3eb4e18SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
2062b3eb4e18SMark Rustad 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2063b3eb4e18SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
2064b3eb4e18SMark Rustad 	if (rc)
2065b3eb4e18SMark Rustad 		return rc;
2066b3eb4e18SMark Rustad 
2067b3eb4e18SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
2068b3eb4e18SMark Rustad 				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2069b3eb4e18SMark Rustad 				    IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
2070b3eb4e18SMark Rustad 	if (rc)
2071b3eb4e18SMark Rustad 		return rc;
2072b3eb4e18SMark Rustad 
2073b3eb4e18SMark Rustad 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
2074b3eb4e18SMark Rustad 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
2075b3eb4e18SMark Rustad 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
2076b3eb4e18SMark Rustad 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
2077b3eb4e18SMark Rustad 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
2078b3eb4e18SMark Rustad 
2079b3eb4e18SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
2080b3eb4e18SMark Rustad 				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2081b3eb4e18SMark Rustad 				    IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
2082b3eb4e18SMark Rustad 	if (rc)
2083b3eb4e18SMark Rustad 		return rc;
2084b3eb4e18SMark Rustad 
2085b3eb4e18SMark Rustad 	ixgbe_restart_an_internal_phy_x550em(hw);
2086b3eb4e18SMark Rustad 
2087b3eb4e18SMark Rustad 	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
2088b3eb4e18SMark Rustad }
2089b3eb4e18SMark Rustad 
2090b3eb4e18SMark Rustad /**
2091b3eb4e18SMark Rustad  * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37
2092b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
2093b3eb4e18SMark Rustad  *
2094b3eb4e18SMark Rustad  * Enable flow control according to IEEE clause 37.
2095b3eb4e18SMark Rustad  */
2096b3eb4e18SMark Rustad static void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)
2097b3eb4e18SMark Rustad {
2098b3eb4e18SMark Rustad 	s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
2099b3eb4e18SMark Rustad 	u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
2100b3eb4e18SMark Rustad 	ixgbe_link_speed speed;
2101b3eb4e18SMark Rustad 	bool link_up;
2102b3eb4e18SMark Rustad 
2103b3eb4e18SMark Rustad 	/* AN should have completed when the cable was plugged in.
2104b3eb4e18SMark Rustad 	 * Look for reasons to bail out.  Bail out if:
2105b3eb4e18SMark Rustad 	 * - FC autoneg is disabled, or if
2106b3eb4e18SMark Rustad 	 * - link is not up.
2107b3eb4e18SMark Rustad 	 */
2108b3eb4e18SMark Rustad 	if (hw->fc.disable_fc_autoneg)
2109b3eb4e18SMark Rustad 		goto out;
2110b3eb4e18SMark Rustad 
2111b3eb4e18SMark Rustad 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
2112b3eb4e18SMark Rustad 	if (!link_up)
2113b3eb4e18SMark Rustad 		goto out;
2114b3eb4e18SMark Rustad 
2115b3eb4e18SMark Rustad 	/* Check if auto-negotiation has completed */
2116b3eb4e18SMark Rustad 	status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info);
2117b3eb4e18SMark Rustad 	if (status || !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) {
2118b3eb4e18SMark Rustad 		status = IXGBE_ERR_FC_NOT_NEGOTIATED;
2119b3eb4e18SMark Rustad 		goto out;
2120b3eb4e18SMark Rustad 	}
2121b3eb4e18SMark Rustad 
2122b3eb4e18SMark Rustad 	/* Negotiate the flow control */
2123b3eb4e18SMark Rustad 	status = ixgbe_negotiate_fc(hw, info[0], info[0],
2124b3eb4e18SMark Rustad 				    FW_PHY_ACT_GET_LINK_INFO_FC_RX,
2125b3eb4e18SMark Rustad 				    FW_PHY_ACT_GET_LINK_INFO_FC_TX,
2126b3eb4e18SMark Rustad 				    FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX,
2127b3eb4e18SMark Rustad 				    FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX);
2128b3eb4e18SMark Rustad 
2129b3eb4e18SMark Rustad out:
2130b3eb4e18SMark Rustad 	if (!status) {
2131b3eb4e18SMark Rustad 		hw->fc.fc_was_autonegged = true;
2132b3eb4e18SMark Rustad 	} else {
2133b3eb4e18SMark Rustad 		hw->fc.fc_was_autonegged = false;
2134b3eb4e18SMark Rustad 		hw->fc.current_mode = hw->fc.requested_mode;
2135b3eb4e18SMark Rustad 	}
2136b3eb4e18SMark Rustad }
2137b3eb4e18SMark Rustad 
21382916500dSDon Skidmore /** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers
21392916500dSDon Skidmore  *  @hw: pointer to hardware structure
21402916500dSDon Skidmore  **/
21412916500dSDon Skidmore static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw)
21422916500dSDon Skidmore {
21432916500dSDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
21442916500dSDon Skidmore 
21452916500dSDon Skidmore 	switch (mac->ops.get_media_type(hw)) {
21462916500dSDon Skidmore 	case ixgbe_media_type_fiber:
21472916500dSDon Skidmore 		mac->ops.setup_fc = NULL;
21482916500dSDon Skidmore 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;
21492916500dSDon Skidmore 		break;
2150b3eb4e18SMark Rustad 	case ixgbe_media_type_copper:
2151b3eb4e18SMark Rustad 		if (hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T &&
2152b3eb4e18SMark Rustad 		    hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T_L) {
2153b3eb4e18SMark Rustad 			mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
2154b3eb4e18SMark Rustad 			break;
2155b3eb4e18SMark Rustad 		}
2156b3eb4e18SMark Rustad 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a;
2157b3eb4e18SMark Rustad 		mac->ops.setup_fc = ixgbe_fc_autoneg_fw;
2158b3eb4e18SMark Rustad 		mac->ops.setup_link = ixgbe_setup_sgmii_fw;
2159b3eb4e18SMark Rustad 		mac->ops.check_link = ixgbe_check_mac_link_generic;
2160b3eb4e18SMark Rustad 		break;
21612916500dSDon Skidmore 	case ixgbe_media_type_backplane:
21622916500dSDon Skidmore 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;
21632916500dSDon Skidmore 		mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;
21642916500dSDon Skidmore 		break;
21652916500dSDon Skidmore 	default:
21662916500dSDon Skidmore 		break;
21672916500dSDon Skidmore 	}
21682916500dSDon Skidmore }
21692916500dSDon Skidmore 
2170c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers
2171c3dc4c09SDon Skidmore  *  @hw: pointer to hardware structure
2172c3dc4c09SDon Skidmore  **/
2173c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
2174c3dc4c09SDon Skidmore {
2175c3dc4c09SDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
2176c3dc4c09SDon Skidmore 
2177abf76d76SEmil Tantilov 	mac->ops.setup_fc = ixgbe_setup_fc_x550em;
2178abf76d76SEmil Tantilov 
2179c3dc4c09SDon Skidmore 	switch (mac->ops.get_media_type(hw)) {
2180c3dc4c09SDon Skidmore 	case ixgbe_media_type_fiber:
2181c3dc4c09SDon Skidmore 		/* CS4227 does not support autoneg, so disable the laser control
2182c3dc4c09SDon Skidmore 		 * functions for SFP+ fiber
2183c3dc4c09SDon Skidmore 		 */
2184c3dc4c09SDon Skidmore 		mac->ops.disable_tx_laser = NULL;
2185c3dc4c09SDon Skidmore 		mac->ops.enable_tx_laser = NULL;
2186c3dc4c09SDon Skidmore 		mac->ops.flap_tx_laser = NULL;
21876d373a1bSMark Rustad 		mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
21882d40cd17SMark Rustad 		switch (hw->device_id) {
21892d40cd17SMark Rustad 		case IXGBE_DEV_ID_X550EM_A_SFP_N:
21902d40cd17SMark Rustad 			mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n;
21912d40cd17SMark Rustad 			break;
21922d40cd17SMark Rustad 		case IXGBE_DEV_ID_X550EM_A_SFP:
21932d40cd17SMark Rustad 			mac->ops.setup_mac_link =
21942d40cd17SMark Rustad 						ixgbe_setup_mac_link_sfp_x550a;
21952d40cd17SMark Rustad 			break;
21962d40cd17SMark Rustad 		default:
21972d40cd17SMark Rustad 			mac->ops.setup_mac_link =
21982d40cd17SMark Rustad 						ixgbe_setup_mac_link_sfp_x550em;
21992d40cd17SMark Rustad 			break;
22002d40cd17SMark Rustad 		}
22016d373a1bSMark Rustad 		mac->ops.set_rate_select_speed =
22026d373a1bSMark Rustad 					ixgbe_set_soft_rate_select_speed;
2203c3dc4c09SDon Skidmore 		break;
2204c3dc4c09SDon Skidmore 	case ixgbe_media_type_copper:
22058dc963e1SPaul Greenwalt 		if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T)
22068dc963e1SPaul Greenwalt 			break;
2207c3dc4c09SDon Skidmore 		mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
2208afdc71e4SMark Rustad 		mac->ops.setup_fc = ixgbe_setup_fc_generic;
2209a4e293a5SDon Skidmore 		mac->ops.check_link = ixgbe_check_link_t_X550em;
2210b3eb4e18SMark Rustad 		break;
221149425dfcSMark Rustad 	case ixgbe_media_type_backplane:
2212200157c2SMark Rustad 		if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
2213200157c2SMark Rustad 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)
2214200157c2SMark Rustad 			mac->ops.setup_link = ixgbe_setup_sgmii;
2215c3dc4c09SDon Skidmore 		break;
2216c3dc4c09SDon Skidmore 	default:
2217c3dc4c09SDon Skidmore 		break;
2218c3dc4c09SDon Skidmore 	}
22192916500dSDon Skidmore 
22202916500dSDon Skidmore 	/* Additional modification for X550em_a devices */
22212916500dSDon Skidmore 	if (hw->mac.type == ixgbe_mac_x550em_a)
22222916500dSDon Skidmore 		ixgbe_init_mac_link_ops_X550em_a(hw);
2223c3dc4c09SDon Skidmore }
2224c3dc4c09SDon Skidmore 
2225c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module
2226c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2227c3dc4c09SDon Skidmore  */
2228c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
2229c3dc4c09SDon Skidmore {
2230e23f3336SMark Rustad 	s32 status;
2231e23f3336SMark Rustad 	bool linear;
2232c3dc4c09SDon Skidmore 
2233e23f3336SMark Rustad 	/* Check if SFP module is supported */
2234e23f3336SMark Rustad 	status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
2235e23f3336SMark Rustad 	if (status)
2236e23f3336SMark Rustad 		return status;
2237c3dc4c09SDon Skidmore 
2238c3dc4c09SDon Skidmore 	ixgbe_init_mac_link_ops_X550em(hw);
2239c3dc4c09SDon Skidmore 	hw->phy.ops.reset = NULL;
2240c3dc4c09SDon Skidmore 
2241e23f3336SMark Rustad 	return 0;
2242c3dc4c09SDon Skidmore }
2243c3dc4c09SDon Skidmore 
2244c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities
2245c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2246c3dc4c09SDon Skidmore  * @speed: pointer to link speed
2247c3dc4c09SDon Skidmore  * @autoneg: true when autoneg or autotry is enabled
2248c3dc4c09SDon Skidmore  **/
2249c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
2250c3dc4c09SDon Skidmore 					      ixgbe_link_speed *speed,
2251c3dc4c09SDon Skidmore 					      bool *autoneg)
2252c3dc4c09SDon Skidmore {
2253b3eb4e18SMark Rustad 	if (hw->phy.type == ixgbe_phy_fw) {
2254b3eb4e18SMark Rustad 		*autoneg = true;
2255b3eb4e18SMark Rustad 		*speed = hw->phy.speeds_supported;
2256b3eb4e18SMark Rustad 		return 0;
2257b3eb4e18SMark Rustad 	}
2258b3eb4e18SMark Rustad 
2259c3dc4c09SDon Skidmore 	/* SFP */
2260c3dc4c09SDon Skidmore 	if (hw->phy.media_type == ixgbe_media_type_fiber) {
2261c3dc4c09SDon Skidmore 		/* CS4227 SFP must not enable auto-negotiation */
2262c3dc4c09SDon Skidmore 		*autoneg = false;
2263c3dc4c09SDon Skidmore 
2264c3dc4c09SDon Skidmore 		if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
2265a8bf879aSJosh Elsasser 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
2266a8bf879aSJosh Elsasser 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
2267a8bf879aSJosh Elsasser 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) {
2268c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_1GB_FULL;
2269c3dc4c09SDon Skidmore 			return 0;
2270c3dc4c09SDon Skidmore 		}
2271c3dc4c09SDon Skidmore 
2272c3dc4c09SDon Skidmore 		/* Link capabilities are based on SFP */
2273c3dc4c09SDon Skidmore 		if (hw->phy.multispeed_fiber)
2274c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_10GB_FULL |
2275c3dc4c09SDon Skidmore 				 IXGBE_LINK_SPEED_1GB_FULL;
2276c3dc4c09SDon Skidmore 		else
2277c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_10GB_FULL;
2278c3dc4c09SDon Skidmore 	} else {
227918bda0d9SDon Skidmore 		switch (hw->phy.type) {
228018bda0d9SDon Skidmore 		case ixgbe_phy_x550em_kx4:
228118bda0d9SDon Skidmore 			*speed = IXGBE_LINK_SPEED_1GB_FULL |
228218bda0d9SDon Skidmore 				 IXGBE_LINK_SPEED_2_5GB_FULL |
228318bda0d9SDon Skidmore 				 IXGBE_LINK_SPEED_10GB_FULL;
228418bda0d9SDon Skidmore 			break;
228518e01ee7SDon Skidmore 		case ixgbe_phy_x550em_xfi:
228618e01ee7SDon Skidmore 			*speed = IXGBE_LINK_SPEED_1GB_FULL |
228718e01ee7SDon Skidmore 				 IXGBE_LINK_SPEED_10GB_FULL;
228818e01ee7SDon Skidmore 			break;
22898dc963e1SPaul Greenwalt 		case ixgbe_phy_ext_1g_t:
229018bda0d9SDon Skidmore 		case ixgbe_phy_sgmii:
229118bda0d9SDon Skidmore 			*speed = IXGBE_LINK_SPEED_1GB_FULL;
229218bda0d9SDon Skidmore 			break;
22938e5c9c53SDon Skidmore 		case ixgbe_phy_x550em_kr:
22948e5c9c53SDon Skidmore 			if (hw->mac.type == ixgbe_mac_x550em_a) {
22958e5c9c53SDon Skidmore 				/* check different backplane modes */
22968e5c9c53SDon Skidmore 				if (hw->phy.nw_mng_if_sel &
22978e5c9c53SDon Skidmore 				    IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
22988e5c9c53SDon Skidmore 					*speed = IXGBE_LINK_SPEED_2_5GB_FULL;
22998e5c9c53SDon Skidmore 					break;
23008e5c9c53SDon Skidmore 				} else if (hw->device_id ==
23018e5c9c53SDon Skidmore 					   IXGBE_DEV_ID_X550EM_A_KR_L) {
23028e5c9c53SDon Skidmore 					*speed = IXGBE_LINK_SPEED_1GB_FULL;
23038e5c9c53SDon Skidmore 					break;
23048e5c9c53SDon Skidmore 				}
23058e5c9c53SDon Skidmore 			}
23065463fce6SJeff Kirsher 			fallthrough;
230718bda0d9SDon Skidmore 		default:
2308c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_10GB_FULL |
2309c3dc4c09SDon Skidmore 				 IXGBE_LINK_SPEED_1GB_FULL;
231018bda0d9SDon Skidmore 			break;
231118bda0d9SDon Skidmore 		}
2312c3dc4c09SDon Skidmore 		*autoneg = true;
2313c3dc4c09SDon Skidmore 	}
2314c3dc4c09SDon Skidmore 	return 0;
2315c3dc4c09SDon Skidmore }
2316c3dc4c09SDon Skidmore 
2317c3dc4c09SDon Skidmore /**
2318c3dc4c09SDon Skidmore  * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause
2319c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2320c3dc4c09SDon Skidmore  * @lsc: pointer to boolean flag which indicates whether external Base T
2321c3dc4c09SDon Skidmore  *	 PHY interrupt is lsc
2322c3dc4c09SDon Skidmore  *
2323c3dc4c09SDon Skidmore  * Determime if external Base T PHY interrupt cause is high temperature
2324c3dc4c09SDon Skidmore  * failure alarm or link status change.
2325c3dc4c09SDon Skidmore  *
2326c3dc4c09SDon Skidmore  * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
2327c3dc4c09SDon Skidmore  * failure alarm, else return PHY access status.
2328c3dc4c09SDon Skidmore  **/
2329c3dc4c09SDon Skidmore static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
2330c3dc4c09SDon Skidmore {
2331c3dc4c09SDon Skidmore 	u32 status;
2332c3dc4c09SDon Skidmore 	u16 reg;
2333c3dc4c09SDon Skidmore 
2334c3dc4c09SDon Skidmore 	*lsc = false;
2335c3dc4c09SDon Skidmore 
2336c3dc4c09SDon Skidmore 	/* Vendor alarm triggered */
2337c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
23384dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2339c3dc4c09SDon Skidmore 				      &reg);
2340c3dc4c09SDon Skidmore 
2341c3dc4c09SDon Skidmore 	if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
2342c3dc4c09SDon Skidmore 		return status;
2343c3dc4c09SDon Skidmore 
2344c3dc4c09SDon Skidmore 	/* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
2345c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
23464dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2347c3dc4c09SDon Skidmore 				      &reg);
2348c3dc4c09SDon Skidmore 
2349c3dc4c09SDon Skidmore 	if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
2350c3dc4c09SDon Skidmore 				IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
2351c3dc4c09SDon Skidmore 		return status;
2352c3dc4c09SDon Skidmore 
235383a9fb20SMark Rustad 	/* Global alarm triggered */
2354c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
23554dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2356c3dc4c09SDon Skidmore 				      &reg);
2357c3dc4c09SDon Skidmore 
2358c3dc4c09SDon Skidmore 	if (status)
2359c3dc4c09SDon Skidmore 		return status;
2360c3dc4c09SDon Skidmore 
2361c3dc4c09SDon Skidmore 	/* If high temperature failure, then return over temp error and exit */
2362c3dc4c09SDon Skidmore 	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
2363c3dc4c09SDon Skidmore 		/* power down the PHY in case the PHY FW didn't already */
2364c3dc4c09SDon Skidmore 		ixgbe_set_copper_phy_power(hw, false);
2365c3dc4c09SDon Skidmore 		return IXGBE_ERR_OVERTEMP;
2366c3dc4c09SDon Skidmore 	}
236783a9fb20SMark Rustad 	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
236883a9fb20SMark Rustad 		/*  device fault alarm triggered */
236983a9fb20SMark Rustad 		status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
23704dc4000bSEmil Tantilov 					  MDIO_MMD_VEND1,
237183a9fb20SMark Rustad 					  &reg);
237283a9fb20SMark Rustad 		if (status)
237383a9fb20SMark Rustad 			return status;
237483a9fb20SMark Rustad 
237583a9fb20SMark Rustad 		/* if device fault was due to high temp alarm handle and exit */
237683a9fb20SMark Rustad 		if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
237783a9fb20SMark Rustad 			/* power down the PHY in case the PHY FW didn't */
237883a9fb20SMark Rustad 			ixgbe_set_copper_phy_power(hw, false);
237983a9fb20SMark Rustad 			return IXGBE_ERR_OVERTEMP;
238083a9fb20SMark Rustad 		}
238183a9fb20SMark Rustad 	}
2382c3dc4c09SDon Skidmore 
2383c3dc4c09SDon Skidmore 	/* Vendor alarm 2 triggered */
2384c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
23854dc4000bSEmil Tantilov 				      MDIO_MMD_AN, &reg);
2386c3dc4c09SDon Skidmore 
2387c3dc4c09SDon Skidmore 	if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
2388c3dc4c09SDon Skidmore 		return status;
2389c3dc4c09SDon Skidmore 
2390c3dc4c09SDon Skidmore 	/* link connect/disconnect event occurred */
2391c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
23924dc4000bSEmil Tantilov 				      MDIO_MMD_AN, &reg);
2393c3dc4c09SDon Skidmore 
2394c3dc4c09SDon Skidmore 	if (status)
2395c3dc4c09SDon Skidmore 		return status;
2396c3dc4c09SDon Skidmore 
2397c3dc4c09SDon Skidmore 	/* Indicate LSC */
2398c3dc4c09SDon Skidmore 	if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC)
2399c3dc4c09SDon Skidmore 		*lsc = true;
2400c3dc4c09SDon Skidmore 
2401c3dc4c09SDon Skidmore 	return 0;
2402c3dc4c09SDon Skidmore }
2403c3dc4c09SDon Skidmore 
2404c3dc4c09SDon Skidmore /**
2405c3dc4c09SDon Skidmore  * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts
2406c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2407c3dc4c09SDon Skidmore  *
2408c3dc4c09SDon Skidmore  * Enable link status change and temperature failure alarm for the external
2409c3dc4c09SDon Skidmore  * Base T PHY
2410c3dc4c09SDon Skidmore  *
2411c3dc4c09SDon Skidmore  * Returns PHY access status
2412c3dc4c09SDon Skidmore  **/
2413c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
2414c3dc4c09SDon Skidmore {
2415c3dc4c09SDon Skidmore 	u32 status;
2416c3dc4c09SDon Skidmore 	u16 reg;
2417c3dc4c09SDon Skidmore 	bool lsc;
2418c3dc4c09SDon Skidmore 
2419c3dc4c09SDon Skidmore 	/* Clear interrupt flags */
2420c3dc4c09SDon Skidmore 	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
2421c3dc4c09SDon Skidmore 
2422c3dc4c09SDon Skidmore 	/* Enable link status change alarm */
242372f740b1STony Nguyen 
242472f740b1STony Nguyen 	/* Enable the LASI interrupts on X552 devices to receive notifications
242572f740b1STony Nguyen 	 * of the link configurations of the external PHY and correspondingly
242672f740b1STony Nguyen 	 * support the configuration of the internal iXFI link, since iXFI does
242772f740b1STony Nguyen 	 * not support auto-negotiation. This is not required for X553 devices
242872f740b1STony Nguyen 	 * having KR support, which performs auto-negotiations and which is used
242972f740b1STony Nguyen 	 * as the internal link to the external PHY. Hence adding a check here
243072f740b1STony Nguyen 	 * to avoid enabling LASI interrupts for X553 devices.
243172f740b1STony Nguyen 	 */
243272f740b1STony Nguyen 	if (hw->mac.type != ixgbe_mac_x550em_a) {
243372f740b1STony Nguyen 		status = hw->phy.ops.read_reg(hw,
243472f740b1STony Nguyen 					    IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
24354dc4000bSEmil Tantilov 					    MDIO_MMD_AN, &reg);
2436c3dc4c09SDon Skidmore 		if (status)
2437c3dc4c09SDon Skidmore 			return status;
2438c3dc4c09SDon Skidmore 
2439c3dc4c09SDon Skidmore 		reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
2440c3dc4c09SDon Skidmore 
244172f740b1STony Nguyen 		status = hw->phy.ops.write_reg(hw,
244272f740b1STony Nguyen 					    IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
24434dc4000bSEmil Tantilov 					    MDIO_MMD_AN, reg);
2444c3dc4c09SDon Skidmore 		if (status)
2445c3dc4c09SDon Skidmore 			return status;
244672f740b1STony Nguyen 	}
2447c3dc4c09SDon Skidmore 
244883a9fb20SMark Rustad 	/* Enable high temperature failure and global fault alarms */
2449c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
24504dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2451c3dc4c09SDon Skidmore 				      &reg);
2452c3dc4c09SDon Skidmore 	if (status)
2453c3dc4c09SDon Skidmore 		return status;
2454c3dc4c09SDon Skidmore 
245583a9fb20SMark Rustad 	reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN |
245683a9fb20SMark Rustad 		IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);
2457c3dc4c09SDon Skidmore 
2458c3dc4c09SDon Skidmore 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
24594dc4000bSEmil Tantilov 				       MDIO_MMD_VEND1,
2460c3dc4c09SDon Skidmore 				       reg);
2461c3dc4c09SDon Skidmore 	if (status)
2462c3dc4c09SDon Skidmore 		return status;
2463c3dc4c09SDon Skidmore 
2464c3dc4c09SDon Skidmore 	/* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
2465c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
24664dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2467c3dc4c09SDon Skidmore 				      &reg);
2468c3dc4c09SDon Skidmore 	if (status)
2469c3dc4c09SDon Skidmore 		return status;
2470c3dc4c09SDon Skidmore 
2471c3dc4c09SDon Skidmore 	reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
2472c3dc4c09SDon Skidmore 		IXGBE_MDIO_GLOBAL_ALARM_1_INT);
2473c3dc4c09SDon Skidmore 
2474c3dc4c09SDon Skidmore 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
24754dc4000bSEmil Tantilov 				       MDIO_MMD_VEND1,
2476c3dc4c09SDon Skidmore 				       reg);
2477c3dc4c09SDon Skidmore 	if (status)
2478c3dc4c09SDon Skidmore 		return status;
2479c3dc4c09SDon Skidmore 
2480c3dc4c09SDon Skidmore 	/* Enable chip-wide vendor alarm */
2481c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
24824dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2483c3dc4c09SDon Skidmore 				      &reg);
2484c3dc4c09SDon Skidmore 	if (status)
2485c3dc4c09SDon Skidmore 		return status;
2486c3dc4c09SDon Skidmore 
2487c3dc4c09SDon Skidmore 	reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
2488c3dc4c09SDon Skidmore 
2489c3dc4c09SDon Skidmore 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
24904dc4000bSEmil Tantilov 				       MDIO_MMD_VEND1,
2491c3dc4c09SDon Skidmore 				       reg);
2492c3dc4c09SDon Skidmore 
2493c3dc4c09SDon Skidmore 	return status;
2494c3dc4c09SDon Skidmore }
2495c3dc4c09SDon Skidmore 
2496c3dc4c09SDon Skidmore /**
2497c3dc4c09SDon Skidmore  * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
2498c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2499c3dc4c09SDon Skidmore  *
2500c3dc4c09SDon Skidmore  * Handle external Base T PHY interrupt. If high temperature
2501c3dc4c09SDon Skidmore  * failure alarm then return error, else if link status change
2502c3dc4c09SDon Skidmore  * then setup internal/external PHY link
2503c3dc4c09SDon Skidmore  *
2504c3dc4c09SDon Skidmore  * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
2505c3dc4c09SDon Skidmore  * failure alarm, else return PHY access status.
2506c3dc4c09SDon Skidmore  **/
2507c3dc4c09SDon Skidmore static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
2508c3dc4c09SDon Skidmore {
2509c3dc4c09SDon Skidmore 	struct ixgbe_phy_info *phy = &hw->phy;
2510c3dc4c09SDon Skidmore 	bool lsc;
2511c3dc4c09SDon Skidmore 	u32 status;
2512c3dc4c09SDon Skidmore 
2513c3dc4c09SDon Skidmore 	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
2514c3dc4c09SDon Skidmore 	if (status)
2515c3dc4c09SDon Skidmore 		return status;
2516c3dc4c09SDon Skidmore 
2517a85ce532SMark Rustad 	if (lsc && phy->ops.setup_internal_link)
2518c3dc4c09SDon Skidmore 		return phy->ops.setup_internal_link(hw);
2519c3dc4c09SDon Skidmore 
2520c3dc4c09SDon Skidmore 	return 0;
2521c3dc4c09SDon Skidmore }
2522c3dc4c09SDon Skidmore 
2523c3dc4c09SDon Skidmore /**
2524c3dc4c09SDon Skidmore  * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed.
2525c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2526c3dc4c09SDon Skidmore  * @speed: link speed
2527c3dc4c09SDon Skidmore  *
2528c3dc4c09SDon Skidmore  * Configures the integrated KR PHY.
2529c3dc4c09SDon Skidmore  **/
2530c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
2531c3dc4c09SDon Skidmore 				       ixgbe_link_speed speed)
2532c3dc4c09SDon Skidmore {
2533c3dc4c09SDon Skidmore 	s32 status;
2534c3dc4c09SDon Skidmore 	u32 reg_val;
2535c3dc4c09SDon Skidmore 
25369a5c27e6SMark Rustad 	status = hw->mac.ops.read_iosf_sb_reg(hw,
2537c3dc4c09SDon Skidmore 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2538c3dc4c09SDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
2539c3dc4c09SDon Skidmore 	if (status)
2540c3dc4c09SDon Skidmore 		return status;
2541c3dc4c09SDon Skidmore 
2542c3dc4c09SDon Skidmore 	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
2543c3dc4c09SDon Skidmore 	reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
2544c3dc4c09SDon Skidmore 		     IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
2545c3dc4c09SDon Skidmore 
2546c3dc4c09SDon Skidmore 	/* Advertise 10G support. */
2547c3dc4c09SDon Skidmore 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
2548c3dc4c09SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR;
2549c3dc4c09SDon Skidmore 
2550c3dc4c09SDon Skidmore 	/* Advertise 1G support. */
2551c3dc4c09SDon Skidmore 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
2552c3dc4c09SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
2553c3dc4c09SDon Skidmore 
25549a5c27e6SMark Rustad 	status = hw->mac.ops.write_iosf_sb_reg(hw,
2555c3dc4c09SDon Skidmore 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2556c3dc4c09SDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2557c3dc4c09SDon Skidmore 
2558470739b5SDon Skidmore 	if (hw->mac.type == ixgbe_mac_x550em_a) {
2559470739b5SDon Skidmore 		/* Set lane mode  to KR auto negotiation */
2560470739b5SDon Skidmore 		status = hw->mac.ops.read_iosf_sb_reg(hw,
2561470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2562470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
2563470739b5SDon Skidmore 
2564470739b5SDon Skidmore 		if (status)
2565c3dc4c09SDon Skidmore 			return status;
2566470739b5SDon Skidmore 
2567470739b5SDon Skidmore 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
2568470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
2569470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
2570470739b5SDon Skidmore 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
2571470739b5SDon Skidmore 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
2572470739b5SDon Skidmore 
2573470739b5SDon Skidmore 		status = hw->mac.ops.write_iosf_sb_reg(hw,
2574470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2575470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2576470739b5SDon Skidmore 	}
2577470739b5SDon Skidmore 
2578470739b5SDon Skidmore 	return ixgbe_restart_an_internal_phy_x550em(hw);
2579c3dc4c09SDon Skidmore }
2580c3dc4c09SDon Skidmore 
2581f572b2c4SMark Rustad /**
2582f572b2c4SMark Rustad  * ixgbe_setup_kr_x550em - Configure the KR PHY
25836a14ee0cSDon Skidmore  * @hw: pointer to hardware structure
25846a14ee0cSDon Skidmore  **/
25857ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
25866a14ee0cSDon Skidmore {
258754f6d4c4SDon Skidmore 	/* leave link alone for 2.5G */
258854f6d4c4SDon Skidmore 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
2589f572b2c4SMark Rustad 		return 0;
2590f572b2c4SMark Rustad 
2591f4a6374bSTony Nguyen 	if (ixgbe_check_reset_blocked(hw))
2592f4a6374bSTony Nguyen 		return 0;
2593f4a6374bSTony Nguyen 
2594c3dc4c09SDon Skidmore 	return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised);
25956a14ee0cSDon Skidmore }
25966a14ee0cSDon Skidmore 
2597c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status
2598c3dc4c09SDon Skidmore  *  @hw: address of hardware structure
2599c3dc4c09SDon Skidmore  *  @link_up: address of boolean to indicate link status
2600c3dc4c09SDon Skidmore  *
2601c3dc4c09SDon Skidmore  *  Returns error code if unable to get link status.
2602c3dc4c09SDon Skidmore  **/
2603c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
2604c3dc4c09SDon Skidmore {
2605c3dc4c09SDon Skidmore 	u32 ret;
2606c3dc4c09SDon Skidmore 	u16 autoneg_status;
2607c3dc4c09SDon Skidmore 
2608c3dc4c09SDon Skidmore 	*link_up = false;
2609c3dc4c09SDon Skidmore 
2610c3dc4c09SDon Skidmore 	/* read this twice back to back to indicate current status */
26114dc4000bSEmil Tantilov 	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
2612c3dc4c09SDon Skidmore 				   &autoneg_status);
2613c3dc4c09SDon Skidmore 	if (ret)
2614c3dc4c09SDon Skidmore 		return ret;
2615c3dc4c09SDon Skidmore 
26164dc4000bSEmil Tantilov 	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
2617c3dc4c09SDon Skidmore 				   &autoneg_status);
2618c3dc4c09SDon Skidmore 	if (ret)
2619c3dc4c09SDon Skidmore 		return ret;
2620c3dc4c09SDon Skidmore 
2621c3dc4c09SDon Skidmore 	*link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS);
2622c3dc4c09SDon Skidmore 
2623c3dc4c09SDon Skidmore 	return 0;
2624c3dc4c09SDon Skidmore }
2625c3dc4c09SDon Skidmore 
2626c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link
26276a14ee0cSDon Skidmore  *  @hw: point to hardware structure
26286a14ee0cSDon Skidmore  *
2629c3dc4c09SDon Skidmore  *  Configures the link between the integrated KR PHY and the external X557 PHY
2630c3dc4c09SDon Skidmore  *  The driver will call this function when it gets a link status change
2631c3dc4c09SDon Skidmore  *  interrupt from the X557 PHY. This function configures the link speed
2632c3dc4c09SDon Skidmore  *  between the PHYs to match the link speed of the BASE-T link.
26336a14ee0cSDon Skidmore  *
26346a14ee0cSDon Skidmore  * A return of a non-zero value indicates an error, and the base driver should
26356a14ee0cSDon Skidmore  * not report link up.
26366a14ee0cSDon Skidmore  **/
2637c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
26386a14ee0cSDon Skidmore {
26396a14ee0cSDon Skidmore 	ixgbe_link_speed force_speed;
2640c3dc4c09SDon Skidmore 	bool link_up;
2641c3dc4c09SDon Skidmore 	u32 status;
2642c3dc4c09SDon Skidmore 	u16 speed;
26436a14ee0cSDon Skidmore 
2644c3dc4c09SDon Skidmore 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
2645c3dc4c09SDon Skidmore 		return IXGBE_ERR_CONFIG;
2646c3dc4c09SDon Skidmore 
264748301cf2STony Nguyen 	if (!(hw->mac.type == ixgbe_mac_X550EM_x &&
264848301cf2STony Nguyen 	      !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))) {
2649f164b845SMark Rustad 		speed = IXGBE_LINK_SPEED_10GB_FULL |
2650f164b845SMark Rustad 			IXGBE_LINK_SPEED_1GB_FULL;
2651f164b845SMark Rustad 		return ixgbe_setup_kr_speed_x550em(hw, speed);
2652f164b845SMark Rustad 	}
2653f164b845SMark Rustad 
2654c3dc4c09SDon Skidmore 	/* If link is not up, then there is no setup necessary so return  */
2655c3dc4c09SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
26566a14ee0cSDon Skidmore 	if (status)
26576a14ee0cSDon Skidmore 		return status;
26586a14ee0cSDon Skidmore 
2659c3dc4c09SDon Skidmore 	if (!link_up)
26606a14ee0cSDon Skidmore 		return 0;
26616a14ee0cSDon Skidmore 
26626a14ee0cSDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
26634dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
26646a14ee0cSDon Skidmore 				      &speed);
2665c3dc4c09SDon Skidmore 	if (status)
2666c3dc4c09SDon Skidmore 		return status;
2667c3dc4c09SDon Skidmore 
2668c3dc4c09SDon Skidmore 	/* If link is not still up, then no setup is necessary so return */
2669c3dc4c09SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
2670c3dc4c09SDon Skidmore 	if (status)
2671c3dc4c09SDon Skidmore 		return status;
2672c3dc4c09SDon Skidmore 
2673c3dc4c09SDon Skidmore 	if (!link_up)
2674c3dc4c09SDon Skidmore 		return 0;
26756a14ee0cSDon Skidmore 
26766a14ee0cSDon Skidmore 	/* clear everything but the speed and duplex bits */
26776a14ee0cSDon Skidmore 	speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
26786a14ee0cSDon Skidmore 
26796a14ee0cSDon Skidmore 	switch (speed) {
26806a14ee0cSDon Skidmore 	case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
26816a14ee0cSDon Skidmore 		force_speed = IXGBE_LINK_SPEED_10GB_FULL;
26826a14ee0cSDon Skidmore 		break;
26836a14ee0cSDon Skidmore 	case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
26846a14ee0cSDon Skidmore 		force_speed = IXGBE_LINK_SPEED_1GB_FULL;
26856a14ee0cSDon Skidmore 		break;
26866a14ee0cSDon Skidmore 	default:
26876a14ee0cSDon Skidmore 		/* Internal PHY does not support anything else */
26886a14ee0cSDon Skidmore 		return IXGBE_ERR_INVALID_LINK_SETTINGS;
26896a14ee0cSDon Skidmore 	}
26906a14ee0cSDon Skidmore 
26916a14ee0cSDon Skidmore 	return ixgbe_setup_ixfi_x550em(hw, &force_speed);
26926a14ee0cSDon Skidmore }
26936a14ee0cSDon Skidmore 
2694f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI
2695f4410d2cSDon Skidmore  *  @hw: pointer to hardware structure
2696f4410d2cSDon Skidmore  **/
2697f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw)
2698f4410d2cSDon Skidmore {
2699f4410d2cSDon Skidmore 	s32 status;
2700f4410d2cSDon Skidmore 
2701f4410d2cSDon Skidmore 	status = ixgbe_reset_phy_generic(hw);
2702f4410d2cSDon Skidmore 
2703f4410d2cSDon Skidmore 	if (status)
2704f4410d2cSDon Skidmore 		return status;
2705f4410d2cSDon Skidmore 
2706f4410d2cSDon Skidmore 	/* Configure Link Status Alarm and Temperature Threshold interrupts */
2707f4410d2cSDon Skidmore 	return ixgbe_enable_lasi_ext_t_x550em(hw);
2708f4410d2cSDon Skidmore }
2709f4410d2cSDon Skidmore 
2710a0ad55a3SDon Skidmore /**
2711a0ad55a3SDon Skidmore  *  ixgbe_led_on_t_x550em - Turns on the software controllable LEDs.
2712a0ad55a3SDon Skidmore  *  @hw: pointer to hardware structure
2713a0ad55a3SDon Skidmore  *  @led_idx: led number to turn on
2714a0ad55a3SDon Skidmore  **/
2715d2d43e5bSEmil Tantilov static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
2716a0ad55a3SDon Skidmore {
2717a0ad55a3SDon Skidmore 	u16 phy_data;
2718a0ad55a3SDon Skidmore 
2719a0ad55a3SDon Skidmore 	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
2720a0ad55a3SDon Skidmore 		return IXGBE_ERR_PARAM;
2721a0ad55a3SDon Skidmore 
2722a0ad55a3SDon Skidmore 	/* To turn on the LED, set mode to ON. */
2723a0ad55a3SDon Skidmore 	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
27244dc4000bSEmil Tantilov 			     MDIO_MMD_VEND1, &phy_data);
2725a0ad55a3SDon Skidmore 	phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;
2726a0ad55a3SDon Skidmore 	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
27274dc4000bSEmil Tantilov 			      MDIO_MMD_VEND1, phy_data);
2728a0ad55a3SDon Skidmore 
2729a0ad55a3SDon Skidmore 	return 0;
2730a0ad55a3SDon Skidmore }
2731a0ad55a3SDon Skidmore 
2732a0ad55a3SDon Skidmore /**
2733a0ad55a3SDon Skidmore  *  ixgbe_led_off_t_x550em - Turns off the software controllable LEDs.
2734a0ad55a3SDon Skidmore  *  @hw: pointer to hardware structure
2735a0ad55a3SDon Skidmore  *  @led_idx: led number to turn off
2736a0ad55a3SDon Skidmore  **/
2737d2d43e5bSEmil Tantilov static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
2738a0ad55a3SDon Skidmore {
2739a0ad55a3SDon Skidmore 	u16 phy_data;
2740a0ad55a3SDon Skidmore 
2741a0ad55a3SDon Skidmore 	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
2742a0ad55a3SDon Skidmore 		return IXGBE_ERR_PARAM;
2743a0ad55a3SDon Skidmore 
2744a0ad55a3SDon Skidmore 	/* To turn on the LED, set mode to ON. */
2745a0ad55a3SDon Skidmore 	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
27464dc4000bSEmil Tantilov 			     MDIO_MMD_VEND1, &phy_data);
2747a0ad55a3SDon Skidmore 	phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;
2748a0ad55a3SDon Skidmore 	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
27494dc4000bSEmil Tantilov 			      MDIO_MMD_VEND1, phy_data);
2750a0ad55a3SDon Skidmore 
2751a0ad55a3SDon Skidmore 	return 0;
2752a0ad55a3SDon Skidmore }
2753a0ad55a3SDon Skidmore 
2754cb8e0514STony Nguyen /**
2755cb8e0514STony Nguyen  *  ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware
2756cb8e0514STony Nguyen  *  @hw: pointer to the HW structure
2757cb8e0514STony Nguyen  *  @maj: driver version major number
2758cb8e0514STony Nguyen  *  @min: driver version minor number
2759cb8e0514STony Nguyen  *  @build: driver version build number
2760cb8e0514STony Nguyen  *  @sub: driver version sub build number
2761cb8e0514STony Nguyen  *  @len: length of driver_ver string
2762cb8e0514STony Nguyen  *  @driver_ver: driver string
2763cb8e0514STony Nguyen  *
2764cb8e0514STony Nguyen  *  Sends driver version number to firmware through the manageability
2765cb8e0514STony Nguyen  *  block.  On success return 0
2766cb8e0514STony Nguyen  *  else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
2767cb8e0514STony Nguyen  *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
2768cb8e0514STony Nguyen  **/
2769cb8e0514STony Nguyen static s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
2770cb8e0514STony Nguyen 				     u8 build, u8 sub, u16 len,
2771cb8e0514STony Nguyen 				     const char *driver_ver)
2772cb8e0514STony Nguyen {
2773cb8e0514STony Nguyen 	struct ixgbe_hic_drv_info2 fw_cmd;
2774cb8e0514STony Nguyen 	s32 ret_val;
2775cb8e0514STony Nguyen 	int i;
2776cb8e0514STony Nguyen 
2777cb8e0514STony Nguyen 	if (!len || !driver_ver || (len > sizeof(fw_cmd.driver_string)))
2778cb8e0514STony Nguyen 		return IXGBE_ERR_INVALID_ARGUMENT;
2779cb8e0514STony Nguyen 
2780cb8e0514STony Nguyen 	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
2781cb8e0514STony Nguyen 	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len;
2782cb8e0514STony Nguyen 	fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
2783cb8e0514STony Nguyen 	fw_cmd.port_num = (u8)hw->bus.func;
2784cb8e0514STony Nguyen 	fw_cmd.ver_maj = maj;
2785cb8e0514STony Nguyen 	fw_cmd.ver_min = min;
2786cb8e0514STony Nguyen 	fw_cmd.ver_build = build;
2787cb8e0514STony Nguyen 	fw_cmd.ver_sub = sub;
2788cb8e0514STony Nguyen 	fw_cmd.hdr.checksum = 0;
2789cb8e0514STony Nguyen 	memcpy(fw_cmd.driver_string, driver_ver, len);
2790cb8e0514STony Nguyen 	fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
2791cb8e0514STony Nguyen 			      (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
2792cb8e0514STony Nguyen 
2793cb8e0514STony Nguyen 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
2794cb8e0514STony Nguyen 		ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
2795cb8e0514STony Nguyen 						       sizeof(fw_cmd),
2796cb8e0514STony Nguyen 						       IXGBE_HI_COMMAND_TIMEOUT,
2797cb8e0514STony Nguyen 						       true);
2798cb8e0514STony Nguyen 		if (ret_val)
2799cb8e0514STony Nguyen 			continue;
2800cb8e0514STony Nguyen 
2801cb8e0514STony Nguyen 		if (fw_cmd.hdr.cmd_or_resp.ret_status !=
2802cb8e0514STony Nguyen 		    FW_CEM_RESP_STATUS_SUCCESS)
2803cb8e0514STony Nguyen 			return IXGBE_ERR_HOST_INTERFACE_COMMAND;
2804cb8e0514STony Nguyen 		return 0;
2805cb8e0514STony Nguyen 	}
2806cb8e0514STony Nguyen 
2807cb8e0514STony Nguyen 	return ret_val;
2808cb8e0514STony Nguyen }
2809cb8e0514STony Nguyen 
28106ac74394SDon Skidmore /** ixgbe_get_lcd_x550em - Determine lowest common denominator
28116ac74394SDon Skidmore  *  @hw: pointer to hardware structure
28126ac74394SDon Skidmore  *  @lcd_speed: pointer to lowest common link speed
28136ac74394SDon Skidmore  *
28146ac74394SDon Skidmore  *  Determine lowest common link speed with link partner.
28156ac74394SDon Skidmore  **/
28166ac74394SDon Skidmore static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw,
28176ac74394SDon Skidmore 				  ixgbe_link_speed *lcd_speed)
28186ac74394SDon Skidmore {
28196ac74394SDon Skidmore 	u16 an_lp_status;
28206ac74394SDon Skidmore 	s32 status;
28216ac74394SDon Skidmore 	u16 word = hw->eeprom.ctrl_word_3;
28226ac74394SDon Skidmore 
28236ac74394SDon Skidmore 	*lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
28246ac74394SDon Skidmore 
28256ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
28264dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
28276ac74394SDon Skidmore 				      &an_lp_status);
28286ac74394SDon Skidmore 	if (status)
28296ac74394SDon Skidmore 		return status;
28306ac74394SDon Skidmore 
28316ac74394SDon Skidmore 	/* If link partner advertised 1G, return 1G */
28326ac74394SDon Skidmore 	if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) {
28336ac74394SDon Skidmore 		*lcd_speed = IXGBE_LINK_SPEED_1GB_FULL;
28346ac74394SDon Skidmore 		return status;
28356ac74394SDon Skidmore 	}
28366ac74394SDon Skidmore 
28376ac74394SDon Skidmore 	/* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */
28386ac74394SDon Skidmore 	if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) ||
28396ac74394SDon Skidmore 	    (word & NVM_INIT_CTRL_3_D10GMP_PORT0))
28406ac74394SDon Skidmore 		return status;
28416ac74394SDon Skidmore 
28426ac74394SDon Skidmore 	/* Link partner not capable of lower speeds, return 10G */
28436ac74394SDon Skidmore 	*lcd_speed = IXGBE_LINK_SPEED_10GB_FULL;
28446ac74394SDon Skidmore 	return status;
28456ac74394SDon Skidmore }
28466ac74394SDon Skidmore 
2847afdc71e4SMark Rustad /**
2848afdc71e4SMark Rustad  * ixgbe_setup_fc_x550em - Set up flow control
2849afdc71e4SMark Rustad  * @hw: pointer to hardware structure
2850afdc71e4SMark Rustad  */
2851afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw)
2852afdc71e4SMark Rustad {
2853afdc71e4SMark Rustad 	bool pause, asm_dir;
2854afdc71e4SMark Rustad 	u32 reg_val;
28557adbccbbSTony Nguyen 	s32 rc = 0;
2856afdc71e4SMark Rustad 
2857afdc71e4SMark Rustad 	/* Validate the requested mode */
2858afdc71e4SMark Rustad 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
2859afdc71e4SMark Rustad 		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
2860afdc71e4SMark Rustad 		return IXGBE_ERR_INVALID_LINK_SETTINGS;
2861afdc71e4SMark Rustad 	}
2862afdc71e4SMark Rustad 
2863afdc71e4SMark Rustad 	/* 10gig parts do not have a word in the EEPROM to determine the
2864afdc71e4SMark Rustad 	 * default flow control setting, so we explicitly set it to full.
2865afdc71e4SMark Rustad 	 */
2866afdc71e4SMark Rustad 	if (hw->fc.requested_mode == ixgbe_fc_default)
2867afdc71e4SMark Rustad 		hw->fc.requested_mode = ixgbe_fc_full;
2868afdc71e4SMark Rustad 
2869afdc71e4SMark Rustad 	/* Determine PAUSE and ASM_DIR bits. */
2870afdc71e4SMark Rustad 	switch (hw->fc.requested_mode) {
2871afdc71e4SMark Rustad 	case ixgbe_fc_none:
2872afdc71e4SMark Rustad 		pause = false;
2873afdc71e4SMark Rustad 		asm_dir = false;
2874afdc71e4SMark Rustad 		break;
2875afdc71e4SMark Rustad 	case ixgbe_fc_tx_pause:
2876afdc71e4SMark Rustad 		pause = false;
2877afdc71e4SMark Rustad 		asm_dir = true;
2878afdc71e4SMark Rustad 		break;
2879afdc71e4SMark Rustad 	case ixgbe_fc_rx_pause:
2880afdc71e4SMark Rustad 		/* Rx Flow control is enabled and Tx Flow control is
2881afdc71e4SMark Rustad 		 * disabled by software override. Since there really
2882afdc71e4SMark Rustad 		 * isn't a way to advertise that we are capable of RX
2883afdc71e4SMark Rustad 		 * Pause ONLY, we will advertise that we support both
2884afdc71e4SMark Rustad 		 * symmetric and asymmetric Rx PAUSE, as such we fall
2885afdc71e4SMark Rustad 		 * through to the fc_full statement.  Later, we will
2886afdc71e4SMark Rustad 		 * disable the adapter's ability to send PAUSE frames.
2887afdc71e4SMark Rustad 		 */
28885463fce6SJeff Kirsher 		fallthrough;
2889afdc71e4SMark Rustad 	case ixgbe_fc_full:
2890afdc71e4SMark Rustad 		pause = true;
2891afdc71e4SMark Rustad 		asm_dir = true;
2892afdc71e4SMark Rustad 		break;
2893afdc71e4SMark Rustad 	default:
2894afdc71e4SMark Rustad 		hw_err(hw, "Flow control param set incorrectly\n");
2895afdc71e4SMark Rustad 		return IXGBE_ERR_CONFIG;
2896afdc71e4SMark Rustad 	}
2897afdc71e4SMark Rustad 
28987adbccbbSTony Nguyen 	switch (hw->device_id) {
28997adbccbbSTony Nguyen 	case IXGBE_DEV_ID_X550EM_X_KR:
29007adbccbbSTony Nguyen 	case IXGBE_DEV_ID_X550EM_A_KR:
29017adbccbbSTony Nguyen 	case IXGBE_DEV_ID_X550EM_A_KR_L:
29029a5c27e6SMark Rustad 		rc = hw->mac.ops.read_iosf_sb_reg(hw,
2903afdc71e4SMark Rustad 					    IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
29049a5c27e6SMark Rustad 					    IXGBE_SB_IOSF_TARGET_KR_PHY,
29059a5c27e6SMark Rustad 					    &reg_val);
2906afdc71e4SMark Rustad 		if (rc)
2907afdc71e4SMark Rustad 			return rc;
2908afdc71e4SMark Rustad 
2909afdc71e4SMark Rustad 		reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
2910afdc71e4SMark Rustad 			     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
2911afdc71e4SMark Rustad 		if (pause)
2912afdc71e4SMark Rustad 			reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
2913afdc71e4SMark Rustad 		if (asm_dir)
2914afdc71e4SMark Rustad 			reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
29159a5c27e6SMark Rustad 		rc = hw->mac.ops.write_iosf_sb_reg(hw,
2916afdc71e4SMark Rustad 					    IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
29179a5c27e6SMark Rustad 					    IXGBE_SB_IOSF_TARGET_KR_PHY,
29189a5c27e6SMark Rustad 					    reg_val);
2919afdc71e4SMark Rustad 
2920afdc71e4SMark Rustad 		/* This device does not fully support AN. */
2921afdc71e4SMark Rustad 		hw->fc.disable_fc_autoneg = true;
29227adbccbbSTony Nguyen 		break;
29237adbccbbSTony Nguyen 	case IXGBE_DEV_ID_X550EM_X_XFI:
29247adbccbbSTony Nguyen 		hw->fc.disable_fc_autoneg = true;
29257adbccbbSTony Nguyen 		break;
29267adbccbbSTony Nguyen 	default:
29277adbccbbSTony Nguyen 		break;
29287adbccbbSTony Nguyen 	}
2929afdc71e4SMark Rustad 	return rc;
2930afdc71e4SMark Rustad }
2931afdc71e4SMark Rustad 
29322916500dSDon Skidmore /**
29332916500dSDon Skidmore  *  ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37
29342916500dSDon Skidmore  *  @hw: pointer to hardware structure
29352916500dSDon Skidmore  **/
29362916500dSDon Skidmore static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
29372916500dSDon Skidmore {
29382916500dSDon Skidmore 	u32 link_s1, lp_an_page_low, an_cntl_1;
29392916500dSDon Skidmore 	s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
29402916500dSDon Skidmore 	ixgbe_link_speed speed;
29412916500dSDon Skidmore 	bool link_up;
29422916500dSDon Skidmore 
29432916500dSDon Skidmore 	/* AN should have completed when the cable was plugged in.
29442916500dSDon Skidmore 	 * Look for reasons to bail out.  Bail out if:
29452916500dSDon Skidmore 	 * - FC autoneg is disabled, or if
29462916500dSDon Skidmore 	 * - link is not up.
29472916500dSDon Skidmore 	 */
29482916500dSDon Skidmore 	if (hw->fc.disable_fc_autoneg) {
29492916500dSDon Skidmore 		hw_err(hw, "Flow control autoneg is disabled");
29502916500dSDon Skidmore 		goto out;
29512916500dSDon Skidmore 	}
29522916500dSDon Skidmore 
29532916500dSDon Skidmore 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
29542916500dSDon Skidmore 	if (!link_up) {
29552916500dSDon Skidmore 		hw_err(hw, "The link is down");
29562916500dSDon Skidmore 		goto out;
29572916500dSDon Skidmore 	}
29582916500dSDon Skidmore 
29592916500dSDon Skidmore 	/* Check at auto-negotiation has completed */
29602916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
29612916500dSDon Skidmore 					IXGBE_KRM_LINK_S1(hw->bus.lan_id),
29622916500dSDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1);
29632916500dSDon Skidmore 
29642916500dSDon Skidmore 	if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
29652916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
29662916500dSDon Skidmore 		status = IXGBE_ERR_FC_NOT_NEGOTIATED;
29672916500dSDon Skidmore 		goto out;
29682916500dSDon Skidmore 	}
29692916500dSDon Skidmore 
29702916500dSDon Skidmore 	/* Read the 10g AN autoc and LP ability registers and resolve
29712916500dSDon Skidmore 	 * local flow control settings accordingly
29722916500dSDon Skidmore 	 */
29732916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
29742916500dSDon Skidmore 				IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
29752916500dSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1);
29762916500dSDon Skidmore 
29772916500dSDon Skidmore 	if (status) {
29782916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
29792916500dSDon Skidmore 		goto out;
29802916500dSDon Skidmore 	}
29812916500dSDon Skidmore 
29822916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
29832916500dSDon Skidmore 				IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id),
29842916500dSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low);
29852916500dSDon Skidmore 
29862916500dSDon Skidmore 	if (status) {
29872916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
29882916500dSDon Skidmore 		goto out;
29892916500dSDon Skidmore 	}
29902916500dSDon Skidmore 
29912916500dSDon Skidmore 	status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low,
29922916500dSDon Skidmore 				    IXGBE_KRM_AN_CNTL_1_SYM_PAUSE,
29932916500dSDon Skidmore 				    IXGBE_KRM_AN_CNTL_1_ASM_PAUSE,
29942916500dSDon Skidmore 				    IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE,
29952916500dSDon Skidmore 				    IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE);
29962916500dSDon Skidmore 
29972916500dSDon Skidmore out:
29982916500dSDon Skidmore 	if (!status) {
29992916500dSDon Skidmore 		hw->fc.fc_was_autonegged = true;
30002916500dSDon Skidmore 	} else {
30012916500dSDon Skidmore 		hw->fc.fc_was_autonegged = false;
30022916500dSDon Skidmore 		hw->fc.current_mode = hw->fc.requested_mode;
30032916500dSDon Skidmore 	}
30042916500dSDon Skidmore }
30052916500dSDon Skidmore 
30062916500dSDon Skidmore /**
30072916500dSDon Skidmore  *  ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings
30082916500dSDon Skidmore  *  @hw: pointer to hardware structure
30092916500dSDon Skidmore  **/
30102916500dSDon Skidmore static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw)
30112916500dSDon Skidmore {
30122916500dSDon Skidmore 	hw->fc.fc_was_autonegged = false;
30132916500dSDon Skidmore 	hw->fc.current_mode = hw->fc.requested_mode;
30142916500dSDon Skidmore }
30152916500dSDon Skidmore 
30166ac74394SDon Skidmore /** ixgbe_enter_lplu_x550em - Transition to low power states
30176ac74394SDon Skidmore  *  @hw: pointer to hardware structure
30186ac74394SDon Skidmore  *
30196ac74394SDon Skidmore  *  Configures Low Power Link Up on transition to low power states
30206ac74394SDon Skidmore  *  (from D0 to non-D0). Link is required to enter LPLU so avoid resetting
30216ac74394SDon Skidmore  *  the X557 PHY immediately prior to entering LPLU.
30226ac74394SDon Skidmore  **/
30236ac74394SDon Skidmore static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
30246ac74394SDon Skidmore {
30256ac74394SDon Skidmore 	u16 an_10g_cntl_reg, autoneg_reg, speed;
30266ac74394SDon Skidmore 	s32 status;
30276ac74394SDon Skidmore 	ixgbe_link_speed lcd_speed;
30286ac74394SDon Skidmore 	u32 save_autoneg;
30296ac74394SDon Skidmore 	bool link_up;
30306ac74394SDon Skidmore 
30316ac74394SDon Skidmore 	/* If blocked by MNG FW, then don't restart AN */
30326ac74394SDon Skidmore 	if (ixgbe_check_reset_blocked(hw))
30336ac74394SDon Skidmore 		return 0;
30346ac74394SDon Skidmore 
30356ac74394SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
30366ac74394SDon Skidmore 	if (status)
30376ac74394SDon Skidmore 		return status;
30386ac74394SDon Skidmore 
30396ac74394SDon Skidmore 	status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3,
30406ac74394SDon Skidmore 				     &hw->eeprom.ctrl_word_3);
30416ac74394SDon Skidmore 	if (status)
30426ac74394SDon Skidmore 		return status;
30436ac74394SDon Skidmore 
30446ac74394SDon Skidmore 	/* If link is down, LPLU disabled in NVM, WoL disabled, or
30456ac74394SDon Skidmore 	 * manageability disabled, then force link down by entering
30466ac74394SDon Skidmore 	 * low power mode.
30476ac74394SDon Skidmore 	 */
30486ac74394SDon Skidmore 	if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
30496ac74394SDon Skidmore 	    !(hw->wol_enabled || ixgbe_mng_present(hw)))
30506ac74394SDon Skidmore 		return ixgbe_set_copper_phy_power(hw, false);
30516ac74394SDon Skidmore 
30526ac74394SDon Skidmore 	/* Determine LCD */
30536ac74394SDon Skidmore 	status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed);
30546ac74394SDon Skidmore 	if (status)
30556ac74394SDon Skidmore 		return status;
30566ac74394SDon Skidmore 
30576ac74394SDon Skidmore 	/* If no valid LCD link speed, then force link down and exit. */
30586ac74394SDon Skidmore 	if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN)
30596ac74394SDon Skidmore 		return ixgbe_set_copper_phy_power(hw, false);
30606ac74394SDon Skidmore 
30616ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
30624dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
30636ac74394SDon Skidmore 				      &speed);
30646ac74394SDon Skidmore 	if (status)
30656ac74394SDon Skidmore 		return status;
30666ac74394SDon Skidmore 
30676ac74394SDon Skidmore 	/* If no link now, speed is invalid so take link down */
30686ac74394SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
30696ac74394SDon Skidmore 	if (status)
30706ac74394SDon Skidmore 		return ixgbe_set_copper_phy_power(hw, false);
30716ac74394SDon Skidmore 
30726ac74394SDon Skidmore 	/* clear everything but the speed bits */
30736ac74394SDon Skidmore 	speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK;
30746ac74394SDon Skidmore 
30756ac74394SDon Skidmore 	/* If current speed is already LCD, then exit. */
30766ac74394SDon Skidmore 	if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) &&
30776ac74394SDon Skidmore 	     (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) ||
30786ac74394SDon Skidmore 	    ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) &&
30796ac74394SDon Skidmore 	     (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL)))
30806ac74394SDon Skidmore 		return status;
30816ac74394SDon Skidmore 
30826ac74394SDon Skidmore 	/* Clear AN completed indication */
30836ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
30844dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
30856ac74394SDon Skidmore 				      &autoneg_reg);
30866ac74394SDon Skidmore 	if (status)
30876ac74394SDon Skidmore 		return status;
30886ac74394SDon Skidmore 
30894dc4000bSEmil Tantilov 	status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
30904dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
30916ac74394SDon Skidmore 				      &an_10g_cntl_reg);
30926ac74394SDon Skidmore 	if (status)
30936ac74394SDon Skidmore 		return status;
30946ac74394SDon Skidmore 
30956ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw,
30966ac74394SDon Skidmore 				      IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
30974dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
30986ac74394SDon Skidmore 				      &autoneg_reg);
30996ac74394SDon Skidmore 	if (status)
31006ac74394SDon Skidmore 		return status;
31016ac74394SDon Skidmore 
31026ac74394SDon Skidmore 	save_autoneg = hw->phy.autoneg_advertised;
31036ac74394SDon Skidmore 
31046ac74394SDon Skidmore 	/* Setup link at least common link speed */
31056ac74394SDon Skidmore 	status = hw->mac.ops.setup_link(hw, lcd_speed, false);
31066ac74394SDon Skidmore 
31076ac74394SDon Skidmore 	/* restore autoneg from before setting lplu speed */
31086ac74394SDon Skidmore 	hw->phy.autoneg_advertised = save_autoneg;
31096ac74394SDon Skidmore 
31106ac74394SDon Skidmore 	return status;
31116ac74394SDon Skidmore }
31126ac74394SDon Skidmore 
3113537cc5dfSMark Rustad /**
3114b3eb4e18SMark Rustad  * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs
3115b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
3116b3eb4e18SMark Rustad  */
3117b3eb4e18SMark Rustad static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw)
3118b3eb4e18SMark Rustad {
3119b3eb4e18SMark Rustad 	u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
3120b3eb4e18SMark Rustad 	s32 rc;
3121b3eb4e18SMark Rustad 
3122b3eb4e18SMark Rustad 	if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
3123b3eb4e18SMark Rustad 		return 0;
3124b3eb4e18SMark Rustad 
3125b3eb4e18SMark Rustad 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store);
3126b3eb4e18SMark Rustad 	if (rc)
3127b3eb4e18SMark Rustad 		return rc;
3128b3eb4e18SMark Rustad 	memset(store, 0, sizeof(store));
3129b3eb4e18SMark Rustad 
3130b3eb4e18SMark Rustad 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store);
3131b3eb4e18SMark Rustad 	if (rc)
3132b3eb4e18SMark Rustad 		return rc;
3133b3eb4e18SMark Rustad 
3134b3eb4e18SMark Rustad 	return ixgbe_setup_fw_link(hw);
3135b3eb4e18SMark Rustad }
3136b3eb4e18SMark Rustad 
3137b3eb4e18SMark Rustad /**
3138b3eb4e18SMark Rustad  * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp
3139b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
3140b3eb4e18SMark Rustad  */
3141b3eb4e18SMark Rustad static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
3142b3eb4e18SMark Rustad {
3143b3eb4e18SMark Rustad 	u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
3144b3eb4e18SMark Rustad 	s32 rc;
3145b3eb4e18SMark Rustad 
3146b3eb4e18SMark Rustad 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);
3147b3eb4e18SMark Rustad 	if (rc)
3148b3eb4e18SMark Rustad 		return rc;
3149b3eb4e18SMark Rustad 
3150b3eb4e18SMark Rustad 	if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {
3151b3eb4e18SMark Rustad 		ixgbe_shutdown_fw_phy(hw);
3152b3eb4e18SMark Rustad 		return IXGBE_ERR_OVERTEMP;
3153b3eb4e18SMark Rustad 	}
3154b3eb4e18SMark Rustad 	return 0;
3155b3eb4e18SMark Rustad }
3156b3eb4e18SMark Rustad 
3157b3eb4e18SMark Rustad /**
3158537cc5dfSMark Rustad  * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register
3159537cc5dfSMark Rustad  * @hw: pointer to hardware structure
3160537cc5dfSMark Rustad  *
3161537cc5dfSMark Rustad  * Read NW_MNG_IF_SEL register and save field values.
3162537cc5dfSMark Rustad  */
3163537cc5dfSMark Rustad static void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw)
3164537cc5dfSMark Rustad {
3165537cc5dfSMark Rustad 	/* Save NW management interface connected on board. This is used
3166537cc5dfSMark Rustad 	 * to determine internal PHY mode.
3167537cc5dfSMark Rustad 	 */
3168537cc5dfSMark Rustad 	hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
3169537cc5dfSMark Rustad 
3170537cc5dfSMark Rustad 	/* If X552 (X550EM_a) and MDIO is connected to external PHY, then set
3171537cc5dfSMark Rustad 	 * PHY address. This register field was has only been used for X552.
3172537cc5dfSMark Rustad 	 */
3173ae3cb8cbSMark Rustad 	if (hw->mac.type == ixgbe_mac_x550em_a &&
3174ae3cb8cbSMark Rustad 	    hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) {
3175537cc5dfSMark Rustad 		hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel &
3176537cc5dfSMark Rustad 				      IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
3177537cc5dfSMark Rustad 				     IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
3178537cc5dfSMark Rustad 	}
3179ae3cb8cbSMark Rustad }
3180537cc5dfSMark Rustad 
31816a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init
31826a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
31836a14ee0cSDon Skidmore  *
31846a14ee0cSDon Skidmore  *  Initialize any function pointers that were not able to be
31856a14ee0cSDon Skidmore  *  set during init_shared_code because the PHY/SFP type was
31866a14ee0cSDon Skidmore  *  not known.  Perform the SFP init if necessary.
31876a14ee0cSDon Skidmore  **/
31887ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
31896a14ee0cSDon Skidmore {
31906a14ee0cSDon Skidmore 	struct ixgbe_phy_info *phy = &hw->phy;
31916a14ee0cSDon Skidmore 	s32 ret_val;
31926a14ee0cSDon Skidmore 
31937e49d616SDon Skidmore 	hw->mac.ops.set_lan_id(hw);
31947e49d616SDon Skidmore 
3195537cc5dfSMark Rustad 	ixgbe_read_mng_if_sel_x550em(hw);
3196537cc5dfSMark Rustad 
3197c3dc4c09SDon Skidmore 	if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) {
31986a14ee0cSDon Skidmore 		phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
3199ab5fe0c5SDon Skidmore 		ixgbe_setup_mux_ctl(hw);
32006a14ee0cSDon Skidmore 	}
32016a14ee0cSDon Skidmore 
32026a14ee0cSDon Skidmore 	/* Identify the PHY or SFP module */
32036a14ee0cSDon Skidmore 	ret_val = phy->ops.identify(hw);
3204c69be946SEmil Tantilov 	if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED ||
3205c69be946SEmil Tantilov 	    ret_val == IXGBE_ERR_PHY_ADDR_INVALID)
3206c69be946SEmil Tantilov 		return ret_val;
32076a14ee0cSDon Skidmore 
3208c3dc4c09SDon Skidmore 	/* Setup function pointers based on detected hardware */
32096a14ee0cSDon Skidmore 	ixgbe_init_mac_link_ops_X550em(hw);
32106a14ee0cSDon Skidmore 	if (phy->sfp_type != ixgbe_sfp_type_unknown)
32116a14ee0cSDon Skidmore 		phy->ops.reset = NULL;
32126a14ee0cSDon Skidmore 
32136a14ee0cSDon Skidmore 	/* Set functions pointers based on phy type */
32146a14ee0cSDon Skidmore 	switch (hw->phy.type) {
32156a14ee0cSDon Skidmore 	case ixgbe_phy_x550em_kx4:
32165fbf5addSTony Nguyen 		phy->ops.setup_link = NULL;
32176a14ee0cSDon Skidmore 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
32186a14ee0cSDon Skidmore 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
32196a14ee0cSDon Skidmore 		break;
32206a14ee0cSDon Skidmore 	case ixgbe_phy_x550em_kr:
32216a14ee0cSDon Skidmore 		phy->ops.setup_link = ixgbe_setup_kr_x550em;
32226a14ee0cSDon Skidmore 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
32236a14ee0cSDon Skidmore 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
32246a14ee0cSDon Skidmore 		break;
322518e01ee7SDon Skidmore 	case ixgbe_phy_x550em_xfi:
322618e01ee7SDon Skidmore 		/* link is managed by HW */
322718e01ee7SDon Skidmore 		phy->ops.setup_link = NULL;
322818e01ee7SDon Skidmore 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
322918e01ee7SDon Skidmore 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
323018e01ee7SDon Skidmore 		break;
32316a14ee0cSDon Skidmore 	case ixgbe_phy_x550em_ext_t:
3232c3dc4c09SDon Skidmore 		/* Save NW management interface connected on board. This is used
3233c3dc4c09SDon Skidmore 		 * to determine internal PHY mode
3234c3dc4c09SDon Skidmore 		 */
3235c3dc4c09SDon Skidmore 		phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
3236c3dc4c09SDon Skidmore 
3237c3dc4c09SDon Skidmore 		/* If internal link mode is XFI, then setup iXFI internal link,
3238c3dc4c09SDon Skidmore 		 * else setup KR now.
3239c3dc4c09SDon Skidmore 		 */
3240c3dc4c09SDon Skidmore 		phy->ops.setup_internal_link =
3241c3dc4c09SDon Skidmore 					      ixgbe_setup_internal_phy_t_x550em;
3242c3dc4c09SDon Skidmore 
32436ac74394SDon Skidmore 		/* setup SW LPLU only for first revision */
32443ca2b250SMark Rustad 		if (hw->mac.type == ixgbe_mac_X550EM_x &&
32453ca2b250SMark Rustad 		    !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) &
32463ca2b250SMark Rustad 		      IXGBE_FUSES0_REV_MASK))
32476ac74394SDon Skidmore 			phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
32486ac74394SDon Skidmore 
3249c3dc4c09SDon Skidmore 		phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
3250f4410d2cSDon Skidmore 		phy->ops.reset = ixgbe_reset_phy_t_X550em;
32516a14ee0cSDon Skidmore 		break;
325218bda0d9SDon Skidmore 	case ixgbe_phy_sgmii:
325318bda0d9SDon Skidmore 		phy->ops.setup_link = NULL;
325418bda0d9SDon Skidmore 		break;
3255b3eb4e18SMark Rustad 	case ixgbe_phy_fw:
3256b3eb4e18SMark Rustad 		phy->ops.setup_link = ixgbe_setup_fw_link;
3257b3eb4e18SMark Rustad 		phy->ops.reset = ixgbe_reset_phy_fw;
3258b3eb4e18SMark Rustad 		break;
32598dc963e1SPaul Greenwalt 	case ixgbe_phy_ext_1g_t:
32608dc963e1SPaul Greenwalt 		phy->ops.setup_link = NULL;
32618dc963e1SPaul Greenwalt 		phy->ops.read_reg = NULL;
32628dc963e1SPaul Greenwalt 		phy->ops.write_reg = NULL;
32635e999fb4SPaul Greenwalt 		phy->ops.reset = NULL;
32648dc963e1SPaul Greenwalt 		break;
32656a14ee0cSDon Skidmore 	default:
32666a14ee0cSDon Skidmore 		break;
32676a14ee0cSDon Skidmore 	}
3268c3dc4c09SDon Skidmore 
32696a14ee0cSDon Skidmore 	return ret_val;
32706a14ee0cSDon Skidmore }
32716a14ee0cSDon Skidmore 
32726a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type
32736a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
32746a14ee0cSDon Skidmore  *
32756a14ee0cSDon Skidmore  *  Returns the media type (fiber, copper, backplane)
32766a14ee0cSDon Skidmore  *
32776a14ee0cSDon Skidmore  */
32787ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
32796a14ee0cSDon Skidmore {
32806a14ee0cSDon Skidmore 	enum ixgbe_media_type media_type;
32816a14ee0cSDon Skidmore 
32826a14ee0cSDon Skidmore 	/* Detect if there is a copper PHY attached. */
32836a14ee0cSDon Skidmore 	switch (hw->device_id) {
3284200157c2SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SGMII:
3285200157c2SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SGMII_L:
3286200157c2SMark Rustad 		hw->phy.type = ixgbe_phy_sgmii;
32875463fce6SJeff Kirsher 		fallthrough;
32886a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_KR:
32896a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_KX4:
329018e01ee7SDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_XFI:
3291f572b2c4SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_KR:
3292f572b2c4SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_KR_L:
32936a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_backplane;
32946a14ee0cSDon Skidmore 		break;
32956a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_SFP:
32962d40cd17SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP:
329749425dfcSMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP_N:
32986a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_fiber;
32996a14ee0cSDon Skidmore 		break;
33006a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_1G_T:
33016a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_10G_T:
330292ed8430SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_10G_T:
3303b3eb4e18SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_1G_T:
3304b3eb4e18SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
33056a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_copper;
33066a14ee0cSDon Skidmore 		break;
33076a14ee0cSDon Skidmore 	default:
33086a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_unknown;
33096a14ee0cSDon Skidmore 		break;
33106a14ee0cSDon Skidmore 	}
33116a14ee0cSDon Skidmore 	return media_type;
33126a14ee0cSDon Skidmore }
33136a14ee0cSDon Skidmore 
33146a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY.
33156a14ee0cSDon Skidmore  ** @hw: pointer to hardware structure
33166a14ee0cSDon Skidmore  **/
33177ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
33186a14ee0cSDon Skidmore {
3319a1e869deSMark Rustad 	s32 status;
33206a14ee0cSDon Skidmore 	u16 reg;
33216a14ee0cSDon Skidmore 
33226a14ee0cSDon Skidmore 	status = hw->phy.ops.read_reg(hw,
33236a14ee0cSDon Skidmore 				      IXGBE_MDIO_TX_VENDOR_ALARMS_3,
33244dc4000bSEmil Tantilov 				      MDIO_MMD_PMAPMD,
33256a14ee0cSDon Skidmore 				      &reg);
33266a14ee0cSDon Skidmore 	if (status)
33276a14ee0cSDon Skidmore 		return status;
33286a14ee0cSDon Skidmore 
3329e2261bccSDon Skidmore 	/* If PHY FW reset completed bit is set then this is the first
3330e2261bccSDon Skidmore 	 * SW instance after a power on so the PHY FW must be un-stalled.
3331e2261bccSDon Skidmore 	 */
3332e2261bccSDon Skidmore 	if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
33336a14ee0cSDon Skidmore 		status = hw->phy.ops.read_reg(hw,
33346a14ee0cSDon Skidmore 					IXGBE_MDIO_GLOBAL_RES_PR_10,
33354dc4000bSEmil Tantilov 					MDIO_MMD_VEND1,
33366a14ee0cSDon Skidmore 					&reg);
33376a14ee0cSDon Skidmore 		if (status)
33386a14ee0cSDon Skidmore 			return status;
33396a14ee0cSDon Skidmore 
33406a14ee0cSDon Skidmore 		reg &= ~IXGBE_MDIO_POWER_UP_STALL;
33416a14ee0cSDon Skidmore 
33426a14ee0cSDon Skidmore 		status = hw->phy.ops.write_reg(hw,
33436a14ee0cSDon Skidmore 					IXGBE_MDIO_GLOBAL_RES_PR_10,
33444dc4000bSEmil Tantilov 					MDIO_MMD_VEND1,
33456a14ee0cSDon Skidmore 					reg);
3346e2261bccSDon Skidmore 		if (status)
3347e2261bccSDon Skidmore 			return status;
3348e2261bccSDon Skidmore 	}
3349e2261bccSDon Skidmore 
33506a14ee0cSDon Skidmore 	return status;
33516a14ee0cSDon Skidmore }
33526a14ee0cSDon Skidmore 
3353e84db727SMark Rustad /**
3354e84db727SMark Rustad  * ixgbe_set_mdio_speed - Set MDIO clock speed
3355e84db727SMark Rustad  * @hw: pointer to hardware structure
3356e84db727SMark Rustad  */
3357e84db727SMark Rustad static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw)
3358e84db727SMark Rustad {
3359e84db727SMark Rustad 	u32 hlreg0;
3360e84db727SMark Rustad 
3361e84db727SMark Rustad 	switch (hw->device_id) {
3362e84db727SMark Rustad 	case IXGBE_DEV_ID_X550EM_X_10G_T:
3363a83c27e7SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_SGMII:
3364a83c27e7SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_SGMII_L:
336592ed8430SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_10G_T:
33662d40cd17SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP:
3367e84db727SMark Rustad 		/* Config MDIO clock speed before the first MDIO PHY access */
3368e84db727SMark Rustad 		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
3369e84db727SMark Rustad 		hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
3370e84db727SMark Rustad 		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
3371e84db727SMark Rustad 		break;
3372b3eb4e18SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_1G_T:
3373b3eb4e18SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
3374b3eb4e18SMark Rustad 		/* Select fast MDIO clock speed for these devices */
3375b3eb4e18SMark Rustad 		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
3376b3eb4e18SMark Rustad 		hlreg0 |= IXGBE_HLREG0_MDCSPD;
3377b3eb4e18SMark Rustad 		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
3378b3eb4e18SMark Rustad 		break;
3379e84db727SMark Rustad 	default:
3380e84db727SMark Rustad 		break;
3381e84db727SMark Rustad 	}
3382e84db727SMark Rustad }
3383e84db727SMark Rustad 
33846a14ee0cSDon Skidmore /**  ixgbe_reset_hw_X550em - Perform hardware reset
33856a14ee0cSDon Skidmore  **  @hw: pointer to hardware structure
33866a14ee0cSDon Skidmore  **
33876a14ee0cSDon Skidmore  **  Resets the hardware by resetting the transmit and receive units, masks
33886a14ee0cSDon Skidmore  **  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
33896a14ee0cSDon Skidmore  **  reset.
33906a14ee0cSDon Skidmore  **/
33917ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
33926a14ee0cSDon Skidmore {
33936a14ee0cSDon Skidmore 	ixgbe_link_speed link_speed;
33946a14ee0cSDon Skidmore 	s32 status;
33956a14ee0cSDon Skidmore 	u32 ctrl = 0;
33966a14ee0cSDon Skidmore 	u32 i;
33976a14ee0cSDon Skidmore 	bool link_up = false;
33986133406bSPaul Greenwalt 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
33996a14ee0cSDon Skidmore 
34006a14ee0cSDon Skidmore 	/* Call adapter stop to disable Tx/Rx and clear interrupts */
34016a14ee0cSDon Skidmore 	status = hw->mac.ops.stop_adapter(hw);
34026a14ee0cSDon Skidmore 	if (status)
34036a14ee0cSDon Skidmore 		return status;
34046a14ee0cSDon Skidmore 
34056a14ee0cSDon Skidmore 	/* flush pending Tx transactions */
34066a14ee0cSDon Skidmore 	ixgbe_clear_tx_pending(hw);
34076a14ee0cSDon Skidmore 
3408*bf0a3750SCyril Novikov 	/* set MDIO speed before talking to the PHY in case it's the 1st time */
3409*bf0a3750SCyril Novikov 	ixgbe_set_mdio_speed(hw);
3410*bf0a3750SCyril Novikov 
34116a14ee0cSDon Skidmore 	/* PHY ops must be identified and initialized prior to reset */
34126a14ee0cSDon Skidmore 	status = hw->phy.ops.init(hw);
3413c69be946SEmil Tantilov 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED ||
3414c69be946SEmil Tantilov 	    status == IXGBE_ERR_PHY_ADDR_INVALID)
3415c69be946SEmil Tantilov 		return status;
34166a14ee0cSDon Skidmore 
34176a14ee0cSDon Skidmore 	/* start the external PHY */
34186a14ee0cSDon Skidmore 	if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
34196a14ee0cSDon Skidmore 		status = ixgbe_init_ext_t_x550em(hw);
34206a14ee0cSDon Skidmore 		if (status)
34216a14ee0cSDon Skidmore 			return status;
34226a14ee0cSDon Skidmore 	}
34236a14ee0cSDon Skidmore 
34246a14ee0cSDon Skidmore 	/* Setup SFP module if there is one present. */
34256a14ee0cSDon Skidmore 	if (hw->phy.sfp_setup_needed) {
34266a14ee0cSDon Skidmore 		status = hw->mac.ops.setup_sfp(hw);
34276a14ee0cSDon Skidmore 		hw->phy.sfp_setup_needed = false;
34286a14ee0cSDon Skidmore 	}
34296a14ee0cSDon Skidmore 
3430bbb27076SEmil Tantilov 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
3431bbb27076SEmil Tantilov 		return status;
3432bbb27076SEmil Tantilov 
34336a14ee0cSDon Skidmore 	/* Reset PHY */
34346a14ee0cSDon Skidmore 	if (!hw->phy.reset_disable && hw->phy.ops.reset)
34356a14ee0cSDon Skidmore 		hw->phy.ops.reset(hw);
34366a14ee0cSDon Skidmore 
34376a14ee0cSDon Skidmore mac_reset_top:
34386a14ee0cSDon Skidmore 	/* Issue global reset to the MAC.  Needs to be SW reset if link is up.
34396a14ee0cSDon Skidmore 	 * If link reset is used when link is up, it might reset the PHY when
34406a14ee0cSDon Skidmore 	 * mng is using it.  If link is down or the flag to force full link
34416a14ee0cSDon Skidmore 	 * reset is set, then perform link reset.
34426a14ee0cSDon Skidmore 	 */
34436a14ee0cSDon Skidmore 	ctrl = IXGBE_CTRL_LNK_RST;
34446a14ee0cSDon Skidmore 
34456a14ee0cSDon Skidmore 	if (!hw->force_full_reset) {
34466a14ee0cSDon Skidmore 		hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
34476a14ee0cSDon Skidmore 		if (link_up)
34486a14ee0cSDon Skidmore 			ctrl = IXGBE_CTRL_RST;
34496a14ee0cSDon Skidmore 	}
34506a14ee0cSDon Skidmore 
34516133406bSPaul Greenwalt 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
34526133406bSPaul Greenwalt 	if (status) {
34536133406bSPaul Greenwalt 		hw_dbg(hw, "semaphore failed with %d", status);
34546133406bSPaul Greenwalt 		return IXGBE_ERR_SWFW_SYNC;
34556133406bSPaul Greenwalt 	}
34566133406bSPaul Greenwalt 
34576a14ee0cSDon Skidmore 	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
34586a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
34596a14ee0cSDon Skidmore 	IXGBE_WRITE_FLUSH(hw);
34606133406bSPaul Greenwalt 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
3461efff2e02SMark Rustad 	usleep_range(1000, 1200);
34626a14ee0cSDon Skidmore 
34636a14ee0cSDon Skidmore 	/* Poll for reset bit to self-clear meaning reset is complete */
34646a14ee0cSDon Skidmore 	for (i = 0; i < 10; i++) {
34656a14ee0cSDon Skidmore 		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
34666a14ee0cSDon Skidmore 		if (!(ctrl & IXGBE_CTRL_RST_MASK))
34676a14ee0cSDon Skidmore 			break;
3468efff2e02SMark Rustad 		udelay(1);
34696a14ee0cSDon Skidmore 	}
34706a14ee0cSDon Skidmore 
34716a14ee0cSDon Skidmore 	if (ctrl & IXGBE_CTRL_RST_MASK) {
34726a14ee0cSDon Skidmore 		status = IXGBE_ERR_RESET_FAILED;
34736a14ee0cSDon Skidmore 		hw_dbg(hw, "Reset polling failed to complete.\n");
34746a14ee0cSDon Skidmore 	}
34756a14ee0cSDon Skidmore 
34766a14ee0cSDon Skidmore 	msleep(50);
34776a14ee0cSDon Skidmore 
34786a14ee0cSDon Skidmore 	/* Double resets are required for recovery from certain error
34796a14ee0cSDon Skidmore 	 * clear the multicast table.  Also reset num_rar_entries to 128,
34806a14ee0cSDon Skidmore 	 * since we modify this value when programming the SAN MAC address.
34816a14ee0cSDon Skidmore 	 */
34826a14ee0cSDon Skidmore 	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
34836a14ee0cSDon Skidmore 		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
34846a14ee0cSDon Skidmore 		goto mac_reset_top;
34856a14ee0cSDon Skidmore 	}
34866a14ee0cSDon Skidmore 
34876a14ee0cSDon Skidmore 	/* Store the permanent mac address */
34886a14ee0cSDon Skidmore 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
34896a14ee0cSDon Skidmore 
34906a14ee0cSDon Skidmore 	/* Store MAC address from RAR0, clear receive address registers, and
34916a14ee0cSDon Skidmore 	 * clear the multicast table.  Also reset num_rar_entries to 128,
34926a14ee0cSDon Skidmore 	 * since we modify this value when programming the SAN MAC address.
34936a14ee0cSDon Skidmore 	 */
34946a14ee0cSDon Skidmore 	hw->mac.num_rar_entries = 128;
34956a14ee0cSDon Skidmore 	hw->mac.ops.init_rx_addrs(hw);
34966a14ee0cSDon Skidmore 
3497e84db727SMark Rustad 	ixgbe_set_mdio_speed(hw);
3498deda562aSDon Skidmore 
3499ab5fe0c5SDon Skidmore 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
3500ab5fe0c5SDon Skidmore 		ixgbe_setup_mux_ctl(hw);
3501ab5fe0c5SDon Skidmore 
35026a14ee0cSDon Skidmore 	return status;
35036a14ee0cSDon Skidmore }
35046a14ee0cSDon Skidmore 
35055b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype
35065b7f000fSDon Skidmore  *	anti-spoofing
35075b7f000fSDon Skidmore  *  @hw:  pointer to hardware structure
35085b7f000fSDon Skidmore  *  @enable: enable or disable switch for Ethertype anti-spoofing
35095b7f000fSDon Skidmore  *  @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing
35105b7f000fSDon Skidmore  **/
3511bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
3512bc035fc5SDon Skidmore 						   bool enable, int vf)
35135b7f000fSDon Skidmore {
35145b7f000fSDon Skidmore 	int vf_target_reg = vf >> 3;
35155b7f000fSDon Skidmore 	int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT;
35165b7f000fSDon Skidmore 	u32 pfvfspoof;
35175b7f000fSDon Skidmore 
35185b7f000fSDon Skidmore 	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
35195b7f000fSDon Skidmore 	if (enable)
3520b4f47a48SJacob Keller 		pfvfspoof |= BIT(vf_target_shift);
35215b7f000fSDon Skidmore 	else
3522b4f47a48SJacob Keller 		pfvfspoof &= ~BIT(vf_target_shift);
35235b7f000fSDon Skidmore 
35245b7f000fSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
35255b7f000fSDon Skidmore }
35265b7f000fSDon Skidmore 
35276d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning
35286d4c96adSDon Skidmore  *  @hw: pointer to hardware structure
35296d4c96adSDon Skidmore  *  @enable: enable or disable source address pruning
35306d4c96adSDon Skidmore  *  @pool: Rx pool to set source address pruning for
35316d4c96adSDon Skidmore  **/
35326d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
35336d4c96adSDon Skidmore 						  bool enable,
35346d4c96adSDon Skidmore 						  unsigned int pool)
35356d4c96adSDon Skidmore {
35366d4c96adSDon Skidmore 	u64 pfflp;
35376d4c96adSDon Skidmore 
35386d4c96adSDon Skidmore 	/* max rx pool is 63 */
35396d4c96adSDon Skidmore 	if (pool > 63)
35406d4c96adSDon Skidmore 		return;
35416d4c96adSDon Skidmore 
35426d4c96adSDon Skidmore 	pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL);
35436d4c96adSDon Skidmore 	pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32;
35446d4c96adSDon Skidmore 
35456d4c96adSDon Skidmore 	if (enable)
35466d4c96adSDon Skidmore 		pfflp |= (1ULL << pool);
35476d4c96adSDon Skidmore 	else
35486d4c96adSDon Skidmore 		pfflp &= ~(1ULL << pool);
35496d4c96adSDon Skidmore 
35506d4c96adSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp);
35516d4c96adSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32));
35526d4c96adSDon Skidmore }
35536d4c96adSDon Skidmore 
3554449e21a9SMark Rustad /**
35552916500dSDon Skidmore  *  ixgbe_setup_fc_backplane_x550em_a - Set up flow control
35562916500dSDon Skidmore  *  @hw: pointer to hardware structure
35572916500dSDon Skidmore  *
35582916500dSDon Skidmore  *  Called at init time to set up flow control.
35592916500dSDon Skidmore  **/
35602916500dSDon Skidmore static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw)
35612916500dSDon Skidmore {
35622916500dSDon Skidmore 	s32 status = 0;
35632916500dSDon Skidmore 	u32 an_cntl = 0;
35642916500dSDon Skidmore 
35652916500dSDon Skidmore 	/* Validate the requested mode */
35662916500dSDon Skidmore 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
35672916500dSDon Skidmore 		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
35682916500dSDon Skidmore 		return IXGBE_ERR_INVALID_LINK_SETTINGS;
35692916500dSDon Skidmore 	}
35702916500dSDon Skidmore 
35712916500dSDon Skidmore 	if (hw->fc.requested_mode == ixgbe_fc_default)
35722916500dSDon Skidmore 		hw->fc.requested_mode = ixgbe_fc_full;
35732916500dSDon Skidmore 
35742916500dSDon Skidmore 	/* Set up the 1G and 10G flow control advertisement registers so the
35752916500dSDon Skidmore 	 * HW will be able to do FC autoneg once the cable is plugged in.  If
35762916500dSDon Skidmore 	 * we link at 10G, the 1G advertisement is harmless and vice versa.
35772916500dSDon Skidmore 	 */
35782916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
35792916500dSDon Skidmore 					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
35802916500dSDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl);
35812916500dSDon Skidmore 
35822916500dSDon Skidmore 	if (status) {
35832916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
35842916500dSDon Skidmore 		return status;
35852916500dSDon Skidmore 	}
35862916500dSDon Skidmore 
35872916500dSDon Skidmore 	/* The possible values of fc.requested_mode are:
35882916500dSDon Skidmore 	 * 0: Flow control is completely disabled
35892916500dSDon Skidmore 	 * 1: Rx flow control is enabled (we can receive pause frames,
35902916500dSDon Skidmore 	 *    but not send pause frames).
35912916500dSDon Skidmore 	 * 2: Tx flow control is enabled (we can send pause frames but
35922916500dSDon Skidmore 	 *    we do not support receiving pause frames).
35932916500dSDon Skidmore 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
35942916500dSDon Skidmore 	 * other: Invalid.
35952916500dSDon Skidmore 	 */
35962916500dSDon Skidmore 	switch (hw->fc.requested_mode) {
35972916500dSDon Skidmore 	case ixgbe_fc_none:
35982916500dSDon Skidmore 		/* Flow control completely disabled by software override. */
35992916500dSDon Skidmore 		an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
36002916500dSDon Skidmore 			     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
36012916500dSDon Skidmore 		break;
36022916500dSDon Skidmore 	case ixgbe_fc_tx_pause:
36032916500dSDon Skidmore 		/* Tx Flow control is enabled, and Rx Flow control is
36042916500dSDon Skidmore 		 * disabled by software override.
36052916500dSDon Skidmore 		 */
36062916500dSDon Skidmore 		an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
36072916500dSDon Skidmore 		an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
36082916500dSDon Skidmore 		break;
36092916500dSDon Skidmore 	case ixgbe_fc_rx_pause:
36102916500dSDon Skidmore 		/* Rx Flow control is enabled and Tx Flow control is
36112916500dSDon Skidmore 		 * disabled by software override. Since there really
36122916500dSDon Skidmore 		 * isn't a way to advertise that we are capable of RX
36132916500dSDon Skidmore 		 * Pause ONLY, we will advertise that we support both
36142916500dSDon Skidmore 		 * symmetric and asymmetric Rx PAUSE, as such we fall
36152916500dSDon Skidmore 		 * through to the fc_full statement.  Later, we will
36162916500dSDon Skidmore 		 * disable the adapter's ability to send PAUSE frames.
36172916500dSDon Skidmore 		 */
36182916500dSDon Skidmore 	case ixgbe_fc_full:
36192916500dSDon Skidmore 		/* Flow control (both Rx and Tx) is enabled by SW override. */
36202916500dSDon Skidmore 		an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
36212916500dSDon Skidmore 			   IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
36222916500dSDon Skidmore 		break;
36232916500dSDon Skidmore 	default:
36242916500dSDon Skidmore 		hw_err(hw, "Flow control param set incorrectly\n");
36252916500dSDon Skidmore 		return IXGBE_ERR_CONFIG;
36262916500dSDon Skidmore 	}
36272916500dSDon Skidmore 
36282916500dSDon Skidmore 	status = hw->mac.ops.write_iosf_sb_reg(hw,
36292916500dSDon Skidmore 					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
36302916500dSDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl);
36312916500dSDon Skidmore 
36322916500dSDon Skidmore 	/* Restart auto-negotiation. */
3633470739b5SDon Skidmore 	status = ixgbe_restart_an_internal_phy_x550em(hw);
36342916500dSDon Skidmore 
36352916500dSDon Skidmore 	return status;
36362916500dSDon Skidmore }
36372916500dSDon Skidmore 
36382916500dSDon Skidmore /**
3639449e21a9SMark Rustad  * ixgbe_set_mux - Set mux for port 1 access with CS4227
3640449e21a9SMark Rustad  * @hw: pointer to hardware structure
3641449e21a9SMark Rustad  * @state: set mux if 1, clear if 0
3642449e21a9SMark Rustad  */
3643449e21a9SMark Rustad static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state)
3644449e21a9SMark Rustad {
3645449e21a9SMark Rustad 	u32 esdp;
3646449e21a9SMark Rustad 
3647449e21a9SMark Rustad 	if (!hw->bus.lan_id)
3648449e21a9SMark Rustad 		return;
3649449e21a9SMark Rustad 	esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
3650449e21a9SMark Rustad 	if (state)
3651449e21a9SMark Rustad 		esdp |= IXGBE_ESDP_SDP1;
3652449e21a9SMark Rustad 	else
3653449e21a9SMark Rustad 		esdp &= ~IXGBE_ESDP_SDP1;
3654449e21a9SMark Rustad 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
3655449e21a9SMark Rustad 	IXGBE_WRITE_FLUSH(hw);
3656449e21a9SMark Rustad }
3657449e21a9SMark Rustad 
3658449e21a9SMark Rustad /**
3659449e21a9SMark Rustad  * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore
3660449e21a9SMark Rustad  * @hw: pointer to hardware structure
3661449e21a9SMark Rustad  * @mask: Mask to specify which semaphore to acquire
3662449e21a9SMark Rustad  *
3663449e21a9SMark Rustad  * Acquires the SWFW semaphore and sets the I2C MUX
3664449e21a9SMark Rustad  */
3665449e21a9SMark Rustad static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
3666449e21a9SMark Rustad {
3667449e21a9SMark Rustad 	s32 status;
3668449e21a9SMark Rustad 
3669449e21a9SMark Rustad 	status = ixgbe_acquire_swfw_sync_X540(hw, mask);
3670449e21a9SMark Rustad 	if (status)
3671449e21a9SMark Rustad 		return status;
3672449e21a9SMark Rustad 
3673449e21a9SMark Rustad 	if (mask & IXGBE_GSSR_I2C_MASK)
3674449e21a9SMark Rustad 		ixgbe_set_mux(hw, 1);
3675449e21a9SMark Rustad 
3676449e21a9SMark Rustad 	return 0;
3677449e21a9SMark Rustad }
3678449e21a9SMark Rustad 
3679449e21a9SMark Rustad /**
3680449e21a9SMark Rustad  * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore
3681449e21a9SMark Rustad  * @hw: pointer to hardware structure
3682449e21a9SMark Rustad  * @mask: Mask to specify which semaphore to release
3683449e21a9SMark Rustad  *
3684449e21a9SMark Rustad  * Releases the SWFW semaphore and sets the I2C MUX
3685449e21a9SMark Rustad  */
3686449e21a9SMark Rustad static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
3687449e21a9SMark Rustad {
3688449e21a9SMark Rustad 	if (mask & IXGBE_GSSR_I2C_MASK)
3689449e21a9SMark Rustad 		ixgbe_set_mux(hw, 0);
3690449e21a9SMark Rustad 
3691449e21a9SMark Rustad 	ixgbe_release_swfw_sync_X540(hw, mask);
3692449e21a9SMark Rustad }
3693449e21a9SMark Rustad 
369449425dfcSMark Rustad /**
369549425dfcSMark Rustad  * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore
369649425dfcSMark Rustad  * @hw: pointer to hardware structure
369749425dfcSMark Rustad  * @mask: Mask to specify which semaphore to acquire
369849425dfcSMark Rustad  *
369949425dfcSMark Rustad  * Acquires the SWFW semaphore and get the shared PHY token as needed
370049425dfcSMark Rustad  */
370149425dfcSMark Rustad static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask)
370249425dfcSMark Rustad {
370349425dfcSMark Rustad 	u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
370449425dfcSMark Rustad 	int retries = FW_PHY_TOKEN_RETRIES;
370549425dfcSMark Rustad 	s32 status;
370649425dfcSMark Rustad 
370749425dfcSMark Rustad 	while (--retries) {
370849425dfcSMark Rustad 		status = 0;
370949425dfcSMark Rustad 		if (hmask)
371049425dfcSMark Rustad 			status = ixgbe_acquire_swfw_sync_X540(hw, hmask);
371149425dfcSMark Rustad 		if (status)
371249425dfcSMark Rustad 			return status;
371349425dfcSMark Rustad 		if (!(mask & IXGBE_GSSR_TOKEN_SM))
371449425dfcSMark Rustad 			return 0;
371549425dfcSMark Rustad 
371649425dfcSMark Rustad 		status = ixgbe_get_phy_token(hw);
371749425dfcSMark Rustad 		if (!status)
371849425dfcSMark Rustad 			return 0;
371949425dfcSMark Rustad 		if (hmask)
372049425dfcSMark Rustad 			ixgbe_release_swfw_sync_X540(hw, hmask);
372149425dfcSMark Rustad 		if (status != IXGBE_ERR_TOKEN_RETRY)
372249425dfcSMark Rustad 			return status;
3723d4f90d9dSArnd Bergmann 		msleep(FW_PHY_TOKEN_DELAY);
372449425dfcSMark Rustad 	}
372549425dfcSMark Rustad 
372649425dfcSMark Rustad 	return status;
372749425dfcSMark Rustad }
372849425dfcSMark Rustad 
372949425dfcSMark Rustad /**
373049425dfcSMark Rustad  * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore
373149425dfcSMark Rustad  * @hw: pointer to hardware structure
373249425dfcSMark Rustad  * @mask: Mask to specify which semaphore to release
373349425dfcSMark Rustad  *
373449425dfcSMark Rustad  * Release the SWFW semaphore and puts the shared PHY token as needed
373549425dfcSMark Rustad  */
373649425dfcSMark Rustad static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask)
373749425dfcSMark Rustad {
373849425dfcSMark Rustad 	u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
373949425dfcSMark Rustad 
374049425dfcSMark Rustad 	if (mask & IXGBE_GSSR_TOKEN_SM)
374149425dfcSMark Rustad 		ixgbe_put_phy_token(hw);
374249425dfcSMark Rustad 
374349425dfcSMark Rustad 	if (hmask)
374449425dfcSMark Rustad 		ixgbe_release_swfw_sync_X540(hw, hmask);
374549425dfcSMark Rustad }
374649425dfcSMark Rustad 
3747d31afc8fSMark Rustad /**
3748d31afc8fSMark Rustad  * ixgbe_read_phy_reg_x550a - Reads specified PHY register
3749d31afc8fSMark Rustad  * @hw: pointer to hardware structure
3750d31afc8fSMark Rustad  * @reg_addr: 32 bit address of PHY register to read
37515ba643c6STony Nguyen  * @device_type: 5 bit device type
3752d31afc8fSMark Rustad  * @phy_data: Pointer to read data from PHY register
3753d31afc8fSMark Rustad  *
3754d31afc8fSMark Rustad  * Reads a value from a specified PHY register using the SWFW lock and PHY
3755d31afc8fSMark Rustad  * Token. The PHY Token is needed since the MDIO is shared between to MAC
3756d31afc8fSMark Rustad  * instances.
3757d31afc8fSMark Rustad  */
3758d31afc8fSMark Rustad static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
3759d31afc8fSMark Rustad 				    u32 device_type, u16 *phy_data)
3760d31afc8fSMark Rustad {
3761d31afc8fSMark Rustad 	u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
3762d31afc8fSMark Rustad 	s32 status;
3763d31afc8fSMark Rustad 
3764d31afc8fSMark Rustad 	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
3765d31afc8fSMark Rustad 		return IXGBE_ERR_SWFW_SYNC;
3766d31afc8fSMark Rustad 
3767d31afc8fSMark Rustad 	status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data);
3768d31afc8fSMark Rustad 
3769d31afc8fSMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
3770d31afc8fSMark Rustad 
3771d31afc8fSMark Rustad 	return status;
3772d31afc8fSMark Rustad }
3773d31afc8fSMark Rustad 
3774d31afc8fSMark Rustad /**
3775d31afc8fSMark Rustad  * ixgbe_write_phy_reg_x550a - Writes specified PHY register
3776d31afc8fSMark Rustad  * @hw: pointer to hardware structure
3777d31afc8fSMark Rustad  * @reg_addr: 32 bit PHY register to write
3778d31afc8fSMark Rustad  * @device_type: 5 bit device type
3779d31afc8fSMark Rustad  * @phy_data: Data to write to the PHY register
3780d31afc8fSMark Rustad  *
3781d31afc8fSMark Rustad  * Writes a value to specified PHY register using the SWFW lock and PHY Token.
3782d31afc8fSMark Rustad  * The PHY Token is needed since the MDIO is shared between to MAC instances.
3783d31afc8fSMark Rustad  */
3784d31afc8fSMark Rustad static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
3785d31afc8fSMark Rustad 				     u32 device_type, u16 phy_data)
3786d31afc8fSMark Rustad {
3787d31afc8fSMark Rustad 	u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
3788d31afc8fSMark Rustad 	s32 status;
3789d31afc8fSMark Rustad 
3790d31afc8fSMark Rustad 	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
3791d31afc8fSMark Rustad 		return IXGBE_ERR_SWFW_SYNC;
3792d31afc8fSMark Rustad 
3793d31afc8fSMark Rustad 	status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data);
3794d31afc8fSMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
3795d31afc8fSMark Rustad 
3796d31afc8fSMark Rustad 	return status;
3797d31afc8fSMark Rustad }
3798d31afc8fSMark Rustad 
37996a14ee0cSDon Skidmore #define X550_COMMON_MAC \
38006a14ee0cSDon Skidmore 	.init_hw			= &ixgbe_init_hw_generic, \
38016a14ee0cSDon Skidmore 	.start_hw			= &ixgbe_start_hw_X540, \
38026a14ee0cSDon Skidmore 	.clear_hw_cntrs			= &ixgbe_clear_hw_cntrs_generic, \
38036a14ee0cSDon Skidmore 	.enable_rx_dma			= &ixgbe_enable_rx_dma_generic, \
38046a14ee0cSDon Skidmore 	.get_mac_addr			= &ixgbe_get_mac_addr_generic, \
38056a14ee0cSDon Skidmore 	.get_device_caps		= &ixgbe_get_device_caps_generic, \
38066a14ee0cSDon Skidmore 	.stop_adapter			= &ixgbe_stop_adapter_generic, \
38076a14ee0cSDon Skidmore 	.set_lan_id			= &ixgbe_set_lan_id_multi_port_pcie, \
38086a14ee0cSDon Skidmore 	.read_analog_reg8		= NULL, \
38096a14ee0cSDon Skidmore 	.write_analog_reg8		= NULL, \
38106a14ee0cSDon Skidmore 	.set_rxpba			= &ixgbe_set_rxpba_generic, \
38116a14ee0cSDon Skidmore 	.check_link			= &ixgbe_check_mac_link_generic, \
38126a14ee0cSDon Skidmore 	.blink_led_start		= &ixgbe_blink_led_start_X540, \
38136a14ee0cSDon Skidmore 	.blink_led_stop			= &ixgbe_blink_led_stop_X540, \
38146a14ee0cSDon Skidmore 	.set_rar			= &ixgbe_set_rar_generic, \
38156a14ee0cSDon Skidmore 	.clear_rar			= &ixgbe_clear_rar_generic, \
38166a14ee0cSDon Skidmore 	.set_vmdq			= &ixgbe_set_vmdq_generic, \
38176a14ee0cSDon Skidmore 	.set_vmdq_san_mac		= &ixgbe_set_vmdq_san_mac_generic, \
38186a14ee0cSDon Skidmore 	.clear_vmdq			= &ixgbe_clear_vmdq_generic, \
38196a14ee0cSDon Skidmore 	.init_rx_addrs			= &ixgbe_init_rx_addrs_generic, \
38206a14ee0cSDon Skidmore 	.update_mc_addr_list		= &ixgbe_update_mc_addr_list_generic, \
38216a14ee0cSDon Skidmore 	.enable_mc			= &ixgbe_enable_mc_generic, \
38226a14ee0cSDon Skidmore 	.disable_mc			= &ixgbe_disable_mc_generic, \
38236a14ee0cSDon Skidmore 	.clear_vfta			= &ixgbe_clear_vfta_generic, \
38246a14ee0cSDon Skidmore 	.set_vfta			= &ixgbe_set_vfta_generic, \
38256a14ee0cSDon Skidmore 	.fc_enable			= &ixgbe_fc_enable_generic, \
3826cb8e0514STony Nguyen 	.set_fw_drv_ver			= &ixgbe_set_fw_drv_ver_x550, \
38276a14ee0cSDon Skidmore 	.init_uta_tables		= &ixgbe_init_uta_tables_generic, \
38286a14ee0cSDon Skidmore 	.set_mac_anti_spoofing		= &ixgbe_set_mac_anti_spoofing, \
38296a14ee0cSDon Skidmore 	.set_vlan_anti_spoofing		= &ixgbe_set_vlan_anti_spoofing, \
38306d4c96adSDon Skidmore 	.set_source_address_pruning	= \
38316d4c96adSDon Skidmore 				&ixgbe_set_source_address_pruning_X550, \
38325b7f000fSDon Skidmore 	.set_ethertype_anti_spoofing	= \
38335b7f000fSDon Skidmore 				&ixgbe_set_ethertype_anti_spoofing_X550, \
38346a14ee0cSDon Skidmore 	.disable_rx_buff		= &ixgbe_disable_rx_buff_generic, \
38356a14ee0cSDon Skidmore 	.enable_rx_buff			= &ixgbe_enable_rx_buff_generic, \
38366a14ee0cSDon Skidmore 	.get_thermal_sensor_data	= NULL, \
38376a14ee0cSDon Skidmore 	.init_thermal_sensor_thresh	= NULL, \
383859dd45d5SSebastian Basierski 	.fw_recovery_mode		= &ixgbe_fw_recovery_mode_X550, \
38391f9ac57cSDon Skidmore 	.enable_rx			= &ixgbe_enable_rx_generic, \
38401f9ac57cSDon Skidmore 	.disable_rx			= &ixgbe_disable_rx_x550, \
38416a14ee0cSDon Skidmore 
384237689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550 = {
38436a14ee0cSDon Skidmore 	X550_COMMON_MAC
3844a0ad55a3SDon Skidmore 	.led_on			= ixgbe_led_on_generic,
3845a0ad55a3SDon Skidmore 	.led_off		= ixgbe_led_off_generic,
3846805cedd6SDon Skidmore 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
38476a14ee0cSDon Skidmore 	.reset_hw		= &ixgbe_reset_hw_X540,
38486a14ee0cSDon Skidmore 	.get_media_type		= &ixgbe_get_media_type_X540,
38496a14ee0cSDon Skidmore 	.get_san_mac_addr	= &ixgbe_get_san_mac_addr_generic,
38506a14ee0cSDon Skidmore 	.get_wwn_prefix		= &ixgbe_get_wwn_prefix_generic,
38516a14ee0cSDon Skidmore 	.setup_link		= &ixgbe_setup_mac_link_X540,
38526a14ee0cSDon Skidmore 	.get_link_capabilities	= &ixgbe_get_copper_link_capabilities_generic,
3853454c65ddSDon Skidmore 	.get_bus_info		= &ixgbe_get_bus_info_generic,
38546a14ee0cSDon Skidmore 	.setup_sfp		= NULL,
3855449e21a9SMark Rustad 	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X540,
3856449e21a9SMark Rustad 	.release_swfw_sync	= &ixgbe_release_swfw_sync_X540,
3857dbd15b8fSDon Skidmore 	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
3858afdc71e4SMark Rustad 	.prot_autoc_read	= prot_autoc_read_generic,
3859afdc71e4SMark Rustad 	.prot_autoc_write	= prot_autoc_write_generic,
3860afdc71e4SMark Rustad 	.setup_fc		= ixgbe_setup_fc_generic,
38612916500dSDon Skidmore 	.fc_autoneg		= ixgbe_fc_autoneg,
38626a14ee0cSDon Skidmore };
38636a14ee0cSDon Skidmore 
386437689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550EM_x = {
38656a14ee0cSDon Skidmore 	X550_COMMON_MAC
3866a0ad55a3SDon Skidmore 	.led_on			= ixgbe_led_on_t_x550em,
3867a0ad55a3SDon Skidmore 	.led_off		= ixgbe_led_off_t_x550em,
3868805cedd6SDon Skidmore 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
38696a14ee0cSDon Skidmore 	.reset_hw		= &ixgbe_reset_hw_X550em,
38706a14ee0cSDon Skidmore 	.get_media_type		= &ixgbe_get_media_type_X550em,
38716a14ee0cSDon Skidmore 	.get_san_mac_addr	= NULL,
38726a14ee0cSDon Skidmore 	.get_wwn_prefix		= NULL,
38734695886cSEmil Tantilov 	.setup_link		= &ixgbe_setup_mac_link_X540,
38746a14ee0cSDon Skidmore 	.get_link_capabilities	= &ixgbe_get_link_capabilities_X550em,
3875454c65ddSDon Skidmore 	.get_bus_info		= &ixgbe_get_bus_info_X550em,
38766a14ee0cSDon Skidmore 	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
3877449e21a9SMark Rustad 	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X550em,
3878449e21a9SMark Rustad 	.release_swfw_sync	= &ixgbe_release_swfw_sync_X550em,
3879dbd15b8fSDon Skidmore 	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
3880afdc71e4SMark Rustad 	.setup_fc		= NULL, /* defined later */
38812916500dSDon Skidmore 	.fc_autoneg		= ixgbe_fc_autoneg,
38829a5c27e6SMark Rustad 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550,
38839a5c27e6SMark Rustad 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550,
38846a14ee0cSDon Skidmore };
38856a14ee0cSDon Skidmore 
38865e999fb4SPaul Greenwalt static const struct ixgbe_mac_operations mac_ops_X550EM_x_fw = {
38875e999fb4SPaul Greenwalt 	X550_COMMON_MAC
38885e999fb4SPaul Greenwalt 	.led_on			= NULL,
38895e999fb4SPaul Greenwalt 	.led_off		= NULL,
38905e999fb4SPaul Greenwalt 	.init_led_link_act	= NULL,
38915e999fb4SPaul Greenwalt 	.reset_hw		= &ixgbe_reset_hw_X550em,
38925e999fb4SPaul Greenwalt 	.get_media_type		= &ixgbe_get_media_type_X550em,
38935e999fb4SPaul Greenwalt 	.get_san_mac_addr	= NULL,
38945e999fb4SPaul Greenwalt 	.get_wwn_prefix		= NULL,
38955e999fb4SPaul Greenwalt 	.setup_link		= &ixgbe_setup_mac_link_X540,
38965e999fb4SPaul Greenwalt 	.get_link_capabilities	= &ixgbe_get_link_capabilities_X550em,
38975e999fb4SPaul Greenwalt 	.get_bus_info		= &ixgbe_get_bus_info_X550em,
38985e999fb4SPaul Greenwalt 	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
38995e999fb4SPaul Greenwalt 	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X550em,
39005e999fb4SPaul Greenwalt 	.release_swfw_sync	= &ixgbe_release_swfw_sync_X550em,
39015e999fb4SPaul Greenwalt 	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
39025e999fb4SPaul Greenwalt 	.setup_fc		= NULL,
39035e999fb4SPaul Greenwalt 	.fc_autoneg		= ixgbe_fc_autoneg,
39045e999fb4SPaul Greenwalt 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550,
39055e999fb4SPaul Greenwalt 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550,
39065e999fb4SPaul Greenwalt };
39075e999fb4SPaul Greenwalt 
39082e033eacSBhumika Goyal static const struct ixgbe_mac_operations mac_ops_x550em_a = {
390949425dfcSMark Rustad 	X550_COMMON_MAC
3910a0ad55a3SDon Skidmore 	.led_on			= ixgbe_led_on_t_x550em,
3911a0ad55a3SDon Skidmore 	.led_off		= ixgbe_led_off_t_x550em,
3912805cedd6SDon Skidmore 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
391349425dfcSMark Rustad 	.reset_hw		= ixgbe_reset_hw_X550em,
391449425dfcSMark Rustad 	.get_media_type		= ixgbe_get_media_type_X550em,
391549425dfcSMark Rustad 	.get_san_mac_addr	= NULL,
391649425dfcSMark Rustad 	.get_wwn_prefix		= NULL,
39175b9d3cfbSEmil Tantilov 	.setup_link		= &ixgbe_setup_mac_link_X540,
391849425dfcSMark Rustad 	.get_link_capabilities	= ixgbe_get_link_capabilities_X550em,
391949425dfcSMark Rustad 	.get_bus_info		= ixgbe_get_bus_info_X550em,
392049425dfcSMark Rustad 	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
392149425dfcSMark Rustad 	.acquire_swfw_sync	= ixgbe_acquire_swfw_sync_x550em_a,
392249425dfcSMark Rustad 	.release_swfw_sync	= ixgbe_release_swfw_sync_x550em_a,
3923a0254a70SMark Rustad 	.setup_fc		= ixgbe_setup_fc_x550em,
3924470739b5SDon Skidmore 	.fc_autoneg		= ixgbe_fc_autoneg,
392549425dfcSMark Rustad 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550a,
392649425dfcSMark Rustad 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550a,
392749425dfcSMark Rustad };
392849425dfcSMark Rustad 
39292e033eacSBhumika Goyal static const struct ixgbe_mac_operations mac_ops_x550em_a_fw = {
3930b3eb4e18SMark Rustad 	X550_COMMON_MAC
3931b3eb4e18SMark Rustad 	.led_on			= ixgbe_led_on_generic,
3932b3eb4e18SMark Rustad 	.led_off		= ixgbe_led_off_generic,
3933b3eb4e18SMark Rustad 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
3934b3eb4e18SMark Rustad 	.reset_hw		= ixgbe_reset_hw_X550em,
3935b3eb4e18SMark Rustad 	.get_media_type		= ixgbe_get_media_type_X550em,
3936b3eb4e18SMark Rustad 	.get_san_mac_addr	= NULL,
3937b3eb4e18SMark Rustad 	.get_wwn_prefix		= NULL,
3938b3eb4e18SMark Rustad 	.setup_link		= NULL, /* defined later */
3939b3eb4e18SMark Rustad 	.get_link_capabilities	= ixgbe_get_link_capabilities_X550em,
3940b3eb4e18SMark Rustad 	.get_bus_info		= ixgbe_get_bus_info_X550em,
3941b3eb4e18SMark Rustad 	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
3942b3eb4e18SMark Rustad 	.acquire_swfw_sync	= ixgbe_acquire_swfw_sync_x550em_a,
3943b3eb4e18SMark Rustad 	.release_swfw_sync	= ixgbe_release_swfw_sync_x550em_a,
3944b3eb4e18SMark Rustad 	.setup_fc		= ixgbe_setup_fc_x550em,
3945b3eb4e18SMark Rustad 	.fc_autoneg		= ixgbe_fc_autoneg,
3946b3eb4e18SMark Rustad 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550a,
3947b3eb4e18SMark Rustad 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550a,
3948b3eb4e18SMark Rustad };
3949b3eb4e18SMark Rustad 
39506a14ee0cSDon Skidmore #define X550_COMMON_EEP \
39516a14ee0cSDon Skidmore 	.read			= &ixgbe_read_ee_hostif_X550, \
39526a14ee0cSDon Skidmore 	.read_buffer		= &ixgbe_read_ee_hostif_buffer_X550, \
39536a14ee0cSDon Skidmore 	.write			= &ixgbe_write_ee_hostif_X550, \
39546a14ee0cSDon Skidmore 	.write_buffer		= &ixgbe_write_ee_hostif_buffer_X550, \
39556a14ee0cSDon Skidmore 	.validate_checksum	= &ixgbe_validate_eeprom_checksum_X550, \
39566a14ee0cSDon Skidmore 	.update_checksum	= &ixgbe_update_eeprom_checksum_X550, \
39576a14ee0cSDon Skidmore 	.calc_checksum		= &ixgbe_calc_eeprom_checksum_X550, \
39586a14ee0cSDon Skidmore 
395937689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550 = {
39606a14ee0cSDon Skidmore 	X550_COMMON_EEP
39616a14ee0cSDon Skidmore 	.init_params		= &ixgbe_init_eeprom_params_X550,
39626a14ee0cSDon Skidmore };
39636a14ee0cSDon Skidmore 
396437689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = {
39656a14ee0cSDon Skidmore 	X550_COMMON_EEP
39666a14ee0cSDon Skidmore 	.init_params		= &ixgbe_init_eeprom_params_X540,
39676a14ee0cSDon Skidmore };
39686a14ee0cSDon Skidmore 
39696a14ee0cSDon Skidmore #define X550_COMMON_PHY	\
39706a14ee0cSDon Skidmore 	.identify_sfp		= &ixgbe_identify_module_generic, \
39716a14ee0cSDon Skidmore 	.reset			= NULL, \
39726a14ee0cSDon Skidmore 	.setup_link_speed	= &ixgbe_setup_phy_link_speed_generic, \
39736a14ee0cSDon Skidmore 	.read_i2c_byte		= &ixgbe_read_i2c_byte_generic, \
39746a14ee0cSDon Skidmore 	.write_i2c_byte		= &ixgbe_write_i2c_byte_generic, \
39756a14ee0cSDon Skidmore 	.read_i2c_sff8472	= &ixgbe_read_i2c_sff8472_generic, \
39766a14ee0cSDon Skidmore 	.read_i2c_eeprom	= &ixgbe_read_i2c_eeprom_generic, \
39776a14ee0cSDon Skidmore 	.write_i2c_eeprom	= &ixgbe_write_i2c_eeprom_generic, \
3978bef23de1SDon Skidmore 	.setup_link		= &ixgbe_setup_phy_link_generic, \
3979b3eb4e18SMark Rustad 	.set_phy_power		= NULL,
39806a14ee0cSDon Skidmore 
398137689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550 = {
39826a14ee0cSDon Skidmore 	X550_COMMON_PHY
3983b3eb4e18SMark Rustad 	.check_overtemp		= &ixgbe_tn_check_overtemp,
39846a14ee0cSDon Skidmore 	.init			= NULL,
39856a14ee0cSDon Skidmore 	.identify		= &ixgbe_identify_phy_generic,
3986d31afc8fSMark Rustad 	.read_reg		= &ixgbe_read_phy_reg_generic,
3987d31afc8fSMark Rustad 	.write_reg		= &ixgbe_write_phy_reg_generic,
39886a14ee0cSDon Skidmore };
39896a14ee0cSDon Skidmore 
399037689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550EM_x = {
39916a14ee0cSDon Skidmore 	X550_COMMON_PHY
3992b3eb4e18SMark Rustad 	.check_overtemp		= &ixgbe_tn_check_overtemp,
39936a14ee0cSDon Skidmore 	.init			= &ixgbe_init_phy_ops_X550em,
39946a14ee0cSDon Skidmore 	.identify		= &ixgbe_identify_phy_x550em,
3995d31afc8fSMark Rustad 	.read_reg		= &ixgbe_read_phy_reg_generic,
3996d31afc8fSMark Rustad 	.write_reg		= &ixgbe_write_phy_reg_generic,
39976a14ee0cSDon Skidmore };
39986a14ee0cSDon Skidmore 
39998dc963e1SPaul Greenwalt static const struct ixgbe_phy_operations phy_ops_x550em_x_fw = {
40008dc963e1SPaul Greenwalt 	X550_COMMON_PHY
40018dc963e1SPaul Greenwalt 	.check_overtemp		= NULL,
40028dc963e1SPaul Greenwalt 	.init			= ixgbe_init_phy_ops_X550em,
40038dc963e1SPaul Greenwalt 	.identify		= ixgbe_identify_phy_x550em,
40048dc963e1SPaul Greenwalt 	.read_reg		= NULL,
40058dc963e1SPaul Greenwalt 	.write_reg		= NULL,
40068dc963e1SPaul Greenwalt 	.read_reg_mdi		= NULL,
40078dc963e1SPaul Greenwalt 	.write_reg_mdi		= NULL,
40088dc963e1SPaul Greenwalt };
40098dc963e1SPaul Greenwalt 
4010d31afc8fSMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a = {
4011d31afc8fSMark Rustad 	X550_COMMON_PHY
4012b3eb4e18SMark Rustad 	.check_overtemp		= &ixgbe_tn_check_overtemp,
4013d31afc8fSMark Rustad 	.init			= &ixgbe_init_phy_ops_X550em,
4014d31afc8fSMark Rustad 	.identify		= &ixgbe_identify_phy_x550em,
4015d31afc8fSMark Rustad 	.read_reg		= &ixgbe_read_phy_reg_x550a,
4016d31afc8fSMark Rustad 	.write_reg		= &ixgbe_write_phy_reg_x550a,
40178fe293aaSMark Rustad 	.read_reg_mdi		= &ixgbe_read_phy_reg_mdi,
40188fe293aaSMark Rustad 	.write_reg_mdi		= &ixgbe_write_phy_reg_mdi,
4019d31afc8fSMark Rustad };
4020d31afc8fSMark Rustad 
4021b3eb4e18SMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a_fw = {
4022b3eb4e18SMark Rustad 	X550_COMMON_PHY
4023b3eb4e18SMark Rustad 	.check_overtemp		= ixgbe_check_overtemp_fw,
4024b3eb4e18SMark Rustad 	.init			= ixgbe_init_phy_ops_X550em,
4025b3eb4e18SMark Rustad 	.identify		= ixgbe_identify_phy_fw,
4026b3eb4e18SMark Rustad 	.read_reg		= NULL,
4027b3eb4e18SMark Rustad 	.write_reg		= NULL,
4028b3eb4e18SMark Rustad 	.read_reg_mdi		= NULL,
4029b3eb4e18SMark Rustad 	.write_reg_mdi		= NULL,
4030b3eb4e18SMark Rustad };
4031b3eb4e18SMark Rustad 
4032b71f6c40SEmil Tantilov static const struct ixgbe_link_operations link_ops_x550em_x = {
4033b71f6c40SEmil Tantilov 	.read_link		= &ixgbe_read_i2c_combined_generic,
4034b71f6c40SEmil Tantilov 	.read_link_unlocked	= &ixgbe_read_i2c_combined_generic_unlocked,
4035b71f6c40SEmil Tantilov 	.write_link		= &ixgbe_write_i2c_combined_generic,
4036b71f6c40SEmil Tantilov 	.write_link_unlocked	= &ixgbe_write_i2c_combined_generic_unlocked,
4037b71f6c40SEmil Tantilov };
4038b71f6c40SEmil Tantilov 
40399a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = {
40409a900ecaSDon Skidmore 	IXGBE_MVALS_INIT(X550)
40419a900ecaSDon Skidmore };
40429a900ecaSDon Skidmore 
40439a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = {
40449a900ecaSDon Skidmore 	IXGBE_MVALS_INIT(X550EM_x)
40459a900ecaSDon Skidmore };
40469a900ecaSDon Skidmore 
404749425dfcSMark Rustad static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = {
404849425dfcSMark Rustad 	IXGBE_MVALS_INIT(X550EM_a)
404949425dfcSMark Rustad };
405049425dfcSMark Rustad 
405137689010SMark Rustad const struct ixgbe_info ixgbe_X550_info = {
40526a14ee0cSDon Skidmore 	.mac			= ixgbe_mac_X550,
40536a14ee0cSDon Skidmore 	.get_invariants		= &ixgbe_get_invariants_X540,
40546a14ee0cSDon Skidmore 	.mac_ops		= &mac_ops_X550,
40556a14ee0cSDon Skidmore 	.eeprom_ops		= &eeprom_ops_X550,
40566a14ee0cSDon Skidmore 	.phy_ops		= &phy_ops_X550,
40576a14ee0cSDon Skidmore 	.mbx_ops		= &mbx_ops_generic,
40589a900ecaSDon Skidmore 	.mvals			= ixgbe_mvals_X550,
40596a14ee0cSDon Skidmore };
40606a14ee0cSDon Skidmore 
406137689010SMark Rustad const struct ixgbe_info ixgbe_X550EM_x_info = {
40626a14ee0cSDon Skidmore 	.mac			= ixgbe_mac_X550EM_x,
4063b5529ef5SDon Skidmore 	.get_invariants		= &ixgbe_get_invariants_X550_x,
40646a14ee0cSDon Skidmore 	.mac_ops		= &mac_ops_X550EM_x,
40656a14ee0cSDon Skidmore 	.eeprom_ops		= &eeprom_ops_X550EM_x,
40666a14ee0cSDon Skidmore 	.phy_ops		= &phy_ops_X550EM_x,
40676a14ee0cSDon Skidmore 	.mbx_ops		= &mbx_ops_generic,
40689a900ecaSDon Skidmore 	.mvals			= ixgbe_mvals_X550EM_x,
4069b71f6c40SEmil Tantilov 	.link_ops		= &link_ops_x550em_x,
40706a14ee0cSDon Skidmore };
407149425dfcSMark Rustad 
40728dc963e1SPaul Greenwalt const struct ixgbe_info ixgbe_x550em_x_fw_info = {
40738dc963e1SPaul Greenwalt 	.mac			= ixgbe_mac_X550EM_x,
40748dc963e1SPaul Greenwalt 	.get_invariants		= ixgbe_get_invariants_X550_x_fw,
40755e999fb4SPaul Greenwalt 	.mac_ops		= &mac_ops_X550EM_x_fw,
40768dc963e1SPaul Greenwalt 	.eeprom_ops		= &eeprom_ops_X550EM_x,
40778dc963e1SPaul Greenwalt 	.phy_ops		= &phy_ops_x550em_x_fw,
40788dc963e1SPaul Greenwalt 	.mbx_ops		= &mbx_ops_generic,
40798dc963e1SPaul Greenwalt 	.mvals			= ixgbe_mvals_X550EM_x,
40808dc963e1SPaul Greenwalt };
40818dc963e1SPaul Greenwalt 
408249425dfcSMark Rustad const struct ixgbe_info ixgbe_x550em_a_info = {
408349425dfcSMark Rustad 	.mac			= ixgbe_mac_x550em_a,
4084b71f6c40SEmil Tantilov 	.get_invariants		= &ixgbe_get_invariants_X550_a,
408549425dfcSMark Rustad 	.mac_ops		= &mac_ops_x550em_a,
408649425dfcSMark Rustad 	.eeprom_ops		= &eeprom_ops_X550EM_x,
4087d31afc8fSMark Rustad 	.phy_ops		= &phy_ops_x550em_a,
408849425dfcSMark Rustad 	.mbx_ops		= &mbx_ops_generic,
408949425dfcSMark Rustad 	.mvals			= ixgbe_mvals_x550em_a,
409049425dfcSMark Rustad };
4091b3eb4e18SMark Rustad 
4092b3eb4e18SMark Rustad const struct ixgbe_info ixgbe_x550em_a_fw_info = {
4093b3eb4e18SMark Rustad 	.mac			= ixgbe_mac_x550em_a,
4094b3eb4e18SMark Rustad 	.get_invariants		= ixgbe_get_invariants_X550_a_fw,
4095b3eb4e18SMark Rustad 	.mac_ops		= &mac_ops_x550em_a_fw,
4096b3eb4e18SMark Rustad 	.eeprom_ops		= &eeprom_ops_X550EM_x,
4097b3eb4e18SMark Rustad 	.phy_ops		= &phy_ops_x550em_a_fw,
4098b3eb4e18SMark Rustad 	.mbx_ops		= &mbx_ops_generic,
4099b3eb4e18SMark Rustad 	.mvals			= ixgbe_mvals_x550em_a,
4100b3eb4e18SMark Rustad };
4101