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 
ixgbe_get_invariants_X550_x(struct ixgbe_hw * hw)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 
ixgbe_get_invariants_X550_x_fw(struct ixgbe_hw * hw)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 
ixgbe_get_invariants_X550_a(struct ixgbe_hw * hw)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 
ixgbe_get_invariants_X550_a_fw(struct ixgbe_hw * hw)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  **/
ixgbe_setup_mux_ctl(struct ixgbe_hw * hw)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  */
ixgbe_read_cs4227(struct ixgbe_hw * hw,u16 reg,u16 * value)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  */
ixgbe_write_cs4227(struct ixgbe_hw * hw,u16 reg,u16 value)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  */
ixgbe_read_pe(struct ixgbe_hw * hw,u8 reg,u8 * value)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  */
ixgbe_write_pe(struct ixgbe_hw * hw,u8 reg,u8 value)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  */
ixgbe_reset_cs4227(struct ixgbe_hw * hw)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");
20903c5b6d4SJedrzej Jagielski 		return -EIO;
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");
21503c5b6d4SJedrzej Jagielski 		return -EIO;
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  */
ixgbe_check_cs4227(struct ixgbe_hw * hw)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  */
ixgbe_identify_phy_x550em(struct ixgbe_hw * hw)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 
ixgbe_read_phy_reg_x550em(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)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 {
35303c5b6d4SJedrzej Jagielski 	return -EOPNOTSUPP;
3546a14ee0cSDon Skidmore }
3556a14ee0cSDon Skidmore 
ixgbe_write_phy_reg_x550em(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)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 {
35903c5b6d4SJedrzej Jagielski 	return -EOPNOTSUPP;
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  **/
ixgbe_read_i2c_combined_generic(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 * val)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
ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 * val)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  **/
ixgbe_write_i2c_combined_generic(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 val)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
ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 val)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  */
ixgbe_fw_phy_activity(struct ixgbe_hw * hw,u16 activity,u32 (* data)[FW_PHY_ACT_DATA_COUNT])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 
46603c5b6d4SJedrzej Jagielski 	return -EIO;
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  */
ixgbe_get_phy_id_fw(struct ixgbe_hw * hw)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)
51403c5b6d4SJedrzej Jagielski 		return -EFAULT;
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  */
ixgbe_identify_phy_fw(struct ixgbe_hw * hw)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  */
ixgbe_shutdown_fw_phy(struct ixgbe_hw * hw)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  */
ixgbe_setup_fw_link(struct ixgbe_hw * hw)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");
57103c5b6d4SJedrzej Jagielski 		return -EINVAL;
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;
60309943985SJedrzej Jagielski 
604b3eb4e18SMark Rustad 	if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
60509943985SJedrzej Jagielski 		return -EIO;
60609943985SJedrzej Jagielski 
607b3eb4e18SMark Rustad 	return 0;
608b3eb4e18SMark Rustad }
609b3eb4e18SMark Rustad 
610b3eb4e18SMark Rustad /**
611b3eb4e18SMark Rustad  * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs
612b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
613b3eb4e18SMark Rustad  *
614b3eb4e18SMark Rustad  * Called at init time to set up flow control.
615b3eb4e18SMark Rustad  */
ixgbe_fc_autoneg_fw(struct ixgbe_hw * hw)616b3eb4e18SMark Rustad static s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw)
617b3eb4e18SMark Rustad {
618b3eb4e18SMark Rustad 	if (hw->fc.requested_mode == ixgbe_fc_default)
619b3eb4e18SMark Rustad 		hw->fc.requested_mode = ixgbe_fc_full;
620b3eb4e18SMark Rustad 
621b3eb4e18SMark Rustad 	return ixgbe_setup_fw_link(hw);
622b3eb4e18SMark Rustad }
623b3eb4e18SMark Rustad 
6246a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params
6256a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
6266a14ee0cSDon Skidmore  *
6276a14ee0cSDon Skidmore  *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
6286a14ee0cSDon Skidmore  *  ixgbe_hw struct in order to set up EEPROM access.
6296a14ee0cSDon Skidmore  **/
ixgbe_init_eeprom_params_X550(struct ixgbe_hw * hw)6307ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
6316a14ee0cSDon Skidmore {
6326a14ee0cSDon Skidmore 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
6336a14ee0cSDon Skidmore 
6346a14ee0cSDon Skidmore 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
635d5752c7bSJesse Brandeburg 		u16 eeprom_size;
636d5752c7bSJesse Brandeburg 		u32 eec;
637d5752c7bSJesse Brandeburg 
6386a14ee0cSDon Skidmore 		eeprom->semaphore_delay = 10;
6396a14ee0cSDon Skidmore 		eeprom->type = ixgbe_flash;
6406a14ee0cSDon Skidmore 
6419a900ecaSDon Skidmore 		eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
642d5752c7bSJesse Brandeburg 		eeprom_size = FIELD_GET(IXGBE_EEC_SIZE, eec);
643b4f47a48SJacob Keller 		eeprom->word_size = BIT(eeprom_size +
6446a14ee0cSDon Skidmore 					IXGBE_EEPROM_WORD_SIZE_SHIFT);
6456a14ee0cSDon Skidmore 
6466a14ee0cSDon Skidmore 		hw_dbg(hw, "Eeprom params: type = %d, size = %d\n",
6476a14ee0cSDon Skidmore 		       eeprom->type, eeprom->word_size);
6486a14ee0cSDon Skidmore 	}
6496a14ee0cSDon Skidmore 
6506a14ee0cSDon Skidmore 	return 0;
6516a14ee0cSDon Skidmore }
6526a14ee0cSDon Skidmore 
653ae14a1d8SMark Rustad /**
654ae14a1d8SMark Rustad  * ixgbe_iosf_wait - Wait for IOSF command completion
655ae14a1d8SMark Rustad  * @hw: pointer to hardware structure
656ae14a1d8SMark Rustad  * @ctrl: pointer to location to receive final IOSF control value
657ae14a1d8SMark Rustad  *
658ae14a1d8SMark Rustad  * Return: failing status on timeout
659ae14a1d8SMark Rustad  *
660ae14a1d8SMark Rustad  * Note: ctrl can be NULL if the IOSF control register value is not needed
661ae14a1d8SMark Rustad  */
ixgbe_iosf_wait(struct ixgbe_hw * hw,u32 * ctrl)662ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl)
663ae14a1d8SMark Rustad {
664ae14a1d8SMark Rustad 	u32 i, command;
665ae14a1d8SMark Rustad 
666ae14a1d8SMark Rustad 	/* Check every 10 usec to see if the address cycle completed.
667ae14a1d8SMark Rustad 	 * The SB IOSF BUSY bit will clear when the operation is
668ae14a1d8SMark Rustad 	 * complete.
669ae14a1d8SMark Rustad 	 */
670ae14a1d8SMark Rustad 	for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
671ae14a1d8SMark Rustad 		command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
672ae14a1d8SMark Rustad 		if (!(command & IXGBE_SB_IOSF_CTRL_BUSY))
673ae14a1d8SMark Rustad 			break;
674d90b5b0eSMark Rustad 		udelay(10);
675ae14a1d8SMark Rustad 	}
676ae14a1d8SMark Rustad 	if (ctrl)
677ae14a1d8SMark Rustad 		*ctrl = command;
678ae14a1d8SMark Rustad 	if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
679ae14a1d8SMark Rustad 		hw_dbg(hw, "IOSF wait timed out\n");
68003c5b6d4SJedrzej Jagielski 		return -EIO;
681ae14a1d8SMark Rustad 	}
682ae14a1d8SMark Rustad 
683ae14a1d8SMark Rustad 	return 0;
684ae14a1d8SMark Rustad }
685ae14a1d8SMark Rustad 
6866a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the
6876a14ee0cSDon Skidmore  *  IOSF device
6886a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
6896a14ee0cSDon Skidmore  *  @reg_addr: 32 bit PHY register to write
6906a14ee0cSDon Skidmore  *  @device_type: 3 bit device type
6916a14ee0cSDon Skidmore  *  @phy_data: Pointer to read data from the register
6926a14ee0cSDon Skidmore  **/
ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u32 * data)6937ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
6946a14ee0cSDon Skidmore 				       u32 device_type, u32 *data)
6956a14ee0cSDon Skidmore {
696ae14a1d8SMark Rustad 	u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
697ae14a1d8SMark Rustad 	u32 command, error;
698ae14a1d8SMark Rustad 	s32 ret;
699ae14a1d8SMark Rustad 
700ae14a1d8SMark Rustad 	ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
701ae14a1d8SMark Rustad 	if (ret)
702ae14a1d8SMark Rustad 		return ret;
703ae14a1d8SMark Rustad 
704ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, NULL);
705ae14a1d8SMark Rustad 	if (ret)
706ae14a1d8SMark Rustad 		goto out;
7076a14ee0cSDon Skidmore 
7086a14ee0cSDon Skidmore 	command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
7096a14ee0cSDon Skidmore 		   (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
7106a14ee0cSDon Skidmore 
7116a14ee0cSDon Skidmore 	/* Write IOSF control register */
7126a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
7136a14ee0cSDon Skidmore 
714ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, &command);
7156a14ee0cSDon Skidmore 
7166a14ee0cSDon Skidmore 	if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
717d5752c7bSJesse Brandeburg 		error = FIELD_GET(IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK, command);
7186a14ee0cSDon Skidmore 		hw_dbg(hw, "Failed to read, error %x\n", error);
719a4b6f9deSChristophe JAILLET 		ret = -EIO;
720a4b6f9deSChristophe JAILLET 		goto out;
7216a14ee0cSDon Skidmore 	}
7226a14ee0cSDon Skidmore 
723ae14a1d8SMark Rustad 	if (!ret)
7246a14ee0cSDon Skidmore 		*data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
7256a14ee0cSDon Skidmore 
726ae14a1d8SMark Rustad out:
727ae14a1d8SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, gssr);
728ae14a1d8SMark Rustad 	return ret;
7296a14ee0cSDon Skidmore }
7306a14ee0cSDon Skidmore 
73149425dfcSMark Rustad /**
73249425dfcSMark Rustad  * ixgbe_get_phy_token - Get the token for shared PHY access
73349425dfcSMark Rustad  * @hw: Pointer to hardware structure
73449425dfcSMark Rustad  */
ixgbe_get_phy_token(struct ixgbe_hw * hw)73549425dfcSMark Rustad static s32 ixgbe_get_phy_token(struct ixgbe_hw *hw)
73649425dfcSMark Rustad {
73749425dfcSMark Rustad 	struct ixgbe_hic_phy_token_req token_cmd;
73849425dfcSMark Rustad 	s32 status;
73949425dfcSMark Rustad 
74049425dfcSMark Rustad 	token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
74149425dfcSMark Rustad 	token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
74249425dfcSMark Rustad 	token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
74349425dfcSMark Rustad 	token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
74449425dfcSMark Rustad 	token_cmd.port_number = hw->bus.lan_id;
74549425dfcSMark Rustad 	token_cmd.command_type = FW_PHY_TOKEN_REQ;
74649425dfcSMark Rustad 	token_cmd.pad = 0;
74749425dfcSMark Rustad 	status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd),
74849425dfcSMark Rustad 					      IXGBE_HI_COMMAND_TIMEOUT,
74949425dfcSMark Rustad 					      true);
75049425dfcSMark Rustad 	if (status)
75149425dfcSMark Rustad 		return status;
75249425dfcSMark Rustad 	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
75349425dfcSMark Rustad 		return 0;
75449425dfcSMark Rustad 	if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY)
75503c5b6d4SJedrzej Jagielski 		return -EIO;
75649425dfcSMark Rustad 
75703c5b6d4SJedrzej Jagielski 	return -EAGAIN;
75849425dfcSMark Rustad }
75949425dfcSMark Rustad 
76049425dfcSMark Rustad /**
76149425dfcSMark Rustad  * ixgbe_put_phy_token - Put the token for shared PHY access
76249425dfcSMark Rustad  * @hw: Pointer to hardware structure
76349425dfcSMark Rustad  */
ixgbe_put_phy_token(struct ixgbe_hw * hw)76449425dfcSMark Rustad static s32 ixgbe_put_phy_token(struct ixgbe_hw *hw)
76549425dfcSMark Rustad {
76649425dfcSMark Rustad 	struct ixgbe_hic_phy_token_req token_cmd;
76749425dfcSMark Rustad 	s32 status;
76849425dfcSMark Rustad 
76949425dfcSMark Rustad 	token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
77049425dfcSMark Rustad 	token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
77149425dfcSMark Rustad 	token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
77249425dfcSMark Rustad 	token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
77349425dfcSMark Rustad 	token_cmd.port_number = hw->bus.lan_id;
77449425dfcSMark Rustad 	token_cmd.command_type = FW_PHY_TOKEN_REL;
77549425dfcSMark Rustad 	token_cmd.pad = 0;
77649425dfcSMark Rustad 	status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd),
77749425dfcSMark Rustad 					      IXGBE_HI_COMMAND_TIMEOUT,
77849425dfcSMark Rustad 					      true);
77949425dfcSMark Rustad 	if (status)
78049425dfcSMark Rustad 		return status;
78149425dfcSMark Rustad 	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
78249425dfcSMark Rustad 		return 0;
78303c5b6d4SJedrzej Jagielski 	return -EIO;
78449425dfcSMark Rustad }
78549425dfcSMark Rustad 
78649425dfcSMark Rustad /**
78749425dfcSMark Rustad  *  ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register
78849425dfcSMark Rustad  *  @hw: pointer to hardware structure
78949425dfcSMark Rustad  *  @reg_addr: 32 bit PHY register to write
79049425dfcSMark Rustad  *  @device_type: 3 bit device type
79149425dfcSMark Rustad  *  @data: Data to write to the register
79249425dfcSMark Rustad  **/
ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw * hw,u32 reg_addr,__always_unused u32 device_type,u32 data)79349425dfcSMark Rustad static s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
79449425dfcSMark Rustad 					 __always_unused u32 device_type,
79549425dfcSMark Rustad 					 u32 data)
79649425dfcSMark Rustad {
79749425dfcSMark Rustad 	struct ixgbe_hic_internal_phy_req write_cmd;
79849425dfcSMark Rustad 
79949425dfcSMark Rustad 	memset(&write_cmd, 0, sizeof(write_cmd));
80049425dfcSMark Rustad 	write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD;
80149425dfcSMark Rustad 	write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN;
80249425dfcSMark Rustad 	write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
80349425dfcSMark Rustad 	write_cmd.port_number = hw->bus.lan_id;
80449425dfcSMark Rustad 	write_cmd.command_type = FW_INT_PHY_REQ_WRITE;
80549425dfcSMark Rustad 	write_cmd.address = cpu_to_be16(reg_addr);
80649425dfcSMark Rustad 	write_cmd.write_data = cpu_to_be32(data);
80749425dfcSMark Rustad 
80849425dfcSMark Rustad 	return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd),
80949425dfcSMark Rustad 					    IXGBE_HI_COMMAND_TIMEOUT, false);
81049425dfcSMark Rustad }
81149425dfcSMark Rustad 
81249425dfcSMark Rustad /**
81349425dfcSMark Rustad  *  ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register
81449425dfcSMark Rustad  *  @hw: pointer to hardware structure
81549425dfcSMark Rustad  *  @reg_addr: 32 bit PHY register to write
81649425dfcSMark Rustad  *  @device_type: 3 bit device type
81749425dfcSMark Rustad  *  @data: Pointer to read data from the register
81849425dfcSMark Rustad  **/
ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw * hw,u32 reg_addr,__always_unused u32 device_type,u32 * data)81949425dfcSMark Rustad static s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
82049425dfcSMark Rustad 					__always_unused u32 device_type,
82149425dfcSMark Rustad 					u32 *data)
82249425dfcSMark Rustad {
82349425dfcSMark Rustad 	union {
82449425dfcSMark Rustad 		struct ixgbe_hic_internal_phy_req cmd;
82549425dfcSMark Rustad 		struct ixgbe_hic_internal_phy_resp rsp;
82649425dfcSMark Rustad 	} hic;
82749425dfcSMark Rustad 	s32 status;
82849425dfcSMark Rustad 
82949425dfcSMark Rustad 	memset(&hic, 0, sizeof(hic));
83049425dfcSMark Rustad 	hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD;
83149425dfcSMark Rustad 	hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN;
83249425dfcSMark Rustad 	hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
83349425dfcSMark Rustad 	hic.cmd.port_number = hw->bus.lan_id;
83449425dfcSMark Rustad 	hic.cmd.command_type = FW_INT_PHY_REQ_READ;
83549425dfcSMark Rustad 	hic.cmd.address = cpu_to_be16(reg_addr);
83649425dfcSMark Rustad 
83749425dfcSMark Rustad 	status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd),
83849425dfcSMark Rustad 					      IXGBE_HI_COMMAND_TIMEOUT, true);
83949425dfcSMark Rustad 
84049425dfcSMark Rustad 	/* Extract the register value from the response. */
84149425dfcSMark Rustad 	*data = be32_to_cpu(hic.rsp.read_data);
84249425dfcSMark Rustad 
84349425dfcSMark Rustad 	return status;
84449425dfcSMark Rustad }
84549425dfcSMark Rustad 
8466a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif
8476a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
8486a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to read
8496a14ee0cSDon Skidmore  *  @words: number of words
8506a14ee0cSDon Skidmore  *  @data: word(s) read from the EEPROM
8516a14ee0cSDon Skidmore  *
8526a14ee0cSDon Skidmore  *  Reads a 16 bit word(s) from the EEPROM using the hostif.
8536a14ee0cSDon Skidmore  **/
ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)8547ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
8556a14ee0cSDon Skidmore 					    u16 offset, u16 words, u16 *data)
8566a14ee0cSDon Skidmore {
8573efa9ed2SMark Rustad 	const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
8586a14ee0cSDon Skidmore 	struct ixgbe_hic_read_shadow_ram buffer;
8596a14ee0cSDon Skidmore 	u32 current_word = 0;
8606a14ee0cSDon Skidmore 	u16 words_to_read;
8616a14ee0cSDon Skidmore 	s32 status;
8626a14ee0cSDon Skidmore 	u32 i;
8636a14ee0cSDon Skidmore 
8646a14ee0cSDon Skidmore 	/* Take semaphore for the entire operation. */
8653efa9ed2SMark Rustad 	status = hw->mac.ops.acquire_swfw_sync(hw, mask);
8666a14ee0cSDon Skidmore 	if (status) {
8676a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM read buffer - semaphore failed\n");
8686a14ee0cSDon Skidmore 		return status;
8696a14ee0cSDon Skidmore 	}
8706a14ee0cSDon Skidmore 
8716a14ee0cSDon Skidmore 	while (words) {
8726a14ee0cSDon Skidmore 		if (words > FW_MAX_READ_BUFFER_SIZE / 2)
8736a14ee0cSDon Skidmore 			words_to_read = FW_MAX_READ_BUFFER_SIZE / 2;
8746a14ee0cSDon Skidmore 		else
8756a14ee0cSDon Skidmore 			words_to_read = words;
8766a14ee0cSDon Skidmore 
8776a14ee0cSDon Skidmore 		buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
8786a14ee0cSDon Skidmore 		buffer.hdr.req.buf_lenh = 0;
8796a14ee0cSDon Skidmore 		buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
8806a14ee0cSDon Skidmore 		buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
8816a14ee0cSDon Skidmore 
8826a14ee0cSDon Skidmore 		/* convert offset from words to bytes */
8839cfbfa70SCathy Zhou 		buffer.address = (__force u32)cpu_to_be32((offset +
8849cfbfa70SCathy Zhou 							   current_word) * 2);
8859cfbfa70SCathy Zhou 		buffer.length = (__force u16)cpu_to_be16(words_to_read * 2);
886dcfd6b83SEmil Tantilov 		buffer.pad2 = 0;
887dcfd6b83SEmil Tantilov 		buffer.pad3 = 0;
8886a14ee0cSDon Skidmore 
8893efa9ed2SMark Rustad 		status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
8903efa9ed2SMark Rustad 					    IXGBE_HI_COMMAND_TIMEOUT);
8916a14ee0cSDon Skidmore 		if (status) {
8926a14ee0cSDon Skidmore 			hw_dbg(hw, "Host interface command failed\n");
8936a14ee0cSDon Skidmore 			goto out;
8946a14ee0cSDon Skidmore 		}
8956a14ee0cSDon Skidmore 
8966a14ee0cSDon Skidmore 		for (i = 0; i < words_to_read; i++) {
8976a14ee0cSDon Skidmore 			u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) +
8986a14ee0cSDon Skidmore 				  2 * i;
8996a14ee0cSDon Skidmore 			u32 value = IXGBE_READ_REG(hw, reg);
9006a14ee0cSDon Skidmore 
9016a14ee0cSDon Skidmore 			data[current_word] = (u16)(value & 0xffff);
9026a14ee0cSDon Skidmore 			current_word++;
9036a14ee0cSDon Skidmore 			i++;
9046a14ee0cSDon Skidmore 			if (i < words_to_read) {
9056a14ee0cSDon Skidmore 				value >>= 16;
9066a14ee0cSDon Skidmore 				data[current_word] = (u16)(value & 0xffff);
9076a14ee0cSDon Skidmore 				current_word++;
9086a14ee0cSDon Skidmore 			}
9096a14ee0cSDon Skidmore 		}
9106a14ee0cSDon Skidmore 		words -= words_to_read;
9116a14ee0cSDon Skidmore 	}
9126a14ee0cSDon Skidmore 
9136a14ee0cSDon Skidmore out:
9143efa9ed2SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
9156a14ee0cSDon Skidmore 	return status;
9166a14ee0cSDon Skidmore }
9176a14ee0cSDon Skidmore 
9186a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region
9196a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
9206a14ee0cSDon Skidmore  *  @ptr: pointer offset in eeprom
9216a14ee0cSDon Skidmore  *  @size: size of section pointed by ptr, if 0 first word will be used as size
9226a14ee0cSDon Skidmore  *  @csum: address of checksum to update
9236a14ee0cSDon Skidmore  *
9246a14ee0cSDon Skidmore  *  Returns error status for any failure
9256a14ee0cSDon Skidmore  **/
ixgbe_checksum_ptr_x550(struct ixgbe_hw * hw,u16 ptr,u16 size,u16 * csum,u16 * buffer,u32 buffer_size)9266a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
9276a14ee0cSDon Skidmore 				   u16 size, u16 *csum, u16 *buffer,
9286a14ee0cSDon Skidmore 				   u32 buffer_size)
9296a14ee0cSDon Skidmore {
9306a14ee0cSDon Skidmore 	u16 buf[256];
9316a14ee0cSDon Skidmore 	s32 status;
9326a14ee0cSDon Skidmore 	u16 length, bufsz, i, start;
9336a14ee0cSDon Skidmore 	u16 *local_buffer;
9346a14ee0cSDon Skidmore 
935f0e49dc3SColin Ian King 	bufsz = ARRAY_SIZE(buf);
9366a14ee0cSDon Skidmore 
9376a14ee0cSDon Skidmore 	/* Read a chunk at the pointer location */
9386a14ee0cSDon Skidmore 	if (!buffer) {
9396a14ee0cSDon Skidmore 		status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf);
9406a14ee0cSDon Skidmore 		if (status) {
9416a14ee0cSDon Skidmore 			hw_dbg(hw, "Failed to read EEPROM image\n");
9426a14ee0cSDon Skidmore 			return status;
9436a14ee0cSDon Skidmore 		}
9446a14ee0cSDon Skidmore 		local_buffer = buf;
9456a14ee0cSDon Skidmore 	} else {
9466a14ee0cSDon Skidmore 		if (buffer_size < ptr)
94703c5b6d4SJedrzej Jagielski 			return  -EINVAL;
9486a14ee0cSDon Skidmore 		local_buffer = &buffer[ptr];
9496a14ee0cSDon Skidmore 	}
9506a14ee0cSDon Skidmore 
9516a14ee0cSDon Skidmore 	if (size) {
9526a14ee0cSDon Skidmore 		start = 0;
9536a14ee0cSDon Skidmore 		length = size;
9546a14ee0cSDon Skidmore 	} else {
9556a14ee0cSDon Skidmore 		start = 1;
9566a14ee0cSDon Skidmore 		length = local_buffer[0];
9576a14ee0cSDon Skidmore 
9586a14ee0cSDon Skidmore 		/* Skip pointer section if length is invalid. */
9596a14ee0cSDon Skidmore 		if (length == 0xFFFF || length == 0 ||
9606a14ee0cSDon Skidmore 		    (ptr + length) >= hw->eeprom.word_size)
9616a14ee0cSDon Skidmore 			return 0;
9626a14ee0cSDon Skidmore 	}
9636a14ee0cSDon Skidmore 
9646a14ee0cSDon Skidmore 	if (buffer && ((u32)start + (u32)length > buffer_size))
96503c5b6d4SJedrzej Jagielski 		return -EINVAL;
9666a14ee0cSDon Skidmore 
9676a14ee0cSDon Skidmore 	for (i = start; length; i++, length--) {
9686a14ee0cSDon Skidmore 		if (i == bufsz && !buffer) {
9696a14ee0cSDon Skidmore 			ptr += bufsz;
9706a14ee0cSDon Skidmore 			i = 0;
9716a14ee0cSDon Skidmore 			if (length < bufsz)
9726a14ee0cSDon Skidmore 				bufsz = length;
9736a14ee0cSDon Skidmore 
9746a14ee0cSDon Skidmore 			/* Read a chunk at the pointer location */
9756a14ee0cSDon Skidmore 			status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr,
9766a14ee0cSDon Skidmore 								  bufsz, buf);
9776a14ee0cSDon Skidmore 			if (status) {
9786a14ee0cSDon Skidmore 				hw_dbg(hw, "Failed to read EEPROM image\n");
9796a14ee0cSDon Skidmore 				return status;
9806a14ee0cSDon Skidmore 			}
9816a14ee0cSDon Skidmore 		}
9826a14ee0cSDon Skidmore 		*csum += local_buffer[i];
9836a14ee0cSDon Skidmore 	}
9846a14ee0cSDon Skidmore 	return 0;
9856a14ee0cSDon Skidmore }
9866a14ee0cSDon Skidmore 
9876a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum
9886a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
9896a14ee0cSDon Skidmore  *  @buffer: pointer to buffer containing calculated checksum
9906a14ee0cSDon Skidmore  *  @buffer_size: size of buffer
9916a14ee0cSDon Skidmore  *
9926a14ee0cSDon Skidmore  *  Returns a negative error code on error, or the 16-bit checksum
9936a14ee0cSDon Skidmore  **/
ixgbe_calc_checksum_X550(struct ixgbe_hw * hw,u16 * buffer,u32 buffer_size)9947ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer,
9957ddbde3fSDon Skidmore 				    u32 buffer_size)
9966a14ee0cSDon Skidmore {
9976a14ee0cSDon Skidmore 	u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1];
9986a14ee0cSDon Skidmore 	u16 *local_buffer;
9996a14ee0cSDon Skidmore 	s32 status;
10006a14ee0cSDon Skidmore 	u16 checksum = 0;
10016a14ee0cSDon Skidmore 	u16 pointer, i, size;
10026a14ee0cSDon Skidmore 
10036a14ee0cSDon Skidmore 	hw->eeprom.ops.init_params(hw);
10046a14ee0cSDon Skidmore 
10056a14ee0cSDon Skidmore 	if (!buffer) {
10066a14ee0cSDon Skidmore 		/* Read pointer area */
10076a14ee0cSDon Skidmore 		status = ixgbe_read_ee_hostif_buffer_X550(hw, 0,
10086a14ee0cSDon Skidmore 						IXGBE_EEPROM_LAST_WORD + 1,
10096a14ee0cSDon Skidmore 						eeprom_ptrs);
10106a14ee0cSDon Skidmore 		if (status) {
10116a14ee0cSDon Skidmore 			hw_dbg(hw, "Failed to read EEPROM image\n");
10126a14ee0cSDon Skidmore 			return status;
10136a14ee0cSDon Skidmore 		}
10146a14ee0cSDon Skidmore 		local_buffer = eeprom_ptrs;
10156a14ee0cSDon Skidmore 	} else {
10166a14ee0cSDon Skidmore 		if (buffer_size < IXGBE_EEPROM_LAST_WORD)
101703c5b6d4SJedrzej Jagielski 			return -EINVAL;
10186a14ee0cSDon Skidmore 		local_buffer = buffer;
10196a14ee0cSDon Skidmore 	}
10206a14ee0cSDon Skidmore 
10216a14ee0cSDon Skidmore 	/* For X550 hardware include 0x0-0x41 in the checksum, skip the
10226a14ee0cSDon Skidmore 	 * checksum word itself
10236a14ee0cSDon Skidmore 	 */
10246a14ee0cSDon Skidmore 	for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++)
10256a14ee0cSDon Skidmore 		if (i != IXGBE_EEPROM_CHECKSUM)
10266a14ee0cSDon Skidmore 			checksum += local_buffer[i];
10276a14ee0cSDon Skidmore 
10286a14ee0cSDon Skidmore 	/* Include all data from pointers 0x3, 0x6-0xE.  This excludes the
10296a14ee0cSDon Skidmore 	 * FW, PHY module, and PCIe Expansion/Option ROM pointers.
10306a14ee0cSDon Skidmore 	 */
10316a14ee0cSDon Skidmore 	for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) {
10326a14ee0cSDon Skidmore 		if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
10336a14ee0cSDon Skidmore 			continue;
10346a14ee0cSDon Skidmore 
10356a14ee0cSDon Skidmore 		pointer = local_buffer[i];
10366a14ee0cSDon Skidmore 
10376a14ee0cSDon Skidmore 		/* Skip pointer section if the pointer is invalid. */
10386a14ee0cSDon Skidmore 		if (pointer == 0xFFFF || pointer == 0 ||
10396a14ee0cSDon Skidmore 		    pointer >= hw->eeprom.word_size)
10406a14ee0cSDon Skidmore 			continue;
10416a14ee0cSDon Skidmore 
10426a14ee0cSDon Skidmore 		switch (i) {
10436a14ee0cSDon Skidmore 		case IXGBE_PCIE_GENERAL_PTR:
10446a14ee0cSDon Skidmore 			size = IXGBE_IXGBE_PCIE_GENERAL_SIZE;
10456a14ee0cSDon Skidmore 			break;
10466a14ee0cSDon Skidmore 		case IXGBE_PCIE_CONFIG0_PTR:
10476a14ee0cSDon Skidmore 		case IXGBE_PCIE_CONFIG1_PTR:
10486a14ee0cSDon Skidmore 			size = IXGBE_PCIE_CONFIG_SIZE;
10496a14ee0cSDon Skidmore 			break;
10506a14ee0cSDon Skidmore 		default:
10516a14ee0cSDon Skidmore 			size = 0;
10526a14ee0cSDon Skidmore 			break;
10536a14ee0cSDon Skidmore 		}
10546a14ee0cSDon Skidmore 
10556a14ee0cSDon Skidmore 		status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum,
10566a14ee0cSDon Skidmore 						 buffer, buffer_size);
10576a14ee0cSDon Skidmore 		if (status)
10586a14ee0cSDon Skidmore 			return status;
10596a14ee0cSDon Skidmore 	}
10606a14ee0cSDon Skidmore 
10616a14ee0cSDon Skidmore 	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
10626a14ee0cSDon Skidmore 
10636a14ee0cSDon Skidmore 	return (s32)checksum;
10646a14ee0cSDon Skidmore }
10656a14ee0cSDon Skidmore 
10666a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum
10676a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
10686a14ee0cSDon Skidmore  *
10696a14ee0cSDon Skidmore  *  Returns a negative error code on error, or the 16-bit checksum
10706a14ee0cSDon Skidmore  **/
ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw * hw)10717ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
10726a14ee0cSDon Skidmore {
10736a14ee0cSDon Skidmore 	return ixgbe_calc_checksum_X550(hw, NULL, 0);
10746a14ee0cSDon Skidmore }
10756a14ee0cSDon Skidmore 
10766a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command
10776a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
10786a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to read
10796a14ee0cSDon Skidmore  *  @data: word read from the EEPROM
10806a14ee0cSDon Skidmore  *
10816a14ee0cSDon Skidmore  *   Reads a 16 bit word from the EEPROM using the hostif.
10826a14ee0cSDon Skidmore  **/
ixgbe_read_ee_hostif_X550(struct ixgbe_hw * hw,u16 offset,u16 * data)10837ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data)
10846a14ee0cSDon Skidmore {
10853efa9ed2SMark Rustad 	const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
10863efa9ed2SMark Rustad 	struct ixgbe_hic_read_shadow_ram buffer;
10873efa9ed2SMark Rustad 	s32 status;
10886a14ee0cSDon Skidmore 
10893efa9ed2SMark Rustad 	buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
10903efa9ed2SMark Rustad 	buffer.hdr.req.buf_lenh = 0;
10913efa9ed2SMark Rustad 	buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
10923efa9ed2SMark Rustad 	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
10933efa9ed2SMark Rustad 
10943efa9ed2SMark Rustad 	/* convert offset from words to bytes */
10959cfbfa70SCathy Zhou 	buffer.address = (__force u32)cpu_to_be32(offset * 2);
10963efa9ed2SMark Rustad 	/* one word */
10979cfbfa70SCathy Zhou 	buffer.length = (__force u16)cpu_to_be16(sizeof(u16));
10983efa9ed2SMark Rustad 
10993efa9ed2SMark Rustad 	status = hw->mac.ops.acquire_swfw_sync(hw, mask);
11003efa9ed2SMark Rustad 	if (status)
11013efa9ed2SMark Rustad 		return status;
11023efa9ed2SMark Rustad 
11033efa9ed2SMark Rustad 	status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
11043efa9ed2SMark Rustad 				    IXGBE_HI_COMMAND_TIMEOUT);
11053efa9ed2SMark Rustad 	if (!status) {
11063efa9ed2SMark Rustad 		*data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
11073efa9ed2SMark Rustad 						  FW_NVM_DATA_OFFSET);
11086a14ee0cSDon Skidmore 	}
11096a14ee0cSDon Skidmore 
11103efa9ed2SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
11116a14ee0cSDon Skidmore 	return status;
11126a14ee0cSDon Skidmore }
11136a14ee0cSDon Skidmore 
11146a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum
11156a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
11166a14ee0cSDon Skidmore  *  @checksum_val: calculated checksum
11176a14ee0cSDon Skidmore  *
11186a14ee0cSDon Skidmore  *  Performs checksum calculation and validates the EEPROM checksum.  If the
11196a14ee0cSDon Skidmore  *  caller does not need checksum_val, the value can be NULL.
11206a14ee0cSDon Skidmore  **/
ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw * hw,u16 * checksum_val)11217ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw,
11227ddbde3fSDon Skidmore 					       u16 *checksum_val)
11236a14ee0cSDon Skidmore {
11246a14ee0cSDon Skidmore 	s32 status;
11256a14ee0cSDon Skidmore 	u16 checksum;
11266a14ee0cSDon Skidmore 	u16 read_checksum = 0;
11276a14ee0cSDon Skidmore 
11286a14ee0cSDon Skidmore 	/* Read the first word from the EEPROM. If this times out or fails, do
11296a14ee0cSDon Skidmore 	 * not continue or we could be in for a very long wait while every
11306a14ee0cSDon Skidmore 	 * EEPROM read fails
11316a14ee0cSDon Skidmore 	 */
11326a14ee0cSDon Skidmore 	status = hw->eeprom.ops.read(hw, 0, &checksum);
11336a14ee0cSDon Skidmore 	if (status) {
11346a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM read failed\n");
11356a14ee0cSDon Skidmore 		return status;
11366a14ee0cSDon Skidmore 	}
11376a14ee0cSDon Skidmore 
11386a14ee0cSDon Skidmore 	status = hw->eeprom.ops.calc_checksum(hw);
11396a14ee0cSDon Skidmore 	if (status < 0)
11406a14ee0cSDon Skidmore 		return status;
11416a14ee0cSDon Skidmore 
11426a14ee0cSDon Skidmore 	checksum = (u16)(status & 0xffff);
11436a14ee0cSDon Skidmore 
11446a14ee0cSDon Skidmore 	status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
11456a14ee0cSDon Skidmore 					   &read_checksum);
11466a14ee0cSDon Skidmore 	if (status)
11476a14ee0cSDon Skidmore 		return status;
11486a14ee0cSDon Skidmore 
11496a14ee0cSDon Skidmore 	/* Verify read checksum from EEPROM is the same as
11506a14ee0cSDon Skidmore 	 * calculated checksum
11516a14ee0cSDon Skidmore 	 */
11526a14ee0cSDon Skidmore 	if (read_checksum != checksum) {
115303c5b6d4SJedrzej Jagielski 		status = -EIO;
11546a14ee0cSDon Skidmore 		hw_dbg(hw, "Invalid EEPROM checksum");
11556a14ee0cSDon Skidmore 	}
11566a14ee0cSDon Skidmore 
11576a14ee0cSDon Skidmore 	/* If the user cares, return the calculated checksum */
11586a14ee0cSDon Skidmore 	if (checksum_val)
11596a14ee0cSDon Skidmore 		*checksum_val = checksum;
11606a14ee0cSDon Skidmore 
11616a14ee0cSDon Skidmore 	return status;
11626a14ee0cSDon Skidmore }
11636a14ee0cSDon Skidmore 
11646a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
11656a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
11666a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to write
11676a14ee0cSDon Skidmore  *  @data: word write to the EEPROM
11686a14ee0cSDon Skidmore  *
11696a14ee0cSDon Skidmore  *  Write a 16 bit word to the EEPROM using the hostif.
11706a14ee0cSDon Skidmore  **/
ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw * hw,u16 offset,u16 data)11717ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
11727ddbde3fSDon Skidmore 					   u16 data)
11736a14ee0cSDon Skidmore {
11746a14ee0cSDon Skidmore 	s32 status;
11756a14ee0cSDon Skidmore 	struct ixgbe_hic_write_shadow_ram buffer;
11766a14ee0cSDon Skidmore 
11776a14ee0cSDon Skidmore 	buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
11786a14ee0cSDon Skidmore 	buffer.hdr.req.buf_lenh = 0;
11796a14ee0cSDon Skidmore 	buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
11806a14ee0cSDon Skidmore 	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
11816a14ee0cSDon Skidmore 
11826a14ee0cSDon Skidmore 	/* one word */
11836a14ee0cSDon Skidmore 	buffer.length = cpu_to_be16(sizeof(u16));
11846a14ee0cSDon Skidmore 	buffer.data = data;
11856a14ee0cSDon Skidmore 	buffer.address = cpu_to_be32(offset * 2);
11866a14ee0cSDon Skidmore 
11875cffde30SMark Rustad 	status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer),
11886a14ee0cSDon Skidmore 					      IXGBE_HI_COMMAND_TIMEOUT, false);
11896a14ee0cSDon Skidmore 	return status;
11906a14ee0cSDon Skidmore }
11916a14ee0cSDon Skidmore 
11926a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
11936a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
11946a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to write
11956a14ee0cSDon Skidmore  *  @data: word write to the EEPROM
11966a14ee0cSDon Skidmore  *
11976a14ee0cSDon Skidmore  *  Write a 16 bit word to the EEPROM using the hostif.
11986a14ee0cSDon Skidmore  **/
ixgbe_write_ee_hostif_X550(struct ixgbe_hw * hw,u16 offset,u16 data)11997ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data)
12006a14ee0cSDon Skidmore {
12016a14ee0cSDon Skidmore 	s32 status = 0;
12026a14ee0cSDon Skidmore 
12036a14ee0cSDon Skidmore 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
12046a14ee0cSDon Skidmore 		status = ixgbe_write_ee_hostif_data_X550(hw, offset, data);
12056a14ee0cSDon Skidmore 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
12066a14ee0cSDon Skidmore 	} else {
12076a14ee0cSDon Skidmore 		hw_dbg(hw, "write ee hostif failed to get semaphore");
120803c5b6d4SJedrzej Jagielski 		status = -EBUSY;
12096a14ee0cSDon Skidmore 	}
12106a14ee0cSDon Skidmore 
12116a14ee0cSDon Skidmore 	return status;
12126a14ee0cSDon Skidmore }
12136a14ee0cSDon Skidmore 
12146a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device
12156a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
12166a14ee0cSDon Skidmore  *
12176a14ee0cSDon Skidmore  *  Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash.
12186a14ee0cSDon Skidmore  **/
ixgbe_update_flash_X550(struct ixgbe_hw * hw)12197ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw)
12206a14ee0cSDon Skidmore {
12216a14ee0cSDon Skidmore 	s32 status = 0;
12226a14ee0cSDon Skidmore 	union ixgbe_hic_hdr2 buffer;
12236a14ee0cSDon Skidmore 
12246a14ee0cSDon Skidmore 	buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD;
12256a14ee0cSDon Skidmore 	buffer.req.buf_lenh = 0;
12266a14ee0cSDon Skidmore 	buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN;
12276a14ee0cSDon Skidmore 	buffer.req.checksum = FW_DEFAULT_CHECKSUM;
12286a14ee0cSDon Skidmore 
12295cffde30SMark Rustad 	status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer),
12306a14ee0cSDon Skidmore 					      IXGBE_HI_COMMAND_TIMEOUT, false);
12316a14ee0cSDon Skidmore 	return status;
12326a14ee0cSDon Skidmore }
12336a14ee0cSDon Skidmore 
1234454c65ddSDon Skidmore /**
1235454c65ddSDon Skidmore  * ixgbe_get_bus_info_X550em - Set PCI bus info
1236454c65ddSDon Skidmore  * @hw: pointer to hardware structure
1237454c65ddSDon Skidmore  *
1238454c65ddSDon Skidmore  * Sets bus link width and speed to unknown because X550em is
1239454c65ddSDon Skidmore  * not a PCI device.
1240454c65ddSDon Skidmore  **/
ixgbe_get_bus_info_X550em(struct ixgbe_hw * hw)1241454c65ddSDon Skidmore static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
1242454c65ddSDon Skidmore {
1243f9328bc6SDon Skidmore 	hw->bus.type  = ixgbe_bus_type_internal;
1244454c65ddSDon Skidmore 	hw->bus.width = ixgbe_bus_width_unknown;
1245454c65ddSDon Skidmore 	hw->bus.speed = ixgbe_bus_speed_unknown;
1246454c65ddSDon Skidmore 
1247454c65ddSDon Skidmore 	hw->mac.ops.set_lan_id(hw);
1248454c65ddSDon Skidmore 
1249454c65ddSDon Skidmore 	return 0;
1250454c65ddSDon Skidmore }
1251454c65ddSDon Skidmore 
125259dd45d5SSebastian Basierski /**
1253262de08fSJesse Brandeburg  * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode
125459dd45d5SSebastian Basierski  * @hw: pointer t hardware structure
125559dd45d5SSebastian Basierski  *
125659dd45d5SSebastian Basierski  * Returns true if in FW NVM recovery mode.
125759dd45d5SSebastian Basierski  */
ixgbe_fw_recovery_mode_X550(struct ixgbe_hw * hw)125859dd45d5SSebastian Basierski static bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw)
125959dd45d5SSebastian Basierski {
126059dd45d5SSebastian Basierski 	u32 fwsm;
126159dd45d5SSebastian Basierski 
126259dd45d5SSebastian Basierski 	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
126359dd45d5SSebastian Basierski 	return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE);
126459dd45d5SSebastian Basierski }
126559dd45d5SSebastian Basierski 
12661f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit
12671f9ac57cSDon Skidmore  *
12681f9ac57cSDon Skidmore  *  Enables the Rx DMA unit for x550
12691f9ac57cSDon Skidmore  **/
ixgbe_disable_rx_x550(struct ixgbe_hw * hw)12701f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
12711f9ac57cSDon Skidmore {
12721f9ac57cSDon Skidmore 	u32 rxctrl, pfdtxgswc;
12731f9ac57cSDon Skidmore 	s32 status;
12741f9ac57cSDon Skidmore 	struct ixgbe_hic_disable_rxen fw_cmd;
12751f9ac57cSDon Skidmore 
12761f9ac57cSDon Skidmore 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
12771f9ac57cSDon Skidmore 	if (rxctrl & IXGBE_RXCTRL_RXEN) {
12781f9ac57cSDon Skidmore 		pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
12791f9ac57cSDon Skidmore 		if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
12801f9ac57cSDon Skidmore 			pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
12811f9ac57cSDon Skidmore 			IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
12821f9ac57cSDon Skidmore 			hw->mac.set_lben = true;
12831f9ac57cSDon Skidmore 		} else {
12841f9ac57cSDon Skidmore 			hw->mac.set_lben = false;
12851f9ac57cSDon Skidmore 		}
12861f9ac57cSDon Skidmore 
12871f9ac57cSDon Skidmore 		fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD;
12881f9ac57cSDon Skidmore 		fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN;
12891f9ac57cSDon Skidmore 		fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
12903775b814SMark Rustad 		fw_cmd.port_number = hw->bus.lan_id;
12911f9ac57cSDon Skidmore 
12925cffde30SMark Rustad 		status = ixgbe_host_interface_command(hw, &fw_cmd,
12931f9ac57cSDon Skidmore 					sizeof(struct ixgbe_hic_disable_rxen),
12941f9ac57cSDon Skidmore 					IXGBE_HI_COMMAND_TIMEOUT, true);
12951f9ac57cSDon Skidmore 
12961f9ac57cSDon Skidmore 		/* If we fail - disable RX using register write */
12971f9ac57cSDon Skidmore 		if (status) {
12981f9ac57cSDon Skidmore 			rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
12991f9ac57cSDon Skidmore 			if (rxctrl & IXGBE_RXCTRL_RXEN) {
13001f9ac57cSDon Skidmore 				rxctrl &= ~IXGBE_RXCTRL_RXEN;
13011f9ac57cSDon Skidmore 				IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
13021f9ac57cSDon Skidmore 			}
13031f9ac57cSDon Skidmore 		}
13041f9ac57cSDon Skidmore 	}
13051f9ac57cSDon Skidmore }
13061f9ac57cSDon Skidmore 
13076a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash
13086a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
13096a14ee0cSDon Skidmore  *
13106a14ee0cSDon Skidmore  *  After writing EEPROM to shadow RAM using EEWR register, software calculates
13116a14ee0cSDon Skidmore  *  checksum and updates the EEPROM and instructs the hardware to update
13126a14ee0cSDon Skidmore  *  the flash.
13136a14ee0cSDon Skidmore  **/
ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw * hw)13147ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw)
13156a14ee0cSDon Skidmore {
13166a14ee0cSDon Skidmore 	s32 status;
13176a14ee0cSDon Skidmore 	u16 checksum = 0;
13186a14ee0cSDon Skidmore 
13196a14ee0cSDon Skidmore 	/* Read the first word from the EEPROM. If this times out or fails, do
13206a14ee0cSDon Skidmore 	 * not continue or we could be in for a very long wait while every
13216a14ee0cSDon Skidmore 	 * EEPROM read fails
13226a14ee0cSDon Skidmore 	 */
13236a14ee0cSDon Skidmore 	status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum);
13246a14ee0cSDon Skidmore 	if (status) {
13256a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM read failed\n");
13266a14ee0cSDon Skidmore 		return status;
13276a14ee0cSDon Skidmore 	}
13286a14ee0cSDon Skidmore 
13296a14ee0cSDon Skidmore 	status = ixgbe_calc_eeprom_checksum_X550(hw);
13306a14ee0cSDon Skidmore 	if (status < 0)
13316a14ee0cSDon Skidmore 		return status;
13326a14ee0cSDon Skidmore 
13336a14ee0cSDon Skidmore 	checksum = (u16)(status & 0xffff);
13346a14ee0cSDon Skidmore 
13356a14ee0cSDon Skidmore 	status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
13366a14ee0cSDon Skidmore 					    checksum);
13376a14ee0cSDon Skidmore 	if (status)
13386a14ee0cSDon Skidmore 		return status;
13396a14ee0cSDon Skidmore 
13406a14ee0cSDon Skidmore 	status = ixgbe_update_flash_X550(hw);
13416a14ee0cSDon Skidmore 
13426a14ee0cSDon Skidmore 	return status;
13436a14ee0cSDon Skidmore }
13446a14ee0cSDon Skidmore 
13456a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif
13466a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
13476a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to write
13486a14ee0cSDon Skidmore  *  @words: number of words
13496a14ee0cSDon Skidmore  *  @data: word(s) write to the EEPROM
13506a14ee0cSDon Skidmore  *
13516a14ee0cSDon Skidmore  *
13526a14ee0cSDon Skidmore  *  Write a 16 bit word(s) to the EEPROM using the hostif.
13536a14ee0cSDon Skidmore  **/
ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)13547ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
13557ddbde3fSDon Skidmore 					     u16 offset, u16 words,
13567ddbde3fSDon Skidmore 					     u16 *data)
13576a14ee0cSDon Skidmore {
13586a14ee0cSDon Skidmore 	s32 status = 0;
13596a14ee0cSDon Skidmore 	u32 i = 0;
13606a14ee0cSDon Skidmore 
13616a14ee0cSDon Skidmore 	/* Take semaphore for the entire operation. */
13626a14ee0cSDon Skidmore 	status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
13636a14ee0cSDon Skidmore 	if (status) {
13646a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM write buffer - semaphore failed\n");
13656a14ee0cSDon Skidmore 		return status;
13666a14ee0cSDon Skidmore 	}
13676a14ee0cSDon Skidmore 
13686a14ee0cSDon Skidmore 	for (i = 0; i < words; i++) {
13696a14ee0cSDon Skidmore 		status = ixgbe_write_ee_hostif_data_X550(hw, offset + i,
13706a14ee0cSDon Skidmore 							 data[i]);
13716a14ee0cSDon Skidmore 		if (status) {
13726a14ee0cSDon Skidmore 			hw_dbg(hw, "Eeprom buffered write failed\n");
13736a14ee0cSDon Skidmore 			break;
13746a14ee0cSDon Skidmore 		}
13756a14ee0cSDon Skidmore 	}
13766a14ee0cSDon Skidmore 
13776a14ee0cSDon Skidmore 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
13786a14ee0cSDon Skidmore 
13796a14ee0cSDon Skidmore 	return status;
13806a14ee0cSDon Skidmore }
13816a14ee0cSDon Skidmore 
13826a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the
13836a14ee0cSDon Skidmore  *  IOSF device
13846a14ee0cSDon Skidmore  *
13856a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
13866a14ee0cSDon Skidmore  *  @reg_addr: 32 bit PHY register to write
13876a14ee0cSDon Skidmore  *  @device_type: 3 bit device type
13886a14ee0cSDon Skidmore  *  @data: Data to write to the register
13896a14ee0cSDon Skidmore  **/
ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u32 data)13907ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
13916a14ee0cSDon Skidmore 					u32 device_type, u32 data)
13926a14ee0cSDon Skidmore {
1393ae14a1d8SMark Rustad 	u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
1394ae14a1d8SMark Rustad 	u32 command, error;
1395ae14a1d8SMark Rustad 	s32 ret;
1396ae14a1d8SMark Rustad 
1397ae14a1d8SMark Rustad 	ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
1398ae14a1d8SMark Rustad 	if (ret)
1399ae14a1d8SMark Rustad 		return ret;
1400ae14a1d8SMark Rustad 
1401ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, NULL);
1402ae14a1d8SMark Rustad 	if (ret)
1403ae14a1d8SMark Rustad 		goto out;
14046a14ee0cSDon Skidmore 
14056a14ee0cSDon Skidmore 	command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
14066a14ee0cSDon Skidmore 		   (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
14076a14ee0cSDon Skidmore 
14086a14ee0cSDon Skidmore 	/* Write IOSF control register */
14096a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
14106a14ee0cSDon Skidmore 
14116a14ee0cSDon Skidmore 	/* Write IOSF data register */
14126a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data);
14136a14ee0cSDon Skidmore 
1414ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, &command);
14156a14ee0cSDon Skidmore 
14166a14ee0cSDon Skidmore 	if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
1417d5752c7bSJesse Brandeburg 		error = FIELD_GET(IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK, command);
14186a14ee0cSDon Skidmore 		hw_dbg(hw, "Failed to write, error %x\n", error);
141903c5b6d4SJedrzej Jagielski 		return -EIO;
14206a14ee0cSDon Skidmore 	}
14216a14ee0cSDon Skidmore 
1422ae14a1d8SMark Rustad out:
1423ae14a1d8SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, gssr);
1424ae14a1d8SMark Rustad 	return ret;
14256a14ee0cSDon Skidmore }
14266a14ee0cSDon Skidmore 
14270c1b7de4SDon Skidmore /**
14280c1b7de4SDon Skidmore  *  ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration
14296a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
14306a14ee0cSDon Skidmore  *
14310c1b7de4SDon Skidmore  *  iXfI configuration needed for ixgbe_mac_X550EM_x devices.
14326a14ee0cSDon Skidmore  **/
ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw * hw)14330c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)
14346a14ee0cSDon Skidmore {
14356a14ee0cSDon Skidmore 	s32 status;
14366a14ee0cSDon Skidmore 	u32 reg_val;
14376a14ee0cSDon Skidmore 
14386a14ee0cSDon Skidmore 	/* Disable training protocol FSM. */
14396a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
14406a14ee0cSDon Skidmore 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
14416a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
14426a14ee0cSDon Skidmore 	if (status)
14436a14ee0cSDon Skidmore 		return status;
14446a14ee0cSDon Skidmore 
14456a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL;
14466a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
14476a14ee0cSDon Skidmore 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
14486a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
14496a14ee0cSDon Skidmore 	if (status)
14506a14ee0cSDon Skidmore 		return status;
14516a14ee0cSDon Skidmore 
14526a14ee0cSDon Skidmore 	/* Disable Flex from training TXFFE. */
14536a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
14546a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
14556a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
14566a14ee0cSDon Skidmore 	if (status)
14576a14ee0cSDon Skidmore 		return status;
14586a14ee0cSDon Skidmore 
14596a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
14606a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
14616a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
14626a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
14636a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
14646a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
14656a14ee0cSDon Skidmore 	if (status)
14666a14ee0cSDon Skidmore 		return status;
14676a14ee0cSDon Skidmore 
14686a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
14696a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
14706a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
14716a14ee0cSDon Skidmore 	if (status)
14726a14ee0cSDon Skidmore 		return status;
14736a14ee0cSDon Skidmore 
14746a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
14756a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
14766a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
14776a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
14786a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
14796a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
14806a14ee0cSDon Skidmore 	if (status)
14816a14ee0cSDon Skidmore 		return status;
14826a14ee0cSDon Skidmore 
14836a14ee0cSDon Skidmore 	/* Enable override for coefficients. */
14846a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
14856a14ee0cSDon Skidmore 				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
14866a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
14876a14ee0cSDon Skidmore 	if (status)
14886a14ee0cSDon Skidmore 		return status;
14896a14ee0cSDon Skidmore 
14906a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN;
14916a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN;
14926a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN;
14936a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN;
14946a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
14956a14ee0cSDon Skidmore 				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
14966a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
14970c1b7de4SDon Skidmore 	return status;
14980c1b7de4SDon Skidmore }
14990c1b7de4SDon Skidmore 
1500470739b5SDon Skidmore /**
1501470739b5SDon Skidmore  *  ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the
1502470739b5SDon Skidmore  *  internal PHY
1503470739b5SDon Skidmore  *  @hw: pointer to hardware structure
1504470739b5SDon Skidmore  **/
ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw * hw)1505470739b5SDon Skidmore static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
1506470739b5SDon Skidmore {
1507470739b5SDon Skidmore 	s32 status;
1508470739b5SDon Skidmore 	u32 link_ctrl;
1509470739b5SDon Skidmore 
1510470739b5SDon Skidmore 	/* Restart auto-negotiation. */
1511470739b5SDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
1512470739b5SDon Skidmore 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1513470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl);
1514470739b5SDon Skidmore 
1515470739b5SDon Skidmore 	if (status) {
1516470739b5SDon Skidmore 		hw_dbg(hw, "Auto-negotiation did not complete\n");
1517470739b5SDon Skidmore 		return status;
1518470739b5SDon Skidmore 	}
1519470739b5SDon Skidmore 
1520470739b5SDon Skidmore 	link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
1521470739b5SDon Skidmore 	status = hw->mac.ops.write_iosf_sb_reg(hw,
1522470739b5SDon Skidmore 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1523470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl);
1524470739b5SDon Skidmore 
1525470739b5SDon Skidmore 	if (hw->mac.type == ixgbe_mac_x550em_a) {
1526470739b5SDon Skidmore 		u32 flx_mask_st20;
1527470739b5SDon Skidmore 
1528470739b5SDon Skidmore 		/* Indicate to FW that AN restart has been asserted */
1529470739b5SDon Skidmore 		status = hw->mac.ops.read_iosf_sb_reg(hw,
1530470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1531470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20);
1532470739b5SDon Skidmore 
1533470739b5SDon Skidmore 		if (status) {
1534470739b5SDon Skidmore 			hw_dbg(hw, "Auto-negotiation did not complete\n");
1535470739b5SDon Skidmore 			return status;
1536470739b5SDon Skidmore 		}
1537470739b5SDon Skidmore 
1538470739b5SDon Skidmore 		flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART;
1539470739b5SDon Skidmore 		status = hw->mac.ops.write_iosf_sb_reg(hw,
1540470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1541470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20);
1542470739b5SDon Skidmore 	}
1543470739b5SDon Skidmore 
1544470739b5SDon Skidmore 	return status;
1545470739b5SDon Skidmore }
1546470739b5SDon Skidmore 
15470c1b7de4SDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
15480c1b7de4SDon Skidmore  *  @hw: pointer to hardware structure
15490c1b7de4SDon Skidmore  *  @speed: the link speed to force
15500c1b7de4SDon Skidmore  *
15510c1b7de4SDon Skidmore  *  Configures the integrated KR PHY to use iXFI mode. Used to connect an
15520c1b7de4SDon Skidmore  *  internal and external PHY at a specific speed, without autonegotiation.
15530c1b7de4SDon Skidmore  **/
ixgbe_setup_ixfi_x550em(struct ixgbe_hw * hw,ixgbe_link_speed * speed)15540c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
15550c1b7de4SDon Skidmore {
155648301cf2STony Nguyen 	struct ixgbe_mac_info *mac = &hw->mac;
15570c1b7de4SDon Skidmore 	s32 status;
15580c1b7de4SDon Skidmore 	u32 reg_val;
15590c1b7de4SDon Skidmore 
156048301cf2STony Nguyen 	/* iXFI is only supported with X552 */
156148301cf2STony Nguyen 	if (mac->type != ixgbe_mac_X550EM_x)
156203c5b6d4SJedrzej Jagielski 		return -EIO;
156348301cf2STony Nguyen 
15640c1b7de4SDon Skidmore 	/* Disable AN and force speed to 10G Serial. */
15650c1b7de4SDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
15660c1b7de4SDon Skidmore 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
15670c1b7de4SDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
15686a14ee0cSDon Skidmore 	if (status)
15696a14ee0cSDon Skidmore 		return status;
15706a14ee0cSDon Skidmore 
15710c1b7de4SDon Skidmore 	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
15720c1b7de4SDon Skidmore 	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
15730c1b7de4SDon Skidmore 
15740c1b7de4SDon Skidmore 	/* Select forced link speed for internal PHY. */
15750c1b7de4SDon Skidmore 	switch (*speed) {
15760c1b7de4SDon Skidmore 	case IXGBE_LINK_SPEED_10GB_FULL:
15770c1b7de4SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
15780c1b7de4SDon Skidmore 		break;
15790c1b7de4SDon Skidmore 	case IXGBE_LINK_SPEED_1GB_FULL:
15800c1b7de4SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
15810c1b7de4SDon Skidmore 		break;
15820c1b7de4SDon Skidmore 	default:
15830c1b7de4SDon Skidmore 		/* Other link speeds are not supported by internal KR PHY. */
158403c5b6d4SJedrzej Jagielski 		return -EINVAL;
15850c1b7de4SDon Skidmore 	}
15860c1b7de4SDon Skidmore 
15870c1b7de4SDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
15880c1b7de4SDon Skidmore 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
15890c1b7de4SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
15900c1b7de4SDon Skidmore 	if (status)
15910c1b7de4SDon Skidmore 		return status;
15920c1b7de4SDon Skidmore 
15930c1b7de4SDon Skidmore 	/* Additional configuration needed for x550em_x */
15940c1b7de4SDon Skidmore 	if (hw->mac.type == ixgbe_mac_X550EM_x) {
15950c1b7de4SDon Skidmore 		status = ixgbe_setup_ixfi_x550em_x(hw);
15960c1b7de4SDon Skidmore 		if (status)
15970c1b7de4SDon Skidmore 			return status;
15980c1b7de4SDon Skidmore 	}
15990c1b7de4SDon Skidmore 
16006a14ee0cSDon Skidmore 	/* Toggle port SW reset by AN reset. */
1601470739b5SDon Skidmore 	status = ixgbe_restart_an_internal_phy_x550em(hw);
16026a14ee0cSDon Skidmore 
16036a14ee0cSDon Skidmore 	return status;
16046a14ee0cSDon Skidmore }
16056a14ee0cSDon Skidmore 
1606c3dc4c09SDon Skidmore /**
1607e23f3336SMark Rustad  *  ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported
1608e23f3336SMark Rustad  *  @hw: pointer to hardware structure
1609e23f3336SMark Rustad  *  @linear: true if SFP module is linear
1610e23f3336SMark Rustad  */
ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw * hw,bool * linear)1611e23f3336SMark Rustad static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear)
1612e23f3336SMark Rustad {
1613e23f3336SMark Rustad 	switch (hw->phy.sfp_type) {
1614e23f3336SMark Rustad 	case ixgbe_sfp_type_not_present:
161503c5b6d4SJedrzej Jagielski 		return -ENOENT;
1616e23f3336SMark Rustad 	case ixgbe_sfp_type_da_cu_core0:
1617e23f3336SMark Rustad 	case ixgbe_sfp_type_da_cu_core1:
1618e23f3336SMark Rustad 		*linear = true;
1619e23f3336SMark Rustad 		break;
1620e23f3336SMark Rustad 	case ixgbe_sfp_type_srlr_core0:
1621e23f3336SMark Rustad 	case ixgbe_sfp_type_srlr_core1:
1622e23f3336SMark Rustad 	case ixgbe_sfp_type_da_act_lmt_core0:
1623e23f3336SMark Rustad 	case ixgbe_sfp_type_da_act_lmt_core1:
1624e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_sx_core0:
1625e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_sx_core1:
1626e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_lx_core0:
1627e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_lx_core1:
1628e23f3336SMark Rustad 		*linear = false;
1629e23f3336SMark Rustad 		break;
1630e23f3336SMark Rustad 	case ixgbe_sfp_type_unknown:
1631e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_cu_core0:
1632e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_cu_core1:
1633e23f3336SMark Rustad 	default:
163403c5b6d4SJedrzej Jagielski 		return -EOPNOTSUPP;
1635e23f3336SMark Rustad 	}
1636e23f3336SMark Rustad 
1637e23f3336SMark Rustad 	return 0;
1638e23f3336SMark Rustad }
1639e23f3336SMark Rustad 
1640e23f3336SMark Rustad /**
16416d373a1bSMark Rustad  * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP.
16426d373a1bSMark Rustad  * @hw: pointer to hardware structure
16435ba643c6STony Nguyen  * @speed: the link speed to force
16445ba643c6STony Nguyen  * @autoneg_wait_to_complete: unused
16456d373a1bSMark Rustad  *
16466d373a1bSMark Rustad  * Configures the extern PHY and the integrated KR PHY for SFP support.
16476d373a1bSMark Rustad  */
16486d373a1bSMark Rustad static s32
ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw * hw,ixgbe_link_speed speed,__always_unused bool autoneg_wait_to_complete)16496d373a1bSMark Rustad ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
16506d373a1bSMark Rustad 				ixgbe_link_speed speed,
16516d373a1bSMark Rustad 				__always_unused bool autoneg_wait_to_complete)
16526d373a1bSMark Rustad {
1653e23f3336SMark Rustad 	s32 status;
1654812d7dffSEmil Tantilov 	u16 reg_slice, reg_val;
1655e23f3336SMark Rustad 	bool setup_linear = false;
1656e23f3336SMark Rustad 
1657e23f3336SMark Rustad 	/* Check if SFP module is supported and linear */
1658e23f3336SMark Rustad 	status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
1659e23f3336SMark Rustad 
1660e23f3336SMark Rustad 	/* If no SFP module present, then return success. Return success since
1661e23f3336SMark Rustad 	 * there is no reason to configure CS4227 and SFP not present error is
1662e23f3336SMark Rustad 	 * not accepted in the setup MAC link flow.
1663e23f3336SMark Rustad 	 */
166403c5b6d4SJedrzej Jagielski 	if (status == -ENOENT)
1665e23f3336SMark Rustad 		return 0;
1666e23f3336SMark Rustad 
1667e23f3336SMark Rustad 	if (status)
1668e23f3336SMark Rustad 		return status;
1669e23f3336SMark Rustad 
1670d91e3a7dSMark Rustad 	/* Configure internal PHY for KR/KX. */
1671812d7dffSEmil Tantilov 	ixgbe_setup_kr_speed_x550em(hw, speed);
1672e23f3336SMark Rustad 
1673d91e3a7dSMark Rustad 	/* Configure CS4227 LINE side to proper mode. */
1674812d7dffSEmil Tantilov 	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
1675d91e3a7dSMark Rustad 	if (setup_linear)
1676812d7dffSEmil Tantilov 		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
1677d91e3a7dSMark Rustad 	else
1678812d7dffSEmil Tantilov 		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
1679b71f6c40SEmil Tantilov 
1680b71f6c40SEmil Tantilov 	status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice,
1681b71f6c40SEmil Tantilov 					 reg_val);
1682b71f6c40SEmil Tantilov 
1683e23f3336SMark Rustad 	return status;
16846d373a1bSMark Rustad }
16856d373a1bSMark Rustad 
16866d373a1bSMark Rustad /**
1687470739b5SDon Skidmore  * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode
1688470739b5SDon Skidmore  * @hw: pointer to hardware structure
1689470739b5SDon Skidmore  * @speed: the link speed to force
1690470739b5SDon Skidmore  *
1691470739b5SDon Skidmore  * Configures the integrated PHY for native SFI mode. Used to connect the
1692470739b5SDon Skidmore  * internal PHY directly to an SFP cage, without autonegotiation.
1693470739b5SDon Skidmore  **/
ixgbe_setup_sfi_x550a(struct ixgbe_hw * hw,ixgbe_link_speed * speed)1694470739b5SDon Skidmore static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
1695470739b5SDon Skidmore {
1696470739b5SDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
1697470739b5SDon Skidmore 	s32 status;
1698470739b5SDon Skidmore 	u32 reg_val;
1699470739b5SDon Skidmore 
1700470739b5SDon Skidmore 	/* Disable all AN and force speed to 10G Serial. */
1701470739b5SDon Skidmore 	status = mac->ops.read_iosf_sb_reg(hw,
1702470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1703470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
1704470739b5SDon Skidmore 	if (status)
1705470739b5SDon Skidmore 		return status;
1706470739b5SDon Skidmore 
1707470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
1708470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
1709470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
1710470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
1711470739b5SDon Skidmore 
1712470739b5SDon Skidmore 	/* Select forced link speed for internal PHY. */
1713470739b5SDon Skidmore 	switch (*speed) {
1714470739b5SDon Skidmore 	case IXGBE_LINK_SPEED_10GB_FULL:
1715470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G;
1716470739b5SDon Skidmore 		break;
1717470739b5SDon Skidmore 	case IXGBE_LINK_SPEED_1GB_FULL:
1718470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
1719470739b5SDon Skidmore 		break;
1720470739b5SDon Skidmore 	default:
1721470739b5SDon Skidmore 		/* Other link speeds are not supported by internal PHY. */
172203c5b6d4SJedrzej Jagielski 		return -EINVAL;
1723470739b5SDon Skidmore 	}
1724470739b5SDon Skidmore 
172511f1fb81SJacob Keller 	status = mac->ops.write_iosf_sb_reg(hw,
1726470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1727470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
1728470739b5SDon Skidmore 
1729470739b5SDon Skidmore 	/* Toggle port SW reset by AN reset. */
1730470739b5SDon Skidmore 	status = ixgbe_restart_an_internal_phy_x550em(hw);
1731470739b5SDon Skidmore 
1732470739b5SDon Skidmore 	return status;
1733470739b5SDon Skidmore }
1734470739b5SDon Skidmore 
1735470739b5SDon Skidmore /**
17362d40cd17SMark Rustad  * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP
17372d40cd17SMark Rustad  * @hw: pointer to hardware structure
17385ba643c6STony Nguyen  * @speed: link speed
17395ba643c6STony Nguyen  * @autoneg_wait_to_complete: unused
17402d40cd17SMark Rustad  *
17414fb8cfedSJiang Jian  * Configure the integrated PHY for native SFP support.
17422d40cd17SMark Rustad  */
17432d40cd17SMark Rustad static s32
ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw * hw,ixgbe_link_speed speed,__always_unused bool autoneg_wait_to_complete)17442d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed,
17452d40cd17SMark Rustad 			   __always_unused bool autoneg_wait_to_complete)
17462d40cd17SMark Rustad {
17472d40cd17SMark Rustad 	bool setup_linear = false;
17482d40cd17SMark Rustad 	u32 reg_phy_int;
1749470739b5SDon Skidmore 	s32 ret_val;
17502d40cd17SMark Rustad 
17512d40cd17SMark Rustad 	/* Check if SFP module is supported and linear */
1752470739b5SDon Skidmore 	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
17532d40cd17SMark Rustad 
17542d40cd17SMark Rustad 	/* If no SFP module present, then return success. Return success since
17552d40cd17SMark Rustad 	 * SFP not present error is not excepted in the setup MAC link flow.
17562d40cd17SMark Rustad 	 */
175703c5b6d4SJedrzej Jagielski 	if (ret_val == -ENOENT)
17582d40cd17SMark Rustad 		return 0;
17592d40cd17SMark Rustad 
1760d9c23ff8SEmil Tantilov 	if (ret_val)
1761470739b5SDon Skidmore 		return ret_val;
17622d40cd17SMark Rustad 
1763470739b5SDon Skidmore 	/* Configure internal PHY for native SFI based on module type */
1764470739b5SDon Skidmore 	ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
1765470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1766470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
1767d9c23ff8SEmil Tantilov 	if (ret_val)
1768470739b5SDon Skidmore 		return ret_val;
17692d40cd17SMark Rustad 
1770470739b5SDon Skidmore 	reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA;
1771470739b5SDon Skidmore 	if (!setup_linear)
1772470739b5SDon Skidmore 		reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR;
17732d40cd17SMark Rustad 
1774470739b5SDon Skidmore 	ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
1775470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1776470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
1777d9c23ff8SEmil Tantilov 	if (ret_val)
1778470739b5SDon Skidmore 		return ret_val;
17792d40cd17SMark Rustad 
1780470739b5SDon Skidmore 	/* Setup SFI internal link. */
1781470739b5SDon Skidmore 	return ixgbe_setup_sfi_x550a(hw, &speed);
17822d40cd17SMark Rustad }
17832d40cd17SMark Rustad 
17842d40cd17SMark Rustad /**
17852d40cd17SMark Rustad  * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP
17862d40cd17SMark Rustad  * @hw: pointer to hardware structure
17875ba643c6STony Nguyen  * @speed: link speed
17885ba643c6STony Nguyen  * @autoneg_wait_to_complete: unused
17892d40cd17SMark Rustad  *
17904fb8cfedSJiang Jian  * Configure the integrated PHY for SFP support.
17912d40cd17SMark Rustad  */
17922d40cd17SMark Rustad static s32
ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw * hw,ixgbe_link_speed speed,__always_unused bool autoneg_wait_to_complete)17932d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed,
17942d40cd17SMark Rustad 			       __always_unused bool autoneg_wait_to_complete)
17952d40cd17SMark Rustad {
17962d40cd17SMark Rustad 	u32 reg_slice, slice_offset;
17972d40cd17SMark Rustad 	bool setup_linear = false;
17982d40cd17SMark Rustad 	u16 reg_phy_ext;
1799470739b5SDon Skidmore 	s32 ret_val;
18002d40cd17SMark Rustad 
18012d40cd17SMark Rustad 	/* Check if SFP module is supported and linear */
1802470739b5SDon Skidmore 	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
18032d40cd17SMark Rustad 
18042d40cd17SMark Rustad 	/* If no SFP module present, then return success. Return success since
18052d40cd17SMark Rustad 	 * SFP not present error is not excepted in the setup MAC link flow.
18062d40cd17SMark Rustad 	 */
180703c5b6d4SJedrzej Jagielski 	if (ret_val == -ENOENT)
18082d40cd17SMark Rustad 		return 0;
18092d40cd17SMark Rustad 
1810d9c23ff8SEmil Tantilov 	if (ret_val)
1811470739b5SDon Skidmore 		return ret_val;
18122d40cd17SMark Rustad 
18132d40cd17SMark Rustad 	/* Configure internal PHY for KR/KX. */
18142d40cd17SMark Rustad 	ixgbe_setup_kr_speed_x550em(hw, speed);
18152d40cd17SMark Rustad 
18167564a888SMark Rustad 	if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE)
181703c5b6d4SJedrzej Jagielski 		return -EFAULT;
18182d40cd17SMark Rustad 
1819cc1de78cSEmil Tantilov 	/* Get external PHY SKU id */
1820cc1de78cSEmil Tantilov 	ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU,
18212d40cd17SMark Rustad 				       IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
1822470739b5SDon Skidmore 	if (ret_val)
1823470739b5SDon Skidmore 		return ret_val;
18242d40cd17SMark Rustad 
18252d40cd17SMark Rustad 	/* When configuring quad port CS4223, the MAC instance is part
18262d40cd17SMark Rustad 	 * of the slice offset.
18272d40cd17SMark Rustad 	 */
1828cc1de78cSEmil Tantilov 	if (reg_phy_ext == IXGBE_CS4223_SKU_ID)
18292d40cd17SMark Rustad 		slice_offset = (hw->bus.lan_id +
18302d40cd17SMark Rustad 				(hw->bus.instance_id << 1)) << 12;
18312d40cd17SMark Rustad 	else
18322d40cd17SMark Rustad 		slice_offset = hw->bus.lan_id << 12;
18332d40cd17SMark Rustad 
18342d40cd17SMark Rustad 	/* Configure CS4227/CS4223 LINE side to proper mode. */
18352d40cd17SMark Rustad 	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
1836410a4949SEmil Tantilov 
1837410a4949SEmil Tantilov 	ret_val = hw->phy.ops.read_reg(hw, reg_slice,
1838410a4949SEmil Tantilov 				       IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
1839410a4949SEmil Tantilov 	if (ret_val)
1840410a4949SEmil Tantilov 		return ret_val;
1841410a4949SEmil Tantilov 
1842410a4949SEmil Tantilov 	reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) |
1843410a4949SEmil Tantilov 			 (IXGBE_CS4227_EDC_MODE_SR << 1));
1844410a4949SEmil Tantilov 
18452d40cd17SMark Rustad 	if (setup_linear)
18469bf1e20fSPaul Greenwalt 		reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1;
18472d40cd17SMark Rustad 	else
18489bf1e20fSPaul Greenwalt 		reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_SR << 1) | 1;
1849410a4949SEmil Tantilov 
1850410a4949SEmil Tantilov 	ret_val = hw->phy.ops.write_reg(hw, reg_slice,
1851410a4949SEmil Tantilov 					IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
1852410a4949SEmil Tantilov 	if (ret_val)
1853410a4949SEmil Tantilov 		return ret_val;
1854410a4949SEmil Tantilov 
1855410a4949SEmil Tantilov 	/* Flush previous write with a read */
1856410a4949SEmil Tantilov 	return hw->phy.ops.read_reg(hw, reg_slice,
1857410a4949SEmil Tantilov 				    IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
18582d40cd17SMark Rustad }
18592d40cd17SMark Rustad 
18602d40cd17SMark Rustad /**
1861c3dc4c09SDon Skidmore  * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
1862c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
1863c3dc4c09SDon Skidmore  * @speed: new link speed
18645ba643c6STony Nguyen  * @autoneg_wait: true when waiting for completion is needed
1865c3dc4c09SDon Skidmore  *
1866c3dc4c09SDon Skidmore  * Setup internal/external PHY link speed based on link speed, then set
1867c3dc4c09SDon Skidmore  * external PHY auto advertised link speed.
1868c3dc4c09SDon Skidmore  *
1869c3dc4c09SDon Skidmore  * Returns error status for any failure
1870c3dc4c09SDon Skidmore  **/
ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait)1871c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
1872c3dc4c09SDon Skidmore 					 ixgbe_link_speed speed,
1873c3dc4c09SDon Skidmore 					 bool autoneg_wait)
1874c3dc4c09SDon Skidmore {
1875c3dc4c09SDon Skidmore 	s32 status;
1876c3dc4c09SDon Skidmore 	ixgbe_link_speed force_speed;
1877c3dc4c09SDon Skidmore 
1878c3dc4c09SDon Skidmore 	/* Setup internal/external PHY link speed to iXFI (10G), unless
1879c3dc4c09SDon Skidmore 	 * only 1G is auto advertised then setup KX link.
1880c3dc4c09SDon Skidmore 	 */
1881c3dc4c09SDon Skidmore 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
1882c3dc4c09SDon Skidmore 		force_speed = IXGBE_LINK_SPEED_10GB_FULL;
1883c3dc4c09SDon Skidmore 	else
1884c3dc4c09SDon Skidmore 		force_speed = IXGBE_LINK_SPEED_1GB_FULL;
1885c3dc4c09SDon Skidmore 
188648301cf2STony Nguyen 	/* If X552 and internal link mode is XFI, then setup XFI internal link.
188748301cf2STony Nguyen 	 */
188848301cf2STony Nguyen 	if (hw->mac.type == ixgbe_mac_X550EM_x &&
188948301cf2STony Nguyen 	    !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
1890c3dc4c09SDon Skidmore 		status = ixgbe_setup_ixfi_x550em(hw, &force_speed);
1891c3dc4c09SDon Skidmore 
1892c3dc4c09SDon Skidmore 		if (status)
1893c3dc4c09SDon Skidmore 			return status;
1894c3dc4c09SDon Skidmore 	}
1895c3dc4c09SDon Skidmore 
1896c3dc4c09SDon Skidmore 	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
1897c3dc4c09SDon Skidmore }
1898c3dc4c09SDon Skidmore 
1899a4e293a5SDon Skidmore /** ixgbe_check_link_t_X550em - Determine link and speed status
1900a4e293a5SDon Skidmore   * @hw: pointer to hardware structure
1901a4e293a5SDon Skidmore   * @speed: pointer to link speed
1902a4e293a5SDon Skidmore   * @link_up: true when link is up
1903a4e293a5SDon Skidmore   * @link_up_wait_to_complete: bool used to wait for link up or not
1904a4e293a5SDon Skidmore   *
1905a4e293a5SDon Skidmore   * Check that both the MAC and X557 external PHY have link.
1906a4e293a5SDon Skidmore   **/
ixgbe_check_link_t_X550em(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * link_up,bool link_up_wait_to_complete)1907a4e293a5SDon Skidmore static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw,
1908a4e293a5SDon Skidmore 				     ixgbe_link_speed *speed,
1909a4e293a5SDon Skidmore 				     bool *link_up,
1910a4e293a5SDon Skidmore 				     bool link_up_wait_to_complete)
1911a4e293a5SDon Skidmore {
1912a4e293a5SDon Skidmore 	u32 status;
191321d882ebSEmil Tantilov 	u16 i, autoneg_status;
1914a4e293a5SDon Skidmore 
1915a4e293a5SDon Skidmore 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
191603c5b6d4SJedrzej Jagielski 		return -EIO;
1917a4e293a5SDon Skidmore 
1918a4e293a5SDon Skidmore 	status = ixgbe_check_mac_link_generic(hw, speed, link_up,
1919a4e293a5SDon Skidmore 					      link_up_wait_to_complete);
1920a4e293a5SDon Skidmore 
1921a4e293a5SDon Skidmore 	/* If check link fails or MAC link is not up, then return */
1922a4e293a5SDon Skidmore 	if (status || !(*link_up))
1923a4e293a5SDon Skidmore 		return status;
1924a4e293a5SDon Skidmore 
1925a4e293a5SDon Skidmore 	/* MAC link is up, so check external PHY link.
192621d882ebSEmil Tantilov 	 * Link status is latching low, and can only be used to detect link
192721d882ebSEmil Tantilov 	 * drop, and not the current status of the link without performing
192821d882ebSEmil Tantilov 	 * back-to-back reads.
1929a4e293a5SDon Skidmore 	 */
193021d882ebSEmil Tantilov 	for (i = 0; i < 2; i++) {
19314dc4000bSEmil Tantilov 		status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
1932a4e293a5SDon Skidmore 					      &autoneg_status);
193321d882ebSEmil Tantilov 
1934a4e293a5SDon Skidmore 		if (status)
1935a4e293a5SDon Skidmore 			return status;
193621d882ebSEmil Tantilov 	}
1937a4e293a5SDon Skidmore 
1938a4e293a5SDon Skidmore 	/* If external PHY link is not up, then indicate link not up */
1939a4e293a5SDon Skidmore 	if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
1940a4e293a5SDon Skidmore 		*link_up = false;
1941a4e293a5SDon Skidmore 
1942a4e293a5SDon Skidmore 	return 0;
1943a4e293a5SDon Skidmore }
1944a4e293a5SDon Skidmore 
1945200157c2SMark Rustad /**
1946200157c2SMark Rustad  * ixgbe_setup_sgmii - Set up link for sgmii
1947200157c2SMark Rustad  * @hw: pointer to hardware structure
19485ba643c6STony Nguyen  * @speed: unused
19495ba643c6STony Nguyen  * @autoneg_wait_to_complete: unused
1950200157c2SMark Rustad  */
1951200157c2SMark Rustad static s32
ixgbe_setup_sgmii(struct ixgbe_hw * hw,__always_unused ixgbe_link_speed speed,__always_unused bool autoneg_wait_to_complete)1952200157c2SMark Rustad ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed,
1953200157c2SMark Rustad 		  __always_unused bool autoneg_wait_to_complete)
1954200157c2SMark Rustad {
1955200157c2SMark Rustad 	struct ixgbe_mac_info *mac = &hw->mac;
1956470739b5SDon Skidmore 	u32 lval, sval, flx_val;
1957200157c2SMark Rustad 	s32 rc;
1958200157c2SMark Rustad 
1959200157c2SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
1960200157c2SMark Rustad 				       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1961200157c2SMark Rustad 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
1962200157c2SMark Rustad 	if (rc)
1963200157c2SMark Rustad 		return rc;
1964200157c2SMark Rustad 
1965200157c2SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
1966200157c2SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
1967200157c2SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
1968200157c2SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
1969200157c2SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
1970200157c2SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
1971200157c2SMark Rustad 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1972200157c2SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
1973200157c2SMark Rustad 	if (rc)
1974200157c2SMark Rustad 		return rc;
1975200157c2SMark Rustad 
1976200157c2SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
1977200157c2SMark Rustad 				       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
1978200157c2SMark Rustad 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
1979200157c2SMark Rustad 	if (rc)
1980200157c2SMark Rustad 		return rc;
1981200157c2SMark Rustad 
1982200157c2SMark Rustad 	sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
1983200157c2SMark Rustad 	sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
1984200157c2SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
1985200157c2SMark Rustad 					IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
1986200157c2SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
1987200157c2SMark Rustad 	if (rc)
1988200157c2SMark Rustad 		return rc;
1989200157c2SMark Rustad 
1990470739b5SDon Skidmore 	rc = mac->ops.read_iosf_sb_reg(hw,
1991470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1992470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
1993470739b5SDon Skidmore 	if (rc)
1994470739b5SDon Skidmore 		return rc;
1995200157c2SMark Rustad 
1996470739b5SDon Skidmore 	rc = mac->ops.read_iosf_sb_reg(hw,
1997470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1998470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
1999470739b5SDon Skidmore 	if (rc)
2000470739b5SDon Skidmore 		return rc;
2001470739b5SDon Skidmore 
2002470739b5SDon Skidmore 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
2003470739b5SDon Skidmore 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
2004470739b5SDon Skidmore 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
2005470739b5SDon Skidmore 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
2006470739b5SDon Skidmore 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
2007470739b5SDon Skidmore 
2008470739b5SDon Skidmore 	rc = mac->ops.write_iosf_sb_reg(hw,
2009470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2010470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
2011470739b5SDon Skidmore 	if (rc)
2012470739b5SDon Skidmore 		return rc;
2013470739b5SDon Skidmore 
2014470739b5SDon Skidmore 	rc = ixgbe_restart_an_internal_phy_x550em(hw);
2015200157c2SMark Rustad 	return rc;
2016200157c2SMark Rustad }
2017200157c2SMark Rustad 
2018b3eb4e18SMark Rustad /**
2019b3eb4e18SMark Rustad  * ixgbe_setup_sgmii_fw - Set up link for sgmii with firmware-controlled PHYs
2020b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
20215ba643c6STony Nguyen  * @speed: the link speed to force
20225ba643c6STony Nguyen  * @autoneg_wait: true when waiting for completion is needed
2023b3eb4e18SMark Rustad  */
ixgbe_setup_sgmii_fw(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait)2024b3eb4e18SMark Rustad static s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed,
2025b3eb4e18SMark Rustad 				bool autoneg_wait)
2026b3eb4e18SMark Rustad {
2027b3eb4e18SMark Rustad 	struct ixgbe_mac_info *mac = &hw->mac;
2028b3eb4e18SMark Rustad 	u32 lval, sval, flx_val;
2029b3eb4e18SMark Rustad 	s32 rc;
2030b3eb4e18SMark Rustad 
2031b3eb4e18SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
2032b3eb4e18SMark Rustad 				       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2033b3eb4e18SMark Rustad 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
2034b3eb4e18SMark Rustad 	if (rc)
2035b3eb4e18SMark Rustad 		return rc;
2036b3eb4e18SMark Rustad 
2037b3eb4e18SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
2038b3eb4e18SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
2039b3eb4e18SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
2040b3eb4e18SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
2041b3eb4e18SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
2042b3eb4e18SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
2043b3eb4e18SMark Rustad 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2044b3eb4e18SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
2045b3eb4e18SMark Rustad 	if (rc)
2046b3eb4e18SMark Rustad 		return rc;
2047b3eb4e18SMark Rustad 
2048b3eb4e18SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
2049b3eb4e18SMark Rustad 				       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
2050b3eb4e18SMark Rustad 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
2051b3eb4e18SMark Rustad 	if (rc)
2052b3eb4e18SMark Rustad 		return rc;
2053b3eb4e18SMark Rustad 
2054b3eb4e18SMark Rustad 	sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
2055b3eb4e18SMark Rustad 	sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
2056b3eb4e18SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
2057b3eb4e18SMark Rustad 					IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
2058b3eb4e18SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
2059b3eb4e18SMark Rustad 	if (rc)
2060b3eb4e18SMark Rustad 		return rc;
2061b3eb4e18SMark Rustad 
2062b3eb4e18SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
2063b3eb4e18SMark Rustad 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2064b3eb4e18SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
2065b3eb4e18SMark Rustad 	if (rc)
2066b3eb4e18SMark Rustad 		return rc;
2067b3eb4e18SMark Rustad 
2068b3eb4e18SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
2069b3eb4e18SMark Rustad 				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2070b3eb4e18SMark Rustad 				    IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
2071b3eb4e18SMark Rustad 	if (rc)
2072b3eb4e18SMark Rustad 		return rc;
2073b3eb4e18SMark Rustad 
2074b3eb4e18SMark Rustad 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
2075b3eb4e18SMark Rustad 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
2076b3eb4e18SMark Rustad 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
2077b3eb4e18SMark Rustad 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
2078b3eb4e18SMark Rustad 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
2079b3eb4e18SMark Rustad 
2080b3eb4e18SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
2081b3eb4e18SMark Rustad 				    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2082b3eb4e18SMark Rustad 				    IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
2083b3eb4e18SMark Rustad 	if (rc)
2084b3eb4e18SMark Rustad 		return rc;
2085b3eb4e18SMark Rustad 
2086b3eb4e18SMark Rustad 	ixgbe_restart_an_internal_phy_x550em(hw);
2087b3eb4e18SMark Rustad 
2088b3eb4e18SMark Rustad 	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
2089b3eb4e18SMark Rustad }
2090b3eb4e18SMark Rustad 
2091b3eb4e18SMark Rustad /**
2092b3eb4e18SMark Rustad  * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37
2093b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
2094b3eb4e18SMark Rustad  *
2095b3eb4e18SMark Rustad  * Enable flow control according to IEEE clause 37.
2096b3eb4e18SMark Rustad  */
ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw * hw)2097b3eb4e18SMark Rustad static void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)
2098b3eb4e18SMark Rustad {
2099b3eb4e18SMark Rustad 	u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
2100b3eb4e18SMark Rustad 	ixgbe_link_speed speed;
210103c5b6d4SJedrzej Jagielski 	s32 status = -EIO;
2102b3eb4e18SMark Rustad 	bool link_up;
2103b3eb4e18SMark Rustad 
2104b3eb4e18SMark Rustad 	/* AN should have completed when the cable was plugged in.
2105b3eb4e18SMark Rustad 	 * Look for reasons to bail out.  Bail out if:
2106b3eb4e18SMark Rustad 	 * - FC autoneg is disabled, or if
2107b3eb4e18SMark Rustad 	 * - link is not up.
2108b3eb4e18SMark Rustad 	 */
2109b3eb4e18SMark Rustad 	if (hw->fc.disable_fc_autoneg)
2110b3eb4e18SMark Rustad 		goto out;
2111b3eb4e18SMark Rustad 
2112b3eb4e18SMark Rustad 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
2113b3eb4e18SMark Rustad 	if (!link_up)
2114b3eb4e18SMark Rustad 		goto out;
2115b3eb4e18SMark Rustad 
2116b3eb4e18SMark Rustad 	/* Check if auto-negotiation has completed */
2117b3eb4e18SMark Rustad 	status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info);
2118b3eb4e18SMark Rustad 	if (status || !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) {
211903c5b6d4SJedrzej Jagielski 		status = -EIO;
2120b3eb4e18SMark Rustad 		goto out;
2121b3eb4e18SMark Rustad 	}
2122b3eb4e18SMark Rustad 
2123b3eb4e18SMark Rustad 	/* Negotiate the flow control */
2124b3eb4e18SMark Rustad 	status = ixgbe_negotiate_fc(hw, info[0], info[0],
2125b3eb4e18SMark Rustad 				    FW_PHY_ACT_GET_LINK_INFO_FC_RX,
2126b3eb4e18SMark Rustad 				    FW_PHY_ACT_GET_LINK_INFO_FC_TX,
2127b3eb4e18SMark Rustad 				    FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX,
2128b3eb4e18SMark Rustad 				    FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX);
2129b3eb4e18SMark Rustad 
2130b3eb4e18SMark Rustad out:
2131b3eb4e18SMark Rustad 	if (!status) {
2132b3eb4e18SMark Rustad 		hw->fc.fc_was_autonegged = true;
2133b3eb4e18SMark Rustad 	} else {
2134b3eb4e18SMark Rustad 		hw->fc.fc_was_autonegged = false;
2135b3eb4e18SMark Rustad 		hw->fc.current_mode = hw->fc.requested_mode;
2136b3eb4e18SMark Rustad 	}
2137b3eb4e18SMark Rustad }
2138b3eb4e18SMark Rustad 
21392916500dSDon Skidmore /** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers
21402916500dSDon Skidmore  *  @hw: pointer to hardware structure
21412916500dSDon Skidmore  **/
ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw * hw)21422916500dSDon Skidmore static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw)
21432916500dSDon Skidmore {
21442916500dSDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
21452916500dSDon Skidmore 
21462916500dSDon Skidmore 	switch (mac->ops.get_media_type(hw)) {
21472916500dSDon Skidmore 	case ixgbe_media_type_fiber:
21482916500dSDon Skidmore 		mac->ops.setup_fc = NULL;
21492916500dSDon Skidmore 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;
21502916500dSDon Skidmore 		break;
2151b3eb4e18SMark Rustad 	case ixgbe_media_type_copper:
2152b3eb4e18SMark Rustad 		if (hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T &&
2153b3eb4e18SMark Rustad 		    hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T_L) {
2154b3eb4e18SMark Rustad 			mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
2155b3eb4e18SMark Rustad 			break;
2156b3eb4e18SMark Rustad 		}
2157b3eb4e18SMark Rustad 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a;
2158b3eb4e18SMark Rustad 		mac->ops.setup_fc = ixgbe_fc_autoneg_fw;
2159b3eb4e18SMark Rustad 		mac->ops.setup_link = ixgbe_setup_sgmii_fw;
2160b3eb4e18SMark Rustad 		mac->ops.check_link = ixgbe_check_mac_link_generic;
2161b3eb4e18SMark Rustad 		break;
21622916500dSDon Skidmore 	case ixgbe_media_type_backplane:
21632916500dSDon Skidmore 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;
21642916500dSDon Skidmore 		mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;
21652916500dSDon Skidmore 		break;
21662916500dSDon Skidmore 	default:
21672916500dSDon Skidmore 		break;
21682916500dSDon Skidmore 	}
21692916500dSDon Skidmore }
21702916500dSDon Skidmore 
2171c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers
2172c3dc4c09SDon Skidmore  *  @hw: pointer to hardware structure
2173c3dc4c09SDon Skidmore  **/
ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw * hw)2174c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
2175c3dc4c09SDon Skidmore {
2176c3dc4c09SDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
2177c3dc4c09SDon Skidmore 
2178abf76d76SEmil Tantilov 	mac->ops.setup_fc = ixgbe_setup_fc_x550em;
2179abf76d76SEmil Tantilov 
2180c3dc4c09SDon Skidmore 	switch (mac->ops.get_media_type(hw)) {
2181c3dc4c09SDon Skidmore 	case ixgbe_media_type_fiber:
2182c3dc4c09SDon Skidmore 		/* CS4227 does not support autoneg, so disable the laser control
2183c3dc4c09SDon Skidmore 		 * functions for SFP+ fiber
2184c3dc4c09SDon Skidmore 		 */
2185c3dc4c09SDon Skidmore 		mac->ops.disable_tx_laser = NULL;
2186c3dc4c09SDon Skidmore 		mac->ops.enable_tx_laser = NULL;
2187c3dc4c09SDon Skidmore 		mac->ops.flap_tx_laser = NULL;
21886d373a1bSMark Rustad 		mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
21892d40cd17SMark Rustad 		switch (hw->device_id) {
21902d40cd17SMark Rustad 		case IXGBE_DEV_ID_X550EM_A_SFP_N:
21912d40cd17SMark Rustad 			mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n;
21922d40cd17SMark Rustad 			break;
21932d40cd17SMark Rustad 		case IXGBE_DEV_ID_X550EM_A_SFP:
21942d40cd17SMark Rustad 			mac->ops.setup_mac_link =
21952d40cd17SMark Rustad 						ixgbe_setup_mac_link_sfp_x550a;
21962d40cd17SMark Rustad 			break;
21972d40cd17SMark Rustad 		default:
21982d40cd17SMark Rustad 			mac->ops.setup_mac_link =
21992d40cd17SMark Rustad 						ixgbe_setup_mac_link_sfp_x550em;
22002d40cd17SMark Rustad 			break;
22012d40cd17SMark Rustad 		}
22026d373a1bSMark Rustad 		mac->ops.set_rate_select_speed =
22036d373a1bSMark Rustad 					ixgbe_set_soft_rate_select_speed;
2204c3dc4c09SDon Skidmore 		break;
2205c3dc4c09SDon Skidmore 	case ixgbe_media_type_copper:
22068dc963e1SPaul Greenwalt 		if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T)
22078dc963e1SPaul Greenwalt 			break;
2208c3dc4c09SDon Skidmore 		mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
2209afdc71e4SMark Rustad 		mac->ops.setup_fc = ixgbe_setup_fc_generic;
2210a4e293a5SDon Skidmore 		mac->ops.check_link = ixgbe_check_link_t_X550em;
2211b3eb4e18SMark Rustad 		break;
221249425dfcSMark Rustad 	case ixgbe_media_type_backplane:
2213200157c2SMark Rustad 		if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
2214200157c2SMark Rustad 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)
2215200157c2SMark Rustad 			mac->ops.setup_link = ixgbe_setup_sgmii;
2216c3dc4c09SDon Skidmore 		break;
2217c3dc4c09SDon Skidmore 	default:
2218c3dc4c09SDon Skidmore 		break;
2219c3dc4c09SDon Skidmore 	}
22202916500dSDon Skidmore 
22212916500dSDon Skidmore 	/* Additional modification for X550em_a devices */
22222916500dSDon Skidmore 	if (hw->mac.type == ixgbe_mac_x550em_a)
22232916500dSDon Skidmore 		ixgbe_init_mac_link_ops_X550em_a(hw);
2224c3dc4c09SDon Skidmore }
2225c3dc4c09SDon Skidmore 
2226c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module
2227c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2228c3dc4c09SDon Skidmore  */
ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw * hw)2229c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
2230c3dc4c09SDon Skidmore {
2231e23f3336SMark Rustad 	s32 status;
2232e23f3336SMark Rustad 	bool linear;
2233c3dc4c09SDon Skidmore 
2234e23f3336SMark Rustad 	/* Check if SFP module is supported */
2235e23f3336SMark Rustad 	status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
2236e23f3336SMark Rustad 	if (status)
2237e23f3336SMark Rustad 		return status;
2238c3dc4c09SDon Skidmore 
2239c3dc4c09SDon Skidmore 	ixgbe_init_mac_link_ops_X550em(hw);
2240c3dc4c09SDon Skidmore 	hw->phy.ops.reset = NULL;
2241c3dc4c09SDon Skidmore 
2242e23f3336SMark Rustad 	return 0;
2243c3dc4c09SDon Skidmore }
2244c3dc4c09SDon Skidmore 
2245c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities
2246c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2247c3dc4c09SDon Skidmore  * @speed: pointer to link speed
2248c3dc4c09SDon Skidmore  * @autoneg: true when autoneg or autotry is enabled
2249c3dc4c09SDon Skidmore  **/
ixgbe_get_link_capabilities_X550em(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * autoneg)2250c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
2251c3dc4c09SDon Skidmore 					      ixgbe_link_speed *speed,
2252c3dc4c09SDon Skidmore 					      bool *autoneg)
2253c3dc4c09SDon Skidmore {
2254b3eb4e18SMark Rustad 	if (hw->phy.type == ixgbe_phy_fw) {
2255b3eb4e18SMark Rustad 		*autoneg = true;
2256b3eb4e18SMark Rustad 		*speed = hw->phy.speeds_supported;
2257b3eb4e18SMark Rustad 		return 0;
2258b3eb4e18SMark Rustad 	}
2259b3eb4e18SMark Rustad 
2260c3dc4c09SDon Skidmore 	/* SFP */
2261c3dc4c09SDon Skidmore 	if (hw->phy.media_type == ixgbe_media_type_fiber) {
2262c3dc4c09SDon Skidmore 		/* CS4227 SFP must not enable auto-negotiation */
2263c3dc4c09SDon Skidmore 		*autoneg = false;
2264c3dc4c09SDon Skidmore 
2265c3dc4c09SDon Skidmore 		if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
2266a8bf879aSJosh Elsasser 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
2267a8bf879aSJosh Elsasser 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
2268a8bf879aSJosh Elsasser 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) {
2269c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_1GB_FULL;
2270c3dc4c09SDon Skidmore 			return 0;
2271c3dc4c09SDon Skidmore 		}
2272c3dc4c09SDon Skidmore 
2273c3dc4c09SDon Skidmore 		/* Link capabilities are based on SFP */
2274c3dc4c09SDon Skidmore 		if (hw->phy.multispeed_fiber)
2275c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_10GB_FULL |
2276c3dc4c09SDon Skidmore 				 IXGBE_LINK_SPEED_1GB_FULL;
2277c3dc4c09SDon Skidmore 		else
2278c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_10GB_FULL;
2279c3dc4c09SDon Skidmore 	} else {
228018bda0d9SDon Skidmore 		switch (hw->phy.type) {
228118bda0d9SDon Skidmore 		case ixgbe_phy_x550em_kx4:
228218bda0d9SDon Skidmore 			*speed = IXGBE_LINK_SPEED_1GB_FULL |
228318bda0d9SDon Skidmore 				 IXGBE_LINK_SPEED_2_5GB_FULL |
228418bda0d9SDon Skidmore 				 IXGBE_LINK_SPEED_10GB_FULL;
228518bda0d9SDon Skidmore 			break;
228618e01ee7SDon Skidmore 		case ixgbe_phy_x550em_xfi:
228718e01ee7SDon Skidmore 			*speed = IXGBE_LINK_SPEED_1GB_FULL |
228818e01ee7SDon Skidmore 				 IXGBE_LINK_SPEED_10GB_FULL;
228918e01ee7SDon Skidmore 			break;
22908dc963e1SPaul Greenwalt 		case ixgbe_phy_ext_1g_t:
229118bda0d9SDon Skidmore 		case ixgbe_phy_sgmii:
229218bda0d9SDon Skidmore 			*speed = IXGBE_LINK_SPEED_1GB_FULL;
229318bda0d9SDon Skidmore 			break;
22948e5c9c53SDon Skidmore 		case ixgbe_phy_x550em_kr:
22958e5c9c53SDon Skidmore 			if (hw->mac.type == ixgbe_mac_x550em_a) {
22968e5c9c53SDon Skidmore 				/* check different backplane modes */
22978e5c9c53SDon Skidmore 				if (hw->phy.nw_mng_if_sel &
22988e5c9c53SDon Skidmore 				    IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
22998e5c9c53SDon Skidmore 					*speed = IXGBE_LINK_SPEED_2_5GB_FULL;
23008e5c9c53SDon Skidmore 					break;
23018e5c9c53SDon Skidmore 				} else if (hw->device_id ==
23028e5c9c53SDon Skidmore 					   IXGBE_DEV_ID_X550EM_A_KR_L) {
23038e5c9c53SDon Skidmore 					*speed = IXGBE_LINK_SPEED_1GB_FULL;
23048e5c9c53SDon Skidmore 					break;
23058e5c9c53SDon Skidmore 				}
23068e5c9c53SDon Skidmore 			}
23075463fce6SJeff Kirsher 			fallthrough;
230818bda0d9SDon Skidmore 		default:
2309c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_10GB_FULL |
2310c3dc4c09SDon Skidmore 				 IXGBE_LINK_SPEED_1GB_FULL;
231118bda0d9SDon Skidmore 			break;
231218bda0d9SDon Skidmore 		}
2313c3dc4c09SDon Skidmore 		*autoneg = true;
2314c3dc4c09SDon Skidmore 	}
2315c3dc4c09SDon Skidmore 	return 0;
2316c3dc4c09SDon Skidmore }
2317c3dc4c09SDon Skidmore 
2318c3dc4c09SDon Skidmore /**
2319c3dc4c09SDon Skidmore  * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause
2320c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2321c3dc4c09SDon Skidmore  * @lsc: pointer to boolean flag which indicates whether external Base T
2322c3dc4c09SDon Skidmore  *	 PHY interrupt is lsc
232309943985SJedrzej Jagielski  * @is_overtemp: indicate whether an overtemp event encountered
2324c3dc4c09SDon Skidmore  *
2325c3dc4c09SDon Skidmore  * Determime if external Base T PHY interrupt cause is high temperature
2326c3dc4c09SDon Skidmore  * failure alarm or link status change.
2327c3dc4c09SDon Skidmore  **/
ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw * hw,bool * lsc,bool * is_overtemp)232809943985SJedrzej Jagielski static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc,
232909943985SJedrzej Jagielski 				       bool *is_overtemp)
2330c3dc4c09SDon Skidmore {
2331c3dc4c09SDon Skidmore 	u32 status;
2332c3dc4c09SDon Skidmore 	u16 reg;
2333c3dc4c09SDon Skidmore 
233409943985SJedrzej Jagielski 	*is_overtemp = false;
2335c3dc4c09SDon Skidmore 	*lsc = false;
2336c3dc4c09SDon Skidmore 
2337c3dc4c09SDon Skidmore 	/* Vendor alarm triggered */
2338c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
23394dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2340c3dc4c09SDon Skidmore 				      &reg);
2341c3dc4c09SDon Skidmore 
2342c3dc4c09SDon Skidmore 	if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
2343c3dc4c09SDon Skidmore 		return status;
2344c3dc4c09SDon Skidmore 
2345c3dc4c09SDon Skidmore 	/* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
2346c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
23474dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2348c3dc4c09SDon Skidmore 				      &reg);
2349c3dc4c09SDon Skidmore 
2350c3dc4c09SDon Skidmore 	if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
2351c3dc4c09SDon Skidmore 				IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
2352c3dc4c09SDon Skidmore 		return status;
2353c3dc4c09SDon Skidmore 
235483a9fb20SMark Rustad 	/* Global alarm triggered */
2355c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
23564dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2357c3dc4c09SDon Skidmore 				      &reg);
2358c3dc4c09SDon Skidmore 
2359c3dc4c09SDon Skidmore 	if (status)
2360c3dc4c09SDon Skidmore 		return status;
2361c3dc4c09SDon Skidmore 
2362c3dc4c09SDon Skidmore 	/* If high temperature failure, then return over temp error and exit */
2363c3dc4c09SDon Skidmore 	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
2364c3dc4c09SDon Skidmore 		/* power down the PHY in case the PHY FW didn't already */
2365c3dc4c09SDon Skidmore 		ixgbe_set_copper_phy_power(hw, false);
236609943985SJedrzej Jagielski 		*is_overtemp = true;
236709943985SJedrzej Jagielski 		return -EIO;
2368c3dc4c09SDon Skidmore 	}
236983a9fb20SMark Rustad 	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
237083a9fb20SMark Rustad 		/*  device fault alarm triggered */
237183a9fb20SMark Rustad 		status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
23724dc4000bSEmil Tantilov 					  MDIO_MMD_VEND1,
237383a9fb20SMark Rustad 					  &reg);
237483a9fb20SMark Rustad 		if (status)
237583a9fb20SMark Rustad 			return status;
237683a9fb20SMark Rustad 
237783a9fb20SMark Rustad 		/* if device fault was due to high temp alarm handle and exit */
237883a9fb20SMark Rustad 		if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
237983a9fb20SMark Rustad 			/* power down the PHY in case the PHY FW didn't */
238083a9fb20SMark Rustad 			ixgbe_set_copper_phy_power(hw, false);
238109943985SJedrzej Jagielski 			*is_overtemp = true;
238209943985SJedrzej Jagielski 			return -EIO;
238383a9fb20SMark Rustad 		}
238483a9fb20SMark Rustad 	}
2385c3dc4c09SDon Skidmore 
2386c3dc4c09SDon Skidmore 	/* Vendor alarm 2 triggered */
2387c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
23884dc4000bSEmil Tantilov 				      MDIO_MMD_AN, &reg);
2389c3dc4c09SDon Skidmore 
2390c3dc4c09SDon Skidmore 	if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
2391c3dc4c09SDon Skidmore 		return status;
2392c3dc4c09SDon Skidmore 
2393c3dc4c09SDon Skidmore 	/* link connect/disconnect event occurred */
2394c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
23954dc4000bSEmil Tantilov 				      MDIO_MMD_AN, &reg);
2396c3dc4c09SDon Skidmore 
2397c3dc4c09SDon Skidmore 	if (status)
2398c3dc4c09SDon Skidmore 		return status;
2399c3dc4c09SDon Skidmore 
2400c3dc4c09SDon Skidmore 	/* Indicate LSC */
2401c3dc4c09SDon Skidmore 	if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC)
2402c3dc4c09SDon Skidmore 		*lsc = true;
2403c3dc4c09SDon Skidmore 
2404c3dc4c09SDon Skidmore 	return 0;
2405c3dc4c09SDon Skidmore }
2406c3dc4c09SDon Skidmore 
2407c3dc4c09SDon Skidmore /**
2408c3dc4c09SDon Skidmore  * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts
2409c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2410c3dc4c09SDon Skidmore  *
2411c3dc4c09SDon Skidmore  * Enable link status change and temperature failure alarm for the external
2412c3dc4c09SDon Skidmore  * Base T PHY
2413c3dc4c09SDon Skidmore  *
2414c3dc4c09SDon Skidmore  * Returns PHY access status
2415c3dc4c09SDon Skidmore  **/
ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw * hw)2416c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
2417c3dc4c09SDon Skidmore {
241809943985SJedrzej Jagielski 	bool lsc, overtemp;
2419c3dc4c09SDon Skidmore 	u32 status;
2420c3dc4c09SDon Skidmore 	u16 reg;
2421c3dc4c09SDon Skidmore 
2422c3dc4c09SDon Skidmore 	/* Clear interrupt flags */
242309943985SJedrzej Jagielski 	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, &overtemp);
2424c3dc4c09SDon Skidmore 
2425c3dc4c09SDon Skidmore 	/* Enable link status change alarm */
242672f740b1STony Nguyen 
242772f740b1STony Nguyen 	/* Enable the LASI interrupts on X552 devices to receive notifications
242872f740b1STony Nguyen 	 * of the link configurations of the external PHY and correspondingly
242972f740b1STony Nguyen 	 * support the configuration of the internal iXFI link, since iXFI does
243072f740b1STony Nguyen 	 * not support auto-negotiation. This is not required for X553 devices
243172f740b1STony Nguyen 	 * having KR support, which performs auto-negotiations and which is used
243272f740b1STony Nguyen 	 * as the internal link to the external PHY. Hence adding a check here
243372f740b1STony Nguyen 	 * to avoid enabling LASI interrupts for X553 devices.
243472f740b1STony Nguyen 	 */
243572f740b1STony Nguyen 	if (hw->mac.type != ixgbe_mac_x550em_a) {
243672f740b1STony Nguyen 		status = hw->phy.ops.read_reg(hw,
243772f740b1STony Nguyen 					    IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
24384dc4000bSEmil Tantilov 					    MDIO_MMD_AN, &reg);
2439c3dc4c09SDon Skidmore 		if (status)
2440c3dc4c09SDon Skidmore 			return status;
2441c3dc4c09SDon Skidmore 
2442c3dc4c09SDon Skidmore 		reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
2443c3dc4c09SDon Skidmore 
244472f740b1STony Nguyen 		status = hw->phy.ops.write_reg(hw,
244572f740b1STony Nguyen 					    IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
24464dc4000bSEmil Tantilov 					    MDIO_MMD_AN, reg);
2447c3dc4c09SDon Skidmore 		if (status)
2448c3dc4c09SDon Skidmore 			return status;
244972f740b1STony Nguyen 	}
2450c3dc4c09SDon Skidmore 
245183a9fb20SMark Rustad 	/* Enable high temperature failure and global fault alarms */
2452c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
24534dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2454c3dc4c09SDon Skidmore 				      &reg);
2455c3dc4c09SDon Skidmore 	if (status)
2456c3dc4c09SDon Skidmore 		return status;
2457c3dc4c09SDon Skidmore 
245883a9fb20SMark Rustad 	reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN |
245983a9fb20SMark Rustad 		IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);
2460c3dc4c09SDon Skidmore 
2461c3dc4c09SDon Skidmore 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
24624dc4000bSEmil Tantilov 				       MDIO_MMD_VEND1,
2463c3dc4c09SDon Skidmore 				       reg);
2464c3dc4c09SDon Skidmore 	if (status)
2465c3dc4c09SDon Skidmore 		return status;
2466c3dc4c09SDon Skidmore 
2467c3dc4c09SDon Skidmore 	/* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
2468c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
24694dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2470c3dc4c09SDon Skidmore 				      &reg);
2471c3dc4c09SDon Skidmore 	if (status)
2472c3dc4c09SDon Skidmore 		return status;
2473c3dc4c09SDon Skidmore 
2474c3dc4c09SDon Skidmore 	reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
2475c3dc4c09SDon Skidmore 		IXGBE_MDIO_GLOBAL_ALARM_1_INT);
2476c3dc4c09SDon Skidmore 
2477c3dc4c09SDon Skidmore 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
24784dc4000bSEmil Tantilov 				       MDIO_MMD_VEND1,
2479c3dc4c09SDon Skidmore 				       reg);
2480c3dc4c09SDon Skidmore 	if (status)
2481c3dc4c09SDon Skidmore 		return status;
2482c3dc4c09SDon Skidmore 
2483c3dc4c09SDon Skidmore 	/* Enable chip-wide vendor alarm */
2484c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
24854dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2486c3dc4c09SDon Skidmore 				      &reg);
2487c3dc4c09SDon Skidmore 	if (status)
2488c3dc4c09SDon Skidmore 		return status;
2489c3dc4c09SDon Skidmore 
2490c3dc4c09SDon Skidmore 	reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
2491c3dc4c09SDon Skidmore 
2492c3dc4c09SDon Skidmore 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
24934dc4000bSEmil Tantilov 				       MDIO_MMD_VEND1,
2494c3dc4c09SDon Skidmore 				       reg);
2495c3dc4c09SDon Skidmore 
2496c3dc4c09SDon Skidmore 	return status;
2497c3dc4c09SDon Skidmore }
2498c3dc4c09SDon Skidmore 
2499c3dc4c09SDon Skidmore /**
2500c3dc4c09SDon Skidmore  * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
2501c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
250209943985SJedrzej Jagielski  * @is_overtemp: indicate whether an overtemp event encountered
2503c3dc4c09SDon Skidmore  *
2504c3dc4c09SDon Skidmore  * Handle external Base T PHY interrupt. If high temperature
2505c3dc4c09SDon Skidmore  * failure alarm then return error, else if link status change
2506c3dc4c09SDon Skidmore  * then setup internal/external PHY link
2507c3dc4c09SDon Skidmore  **/
ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw * hw,bool * is_overtemp)250809943985SJedrzej Jagielski static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw,
250909943985SJedrzej Jagielski 					  bool *is_overtemp)
2510c3dc4c09SDon Skidmore {
2511c3dc4c09SDon Skidmore 	struct ixgbe_phy_info *phy = &hw->phy;
2512c3dc4c09SDon Skidmore 	bool lsc;
2513c3dc4c09SDon Skidmore 	u32 status;
2514c3dc4c09SDon Skidmore 
251509943985SJedrzej Jagielski 	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, is_overtemp);
2516c3dc4c09SDon Skidmore 	if (status)
2517c3dc4c09SDon Skidmore 		return status;
2518c3dc4c09SDon Skidmore 
2519a85ce532SMark Rustad 	if (lsc && phy->ops.setup_internal_link)
2520c3dc4c09SDon Skidmore 		return phy->ops.setup_internal_link(hw);
2521c3dc4c09SDon Skidmore 
2522c3dc4c09SDon Skidmore 	return 0;
2523c3dc4c09SDon Skidmore }
2524c3dc4c09SDon Skidmore 
2525c3dc4c09SDon Skidmore /**
2526c3dc4c09SDon Skidmore  * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed.
2527c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2528c3dc4c09SDon Skidmore  * @speed: link speed
2529c3dc4c09SDon Skidmore  *
2530c3dc4c09SDon Skidmore  * Configures the integrated KR PHY.
2531c3dc4c09SDon Skidmore  **/
ixgbe_setup_kr_speed_x550em(struct ixgbe_hw * hw,ixgbe_link_speed speed)2532c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
2533c3dc4c09SDon Skidmore 				       ixgbe_link_speed speed)
2534c3dc4c09SDon Skidmore {
2535c3dc4c09SDon Skidmore 	s32 status;
2536c3dc4c09SDon Skidmore 	u32 reg_val;
2537c3dc4c09SDon Skidmore 
25389a5c27e6SMark Rustad 	status = hw->mac.ops.read_iosf_sb_reg(hw,
2539c3dc4c09SDon Skidmore 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2540c3dc4c09SDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
2541c3dc4c09SDon Skidmore 	if (status)
2542c3dc4c09SDon Skidmore 		return status;
2543c3dc4c09SDon Skidmore 
2544c3dc4c09SDon Skidmore 	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
2545c3dc4c09SDon Skidmore 	reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
2546c3dc4c09SDon Skidmore 		     IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
2547c3dc4c09SDon Skidmore 
2548c3dc4c09SDon Skidmore 	/* Advertise 10G support. */
2549c3dc4c09SDon Skidmore 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
2550c3dc4c09SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR;
2551c3dc4c09SDon Skidmore 
2552c3dc4c09SDon Skidmore 	/* Advertise 1G support. */
2553c3dc4c09SDon Skidmore 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
2554c3dc4c09SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
2555c3dc4c09SDon Skidmore 
25569a5c27e6SMark Rustad 	status = hw->mac.ops.write_iosf_sb_reg(hw,
2557c3dc4c09SDon Skidmore 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2558c3dc4c09SDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2559c3dc4c09SDon Skidmore 
2560470739b5SDon Skidmore 	if (hw->mac.type == ixgbe_mac_x550em_a) {
2561470739b5SDon Skidmore 		/* Set lane mode  to KR auto negotiation */
2562470739b5SDon Skidmore 		status = hw->mac.ops.read_iosf_sb_reg(hw,
2563470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2564470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
2565470739b5SDon Skidmore 
2566470739b5SDon Skidmore 		if (status)
2567c3dc4c09SDon Skidmore 			return status;
2568470739b5SDon Skidmore 
2569470739b5SDon Skidmore 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
2570470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
2571470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
2572470739b5SDon Skidmore 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
2573470739b5SDon Skidmore 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
2574470739b5SDon Skidmore 
2575470739b5SDon Skidmore 		status = hw->mac.ops.write_iosf_sb_reg(hw,
2576470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2577470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2578470739b5SDon Skidmore 	}
2579470739b5SDon Skidmore 
2580470739b5SDon Skidmore 	return ixgbe_restart_an_internal_phy_x550em(hw);
2581c3dc4c09SDon Skidmore }
2582c3dc4c09SDon Skidmore 
2583f572b2c4SMark Rustad /**
2584f572b2c4SMark Rustad  * ixgbe_setup_kr_x550em - Configure the KR PHY
25856a14ee0cSDon Skidmore  * @hw: pointer to hardware structure
25866a14ee0cSDon Skidmore  **/
ixgbe_setup_kr_x550em(struct ixgbe_hw * hw)25877ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
25886a14ee0cSDon Skidmore {
258954f6d4c4SDon Skidmore 	/* leave link alone for 2.5G */
259054f6d4c4SDon Skidmore 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
2591f572b2c4SMark Rustad 		return 0;
2592f572b2c4SMark Rustad 
2593f4a6374bSTony Nguyen 	if (ixgbe_check_reset_blocked(hw))
2594f4a6374bSTony Nguyen 		return 0;
2595f4a6374bSTony Nguyen 
2596c3dc4c09SDon Skidmore 	return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised);
25976a14ee0cSDon Skidmore }
25986a14ee0cSDon Skidmore 
2599c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status
2600c3dc4c09SDon Skidmore  *  @hw: address of hardware structure
2601c3dc4c09SDon Skidmore  *  @link_up: address of boolean to indicate link status
2602c3dc4c09SDon Skidmore  *
2603c3dc4c09SDon Skidmore  *  Returns error code if unable to get link status.
2604c3dc4c09SDon Skidmore  **/
ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw * hw,bool * link_up)2605c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
2606c3dc4c09SDon Skidmore {
2607c3dc4c09SDon Skidmore 	u32 ret;
2608c3dc4c09SDon Skidmore 	u16 autoneg_status;
2609c3dc4c09SDon Skidmore 
2610c3dc4c09SDon Skidmore 	*link_up = false;
2611c3dc4c09SDon Skidmore 
2612c3dc4c09SDon Skidmore 	/* read this twice back to back to indicate current status */
26134dc4000bSEmil Tantilov 	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
2614c3dc4c09SDon Skidmore 				   &autoneg_status);
2615c3dc4c09SDon Skidmore 	if (ret)
2616c3dc4c09SDon Skidmore 		return ret;
2617c3dc4c09SDon Skidmore 
26184dc4000bSEmil Tantilov 	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
2619c3dc4c09SDon Skidmore 				   &autoneg_status);
2620c3dc4c09SDon Skidmore 	if (ret)
2621c3dc4c09SDon Skidmore 		return ret;
2622c3dc4c09SDon Skidmore 
2623c3dc4c09SDon Skidmore 	*link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS);
2624c3dc4c09SDon Skidmore 
2625c3dc4c09SDon Skidmore 	return 0;
2626c3dc4c09SDon Skidmore }
2627c3dc4c09SDon Skidmore 
2628c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link
26296a14ee0cSDon Skidmore  *  @hw: point to hardware structure
26306a14ee0cSDon Skidmore  *
2631c3dc4c09SDon Skidmore  *  Configures the link between the integrated KR PHY and the external X557 PHY
2632c3dc4c09SDon Skidmore  *  The driver will call this function when it gets a link status change
2633c3dc4c09SDon Skidmore  *  interrupt from the X557 PHY. This function configures the link speed
2634c3dc4c09SDon Skidmore  *  between the PHYs to match the link speed of the BASE-T link.
26356a14ee0cSDon Skidmore  *
26366a14ee0cSDon Skidmore  * A return of a non-zero value indicates an error, and the base driver should
26376a14ee0cSDon Skidmore  * not report link up.
26386a14ee0cSDon Skidmore  **/
ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw * hw)2639c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
26406a14ee0cSDon Skidmore {
26416a14ee0cSDon Skidmore 	ixgbe_link_speed force_speed;
2642c3dc4c09SDon Skidmore 	bool link_up;
2643c3dc4c09SDon Skidmore 	u32 status;
2644c3dc4c09SDon Skidmore 	u16 speed;
26456a14ee0cSDon Skidmore 
2646c3dc4c09SDon Skidmore 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
264703c5b6d4SJedrzej Jagielski 		return -EIO;
2648c3dc4c09SDon Skidmore 
264948301cf2STony Nguyen 	if (!(hw->mac.type == ixgbe_mac_X550EM_x &&
265048301cf2STony Nguyen 	      !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))) {
2651f164b845SMark Rustad 		speed = IXGBE_LINK_SPEED_10GB_FULL |
2652f164b845SMark Rustad 			IXGBE_LINK_SPEED_1GB_FULL;
2653f164b845SMark Rustad 		return ixgbe_setup_kr_speed_x550em(hw, speed);
2654f164b845SMark Rustad 	}
2655f164b845SMark Rustad 
2656c3dc4c09SDon Skidmore 	/* If link is not up, then there is no setup necessary so return  */
2657c3dc4c09SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
26586a14ee0cSDon Skidmore 	if (status)
26596a14ee0cSDon Skidmore 		return status;
26606a14ee0cSDon Skidmore 
2661c3dc4c09SDon Skidmore 	if (!link_up)
26626a14ee0cSDon Skidmore 		return 0;
26636a14ee0cSDon Skidmore 
26646a14ee0cSDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
26654dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
26666a14ee0cSDon Skidmore 				      &speed);
2667c3dc4c09SDon Skidmore 	if (status)
2668c3dc4c09SDon Skidmore 		return status;
2669c3dc4c09SDon Skidmore 
2670c3dc4c09SDon Skidmore 	/* If link is not still up, then no setup is necessary so return */
2671c3dc4c09SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
2672c3dc4c09SDon Skidmore 	if (status)
2673c3dc4c09SDon Skidmore 		return status;
2674c3dc4c09SDon Skidmore 
2675c3dc4c09SDon Skidmore 	if (!link_up)
2676c3dc4c09SDon Skidmore 		return 0;
26776a14ee0cSDon Skidmore 
26786a14ee0cSDon Skidmore 	/* clear everything but the speed and duplex bits */
26796a14ee0cSDon Skidmore 	speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
26806a14ee0cSDon Skidmore 
26816a14ee0cSDon Skidmore 	switch (speed) {
26826a14ee0cSDon Skidmore 	case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
26836a14ee0cSDon Skidmore 		force_speed = IXGBE_LINK_SPEED_10GB_FULL;
26846a14ee0cSDon Skidmore 		break;
26856a14ee0cSDon Skidmore 	case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
26866a14ee0cSDon Skidmore 		force_speed = IXGBE_LINK_SPEED_1GB_FULL;
26876a14ee0cSDon Skidmore 		break;
26886a14ee0cSDon Skidmore 	default:
26896a14ee0cSDon Skidmore 		/* Internal PHY does not support anything else */
269003c5b6d4SJedrzej Jagielski 		return -EINVAL;
26916a14ee0cSDon Skidmore 	}
26926a14ee0cSDon Skidmore 
26936a14ee0cSDon Skidmore 	return ixgbe_setup_ixfi_x550em(hw, &force_speed);
26946a14ee0cSDon Skidmore }
26956a14ee0cSDon Skidmore 
2696f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI
2697f4410d2cSDon Skidmore  *  @hw: pointer to hardware structure
2698f4410d2cSDon Skidmore  **/
ixgbe_reset_phy_t_X550em(struct ixgbe_hw * hw)2699f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw)
2700f4410d2cSDon Skidmore {
2701f4410d2cSDon Skidmore 	s32 status;
2702f4410d2cSDon Skidmore 
2703f4410d2cSDon Skidmore 	status = ixgbe_reset_phy_generic(hw);
2704f4410d2cSDon Skidmore 
2705f4410d2cSDon Skidmore 	if (status)
2706f4410d2cSDon Skidmore 		return status;
2707f4410d2cSDon Skidmore 
2708f4410d2cSDon Skidmore 	/* Configure Link Status Alarm and Temperature Threshold interrupts */
2709f4410d2cSDon Skidmore 	return ixgbe_enable_lasi_ext_t_x550em(hw);
2710f4410d2cSDon Skidmore }
2711f4410d2cSDon Skidmore 
2712a0ad55a3SDon Skidmore /**
2713a0ad55a3SDon Skidmore  *  ixgbe_led_on_t_x550em - Turns on the software controllable LEDs.
2714a0ad55a3SDon Skidmore  *  @hw: pointer to hardware structure
2715a0ad55a3SDon Skidmore  *  @led_idx: led number to turn on
2716a0ad55a3SDon Skidmore  **/
ixgbe_led_on_t_x550em(struct ixgbe_hw * hw,u32 led_idx)2717d2d43e5bSEmil Tantilov static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
2718a0ad55a3SDon Skidmore {
2719a0ad55a3SDon Skidmore 	u16 phy_data;
2720a0ad55a3SDon Skidmore 
2721a0ad55a3SDon Skidmore 	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
272203c5b6d4SJedrzej Jagielski 		return -EINVAL;
2723a0ad55a3SDon Skidmore 
2724a0ad55a3SDon Skidmore 	/* To turn on the LED, set mode to ON. */
2725a0ad55a3SDon Skidmore 	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
27264dc4000bSEmil Tantilov 			     MDIO_MMD_VEND1, &phy_data);
2727a0ad55a3SDon Skidmore 	phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;
2728a0ad55a3SDon Skidmore 	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
27294dc4000bSEmil Tantilov 			      MDIO_MMD_VEND1, phy_data);
2730a0ad55a3SDon Skidmore 
2731a0ad55a3SDon Skidmore 	return 0;
2732a0ad55a3SDon Skidmore }
2733a0ad55a3SDon Skidmore 
2734a0ad55a3SDon Skidmore /**
2735a0ad55a3SDon Skidmore  *  ixgbe_led_off_t_x550em - Turns off the software controllable LEDs.
2736a0ad55a3SDon Skidmore  *  @hw: pointer to hardware structure
2737a0ad55a3SDon Skidmore  *  @led_idx: led number to turn off
2738a0ad55a3SDon Skidmore  **/
ixgbe_led_off_t_x550em(struct ixgbe_hw * hw,u32 led_idx)2739d2d43e5bSEmil Tantilov static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
2740a0ad55a3SDon Skidmore {
2741a0ad55a3SDon Skidmore 	u16 phy_data;
2742a0ad55a3SDon Skidmore 
2743a0ad55a3SDon Skidmore 	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
274403c5b6d4SJedrzej Jagielski 		return -EINVAL;
2745a0ad55a3SDon Skidmore 
2746a0ad55a3SDon Skidmore 	/* To turn on the LED, set mode to ON. */
2747a0ad55a3SDon Skidmore 	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
27484dc4000bSEmil Tantilov 			     MDIO_MMD_VEND1, &phy_data);
2749a0ad55a3SDon Skidmore 	phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;
2750a0ad55a3SDon Skidmore 	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
27514dc4000bSEmil Tantilov 			      MDIO_MMD_VEND1, phy_data);
2752a0ad55a3SDon Skidmore 
2753a0ad55a3SDon Skidmore 	return 0;
2754a0ad55a3SDon Skidmore }
2755a0ad55a3SDon Skidmore 
2756cb8e0514STony Nguyen /**
2757cb8e0514STony Nguyen  *  ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware
2758cb8e0514STony Nguyen  *  @hw: pointer to the HW structure
2759cb8e0514STony Nguyen  *  @maj: driver version major number
2760cb8e0514STony Nguyen  *  @min: driver version minor number
2761cb8e0514STony Nguyen  *  @build: driver version build number
2762cb8e0514STony Nguyen  *  @sub: driver version sub build number
2763cb8e0514STony Nguyen  *  @len: length of driver_ver string
2764cb8e0514STony Nguyen  *  @driver_ver: driver string
2765cb8e0514STony Nguyen  *
2766cb8e0514STony Nguyen  *  Sends driver version number to firmware through the manageability
2767cb8e0514STony Nguyen  *  block.  On success return 0
276803c5b6d4SJedrzej Jagielski  *  else returns -EBUSY when encountering an error acquiring
276903c5b6d4SJedrzej Jagielski  *  semaphore, -EIO when command fails or -ENIVAL when incorrect
277003c5b6d4SJedrzej Jagielski  *  params passed.
2771cb8e0514STony Nguyen  **/
ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw * hw,u8 maj,u8 min,u8 build,u8 sub,u16 len,const char * driver_ver)2772cb8e0514STony Nguyen static s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
2773cb8e0514STony Nguyen 				     u8 build, u8 sub, u16 len,
2774cb8e0514STony Nguyen 				     const char *driver_ver)
2775cb8e0514STony Nguyen {
2776cb8e0514STony Nguyen 	struct ixgbe_hic_drv_info2 fw_cmd;
2777cb8e0514STony Nguyen 	s32 ret_val;
2778cb8e0514STony Nguyen 	int i;
2779cb8e0514STony Nguyen 
2780cb8e0514STony Nguyen 	if (!len || !driver_ver || (len > sizeof(fw_cmd.driver_string)))
278103c5b6d4SJedrzej Jagielski 		return -EINVAL;
2782cb8e0514STony Nguyen 
2783cb8e0514STony Nguyen 	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
2784cb8e0514STony Nguyen 	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len;
2785cb8e0514STony Nguyen 	fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
2786cb8e0514STony Nguyen 	fw_cmd.port_num = (u8)hw->bus.func;
2787cb8e0514STony Nguyen 	fw_cmd.ver_maj = maj;
2788cb8e0514STony Nguyen 	fw_cmd.ver_min = min;
2789cb8e0514STony Nguyen 	fw_cmd.ver_build = build;
2790cb8e0514STony Nguyen 	fw_cmd.ver_sub = sub;
2791cb8e0514STony Nguyen 	fw_cmd.hdr.checksum = 0;
2792cb8e0514STony Nguyen 	memcpy(fw_cmd.driver_string, driver_ver, len);
2793cb8e0514STony Nguyen 	fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
2794cb8e0514STony Nguyen 			      (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
2795cb8e0514STony Nguyen 
2796cb8e0514STony Nguyen 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
2797cb8e0514STony Nguyen 		ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
2798cb8e0514STony Nguyen 						       sizeof(fw_cmd),
2799cb8e0514STony Nguyen 						       IXGBE_HI_COMMAND_TIMEOUT,
2800cb8e0514STony Nguyen 						       true);
2801cb8e0514STony Nguyen 		if (ret_val)
2802cb8e0514STony Nguyen 			continue;
2803cb8e0514STony Nguyen 
2804cb8e0514STony Nguyen 		if (fw_cmd.hdr.cmd_or_resp.ret_status !=
2805cb8e0514STony Nguyen 		    FW_CEM_RESP_STATUS_SUCCESS)
280603c5b6d4SJedrzej Jagielski 			return -EIO;
2807cb8e0514STony Nguyen 		return 0;
2808cb8e0514STony Nguyen 	}
2809cb8e0514STony Nguyen 
2810cb8e0514STony Nguyen 	return ret_val;
2811cb8e0514STony Nguyen }
2812cb8e0514STony Nguyen 
28136ac74394SDon Skidmore /** ixgbe_get_lcd_x550em - Determine lowest common denominator
28146ac74394SDon Skidmore  *  @hw: pointer to hardware structure
28156ac74394SDon Skidmore  *  @lcd_speed: pointer to lowest common link speed
28166ac74394SDon Skidmore  *
28176ac74394SDon Skidmore  *  Determine lowest common link speed with link partner.
28186ac74394SDon Skidmore  **/
ixgbe_get_lcd_t_x550em(struct ixgbe_hw * hw,ixgbe_link_speed * lcd_speed)28196ac74394SDon Skidmore static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw,
28206ac74394SDon Skidmore 				  ixgbe_link_speed *lcd_speed)
28216ac74394SDon Skidmore {
28226ac74394SDon Skidmore 	u16 an_lp_status;
28236ac74394SDon Skidmore 	s32 status;
28246ac74394SDon Skidmore 	u16 word = hw->eeprom.ctrl_word_3;
28256ac74394SDon Skidmore 
28266ac74394SDon Skidmore 	*lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
28276ac74394SDon Skidmore 
28286ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
28294dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
28306ac74394SDon Skidmore 				      &an_lp_status);
28316ac74394SDon Skidmore 	if (status)
28326ac74394SDon Skidmore 		return status;
28336ac74394SDon Skidmore 
28346ac74394SDon Skidmore 	/* If link partner advertised 1G, return 1G */
28356ac74394SDon Skidmore 	if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) {
28366ac74394SDon Skidmore 		*lcd_speed = IXGBE_LINK_SPEED_1GB_FULL;
28376ac74394SDon Skidmore 		return status;
28386ac74394SDon Skidmore 	}
28396ac74394SDon Skidmore 
28406ac74394SDon Skidmore 	/* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */
28416ac74394SDon Skidmore 	if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) ||
28426ac74394SDon Skidmore 	    (word & NVM_INIT_CTRL_3_D10GMP_PORT0))
28436ac74394SDon Skidmore 		return status;
28446ac74394SDon Skidmore 
28456ac74394SDon Skidmore 	/* Link partner not capable of lower speeds, return 10G */
28466ac74394SDon Skidmore 	*lcd_speed = IXGBE_LINK_SPEED_10GB_FULL;
28476ac74394SDon Skidmore 	return status;
28486ac74394SDon Skidmore }
28496ac74394SDon Skidmore 
2850afdc71e4SMark Rustad /**
2851afdc71e4SMark Rustad  * ixgbe_setup_fc_x550em - Set up flow control
2852afdc71e4SMark Rustad  * @hw: pointer to hardware structure
2853afdc71e4SMark Rustad  */
ixgbe_setup_fc_x550em(struct ixgbe_hw * hw)2854afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw)
2855afdc71e4SMark Rustad {
2856afdc71e4SMark Rustad 	bool pause, asm_dir;
2857afdc71e4SMark Rustad 	u32 reg_val;
28587adbccbbSTony Nguyen 	s32 rc = 0;
2859afdc71e4SMark Rustad 
2860afdc71e4SMark Rustad 	/* Validate the requested mode */
2861afdc71e4SMark Rustad 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
2862afdc71e4SMark Rustad 		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
286303c5b6d4SJedrzej Jagielski 		return -EINVAL;
2864afdc71e4SMark Rustad 	}
2865afdc71e4SMark Rustad 
2866afdc71e4SMark Rustad 	/* 10gig parts do not have a word in the EEPROM to determine the
2867afdc71e4SMark Rustad 	 * default flow control setting, so we explicitly set it to full.
2868afdc71e4SMark Rustad 	 */
2869afdc71e4SMark Rustad 	if (hw->fc.requested_mode == ixgbe_fc_default)
2870afdc71e4SMark Rustad 		hw->fc.requested_mode = ixgbe_fc_full;
2871afdc71e4SMark Rustad 
2872afdc71e4SMark Rustad 	/* Determine PAUSE and ASM_DIR bits. */
2873afdc71e4SMark Rustad 	switch (hw->fc.requested_mode) {
2874afdc71e4SMark Rustad 	case ixgbe_fc_none:
2875afdc71e4SMark Rustad 		pause = false;
2876afdc71e4SMark Rustad 		asm_dir = false;
2877afdc71e4SMark Rustad 		break;
2878afdc71e4SMark Rustad 	case ixgbe_fc_tx_pause:
2879afdc71e4SMark Rustad 		pause = false;
2880afdc71e4SMark Rustad 		asm_dir = true;
2881afdc71e4SMark Rustad 		break;
2882afdc71e4SMark Rustad 	case ixgbe_fc_rx_pause:
2883afdc71e4SMark Rustad 		/* Rx Flow control is enabled and Tx Flow control is
2884afdc71e4SMark Rustad 		 * disabled by software override. Since there really
2885afdc71e4SMark Rustad 		 * isn't a way to advertise that we are capable of RX
2886afdc71e4SMark Rustad 		 * Pause ONLY, we will advertise that we support both
2887afdc71e4SMark Rustad 		 * symmetric and asymmetric Rx PAUSE, as such we fall
2888afdc71e4SMark Rustad 		 * through to the fc_full statement.  Later, we will
2889afdc71e4SMark Rustad 		 * disable the adapter's ability to send PAUSE frames.
2890afdc71e4SMark Rustad 		 */
28915463fce6SJeff Kirsher 		fallthrough;
2892afdc71e4SMark Rustad 	case ixgbe_fc_full:
2893afdc71e4SMark Rustad 		pause = true;
2894afdc71e4SMark Rustad 		asm_dir = true;
2895afdc71e4SMark Rustad 		break;
2896afdc71e4SMark Rustad 	default:
2897afdc71e4SMark Rustad 		hw_err(hw, "Flow control param set incorrectly\n");
289803c5b6d4SJedrzej Jagielski 		return -EIO;
2899afdc71e4SMark Rustad 	}
2900afdc71e4SMark Rustad 
29017adbccbbSTony Nguyen 	switch (hw->device_id) {
29027adbccbbSTony Nguyen 	case IXGBE_DEV_ID_X550EM_X_KR:
29037adbccbbSTony Nguyen 	case IXGBE_DEV_ID_X550EM_A_KR:
29047adbccbbSTony Nguyen 	case IXGBE_DEV_ID_X550EM_A_KR_L:
29059a5c27e6SMark Rustad 		rc = hw->mac.ops.read_iosf_sb_reg(hw,
2906afdc71e4SMark Rustad 					    IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
29079a5c27e6SMark Rustad 					    IXGBE_SB_IOSF_TARGET_KR_PHY,
29089a5c27e6SMark Rustad 					    &reg_val);
2909afdc71e4SMark Rustad 		if (rc)
2910afdc71e4SMark Rustad 			return rc;
2911afdc71e4SMark Rustad 
2912afdc71e4SMark Rustad 		reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
2913afdc71e4SMark Rustad 			     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
2914afdc71e4SMark Rustad 		if (pause)
2915afdc71e4SMark Rustad 			reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
2916afdc71e4SMark Rustad 		if (asm_dir)
2917afdc71e4SMark Rustad 			reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
29189a5c27e6SMark Rustad 		rc = hw->mac.ops.write_iosf_sb_reg(hw,
2919afdc71e4SMark Rustad 					    IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
29209a5c27e6SMark Rustad 					    IXGBE_SB_IOSF_TARGET_KR_PHY,
29219a5c27e6SMark Rustad 					    reg_val);
2922afdc71e4SMark Rustad 
2923afdc71e4SMark Rustad 		/* This device does not fully support AN. */
2924afdc71e4SMark Rustad 		hw->fc.disable_fc_autoneg = true;
29257adbccbbSTony Nguyen 		break;
29267adbccbbSTony Nguyen 	case IXGBE_DEV_ID_X550EM_X_XFI:
29277adbccbbSTony Nguyen 		hw->fc.disable_fc_autoneg = true;
29287adbccbbSTony Nguyen 		break;
29297adbccbbSTony Nguyen 	default:
29307adbccbbSTony Nguyen 		break;
29317adbccbbSTony Nguyen 	}
2932afdc71e4SMark Rustad 	return rc;
2933afdc71e4SMark Rustad }
2934afdc71e4SMark Rustad 
29352916500dSDon Skidmore /**
29362916500dSDon Skidmore  *  ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37
29372916500dSDon Skidmore  *  @hw: pointer to hardware structure
29382916500dSDon Skidmore  **/
ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw * hw)29392916500dSDon Skidmore static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
29402916500dSDon Skidmore {
29412916500dSDon Skidmore 	u32 link_s1, lp_an_page_low, an_cntl_1;
29422916500dSDon Skidmore 	ixgbe_link_speed speed;
294303c5b6d4SJedrzej Jagielski 	s32 status = -EIO;
29442916500dSDon Skidmore 	bool link_up;
29452916500dSDon Skidmore 
29462916500dSDon Skidmore 	/* AN should have completed when the cable was plugged in.
29472916500dSDon Skidmore 	 * Look for reasons to bail out.  Bail out if:
29482916500dSDon Skidmore 	 * - FC autoneg is disabled, or if
29492916500dSDon Skidmore 	 * - link is not up.
29502916500dSDon Skidmore 	 */
29512916500dSDon Skidmore 	if (hw->fc.disable_fc_autoneg) {
29522916500dSDon Skidmore 		hw_err(hw, "Flow control autoneg is disabled");
29532916500dSDon Skidmore 		goto out;
29542916500dSDon Skidmore 	}
29552916500dSDon Skidmore 
29562916500dSDon Skidmore 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
29572916500dSDon Skidmore 	if (!link_up) {
29582916500dSDon Skidmore 		hw_err(hw, "The link is down");
29592916500dSDon Skidmore 		goto out;
29602916500dSDon Skidmore 	}
29612916500dSDon Skidmore 
29622916500dSDon Skidmore 	/* Check at auto-negotiation has completed */
29632916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
29642916500dSDon Skidmore 					IXGBE_KRM_LINK_S1(hw->bus.lan_id),
29652916500dSDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1);
29662916500dSDon Skidmore 
29672916500dSDon Skidmore 	if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
29682916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
296903c5b6d4SJedrzej Jagielski 		status = -EIO;
29702916500dSDon Skidmore 		goto out;
29712916500dSDon Skidmore 	}
29722916500dSDon Skidmore 
29732916500dSDon Skidmore 	/* Read the 10g AN autoc and LP ability registers and resolve
29742916500dSDon Skidmore 	 * local flow control settings accordingly
29752916500dSDon Skidmore 	 */
29762916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
29772916500dSDon Skidmore 				IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
29782916500dSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1);
29792916500dSDon Skidmore 
29802916500dSDon Skidmore 	if (status) {
29812916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
29822916500dSDon Skidmore 		goto out;
29832916500dSDon Skidmore 	}
29842916500dSDon Skidmore 
29852916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
29862916500dSDon Skidmore 				IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id),
29872916500dSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low);
29882916500dSDon Skidmore 
29892916500dSDon Skidmore 	if (status) {
29902916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
29912916500dSDon Skidmore 		goto out;
29922916500dSDon Skidmore 	}
29932916500dSDon Skidmore 
29942916500dSDon Skidmore 	status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low,
29952916500dSDon Skidmore 				    IXGBE_KRM_AN_CNTL_1_SYM_PAUSE,
29962916500dSDon Skidmore 				    IXGBE_KRM_AN_CNTL_1_ASM_PAUSE,
29972916500dSDon Skidmore 				    IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE,
29982916500dSDon Skidmore 				    IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE);
29992916500dSDon Skidmore 
30002916500dSDon Skidmore out:
30012916500dSDon Skidmore 	if (!status) {
30022916500dSDon Skidmore 		hw->fc.fc_was_autonegged = true;
30032916500dSDon Skidmore 	} else {
30042916500dSDon Skidmore 		hw->fc.fc_was_autonegged = false;
30052916500dSDon Skidmore 		hw->fc.current_mode = hw->fc.requested_mode;
30062916500dSDon Skidmore 	}
30072916500dSDon Skidmore }
30082916500dSDon Skidmore 
30092916500dSDon Skidmore /**
30102916500dSDon Skidmore  *  ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings
30112916500dSDon Skidmore  *  @hw: pointer to hardware structure
30122916500dSDon Skidmore  **/
ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw * hw)30132916500dSDon Skidmore static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw)
30142916500dSDon Skidmore {
30152916500dSDon Skidmore 	hw->fc.fc_was_autonegged = false;
30162916500dSDon Skidmore 	hw->fc.current_mode = hw->fc.requested_mode;
30172916500dSDon Skidmore }
30182916500dSDon Skidmore 
30196ac74394SDon Skidmore /** ixgbe_enter_lplu_x550em - Transition to low power states
30206ac74394SDon Skidmore  *  @hw: pointer to hardware structure
30216ac74394SDon Skidmore  *
30226ac74394SDon Skidmore  *  Configures Low Power Link Up on transition to low power states
30236ac74394SDon Skidmore  *  (from D0 to non-D0). Link is required to enter LPLU so avoid resetting
30246ac74394SDon Skidmore  *  the X557 PHY immediately prior to entering LPLU.
30256ac74394SDon Skidmore  **/
ixgbe_enter_lplu_t_x550em(struct ixgbe_hw * hw)30266ac74394SDon Skidmore static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
30276ac74394SDon Skidmore {
30286ac74394SDon Skidmore 	u16 an_10g_cntl_reg, autoneg_reg, speed;
30296ac74394SDon Skidmore 	s32 status;
30306ac74394SDon Skidmore 	ixgbe_link_speed lcd_speed;
30316ac74394SDon Skidmore 	u32 save_autoneg;
30326ac74394SDon Skidmore 	bool link_up;
30336ac74394SDon Skidmore 
30346ac74394SDon Skidmore 	/* If blocked by MNG FW, then don't restart AN */
30356ac74394SDon Skidmore 	if (ixgbe_check_reset_blocked(hw))
30366ac74394SDon Skidmore 		return 0;
30376ac74394SDon Skidmore 
30386ac74394SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
30396ac74394SDon Skidmore 	if (status)
30406ac74394SDon Skidmore 		return status;
30416ac74394SDon Skidmore 
30426ac74394SDon Skidmore 	status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3,
30436ac74394SDon Skidmore 				     &hw->eeprom.ctrl_word_3);
30446ac74394SDon Skidmore 	if (status)
30456ac74394SDon Skidmore 		return status;
30466ac74394SDon Skidmore 
30476ac74394SDon Skidmore 	/* If link is down, LPLU disabled in NVM, WoL disabled, or
30486ac74394SDon Skidmore 	 * manageability disabled, then force link down by entering
30496ac74394SDon Skidmore 	 * low power mode.
30506ac74394SDon Skidmore 	 */
30516ac74394SDon Skidmore 	if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
30526ac74394SDon Skidmore 	    !(hw->wol_enabled || ixgbe_mng_present(hw)))
30536ac74394SDon Skidmore 		return ixgbe_set_copper_phy_power(hw, false);
30546ac74394SDon Skidmore 
30556ac74394SDon Skidmore 	/* Determine LCD */
30566ac74394SDon Skidmore 	status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed);
30576ac74394SDon Skidmore 	if (status)
30586ac74394SDon Skidmore 		return status;
30596ac74394SDon Skidmore 
30606ac74394SDon Skidmore 	/* If no valid LCD link speed, then force link down and exit. */
30616ac74394SDon Skidmore 	if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN)
30626ac74394SDon Skidmore 		return ixgbe_set_copper_phy_power(hw, false);
30636ac74394SDon Skidmore 
30646ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
30654dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
30666ac74394SDon Skidmore 				      &speed);
30676ac74394SDon Skidmore 	if (status)
30686ac74394SDon Skidmore 		return status;
30696ac74394SDon Skidmore 
30706ac74394SDon Skidmore 	/* If no link now, speed is invalid so take link down */
30716ac74394SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
30726ac74394SDon Skidmore 	if (status)
30736ac74394SDon Skidmore 		return ixgbe_set_copper_phy_power(hw, false);
30746ac74394SDon Skidmore 
30756ac74394SDon Skidmore 	/* clear everything but the speed bits */
30766ac74394SDon Skidmore 	speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK;
30776ac74394SDon Skidmore 
30786ac74394SDon Skidmore 	/* If current speed is already LCD, then exit. */
30796ac74394SDon Skidmore 	if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) &&
30806ac74394SDon Skidmore 	     (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) ||
30816ac74394SDon Skidmore 	    ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) &&
30826ac74394SDon Skidmore 	     (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL)))
30836ac74394SDon Skidmore 		return status;
30846ac74394SDon Skidmore 
30856ac74394SDon Skidmore 	/* Clear AN completed indication */
30866ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
30874dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
30886ac74394SDon Skidmore 				      &autoneg_reg);
30896ac74394SDon Skidmore 	if (status)
30906ac74394SDon Skidmore 		return status;
30916ac74394SDon Skidmore 
30924dc4000bSEmil Tantilov 	status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
30934dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
30946ac74394SDon Skidmore 				      &an_10g_cntl_reg);
30956ac74394SDon Skidmore 	if (status)
30966ac74394SDon Skidmore 		return status;
30976ac74394SDon Skidmore 
30986ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw,
30996ac74394SDon Skidmore 				      IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
31004dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
31016ac74394SDon Skidmore 				      &autoneg_reg);
31026ac74394SDon Skidmore 	if (status)
31036ac74394SDon Skidmore 		return status;
31046ac74394SDon Skidmore 
31056ac74394SDon Skidmore 	save_autoneg = hw->phy.autoneg_advertised;
31066ac74394SDon Skidmore 
31076ac74394SDon Skidmore 	/* Setup link at least common link speed */
31086ac74394SDon Skidmore 	status = hw->mac.ops.setup_link(hw, lcd_speed, false);
31096ac74394SDon Skidmore 
31106ac74394SDon Skidmore 	/* restore autoneg from before setting lplu speed */
31116ac74394SDon Skidmore 	hw->phy.autoneg_advertised = save_autoneg;
31126ac74394SDon Skidmore 
31136ac74394SDon Skidmore 	return status;
31146ac74394SDon Skidmore }
31156ac74394SDon Skidmore 
3116537cc5dfSMark Rustad /**
3117b3eb4e18SMark Rustad  * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs
3118b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
3119b3eb4e18SMark Rustad  */
ixgbe_reset_phy_fw(struct ixgbe_hw * hw)3120b3eb4e18SMark Rustad static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw)
3121b3eb4e18SMark Rustad {
3122b3eb4e18SMark Rustad 	u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
3123b3eb4e18SMark Rustad 	s32 rc;
3124b3eb4e18SMark Rustad 
3125b3eb4e18SMark Rustad 	if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
3126b3eb4e18SMark Rustad 		return 0;
3127b3eb4e18SMark Rustad 
3128b3eb4e18SMark Rustad 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store);
3129b3eb4e18SMark Rustad 	if (rc)
3130b3eb4e18SMark Rustad 		return rc;
3131b3eb4e18SMark Rustad 	memset(store, 0, sizeof(store));
3132b3eb4e18SMark Rustad 
3133b3eb4e18SMark Rustad 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store);
3134b3eb4e18SMark Rustad 	if (rc)
3135b3eb4e18SMark Rustad 		return rc;
3136b3eb4e18SMark Rustad 
3137b3eb4e18SMark Rustad 	return ixgbe_setup_fw_link(hw);
3138b3eb4e18SMark Rustad }
3139b3eb4e18SMark Rustad 
3140b3eb4e18SMark Rustad /**
3141b3eb4e18SMark Rustad  * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp
3142b3eb4e18SMark Rustad  * @hw: pointer to hardware structure
314309943985SJedrzej Jagielski  *
314409943985SJedrzej Jagielski  * Return true when an overtemp event detected, otherwise false.
3145b3eb4e18SMark Rustad  */
ixgbe_check_overtemp_fw(struct ixgbe_hw * hw)314609943985SJedrzej Jagielski static bool ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
3147b3eb4e18SMark Rustad {
3148b3eb4e18SMark Rustad 	u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
3149b3eb4e18SMark Rustad 	s32 rc;
3150b3eb4e18SMark Rustad 
3151b3eb4e18SMark Rustad 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);
3152b3eb4e18SMark Rustad 	if (rc)
315309943985SJedrzej Jagielski 		return false;
3154b3eb4e18SMark Rustad 
3155b3eb4e18SMark Rustad 	if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {
3156b3eb4e18SMark Rustad 		ixgbe_shutdown_fw_phy(hw);
315709943985SJedrzej Jagielski 		return true;
3158b3eb4e18SMark Rustad 	}
315909943985SJedrzej Jagielski 	return false;
3160b3eb4e18SMark Rustad }
3161b3eb4e18SMark Rustad 
3162b3eb4e18SMark Rustad /**
3163537cc5dfSMark Rustad  * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register
3164537cc5dfSMark Rustad  * @hw: pointer to hardware structure
3165537cc5dfSMark Rustad  *
3166537cc5dfSMark Rustad  * Read NW_MNG_IF_SEL register and save field values.
3167537cc5dfSMark Rustad  */
ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw * hw)3168537cc5dfSMark Rustad static void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw)
3169537cc5dfSMark Rustad {
3170537cc5dfSMark Rustad 	/* Save NW management interface connected on board. This is used
3171537cc5dfSMark Rustad 	 * to determine internal PHY mode.
3172537cc5dfSMark Rustad 	 */
3173537cc5dfSMark Rustad 	hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
3174537cc5dfSMark Rustad 
3175537cc5dfSMark Rustad 	/* If X552 (X550EM_a) and MDIO is connected to external PHY, then set
3176537cc5dfSMark Rustad 	 * PHY address. This register field was has only been used for X552.
3177537cc5dfSMark Rustad 	 */
3178ae3cb8cbSMark Rustad 	if (hw->mac.type == ixgbe_mac_x550em_a &&
3179ae3cb8cbSMark Rustad 	    hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) {
3180d5752c7bSJesse Brandeburg 		hw->phy.mdio.prtad = FIELD_GET(IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD,
3181d5752c7bSJesse Brandeburg 					       hw->phy.nw_mng_if_sel);
3182537cc5dfSMark Rustad 	}
3183ae3cb8cbSMark Rustad }
3184537cc5dfSMark Rustad 
31856a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init
31866a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
31876a14ee0cSDon Skidmore  *
31886a14ee0cSDon Skidmore  *  Initialize any function pointers that were not able to be
31896a14ee0cSDon Skidmore  *  set during init_shared_code because the PHY/SFP type was
31906a14ee0cSDon Skidmore  *  not known.  Perform the SFP init if necessary.
31916a14ee0cSDon Skidmore  **/
ixgbe_init_phy_ops_X550em(struct ixgbe_hw * hw)31927ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
31936a14ee0cSDon Skidmore {
31946a14ee0cSDon Skidmore 	struct ixgbe_phy_info *phy = &hw->phy;
31956a14ee0cSDon Skidmore 	s32 ret_val;
31966a14ee0cSDon Skidmore 
31977e49d616SDon Skidmore 	hw->mac.ops.set_lan_id(hw);
31987e49d616SDon Skidmore 
3199537cc5dfSMark Rustad 	ixgbe_read_mng_if_sel_x550em(hw);
3200537cc5dfSMark Rustad 
3201c3dc4c09SDon Skidmore 	if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) {
32026a14ee0cSDon Skidmore 		phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
3203ab5fe0c5SDon Skidmore 		ixgbe_setup_mux_ctl(hw);
32046a14ee0cSDon Skidmore 	}
32056a14ee0cSDon Skidmore 
32066a14ee0cSDon Skidmore 	/* Identify the PHY or SFP module */
32076a14ee0cSDon Skidmore 	ret_val = phy->ops.identify(hw);
320803c5b6d4SJedrzej Jagielski 	if (ret_val == -EOPNOTSUPP || ret_val == -EFAULT)
3209c69be946SEmil Tantilov 		return ret_val;
32106a14ee0cSDon Skidmore 
3211c3dc4c09SDon Skidmore 	/* Setup function pointers based on detected hardware */
32126a14ee0cSDon Skidmore 	ixgbe_init_mac_link_ops_X550em(hw);
32136a14ee0cSDon Skidmore 	if (phy->sfp_type != ixgbe_sfp_type_unknown)
32146a14ee0cSDon Skidmore 		phy->ops.reset = NULL;
32156a14ee0cSDon Skidmore 
32166a14ee0cSDon Skidmore 	/* Set functions pointers based on phy type */
32176a14ee0cSDon Skidmore 	switch (hw->phy.type) {
32186a14ee0cSDon Skidmore 	case ixgbe_phy_x550em_kx4:
32195fbf5addSTony Nguyen 		phy->ops.setup_link = NULL;
32206a14ee0cSDon Skidmore 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
32216a14ee0cSDon Skidmore 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
32226a14ee0cSDon Skidmore 		break;
32236a14ee0cSDon Skidmore 	case ixgbe_phy_x550em_kr:
32246a14ee0cSDon Skidmore 		phy->ops.setup_link = ixgbe_setup_kr_x550em;
32256a14ee0cSDon Skidmore 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
32266a14ee0cSDon Skidmore 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
32276a14ee0cSDon Skidmore 		break;
322818e01ee7SDon Skidmore 	case ixgbe_phy_x550em_xfi:
322918e01ee7SDon Skidmore 		/* link is managed by HW */
323018e01ee7SDon Skidmore 		phy->ops.setup_link = NULL;
323118e01ee7SDon Skidmore 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
323218e01ee7SDon Skidmore 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
323318e01ee7SDon Skidmore 		break;
32346a14ee0cSDon Skidmore 	case ixgbe_phy_x550em_ext_t:
3235c3dc4c09SDon Skidmore 		/* Save NW management interface connected on board. This is used
3236c3dc4c09SDon Skidmore 		 * to determine internal PHY mode
3237c3dc4c09SDon Skidmore 		 */
3238c3dc4c09SDon Skidmore 		phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
3239c3dc4c09SDon Skidmore 
3240c3dc4c09SDon Skidmore 		/* If internal link mode is XFI, then setup iXFI internal link,
3241c3dc4c09SDon Skidmore 		 * else setup KR now.
3242c3dc4c09SDon Skidmore 		 */
3243c3dc4c09SDon Skidmore 		phy->ops.setup_internal_link =
3244c3dc4c09SDon Skidmore 					      ixgbe_setup_internal_phy_t_x550em;
3245c3dc4c09SDon Skidmore 
32466ac74394SDon Skidmore 		/* setup SW LPLU only for first revision */
32473ca2b250SMark Rustad 		if (hw->mac.type == ixgbe_mac_X550EM_x &&
32483ca2b250SMark Rustad 		    !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) &
32493ca2b250SMark Rustad 		      IXGBE_FUSES0_REV_MASK))
32506ac74394SDon Skidmore 			phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
32516ac74394SDon Skidmore 
3252c3dc4c09SDon Skidmore 		phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
3253f4410d2cSDon Skidmore 		phy->ops.reset = ixgbe_reset_phy_t_X550em;
32546a14ee0cSDon Skidmore 		break;
325518bda0d9SDon Skidmore 	case ixgbe_phy_sgmii:
325618bda0d9SDon Skidmore 		phy->ops.setup_link = NULL;
325718bda0d9SDon Skidmore 		break;
3258b3eb4e18SMark Rustad 	case ixgbe_phy_fw:
3259b3eb4e18SMark Rustad 		phy->ops.setup_link = ixgbe_setup_fw_link;
3260b3eb4e18SMark Rustad 		phy->ops.reset = ixgbe_reset_phy_fw;
3261b3eb4e18SMark Rustad 		break;
32628dc963e1SPaul Greenwalt 	case ixgbe_phy_ext_1g_t:
32638dc963e1SPaul Greenwalt 		phy->ops.setup_link = NULL;
32648dc963e1SPaul Greenwalt 		phy->ops.read_reg = NULL;
32658dc963e1SPaul Greenwalt 		phy->ops.write_reg = NULL;
32665e999fb4SPaul Greenwalt 		phy->ops.reset = NULL;
32678dc963e1SPaul Greenwalt 		break;
32686a14ee0cSDon Skidmore 	default:
32696a14ee0cSDon Skidmore 		break;
32706a14ee0cSDon Skidmore 	}
3271c3dc4c09SDon Skidmore 
32726a14ee0cSDon Skidmore 	return ret_val;
32736a14ee0cSDon Skidmore }
32746a14ee0cSDon Skidmore 
32756a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type
32766a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
32776a14ee0cSDon Skidmore  *
32786a14ee0cSDon Skidmore  *  Returns the media type (fiber, copper, backplane)
32796a14ee0cSDon Skidmore  *
32806a14ee0cSDon Skidmore  */
ixgbe_get_media_type_X550em(struct ixgbe_hw * hw)32817ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
32826a14ee0cSDon Skidmore {
32836a14ee0cSDon Skidmore 	enum ixgbe_media_type media_type;
32846a14ee0cSDon Skidmore 
32856a14ee0cSDon Skidmore 	/* Detect if there is a copper PHY attached. */
32866a14ee0cSDon Skidmore 	switch (hw->device_id) {
3287200157c2SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SGMII:
3288200157c2SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SGMII_L:
3289200157c2SMark Rustad 		hw->phy.type = ixgbe_phy_sgmii;
32905463fce6SJeff Kirsher 		fallthrough;
32916a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_KR:
32926a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_KX4:
329318e01ee7SDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_XFI:
3294f572b2c4SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_KR:
3295f572b2c4SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_KR_L:
32966a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_backplane;
32976a14ee0cSDon Skidmore 		break;
32986a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_SFP:
32992d40cd17SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP:
330049425dfcSMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP_N:
33016a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_fiber;
33026a14ee0cSDon Skidmore 		break;
33036a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_1G_T:
33046a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_10G_T:
330592ed8430SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_10G_T:
3306b3eb4e18SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_1G_T:
3307b3eb4e18SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
33086a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_copper;
33096a14ee0cSDon Skidmore 		break;
33106a14ee0cSDon Skidmore 	default:
33116a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_unknown;
33126a14ee0cSDon Skidmore 		break;
33136a14ee0cSDon Skidmore 	}
33146a14ee0cSDon Skidmore 	return media_type;
33156a14ee0cSDon Skidmore }
33166a14ee0cSDon Skidmore 
33176a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY.
33186a14ee0cSDon Skidmore  ** @hw: pointer to hardware structure
33196a14ee0cSDon Skidmore  **/
ixgbe_init_ext_t_x550em(struct ixgbe_hw * hw)33207ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
33216a14ee0cSDon Skidmore {
3322a1e869deSMark Rustad 	s32 status;
33236a14ee0cSDon Skidmore 	u16 reg;
33246a14ee0cSDon Skidmore 
33256a14ee0cSDon Skidmore 	status = hw->phy.ops.read_reg(hw,
33266a14ee0cSDon Skidmore 				      IXGBE_MDIO_TX_VENDOR_ALARMS_3,
33274dc4000bSEmil Tantilov 				      MDIO_MMD_PMAPMD,
33286a14ee0cSDon Skidmore 				      &reg);
33296a14ee0cSDon Skidmore 	if (status)
33306a14ee0cSDon Skidmore 		return status;
33316a14ee0cSDon Skidmore 
3332e2261bccSDon Skidmore 	/* If PHY FW reset completed bit is set then this is the first
3333e2261bccSDon Skidmore 	 * SW instance after a power on so the PHY FW must be un-stalled.
3334e2261bccSDon Skidmore 	 */
3335e2261bccSDon Skidmore 	if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
33366a14ee0cSDon Skidmore 		status = hw->phy.ops.read_reg(hw,
33376a14ee0cSDon Skidmore 					IXGBE_MDIO_GLOBAL_RES_PR_10,
33384dc4000bSEmil Tantilov 					MDIO_MMD_VEND1,
33396a14ee0cSDon Skidmore 					&reg);
33406a14ee0cSDon Skidmore 		if (status)
33416a14ee0cSDon Skidmore 			return status;
33426a14ee0cSDon Skidmore 
33436a14ee0cSDon Skidmore 		reg &= ~IXGBE_MDIO_POWER_UP_STALL;
33446a14ee0cSDon Skidmore 
33456a14ee0cSDon Skidmore 		status = hw->phy.ops.write_reg(hw,
33466a14ee0cSDon Skidmore 					IXGBE_MDIO_GLOBAL_RES_PR_10,
33474dc4000bSEmil Tantilov 					MDIO_MMD_VEND1,
33486a14ee0cSDon Skidmore 					reg);
3349e2261bccSDon Skidmore 		if (status)
3350e2261bccSDon Skidmore 			return status;
3351e2261bccSDon Skidmore 	}
3352e2261bccSDon Skidmore 
33536a14ee0cSDon Skidmore 	return status;
33546a14ee0cSDon Skidmore }
33556a14ee0cSDon Skidmore 
3356e84db727SMark Rustad /**
3357e84db727SMark Rustad  * ixgbe_set_mdio_speed - Set MDIO clock speed
3358e84db727SMark Rustad  * @hw: pointer to hardware structure
3359e84db727SMark Rustad  */
ixgbe_set_mdio_speed(struct ixgbe_hw * hw)3360e84db727SMark Rustad static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw)
3361e84db727SMark Rustad {
3362e84db727SMark Rustad 	u32 hlreg0;
3363e84db727SMark Rustad 
3364e84db727SMark Rustad 	switch (hw->device_id) {
3365e84db727SMark Rustad 	case IXGBE_DEV_ID_X550EM_X_10G_T:
3366a83c27e7SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_SGMII:
3367a83c27e7SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_SGMII_L:
336892ed8430SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_10G_T:
33692d40cd17SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP:
3370e84db727SMark Rustad 		/* Config MDIO clock speed before the first MDIO PHY access */
3371e84db727SMark Rustad 		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
3372e84db727SMark Rustad 		hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
3373e84db727SMark Rustad 		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
3374e84db727SMark Rustad 		break;
3375b3eb4e18SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_1G_T:
3376b3eb4e18SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
3377b3eb4e18SMark Rustad 		/* Select fast MDIO clock speed for these devices */
3378b3eb4e18SMark Rustad 		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
3379b3eb4e18SMark Rustad 		hlreg0 |= IXGBE_HLREG0_MDCSPD;
3380b3eb4e18SMark Rustad 		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
3381b3eb4e18SMark Rustad 		break;
3382e84db727SMark Rustad 	default:
3383e84db727SMark Rustad 		break;
3384e84db727SMark Rustad 	}
3385e84db727SMark Rustad }
3386e84db727SMark Rustad 
33876a14ee0cSDon Skidmore /**  ixgbe_reset_hw_X550em - Perform hardware reset
33886a14ee0cSDon Skidmore  **  @hw: pointer to hardware structure
33896a14ee0cSDon Skidmore  **
33906a14ee0cSDon Skidmore  **  Resets the hardware by resetting the transmit and receive units, masks
33916a14ee0cSDon Skidmore  **  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
33926a14ee0cSDon Skidmore  **  reset.
33936a14ee0cSDon Skidmore  **/
ixgbe_reset_hw_X550em(struct ixgbe_hw * hw)33947ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
33956a14ee0cSDon Skidmore {
33966a14ee0cSDon Skidmore 	ixgbe_link_speed link_speed;
33976a14ee0cSDon Skidmore 	s32 status;
33986a14ee0cSDon Skidmore 	u32 ctrl = 0;
33996a14ee0cSDon Skidmore 	u32 i;
34006a14ee0cSDon Skidmore 	bool link_up = false;
34016133406bSPaul Greenwalt 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
34026a14ee0cSDon Skidmore 
34036a14ee0cSDon Skidmore 	/* Call adapter stop to disable Tx/Rx and clear interrupts */
34046a14ee0cSDon Skidmore 	status = hw->mac.ops.stop_adapter(hw);
34056a14ee0cSDon Skidmore 	if (status)
34066a14ee0cSDon Skidmore 		return status;
34076a14ee0cSDon Skidmore 
34086a14ee0cSDon Skidmore 	/* flush pending Tx transactions */
34096a14ee0cSDon Skidmore 	ixgbe_clear_tx_pending(hw);
34106a14ee0cSDon Skidmore 
3411bf0a3750SCyril Novikov 	/* set MDIO speed before talking to the PHY in case it's the 1st time */
3412bf0a3750SCyril Novikov 	ixgbe_set_mdio_speed(hw);
3413bf0a3750SCyril Novikov 
34146a14ee0cSDon Skidmore 	/* PHY ops must be identified and initialized prior to reset */
34156a14ee0cSDon Skidmore 	status = hw->phy.ops.init(hw);
341603c5b6d4SJedrzej Jagielski 	if (status == -EOPNOTSUPP || status == -EFAULT)
3417c69be946SEmil Tantilov 		return status;
34186a14ee0cSDon Skidmore 
34196a14ee0cSDon Skidmore 	/* start the external PHY */
34206a14ee0cSDon Skidmore 	if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
34216a14ee0cSDon Skidmore 		status = ixgbe_init_ext_t_x550em(hw);
34226a14ee0cSDon Skidmore 		if (status)
34236a14ee0cSDon Skidmore 			return status;
34246a14ee0cSDon Skidmore 	}
34256a14ee0cSDon Skidmore 
34266a14ee0cSDon Skidmore 	/* Setup SFP module if there is one present. */
34276a14ee0cSDon Skidmore 	if (hw->phy.sfp_setup_needed) {
34286a14ee0cSDon Skidmore 		status = hw->mac.ops.setup_sfp(hw);
34296a14ee0cSDon Skidmore 		hw->phy.sfp_setup_needed = false;
34306a14ee0cSDon Skidmore 	}
34316a14ee0cSDon Skidmore 
343203c5b6d4SJedrzej Jagielski 	if (status == -EOPNOTSUPP)
3433bbb27076SEmil Tantilov 		return status;
3434bbb27076SEmil Tantilov 
34356a14ee0cSDon Skidmore 	/* Reset PHY */
34366a14ee0cSDon Skidmore 	if (!hw->phy.reset_disable && hw->phy.ops.reset)
34376a14ee0cSDon Skidmore 		hw->phy.ops.reset(hw);
34386a14ee0cSDon Skidmore 
34396a14ee0cSDon Skidmore mac_reset_top:
34406a14ee0cSDon Skidmore 	/* Issue global reset to the MAC.  Needs to be SW reset if link is up.
34416a14ee0cSDon Skidmore 	 * If link reset is used when link is up, it might reset the PHY when
34426a14ee0cSDon Skidmore 	 * mng is using it.  If link is down or the flag to force full link
34436a14ee0cSDon Skidmore 	 * reset is set, then perform link reset.
34446a14ee0cSDon Skidmore 	 */
34456a14ee0cSDon Skidmore 	ctrl = IXGBE_CTRL_LNK_RST;
34466a14ee0cSDon Skidmore 
34476a14ee0cSDon Skidmore 	if (!hw->force_full_reset) {
34486a14ee0cSDon Skidmore 		hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
34496a14ee0cSDon Skidmore 		if (link_up)
34506a14ee0cSDon Skidmore 			ctrl = IXGBE_CTRL_RST;
34516a14ee0cSDon Skidmore 	}
34526a14ee0cSDon Skidmore 
34536133406bSPaul Greenwalt 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
34546133406bSPaul Greenwalt 	if (status) {
34556133406bSPaul Greenwalt 		hw_dbg(hw, "semaphore failed with %d", status);
345603c5b6d4SJedrzej Jagielski 		return -EBUSY;
34576133406bSPaul Greenwalt 	}
34586133406bSPaul Greenwalt 
34596a14ee0cSDon Skidmore 	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
34606a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
34616a14ee0cSDon Skidmore 	IXGBE_WRITE_FLUSH(hw);
34626133406bSPaul Greenwalt 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
3463efff2e02SMark Rustad 	usleep_range(1000, 1200);
34646a14ee0cSDon Skidmore 
34656a14ee0cSDon Skidmore 	/* Poll for reset bit to self-clear meaning reset is complete */
34666a14ee0cSDon Skidmore 	for (i = 0; i < 10; i++) {
34676a14ee0cSDon Skidmore 		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
34686a14ee0cSDon Skidmore 		if (!(ctrl & IXGBE_CTRL_RST_MASK))
34696a14ee0cSDon Skidmore 			break;
3470efff2e02SMark Rustad 		udelay(1);
34716a14ee0cSDon Skidmore 	}
34726a14ee0cSDon Skidmore 
34736a14ee0cSDon Skidmore 	if (ctrl & IXGBE_CTRL_RST_MASK) {
347403c5b6d4SJedrzej Jagielski 		status = -EIO;
34756a14ee0cSDon Skidmore 		hw_dbg(hw, "Reset polling failed to complete.\n");
34766a14ee0cSDon Skidmore 	}
34776a14ee0cSDon Skidmore 
34786a14ee0cSDon Skidmore 	msleep(50);
34796a14ee0cSDon Skidmore 
34806a14ee0cSDon Skidmore 	/* Double resets are required for recovery from certain error
34816a14ee0cSDon Skidmore 	 * clear the multicast table.  Also reset num_rar_entries to 128,
34826a14ee0cSDon Skidmore 	 * since we modify this value when programming the SAN MAC address.
34836a14ee0cSDon Skidmore 	 */
34846a14ee0cSDon Skidmore 	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
34856a14ee0cSDon Skidmore 		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
34866a14ee0cSDon Skidmore 		goto mac_reset_top;
34876a14ee0cSDon Skidmore 	}
34886a14ee0cSDon Skidmore 
34896a14ee0cSDon Skidmore 	/* Store the permanent mac address */
34906a14ee0cSDon Skidmore 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
34916a14ee0cSDon Skidmore 
34926a14ee0cSDon Skidmore 	/* Store MAC address from RAR0, clear receive address registers, and
34936a14ee0cSDon Skidmore 	 * clear the multicast table.  Also reset num_rar_entries to 128,
34946a14ee0cSDon Skidmore 	 * since we modify this value when programming the SAN MAC address.
34956a14ee0cSDon Skidmore 	 */
34966a14ee0cSDon Skidmore 	hw->mac.num_rar_entries = 128;
34976a14ee0cSDon Skidmore 	hw->mac.ops.init_rx_addrs(hw);
34986a14ee0cSDon Skidmore 
3499e84db727SMark Rustad 	ixgbe_set_mdio_speed(hw);
3500deda562aSDon Skidmore 
3501ab5fe0c5SDon Skidmore 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
3502ab5fe0c5SDon Skidmore 		ixgbe_setup_mux_ctl(hw);
3503ab5fe0c5SDon Skidmore 
35046a14ee0cSDon Skidmore 	return status;
35056a14ee0cSDon Skidmore }
35066a14ee0cSDon Skidmore 
35075b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype
35085b7f000fSDon Skidmore  *	anti-spoofing
35095b7f000fSDon Skidmore  *  @hw:  pointer to hardware structure
35105b7f000fSDon Skidmore  *  @enable: enable or disable switch for Ethertype anti-spoofing
35115b7f000fSDon Skidmore  *  @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing
35125b7f000fSDon Skidmore  **/
ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw * hw,bool enable,int vf)3513bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
3514bc035fc5SDon Skidmore 						   bool enable, int vf)
35155b7f000fSDon Skidmore {
35165b7f000fSDon Skidmore 	int vf_target_reg = vf >> 3;
35175b7f000fSDon Skidmore 	int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT;
35185b7f000fSDon Skidmore 	u32 pfvfspoof;
35195b7f000fSDon Skidmore 
35205b7f000fSDon Skidmore 	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
35215b7f000fSDon Skidmore 	if (enable)
3522b4f47a48SJacob Keller 		pfvfspoof |= BIT(vf_target_shift);
35235b7f000fSDon Skidmore 	else
3524b4f47a48SJacob Keller 		pfvfspoof &= ~BIT(vf_target_shift);
35255b7f000fSDon Skidmore 
35265b7f000fSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
35275b7f000fSDon Skidmore }
35285b7f000fSDon Skidmore 
35296d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning
35306d4c96adSDon Skidmore  *  @hw: pointer to hardware structure
35316d4c96adSDon Skidmore  *  @enable: enable or disable source address pruning
35326d4c96adSDon Skidmore  *  @pool: Rx pool to set source address pruning for
35336d4c96adSDon Skidmore  **/
ixgbe_set_source_address_pruning_X550(struct ixgbe_hw * hw,bool enable,unsigned int pool)35346d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
35356d4c96adSDon Skidmore 						  bool enable,
35366d4c96adSDon Skidmore 						  unsigned int pool)
35376d4c96adSDon Skidmore {
35386d4c96adSDon Skidmore 	u64 pfflp;
35396d4c96adSDon Skidmore 
35406d4c96adSDon Skidmore 	/* max rx pool is 63 */
35416d4c96adSDon Skidmore 	if (pool > 63)
35426d4c96adSDon Skidmore 		return;
35436d4c96adSDon Skidmore 
35446d4c96adSDon Skidmore 	pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL);
35456d4c96adSDon Skidmore 	pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32;
35466d4c96adSDon Skidmore 
35476d4c96adSDon Skidmore 	if (enable)
35486d4c96adSDon Skidmore 		pfflp |= (1ULL << pool);
35496d4c96adSDon Skidmore 	else
35506d4c96adSDon Skidmore 		pfflp &= ~(1ULL << pool);
35516d4c96adSDon Skidmore 
35526d4c96adSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp);
35536d4c96adSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32));
35546d4c96adSDon Skidmore }
35556d4c96adSDon Skidmore 
3556449e21a9SMark Rustad /**
35572916500dSDon Skidmore  *  ixgbe_setup_fc_backplane_x550em_a - Set up flow control
35582916500dSDon Skidmore  *  @hw: pointer to hardware structure
35592916500dSDon Skidmore  *
35602916500dSDon Skidmore  *  Called at init time to set up flow control.
35612916500dSDon Skidmore  **/
ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw * hw)35622916500dSDon Skidmore static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw)
35632916500dSDon Skidmore {
35642916500dSDon Skidmore 	s32 status = 0;
35652916500dSDon Skidmore 	u32 an_cntl = 0;
35662916500dSDon Skidmore 
35672916500dSDon Skidmore 	/* Validate the requested mode */
35682916500dSDon Skidmore 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
35692916500dSDon Skidmore 		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
357003c5b6d4SJedrzej Jagielski 		return -EINVAL;
35712916500dSDon Skidmore 	}
35722916500dSDon Skidmore 
35732916500dSDon Skidmore 	if (hw->fc.requested_mode == ixgbe_fc_default)
35742916500dSDon Skidmore 		hw->fc.requested_mode = ixgbe_fc_full;
35752916500dSDon Skidmore 
35762916500dSDon Skidmore 	/* Set up the 1G and 10G flow control advertisement registers so the
35772916500dSDon Skidmore 	 * HW will be able to do FC autoneg once the cable is plugged in.  If
35782916500dSDon Skidmore 	 * we link at 10G, the 1G advertisement is harmless and vice versa.
35792916500dSDon Skidmore 	 */
35802916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
35812916500dSDon Skidmore 					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
35822916500dSDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl);
35832916500dSDon Skidmore 
35842916500dSDon Skidmore 	if (status) {
35852916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
35862916500dSDon Skidmore 		return status;
35872916500dSDon Skidmore 	}
35882916500dSDon Skidmore 
35892916500dSDon Skidmore 	/* The possible values of fc.requested_mode are:
35902916500dSDon Skidmore 	 * 0: Flow control is completely disabled
35912916500dSDon Skidmore 	 * 1: Rx flow control is enabled (we can receive pause frames,
35922916500dSDon Skidmore 	 *    but not send pause frames).
35932916500dSDon Skidmore 	 * 2: Tx flow control is enabled (we can send pause frames but
35942916500dSDon Skidmore 	 *    we do not support receiving pause frames).
35952916500dSDon Skidmore 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
35962916500dSDon Skidmore 	 * other: Invalid.
35972916500dSDon Skidmore 	 */
35982916500dSDon Skidmore 	switch (hw->fc.requested_mode) {
35992916500dSDon Skidmore 	case ixgbe_fc_none:
36002916500dSDon Skidmore 		/* Flow control completely disabled by software override. */
36012916500dSDon Skidmore 		an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
36022916500dSDon Skidmore 			     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
36032916500dSDon Skidmore 		break;
36042916500dSDon Skidmore 	case ixgbe_fc_tx_pause:
36052916500dSDon Skidmore 		/* Tx Flow control is enabled, and Rx Flow control is
36062916500dSDon Skidmore 		 * disabled by software override.
36072916500dSDon Skidmore 		 */
36082916500dSDon Skidmore 		an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
36092916500dSDon Skidmore 		an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
36102916500dSDon Skidmore 		break;
36112916500dSDon Skidmore 	case ixgbe_fc_rx_pause:
36122916500dSDon Skidmore 		/* Rx Flow control is enabled and Tx Flow control is
36132916500dSDon Skidmore 		 * disabled by software override. Since there really
36142916500dSDon Skidmore 		 * isn't a way to advertise that we are capable of RX
36152916500dSDon Skidmore 		 * Pause ONLY, we will advertise that we support both
36162916500dSDon Skidmore 		 * symmetric and asymmetric Rx PAUSE, as such we fall
36172916500dSDon Skidmore 		 * through to the fc_full statement.  Later, we will
36182916500dSDon Skidmore 		 * disable the adapter's ability to send PAUSE frames.
36192916500dSDon Skidmore 		 */
36202916500dSDon Skidmore 	case ixgbe_fc_full:
36212916500dSDon Skidmore 		/* Flow control (both Rx and Tx) is enabled by SW override. */
36222916500dSDon Skidmore 		an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
36232916500dSDon Skidmore 			   IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
36242916500dSDon Skidmore 		break;
36252916500dSDon Skidmore 	default:
36262916500dSDon Skidmore 		hw_err(hw, "Flow control param set incorrectly\n");
362703c5b6d4SJedrzej Jagielski 		return -EIO;
36282916500dSDon Skidmore 	}
36292916500dSDon Skidmore 
36302916500dSDon Skidmore 	status = hw->mac.ops.write_iosf_sb_reg(hw,
36312916500dSDon Skidmore 					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
36322916500dSDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl);
36332916500dSDon Skidmore 
36342916500dSDon Skidmore 	/* Restart auto-negotiation. */
3635470739b5SDon Skidmore 	status = ixgbe_restart_an_internal_phy_x550em(hw);
36362916500dSDon Skidmore 
36372916500dSDon Skidmore 	return status;
36382916500dSDon Skidmore }
36392916500dSDon Skidmore 
36402916500dSDon Skidmore /**
3641449e21a9SMark Rustad  * ixgbe_set_mux - Set mux for port 1 access with CS4227
3642449e21a9SMark Rustad  * @hw: pointer to hardware structure
3643449e21a9SMark Rustad  * @state: set mux if 1, clear if 0
3644449e21a9SMark Rustad  */
ixgbe_set_mux(struct ixgbe_hw * hw,u8 state)3645449e21a9SMark Rustad static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state)
3646449e21a9SMark Rustad {
3647449e21a9SMark Rustad 	u32 esdp;
3648449e21a9SMark Rustad 
3649449e21a9SMark Rustad 	if (!hw->bus.lan_id)
3650449e21a9SMark Rustad 		return;
3651449e21a9SMark Rustad 	esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
3652449e21a9SMark Rustad 	if (state)
3653449e21a9SMark Rustad 		esdp |= IXGBE_ESDP_SDP1;
3654449e21a9SMark Rustad 	else
3655449e21a9SMark Rustad 		esdp &= ~IXGBE_ESDP_SDP1;
3656449e21a9SMark Rustad 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
3657449e21a9SMark Rustad 	IXGBE_WRITE_FLUSH(hw);
3658449e21a9SMark Rustad }
3659449e21a9SMark Rustad 
3660449e21a9SMark Rustad /**
3661449e21a9SMark Rustad  * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore
3662449e21a9SMark Rustad  * @hw: pointer to hardware structure
3663449e21a9SMark Rustad  * @mask: Mask to specify which semaphore to acquire
3664449e21a9SMark Rustad  *
3665449e21a9SMark Rustad  * Acquires the SWFW semaphore and sets the I2C MUX
3666449e21a9SMark Rustad  */
ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw * hw,u32 mask)3667449e21a9SMark Rustad static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
3668449e21a9SMark Rustad {
3669449e21a9SMark Rustad 	s32 status;
3670449e21a9SMark Rustad 
3671449e21a9SMark Rustad 	status = ixgbe_acquire_swfw_sync_X540(hw, mask);
3672449e21a9SMark Rustad 	if (status)
3673449e21a9SMark Rustad 		return status;
3674449e21a9SMark Rustad 
3675449e21a9SMark Rustad 	if (mask & IXGBE_GSSR_I2C_MASK)
3676449e21a9SMark Rustad 		ixgbe_set_mux(hw, 1);
3677449e21a9SMark Rustad 
3678449e21a9SMark Rustad 	return 0;
3679449e21a9SMark Rustad }
3680449e21a9SMark Rustad 
3681449e21a9SMark Rustad /**
3682449e21a9SMark Rustad  * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore
3683449e21a9SMark Rustad  * @hw: pointer to hardware structure
3684449e21a9SMark Rustad  * @mask: Mask to specify which semaphore to release
3685449e21a9SMark Rustad  *
3686449e21a9SMark Rustad  * Releases the SWFW semaphore and sets the I2C MUX
3687449e21a9SMark Rustad  */
ixgbe_release_swfw_sync_X550em(struct ixgbe_hw * hw,u32 mask)3688449e21a9SMark Rustad static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
3689449e21a9SMark Rustad {
3690449e21a9SMark Rustad 	if (mask & IXGBE_GSSR_I2C_MASK)
3691449e21a9SMark Rustad 		ixgbe_set_mux(hw, 0);
3692449e21a9SMark Rustad 
3693449e21a9SMark Rustad 	ixgbe_release_swfw_sync_X540(hw, mask);
3694449e21a9SMark Rustad }
3695449e21a9SMark Rustad 
369649425dfcSMark Rustad /**
369749425dfcSMark Rustad  * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore
369849425dfcSMark Rustad  * @hw: pointer to hardware structure
369949425dfcSMark Rustad  * @mask: Mask to specify which semaphore to acquire
370049425dfcSMark Rustad  *
370149425dfcSMark Rustad  * Acquires the SWFW semaphore and get the shared PHY token as needed
370249425dfcSMark Rustad  */
ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw * hw,u32 mask)370349425dfcSMark Rustad static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask)
370449425dfcSMark Rustad {
370549425dfcSMark Rustad 	u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
370649425dfcSMark Rustad 	int retries = FW_PHY_TOKEN_RETRIES;
370749425dfcSMark Rustad 	s32 status;
370849425dfcSMark Rustad 
370949425dfcSMark Rustad 	while (--retries) {
371049425dfcSMark Rustad 		status = 0;
371149425dfcSMark Rustad 		if (hmask)
371249425dfcSMark Rustad 			status = ixgbe_acquire_swfw_sync_X540(hw, hmask);
371349425dfcSMark Rustad 		if (status)
371449425dfcSMark Rustad 			return status;
371549425dfcSMark Rustad 		if (!(mask & IXGBE_GSSR_TOKEN_SM))
371649425dfcSMark Rustad 			return 0;
371749425dfcSMark Rustad 
371849425dfcSMark Rustad 		status = ixgbe_get_phy_token(hw);
371949425dfcSMark Rustad 		if (!status)
372049425dfcSMark Rustad 			return 0;
372149425dfcSMark Rustad 		if (hmask)
372249425dfcSMark Rustad 			ixgbe_release_swfw_sync_X540(hw, hmask);
372303c5b6d4SJedrzej Jagielski 		if (status != -EAGAIN)
372449425dfcSMark Rustad 			return status;
3725d4f90d9dSArnd Bergmann 		msleep(FW_PHY_TOKEN_DELAY);
372649425dfcSMark Rustad 	}
372749425dfcSMark Rustad 
372849425dfcSMark Rustad 	return status;
372949425dfcSMark Rustad }
373049425dfcSMark Rustad 
373149425dfcSMark Rustad /**
373249425dfcSMark Rustad  * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore
373349425dfcSMark Rustad  * @hw: pointer to hardware structure
373449425dfcSMark Rustad  * @mask: Mask to specify which semaphore to release
373549425dfcSMark Rustad  *
373649425dfcSMark Rustad  * Release the SWFW semaphore and puts the shared PHY token as needed
373749425dfcSMark Rustad  */
ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw * hw,u32 mask)373849425dfcSMark Rustad static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask)
373949425dfcSMark Rustad {
374049425dfcSMark Rustad 	u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
374149425dfcSMark Rustad 
374249425dfcSMark Rustad 	if (mask & IXGBE_GSSR_TOKEN_SM)
374349425dfcSMark Rustad 		ixgbe_put_phy_token(hw);
374449425dfcSMark Rustad 
374549425dfcSMark Rustad 	if (hmask)
374649425dfcSMark Rustad 		ixgbe_release_swfw_sync_X540(hw, hmask);
374749425dfcSMark Rustad }
374849425dfcSMark Rustad 
3749d31afc8fSMark Rustad /**
3750d31afc8fSMark Rustad  * ixgbe_read_phy_reg_x550a - Reads specified PHY register
3751d31afc8fSMark Rustad  * @hw: pointer to hardware structure
3752d31afc8fSMark Rustad  * @reg_addr: 32 bit address of PHY register to read
37535ba643c6STony Nguyen  * @device_type: 5 bit device type
3754d31afc8fSMark Rustad  * @phy_data: Pointer to read data from PHY register
3755d31afc8fSMark Rustad  *
3756d31afc8fSMark Rustad  * Reads a value from a specified PHY register using the SWFW lock and PHY
3757d31afc8fSMark Rustad  * Token. The PHY Token is needed since the MDIO is shared between to MAC
3758d31afc8fSMark Rustad  * instances.
3759d31afc8fSMark Rustad  */
ixgbe_read_phy_reg_x550a(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)3760d31afc8fSMark Rustad static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
3761d31afc8fSMark Rustad 				    u32 device_type, u16 *phy_data)
3762d31afc8fSMark Rustad {
3763d31afc8fSMark Rustad 	u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
3764d31afc8fSMark Rustad 	s32 status;
3765d31afc8fSMark Rustad 
3766d31afc8fSMark Rustad 	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
376703c5b6d4SJedrzej Jagielski 		return -EBUSY;
3768d31afc8fSMark Rustad 
3769d31afc8fSMark Rustad 	status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data);
3770d31afc8fSMark Rustad 
3771d31afc8fSMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
3772d31afc8fSMark Rustad 
3773d31afc8fSMark Rustad 	return status;
3774d31afc8fSMark Rustad }
3775d31afc8fSMark Rustad 
3776d31afc8fSMark Rustad /**
3777d31afc8fSMark Rustad  * ixgbe_write_phy_reg_x550a - Writes specified PHY register
3778d31afc8fSMark Rustad  * @hw: pointer to hardware structure
3779d31afc8fSMark Rustad  * @reg_addr: 32 bit PHY register to write
3780d31afc8fSMark Rustad  * @device_type: 5 bit device type
3781d31afc8fSMark Rustad  * @phy_data: Data to write to the PHY register
3782d31afc8fSMark Rustad  *
3783d31afc8fSMark Rustad  * Writes a value to specified PHY register using the SWFW lock and PHY Token.
3784d31afc8fSMark Rustad  * The PHY Token is needed since the MDIO is shared between to MAC instances.
3785d31afc8fSMark Rustad  */
ixgbe_write_phy_reg_x550a(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)3786d31afc8fSMark Rustad static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
3787d31afc8fSMark Rustad 				     u32 device_type, u16 phy_data)
3788d31afc8fSMark Rustad {
3789d31afc8fSMark Rustad 	u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
3790d31afc8fSMark Rustad 	s32 status;
3791d31afc8fSMark Rustad 
3792d31afc8fSMark Rustad 	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
379303c5b6d4SJedrzej Jagielski 		return -EBUSY;
3794d31afc8fSMark Rustad 
3795d31afc8fSMark Rustad 	status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data);
3796d31afc8fSMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
3797d31afc8fSMark Rustad 
3798d31afc8fSMark Rustad 	return status;
3799d31afc8fSMark Rustad }
3800d31afc8fSMark Rustad 
38016a14ee0cSDon Skidmore #define X550_COMMON_MAC \
38026a14ee0cSDon Skidmore 	.init_hw			= &ixgbe_init_hw_generic, \
38036a14ee0cSDon Skidmore 	.start_hw			= &ixgbe_start_hw_X540, \
38046a14ee0cSDon Skidmore 	.clear_hw_cntrs			= &ixgbe_clear_hw_cntrs_generic, \
38056a14ee0cSDon Skidmore 	.enable_rx_dma			= &ixgbe_enable_rx_dma_generic, \
38066a14ee0cSDon Skidmore 	.get_mac_addr			= &ixgbe_get_mac_addr_generic, \
38076a14ee0cSDon Skidmore 	.get_device_caps		= &ixgbe_get_device_caps_generic, \
38086a14ee0cSDon Skidmore 	.stop_adapter			= &ixgbe_stop_adapter_generic, \
38096a14ee0cSDon Skidmore 	.set_lan_id			= &ixgbe_set_lan_id_multi_port_pcie, \
38106a14ee0cSDon Skidmore 	.read_analog_reg8		= NULL, \
38116a14ee0cSDon Skidmore 	.write_analog_reg8		= NULL, \
38126a14ee0cSDon Skidmore 	.set_rxpba			= &ixgbe_set_rxpba_generic, \
38136a14ee0cSDon Skidmore 	.check_link			= &ixgbe_check_mac_link_generic, \
38146a14ee0cSDon Skidmore 	.blink_led_start		= &ixgbe_blink_led_start_X540, \
38156a14ee0cSDon Skidmore 	.blink_led_stop			= &ixgbe_blink_led_stop_X540, \
38166a14ee0cSDon Skidmore 	.set_rar			= &ixgbe_set_rar_generic, \
38176a14ee0cSDon Skidmore 	.clear_rar			= &ixgbe_clear_rar_generic, \
38186a14ee0cSDon Skidmore 	.set_vmdq			= &ixgbe_set_vmdq_generic, \
38196a14ee0cSDon Skidmore 	.set_vmdq_san_mac		= &ixgbe_set_vmdq_san_mac_generic, \
38206a14ee0cSDon Skidmore 	.clear_vmdq			= &ixgbe_clear_vmdq_generic, \
38216a14ee0cSDon Skidmore 	.init_rx_addrs			= &ixgbe_init_rx_addrs_generic, \
38226a14ee0cSDon Skidmore 	.update_mc_addr_list		= &ixgbe_update_mc_addr_list_generic, \
38236a14ee0cSDon Skidmore 	.enable_mc			= &ixgbe_enable_mc_generic, \
38246a14ee0cSDon Skidmore 	.disable_mc			= &ixgbe_disable_mc_generic, \
38256a14ee0cSDon Skidmore 	.clear_vfta			= &ixgbe_clear_vfta_generic, \
38266a14ee0cSDon Skidmore 	.set_vfta			= &ixgbe_set_vfta_generic, \
38276a14ee0cSDon Skidmore 	.fc_enable			= &ixgbe_fc_enable_generic, \
3828cb8e0514STony Nguyen 	.set_fw_drv_ver			= &ixgbe_set_fw_drv_ver_x550, \
38296a14ee0cSDon Skidmore 	.init_uta_tables		= &ixgbe_init_uta_tables_generic, \
38306a14ee0cSDon Skidmore 	.set_mac_anti_spoofing		= &ixgbe_set_mac_anti_spoofing, \
38316a14ee0cSDon Skidmore 	.set_vlan_anti_spoofing		= &ixgbe_set_vlan_anti_spoofing, \
38326d4c96adSDon Skidmore 	.set_source_address_pruning	= \
38336d4c96adSDon Skidmore 				&ixgbe_set_source_address_pruning_X550, \
38345b7f000fSDon Skidmore 	.set_ethertype_anti_spoofing	= \
38355b7f000fSDon Skidmore 				&ixgbe_set_ethertype_anti_spoofing_X550, \
38366a14ee0cSDon Skidmore 	.disable_rx_buff		= &ixgbe_disable_rx_buff_generic, \
38376a14ee0cSDon Skidmore 	.enable_rx_buff			= &ixgbe_enable_rx_buff_generic, \
38386a14ee0cSDon Skidmore 	.get_thermal_sensor_data	= NULL, \
38396a14ee0cSDon Skidmore 	.init_thermal_sensor_thresh	= NULL, \
384059dd45d5SSebastian Basierski 	.fw_recovery_mode		= &ixgbe_fw_recovery_mode_X550, \
38411f9ac57cSDon Skidmore 	.enable_rx			= &ixgbe_enable_rx_generic, \
38421f9ac57cSDon Skidmore 	.disable_rx			= &ixgbe_disable_rx_x550, \
38436a14ee0cSDon Skidmore 
384437689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550 = {
38456a14ee0cSDon Skidmore 	X550_COMMON_MAC
3846a0ad55a3SDon Skidmore 	.led_on			= ixgbe_led_on_generic,
3847a0ad55a3SDon Skidmore 	.led_off		= ixgbe_led_off_generic,
3848805cedd6SDon Skidmore 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
38496a14ee0cSDon Skidmore 	.reset_hw		= &ixgbe_reset_hw_X540,
38506a14ee0cSDon Skidmore 	.get_media_type		= &ixgbe_get_media_type_X540,
38516a14ee0cSDon Skidmore 	.get_san_mac_addr	= &ixgbe_get_san_mac_addr_generic,
38526a14ee0cSDon Skidmore 	.get_wwn_prefix		= &ixgbe_get_wwn_prefix_generic,
38536a14ee0cSDon Skidmore 	.setup_link		= &ixgbe_setup_mac_link_X540,
38546a14ee0cSDon Skidmore 	.get_link_capabilities	= &ixgbe_get_copper_link_capabilities_generic,
3855454c65ddSDon Skidmore 	.get_bus_info		= &ixgbe_get_bus_info_generic,
38566a14ee0cSDon Skidmore 	.setup_sfp		= NULL,
3857449e21a9SMark Rustad 	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X540,
3858449e21a9SMark Rustad 	.release_swfw_sync	= &ixgbe_release_swfw_sync_X540,
3859dbd15b8fSDon Skidmore 	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
3860afdc71e4SMark Rustad 	.prot_autoc_read	= prot_autoc_read_generic,
3861afdc71e4SMark Rustad 	.prot_autoc_write	= prot_autoc_write_generic,
3862afdc71e4SMark Rustad 	.setup_fc		= ixgbe_setup_fc_generic,
38632916500dSDon Skidmore 	.fc_autoneg		= ixgbe_fc_autoneg,
38646a14ee0cSDon Skidmore };
38656a14ee0cSDon Skidmore 
386637689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550EM_x = {
38676a14ee0cSDon Skidmore 	X550_COMMON_MAC
3868a0ad55a3SDon Skidmore 	.led_on			= ixgbe_led_on_t_x550em,
3869a0ad55a3SDon Skidmore 	.led_off		= ixgbe_led_off_t_x550em,
3870805cedd6SDon Skidmore 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
38716a14ee0cSDon Skidmore 	.reset_hw		= &ixgbe_reset_hw_X550em,
38726a14ee0cSDon Skidmore 	.get_media_type		= &ixgbe_get_media_type_X550em,
38736a14ee0cSDon Skidmore 	.get_san_mac_addr	= NULL,
38746a14ee0cSDon Skidmore 	.get_wwn_prefix		= NULL,
38754695886cSEmil Tantilov 	.setup_link		= &ixgbe_setup_mac_link_X540,
38766a14ee0cSDon Skidmore 	.get_link_capabilities	= &ixgbe_get_link_capabilities_X550em,
3877454c65ddSDon Skidmore 	.get_bus_info		= &ixgbe_get_bus_info_X550em,
38786a14ee0cSDon Skidmore 	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
3879449e21a9SMark Rustad 	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X550em,
3880449e21a9SMark Rustad 	.release_swfw_sync	= &ixgbe_release_swfw_sync_X550em,
3881dbd15b8fSDon Skidmore 	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
3882afdc71e4SMark Rustad 	.setup_fc		= NULL, /* defined later */
38832916500dSDon Skidmore 	.fc_autoneg		= ixgbe_fc_autoneg,
38849a5c27e6SMark Rustad 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550,
38859a5c27e6SMark Rustad 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550,
38866a14ee0cSDon Skidmore };
38876a14ee0cSDon Skidmore 
38885e999fb4SPaul Greenwalt static const struct ixgbe_mac_operations mac_ops_X550EM_x_fw = {
38895e999fb4SPaul Greenwalt 	X550_COMMON_MAC
38905e999fb4SPaul Greenwalt 	.led_on			= NULL,
38915e999fb4SPaul Greenwalt 	.led_off		= NULL,
38925e999fb4SPaul Greenwalt 	.init_led_link_act	= NULL,
38935e999fb4SPaul Greenwalt 	.reset_hw		= &ixgbe_reset_hw_X550em,
38945e999fb4SPaul Greenwalt 	.get_media_type		= &ixgbe_get_media_type_X550em,
38955e999fb4SPaul Greenwalt 	.get_san_mac_addr	= NULL,
38965e999fb4SPaul Greenwalt 	.get_wwn_prefix		= NULL,
38975e999fb4SPaul Greenwalt 	.setup_link		= &ixgbe_setup_mac_link_X540,
38985e999fb4SPaul Greenwalt 	.get_link_capabilities	= &ixgbe_get_link_capabilities_X550em,
38995e999fb4SPaul Greenwalt 	.get_bus_info		= &ixgbe_get_bus_info_X550em,
39005e999fb4SPaul Greenwalt 	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
39015e999fb4SPaul Greenwalt 	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X550em,
39025e999fb4SPaul Greenwalt 	.release_swfw_sync	= &ixgbe_release_swfw_sync_X550em,
39035e999fb4SPaul Greenwalt 	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
39045e999fb4SPaul Greenwalt 	.setup_fc		= NULL,
39055e999fb4SPaul Greenwalt 	.fc_autoneg		= ixgbe_fc_autoneg,
39065e999fb4SPaul Greenwalt 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550,
39075e999fb4SPaul Greenwalt 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550,
39085e999fb4SPaul Greenwalt };
39095e999fb4SPaul Greenwalt 
39102e033eacSBhumika Goyal static const struct ixgbe_mac_operations mac_ops_x550em_a = {
391149425dfcSMark Rustad 	X550_COMMON_MAC
3912a0ad55a3SDon Skidmore 	.led_on			= ixgbe_led_on_t_x550em,
3913a0ad55a3SDon Skidmore 	.led_off		= ixgbe_led_off_t_x550em,
3914805cedd6SDon Skidmore 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
391549425dfcSMark Rustad 	.reset_hw		= ixgbe_reset_hw_X550em,
391649425dfcSMark Rustad 	.get_media_type		= ixgbe_get_media_type_X550em,
391749425dfcSMark Rustad 	.get_san_mac_addr	= NULL,
391849425dfcSMark Rustad 	.get_wwn_prefix		= NULL,
39195b9d3cfbSEmil Tantilov 	.setup_link		= &ixgbe_setup_mac_link_X540,
392049425dfcSMark Rustad 	.get_link_capabilities	= ixgbe_get_link_capabilities_X550em,
392149425dfcSMark Rustad 	.get_bus_info		= ixgbe_get_bus_info_X550em,
392249425dfcSMark Rustad 	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
392349425dfcSMark Rustad 	.acquire_swfw_sync	= ixgbe_acquire_swfw_sync_x550em_a,
392449425dfcSMark Rustad 	.release_swfw_sync	= ixgbe_release_swfw_sync_x550em_a,
3925a0254a70SMark Rustad 	.setup_fc		= ixgbe_setup_fc_x550em,
3926470739b5SDon Skidmore 	.fc_autoneg		= ixgbe_fc_autoneg,
392749425dfcSMark Rustad 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550a,
392849425dfcSMark Rustad 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550a,
392949425dfcSMark Rustad };
393049425dfcSMark Rustad 
39312e033eacSBhumika Goyal static const struct ixgbe_mac_operations mac_ops_x550em_a_fw = {
3932b3eb4e18SMark Rustad 	X550_COMMON_MAC
3933b3eb4e18SMark Rustad 	.led_on			= ixgbe_led_on_generic,
3934b3eb4e18SMark Rustad 	.led_off		= ixgbe_led_off_generic,
3935b3eb4e18SMark Rustad 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
3936b3eb4e18SMark Rustad 	.reset_hw		= ixgbe_reset_hw_X550em,
3937b3eb4e18SMark Rustad 	.get_media_type		= ixgbe_get_media_type_X550em,
3938b3eb4e18SMark Rustad 	.get_san_mac_addr	= NULL,
3939b3eb4e18SMark Rustad 	.get_wwn_prefix		= NULL,
3940b3eb4e18SMark Rustad 	.setup_link		= NULL, /* defined later */
3941b3eb4e18SMark Rustad 	.get_link_capabilities	= ixgbe_get_link_capabilities_X550em,
3942b3eb4e18SMark Rustad 	.get_bus_info		= ixgbe_get_bus_info_X550em,
3943b3eb4e18SMark Rustad 	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
3944b3eb4e18SMark Rustad 	.acquire_swfw_sync	= ixgbe_acquire_swfw_sync_x550em_a,
3945b3eb4e18SMark Rustad 	.release_swfw_sync	= ixgbe_release_swfw_sync_x550em_a,
3946b3eb4e18SMark Rustad 	.setup_fc		= ixgbe_setup_fc_x550em,
3947b3eb4e18SMark Rustad 	.fc_autoneg		= ixgbe_fc_autoneg,
3948b3eb4e18SMark Rustad 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550a,
3949b3eb4e18SMark Rustad 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550a,
3950b3eb4e18SMark Rustad };
3951b3eb4e18SMark Rustad 
39526a14ee0cSDon Skidmore #define X550_COMMON_EEP \
39536a14ee0cSDon Skidmore 	.read			= &ixgbe_read_ee_hostif_X550, \
39546a14ee0cSDon Skidmore 	.read_buffer		= &ixgbe_read_ee_hostif_buffer_X550, \
39556a14ee0cSDon Skidmore 	.write			= &ixgbe_write_ee_hostif_X550, \
39566a14ee0cSDon Skidmore 	.write_buffer		= &ixgbe_write_ee_hostif_buffer_X550, \
39576a14ee0cSDon Skidmore 	.validate_checksum	= &ixgbe_validate_eeprom_checksum_X550, \
39586a14ee0cSDon Skidmore 	.update_checksum	= &ixgbe_update_eeprom_checksum_X550, \
39596a14ee0cSDon Skidmore 	.calc_checksum		= &ixgbe_calc_eeprom_checksum_X550, \
39606a14ee0cSDon Skidmore 
396137689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550 = {
39626a14ee0cSDon Skidmore 	X550_COMMON_EEP
39636a14ee0cSDon Skidmore 	.init_params		= &ixgbe_init_eeprom_params_X550,
39646a14ee0cSDon Skidmore };
39656a14ee0cSDon Skidmore 
396637689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = {
39676a14ee0cSDon Skidmore 	X550_COMMON_EEP
39686a14ee0cSDon Skidmore 	.init_params		= &ixgbe_init_eeprom_params_X540,
39696a14ee0cSDon Skidmore };
39706a14ee0cSDon Skidmore 
39716a14ee0cSDon Skidmore #define X550_COMMON_PHY	\
39726a14ee0cSDon Skidmore 	.identify_sfp		= &ixgbe_identify_module_generic, \
39736a14ee0cSDon Skidmore 	.reset			= NULL, \
39746a14ee0cSDon Skidmore 	.setup_link_speed	= &ixgbe_setup_phy_link_speed_generic, \
39756a14ee0cSDon Skidmore 	.read_i2c_byte		= &ixgbe_read_i2c_byte_generic, \
39766a14ee0cSDon Skidmore 	.write_i2c_byte		= &ixgbe_write_i2c_byte_generic, \
39776a14ee0cSDon Skidmore 	.read_i2c_sff8472	= &ixgbe_read_i2c_sff8472_generic, \
39786a14ee0cSDon Skidmore 	.read_i2c_eeprom	= &ixgbe_read_i2c_eeprom_generic, \
39796a14ee0cSDon Skidmore 	.write_i2c_eeprom	= &ixgbe_write_i2c_eeprom_generic, \
3980bef23de1SDon Skidmore 	.setup_link		= &ixgbe_setup_phy_link_generic, \
3981b3eb4e18SMark Rustad 	.set_phy_power		= NULL,
39826a14ee0cSDon Skidmore 
398337689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550 = {
39846a14ee0cSDon Skidmore 	X550_COMMON_PHY
3985b3eb4e18SMark Rustad 	.check_overtemp		= &ixgbe_tn_check_overtemp,
39866a14ee0cSDon Skidmore 	.init			= NULL,
39876a14ee0cSDon Skidmore 	.identify		= &ixgbe_identify_phy_generic,
3988d31afc8fSMark Rustad 	.read_reg		= &ixgbe_read_phy_reg_generic,
3989d31afc8fSMark Rustad 	.write_reg		= &ixgbe_write_phy_reg_generic,
39906a14ee0cSDon Skidmore };
39916a14ee0cSDon Skidmore 
399237689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550EM_x = {
39936a14ee0cSDon Skidmore 	X550_COMMON_PHY
3994b3eb4e18SMark Rustad 	.check_overtemp		= &ixgbe_tn_check_overtemp,
39956a14ee0cSDon Skidmore 	.init			= &ixgbe_init_phy_ops_X550em,
39966a14ee0cSDon Skidmore 	.identify		= &ixgbe_identify_phy_x550em,
3997d31afc8fSMark Rustad 	.read_reg		= &ixgbe_read_phy_reg_generic,
3998d31afc8fSMark Rustad 	.write_reg		= &ixgbe_write_phy_reg_generic,
39996a14ee0cSDon Skidmore };
40006a14ee0cSDon Skidmore 
40018dc963e1SPaul Greenwalt static const struct ixgbe_phy_operations phy_ops_x550em_x_fw = {
40028dc963e1SPaul Greenwalt 	X550_COMMON_PHY
40038dc963e1SPaul Greenwalt 	.check_overtemp		= NULL,
40048dc963e1SPaul Greenwalt 	.init			= ixgbe_init_phy_ops_X550em,
40058dc963e1SPaul Greenwalt 	.identify		= ixgbe_identify_phy_x550em,
40068dc963e1SPaul Greenwalt 	.read_reg		= NULL,
40078dc963e1SPaul Greenwalt 	.write_reg		= NULL,
40088dc963e1SPaul Greenwalt 	.read_reg_mdi		= NULL,
40098dc963e1SPaul Greenwalt 	.write_reg_mdi		= NULL,
40108dc963e1SPaul Greenwalt };
40118dc963e1SPaul Greenwalt 
4012d31afc8fSMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a = {
4013d31afc8fSMark Rustad 	X550_COMMON_PHY
4014b3eb4e18SMark Rustad 	.check_overtemp		= &ixgbe_tn_check_overtemp,
4015d31afc8fSMark Rustad 	.init			= &ixgbe_init_phy_ops_X550em,
4016d31afc8fSMark Rustad 	.identify		= &ixgbe_identify_phy_x550em,
4017d31afc8fSMark Rustad 	.read_reg		= &ixgbe_read_phy_reg_x550a,
4018d31afc8fSMark Rustad 	.write_reg		= &ixgbe_write_phy_reg_x550a,
40198fe293aaSMark Rustad 	.read_reg_mdi		= &ixgbe_read_phy_reg_mdi,
40208fe293aaSMark Rustad 	.write_reg_mdi		= &ixgbe_write_phy_reg_mdi,
4021d31afc8fSMark Rustad };
4022d31afc8fSMark Rustad 
4023b3eb4e18SMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a_fw = {
4024b3eb4e18SMark Rustad 	X550_COMMON_PHY
4025b3eb4e18SMark Rustad 	.check_overtemp		= ixgbe_check_overtemp_fw,
4026b3eb4e18SMark Rustad 	.init			= ixgbe_init_phy_ops_X550em,
4027b3eb4e18SMark Rustad 	.identify		= ixgbe_identify_phy_fw,
4028b3eb4e18SMark Rustad 	.read_reg		= NULL,
4029b3eb4e18SMark Rustad 	.write_reg		= NULL,
4030b3eb4e18SMark Rustad 	.read_reg_mdi		= NULL,
4031b3eb4e18SMark Rustad 	.write_reg_mdi		= NULL,
4032b3eb4e18SMark Rustad };
4033b3eb4e18SMark Rustad 
4034b71f6c40SEmil Tantilov static const struct ixgbe_link_operations link_ops_x550em_x = {
4035b71f6c40SEmil Tantilov 	.read_link		= &ixgbe_read_i2c_combined_generic,
4036b71f6c40SEmil Tantilov 	.read_link_unlocked	= &ixgbe_read_i2c_combined_generic_unlocked,
4037b71f6c40SEmil Tantilov 	.write_link		= &ixgbe_write_i2c_combined_generic,
4038b71f6c40SEmil Tantilov 	.write_link_unlocked	= &ixgbe_write_i2c_combined_generic_unlocked,
4039b71f6c40SEmil Tantilov };
4040b71f6c40SEmil Tantilov 
40419a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = {
40429a900ecaSDon Skidmore 	IXGBE_MVALS_INIT(X550)
40439a900ecaSDon Skidmore };
40449a900ecaSDon Skidmore 
40459a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = {
40469a900ecaSDon Skidmore 	IXGBE_MVALS_INIT(X550EM_x)
40479a900ecaSDon Skidmore };
40489a900ecaSDon Skidmore 
404949425dfcSMark Rustad static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = {
405049425dfcSMark Rustad 	IXGBE_MVALS_INIT(X550EM_a)
405149425dfcSMark Rustad };
405249425dfcSMark Rustad 
405337689010SMark Rustad const struct ixgbe_info ixgbe_X550_info = {
40546a14ee0cSDon Skidmore 	.mac			= ixgbe_mac_X550,
40556a14ee0cSDon Skidmore 	.get_invariants		= &ixgbe_get_invariants_X540,
40566a14ee0cSDon Skidmore 	.mac_ops		= &mac_ops_X550,
40576a14ee0cSDon Skidmore 	.eeprom_ops		= &eeprom_ops_X550,
40586a14ee0cSDon Skidmore 	.phy_ops		= &phy_ops_X550,
40596a14ee0cSDon Skidmore 	.mbx_ops		= &mbx_ops_generic,
40609a900ecaSDon Skidmore 	.mvals			= ixgbe_mvals_X550,
40616a14ee0cSDon Skidmore };
40626a14ee0cSDon Skidmore 
406337689010SMark Rustad const struct ixgbe_info ixgbe_X550EM_x_info = {
40646a14ee0cSDon Skidmore 	.mac			= ixgbe_mac_X550EM_x,
4065b5529ef5SDon Skidmore 	.get_invariants		= &ixgbe_get_invariants_X550_x,
40666a14ee0cSDon Skidmore 	.mac_ops		= &mac_ops_X550EM_x,
40676a14ee0cSDon Skidmore 	.eeprom_ops		= &eeprom_ops_X550EM_x,
40686a14ee0cSDon Skidmore 	.phy_ops		= &phy_ops_X550EM_x,
40696a14ee0cSDon Skidmore 	.mbx_ops		= &mbx_ops_generic,
40709a900ecaSDon Skidmore 	.mvals			= ixgbe_mvals_X550EM_x,
4071b71f6c40SEmil Tantilov 	.link_ops		= &link_ops_x550em_x,
40726a14ee0cSDon Skidmore };
407349425dfcSMark Rustad 
40748dc963e1SPaul Greenwalt const struct ixgbe_info ixgbe_x550em_x_fw_info = {
40758dc963e1SPaul Greenwalt 	.mac			= ixgbe_mac_X550EM_x,
40768dc963e1SPaul Greenwalt 	.get_invariants		= ixgbe_get_invariants_X550_x_fw,
40775e999fb4SPaul Greenwalt 	.mac_ops		= &mac_ops_X550EM_x_fw,
40788dc963e1SPaul Greenwalt 	.eeprom_ops		= &eeprom_ops_X550EM_x,
40798dc963e1SPaul Greenwalt 	.phy_ops		= &phy_ops_x550em_x_fw,
40808dc963e1SPaul Greenwalt 	.mbx_ops		= &mbx_ops_generic,
40818dc963e1SPaul Greenwalt 	.mvals			= ixgbe_mvals_X550EM_x,
40828dc963e1SPaul Greenwalt };
40838dc963e1SPaul Greenwalt 
408449425dfcSMark Rustad const struct ixgbe_info ixgbe_x550em_a_info = {
408549425dfcSMark Rustad 	.mac			= ixgbe_mac_x550em_a,
4086b71f6c40SEmil Tantilov 	.get_invariants		= &ixgbe_get_invariants_X550_a,
408749425dfcSMark Rustad 	.mac_ops		= &mac_ops_x550em_a,
408849425dfcSMark Rustad 	.eeprom_ops		= &eeprom_ops_X550EM_x,
4089d31afc8fSMark Rustad 	.phy_ops		= &phy_ops_x550em_a,
409049425dfcSMark Rustad 	.mbx_ops		= &mbx_ops_generic,
409149425dfcSMark Rustad 	.mvals			= ixgbe_mvals_x550em_a,
409249425dfcSMark Rustad };
4093b3eb4e18SMark Rustad 
4094b3eb4e18SMark Rustad const struct ixgbe_info ixgbe_x550em_a_fw_info = {
4095b3eb4e18SMark Rustad 	.mac			= ixgbe_mac_x550em_a,
4096b3eb4e18SMark Rustad 	.get_invariants		= ixgbe_get_invariants_X550_a_fw,
4097b3eb4e18SMark Rustad 	.mac_ops		= &mac_ops_x550em_a_fw,
4098b3eb4e18SMark Rustad 	.eeprom_ops		= &eeprom_ops_X550EM_x,
4099b3eb4e18SMark Rustad 	.phy_ops		= &phy_ops_x550em_a_fw,
4100b3eb4e18SMark Rustad 	.mbx_ops		= &mbx_ops_generic,
4101b3eb4e18SMark Rustad 	.mvals			= ixgbe_mvals_x550em_a,
4102b3eb4e18SMark Rustad };
4103