16a14ee0cSDon Skidmore /*******************************************************************************
26a14ee0cSDon Skidmore  *
36a14ee0cSDon Skidmore  *  Intel 10 Gigabit PCI Express Linux driver
437689010SMark Rustad  *  Copyright(c) 1999 - 2016 Intel Corporation.
56a14ee0cSDon Skidmore  *
66a14ee0cSDon Skidmore  *  This program is free software; you can redistribute it and/or modify it
76a14ee0cSDon Skidmore  *  under the terms and conditions of the GNU General Public License,
86a14ee0cSDon Skidmore  *  version 2, as published by the Free Software Foundation.
96a14ee0cSDon Skidmore  *
106a14ee0cSDon Skidmore  *  This program is distributed in the hope it will be useful, but WITHOUT
116a14ee0cSDon Skidmore  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
126a14ee0cSDon Skidmore  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
136a14ee0cSDon Skidmore  *  more details.
146a14ee0cSDon Skidmore  *
156a14ee0cSDon Skidmore  *  The full GNU General Public License is included in this distribution in
166a14ee0cSDon Skidmore  *  the file called "COPYING".
176a14ee0cSDon Skidmore  *
186a14ee0cSDon Skidmore  *  Contact Information:
196a14ee0cSDon Skidmore  *  Linux NICS <linux.nics@intel.com>
206a14ee0cSDon Skidmore  *  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
216a14ee0cSDon Skidmore  *  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
226a14ee0cSDon Skidmore  *
236a14ee0cSDon Skidmore  ******************************************************************************/
246a14ee0cSDon Skidmore #include "ixgbe_x540.h"
256a14ee0cSDon Skidmore #include "ixgbe_type.h"
266a14ee0cSDon Skidmore #include "ixgbe_common.h"
276a14ee0cSDon Skidmore #include "ixgbe_phy.h"
286a14ee0cSDon Skidmore 
29d91e3a7dSMark Rustad static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed);
30afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *);
312916500dSDon Skidmore static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *);
322916500dSDon Skidmore static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *);
332916500dSDon Skidmore static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *);
34d91e3a7dSMark Rustad 
35b5529ef5SDon Skidmore static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw)
36b5529ef5SDon Skidmore {
37b5529ef5SDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
38b5529ef5SDon Skidmore 	struct ixgbe_phy_info *phy = &hw->phy;
39b71f6c40SEmil Tantilov 	struct ixgbe_link_info *link = &hw->link;
40b71f6c40SEmil Tantilov 
41b71f6c40SEmil Tantilov 	/* Start with X540 invariants, since so simular */
42b71f6c40SEmil Tantilov 	ixgbe_get_invariants_X540(hw);
43b71f6c40SEmil Tantilov 
44b71f6c40SEmil Tantilov 	if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
45b71f6c40SEmil Tantilov 		phy->ops.set_phy_power = NULL;
46b71f6c40SEmil Tantilov 
47b71f6c40SEmil Tantilov 	link->addr = IXGBE_CS4227;
48b71f6c40SEmil Tantilov 
49b71f6c40SEmil Tantilov 	return 0;
50b71f6c40SEmil Tantilov }
51b71f6c40SEmil Tantilov 
52b71f6c40SEmil Tantilov static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw)
53b71f6c40SEmil Tantilov {
54b71f6c40SEmil Tantilov 	struct ixgbe_mac_info *mac = &hw->mac;
55b71f6c40SEmil Tantilov 	struct ixgbe_phy_info *phy = &hw->phy;
56b5529ef5SDon Skidmore 
57b5529ef5SDon Skidmore 	/* Start with X540 invariants, since so simular */
58b5529ef5SDon Skidmore 	ixgbe_get_invariants_X540(hw);
59b5529ef5SDon Skidmore 
60b5529ef5SDon Skidmore 	if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
61b5529ef5SDon Skidmore 		phy->ops.set_phy_power = NULL;
62b5529ef5SDon Skidmore 
63b5529ef5SDon Skidmore 	return 0;
64b5529ef5SDon Skidmore }
65b5529ef5SDon Skidmore 
66ab5fe0c5SDon Skidmore /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control
67ab5fe0c5SDon Skidmore  *  @hw: pointer to hardware structure
68ab5fe0c5SDon Skidmore  **/
69ab5fe0c5SDon Skidmore static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
70ab5fe0c5SDon Skidmore {
71ab5fe0c5SDon Skidmore 	u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
72ab5fe0c5SDon Skidmore 
73ab5fe0c5SDon Skidmore 	if (hw->bus.lan_id) {
74ab5fe0c5SDon Skidmore 		esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
75ab5fe0c5SDon Skidmore 		esdp |= IXGBE_ESDP_SDP1_DIR;
76ab5fe0c5SDon Skidmore 	}
77ab5fe0c5SDon Skidmore 	esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
78ab5fe0c5SDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
79ab5fe0c5SDon Skidmore 	IXGBE_WRITE_FLUSH(hw);
80ab5fe0c5SDon Skidmore }
81ab5fe0c5SDon Skidmore 
82542b6eecSMark Rustad /**
83542b6eecSMark Rustad  * ixgbe_read_cs4227 - Read CS4227 register
84542b6eecSMark Rustad  * @hw: pointer to hardware structure
85542b6eecSMark Rustad  * @reg: register number to write
86542b6eecSMark Rustad  * @value: pointer to receive value read
87542b6eecSMark Rustad  *
88542b6eecSMark Rustad  * Returns status code
89542b6eecSMark Rustad  */
90542b6eecSMark Rustad static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
91542b6eecSMark Rustad {
92b71f6c40SEmil Tantilov 	return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);
93542b6eecSMark Rustad }
94542b6eecSMark Rustad 
95542b6eecSMark Rustad /**
96542b6eecSMark Rustad  * ixgbe_write_cs4227 - Write CS4227 register
97542b6eecSMark Rustad  * @hw: pointer to hardware structure
98542b6eecSMark Rustad  * @reg: register number to write
99542b6eecSMark Rustad  * @value: value to write to register
100542b6eecSMark Rustad  *
101542b6eecSMark Rustad  * Returns status code
102542b6eecSMark Rustad  */
103542b6eecSMark Rustad static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
104542b6eecSMark Rustad {
105b71f6c40SEmil Tantilov 	return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);
106542b6eecSMark Rustad }
107542b6eecSMark Rustad 
108542b6eecSMark Rustad /**
109542b6eecSMark Rustad  * ixgbe_read_pe - Read register from port expander
110542b6eecSMark Rustad  * @hw: pointer to hardware structure
111542b6eecSMark Rustad  * @reg: register number to read
112542b6eecSMark Rustad  * @value: pointer to receive read value
113542b6eecSMark Rustad  *
114542b6eecSMark Rustad  * Returns status code
115542b6eecSMark Rustad  */
116542b6eecSMark Rustad static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value)
117542b6eecSMark Rustad {
118542b6eecSMark Rustad 	s32 status;
119542b6eecSMark Rustad 
120542b6eecSMark Rustad 	status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, value);
121542b6eecSMark Rustad 	if (status)
122542b6eecSMark Rustad 		hw_err(hw, "port expander access failed with %d\n", status);
123542b6eecSMark Rustad 	return status;
124542b6eecSMark Rustad }
125542b6eecSMark Rustad 
126542b6eecSMark Rustad /**
127542b6eecSMark Rustad  * ixgbe_write_pe - Write register to port expander
128542b6eecSMark Rustad  * @hw: pointer to hardware structure
129542b6eecSMark Rustad  * @reg: register number to write
130542b6eecSMark Rustad  * @value: value to write
131542b6eecSMark Rustad  *
132542b6eecSMark Rustad  * Returns status code
133542b6eecSMark Rustad  */
134542b6eecSMark Rustad static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value)
135542b6eecSMark Rustad {
136542b6eecSMark Rustad 	s32 status;
137542b6eecSMark Rustad 
138542b6eecSMark Rustad 	status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE,
139542b6eecSMark Rustad 						       value);
140542b6eecSMark Rustad 	if (status)
141542b6eecSMark Rustad 		hw_err(hw, "port expander access failed with %d\n", status);
142542b6eecSMark Rustad 	return status;
143542b6eecSMark Rustad }
144542b6eecSMark Rustad 
145542b6eecSMark Rustad /**
146542b6eecSMark Rustad  * ixgbe_reset_cs4227 - Reset CS4227 using port expander
147542b6eecSMark Rustad  * @hw: pointer to hardware structure
148542b6eecSMark Rustad  *
1498bf7a7b8SMark Rustad  * This function assumes that the caller has acquired the proper semaphore.
150542b6eecSMark Rustad  * Returns error code
151542b6eecSMark Rustad  */
152542b6eecSMark Rustad static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
153542b6eecSMark Rustad {
154542b6eecSMark Rustad 	s32 status;
155542b6eecSMark Rustad 	u32 retry;
156542b6eecSMark Rustad 	u16 value;
157542b6eecSMark Rustad 	u8 reg;
158542b6eecSMark Rustad 
159542b6eecSMark Rustad 	/* Trigger hard reset. */
160542b6eecSMark Rustad 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
161542b6eecSMark Rustad 	if (status)
162542b6eecSMark Rustad 		return status;
163542b6eecSMark Rustad 	reg |= IXGBE_PE_BIT1;
164542b6eecSMark Rustad 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
165542b6eecSMark Rustad 	if (status)
166542b6eecSMark Rustad 		return status;
167542b6eecSMark Rustad 
168542b6eecSMark Rustad 	status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, &reg);
169542b6eecSMark Rustad 	if (status)
170542b6eecSMark Rustad 		return status;
171542b6eecSMark Rustad 	reg &= ~IXGBE_PE_BIT1;
172542b6eecSMark Rustad 	status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg);
173542b6eecSMark Rustad 	if (status)
174542b6eecSMark Rustad 		return status;
175542b6eecSMark Rustad 
176542b6eecSMark Rustad 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
177542b6eecSMark Rustad 	if (status)
178542b6eecSMark Rustad 		return status;
179542b6eecSMark Rustad 	reg &= ~IXGBE_PE_BIT1;
180542b6eecSMark Rustad 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
181542b6eecSMark Rustad 	if (status)
182542b6eecSMark Rustad 		return status;
183542b6eecSMark Rustad 
184542b6eecSMark Rustad 	usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100);
185542b6eecSMark Rustad 
186542b6eecSMark Rustad 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
187542b6eecSMark Rustad 	if (status)
188542b6eecSMark Rustad 		return status;
189542b6eecSMark Rustad 	reg |= IXGBE_PE_BIT1;
190542b6eecSMark Rustad 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
191542b6eecSMark Rustad 	if (status)
192542b6eecSMark Rustad 		return status;
193542b6eecSMark Rustad 
194542b6eecSMark Rustad 	/* Wait for the reset to complete. */
195542b6eecSMark Rustad 	msleep(IXGBE_CS4227_RESET_DELAY);
196542b6eecSMark Rustad 	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
197542b6eecSMark Rustad 		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
198542b6eecSMark Rustad 					   &value);
199542b6eecSMark Rustad 		if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK)
200542b6eecSMark Rustad 			break;
201542b6eecSMark Rustad 		msleep(IXGBE_CS4227_CHECK_DELAY);
202542b6eecSMark Rustad 	}
203542b6eecSMark Rustad 	if (retry == IXGBE_CS4227_RETRIES) {
204542b6eecSMark Rustad 		hw_err(hw, "CS4227 reset did not complete\n");
205542b6eecSMark Rustad 		return IXGBE_ERR_PHY;
206542b6eecSMark Rustad 	}
207542b6eecSMark Rustad 
208542b6eecSMark Rustad 	status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
209542b6eecSMark Rustad 	if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
210542b6eecSMark Rustad 		hw_err(hw, "CS4227 EEPROM did not load successfully\n");
211542b6eecSMark Rustad 		return IXGBE_ERR_PHY;
212542b6eecSMark Rustad 	}
213542b6eecSMark Rustad 
214542b6eecSMark Rustad 	return 0;
215542b6eecSMark Rustad }
216542b6eecSMark Rustad 
217542b6eecSMark Rustad /**
218542b6eecSMark Rustad  * ixgbe_check_cs4227 - Check CS4227 and reset as needed
219542b6eecSMark Rustad  * @hw: pointer to hardware structure
220542b6eecSMark Rustad  */
221542b6eecSMark Rustad static void ixgbe_check_cs4227(struct ixgbe_hw *hw)
222542b6eecSMark Rustad {
223542b6eecSMark Rustad 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
224542b6eecSMark Rustad 	s32 status;
225542b6eecSMark Rustad 	u16 value;
226542b6eecSMark Rustad 	u8 retry;
227542b6eecSMark Rustad 
228542b6eecSMark Rustad 	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
229542b6eecSMark Rustad 		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
230542b6eecSMark Rustad 		if (status) {
231542b6eecSMark Rustad 			hw_err(hw, "semaphore failed with %d\n", status);
232542b6eecSMark Rustad 			msleep(IXGBE_CS4227_CHECK_DELAY);
233542b6eecSMark Rustad 			continue;
234542b6eecSMark Rustad 		}
235542b6eecSMark Rustad 
236542b6eecSMark Rustad 		/* Get status of reset flow. */
237542b6eecSMark Rustad 		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
238542b6eecSMark Rustad 		if (!status && value == IXGBE_CS4227_RESET_COMPLETE)
239542b6eecSMark Rustad 			goto out;
240542b6eecSMark Rustad 
241542b6eecSMark Rustad 		if (status || value != IXGBE_CS4227_RESET_PENDING)
242542b6eecSMark Rustad 			break;
243542b6eecSMark Rustad 
244542b6eecSMark Rustad 		/* Reset is pending. Wait and check again. */
245542b6eecSMark Rustad 		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
246542b6eecSMark Rustad 		msleep(IXGBE_CS4227_CHECK_DELAY);
247542b6eecSMark Rustad 	}
2488bf7a7b8SMark Rustad 	/* If still pending, assume other instance failed. */
2498bf7a7b8SMark Rustad 	if (retry == IXGBE_CS4227_RETRIES) {
2508bf7a7b8SMark Rustad 		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
2518bf7a7b8SMark Rustad 		if (status) {
2528bf7a7b8SMark Rustad 			hw_err(hw, "semaphore failed with %d\n", status);
2538bf7a7b8SMark Rustad 			return;
2548bf7a7b8SMark Rustad 		}
2558bf7a7b8SMark Rustad 	}
256542b6eecSMark Rustad 
257542b6eecSMark Rustad 	/* Reset the CS4227. */
258542b6eecSMark Rustad 	status = ixgbe_reset_cs4227(hw);
259542b6eecSMark Rustad 	if (status) {
260542b6eecSMark Rustad 		hw_err(hw, "CS4227 reset failed: %d", status);
261542b6eecSMark Rustad 		goto out;
262542b6eecSMark Rustad 	}
263542b6eecSMark Rustad 
264542b6eecSMark Rustad 	/* Reset takes so long, temporarily release semaphore in case the
265542b6eecSMark Rustad 	 * other driver instance is waiting for the reset indication.
266542b6eecSMark Rustad 	 */
267542b6eecSMark Rustad 	ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
268542b6eecSMark Rustad 			   IXGBE_CS4227_RESET_PENDING);
269542b6eecSMark Rustad 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
270542b6eecSMark Rustad 	usleep_range(10000, 12000);
271542b6eecSMark Rustad 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
272542b6eecSMark Rustad 	if (status) {
273542b6eecSMark Rustad 		hw_err(hw, "semaphore failed with %d", status);
274542b6eecSMark Rustad 		return;
275542b6eecSMark Rustad 	}
276542b6eecSMark Rustad 
277542b6eecSMark Rustad 	/* Record completion for next time. */
278542b6eecSMark Rustad 	status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
279542b6eecSMark Rustad 				    IXGBE_CS4227_RESET_COMPLETE);
280542b6eecSMark Rustad 
281542b6eecSMark Rustad out:
282542b6eecSMark Rustad 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
283542b6eecSMark Rustad 	msleep(hw->eeprom.semaphore_delay);
284542b6eecSMark Rustad }
285542b6eecSMark Rustad 
2866a14ee0cSDon Skidmore /** ixgbe_identify_phy_x550em - Get PHY type based on device id
2876a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
2886a14ee0cSDon Skidmore  *
2896a14ee0cSDon Skidmore  *  Returns error code
2906a14ee0cSDon Skidmore  */
2916a14ee0cSDon Skidmore static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
2926a14ee0cSDon Skidmore {
2936a14ee0cSDon Skidmore 	switch (hw->device_id) {
2942d40cd17SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP:
2952d40cd17SMark Rustad 		if (hw->bus.lan_id)
2962d40cd17SMark Rustad 			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
2972d40cd17SMark Rustad 		else
2982d40cd17SMark Rustad 			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
2992d40cd17SMark Rustad 		return ixgbe_identify_module_generic(hw);
3006a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_SFP:
3016a14ee0cSDon Skidmore 		/* set up for CS4227 usage */
3026a14ee0cSDon Skidmore 		hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
303ab5fe0c5SDon Skidmore 		ixgbe_setup_mux_ctl(hw);
304542b6eecSMark Rustad 		ixgbe_check_cs4227(hw);
30549425dfcSMark Rustad 		/* Fallthrough */
30649425dfcSMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP_N:
3076a14ee0cSDon Skidmore 		return ixgbe_identify_module_generic(hw);
3086a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_KX4:
3096a14ee0cSDon Skidmore 		hw->phy.type = ixgbe_phy_x550em_kx4;
3106a14ee0cSDon Skidmore 		break;
3116a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_KR:
312f572b2c4SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_KR:
313f572b2c4SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_KR_L:
3146a14ee0cSDon Skidmore 		hw->phy.type = ixgbe_phy_x550em_kr;
3156a14ee0cSDon Skidmore 		break;
31692ed8430SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_10G_T:
31792ed8430SDon Skidmore 		if (hw->bus.lan_id)
31892ed8430SDon Skidmore 			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
31992ed8430SDon Skidmore 		else
32092ed8430SDon Skidmore 			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
32192ed8430SDon Skidmore 		/* Fallthrough */
3226a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_1G_T:
3236a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_10G_T:
3246a14ee0cSDon Skidmore 		return ixgbe_identify_phy_generic(hw);
3256a14ee0cSDon Skidmore 	default:
3266a14ee0cSDon Skidmore 		break;
3276a14ee0cSDon Skidmore 	}
3286a14ee0cSDon Skidmore 	return 0;
3296a14ee0cSDon Skidmore }
3306a14ee0cSDon Skidmore 
3316a14ee0cSDon Skidmore static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
3326a14ee0cSDon Skidmore 				     u32 device_type, u16 *phy_data)
3336a14ee0cSDon Skidmore {
3346a14ee0cSDon Skidmore 	return IXGBE_NOT_IMPLEMENTED;
3356a14ee0cSDon Skidmore }
3366a14ee0cSDon Skidmore 
3376a14ee0cSDon Skidmore static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
3386a14ee0cSDon Skidmore 				      u32 device_type, u16 phy_data)
3396a14ee0cSDon Skidmore {
3406a14ee0cSDon Skidmore 	return IXGBE_NOT_IMPLEMENTED;
3416a14ee0cSDon Skidmore }
3426a14ee0cSDon Skidmore 
343b71f6c40SEmil Tantilov /**
344b71f6c40SEmil Tantilov  * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
345b71f6c40SEmil Tantilov  * @hw: pointer to the hardware structure
346b71f6c40SEmil Tantilov  * @addr: I2C bus address to read from
347b71f6c40SEmil Tantilov  * @reg: I2C device register to read from
348b71f6c40SEmil Tantilov  * @val: pointer to location to receive read value
349b71f6c40SEmil Tantilov  *
350b71f6c40SEmil Tantilov  * Returns an error code on error.
351b71f6c40SEmil Tantilov  **/
352b71f6c40SEmil Tantilov static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
353b71f6c40SEmil Tantilov 					   u16 reg, u16 *val)
354b71f6c40SEmil Tantilov {
355b71f6c40SEmil Tantilov 	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true);
356b71f6c40SEmil Tantilov }
357b71f6c40SEmil Tantilov 
358b71f6c40SEmil Tantilov /**
359b71f6c40SEmil Tantilov  * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
360b71f6c40SEmil Tantilov  * @hw: pointer to the hardware structure
361b71f6c40SEmil Tantilov  * @addr: I2C bus address to read from
362b71f6c40SEmil Tantilov  * @reg: I2C device register to read from
363b71f6c40SEmil Tantilov  * @val: pointer to location to receive read value
364b71f6c40SEmil Tantilov  *
365b71f6c40SEmil Tantilov  * Returns an error code on error.
366b71f6c40SEmil Tantilov  **/
367b71f6c40SEmil Tantilov static s32
368b71f6c40SEmil Tantilov ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
369b71f6c40SEmil Tantilov 					 u16 reg, u16 *val)
370b71f6c40SEmil Tantilov {
371b71f6c40SEmil Tantilov 	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false);
372b71f6c40SEmil Tantilov }
373b71f6c40SEmil Tantilov 
374b71f6c40SEmil Tantilov /**
375b71f6c40SEmil Tantilov  * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
376b71f6c40SEmil Tantilov  * @hw: pointer to the hardware structure
377b71f6c40SEmil Tantilov  * @addr: I2C bus address to write to
378b71f6c40SEmil Tantilov  * @reg: I2C device register to write to
379b71f6c40SEmil Tantilov  * @val: value to write
380b71f6c40SEmil Tantilov  *
381b71f6c40SEmil Tantilov  * Returns an error code on error.
382b71f6c40SEmil Tantilov  **/
383b71f6c40SEmil Tantilov static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
384b71f6c40SEmil Tantilov 					    u8 addr, u16 reg, u16 val)
385b71f6c40SEmil Tantilov {
386b71f6c40SEmil Tantilov 	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
387b71f6c40SEmil Tantilov }
388b71f6c40SEmil Tantilov 
389b71f6c40SEmil Tantilov /**
390b71f6c40SEmil Tantilov  * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
391b71f6c40SEmil Tantilov  * @hw: pointer to the hardware structure
392b71f6c40SEmil Tantilov  * @addr: I2C bus address to write to
393b71f6c40SEmil Tantilov  * @reg: I2C device register to write to
394b71f6c40SEmil Tantilov  * @val: value to write
395b71f6c40SEmil Tantilov  *
396b71f6c40SEmil Tantilov  * Returns an error code on error.
397b71f6c40SEmil Tantilov  **/
398b71f6c40SEmil Tantilov static s32
399b71f6c40SEmil Tantilov ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
400b71f6c40SEmil Tantilov 					  u8 addr, u16 reg, u16 val)
401b71f6c40SEmil Tantilov {
402b71f6c40SEmil Tantilov 	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false);
403b71f6c40SEmil Tantilov }
404b71f6c40SEmil Tantilov 
40512c78ef0SMark Rustad /**
40612c78ef0SMark Rustad  * ixgbe_fw_phy_activity - Perform an activity on a PHY
40712c78ef0SMark Rustad  * @hw: pointer to hardware structure
40812c78ef0SMark Rustad  * @activity: activity to perform
40912c78ef0SMark Rustad  * @data: Pointer to 4 32-bit words of data
41012c78ef0SMark Rustad  */
41112c78ef0SMark Rustad s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity,
41212c78ef0SMark Rustad 			  u32 (*data)[FW_PHY_ACT_DATA_COUNT])
41312c78ef0SMark Rustad {
41412c78ef0SMark Rustad 	union {
41512c78ef0SMark Rustad 		struct ixgbe_hic_phy_activity_req cmd;
41612c78ef0SMark Rustad 		struct ixgbe_hic_phy_activity_resp rsp;
41712c78ef0SMark Rustad 	} hic;
41812c78ef0SMark Rustad 	u16 retries = FW_PHY_ACT_RETRIES;
41912c78ef0SMark Rustad 	s32 rc;
42012c78ef0SMark Rustad 	u32 i;
42112c78ef0SMark Rustad 
42212c78ef0SMark Rustad 	do {
42312c78ef0SMark Rustad 		memset(&hic, 0, sizeof(hic));
42412c78ef0SMark Rustad 		hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD;
42512c78ef0SMark Rustad 		hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN;
42612c78ef0SMark Rustad 		hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
42712c78ef0SMark Rustad 		hic.cmd.port_number = hw->bus.lan_id;
42812c78ef0SMark Rustad 		hic.cmd.activity_id = cpu_to_le16(activity);
42912c78ef0SMark Rustad 		for (i = 0; i < ARRAY_SIZE(hic.cmd.data); ++i)
43012c78ef0SMark Rustad 			hic.cmd.data[i] = cpu_to_be32((*data)[i]);
43112c78ef0SMark Rustad 
43212c78ef0SMark Rustad 		rc = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd),
43312c78ef0SMark Rustad 						  IXGBE_HI_COMMAND_TIMEOUT,
43412c78ef0SMark Rustad 						  true);
43512c78ef0SMark Rustad 		if (rc)
43612c78ef0SMark Rustad 			return rc;
43712c78ef0SMark Rustad 		if (hic.rsp.hdr.cmd_or_resp.ret_status ==
43812c78ef0SMark Rustad 		    FW_CEM_RESP_STATUS_SUCCESS) {
43912c78ef0SMark Rustad 			for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
44012c78ef0SMark Rustad 				(*data)[i] = be32_to_cpu(hic.rsp.data[i]);
44112c78ef0SMark Rustad 			return 0;
44212c78ef0SMark Rustad 		}
44312c78ef0SMark Rustad 		usleep_range(20, 30);
44412c78ef0SMark Rustad 		--retries;
44512c78ef0SMark Rustad 	} while (retries > 0);
44612c78ef0SMark Rustad 
44712c78ef0SMark Rustad 	return IXGBE_ERR_HOST_INTERFACE_COMMAND;
44812c78ef0SMark Rustad }
44912c78ef0SMark Rustad 
4506a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params
4516a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
4526a14ee0cSDon Skidmore  *
4536a14ee0cSDon Skidmore  *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
4546a14ee0cSDon Skidmore  *  ixgbe_hw struct in order to set up EEPROM access.
4556a14ee0cSDon Skidmore  **/
4567ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
4576a14ee0cSDon Skidmore {
4586a14ee0cSDon Skidmore 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
4596a14ee0cSDon Skidmore 	u32 eec;
4606a14ee0cSDon Skidmore 	u16 eeprom_size;
4616a14ee0cSDon Skidmore 
4626a14ee0cSDon Skidmore 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
4636a14ee0cSDon Skidmore 		eeprom->semaphore_delay = 10;
4646a14ee0cSDon Skidmore 		eeprom->type = ixgbe_flash;
4656a14ee0cSDon Skidmore 
4669a900ecaSDon Skidmore 		eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
4676a14ee0cSDon Skidmore 		eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
4686a14ee0cSDon Skidmore 				    IXGBE_EEC_SIZE_SHIFT);
469b4f47a48SJacob Keller 		eeprom->word_size = BIT(eeprom_size +
4706a14ee0cSDon Skidmore 					IXGBE_EEPROM_WORD_SIZE_SHIFT);
4716a14ee0cSDon Skidmore 
4726a14ee0cSDon Skidmore 		hw_dbg(hw, "Eeprom params: type = %d, size = %d\n",
4736a14ee0cSDon Skidmore 		       eeprom->type, eeprom->word_size);
4746a14ee0cSDon Skidmore 	}
4756a14ee0cSDon Skidmore 
4766a14ee0cSDon Skidmore 	return 0;
4776a14ee0cSDon Skidmore }
4786a14ee0cSDon Skidmore 
479ae14a1d8SMark Rustad /**
480ae14a1d8SMark Rustad  * ixgbe_iosf_wait - Wait for IOSF command completion
481ae14a1d8SMark Rustad  * @hw: pointer to hardware structure
482ae14a1d8SMark Rustad  * @ctrl: pointer to location to receive final IOSF control value
483ae14a1d8SMark Rustad  *
484ae14a1d8SMark Rustad  * Return: failing status on timeout
485ae14a1d8SMark Rustad  *
486ae14a1d8SMark Rustad  * Note: ctrl can be NULL if the IOSF control register value is not needed
487ae14a1d8SMark Rustad  */
488ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl)
489ae14a1d8SMark Rustad {
490ae14a1d8SMark Rustad 	u32 i, command;
491ae14a1d8SMark Rustad 
492ae14a1d8SMark Rustad 	/* Check every 10 usec to see if the address cycle completed.
493ae14a1d8SMark Rustad 	 * The SB IOSF BUSY bit will clear when the operation is
494ae14a1d8SMark Rustad 	 * complete.
495ae14a1d8SMark Rustad 	 */
496ae14a1d8SMark Rustad 	for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
497ae14a1d8SMark Rustad 		command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
498ae14a1d8SMark Rustad 		if (!(command & IXGBE_SB_IOSF_CTRL_BUSY))
499ae14a1d8SMark Rustad 			break;
500d90b5b0eSMark Rustad 		udelay(10);
501ae14a1d8SMark Rustad 	}
502ae14a1d8SMark Rustad 	if (ctrl)
503ae14a1d8SMark Rustad 		*ctrl = command;
504ae14a1d8SMark Rustad 	if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
505ae14a1d8SMark Rustad 		hw_dbg(hw, "IOSF wait timed out\n");
506ae14a1d8SMark Rustad 		return IXGBE_ERR_PHY;
507ae14a1d8SMark Rustad 	}
508ae14a1d8SMark Rustad 
509ae14a1d8SMark Rustad 	return 0;
510ae14a1d8SMark Rustad }
511ae14a1d8SMark Rustad 
5126a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the
5136a14ee0cSDon Skidmore  *  IOSF device
5146a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
5156a14ee0cSDon Skidmore  *  @reg_addr: 32 bit PHY register to write
5166a14ee0cSDon Skidmore  *  @device_type: 3 bit device type
5176a14ee0cSDon Skidmore  *  @phy_data: Pointer to read data from the register
5186a14ee0cSDon Skidmore  **/
5197ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
5206a14ee0cSDon Skidmore 				       u32 device_type, u32 *data)
5216a14ee0cSDon Skidmore {
522ae14a1d8SMark Rustad 	u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
523ae14a1d8SMark Rustad 	u32 command, error;
524ae14a1d8SMark Rustad 	s32 ret;
525ae14a1d8SMark Rustad 
526ae14a1d8SMark Rustad 	ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
527ae14a1d8SMark Rustad 	if (ret)
528ae14a1d8SMark Rustad 		return ret;
529ae14a1d8SMark Rustad 
530ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, NULL);
531ae14a1d8SMark Rustad 	if (ret)
532ae14a1d8SMark Rustad 		goto out;
5336a14ee0cSDon Skidmore 
5346a14ee0cSDon Skidmore 	command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
5356a14ee0cSDon Skidmore 		   (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
5366a14ee0cSDon Skidmore 
5376a14ee0cSDon Skidmore 	/* Write IOSF control register */
5386a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
5396a14ee0cSDon Skidmore 
540ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, &command);
5416a14ee0cSDon Skidmore 
5426a14ee0cSDon Skidmore 	if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
5436a14ee0cSDon Skidmore 		error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
5446a14ee0cSDon Skidmore 			 IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
5456a14ee0cSDon Skidmore 		hw_dbg(hw, "Failed to read, error %x\n", error);
5466a14ee0cSDon Skidmore 		return IXGBE_ERR_PHY;
5476a14ee0cSDon Skidmore 	}
5486a14ee0cSDon Skidmore 
549ae14a1d8SMark Rustad 	if (!ret)
5506a14ee0cSDon Skidmore 		*data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
5516a14ee0cSDon Skidmore 
552ae14a1d8SMark Rustad out:
553ae14a1d8SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, gssr);
554ae14a1d8SMark Rustad 	return ret;
5556a14ee0cSDon Skidmore }
5566a14ee0cSDon Skidmore 
55749425dfcSMark Rustad /**
55849425dfcSMark Rustad  * ixgbe_get_phy_token - Get the token for shared PHY access
55949425dfcSMark Rustad  * @hw: Pointer to hardware structure
56049425dfcSMark Rustad  */
56149425dfcSMark Rustad static s32 ixgbe_get_phy_token(struct ixgbe_hw *hw)
56249425dfcSMark Rustad {
56349425dfcSMark Rustad 	struct ixgbe_hic_phy_token_req token_cmd;
56449425dfcSMark Rustad 	s32 status;
56549425dfcSMark Rustad 
56649425dfcSMark Rustad 	token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
56749425dfcSMark Rustad 	token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
56849425dfcSMark Rustad 	token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
56949425dfcSMark Rustad 	token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
57049425dfcSMark Rustad 	token_cmd.port_number = hw->bus.lan_id;
57149425dfcSMark Rustad 	token_cmd.command_type = FW_PHY_TOKEN_REQ;
57249425dfcSMark Rustad 	token_cmd.pad = 0;
57349425dfcSMark Rustad 	status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd),
57449425dfcSMark Rustad 					      IXGBE_HI_COMMAND_TIMEOUT,
57549425dfcSMark Rustad 					      true);
57649425dfcSMark Rustad 	if (status)
57749425dfcSMark Rustad 		return status;
57849425dfcSMark Rustad 	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
57949425dfcSMark Rustad 		return 0;
58049425dfcSMark Rustad 	if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY)
58149425dfcSMark Rustad 		return IXGBE_ERR_FW_RESP_INVALID;
58249425dfcSMark Rustad 
58349425dfcSMark Rustad 	return IXGBE_ERR_TOKEN_RETRY;
58449425dfcSMark Rustad }
58549425dfcSMark Rustad 
58649425dfcSMark Rustad /**
58749425dfcSMark Rustad  * ixgbe_put_phy_token - Put the token for shared PHY access
58849425dfcSMark Rustad  * @hw: Pointer to hardware structure
58949425dfcSMark Rustad  */
59049425dfcSMark Rustad static s32 ixgbe_put_phy_token(struct ixgbe_hw *hw)
59149425dfcSMark Rustad {
59249425dfcSMark Rustad 	struct ixgbe_hic_phy_token_req token_cmd;
59349425dfcSMark Rustad 	s32 status;
59449425dfcSMark Rustad 
59549425dfcSMark Rustad 	token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
59649425dfcSMark Rustad 	token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
59749425dfcSMark Rustad 	token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
59849425dfcSMark Rustad 	token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
59949425dfcSMark Rustad 	token_cmd.port_number = hw->bus.lan_id;
60049425dfcSMark Rustad 	token_cmd.command_type = FW_PHY_TOKEN_REL;
60149425dfcSMark Rustad 	token_cmd.pad = 0;
60249425dfcSMark Rustad 	status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd),
60349425dfcSMark Rustad 					      IXGBE_HI_COMMAND_TIMEOUT,
60449425dfcSMark Rustad 					      true);
60549425dfcSMark Rustad 	if (status)
60649425dfcSMark Rustad 		return status;
60749425dfcSMark Rustad 	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
60849425dfcSMark Rustad 		return 0;
60949425dfcSMark Rustad 	return IXGBE_ERR_FW_RESP_INVALID;
61049425dfcSMark Rustad }
61149425dfcSMark Rustad 
61249425dfcSMark Rustad /**
61349425dfcSMark Rustad  *  ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register
61449425dfcSMark Rustad  *  @hw: pointer to hardware structure
61549425dfcSMark Rustad  *  @reg_addr: 32 bit PHY register to write
61649425dfcSMark Rustad  *  @device_type: 3 bit device type
61749425dfcSMark Rustad  *  @data: Data to write to the register
61849425dfcSMark Rustad  **/
61949425dfcSMark Rustad static s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
62049425dfcSMark Rustad 					 __always_unused u32 device_type,
62149425dfcSMark Rustad 					 u32 data)
62249425dfcSMark Rustad {
62349425dfcSMark Rustad 	struct ixgbe_hic_internal_phy_req write_cmd;
62449425dfcSMark Rustad 
62549425dfcSMark Rustad 	memset(&write_cmd, 0, sizeof(write_cmd));
62649425dfcSMark Rustad 	write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD;
62749425dfcSMark Rustad 	write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN;
62849425dfcSMark Rustad 	write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
62949425dfcSMark Rustad 	write_cmd.port_number = hw->bus.lan_id;
63049425dfcSMark Rustad 	write_cmd.command_type = FW_INT_PHY_REQ_WRITE;
63149425dfcSMark Rustad 	write_cmd.address = cpu_to_be16(reg_addr);
63249425dfcSMark Rustad 	write_cmd.write_data = cpu_to_be32(data);
63349425dfcSMark Rustad 
63449425dfcSMark Rustad 	return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd),
63549425dfcSMark Rustad 					    IXGBE_HI_COMMAND_TIMEOUT, false);
63649425dfcSMark Rustad }
63749425dfcSMark Rustad 
63849425dfcSMark Rustad /**
63949425dfcSMark Rustad  *  ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register
64049425dfcSMark Rustad  *  @hw: pointer to hardware structure
64149425dfcSMark Rustad  *  @reg_addr: 32 bit PHY register to write
64249425dfcSMark Rustad  *  @device_type: 3 bit device type
64349425dfcSMark Rustad  *  @data: Pointer to read data from the register
64449425dfcSMark Rustad  **/
64549425dfcSMark Rustad static s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
64649425dfcSMark Rustad 					__always_unused u32 device_type,
64749425dfcSMark Rustad 					u32 *data)
64849425dfcSMark Rustad {
64949425dfcSMark Rustad 	union {
65049425dfcSMark Rustad 		struct ixgbe_hic_internal_phy_req cmd;
65149425dfcSMark Rustad 		struct ixgbe_hic_internal_phy_resp rsp;
65249425dfcSMark Rustad 	} hic;
65349425dfcSMark Rustad 	s32 status;
65449425dfcSMark Rustad 
65549425dfcSMark Rustad 	memset(&hic, 0, sizeof(hic));
65649425dfcSMark Rustad 	hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD;
65749425dfcSMark Rustad 	hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN;
65849425dfcSMark Rustad 	hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
65949425dfcSMark Rustad 	hic.cmd.port_number = hw->bus.lan_id;
66049425dfcSMark Rustad 	hic.cmd.command_type = FW_INT_PHY_REQ_READ;
66149425dfcSMark Rustad 	hic.cmd.address = cpu_to_be16(reg_addr);
66249425dfcSMark Rustad 
66349425dfcSMark Rustad 	status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd),
66449425dfcSMark Rustad 					      IXGBE_HI_COMMAND_TIMEOUT, true);
66549425dfcSMark Rustad 
66649425dfcSMark Rustad 	/* Extract the register value from the response. */
66749425dfcSMark Rustad 	*data = be32_to_cpu(hic.rsp.read_data);
66849425dfcSMark Rustad 
66949425dfcSMark Rustad 	return status;
67049425dfcSMark Rustad }
67149425dfcSMark Rustad 
6726a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif
6736a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
6746a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to read
6756a14ee0cSDon Skidmore  *  @words: number of words
6766a14ee0cSDon Skidmore  *  @data: word(s) read from the EEPROM
6776a14ee0cSDon Skidmore  *
6786a14ee0cSDon Skidmore  *  Reads a 16 bit word(s) from the EEPROM using the hostif.
6796a14ee0cSDon Skidmore  **/
6807ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
6816a14ee0cSDon Skidmore 					    u16 offset, u16 words, u16 *data)
6826a14ee0cSDon Skidmore {
6833efa9ed2SMark Rustad 	const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
6846a14ee0cSDon Skidmore 	struct ixgbe_hic_read_shadow_ram buffer;
6856a14ee0cSDon Skidmore 	u32 current_word = 0;
6866a14ee0cSDon Skidmore 	u16 words_to_read;
6876a14ee0cSDon Skidmore 	s32 status;
6886a14ee0cSDon Skidmore 	u32 i;
6896a14ee0cSDon Skidmore 
6906a14ee0cSDon Skidmore 	/* Take semaphore for the entire operation. */
6913efa9ed2SMark Rustad 	status = hw->mac.ops.acquire_swfw_sync(hw, mask);
6926a14ee0cSDon Skidmore 	if (status) {
6936a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM read buffer - semaphore failed\n");
6946a14ee0cSDon Skidmore 		return status;
6956a14ee0cSDon Skidmore 	}
6966a14ee0cSDon Skidmore 
6976a14ee0cSDon Skidmore 	while (words) {
6986a14ee0cSDon Skidmore 		if (words > FW_MAX_READ_BUFFER_SIZE / 2)
6996a14ee0cSDon Skidmore 			words_to_read = FW_MAX_READ_BUFFER_SIZE / 2;
7006a14ee0cSDon Skidmore 		else
7016a14ee0cSDon Skidmore 			words_to_read = words;
7026a14ee0cSDon Skidmore 
7036a14ee0cSDon Skidmore 		buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
7046a14ee0cSDon Skidmore 		buffer.hdr.req.buf_lenh = 0;
7056a14ee0cSDon Skidmore 		buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
7066a14ee0cSDon Skidmore 		buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
7076a14ee0cSDon Skidmore 
7086a14ee0cSDon Skidmore 		/* convert offset from words to bytes */
7096a14ee0cSDon Skidmore 		buffer.address = cpu_to_be32((offset + current_word) * 2);
7106a14ee0cSDon Skidmore 		buffer.length = cpu_to_be16(words_to_read * 2);
7116a14ee0cSDon Skidmore 
7123efa9ed2SMark Rustad 		status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
7133efa9ed2SMark Rustad 					    IXGBE_HI_COMMAND_TIMEOUT);
7146a14ee0cSDon Skidmore 		if (status) {
7156a14ee0cSDon Skidmore 			hw_dbg(hw, "Host interface command failed\n");
7166a14ee0cSDon Skidmore 			goto out;
7176a14ee0cSDon Skidmore 		}
7186a14ee0cSDon Skidmore 
7196a14ee0cSDon Skidmore 		for (i = 0; i < words_to_read; i++) {
7206a14ee0cSDon Skidmore 			u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) +
7216a14ee0cSDon Skidmore 				  2 * i;
7226a14ee0cSDon Skidmore 			u32 value = IXGBE_READ_REG(hw, reg);
7236a14ee0cSDon Skidmore 
7246a14ee0cSDon Skidmore 			data[current_word] = (u16)(value & 0xffff);
7256a14ee0cSDon Skidmore 			current_word++;
7266a14ee0cSDon Skidmore 			i++;
7276a14ee0cSDon Skidmore 			if (i < words_to_read) {
7286a14ee0cSDon Skidmore 				value >>= 16;
7296a14ee0cSDon Skidmore 				data[current_word] = (u16)(value & 0xffff);
7306a14ee0cSDon Skidmore 				current_word++;
7316a14ee0cSDon Skidmore 			}
7326a14ee0cSDon Skidmore 		}
7336a14ee0cSDon Skidmore 		words -= words_to_read;
7346a14ee0cSDon Skidmore 	}
7356a14ee0cSDon Skidmore 
7366a14ee0cSDon Skidmore out:
7373efa9ed2SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
7386a14ee0cSDon Skidmore 	return status;
7396a14ee0cSDon Skidmore }
7406a14ee0cSDon Skidmore 
7416a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region
7426a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
7436a14ee0cSDon Skidmore  *  @ptr: pointer offset in eeprom
7446a14ee0cSDon Skidmore  *  @size: size of section pointed by ptr, if 0 first word will be used as size
7456a14ee0cSDon Skidmore  *  @csum: address of checksum to update
7466a14ee0cSDon Skidmore  *
7476a14ee0cSDon Skidmore  *  Returns error status for any failure
7486a14ee0cSDon Skidmore  **/
7496a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
7506a14ee0cSDon Skidmore 				   u16 size, u16 *csum, u16 *buffer,
7516a14ee0cSDon Skidmore 				   u32 buffer_size)
7526a14ee0cSDon Skidmore {
7536a14ee0cSDon Skidmore 	u16 buf[256];
7546a14ee0cSDon Skidmore 	s32 status;
7556a14ee0cSDon Skidmore 	u16 length, bufsz, i, start;
7566a14ee0cSDon Skidmore 	u16 *local_buffer;
7576a14ee0cSDon Skidmore 
7586a14ee0cSDon Skidmore 	bufsz = sizeof(buf) / sizeof(buf[0]);
7596a14ee0cSDon Skidmore 
7606a14ee0cSDon Skidmore 	/* Read a chunk at the pointer location */
7616a14ee0cSDon Skidmore 	if (!buffer) {
7626a14ee0cSDon Skidmore 		status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf);
7636a14ee0cSDon Skidmore 		if (status) {
7646a14ee0cSDon Skidmore 			hw_dbg(hw, "Failed to read EEPROM image\n");
7656a14ee0cSDon Skidmore 			return status;
7666a14ee0cSDon Skidmore 		}
7676a14ee0cSDon Skidmore 		local_buffer = buf;
7686a14ee0cSDon Skidmore 	} else {
7696a14ee0cSDon Skidmore 		if (buffer_size < ptr)
7706a14ee0cSDon Skidmore 			return  IXGBE_ERR_PARAM;
7716a14ee0cSDon Skidmore 		local_buffer = &buffer[ptr];
7726a14ee0cSDon Skidmore 	}
7736a14ee0cSDon Skidmore 
7746a14ee0cSDon Skidmore 	if (size) {
7756a14ee0cSDon Skidmore 		start = 0;
7766a14ee0cSDon Skidmore 		length = size;
7776a14ee0cSDon Skidmore 	} else {
7786a14ee0cSDon Skidmore 		start = 1;
7796a14ee0cSDon Skidmore 		length = local_buffer[0];
7806a14ee0cSDon Skidmore 
7816a14ee0cSDon Skidmore 		/* Skip pointer section if length is invalid. */
7826a14ee0cSDon Skidmore 		if (length == 0xFFFF || length == 0 ||
7836a14ee0cSDon Skidmore 		    (ptr + length) >= hw->eeprom.word_size)
7846a14ee0cSDon Skidmore 			return 0;
7856a14ee0cSDon Skidmore 	}
7866a14ee0cSDon Skidmore 
7876a14ee0cSDon Skidmore 	if (buffer && ((u32)start + (u32)length > buffer_size))
7886a14ee0cSDon Skidmore 		return IXGBE_ERR_PARAM;
7896a14ee0cSDon Skidmore 
7906a14ee0cSDon Skidmore 	for (i = start; length; i++, length--) {
7916a14ee0cSDon Skidmore 		if (i == bufsz && !buffer) {
7926a14ee0cSDon Skidmore 			ptr += bufsz;
7936a14ee0cSDon Skidmore 			i = 0;
7946a14ee0cSDon Skidmore 			if (length < bufsz)
7956a14ee0cSDon Skidmore 				bufsz = length;
7966a14ee0cSDon Skidmore 
7976a14ee0cSDon Skidmore 			/* Read a chunk at the pointer location */
7986a14ee0cSDon Skidmore 			status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr,
7996a14ee0cSDon Skidmore 								  bufsz, buf);
8006a14ee0cSDon Skidmore 			if (status) {
8016a14ee0cSDon Skidmore 				hw_dbg(hw, "Failed to read EEPROM image\n");
8026a14ee0cSDon Skidmore 				return status;
8036a14ee0cSDon Skidmore 			}
8046a14ee0cSDon Skidmore 		}
8056a14ee0cSDon Skidmore 		*csum += local_buffer[i];
8066a14ee0cSDon Skidmore 	}
8076a14ee0cSDon Skidmore 	return 0;
8086a14ee0cSDon Skidmore }
8096a14ee0cSDon Skidmore 
8106a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum
8116a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
8126a14ee0cSDon Skidmore  *  @buffer: pointer to buffer containing calculated checksum
8136a14ee0cSDon Skidmore  *  @buffer_size: size of buffer
8146a14ee0cSDon Skidmore  *
8156a14ee0cSDon Skidmore  *  Returns a negative error code on error, or the 16-bit checksum
8166a14ee0cSDon Skidmore  **/
8177ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer,
8187ddbde3fSDon Skidmore 				    u32 buffer_size)
8196a14ee0cSDon Skidmore {
8206a14ee0cSDon Skidmore 	u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1];
8216a14ee0cSDon Skidmore 	u16 *local_buffer;
8226a14ee0cSDon Skidmore 	s32 status;
8236a14ee0cSDon Skidmore 	u16 checksum = 0;
8246a14ee0cSDon Skidmore 	u16 pointer, i, size;
8256a14ee0cSDon Skidmore 
8266a14ee0cSDon Skidmore 	hw->eeprom.ops.init_params(hw);
8276a14ee0cSDon Skidmore 
8286a14ee0cSDon Skidmore 	if (!buffer) {
8296a14ee0cSDon Skidmore 		/* Read pointer area */
8306a14ee0cSDon Skidmore 		status = ixgbe_read_ee_hostif_buffer_X550(hw, 0,
8316a14ee0cSDon Skidmore 						IXGBE_EEPROM_LAST_WORD + 1,
8326a14ee0cSDon Skidmore 						eeprom_ptrs);
8336a14ee0cSDon Skidmore 		if (status) {
8346a14ee0cSDon Skidmore 			hw_dbg(hw, "Failed to read EEPROM image\n");
8356a14ee0cSDon Skidmore 			return status;
8366a14ee0cSDon Skidmore 		}
8376a14ee0cSDon Skidmore 		local_buffer = eeprom_ptrs;
8386a14ee0cSDon Skidmore 	} else {
8396a14ee0cSDon Skidmore 		if (buffer_size < IXGBE_EEPROM_LAST_WORD)
8406a14ee0cSDon Skidmore 			return IXGBE_ERR_PARAM;
8416a14ee0cSDon Skidmore 		local_buffer = buffer;
8426a14ee0cSDon Skidmore 	}
8436a14ee0cSDon Skidmore 
8446a14ee0cSDon Skidmore 	/* For X550 hardware include 0x0-0x41 in the checksum, skip the
8456a14ee0cSDon Skidmore 	 * checksum word itself
8466a14ee0cSDon Skidmore 	 */
8476a14ee0cSDon Skidmore 	for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++)
8486a14ee0cSDon Skidmore 		if (i != IXGBE_EEPROM_CHECKSUM)
8496a14ee0cSDon Skidmore 			checksum += local_buffer[i];
8506a14ee0cSDon Skidmore 
8516a14ee0cSDon Skidmore 	/* Include all data from pointers 0x3, 0x6-0xE.  This excludes the
8526a14ee0cSDon Skidmore 	 * FW, PHY module, and PCIe Expansion/Option ROM pointers.
8536a14ee0cSDon Skidmore 	 */
8546a14ee0cSDon Skidmore 	for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) {
8556a14ee0cSDon Skidmore 		if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
8566a14ee0cSDon Skidmore 			continue;
8576a14ee0cSDon Skidmore 
8586a14ee0cSDon Skidmore 		pointer = local_buffer[i];
8596a14ee0cSDon Skidmore 
8606a14ee0cSDon Skidmore 		/* Skip pointer section if the pointer is invalid. */
8616a14ee0cSDon Skidmore 		if (pointer == 0xFFFF || pointer == 0 ||
8626a14ee0cSDon Skidmore 		    pointer >= hw->eeprom.word_size)
8636a14ee0cSDon Skidmore 			continue;
8646a14ee0cSDon Skidmore 
8656a14ee0cSDon Skidmore 		switch (i) {
8666a14ee0cSDon Skidmore 		case IXGBE_PCIE_GENERAL_PTR:
8676a14ee0cSDon Skidmore 			size = IXGBE_IXGBE_PCIE_GENERAL_SIZE;
8686a14ee0cSDon Skidmore 			break;
8696a14ee0cSDon Skidmore 		case IXGBE_PCIE_CONFIG0_PTR:
8706a14ee0cSDon Skidmore 		case IXGBE_PCIE_CONFIG1_PTR:
8716a14ee0cSDon Skidmore 			size = IXGBE_PCIE_CONFIG_SIZE;
8726a14ee0cSDon Skidmore 			break;
8736a14ee0cSDon Skidmore 		default:
8746a14ee0cSDon Skidmore 			size = 0;
8756a14ee0cSDon Skidmore 			break;
8766a14ee0cSDon Skidmore 		}
8776a14ee0cSDon Skidmore 
8786a14ee0cSDon Skidmore 		status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum,
8796a14ee0cSDon Skidmore 						 buffer, buffer_size);
8806a14ee0cSDon Skidmore 		if (status)
8816a14ee0cSDon Skidmore 			return status;
8826a14ee0cSDon Skidmore 	}
8836a14ee0cSDon Skidmore 
8846a14ee0cSDon Skidmore 	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
8856a14ee0cSDon Skidmore 
8866a14ee0cSDon Skidmore 	return (s32)checksum;
8876a14ee0cSDon Skidmore }
8886a14ee0cSDon Skidmore 
8896a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum
8906a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
8916a14ee0cSDon Skidmore  *
8926a14ee0cSDon Skidmore  *  Returns a negative error code on error, or the 16-bit checksum
8936a14ee0cSDon Skidmore  **/
8947ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
8956a14ee0cSDon Skidmore {
8966a14ee0cSDon Skidmore 	return ixgbe_calc_checksum_X550(hw, NULL, 0);
8976a14ee0cSDon Skidmore }
8986a14ee0cSDon Skidmore 
8996a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command
9006a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
9016a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to read
9026a14ee0cSDon Skidmore  *  @data: word read from the EEPROM
9036a14ee0cSDon Skidmore  *
9046a14ee0cSDon Skidmore  *   Reads a 16 bit word from the EEPROM using the hostif.
9056a14ee0cSDon Skidmore  **/
9067ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data)
9076a14ee0cSDon Skidmore {
9083efa9ed2SMark Rustad 	const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
9093efa9ed2SMark Rustad 	struct ixgbe_hic_read_shadow_ram buffer;
9103efa9ed2SMark Rustad 	s32 status;
9116a14ee0cSDon Skidmore 
9123efa9ed2SMark Rustad 	buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
9133efa9ed2SMark Rustad 	buffer.hdr.req.buf_lenh = 0;
9143efa9ed2SMark Rustad 	buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
9153efa9ed2SMark Rustad 	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
9163efa9ed2SMark Rustad 
9173efa9ed2SMark Rustad 	/* convert offset from words to bytes */
9183efa9ed2SMark Rustad 	buffer.address = cpu_to_be32(offset * 2);
9193efa9ed2SMark Rustad 	/* one word */
9203efa9ed2SMark Rustad 	buffer.length = cpu_to_be16(sizeof(u16));
9213efa9ed2SMark Rustad 
9223efa9ed2SMark Rustad 	status = hw->mac.ops.acquire_swfw_sync(hw, mask);
9233efa9ed2SMark Rustad 	if (status)
9243efa9ed2SMark Rustad 		return status;
9253efa9ed2SMark Rustad 
9263efa9ed2SMark Rustad 	status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
9273efa9ed2SMark Rustad 				    IXGBE_HI_COMMAND_TIMEOUT);
9283efa9ed2SMark Rustad 	if (!status) {
9293efa9ed2SMark Rustad 		*data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
9303efa9ed2SMark Rustad 						  FW_NVM_DATA_OFFSET);
9316a14ee0cSDon Skidmore 	}
9326a14ee0cSDon Skidmore 
9333efa9ed2SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
9346a14ee0cSDon Skidmore 	return status;
9356a14ee0cSDon Skidmore }
9366a14ee0cSDon Skidmore 
9376a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum
9386a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
9396a14ee0cSDon Skidmore  *  @checksum_val: calculated checksum
9406a14ee0cSDon Skidmore  *
9416a14ee0cSDon Skidmore  *  Performs checksum calculation and validates the EEPROM checksum.  If the
9426a14ee0cSDon Skidmore  *  caller does not need checksum_val, the value can be NULL.
9436a14ee0cSDon Skidmore  **/
9447ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw,
9457ddbde3fSDon Skidmore 					       u16 *checksum_val)
9466a14ee0cSDon Skidmore {
9476a14ee0cSDon Skidmore 	s32 status;
9486a14ee0cSDon Skidmore 	u16 checksum;
9496a14ee0cSDon Skidmore 	u16 read_checksum = 0;
9506a14ee0cSDon Skidmore 
9516a14ee0cSDon Skidmore 	/* Read the first word from the EEPROM. If this times out or fails, do
9526a14ee0cSDon Skidmore 	 * not continue or we could be in for a very long wait while every
9536a14ee0cSDon Skidmore 	 * EEPROM read fails
9546a14ee0cSDon Skidmore 	 */
9556a14ee0cSDon Skidmore 	status = hw->eeprom.ops.read(hw, 0, &checksum);
9566a14ee0cSDon Skidmore 	if (status) {
9576a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM read failed\n");
9586a14ee0cSDon Skidmore 		return status;
9596a14ee0cSDon Skidmore 	}
9606a14ee0cSDon Skidmore 
9616a14ee0cSDon Skidmore 	status = hw->eeprom.ops.calc_checksum(hw);
9626a14ee0cSDon Skidmore 	if (status < 0)
9636a14ee0cSDon Skidmore 		return status;
9646a14ee0cSDon Skidmore 
9656a14ee0cSDon Skidmore 	checksum = (u16)(status & 0xffff);
9666a14ee0cSDon Skidmore 
9676a14ee0cSDon Skidmore 	status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
9686a14ee0cSDon Skidmore 					   &read_checksum);
9696a14ee0cSDon Skidmore 	if (status)
9706a14ee0cSDon Skidmore 		return status;
9716a14ee0cSDon Skidmore 
9726a14ee0cSDon Skidmore 	/* Verify read checksum from EEPROM is the same as
9736a14ee0cSDon Skidmore 	 * calculated checksum
9746a14ee0cSDon Skidmore 	 */
9756a14ee0cSDon Skidmore 	if (read_checksum != checksum) {
9766a14ee0cSDon Skidmore 		status = IXGBE_ERR_EEPROM_CHECKSUM;
9776a14ee0cSDon Skidmore 		hw_dbg(hw, "Invalid EEPROM checksum");
9786a14ee0cSDon Skidmore 	}
9796a14ee0cSDon Skidmore 
9806a14ee0cSDon Skidmore 	/* If the user cares, return the calculated checksum */
9816a14ee0cSDon Skidmore 	if (checksum_val)
9826a14ee0cSDon Skidmore 		*checksum_val = checksum;
9836a14ee0cSDon Skidmore 
9846a14ee0cSDon Skidmore 	return status;
9856a14ee0cSDon Skidmore }
9866a14ee0cSDon Skidmore 
9876a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
9886a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
9896a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to write
9906a14ee0cSDon Skidmore  *  @data: word write to the EEPROM
9916a14ee0cSDon Skidmore  *
9926a14ee0cSDon Skidmore  *  Write a 16 bit word to the EEPROM using the hostif.
9936a14ee0cSDon Skidmore  **/
9947ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
9957ddbde3fSDon Skidmore 					   u16 data)
9966a14ee0cSDon Skidmore {
9976a14ee0cSDon Skidmore 	s32 status;
9986a14ee0cSDon Skidmore 	struct ixgbe_hic_write_shadow_ram buffer;
9996a14ee0cSDon Skidmore 
10006a14ee0cSDon Skidmore 	buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
10016a14ee0cSDon Skidmore 	buffer.hdr.req.buf_lenh = 0;
10026a14ee0cSDon Skidmore 	buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
10036a14ee0cSDon Skidmore 	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
10046a14ee0cSDon Skidmore 
10056a14ee0cSDon Skidmore 	/* one word */
10066a14ee0cSDon Skidmore 	buffer.length = cpu_to_be16(sizeof(u16));
10076a14ee0cSDon Skidmore 	buffer.data = data;
10086a14ee0cSDon Skidmore 	buffer.address = cpu_to_be32(offset * 2);
10096a14ee0cSDon Skidmore 
10105cffde30SMark Rustad 	status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer),
10116a14ee0cSDon Skidmore 					      IXGBE_HI_COMMAND_TIMEOUT, false);
10126a14ee0cSDon Skidmore 	return status;
10136a14ee0cSDon Skidmore }
10146a14ee0cSDon Skidmore 
10156a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
10166a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
10176a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to write
10186a14ee0cSDon Skidmore  *  @data: word write to the EEPROM
10196a14ee0cSDon Skidmore  *
10206a14ee0cSDon Skidmore  *  Write a 16 bit word to the EEPROM using the hostif.
10216a14ee0cSDon Skidmore  **/
10227ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data)
10236a14ee0cSDon Skidmore {
10246a14ee0cSDon Skidmore 	s32 status = 0;
10256a14ee0cSDon Skidmore 
10266a14ee0cSDon Skidmore 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
10276a14ee0cSDon Skidmore 		status = ixgbe_write_ee_hostif_data_X550(hw, offset, data);
10286a14ee0cSDon Skidmore 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
10296a14ee0cSDon Skidmore 	} else {
10306a14ee0cSDon Skidmore 		hw_dbg(hw, "write ee hostif failed to get semaphore");
10316a14ee0cSDon Skidmore 		status = IXGBE_ERR_SWFW_SYNC;
10326a14ee0cSDon Skidmore 	}
10336a14ee0cSDon Skidmore 
10346a14ee0cSDon Skidmore 	return status;
10356a14ee0cSDon Skidmore }
10366a14ee0cSDon Skidmore 
10376a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device
10386a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
10396a14ee0cSDon Skidmore  *
10406a14ee0cSDon Skidmore  *  Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash.
10416a14ee0cSDon Skidmore  **/
10427ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw)
10436a14ee0cSDon Skidmore {
10446a14ee0cSDon Skidmore 	s32 status = 0;
10456a14ee0cSDon Skidmore 	union ixgbe_hic_hdr2 buffer;
10466a14ee0cSDon Skidmore 
10476a14ee0cSDon Skidmore 	buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD;
10486a14ee0cSDon Skidmore 	buffer.req.buf_lenh = 0;
10496a14ee0cSDon Skidmore 	buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN;
10506a14ee0cSDon Skidmore 	buffer.req.checksum = FW_DEFAULT_CHECKSUM;
10516a14ee0cSDon Skidmore 
10525cffde30SMark Rustad 	status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer),
10536a14ee0cSDon Skidmore 					      IXGBE_HI_COMMAND_TIMEOUT, false);
10546a14ee0cSDon Skidmore 	return status;
10556a14ee0cSDon Skidmore }
10566a14ee0cSDon Skidmore 
1057454c65ddSDon Skidmore /**
1058454c65ddSDon Skidmore  * ixgbe_get_bus_info_X550em - Set PCI bus info
1059454c65ddSDon Skidmore  * @hw: pointer to hardware structure
1060454c65ddSDon Skidmore  *
1061454c65ddSDon Skidmore  * Sets bus link width and speed to unknown because X550em is
1062454c65ddSDon Skidmore  * not a PCI device.
1063454c65ddSDon Skidmore  **/
1064454c65ddSDon Skidmore static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
1065454c65ddSDon Skidmore {
1066f9328bc6SDon Skidmore 	hw->bus.type  = ixgbe_bus_type_internal;
1067454c65ddSDon Skidmore 	hw->bus.width = ixgbe_bus_width_unknown;
1068454c65ddSDon Skidmore 	hw->bus.speed = ixgbe_bus_speed_unknown;
1069454c65ddSDon Skidmore 
1070454c65ddSDon Skidmore 	hw->mac.ops.set_lan_id(hw);
1071454c65ddSDon Skidmore 
1072454c65ddSDon Skidmore 	return 0;
1073454c65ddSDon Skidmore }
1074454c65ddSDon Skidmore 
10751f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit
10761f9ac57cSDon Skidmore  *
10771f9ac57cSDon Skidmore  *  Enables the Rx DMA unit for x550
10781f9ac57cSDon Skidmore  **/
10791f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
10801f9ac57cSDon Skidmore {
10811f9ac57cSDon Skidmore 	u32 rxctrl, pfdtxgswc;
10821f9ac57cSDon Skidmore 	s32 status;
10831f9ac57cSDon Skidmore 	struct ixgbe_hic_disable_rxen fw_cmd;
10841f9ac57cSDon Skidmore 
10851f9ac57cSDon Skidmore 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
10861f9ac57cSDon Skidmore 	if (rxctrl & IXGBE_RXCTRL_RXEN) {
10871f9ac57cSDon Skidmore 		pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
10881f9ac57cSDon Skidmore 		if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
10891f9ac57cSDon Skidmore 			pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
10901f9ac57cSDon Skidmore 			IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
10911f9ac57cSDon Skidmore 			hw->mac.set_lben = true;
10921f9ac57cSDon Skidmore 		} else {
10931f9ac57cSDon Skidmore 			hw->mac.set_lben = false;
10941f9ac57cSDon Skidmore 		}
10951f9ac57cSDon Skidmore 
10961f9ac57cSDon Skidmore 		fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD;
10971f9ac57cSDon Skidmore 		fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN;
10981f9ac57cSDon Skidmore 		fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
10993775b814SMark Rustad 		fw_cmd.port_number = hw->bus.lan_id;
11001f9ac57cSDon Skidmore 
11015cffde30SMark Rustad 		status = ixgbe_host_interface_command(hw, &fw_cmd,
11021f9ac57cSDon Skidmore 					sizeof(struct ixgbe_hic_disable_rxen),
11031f9ac57cSDon Skidmore 					IXGBE_HI_COMMAND_TIMEOUT, true);
11041f9ac57cSDon Skidmore 
11051f9ac57cSDon Skidmore 		/* If we fail - disable RX using register write */
11061f9ac57cSDon Skidmore 		if (status) {
11071f9ac57cSDon Skidmore 			rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
11081f9ac57cSDon Skidmore 			if (rxctrl & IXGBE_RXCTRL_RXEN) {
11091f9ac57cSDon Skidmore 				rxctrl &= ~IXGBE_RXCTRL_RXEN;
11101f9ac57cSDon Skidmore 				IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
11111f9ac57cSDon Skidmore 			}
11121f9ac57cSDon Skidmore 		}
11131f9ac57cSDon Skidmore 	}
11141f9ac57cSDon Skidmore }
11151f9ac57cSDon Skidmore 
11166a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash
11176a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
11186a14ee0cSDon Skidmore  *
11196a14ee0cSDon Skidmore  *  After writing EEPROM to shadow RAM using EEWR register, software calculates
11206a14ee0cSDon Skidmore  *  checksum and updates the EEPROM and instructs the hardware to update
11216a14ee0cSDon Skidmore  *  the flash.
11226a14ee0cSDon Skidmore  **/
11237ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw)
11246a14ee0cSDon Skidmore {
11256a14ee0cSDon Skidmore 	s32 status;
11266a14ee0cSDon Skidmore 	u16 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 = ixgbe_read_ee_hostif_X550(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 = ixgbe_calc_eeprom_checksum_X550(hw);
11396a14ee0cSDon Skidmore 	if (status < 0)
11406a14ee0cSDon Skidmore 		return status;
11416a14ee0cSDon Skidmore 
11426a14ee0cSDon Skidmore 	checksum = (u16)(status & 0xffff);
11436a14ee0cSDon Skidmore 
11446a14ee0cSDon Skidmore 	status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
11456a14ee0cSDon Skidmore 					    checksum);
11466a14ee0cSDon Skidmore 	if (status)
11476a14ee0cSDon Skidmore 		return status;
11486a14ee0cSDon Skidmore 
11496a14ee0cSDon Skidmore 	status = ixgbe_update_flash_X550(hw);
11506a14ee0cSDon Skidmore 
11516a14ee0cSDon Skidmore 	return status;
11526a14ee0cSDon Skidmore }
11536a14ee0cSDon Skidmore 
11546a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif
11556a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
11566a14ee0cSDon Skidmore  *  @offset: offset of  word in the EEPROM to write
11576a14ee0cSDon Skidmore  *  @words: number of words
11586a14ee0cSDon Skidmore  *  @data: word(s) write to the EEPROM
11596a14ee0cSDon Skidmore  *
11606a14ee0cSDon Skidmore  *
11616a14ee0cSDon Skidmore  *  Write a 16 bit word(s) to the EEPROM using the hostif.
11626a14ee0cSDon Skidmore  **/
11637ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
11647ddbde3fSDon Skidmore 					     u16 offset, u16 words,
11657ddbde3fSDon Skidmore 					     u16 *data)
11666a14ee0cSDon Skidmore {
11676a14ee0cSDon Skidmore 	s32 status = 0;
11686a14ee0cSDon Skidmore 	u32 i = 0;
11696a14ee0cSDon Skidmore 
11706a14ee0cSDon Skidmore 	/* Take semaphore for the entire operation. */
11716a14ee0cSDon Skidmore 	status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
11726a14ee0cSDon Skidmore 	if (status) {
11736a14ee0cSDon Skidmore 		hw_dbg(hw, "EEPROM write buffer - semaphore failed\n");
11746a14ee0cSDon Skidmore 		return status;
11756a14ee0cSDon Skidmore 	}
11766a14ee0cSDon Skidmore 
11776a14ee0cSDon Skidmore 	for (i = 0; i < words; i++) {
11786a14ee0cSDon Skidmore 		status = ixgbe_write_ee_hostif_data_X550(hw, offset + i,
11796a14ee0cSDon Skidmore 							 data[i]);
11806a14ee0cSDon Skidmore 		if (status) {
11816a14ee0cSDon Skidmore 			hw_dbg(hw, "Eeprom buffered write failed\n");
11826a14ee0cSDon Skidmore 			break;
11836a14ee0cSDon Skidmore 		}
11846a14ee0cSDon Skidmore 	}
11856a14ee0cSDon Skidmore 
11866a14ee0cSDon Skidmore 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
11876a14ee0cSDon Skidmore 
11886a14ee0cSDon Skidmore 	return status;
11896a14ee0cSDon Skidmore }
11906a14ee0cSDon Skidmore 
11916a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the
11926a14ee0cSDon Skidmore  *  IOSF device
11936a14ee0cSDon Skidmore  *
11946a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
11956a14ee0cSDon Skidmore  *  @reg_addr: 32 bit PHY register to write
11966a14ee0cSDon Skidmore  *  @device_type: 3 bit device type
11976a14ee0cSDon Skidmore  *  @data: Data to write to the register
11986a14ee0cSDon Skidmore  **/
11997ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
12006a14ee0cSDon Skidmore 					u32 device_type, u32 data)
12016a14ee0cSDon Skidmore {
1202ae14a1d8SMark Rustad 	u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
1203ae14a1d8SMark Rustad 	u32 command, error;
1204ae14a1d8SMark Rustad 	s32 ret;
1205ae14a1d8SMark Rustad 
1206ae14a1d8SMark Rustad 	ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
1207ae14a1d8SMark Rustad 	if (ret)
1208ae14a1d8SMark Rustad 		return ret;
1209ae14a1d8SMark Rustad 
1210ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, NULL);
1211ae14a1d8SMark Rustad 	if (ret)
1212ae14a1d8SMark Rustad 		goto out;
12136a14ee0cSDon Skidmore 
12146a14ee0cSDon Skidmore 	command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
12156a14ee0cSDon Skidmore 		   (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
12166a14ee0cSDon Skidmore 
12176a14ee0cSDon Skidmore 	/* Write IOSF control register */
12186a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
12196a14ee0cSDon Skidmore 
12206a14ee0cSDon Skidmore 	/* Write IOSF data register */
12216a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data);
12226a14ee0cSDon Skidmore 
1223ae14a1d8SMark Rustad 	ret = ixgbe_iosf_wait(hw, &command);
12246a14ee0cSDon Skidmore 
12256a14ee0cSDon Skidmore 	if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
12266a14ee0cSDon Skidmore 		error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
12276a14ee0cSDon Skidmore 			 IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
12286a14ee0cSDon Skidmore 		hw_dbg(hw, "Failed to write, error %x\n", error);
12296a14ee0cSDon Skidmore 		return IXGBE_ERR_PHY;
12306a14ee0cSDon Skidmore 	}
12316a14ee0cSDon Skidmore 
1232ae14a1d8SMark Rustad out:
1233ae14a1d8SMark Rustad 	hw->mac.ops.release_swfw_sync(hw, gssr);
1234ae14a1d8SMark Rustad 	return ret;
12356a14ee0cSDon Skidmore }
12366a14ee0cSDon Skidmore 
12370c1b7de4SDon Skidmore /**
12380c1b7de4SDon Skidmore  *  ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration
12396a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
12406a14ee0cSDon Skidmore  *
12410c1b7de4SDon Skidmore  *  iXfI configuration needed for ixgbe_mac_X550EM_x devices.
12426a14ee0cSDon Skidmore  **/
12430c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)
12446a14ee0cSDon Skidmore {
12456a14ee0cSDon Skidmore 	s32 status;
12466a14ee0cSDon Skidmore 	u32 reg_val;
12476a14ee0cSDon Skidmore 
12486a14ee0cSDon Skidmore 	/* Disable training protocol FSM. */
12496a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
12506a14ee0cSDon Skidmore 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
12516a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
12526a14ee0cSDon Skidmore 	if (status)
12536a14ee0cSDon Skidmore 		return status;
12546a14ee0cSDon Skidmore 
12556a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL;
12566a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
12576a14ee0cSDon Skidmore 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
12586a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
12596a14ee0cSDon Skidmore 	if (status)
12606a14ee0cSDon Skidmore 		return status;
12616a14ee0cSDon Skidmore 
12626a14ee0cSDon Skidmore 	/* Disable Flex from training TXFFE. */
12636a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
12646a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
12656a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
12666a14ee0cSDon Skidmore 	if (status)
12676a14ee0cSDon Skidmore 		return status;
12686a14ee0cSDon Skidmore 
12696a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
12706a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
12716a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
12726a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
12736a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
12746a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
12756a14ee0cSDon Skidmore 	if (status)
12766a14ee0cSDon Skidmore 		return status;
12776a14ee0cSDon Skidmore 
12786a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
12796a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
12806a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
12816a14ee0cSDon Skidmore 	if (status)
12826a14ee0cSDon Skidmore 		return status;
12836a14ee0cSDon Skidmore 
12846a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
12856a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
12866a14ee0cSDon Skidmore 	reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
12876a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
12886a14ee0cSDon Skidmore 				IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
12896a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
12906a14ee0cSDon Skidmore 	if (status)
12916a14ee0cSDon Skidmore 		return status;
12926a14ee0cSDon Skidmore 
12936a14ee0cSDon Skidmore 	/* Enable override for coefficients. */
12946a14ee0cSDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
12956a14ee0cSDon Skidmore 				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
12966a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
12976a14ee0cSDon Skidmore 	if (status)
12986a14ee0cSDon Skidmore 		return status;
12996a14ee0cSDon Skidmore 
13006a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN;
13016a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN;
13026a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN;
13036a14ee0cSDon Skidmore 	reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN;
13046a14ee0cSDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
13056a14ee0cSDon Skidmore 				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
13066a14ee0cSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
13070c1b7de4SDon Skidmore 	return status;
13080c1b7de4SDon Skidmore }
13090c1b7de4SDon Skidmore 
1310470739b5SDon Skidmore /**
1311470739b5SDon Skidmore  *  ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the
1312470739b5SDon Skidmore  *  internal PHY
1313470739b5SDon Skidmore  *  @hw: pointer to hardware structure
1314470739b5SDon Skidmore  **/
1315470739b5SDon Skidmore static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
1316470739b5SDon Skidmore {
1317470739b5SDon Skidmore 	s32 status;
1318470739b5SDon Skidmore 	u32 link_ctrl;
1319470739b5SDon Skidmore 
1320470739b5SDon Skidmore 	/* Restart auto-negotiation. */
1321470739b5SDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
1322470739b5SDon Skidmore 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1323470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl);
1324470739b5SDon Skidmore 
1325470739b5SDon Skidmore 	if (status) {
1326470739b5SDon Skidmore 		hw_dbg(hw, "Auto-negotiation did not complete\n");
1327470739b5SDon Skidmore 		return status;
1328470739b5SDon Skidmore 	}
1329470739b5SDon Skidmore 
1330470739b5SDon Skidmore 	link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
1331470739b5SDon Skidmore 	status = hw->mac.ops.write_iosf_sb_reg(hw,
1332470739b5SDon Skidmore 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1333470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl);
1334470739b5SDon Skidmore 
1335470739b5SDon Skidmore 	if (hw->mac.type == ixgbe_mac_x550em_a) {
1336470739b5SDon Skidmore 		u32 flx_mask_st20;
1337470739b5SDon Skidmore 
1338470739b5SDon Skidmore 		/* Indicate to FW that AN restart has been asserted */
1339470739b5SDon Skidmore 		status = hw->mac.ops.read_iosf_sb_reg(hw,
1340470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1341470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20);
1342470739b5SDon Skidmore 
1343470739b5SDon Skidmore 		if (status) {
1344470739b5SDon Skidmore 			hw_dbg(hw, "Auto-negotiation did not complete\n");
1345470739b5SDon Skidmore 			return status;
1346470739b5SDon Skidmore 		}
1347470739b5SDon Skidmore 
1348470739b5SDon Skidmore 		flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART;
1349470739b5SDon Skidmore 		status = hw->mac.ops.write_iosf_sb_reg(hw,
1350470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1351470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20);
1352470739b5SDon Skidmore 	}
1353470739b5SDon Skidmore 
1354470739b5SDon Skidmore 	return status;
1355470739b5SDon Skidmore }
1356470739b5SDon Skidmore 
13570c1b7de4SDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
13580c1b7de4SDon Skidmore  *  @hw: pointer to hardware structure
13590c1b7de4SDon Skidmore  *  @speed: the link speed to force
13600c1b7de4SDon Skidmore  *
13610c1b7de4SDon Skidmore  *  Configures the integrated KR PHY to use iXFI mode. Used to connect an
13620c1b7de4SDon Skidmore  *  internal and external PHY at a specific speed, without autonegotiation.
13630c1b7de4SDon Skidmore  **/
13640c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
13650c1b7de4SDon Skidmore {
13660c1b7de4SDon Skidmore 	s32 status;
13670c1b7de4SDon Skidmore 	u32 reg_val;
13680c1b7de4SDon Skidmore 
13690c1b7de4SDon Skidmore 	/* Disable AN and force speed to 10G Serial. */
13700c1b7de4SDon Skidmore 	status = ixgbe_read_iosf_sb_reg_x550(hw,
13710c1b7de4SDon Skidmore 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
13720c1b7de4SDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
13736a14ee0cSDon Skidmore 	if (status)
13746a14ee0cSDon Skidmore 		return status;
13756a14ee0cSDon Skidmore 
13760c1b7de4SDon Skidmore 	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
13770c1b7de4SDon Skidmore 	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
13780c1b7de4SDon Skidmore 
13790c1b7de4SDon Skidmore 	/* Select forced link speed for internal PHY. */
13800c1b7de4SDon Skidmore 	switch (*speed) {
13810c1b7de4SDon Skidmore 	case IXGBE_LINK_SPEED_10GB_FULL:
13820c1b7de4SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
13830c1b7de4SDon Skidmore 		break;
13840c1b7de4SDon Skidmore 	case IXGBE_LINK_SPEED_1GB_FULL:
13850c1b7de4SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
13860c1b7de4SDon Skidmore 		break;
13870c1b7de4SDon Skidmore 	default:
13880c1b7de4SDon Skidmore 		/* Other link speeds are not supported by internal KR PHY. */
13890c1b7de4SDon Skidmore 		return IXGBE_ERR_LINK_SETUP;
13900c1b7de4SDon Skidmore 	}
13910c1b7de4SDon Skidmore 
13920c1b7de4SDon Skidmore 	status = ixgbe_write_iosf_sb_reg_x550(hw,
13930c1b7de4SDon Skidmore 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
13940c1b7de4SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
13950c1b7de4SDon Skidmore 	if (status)
13960c1b7de4SDon Skidmore 		return status;
13970c1b7de4SDon Skidmore 
13980c1b7de4SDon Skidmore 	/* Additional configuration needed for x550em_x */
13990c1b7de4SDon Skidmore 	if (hw->mac.type == ixgbe_mac_X550EM_x) {
14000c1b7de4SDon Skidmore 		status = ixgbe_setup_ixfi_x550em_x(hw);
14010c1b7de4SDon Skidmore 		if (status)
14020c1b7de4SDon Skidmore 			return status;
14030c1b7de4SDon Skidmore 	}
14040c1b7de4SDon Skidmore 
14056a14ee0cSDon Skidmore 	/* Toggle port SW reset by AN reset. */
1406470739b5SDon Skidmore 	status = ixgbe_restart_an_internal_phy_x550em(hw);
14076a14ee0cSDon Skidmore 
14086a14ee0cSDon Skidmore 	return status;
14096a14ee0cSDon Skidmore }
14106a14ee0cSDon Skidmore 
1411c3dc4c09SDon Skidmore /**
1412e23f3336SMark Rustad  *  ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported
1413e23f3336SMark Rustad  *  @hw: pointer to hardware structure
1414e23f3336SMark Rustad  *  @linear: true if SFP module is linear
1415e23f3336SMark Rustad  */
1416e23f3336SMark Rustad static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear)
1417e23f3336SMark Rustad {
1418e23f3336SMark Rustad 	switch (hw->phy.sfp_type) {
1419e23f3336SMark Rustad 	case ixgbe_sfp_type_not_present:
1420e23f3336SMark Rustad 		return IXGBE_ERR_SFP_NOT_PRESENT;
1421e23f3336SMark Rustad 	case ixgbe_sfp_type_da_cu_core0:
1422e23f3336SMark Rustad 	case ixgbe_sfp_type_da_cu_core1:
1423e23f3336SMark Rustad 		*linear = true;
1424e23f3336SMark Rustad 		break;
1425e23f3336SMark Rustad 	case ixgbe_sfp_type_srlr_core0:
1426e23f3336SMark Rustad 	case ixgbe_sfp_type_srlr_core1:
1427e23f3336SMark Rustad 	case ixgbe_sfp_type_da_act_lmt_core0:
1428e23f3336SMark Rustad 	case ixgbe_sfp_type_da_act_lmt_core1:
1429e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_sx_core0:
1430e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_sx_core1:
1431e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_lx_core0:
1432e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_lx_core1:
1433e23f3336SMark Rustad 		*linear = false;
1434e23f3336SMark Rustad 		break;
1435e23f3336SMark Rustad 	case ixgbe_sfp_type_unknown:
1436e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_cu_core0:
1437e23f3336SMark Rustad 	case ixgbe_sfp_type_1g_cu_core1:
1438e23f3336SMark Rustad 	default:
1439e23f3336SMark Rustad 		return IXGBE_ERR_SFP_NOT_SUPPORTED;
1440e23f3336SMark Rustad 	}
1441e23f3336SMark Rustad 
1442e23f3336SMark Rustad 	return 0;
1443e23f3336SMark Rustad }
1444e23f3336SMark Rustad 
1445e23f3336SMark Rustad /**
14466d373a1bSMark Rustad  *  ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP.
14476d373a1bSMark Rustad  *  @hw: pointer to hardware structure
14486d373a1bSMark Rustad  *
14496d373a1bSMark Rustad  *  Configures the extern PHY and the integrated KR PHY for SFP support.
14506d373a1bSMark Rustad  */
14516d373a1bSMark Rustad static s32
14526d373a1bSMark Rustad ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
14536d373a1bSMark Rustad 				ixgbe_link_speed speed,
14546d373a1bSMark Rustad 				__always_unused bool autoneg_wait_to_complete)
14556d373a1bSMark Rustad {
1456e23f3336SMark Rustad 	s32 status;
1457812d7dffSEmil Tantilov 	u16 reg_slice, reg_val;
1458e23f3336SMark Rustad 	bool setup_linear = false;
1459e23f3336SMark Rustad 
1460e23f3336SMark Rustad 	/* Check if SFP module is supported and linear */
1461e23f3336SMark Rustad 	status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
1462e23f3336SMark Rustad 
1463e23f3336SMark Rustad 	/* If no SFP module present, then return success. Return success since
1464e23f3336SMark Rustad 	 * there is no reason to configure CS4227 and SFP not present error is
1465e23f3336SMark Rustad 	 * not accepted in the setup MAC link flow.
1466e23f3336SMark Rustad 	 */
1467e23f3336SMark Rustad 	if (status == IXGBE_ERR_SFP_NOT_PRESENT)
1468e23f3336SMark Rustad 		return 0;
1469e23f3336SMark Rustad 
1470e23f3336SMark Rustad 	if (status)
1471e23f3336SMark Rustad 		return status;
1472e23f3336SMark Rustad 
1473d91e3a7dSMark Rustad 	/* Configure internal PHY for KR/KX. */
1474812d7dffSEmil Tantilov 	ixgbe_setup_kr_speed_x550em(hw, speed);
1475e23f3336SMark Rustad 
1476d91e3a7dSMark Rustad 	/* Configure CS4227 LINE side to proper mode. */
1477812d7dffSEmil Tantilov 	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
1478d91e3a7dSMark Rustad 	if (setup_linear)
1479812d7dffSEmil Tantilov 		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
1480d91e3a7dSMark Rustad 	else
1481812d7dffSEmil Tantilov 		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
1482b71f6c40SEmil Tantilov 
1483b71f6c40SEmil Tantilov 	status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice,
1484b71f6c40SEmil Tantilov 					 reg_val);
1485b71f6c40SEmil Tantilov 
1486e23f3336SMark Rustad 	return status;
14876d373a1bSMark Rustad }
14886d373a1bSMark Rustad 
14896d373a1bSMark Rustad /**
1490470739b5SDon Skidmore  * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode
1491470739b5SDon Skidmore  * @hw: pointer to hardware structure
1492470739b5SDon Skidmore  * @speed: the link speed to force
1493470739b5SDon Skidmore  *
1494470739b5SDon Skidmore  * Configures the integrated PHY for native SFI mode. Used to connect the
1495470739b5SDon Skidmore  * internal PHY directly to an SFP cage, without autonegotiation.
1496470739b5SDon Skidmore  **/
1497470739b5SDon Skidmore static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
1498470739b5SDon Skidmore {
1499470739b5SDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
1500470739b5SDon Skidmore 	s32 status;
1501470739b5SDon Skidmore 	u32 reg_val;
1502470739b5SDon Skidmore 
1503470739b5SDon Skidmore 	/* Disable all AN and force speed to 10G Serial. */
1504470739b5SDon Skidmore 	status = mac->ops.read_iosf_sb_reg(hw,
1505470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1506470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
1507470739b5SDon Skidmore 	if (status)
1508470739b5SDon Skidmore 		return status;
1509470739b5SDon Skidmore 
1510470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
1511470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
1512470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
1513470739b5SDon Skidmore 	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
1514470739b5SDon Skidmore 
1515470739b5SDon Skidmore 	/* Select forced link speed for internal PHY. */
1516470739b5SDon Skidmore 	switch (*speed) {
1517470739b5SDon Skidmore 	case IXGBE_LINK_SPEED_10GB_FULL:
1518470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G;
1519470739b5SDon Skidmore 		break;
1520470739b5SDon Skidmore 	case IXGBE_LINK_SPEED_1GB_FULL:
1521470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
1522470739b5SDon Skidmore 		break;
1523470739b5SDon Skidmore 	default:
1524470739b5SDon Skidmore 		/* Other link speeds are not supported by internal PHY. */
1525470739b5SDon Skidmore 		return IXGBE_ERR_LINK_SETUP;
1526470739b5SDon Skidmore 	}
1527470739b5SDon Skidmore 
1528470739b5SDon Skidmore 	status = mac->ops.write_iosf_sb_reg(hw,
1529470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1530470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
1531470739b5SDon Skidmore 
1532470739b5SDon Skidmore 	/* Toggle port SW reset by AN reset. */
1533470739b5SDon Skidmore 	status = ixgbe_restart_an_internal_phy_x550em(hw);
1534470739b5SDon Skidmore 
1535470739b5SDon Skidmore 	return status;
1536470739b5SDon Skidmore }
1537470739b5SDon Skidmore 
1538470739b5SDon Skidmore /**
15392d40cd17SMark Rustad  * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP
15402d40cd17SMark Rustad  * @hw: pointer to hardware structure
15412d40cd17SMark Rustad  *
15422d40cd17SMark Rustad  * Configure the the integrated PHY for native SFP support.
15432d40cd17SMark Rustad  */
15442d40cd17SMark Rustad static s32
15452d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed,
15462d40cd17SMark Rustad 			   __always_unused bool autoneg_wait_to_complete)
15472d40cd17SMark Rustad {
15482d40cd17SMark Rustad 	bool setup_linear = false;
15492d40cd17SMark Rustad 	u32 reg_phy_int;
1550470739b5SDon Skidmore 	s32 ret_val;
15512d40cd17SMark Rustad 
15522d40cd17SMark Rustad 	/* Check if SFP module is supported and linear */
1553470739b5SDon Skidmore 	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
15542d40cd17SMark Rustad 
15552d40cd17SMark Rustad 	/* If no SFP module present, then return success. Return success since
15562d40cd17SMark Rustad 	 * SFP not present error is not excepted in the setup MAC link flow.
15572d40cd17SMark Rustad 	 */
1558470739b5SDon Skidmore 	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
15592d40cd17SMark Rustad 		return 0;
15602d40cd17SMark Rustad 
1561470739b5SDon Skidmore 	if (!ret_val)
1562470739b5SDon Skidmore 		return ret_val;
15632d40cd17SMark Rustad 
1564470739b5SDon Skidmore 	/* Configure internal PHY for native SFI based on module type */
1565470739b5SDon Skidmore 	ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
1566470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1567470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
1568470739b5SDon Skidmore 	if (!ret_val)
1569470739b5SDon Skidmore 		return ret_val;
15702d40cd17SMark Rustad 
1571470739b5SDon Skidmore 	reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA;
1572470739b5SDon Skidmore 	if (!setup_linear)
1573470739b5SDon Skidmore 		reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR;
15742d40cd17SMark Rustad 
1575470739b5SDon Skidmore 	ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
1576470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1577470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
1578470739b5SDon Skidmore 	if (!ret_val)
1579470739b5SDon Skidmore 		return ret_val;
15802d40cd17SMark Rustad 
1581470739b5SDon Skidmore 	/* Setup SFI internal link. */
1582470739b5SDon Skidmore 	return ixgbe_setup_sfi_x550a(hw, &speed);
15832d40cd17SMark Rustad }
15842d40cd17SMark Rustad 
15852d40cd17SMark Rustad /**
15862d40cd17SMark Rustad  * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP
15872d40cd17SMark Rustad  * @hw: pointer to hardware structure
15882d40cd17SMark Rustad  *
15892d40cd17SMark Rustad  * Configure the the integrated PHY for SFP support.
15902d40cd17SMark Rustad  */
15912d40cd17SMark Rustad static s32
15922d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed,
15932d40cd17SMark Rustad 			       __always_unused bool autoneg_wait_to_complete)
15942d40cd17SMark Rustad {
15952d40cd17SMark Rustad 	u32 reg_slice, slice_offset;
15962d40cd17SMark Rustad 	bool setup_linear = false;
15972d40cd17SMark Rustad 	u16 reg_phy_ext;
1598470739b5SDon Skidmore 	s32 ret_val;
15992d40cd17SMark Rustad 
16002d40cd17SMark Rustad 	/* Check if SFP module is supported and linear */
1601470739b5SDon Skidmore 	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
16022d40cd17SMark Rustad 
16032d40cd17SMark Rustad 	/* If no SFP module present, then return success. Return success since
16042d40cd17SMark Rustad 	 * SFP not present error is not excepted in the setup MAC link flow.
16052d40cd17SMark Rustad 	 */
1606470739b5SDon Skidmore 	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
16072d40cd17SMark Rustad 		return 0;
16082d40cd17SMark Rustad 
1609470739b5SDon Skidmore 	if (!ret_val)
1610470739b5SDon Skidmore 		return ret_val;
16112d40cd17SMark Rustad 
16122d40cd17SMark Rustad 	/* Configure internal PHY for KR/KX. */
16132d40cd17SMark Rustad 	ixgbe_setup_kr_speed_x550em(hw, speed);
16142d40cd17SMark Rustad 
16157564a888SMark Rustad 	if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE)
16162d40cd17SMark Rustad 		return IXGBE_ERR_PHY_ADDR_INVALID;
16172d40cd17SMark Rustad 
16182d40cd17SMark Rustad 	/* Get external PHY device id */
1619470739b5SDon Skidmore 	ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB,
16202d40cd17SMark Rustad 				  IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
1621470739b5SDon Skidmore 	if (ret_val)
1622470739b5SDon Skidmore 		return ret_val;
16232d40cd17SMark Rustad 
16242d40cd17SMark Rustad 	/* When configuring quad port CS4223, the MAC instance is part
16252d40cd17SMark Rustad 	 * of the slice offset.
16262d40cd17SMark Rustad 	 */
16272d40cd17SMark Rustad 	if (reg_phy_ext == IXGBE_CS4223_PHY_ID)
16282d40cd17SMark Rustad 		slice_offset = (hw->bus.lan_id +
16292d40cd17SMark Rustad 				(hw->bus.instance_id << 1)) << 12;
16302d40cd17SMark Rustad 	else
16312d40cd17SMark Rustad 		slice_offset = hw->bus.lan_id << 12;
16322d40cd17SMark Rustad 
16332d40cd17SMark Rustad 	/* Configure CS4227/CS4223 LINE side to proper mode. */
16342d40cd17SMark Rustad 	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
16352d40cd17SMark Rustad 	if (setup_linear)
16362d40cd17SMark Rustad 		reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1;
16372d40cd17SMark Rustad 	else
16382d40cd17SMark Rustad 		reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1;
16392d40cd17SMark Rustad 	return hw->phy.ops.write_reg(hw, reg_slice, IXGBE_MDIO_ZERO_DEV_TYPE,
16402d40cd17SMark Rustad 				     reg_phy_ext);
16412d40cd17SMark Rustad }
16422d40cd17SMark Rustad 
16432d40cd17SMark Rustad /**
1644c3dc4c09SDon Skidmore  * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
1645c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
1646c3dc4c09SDon Skidmore  * @speed: new link speed
1647c3dc4c09SDon Skidmore  * @autoneg_wait_to_complete: true when waiting for completion is needed
1648c3dc4c09SDon Skidmore  *
1649c3dc4c09SDon Skidmore  * Setup internal/external PHY link speed based on link speed, then set
1650c3dc4c09SDon Skidmore  * external PHY auto advertised link speed.
1651c3dc4c09SDon Skidmore  *
1652c3dc4c09SDon Skidmore  * Returns error status for any failure
1653c3dc4c09SDon Skidmore  **/
1654c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
1655c3dc4c09SDon Skidmore 					 ixgbe_link_speed speed,
1656c3dc4c09SDon Skidmore 					 bool autoneg_wait)
1657c3dc4c09SDon Skidmore {
1658c3dc4c09SDon Skidmore 	s32 status;
1659c3dc4c09SDon Skidmore 	ixgbe_link_speed force_speed;
1660c3dc4c09SDon Skidmore 
1661c3dc4c09SDon Skidmore 	/* Setup internal/external PHY link speed to iXFI (10G), unless
1662c3dc4c09SDon Skidmore 	 * only 1G is auto advertised then setup KX link.
1663c3dc4c09SDon Skidmore 	 */
1664c3dc4c09SDon Skidmore 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
1665c3dc4c09SDon Skidmore 		force_speed = IXGBE_LINK_SPEED_10GB_FULL;
1666c3dc4c09SDon Skidmore 	else
1667c3dc4c09SDon Skidmore 		force_speed = IXGBE_LINK_SPEED_1GB_FULL;
1668c3dc4c09SDon Skidmore 
1669c3dc4c09SDon Skidmore 	/* If internal link mode is XFI, then setup XFI internal link. */
1670c3dc4c09SDon Skidmore 	if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
1671c3dc4c09SDon Skidmore 		status = ixgbe_setup_ixfi_x550em(hw, &force_speed);
1672c3dc4c09SDon Skidmore 
1673c3dc4c09SDon Skidmore 		if (status)
1674c3dc4c09SDon Skidmore 			return status;
1675c3dc4c09SDon Skidmore 	}
1676c3dc4c09SDon Skidmore 
1677c3dc4c09SDon Skidmore 	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
1678c3dc4c09SDon Skidmore }
1679c3dc4c09SDon Skidmore 
1680a4e293a5SDon Skidmore /** ixgbe_check_link_t_X550em - Determine link and speed status
1681a4e293a5SDon Skidmore   * @hw: pointer to hardware structure
1682a4e293a5SDon Skidmore   * @speed: pointer to link speed
1683a4e293a5SDon Skidmore   * @link_up: true when link is up
1684a4e293a5SDon Skidmore   * @link_up_wait_to_complete: bool used to wait for link up or not
1685a4e293a5SDon Skidmore   *
1686a4e293a5SDon Skidmore   * Check that both the MAC and X557 external PHY have link.
1687a4e293a5SDon Skidmore   **/
1688a4e293a5SDon Skidmore static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw,
1689a4e293a5SDon Skidmore 				     ixgbe_link_speed *speed,
1690a4e293a5SDon Skidmore 				     bool *link_up,
1691a4e293a5SDon Skidmore 				     bool link_up_wait_to_complete)
1692a4e293a5SDon Skidmore {
1693a4e293a5SDon Skidmore 	u32 status;
169421d882ebSEmil Tantilov 	u16 i, autoneg_status;
1695a4e293a5SDon Skidmore 
1696a4e293a5SDon Skidmore 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
1697a4e293a5SDon Skidmore 		return IXGBE_ERR_CONFIG;
1698a4e293a5SDon Skidmore 
1699a4e293a5SDon Skidmore 	status = ixgbe_check_mac_link_generic(hw, speed, link_up,
1700a4e293a5SDon Skidmore 					      link_up_wait_to_complete);
1701a4e293a5SDon Skidmore 
1702a4e293a5SDon Skidmore 	/* If check link fails or MAC link is not up, then return */
1703a4e293a5SDon Skidmore 	if (status || !(*link_up))
1704a4e293a5SDon Skidmore 		return status;
1705a4e293a5SDon Skidmore 
1706a4e293a5SDon Skidmore 	/* MAC link is up, so check external PHY link.
170721d882ebSEmil Tantilov 	 * Link status is latching low, and can only be used to detect link
170821d882ebSEmil Tantilov 	 * drop, and not the current status of the link without performing
170921d882ebSEmil Tantilov 	 * back-to-back reads.
1710a4e293a5SDon Skidmore 	 */
171121d882ebSEmil Tantilov 	for (i = 0; i < 2; i++) {
17124dc4000bSEmil Tantilov 		status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
1713a4e293a5SDon Skidmore 					      &autoneg_status);
171421d882ebSEmil Tantilov 
1715a4e293a5SDon Skidmore 		if (status)
1716a4e293a5SDon Skidmore 			return status;
171721d882ebSEmil Tantilov 	}
1718a4e293a5SDon Skidmore 
1719a4e293a5SDon Skidmore 	/* If external PHY link is not up, then indicate link not up */
1720a4e293a5SDon Skidmore 	if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
1721a4e293a5SDon Skidmore 		*link_up = false;
1722a4e293a5SDon Skidmore 
1723a4e293a5SDon Skidmore 	return 0;
1724a4e293a5SDon Skidmore }
1725a4e293a5SDon Skidmore 
1726200157c2SMark Rustad /**
1727200157c2SMark Rustad  * ixgbe_setup_sgmii - Set up link for sgmii
1728200157c2SMark Rustad  * @hw: pointer to hardware structure
1729200157c2SMark Rustad  */
1730200157c2SMark Rustad static s32
1731200157c2SMark Rustad ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed,
1732200157c2SMark Rustad 		  __always_unused bool autoneg_wait_to_complete)
1733200157c2SMark Rustad {
1734200157c2SMark Rustad 	struct ixgbe_mac_info *mac = &hw->mac;
1735470739b5SDon Skidmore 	u32 lval, sval, flx_val;
1736200157c2SMark Rustad 	s32 rc;
1737200157c2SMark Rustad 
1738200157c2SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
1739200157c2SMark Rustad 				       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1740200157c2SMark Rustad 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
1741200157c2SMark Rustad 	if (rc)
1742200157c2SMark Rustad 		return rc;
1743200157c2SMark Rustad 
1744200157c2SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
1745200157c2SMark Rustad 	lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
1746200157c2SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
1747200157c2SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
1748200157c2SMark Rustad 	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
1749200157c2SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
1750200157c2SMark Rustad 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1751200157c2SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
1752200157c2SMark Rustad 	if (rc)
1753200157c2SMark Rustad 		return rc;
1754200157c2SMark Rustad 
1755200157c2SMark Rustad 	rc = mac->ops.read_iosf_sb_reg(hw,
1756200157c2SMark Rustad 				       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
1757200157c2SMark Rustad 				       IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
1758200157c2SMark Rustad 	if (rc)
1759200157c2SMark Rustad 		return rc;
1760200157c2SMark Rustad 
1761200157c2SMark Rustad 	sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
1762200157c2SMark Rustad 	sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
1763200157c2SMark Rustad 	rc = mac->ops.write_iosf_sb_reg(hw,
1764200157c2SMark Rustad 					IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
1765200157c2SMark Rustad 					IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
1766200157c2SMark Rustad 	if (rc)
1767200157c2SMark Rustad 		return rc;
1768200157c2SMark Rustad 
1769470739b5SDon Skidmore 	rc = mac->ops.read_iosf_sb_reg(hw,
1770470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1771470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
1772470739b5SDon Skidmore 	if (rc)
1773470739b5SDon Skidmore 		return rc;
1774200157c2SMark Rustad 
1775470739b5SDon Skidmore 	rc = mac->ops.read_iosf_sb_reg(hw,
1776470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1777470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
1778470739b5SDon Skidmore 	if (rc)
1779470739b5SDon Skidmore 		return rc;
1780470739b5SDon Skidmore 
1781470739b5SDon Skidmore 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
1782470739b5SDon Skidmore 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
1783470739b5SDon Skidmore 	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
1784470739b5SDon Skidmore 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
1785470739b5SDon Skidmore 	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
1786470739b5SDon Skidmore 
1787470739b5SDon Skidmore 	rc = mac->ops.write_iosf_sb_reg(hw,
1788470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1789470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
1790470739b5SDon Skidmore 	if (rc)
1791470739b5SDon Skidmore 		return rc;
1792470739b5SDon Skidmore 
1793470739b5SDon Skidmore 	rc = ixgbe_restart_an_internal_phy_x550em(hw);
1794200157c2SMark Rustad 	return rc;
1795200157c2SMark Rustad }
1796200157c2SMark Rustad 
17972916500dSDon Skidmore /** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers
17982916500dSDon Skidmore  *  @hw: pointer to hardware structure
17992916500dSDon Skidmore  **/
18002916500dSDon Skidmore static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw)
18012916500dSDon Skidmore {
18022916500dSDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
18032916500dSDon Skidmore 
18042916500dSDon Skidmore 	switch (mac->ops.get_media_type(hw)) {
18052916500dSDon Skidmore 	case ixgbe_media_type_fiber:
18062916500dSDon Skidmore 		mac->ops.setup_fc = NULL;
18072916500dSDon Skidmore 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;
18082916500dSDon Skidmore 		break;
18092916500dSDon Skidmore 	case ixgbe_media_type_backplane:
18102916500dSDon Skidmore 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;
18112916500dSDon Skidmore 		mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;
18122916500dSDon Skidmore 		break;
18132916500dSDon Skidmore 	default:
18142916500dSDon Skidmore 		break;
18152916500dSDon Skidmore 	}
18162916500dSDon Skidmore }
18172916500dSDon Skidmore 
1818c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers
1819c3dc4c09SDon Skidmore  *  @hw: pointer to hardware structure
1820c3dc4c09SDon Skidmore  **/
1821c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
1822c3dc4c09SDon Skidmore {
1823c3dc4c09SDon Skidmore 	struct ixgbe_mac_info *mac = &hw->mac;
1824c3dc4c09SDon Skidmore 
1825abf76d76SEmil Tantilov 	mac->ops.setup_fc = ixgbe_setup_fc_x550em;
1826abf76d76SEmil Tantilov 
1827c3dc4c09SDon Skidmore 	switch (mac->ops.get_media_type(hw)) {
1828c3dc4c09SDon Skidmore 	case ixgbe_media_type_fiber:
1829c3dc4c09SDon Skidmore 		/* CS4227 does not support autoneg, so disable the laser control
1830c3dc4c09SDon Skidmore 		 * functions for SFP+ fiber
1831c3dc4c09SDon Skidmore 		 */
1832c3dc4c09SDon Skidmore 		mac->ops.disable_tx_laser = NULL;
1833c3dc4c09SDon Skidmore 		mac->ops.enable_tx_laser = NULL;
1834c3dc4c09SDon Skidmore 		mac->ops.flap_tx_laser = NULL;
18356d373a1bSMark Rustad 		mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
18362d40cd17SMark Rustad 		switch (hw->device_id) {
18372d40cd17SMark Rustad 		case IXGBE_DEV_ID_X550EM_A_SFP_N:
18382d40cd17SMark Rustad 			mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n;
18392d40cd17SMark Rustad 			break;
18402d40cd17SMark Rustad 		case IXGBE_DEV_ID_X550EM_A_SFP:
18412d40cd17SMark Rustad 			mac->ops.setup_mac_link =
18422d40cd17SMark Rustad 						ixgbe_setup_mac_link_sfp_x550a;
18432d40cd17SMark Rustad 			break;
18442d40cd17SMark Rustad 		default:
18452d40cd17SMark Rustad 			mac->ops.setup_mac_link =
18462d40cd17SMark Rustad 						ixgbe_setup_mac_link_sfp_x550em;
18472d40cd17SMark Rustad 			break;
18482d40cd17SMark Rustad 		}
18496d373a1bSMark Rustad 		mac->ops.set_rate_select_speed =
18506d373a1bSMark Rustad 					ixgbe_set_soft_rate_select_speed;
1851c3dc4c09SDon Skidmore 		break;
1852c3dc4c09SDon Skidmore 	case ixgbe_media_type_copper:
1853c3dc4c09SDon Skidmore 		mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
1854afdc71e4SMark Rustad 		mac->ops.setup_fc = ixgbe_setup_fc_generic;
1855a4e293a5SDon Skidmore 		mac->ops.check_link = ixgbe_check_link_t_X550em;
185649425dfcSMark Rustad 		return;
185749425dfcSMark Rustad 	case ixgbe_media_type_backplane:
1858200157c2SMark Rustad 		if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
1859200157c2SMark Rustad 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)
1860200157c2SMark Rustad 			mac->ops.setup_link = ixgbe_setup_sgmii;
1861c3dc4c09SDon Skidmore 		break;
1862c3dc4c09SDon Skidmore 	default:
1863c3dc4c09SDon Skidmore 		break;
1864c3dc4c09SDon Skidmore 	}
18652916500dSDon Skidmore 
18662916500dSDon Skidmore 	/* Additional modification for X550em_a devices */
18672916500dSDon Skidmore 	if (hw->mac.type == ixgbe_mac_x550em_a)
18682916500dSDon Skidmore 		ixgbe_init_mac_link_ops_X550em_a(hw);
1869c3dc4c09SDon Skidmore }
1870c3dc4c09SDon Skidmore 
1871c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module
1872c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
1873c3dc4c09SDon Skidmore  */
1874c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
1875c3dc4c09SDon Skidmore {
1876e23f3336SMark Rustad 	s32 status;
1877e23f3336SMark Rustad 	bool linear;
1878c3dc4c09SDon Skidmore 
1879e23f3336SMark Rustad 	/* Check if SFP module is supported */
1880e23f3336SMark Rustad 	status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
1881e23f3336SMark Rustad 	if (status)
1882e23f3336SMark Rustad 		return status;
1883c3dc4c09SDon Skidmore 
1884c3dc4c09SDon Skidmore 	ixgbe_init_mac_link_ops_X550em(hw);
1885c3dc4c09SDon Skidmore 	hw->phy.ops.reset = NULL;
1886c3dc4c09SDon Skidmore 
1887e23f3336SMark Rustad 	return 0;
1888c3dc4c09SDon Skidmore }
1889c3dc4c09SDon Skidmore 
1890c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities
1891c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
1892c3dc4c09SDon Skidmore  * @speed: pointer to link speed
1893c3dc4c09SDon Skidmore  * @autoneg: true when autoneg or autotry is enabled
1894c3dc4c09SDon Skidmore  **/
1895c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
1896c3dc4c09SDon Skidmore 					      ixgbe_link_speed *speed,
1897c3dc4c09SDon Skidmore 					      bool *autoneg)
1898c3dc4c09SDon Skidmore {
1899c3dc4c09SDon Skidmore 	/* SFP */
1900c3dc4c09SDon Skidmore 	if (hw->phy.media_type == ixgbe_media_type_fiber) {
1901c3dc4c09SDon Skidmore 		/* CS4227 SFP must not enable auto-negotiation */
1902c3dc4c09SDon Skidmore 		*autoneg = false;
1903c3dc4c09SDon Skidmore 
1904c3dc4c09SDon Skidmore 		if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
1905c3dc4c09SDon Skidmore 		    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
1906c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_1GB_FULL;
1907c3dc4c09SDon Skidmore 			return 0;
1908c3dc4c09SDon Skidmore 		}
1909c3dc4c09SDon Skidmore 
1910c3dc4c09SDon Skidmore 		/* Link capabilities are based on SFP */
1911c3dc4c09SDon Skidmore 		if (hw->phy.multispeed_fiber)
1912c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_10GB_FULL |
1913c3dc4c09SDon Skidmore 				 IXGBE_LINK_SPEED_1GB_FULL;
1914c3dc4c09SDon Skidmore 		else
1915c3dc4c09SDon Skidmore 			*speed = IXGBE_LINK_SPEED_10GB_FULL;
1916c3dc4c09SDon Skidmore 	} else {
1917c3dc4c09SDon Skidmore 		*speed = IXGBE_LINK_SPEED_10GB_FULL |
1918c3dc4c09SDon Skidmore 			 IXGBE_LINK_SPEED_1GB_FULL;
1919c3dc4c09SDon Skidmore 		*autoneg = true;
1920c3dc4c09SDon Skidmore 	}
1921c3dc4c09SDon Skidmore 	return 0;
1922c3dc4c09SDon Skidmore }
1923c3dc4c09SDon Skidmore 
1924c3dc4c09SDon Skidmore /**
1925c3dc4c09SDon Skidmore  * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause
1926c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
1927c3dc4c09SDon Skidmore  * @lsc: pointer to boolean flag which indicates whether external Base T
1928c3dc4c09SDon Skidmore  *	 PHY interrupt is lsc
1929c3dc4c09SDon Skidmore  *
1930c3dc4c09SDon Skidmore  * Determime if external Base T PHY interrupt cause is high temperature
1931c3dc4c09SDon Skidmore  * failure alarm or link status change.
1932c3dc4c09SDon Skidmore  *
1933c3dc4c09SDon Skidmore  * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
1934c3dc4c09SDon Skidmore  * failure alarm, else return PHY access status.
1935c3dc4c09SDon Skidmore  **/
1936c3dc4c09SDon Skidmore static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
1937c3dc4c09SDon Skidmore {
1938c3dc4c09SDon Skidmore 	u32 status;
1939c3dc4c09SDon Skidmore 	u16 reg;
1940c3dc4c09SDon Skidmore 
1941c3dc4c09SDon Skidmore 	*lsc = false;
1942c3dc4c09SDon Skidmore 
1943c3dc4c09SDon Skidmore 	/* Vendor alarm triggered */
1944c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
19454dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
1946c3dc4c09SDon Skidmore 				      &reg);
1947c3dc4c09SDon Skidmore 
1948c3dc4c09SDon Skidmore 	if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
1949c3dc4c09SDon Skidmore 		return status;
1950c3dc4c09SDon Skidmore 
1951c3dc4c09SDon Skidmore 	/* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
1952c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
19534dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
1954c3dc4c09SDon Skidmore 				      &reg);
1955c3dc4c09SDon Skidmore 
1956c3dc4c09SDon Skidmore 	if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
1957c3dc4c09SDon Skidmore 				IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
1958c3dc4c09SDon Skidmore 		return status;
1959c3dc4c09SDon Skidmore 
196083a9fb20SMark Rustad 	/* Global alarm triggered */
1961c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
19624dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
1963c3dc4c09SDon Skidmore 				      &reg);
1964c3dc4c09SDon Skidmore 
1965c3dc4c09SDon Skidmore 	if (status)
1966c3dc4c09SDon Skidmore 		return status;
1967c3dc4c09SDon Skidmore 
1968c3dc4c09SDon Skidmore 	/* If high temperature failure, then return over temp error and exit */
1969c3dc4c09SDon Skidmore 	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
1970c3dc4c09SDon Skidmore 		/* power down the PHY in case the PHY FW didn't already */
1971c3dc4c09SDon Skidmore 		ixgbe_set_copper_phy_power(hw, false);
1972c3dc4c09SDon Skidmore 		return IXGBE_ERR_OVERTEMP;
1973c3dc4c09SDon Skidmore 	}
197483a9fb20SMark Rustad 	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
197583a9fb20SMark Rustad 		/*  device fault alarm triggered */
197683a9fb20SMark Rustad 		status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
19774dc4000bSEmil Tantilov 					  MDIO_MMD_VEND1,
197883a9fb20SMark Rustad 					  &reg);
197983a9fb20SMark Rustad 		if (status)
198083a9fb20SMark Rustad 			return status;
198183a9fb20SMark Rustad 
198283a9fb20SMark Rustad 		/* if device fault was due to high temp alarm handle and exit */
198383a9fb20SMark Rustad 		if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
198483a9fb20SMark Rustad 			/* power down the PHY in case the PHY FW didn't */
198583a9fb20SMark Rustad 			ixgbe_set_copper_phy_power(hw, false);
198683a9fb20SMark Rustad 			return IXGBE_ERR_OVERTEMP;
198783a9fb20SMark Rustad 		}
198883a9fb20SMark Rustad 	}
1989c3dc4c09SDon Skidmore 
1990c3dc4c09SDon Skidmore 	/* Vendor alarm 2 triggered */
1991c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
19924dc4000bSEmil Tantilov 				      MDIO_MMD_AN, &reg);
1993c3dc4c09SDon Skidmore 
1994c3dc4c09SDon Skidmore 	if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
1995c3dc4c09SDon Skidmore 		return status;
1996c3dc4c09SDon Skidmore 
1997c3dc4c09SDon Skidmore 	/* link connect/disconnect event occurred */
1998c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
19994dc4000bSEmil Tantilov 				      MDIO_MMD_AN, &reg);
2000c3dc4c09SDon Skidmore 
2001c3dc4c09SDon Skidmore 	if (status)
2002c3dc4c09SDon Skidmore 		return status;
2003c3dc4c09SDon Skidmore 
2004c3dc4c09SDon Skidmore 	/* Indicate LSC */
2005c3dc4c09SDon Skidmore 	if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC)
2006c3dc4c09SDon Skidmore 		*lsc = true;
2007c3dc4c09SDon Skidmore 
2008c3dc4c09SDon Skidmore 	return 0;
2009c3dc4c09SDon Skidmore }
2010c3dc4c09SDon Skidmore 
2011c3dc4c09SDon Skidmore /**
2012c3dc4c09SDon Skidmore  * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts
2013c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2014c3dc4c09SDon Skidmore  *
2015c3dc4c09SDon Skidmore  * Enable link status change and temperature failure alarm for the external
2016c3dc4c09SDon Skidmore  * Base T PHY
2017c3dc4c09SDon Skidmore  *
2018c3dc4c09SDon Skidmore  * Returns PHY access status
2019c3dc4c09SDon Skidmore  **/
2020c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
2021c3dc4c09SDon Skidmore {
2022c3dc4c09SDon Skidmore 	u32 status;
2023c3dc4c09SDon Skidmore 	u16 reg;
2024c3dc4c09SDon Skidmore 	bool lsc;
2025c3dc4c09SDon Skidmore 
2026c3dc4c09SDon Skidmore 	/* Clear interrupt flags */
2027c3dc4c09SDon Skidmore 	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
2028c3dc4c09SDon Skidmore 
2029c3dc4c09SDon Skidmore 	/* Enable link status change alarm */
2030c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
20314dc4000bSEmil Tantilov 				      MDIO_MMD_AN, &reg);
2032c3dc4c09SDon Skidmore 	if (status)
2033c3dc4c09SDon Skidmore 		return status;
2034c3dc4c09SDon Skidmore 
2035c3dc4c09SDon Skidmore 	reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
2036c3dc4c09SDon Skidmore 
2037c3dc4c09SDon Skidmore 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
20384dc4000bSEmil Tantilov 				       MDIO_MMD_AN, reg);
2039c3dc4c09SDon Skidmore 	if (status)
2040c3dc4c09SDon Skidmore 		return status;
2041c3dc4c09SDon Skidmore 
204283a9fb20SMark Rustad 	/* Enable high temperature failure and global fault alarms */
2043c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
20444dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2045c3dc4c09SDon Skidmore 				      &reg);
2046c3dc4c09SDon Skidmore 	if (status)
2047c3dc4c09SDon Skidmore 		return status;
2048c3dc4c09SDon Skidmore 
204983a9fb20SMark Rustad 	reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN |
205083a9fb20SMark Rustad 		IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);
2051c3dc4c09SDon Skidmore 
2052c3dc4c09SDon Skidmore 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
20534dc4000bSEmil Tantilov 				       MDIO_MMD_VEND1,
2054c3dc4c09SDon Skidmore 				       reg);
2055c3dc4c09SDon Skidmore 	if (status)
2056c3dc4c09SDon Skidmore 		return status;
2057c3dc4c09SDon Skidmore 
2058c3dc4c09SDon Skidmore 	/* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
2059c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
20604dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2061c3dc4c09SDon Skidmore 				      &reg);
2062c3dc4c09SDon Skidmore 	if (status)
2063c3dc4c09SDon Skidmore 		return status;
2064c3dc4c09SDon Skidmore 
2065c3dc4c09SDon Skidmore 	reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
2066c3dc4c09SDon Skidmore 		IXGBE_MDIO_GLOBAL_ALARM_1_INT);
2067c3dc4c09SDon Skidmore 
2068c3dc4c09SDon Skidmore 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
20694dc4000bSEmil Tantilov 				       MDIO_MMD_VEND1,
2070c3dc4c09SDon Skidmore 				       reg);
2071c3dc4c09SDon Skidmore 	if (status)
2072c3dc4c09SDon Skidmore 		return status;
2073c3dc4c09SDon Skidmore 
2074c3dc4c09SDon Skidmore 	/* Enable chip-wide vendor alarm */
2075c3dc4c09SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
20764dc4000bSEmil Tantilov 				      MDIO_MMD_VEND1,
2077c3dc4c09SDon Skidmore 				      &reg);
2078c3dc4c09SDon Skidmore 	if (status)
2079c3dc4c09SDon Skidmore 		return status;
2080c3dc4c09SDon Skidmore 
2081c3dc4c09SDon Skidmore 	reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
2082c3dc4c09SDon Skidmore 
2083c3dc4c09SDon Skidmore 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
20844dc4000bSEmil Tantilov 				       MDIO_MMD_VEND1,
2085c3dc4c09SDon Skidmore 				       reg);
2086c3dc4c09SDon Skidmore 
2087c3dc4c09SDon Skidmore 	return status;
2088c3dc4c09SDon Skidmore }
2089c3dc4c09SDon Skidmore 
2090c3dc4c09SDon Skidmore /**
2091c3dc4c09SDon Skidmore  * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
2092c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2093c3dc4c09SDon Skidmore  *
2094c3dc4c09SDon Skidmore  * Handle external Base T PHY interrupt. If high temperature
2095c3dc4c09SDon Skidmore  * failure alarm then return error, else if link status change
2096c3dc4c09SDon Skidmore  * then setup internal/external PHY link
2097c3dc4c09SDon Skidmore  *
2098c3dc4c09SDon Skidmore  * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
2099c3dc4c09SDon Skidmore  * failure alarm, else return PHY access status.
2100c3dc4c09SDon Skidmore  **/
2101c3dc4c09SDon Skidmore static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
2102c3dc4c09SDon Skidmore {
2103c3dc4c09SDon Skidmore 	struct ixgbe_phy_info *phy = &hw->phy;
2104c3dc4c09SDon Skidmore 	bool lsc;
2105c3dc4c09SDon Skidmore 	u32 status;
2106c3dc4c09SDon Skidmore 
2107c3dc4c09SDon Skidmore 	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
2108c3dc4c09SDon Skidmore 	if (status)
2109c3dc4c09SDon Skidmore 		return status;
2110c3dc4c09SDon Skidmore 
2111a85ce532SMark Rustad 	if (lsc && phy->ops.setup_internal_link)
2112c3dc4c09SDon Skidmore 		return phy->ops.setup_internal_link(hw);
2113c3dc4c09SDon Skidmore 
2114c3dc4c09SDon Skidmore 	return 0;
2115c3dc4c09SDon Skidmore }
2116c3dc4c09SDon Skidmore 
2117c3dc4c09SDon Skidmore /**
2118c3dc4c09SDon Skidmore  * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed.
2119c3dc4c09SDon Skidmore  * @hw: pointer to hardware structure
2120c3dc4c09SDon Skidmore  * @speed: link speed
2121c3dc4c09SDon Skidmore  *
2122c3dc4c09SDon Skidmore  * Configures the integrated KR PHY.
2123c3dc4c09SDon Skidmore  **/
2124c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
2125c3dc4c09SDon Skidmore 				       ixgbe_link_speed speed)
2126c3dc4c09SDon Skidmore {
2127c3dc4c09SDon Skidmore 	s32 status;
2128c3dc4c09SDon Skidmore 	u32 reg_val;
2129c3dc4c09SDon Skidmore 
21309a5c27e6SMark Rustad 	status = hw->mac.ops.read_iosf_sb_reg(hw,
2131c3dc4c09SDon Skidmore 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2132c3dc4c09SDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
2133c3dc4c09SDon Skidmore 	if (status)
2134c3dc4c09SDon Skidmore 		return status;
2135c3dc4c09SDon Skidmore 
2136c3dc4c09SDon Skidmore 	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
2137c3dc4c09SDon Skidmore 	reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
2138c3dc4c09SDon Skidmore 		     IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
2139c3dc4c09SDon Skidmore 
2140c3dc4c09SDon Skidmore 	/* Advertise 10G support. */
2141c3dc4c09SDon Skidmore 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
2142c3dc4c09SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR;
2143c3dc4c09SDon Skidmore 
2144c3dc4c09SDon Skidmore 	/* Advertise 1G support. */
2145c3dc4c09SDon Skidmore 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
2146c3dc4c09SDon Skidmore 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
2147c3dc4c09SDon Skidmore 
21489a5c27e6SMark Rustad 	status = hw->mac.ops.write_iosf_sb_reg(hw,
2149c3dc4c09SDon Skidmore 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2150c3dc4c09SDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2151c3dc4c09SDon Skidmore 
2152470739b5SDon Skidmore 	if (hw->mac.type == ixgbe_mac_x550em_a) {
2153470739b5SDon Skidmore 		/* Set lane mode  to KR auto negotiation */
2154470739b5SDon Skidmore 		status = hw->mac.ops.read_iosf_sb_reg(hw,
2155470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2156470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
2157470739b5SDon Skidmore 
2158470739b5SDon Skidmore 		if (status)
2159c3dc4c09SDon Skidmore 			return status;
2160470739b5SDon Skidmore 
2161470739b5SDon Skidmore 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
2162470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
2163470739b5SDon Skidmore 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
2164470739b5SDon Skidmore 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
2165470739b5SDon Skidmore 		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
2166470739b5SDon Skidmore 
2167470739b5SDon Skidmore 		status = hw->mac.ops.write_iosf_sb_reg(hw,
2168470739b5SDon Skidmore 				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2169470739b5SDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2170470739b5SDon Skidmore 	}
2171470739b5SDon Skidmore 
2172470739b5SDon Skidmore 	return ixgbe_restart_an_internal_phy_x550em(hw);
2173c3dc4c09SDon Skidmore }
2174c3dc4c09SDon Skidmore 
21756a14ee0cSDon Skidmore /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY.
21766a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
21776a14ee0cSDon Skidmore  *
21786a14ee0cSDon Skidmore  *   Configures the integrated KX4 PHY.
21796a14ee0cSDon Skidmore  **/
21807ddbde3fSDon Skidmore static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw)
21816a14ee0cSDon Skidmore {
21826a14ee0cSDon Skidmore 	s32 status;
21836a14ee0cSDon Skidmore 	u32 reg_val;
21846a14ee0cSDon Skidmore 
21859a5c27e6SMark Rustad 	status = hw->mac.ops.read_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1,
21866a14ee0cSDon Skidmore 					      IXGBE_SB_IOSF_TARGET_KX4_PCS0 +
21876a14ee0cSDon Skidmore 					      hw->bus.lan_id, &reg_val);
21886a14ee0cSDon Skidmore 	if (status)
21896a14ee0cSDon Skidmore 		return status;
21906a14ee0cSDon Skidmore 
21916a14ee0cSDon Skidmore 	reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 |
21926a14ee0cSDon Skidmore 		     IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX);
21936a14ee0cSDon Skidmore 
21946a14ee0cSDon Skidmore 	reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE;
21956a14ee0cSDon Skidmore 
21966a14ee0cSDon Skidmore 	/* Advertise 10G support. */
21976a14ee0cSDon Skidmore 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
21986a14ee0cSDon Skidmore 		reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4;
21996a14ee0cSDon Skidmore 
22006a14ee0cSDon Skidmore 	/* Advertise 1G support. */
22016a14ee0cSDon Skidmore 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
22026a14ee0cSDon Skidmore 		reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX;
22036a14ee0cSDon Skidmore 
22046a14ee0cSDon Skidmore 	/* Restart auto-negotiation. */
22056a14ee0cSDon Skidmore 	reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART;
22069a5c27e6SMark Rustad 	status = hw->mac.ops.write_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1,
22076a14ee0cSDon Skidmore 					       IXGBE_SB_IOSF_TARGET_KX4_PCS0 +
22086a14ee0cSDon Skidmore 					       hw->bus.lan_id, reg_val);
22096a14ee0cSDon Skidmore 
22106a14ee0cSDon Skidmore 	return status;
22116a14ee0cSDon Skidmore }
22126a14ee0cSDon Skidmore 
2213f572b2c4SMark Rustad /**
2214f572b2c4SMark Rustad  * ixgbe_setup_kr_x550em - Configure the KR PHY
22156a14ee0cSDon Skidmore  * @hw: pointer to hardware structure
22166a14ee0cSDon Skidmore  **/
22177ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
22186a14ee0cSDon Skidmore {
221954f6d4c4SDon Skidmore 	/* leave link alone for 2.5G */
222054f6d4c4SDon Skidmore 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
2221f572b2c4SMark Rustad 		return 0;
2222f572b2c4SMark Rustad 
2223c3dc4c09SDon Skidmore 	return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised);
22246a14ee0cSDon Skidmore }
22256a14ee0cSDon Skidmore 
2226c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status
2227c3dc4c09SDon Skidmore  *  @hw: address of hardware structure
2228c3dc4c09SDon Skidmore  *  @link_up: address of boolean to indicate link status
2229c3dc4c09SDon Skidmore  *
2230c3dc4c09SDon Skidmore  *  Returns error code if unable to get link status.
2231c3dc4c09SDon Skidmore  **/
2232c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
2233c3dc4c09SDon Skidmore {
2234c3dc4c09SDon Skidmore 	u32 ret;
2235c3dc4c09SDon Skidmore 	u16 autoneg_status;
2236c3dc4c09SDon Skidmore 
2237c3dc4c09SDon Skidmore 	*link_up = false;
2238c3dc4c09SDon Skidmore 
2239c3dc4c09SDon Skidmore 	/* read this twice back to back to indicate current status */
22404dc4000bSEmil Tantilov 	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
2241c3dc4c09SDon Skidmore 				   &autoneg_status);
2242c3dc4c09SDon Skidmore 	if (ret)
2243c3dc4c09SDon Skidmore 		return ret;
2244c3dc4c09SDon Skidmore 
22454dc4000bSEmil Tantilov 	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
2246c3dc4c09SDon Skidmore 				   &autoneg_status);
2247c3dc4c09SDon Skidmore 	if (ret)
2248c3dc4c09SDon Skidmore 		return ret;
2249c3dc4c09SDon Skidmore 
2250c3dc4c09SDon Skidmore 	*link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS);
2251c3dc4c09SDon Skidmore 
2252c3dc4c09SDon Skidmore 	return 0;
2253c3dc4c09SDon Skidmore }
2254c3dc4c09SDon Skidmore 
2255c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link
22566a14ee0cSDon Skidmore  *  @hw: point to hardware structure
22576a14ee0cSDon Skidmore  *
2258c3dc4c09SDon Skidmore  *  Configures the link between the integrated KR PHY and the external X557 PHY
2259c3dc4c09SDon Skidmore  *  The driver will call this function when it gets a link status change
2260c3dc4c09SDon Skidmore  *  interrupt from the X557 PHY. This function configures the link speed
2261c3dc4c09SDon Skidmore  *  between the PHYs to match the link speed of the BASE-T link.
22626a14ee0cSDon Skidmore  *
22636a14ee0cSDon Skidmore  * A return of a non-zero value indicates an error, and the base driver should
22646a14ee0cSDon Skidmore  * not report link up.
22656a14ee0cSDon Skidmore  **/
2266c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
22676a14ee0cSDon Skidmore {
22686a14ee0cSDon Skidmore 	ixgbe_link_speed force_speed;
2269c3dc4c09SDon Skidmore 	bool link_up;
2270c3dc4c09SDon Skidmore 	u32 status;
2271c3dc4c09SDon Skidmore 	u16 speed;
22726a14ee0cSDon Skidmore 
2273c3dc4c09SDon Skidmore 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
2274c3dc4c09SDon Skidmore 		return IXGBE_ERR_CONFIG;
2275c3dc4c09SDon Skidmore 
2276f164b845SMark Rustad 	if (hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) {
2277f164b845SMark Rustad 		speed = IXGBE_LINK_SPEED_10GB_FULL |
2278f164b845SMark Rustad 			IXGBE_LINK_SPEED_1GB_FULL;
2279f164b845SMark Rustad 		return ixgbe_setup_kr_speed_x550em(hw, speed);
2280f164b845SMark Rustad 	}
2281f164b845SMark Rustad 
2282c3dc4c09SDon Skidmore 	/* If link is not up, then there is no setup necessary so return  */
2283c3dc4c09SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
22846a14ee0cSDon Skidmore 	if (status)
22856a14ee0cSDon Skidmore 		return status;
22866a14ee0cSDon Skidmore 
2287c3dc4c09SDon Skidmore 	if (!link_up)
22886a14ee0cSDon Skidmore 		return 0;
22896a14ee0cSDon Skidmore 
22906a14ee0cSDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
22914dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
22926a14ee0cSDon Skidmore 				      &speed);
2293c3dc4c09SDon Skidmore 	if (status)
2294c3dc4c09SDon Skidmore 		return status;
2295c3dc4c09SDon Skidmore 
2296c3dc4c09SDon Skidmore 	/* If link is not still up, then no setup is necessary so return */
2297c3dc4c09SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
2298c3dc4c09SDon Skidmore 	if (status)
2299c3dc4c09SDon Skidmore 		return status;
2300c3dc4c09SDon Skidmore 
2301c3dc4c09SDon Skidmore 	if (!link_up)
2302c3dc4c09SDon Skidmore 		return 0;
23036a14ee0cSDon Skidmore 
23046a14ee0cSDon Skidmore 	/* clear everything but the speed and duplex bits */
23056a14ee0cSDon Skidmore 	speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
23066a14ee0cSDon Skidmore 
23076a14ee0cSDon Skidmore 	switch (speed) {
23086a14ee0cSDon Skidmore 	case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
23096a14ee0cSDon Skidmore 		force_speed = IXGBE_LINK_SPEED_10GB_FULL;
23106a14ee0cSDon Skidmore 		break;
23116a14ee0cSDon Skidmore 	case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
23126a14ee0cSDon Skidmore 		force_speed = IXGBE_LINK_SPEED_1GB_FULL;
23136a14ee0cSDon Skidmore 		break;
23146a14ee0cSDon Skidmore 	default:
23156a14ee0cSDon Skidmore 		/* Internal PHY does not support anything else */
23166a14ee0cSDon Skidmore 		return IXGBE_ERR_INVALID_LINK_SETTINGS;
23176a14ee0cSDon Skidmore 	}
23186a14ee0cSDon Skidmore 
23196a14ee0cSDon Skidmore 	return ixgbe_setup_ixfi_x550em(hw, &force_speed);
23206a14ee0cSDon Skidmore }
23216a14ee0cSDon Skidmore 
2322f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI
2323f4410d2cSDon Skidmore  *  @hw: pointer to hardware structure
2324f4410d2cSDon Skidmore  **/
2325f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw)
2326f4410d2cSDon Skidmore {
2327f4410d2cSDon Skidmore 	s32 status;
2328f4410d2cSDon Skidmore 
2329f4410d2cSDon Skidmore 	status = ixgbe_reset_phy_generic(hw);
2330f4410d2cSDon Skidmore 
2331f4410d2cSDon Skidmore 	if (status)
2332f4410d2cSDon Skidmore 		return status;
2333f4410d2cSDon Skidmore 
2334f4410d2cSDon Skidmore 	/* Configure Link Status Alarm and Temperature Threshold interrupts */
2335f4410d2cSDon Skidmore 	return ixgbe_enable_lasi_ext_t_x550em(hw);
2336f4410d2cSDon Skidmore }
2337f4410d2cSDon Skidmore 
2338a0ad55a3SDon Skidmore /**
2339a0ad55a3SDon Skidmore  *  ixgbe_led_on_t_x550em - Turns on the software controllable LEDs.
2340a0ad55a3SDon Skidmore  *  @hw: pointer to hardware structure
2341a0ad55a3SDon Skidmore  *  @led_idx: led number to turn on
2342a0ad55a3SDon Skidmore  **/
2343d2d43e5bSEmil Tantilov static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
2344a0ad55a3SDon Skidmore {
2345a0ad55a3SDon Skidmore 	u16 phy_data;
2346a0ad55a3SDon Skidmore 
2347a0ad55a3SDon Skidmore 	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
2348a0ad55a3SDon Skidmore 		return IXGBE_ERR_PARAM;
2349a0ad55a3SDon Skidmore 
2350a0ad55a3SDon Skidmore 	/* To turn on the LED, set mode to ON. */
2351a0ad55a3SDon Skidmore 	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
23524dc4000bSEmil Tantilov 			     MDIO_MMD_VEND1, &phy_data);
2353a0ad55a3SDon Skidmore 	phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;
2354a0ad55a3SDon Skidmore 	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
23554dc4000bSEmil Tantilov 			      MDIO_MMD_VEND1, phy_data);
2356a0ad55a3SDon Skidmore 
2357a0ad55a3SDon Skidmore 	return 0;
2358a0ad55a3SDon Skidmore }
2359a0ad55a3SDon Skidmore 
2360a0ad55a3SDon Skidmore /**
2361a0ad55a3SDon Skidmore  *  ixgbe_led_off_t_x550em - Turns off the software controllable LEDs.
2362a0ad55a3SDon Skidmore  *  @hw: pointer to hardware structure
2363a0ad55a3SDon Skidmore  *  @led_idx: led number to turn off
2364a0ad55a3SDon Skidmore  **/
2365d2d43e5bSEmil Tantilov static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
2366a0ad55a3SDon Skidmore {
2367a0ad55a3SDon Skidmore 	u16 phy_data;
2368a0ad55a3SDon Skidmore 
2369a0ad55a3SDon Skidmore 	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
2370a0ad55a3SDon Skidmore 		return IXGBE_ERR_PARAM;
2371a0ad55a3SDon Skidmore 
2372a0ad55a3SDon Skidmore 	/* To turn on the LED, set mode to ON. */
2373a0ad55a3SDon Skidmore 	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
23744dc4000bSEmil Tantilov 			     MDIO_MMD_VEND1, &phy_data);
2375a0ad55a3SDon Skidmore 	phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;
2376a0ad55a3SDon Skidmore 	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
23774dc4000bSEmil Tantilov 			      MDIO_MMD_VEND1, phy_data);
2378a0ad55a3SDon Skidmore 
2379a0ad55a3SDon Skidmore 	return 0;
2380a0ad55a3SDon Skidmore }
2381a0ad55a3SDon Skidmore 
2382cb8e0514STony Nguyen /**
2383cb8e0514STony Nguyen  *  ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware
2384cb8e0514STony Nguyen  *  @hw: pointer to the HW structure
2385cb8e0514STony Nguyen  *  @maj: driver version major number
2386cb8e0514STony Nguyen  *  @min: driver version minor number
2387cb8e0514STony Nguyen  *  @build: driver version build number
2388cb8e0514STony Nguyen  *  @sub: driver version sub build number
2389cb8e0514STony Nguyen  *  @len: length of driver_ver string
2390cb8e0514STony Nguyen  *  @driver_ver: driver string
2391cb8e0514STony Nguyen  *
2392cb8e0514STony Nguyen  *  Sends driver version number to firmware through the manageability
2393cb8e0514STony Nguyen  *  block.  On success return 0
2394cb8e0514STony Nguyen  *  else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
2395cb8e0514STony Nguyen  *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
2396cb8e0514STony Nguyen  **/
2397cb8e0514STony Nguyen static s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
2398cb8e0514STony Nguyen 				     u8 build, u8 sub, u16 len,
2399cb8e0514STony Nguyen 				     const char *driver_ver)
2400cb8e0514STony Nguyen {
2401cb8e0514STony Nguyen 	struct ixgbe_hic_drv_info2 fw_cmd;
2402cb8e0514STony Nguyen 	s32 ret_val;
2403cb8e0514STony Nguyen 	int i;
2404cb8e0514STony Nguyen 
2405cb8e0514STony Nguyen 	if (!len || !driver_ver || (len > sizeof(fw_cmd.driver_string)))
2406cb8e0514STony Nguyen 		return IXGBE_ERR_INVALID_ARGUMENT;
2407cb8e0514STony Nguyen 
2408cb8e0514STony Nguyen 	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
2409cb8e0514STony Nguyen 	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len;
2410cb8e0514STony Nguyen 	fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
2411cb8e0514STony Nguyen 	fw_cmd.port_num = (u8)hw->bus.func;
2412cb8e0514STony Nguyen 	fw_cmd.ver_maj = maj;
2413cb8e0514STony Nguyen 	fw_cmd.ver_min = min;
2414cb8e0514STony Nguyen 	fw_cmd.ver_build = build;
2415cb8e0514STony Nguyen 	fw_cmd.ver_sub = sub;
2416cb8e0514STony Nguyen 	fw_cmd.hdr.checksum = 0;
2417cb8e0514STony Nguyen 	memcpy(fw_cmd.driver_string, driver_ver, len);
2418cb8e0514STony Nguyen 	fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
2419cb8e0514STony Nguyen 			      (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
2420cb8e0514STony Nguyen 
2421cb8e0514STony Nguyen 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
2422cb8e0514STony Nguyen 		ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
2423cb8e0514STony Nguyen 						       sizeof(fw_cmd),
2424cb8e0514STony Nguyen 						       IXGBE_HI_COMMAND_TIMEOUT,
2425cb8e0514STony Nguyen 						       true);
2426cb8e0514STony Nguyen 		if (ret_val)
2427cb8e0514STony Nguyen 			continue;
2428cb8e0514STony Nguyen 
2429cb8e0514STony Nguyen 		if (fw_cmd.hdr.cmd_or_resp.ret_status !=
2430cb8e0514STony Nguyen 		    FW_CEM_RESP_STATUS_SUCCESS)
2431cb8e0514STony Nguyen 			return IXGBE_ERR_HOST_INTERFACE_COMMAND;
2432cb8e0514STony Nguyen 		return 0;
2433cb8e0514STony Nguyen 	}
2434cb8e0514STony Nguyen 
2435cb8e0514STony Nguyen 	return ret_val;
2436cb8e0514STony Nguyen }
2437cb8e0514STony Nguyen 
24386ac74394SDon Skidmore /** ixgbe_get_lcd_x550em - Determine lowest common denominator
24396ac74394SDon Skidmore  *  @hw: pointer to hardware structure
24406ac74394SDon Skidmore  *  @lcd_speed: pointer to lowest common link speed
24416ac74394SDon Skidmore  *
24426ac74394SDon Skidmore  *  Determine lowest common link speed with link partner.
24436ac74394SDon Skidmore  **/
24446ac74394SDon Skidmore static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw,
24456ac74394SDon Skidmore 				  ixgbe_link_speed *lcd_speed)
24466ac74394SDon Skidmore {
24476ac74394SDon Skidmore 	u16 an_lp_status;
24486ac74394SDon Skidmore 	s32 status;
24496ac74394SDon Skidmore 	u16 word = hw->eeprom.ctrl_word_3;
24506ac74394SDon Skidmore 
24516ac74394SDon Skidmore 	*lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
24526ac74394SDon Skidmore 
24536ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
24544dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
24556ac74394SDon Skidmore 				      &an_lp_status);
24566ac74394SDon Skidmore 	if (status)
24576ac74394SDon Skidmore 		return status;
24586ac74394SDon Skidmore 
24596ac74394SDon Skidmore 	/* If link partner advertised 1G, return 1G */
24606ac74394SDon Skidmore 	if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) {
24616ac74394SDon Skidmore 		*lcd_speed = IXGBE_LINK_SPEED_1GB_FULL;
24626ac74394SDon Skidmore 		return status;
24636ac74394SDon Skidmore 	}
24646ac74394SDon Skidmore 
24656ac74394SDon Skidmore 	/* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */
24666ac74394SDon Skidmore 	if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) ||
24676ac74394SDon Skidmore 	    (word & NVM_INIT_CTRL_3_D10GMP_PORT0))
24686ac74394SDon Skidmore 		return status;
24696ac74394SDon Skidmore 
24706ac74394SDon Skidmore 	/* Link partner not capable of lower speeds, return 10G */
24716ac74394SDon Skidmore 	*lcd_speed = IXGBE_LINK_SPEED_10GB_FULL;
24726ac74394SDon Skidmore 	return status;
24736ac74394SDon Skidmore }
24746ac74394SDon Skidmore 
2475afdc71e4SMark Rustad /**
2476afdc71e4SMark Rustad  * ixgbe_setup_fc_x550em - Set up flow control
2477afdc71e4SMark Rustad  * @hw: pointer to hardware structure
2478afdc71e4SMark Rustad  */
2479afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw)
2480afdc71e4SMark Rustad {
2481afdc71e4SMark Rustad 	bool pause, asm_dir;
2482afdc71e4SMark Rustad 	u32 reg_val;
2483afdc71e4SMark Rustad 	s32 rc;
2484afdc71e4SMark Rustad 
2485afdc71e4SMark Rustad 	/* Validate the requested mode */
2486afdc71e4SMark Rustad 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
2487afdc71e4SMark Rustad 		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
2488afdc71e4SMark Rustad 		return IXGBE_ERR_INVALID_LINK_SETTINGS;
2489afdc71e4SMark Rustad 	}
2490afdc71e4SMark Rustad 
2491afdc71e4SMark Rustad 	/* 10gig parts do not have a word in the EEPROM to determine the
2492afdc71e4SMark Rustad 	 * default flow control setting, so we explicitly set it to full.
2493afdc71e4SMark Rustad 	 */
2494afdc71e4SMark Rustad 	if (hw->fc.requested_mode == ixgbe_fc_default)
2495afdc71e4SMark Rustad 		hw->fc.requested_mode = ixgbe_fc_full;
2496afdc71e4SMark Rustad 
2497afdc71e4SMark Rustad 	/* Determine PAUSE and ASM_DIR bits. */
2498afdc71e4SMark Rustad 	switch (hw->fc.requested_mode) {
2499afdc71e4SMark Rustad 	case ixgbe_fc_none:
2500afdc71e4SMark Rustad 		pause = false;
2501afdc71e4SMark Rustad 		asm_dir = false;
2502afdc71e4SMark Rustad 		break;
2503afdc71e4SMark Rustad 	case ixgbe_fc_tx_pause:
2504afdc71e4SMark Rustad 		pause = false;
2505afdc71e4SMark Rustad 		asm_dir = true;
2506afdc71e4SMark Rustad 		break;
2507afdc71e4SMark Rustad 	case ixgbe_fc_rx_pause:
2508afdc71e4SMark Rustad 		/* Rx Flow control is enabled and Tx Flow control is
2509afdc71e4SMark Rustad 		 * disabled by software override. Since there really
2510afdc71e4SMark Rustad 		 * isn't a way to advertise that we are capable of RX
2511afdc71e4SMark Rustad 		 * Pause ONLY, we will advertise that we support both
2512afdc71e4SMark Rustad 		 * symmetric and asymmetric Rx PAUSE, as such we fall
2513afdc71e4SMark Rustad 		 * through to the fc_full statement.  Later, we will
2514afdc71e4SMark Rustad 		 * disable the adapter's ability to send PAUSE frames.
2515afdc71e4SMark Rustad 		 */
2516afdc71e4SMark Rustad 		/* Fallthrough */
2517afdc71e4SMark Rustad 	case ixgbe_fc_full:
2518afdc71e4SMark Rustad 		pause = true;
2519afdc71e4SMark Rustad 		asm_dir = true;
2520afdc71e4SMark Rustad 		break;
2521afdc71e4SMark Rustad 	default:
2522afdc71e4SMark Rustad 		hw_err(hw, "Flow control param set incorrectly\n");
2523afdc71e4SMark Rustad 		return IXGBE_ERR_CONFIG;
2524afdc71e4SMark Rustad 	}
2525afdc71e4SMark Rustad 
2526f572b2c4SMark Rustad 	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR &&
2527f572b2c4SMark Rustad 	    hw->device_id != IXGBE_DEV_ID_X550EM_A_KR &&
2528f572b2c4SMark Rustad 	    hw->device_id != IXGBE_DEV_ID_X550EM_A_KR_L)
2529afdc71e4SMark Rustad 		return 0;
2530afdc71e4SMark Rustad 
25319a5c27e6SMark Rustad 	rc = hw->mac.ops.read_iosf_sb_reg(hw,
2532afdc71e4SMark Rustad 					  IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
25339a5c27e6SMark Rustad 					  IXGBE_SB_IOSF_TARGET_KR_PHY,
25349a5c27e6SMark Rustad 					  &reg_val);
2535afdc71e4SMark Rustad 	if (rc)
2536afdc71e4SMark Rustad 		return rc;
2537afdc71e4SMark Rustad 
2538afdc71e4SMark Rustad 	reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
2539afdc71e4SMark Rustad 		     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
2540afdc71e4SMark Rustad 	if (pause)
2541afdc71e4SMark Rustad 		reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
2542afdc71e4SMark Rustad 	if (asm_dir)
2543afdc71e4SMark Rustad 		reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
25449a5c27e6SMark Rustad 	rc = hw->mac.ops.write_iosf_sb_reg(hw,
2545afdc71e4SMark Rustad 					   IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
25469a5c27e6SMark Rustad 					   IXGBE_SB_IOSF_TARGET_KR_PHY,
25479a5c27e6SMark Rustad 					   reg_val);
2548afdc71e4SMark Rustad 
2549afdc71e4SMark Rustad 	/* This device does not fully support AN. */
2550afdc71e4SMark Rustad 	hw->fc.disable_fc_autoneg = true;
2551afdc71e4SMark Rustad 
2552afdc71e4SMark Rustad 	return rc;
2553afdc71e4SMark Rustad }
2554afdc71e4SMark Rustad 
25552916500dSDon Skidmore /**
25562916500dSDon Skidmore  *  ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37
25572916500dSDon Skidmore  *  @hw: pointer to hardware structure
25582916500dSDon Skidmore  **/
25592916500dSDon Skidmore static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
25602916500dSDon Skidmore {
25612916500dSDon Skidmore 	u32 link_s1, lp_an_page_low, an_cntl_1;
25622916500dSDon Skidmore 	s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
25632916500dSDon Skidmore 	ixgbe_link_speed speed;
25642916500dSDon Skidmore 	bool link_up;
25652916500dSDon Skidmore 
25662916500dSDon Skidmore 	/* AN should have completed when the cable was plugged in.
25672916500dSDon Skidmore 	 * Look for reasons to bail out.  Bail out if:
25682916500dSDon Skidmore 	 * - FC autoneg is disabled, or if
25692916500dSDon Skidmore 	 * - link is not up.
25702916500dSDon Skidmore 	 */
25712916500dSDon Skidmore 	if (hw->fc.disable_fc_autoneg) {
25722916500dSDon Skidmore 		hw_err(hw, "Flow control autoneg is disabled");
25732916500dSDon Skidmore 		goto out;
25742916500dSDon Skidmore 	}
25752916500dSDon Skidmore 
25762916500dSDon Skidmore 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
25772916500dSDon Skidmore 	if (!link_up) {
25782916500dSDon Skidmore 		hw_err(hw, "The link is down");
25792916500dSDon Skidmore 		goto out;
25802916500dSDon Skidmore 	}
25812916500dSDon Skidmore 
25822916500dSDon Skidmore 	/* Check at auto-negotiation has completed */
25832916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
25842916500dSDon Skidmore 					IXGBE_KRM_LINK_S1(hw->bus.lan_id),
25852916500dSDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1);
25862916500dSDon Skidmore 
25872916500dSDon Skidmore 	if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
25882916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
25892916500dSDon Skidmore 		status = IXGBE_ERR_FC_NOT_NEGOTIATED;
25902916500dSDon Skidmore 		goto out;
25912916500dSDon Skidmore 	}
25922916500dSDon Skidmore 
25932916500dSDon Skidmore 	/* Read the 10g AN autoc and LP ability registers and resolve
25942916500dSDon Skidmore 	 * local flow control settings accordingly
25952916500dSDon Skidmore 	 */
25962916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
25972916500dSDon Skidmore 				IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
25982916500dSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1);
25992916500dSDon Skidmore 
26002916500dSDon Skidmore 	if (status) {
26012916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
26022916500dSDon Skidmore 		goto out;
26032916500dSDon Skidmore 	}
26042916500dSDon Skidmore 
26052916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
26062916500dSDon Skidmore 				IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id),
26072916500dSDon Skidmore 				IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low);
26082916500dSDon Skidmore 
26092916500dSDon Skidmore 	if (status) {
26102916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
26112916500dSDon Skidmore 		goto out;
26122916500dSDon Skidmore 	}
26132916500dSDon Skidmore 
26142916500dSDon Skidmore 	status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low,
26152916500dSDon Skidmore 				    IXGBE_KRM_AN_CNTL_1_SYM_PAUSE,
26162916500dSDon Skidmore 				    IXGBE_KRM_AN_CNTL_1_ASM_PAUSE,
26172916500dSDon Skidmore 				    IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE,
26182916500dSDon Skidmore 				    IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE);
26192916500dSDon Skidmore 
26202916500dSDon Skidmore out:
26212916500dSDon Skidmore 	if (!status) {
26222916500dSDon Skidmore 		hw->fc.fc_was_autonegged = true;
26232916500dSDon Skidmore 	} else {
26242916500dSDon Skidmore 		hw->fc.fc_was_autonegged = false;
26252916500dSDon Skidmore 		hw->fc.current_mode = hw->fc.requested_mode;
26262916500dSDon Skidmore 	}
26272916500dSDon Skidmore }
26282916500dSDon Skidmore 
26292916500dSDon Skidmore /**
26302916500dSDon Skidmore  *  ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings
26312916500dSDon Skidmore  *  @hw: pointer to hardware structure
26322916500dSDon Skidmore  **/
26332916500dSDon Skidmore static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw)
26342916500dSDon Skidmore {
26352916500dSDon Skidmore 	hw->fc.fc_was_autonegged = false;
26362916500dSDon Skidmore 	hw->fc.current_mode = hw->fc.requested_mode;
26372916500dSDon Skidmore }
26382916500dSDon Skidmore 
26396ac74394SDon Skidmore /** ixgbe_enter_lplu_x550em - Transition to low power states
26406ac74394SDon Skidmore  *  @hw: pointer to hardware structure
26416ac74394SDon Skidmore  *
26426ac74394SDon Skidmore  *  Configures Low Power Link Up on transition to low power states
26436ac74394SDon Skidmore  *  (from D0 to non-D0). Link is required to enter LPLU so avoid resetting
26446ac74394SDon Skidmore  *  the X557 PHY immediately prior to entering LPLU.
26456ac74394SDon Skidmore  **/
26466ac74394SDon Skidmore static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
26476ac74394SDon Skidmore {
26486ac74394SDon Skidmore 	u16 an_10g_cntl_reg, autoneg_reg, speed;
26496ac74394SDon Skidmore 	s32 status;
26506ac74394SDon Skidmore 	ixgbe_link_speed lcd_speed;
26516ac74394SDon Skidmore 	u32 save_autoneg;
26526ac74394SDon Skidmore 	bool link_up;
26536ac74394SDon Skidmore 
26546ac74394SDon Skidmore 	/* If blocked by MNG FW, then don't restart AN */
26556ac74394SDon Skidmore 	if (ixgbe_check_reset_blocked(hw))
26566ac74394SDon Skidmore 		return 0;
26576ac74394SDon Skidmore 
26586ac74394SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
26596ac74394SDon Skidmore 	if (status)
26606ac74394SDon Skidmore 		return status;
26616ac74394SDon Skidmore 
26626ac74394SDon Skidmore 	status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3,
26636ac74394SDon Skidmore 				     &hw->eeprom.ctrl_word_3);
26646ac74394SDon Skidmore 	if (status)
26656ac74394SDon Skidmore 		return status;
26666ac74394SDon Skidmore 
26676ac74394SDon Skidmore 	/* If link is down, LPLU disabled in NVM, WoL disabled, or
26686ac74394SDon Skidmore 	 * manageability disabled, then force link down by entering
26696ac74394SDon Skidmore 	 * low power mode.
26706ac74394SDon Skidmore 	 */
26716ac74394SDon Skidmore 	if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
26726ac74394SDon Skidmore 	    !(hw->wol_enabled || ixgbe_mng_present(hw)))
26736ac74394SDon Skidmore 		return ixgbe_set_copper_phy_power(hw, false);
26746ac74394SDon Skidmore 
26756ac74394SDon Skidmore 	/* Determine LCD */
26766ac74394SDon Skidmore 	status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed);
26776ac74394SDon Skidmore 	if (status)
26786ac74394SDon Skidmore 		return status;
26796ac74394SDon Skidmore 
26806ac74394SDon Skidmore 	/* If no valid LCD link speed, then force link down and exit. */
26816ac74394SDon Skidmore 	if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN)
26826ac74394SDon Skidmore 		return ixgbe_set_copper_phy_power(hw, false);
26836ac74394SDon Skidmore 
26846ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
26854dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
26866ac74394SDon Skidmore 				      &speed);
26876ac74394SDon Skidmore 	if (status)
26886ac74394SDon Skidmore 		return status;
26896ac74394SDon Skidmore 
26906ac74394SDon Skidmore 	/* If no link now, speed is invalid so take link down */
26916ac74394SDon Skidmore 	status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
26926ac74394SDon Skidmore 	if (status)
26936ac74394SDon Skidmore 		return ixgbe_set_copper_phy_power(hw, false);
26946ac74394SDon Skidmore 
26956ac74394SDon Skidmore 	/* clear everything but the speed bits */
26966ac74394SDon Skidmore 	speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK;
26976ac74394SDon Skidmore 
26986ac74394SDon Skidmore 	/* If current speed is already LCD, then exit. */
26996ac74394SDon Skidmore 	if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) &&
27006ac74394SDon Skidmore 	     (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) ||
27016ac74394SDon Skidmore 	    ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) &&
27026ac74394SDon Skidmore 	     (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL)))
27036ac74394SDon Skidmore 		return status;
27046ac74394SDon Skidmore 
27056ac74394SDon Skidmore 	/* Clear AN completed indication */
27066ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
27074dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
27086ac74394SDon Skidmore 				      &autoneg_reg);
27096ac74394SDon Skidmore 	if (status)
27106ac74394SDon Skidmore 		return status;
27116ac74394SDon Skidmore 
27124dc4000bSEmil Tantilov 	status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
27134dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
27146ac74394SDon Skidmore 				      &an_10g_cntl_reg);
27156ac74394SDon Skidmore 	if (status)
27166ac74394SDon Skidmore 		return status;
27176ac74394SDon Skidmore 
27186ac74394SDon Skidmore 	status = hw->phy.ops.read_reg(hw,
27196ac74394SDon Skidmore 				      IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
27204dc4000bSEmil Tantilov 				      MDIO_MMD_AN,
27216ac74394SDon Skidmore 				      &autoneg_reg);
27226ac74394SDon Skidmore 	if (status)
27236ac74394SDon Skidmore 		return status;
27246ac74394SDon Skidmore 
27256ac74394SDon Skidmore 	save_autoneg = hw->phy.autoneg_advertised;
27266ac74394SDon Skidmore 
27276ac74394SDon Skidmore 	/* Setup link at least common link speed */
27286ac74394SDon Skidmore 	status = hw->mac.ops.setup_link(hw, lcd_speed, false);
27296ac74394SDon Skidmore 
27306ac74394SDon Skidmore 	/* restore autoneg from before setting lplu speed */
27316ac74394SDon Skidmore 	hw->phy.autoneg_advertised = save_autoneg;
27326ac74394SDon Skidmore 
27336ac74394SDon Skidmore 	return status;
27346ac74394SDon Skidmore }
27356ac74394SDon Skidmore 
2736537cc5dfSMark Rustad /**
2737537cc5dfSMark Rustad  * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register
2738537cc5dfSMark Rustad  * @hw: pointer to hardware structure
2739537cc5dfSMark Rustad  *
2740537cc5dfSMark Rustad  * Read NW_MNG_IF_SEL register and save field values.
2741537cc5dfSMark Rustad  */
2742537cc5dfSMark Rustad static void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw)
2743537cc5dfSMark Rustad {
2744537cc5dfSMark Rustad 	/* Save NW management interface connected on board. This is used
2745537cc5dfSMark Rustad 	 * to determine internal PHY mode.
2746537cc5dfSMark Rustad 	 */
2747537cc5dfSMark Rustad 	hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
2748537cc5dfSMark Rustad 
2749537cc5dfSMark Rustad 	/* If X552 (X550EM_a) and MDIO is connected to external PHY, then set
2750537cc5dfSMark Rustad 	 * PHY address. This register field was has only been used for X552.
2751537cc5dfSMark Rustad 	 */
2752ae3cb8cbSMark Rustad 	if (hw->mac.type == ixgbe_mac_x550em_a &&
2753ae3cb8cbSMark Rustad 	    hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) {
2754537cc5dfSMark Rustad 		hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel &
2755537cc5dfSMark Rustad 				      IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
2756537cc5dfSMark Rustad 				     IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
2757537cc5dfSMark Rustad 	}
2758ae3cb8cbSMark Rustad }
2759537cc5dfSMark Rustad 
27606a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init
27616a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
27626a14ee0cSDon Skidmore  *
27636a14ee0cSDon Skidmore  *  Initialize any function pointers that were not able to be
27646a14ee0cSDon Skidmore  *  set during init_shared_code because the PHY/SFP type was
27656a14ee0cSDon Skidmore  *  not known.  Perform the SFP init if necessary.
27666a14ee0cSDon Skidmore  **/
27677ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
27686a14ee0cSDon Skidmore {
27696a14ee0cSDon Skidmore 	struct ixgbe_phy_info *phy = &hw->phy;
27706a14ee0cSDon Skidmore 	s32 ret_val;
27716a14ee0cSDon Skidmore 
27727e49d616SDon Skidmore 	hw->mac.ops.set_lan_id(hw);
27737e49d616SDon Skidmore 
2774537cc5dfSMark Rustad 	ixgbe_read_mng_if_sel_x550em(hw);
2775537cc5dfSMark Rustad 
2776c3dc4c09SDon Skidmore 	if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) {
27776a14ee0cSDon Skidmore 		phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
2778ab5fe0c5SDon Skidmore 		ixgbe_setup_mux_ctl(hw);
27796a14ee0cSDon Skidmore 	}
27806a14ee0cSDon Skidmore 
27816a14ee0cSDon Skidmore 	/* Identify the PHY or SFP module */
27826a14ee0cSDon Skidmore 	ret_val = phy->ops.identify(hw);
27836a14ee0cSDon Skidmore 
2784c3dc4c09SDon Skidmore 	/* Setup function pointers based on detected hardware */
27856a14ee0cSDon Skidmore 	ixgbe_init_mac_link_ops_X550em(hw);
27866a14ee0cSDon Skidmore 	if (phy->sfp_type != ixgbe_sfp_type_unknown)
27876a14ee0cSDon Skidmore 		phy->ops.reset = NULL;
27886a14ee0cSDon Skidmore 
27896a14ee0cSDon Skidmore 	/* Set functions pointers based on phy type */
27906a14ee0cSDon Skidmore 	switch (hw->phy.type) {
27916a14ee0cSDon Skidmore 	case ixgbe_phy_x550em_kx4:
27926a14ee0cSDon Skidmore 		phy->ops.setup_link = ixgbe_setup_kx4_x550em;
27936a14ee0cSDon Skidmore 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
27946a14ee0cSDon Skidmore 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
27956a14ee0cSDon Skidmore 		break;
27966a14ee0cSDon Skidmore 	case ixgbe_phy_x550em_kr:
27976a14ee0cSDon Skidmore 		phy->ops.setup_link = ixgbe_setup_kr_x550em;
27986a14ee0cSDon Skidmore 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
27996a14ee0cSDon Skidmore 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
28006a14ee0cSDon Skidmore 		break;
28016a14ee0cSDon Skidmore 	case ixgbe_phy_x550em_ext_t:
2802c3dc4c09SDon Skidmore 		/* Save NW management interface connected on board. This is used
2803c3dc4c09SDon Skidmore 		 * to determine internal PHY mode
2804c3dc4c09SDon Skidmore 		 */
2805c3dc4c09SDon Skidmore 		phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
2806c3dc4c09SDon Skidmore 
2807c3dc4c09SDon Skidmore 		/* If internal link mode is XFI, then setup iXFI internal link,
2808c3dc4c09SDon Skidmore 		 * else setup KR now.
2809c3dc4c09SDon Skidmore 		 */
2810c3dc4c09SDon Skidmore 		phy->ops.setup_internal_link =
2811c3dc4c09SDon Skidmore 					      ixgbe_setup_internal_phy_t_x550em;
2812c3dc4c09SDon Skidmore 
28136ac74394SDon Skidmore 		/* setup SW LPLU only for first revision */
28143ca2b250SMark Rustad 		if (hw->mac.type == ixgbe_mac_X550EM_x &&
28153ca2b250SMark Rustad 		    !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) &
28163ca2b250SMark Rustad 		      IXGBE_FUSES0_REV_MASK))
28176ac74394SDon Skidmore 			phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
28186ac74394SDon Skidmore 
2819c3dc4c09SDon Skidmore 		phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
2820f4410d2cSDon Skidmore 		phy->ops.reset = ixgbe_reset_phy_t_X550em;
28216a14ee0cSDon Skidmore 		break;
28226a14ee0cSDon Skidmore 	default:
28236a14ee0cSDon Skidmore 		break;
28246a14ee0cSDon Skidmore 	}
2825c3dc4c09SDon Skidmore 
28266a14ee0cSDon Skidmore 	return ret_val;
28276a14ee0cSDon Skidmore }
28286a14ee0cSDon Skidmore 
28296a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type
28306a14ee0cSDon Skidmore  *  @hw: pointer to hardware structure
28316a14ee0cSDon Skidmore  *
28326a14ee0cSDon Skidmore  *  Returns the media type (fiber, copper, backplane)
28336a14ee0cSDon Skidmore  *
28346a14ee0cSDon Skidmore  */
28357ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
28366a14ee0cSDon Skidmore {
28376a14ee0cSDon Skidmore 	enum ixgbe_media_type media_type;
28386a14ee0cSDon Skidmore 
28396a14ee0cSDon Skidmore 	/* Detect if there is a copper PHY attached. */
28406a14ee0cSDon Skidmore 	switch (hw->device_id) {
2841200157c2SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SGMII:
2842200157c2SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SGMII_L:
2843200157c2SMark Rustad 		hw->phy.type = ixgbe_phy_sgmii;
2844200157c2SMark Rustad 		/* Fallthrough */
28456a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_KR:
28466a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_KX4:
2847f572b2c4SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_KR:
2848f572b2c4SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_KR_L:
28496a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_backplane;
28506a14ee0cSDon Skidmore 		break;
28516a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_SFP:
28522d40cd17SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP:
285349425dfcSMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP_N:
28546a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_fiber;
28556a14ee0cSDon Skidmore 		break;
28566a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_1G_T:
28576a14ee0cSDon Skidmore 	case IXGBE_DEV_ID_X550EM_X_10G_T:
285892ed8430SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_10G_T:
28596a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_copper;
28606a14ee0cSDon Skidmore 		break;
28616a14ee0cSDon Skidmore 	default:
28626a14ee0cSDon Skidmore 		media_type = ixgbe_media_type_unknown;
28636a14ee0cSDon Skidmore 		break;
28646a14ee0cSDon Skidmore 	}
28656a14ee0cSDon Skidmore 	return media_type;
28666a14ee0cSDon Skidmore }
28676a14ee0cSDon Skidmore 
28686a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY.
28696a14ee0cSDon Skidmore  ** @hw: pointer to hardware structure
28706a14ee0cSDon Skidmore  **/
28717ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
28726a14ee0cSDon Skidmore {
2873a1e869deSMark Rustad 	s32 status;
28746a14ee0cSDon Skidmore 	u16 reg;
28756a14ee0cSDon Skidmore 
28766a14ee0cSDon Skidmore 	status = hw->phy.ops.read_reg(hw,
28776a14ee0cSDon Skidmore 				      IXGBE_MDIO_TX_VENDOR_ALARMS_3,
28784dc4000bSEmil Tantilov 				      MDIO_MMD_PMAPMD,
28796a14ee0cSDon Skidmore 				      &reg);
28806a14ee0cSDon Skidmore 	if (status)
28816a14ee0cSDon Skidmore 		return status;
28826a14ee0cSDon Skidmore 
2883e2261bccSDon Skidmore 	/* If PHY FW reset completed bit is set then this is the first
2884e2261bccSDon Skidmore 	 * SW instance after a power on so the PHY FW must be un-stalled.
2885e2261bccSDon Skidmore 	 */
2886e2261bccSDon Skidmore 	if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
28876a14ee0cSDon Skidmore 		status = hw->phy.ops.read_reg(hw,
28886a14ee0cSDon Skidmore 					IXGBE_MDIO_GLOBAL_RES_PR_10,
28894dc4000bSEmil Tantilov 					MDIO_MMD_VEND1,
28906a14ee0cSDon Skidmore 					&reg);
28916a14ee0cSDon Skidmore 		if (status)
28926a14ee0cSDon Skidmore 			return status;
28936a14ee0cSDon Skidmore 
28946a14ee0cSDon Skidmore 		reg &= ~IXGBE_MDIO_POWER_UP_STALL;
28956a14ee0cSDon Skidmore 
28966a14ee0cSDon Skidmore 		status = hw->phy.ops.write_reg(hw,
28976a14ee0cSDon Skidmore 					IXGBE_MDIO_GLOBAL_RES_PR_10,
28984dc4000bSEmil Tantilov 					MDIO_MMD_VEND1,
28996a14ee0cSDon Skidmore 					reg);
2900e2261bccSDon Skidmore 		if (status)
2901e2261bccSDon Skidmore 			return status;
2902e2261bccSDon Skidmore 	}
2903e2261bccSDon Skidmore 
29046a14ee0cSDon Skidmore 	return status;
29056a14ee0cSDon Skidmore }
29066a14ee0cSDon Skidmore 
2907e84db727SMark Rustad /**
2908e84db727SMark Rustad  * ixgbe_set_mdio_speed - Set MDIO clock speed
2909e84db727SMark Rustad  * @hw: pointer to hardware structure
2910e84db727SMark Rustad  */
2911e84db727SMark Rustad static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw)
2912e84db727SMark Rustad {
2913e84db727SMark Rustad 	u32 hlreg0;
2914e84db727SMark Rustad 
2915e84db727SMark Rustad 	switch (hw->device_id) {
2916e84db727SMark Rustad 	case IXGBE_DEV_ID_X550EM_X_10G_T:
2917a83c27e7SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_SGMII:
2918a83c27e7SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_SGMII_L:
291992ed8430SDon Skidmore 	case IXGBE_DEV_ID_X550EM_A_10G_T:
29202d40cd17SMark Rustad 	case IXGBE_DEV_ID_X550EM_A_SFP:
2921e84db727SMark Rustad 		/* Config MDIO clock speed before the first MDIO PHY access */
2922e84db727SMark Rustad 		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
2923e84db727SMark Rustad 		hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
2924e84db727SMark Rustad 		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
2925e84db727SMark Rustad 		break;
2926e84db727SMark Rustad 	default:
2927e84db727SMark Rustad 		break;
2928e84db727SMark Rustad 	}
2929e84db727SMark Rustad }
2930e84db727SMark Rustad 
29316a14ee0cSDon Skidmore /**  ixgbe_reset_hw_X550em - Perform hardware reset
29326a14ee0cSDon Skidmore  **  @hw: pointer to hardware structure
29336a14ee0cSDon Skidmore  **
29346a14ee0cSDon Skidmore  **  Resets the hardware by resetting the transmit and receive units, masks
29356a14ee0cSDon Skidmore  **  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
29366a14ee0cSDon Skidmore  **  reset.
29376a14ee0cSDon Skidmore  **/
29387ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
29396a14ee0cSDon Skidmore {
29406a14ee0cSDon Skidmore 	ixgbe_link_speed link_speed;
29416a14ee0cSDon Skidmore 	s32 status;
29426a14ee0cSDon Skidmore 	u32 ctrl = 0;
29436a14ee0cSDon Skidmore 	u32 i;
29446a14ee0cSDon Skidmore 	bool link_up = false;
29456a14ee0cSDon Skidmore 
29466a14ee0cSDon Skidmore 	/* Call adapter stop to disable Tx/Rx and clear interrupts */
29476a14ee0cSDon Skidmore 	status = hw->mac.ops.stop_adapter(hw);
29486a14ee0cSDon Skidmore 	if (status)
29496a14ee0cSDon Skidmore 		return status;
29506a14ee0cSDon Skidmore 
29516a14ee0cSDon Skidmore 	/* flush pending Tx transactions */
29526a14ee0cSDon Skidmore 	ixgbe_clear_tx_pending(hw);
29536a14ee0cSDon Skidmore 
29546a14ee0cSDon Skidmore 	/* PHY ops must be identified and initialized prior to reset */
29556a14ee0cSDon Skidmore 
29566a14ee0cSDon Skidmore 	/* Identify PHY and related function pointers */
29576a14ee0cSDon Skidmore 	status = hw->phy.ops.init(hw);
29586a14ee0cSDon Skidmore 
29596a14ee0cSDon Skidmore 	/* start the external PHY */
29606a14ee0cSDon Skidmore 	if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
29616a14ee0cSDon Skidmore 		status = ixgbe_init_ext_t_x550em(hw);
29626a14ee0cSDon Skidmore 		if (status)
29636a14ee0cSDon Skidmore 			return status;
29646a14ee0cSDon Skidmore 	}
29656a14ee0cSDon Skidmore 
29666a14ee0cSDon Skidmore 	/* Setup SFP module if there is one present. */
29676a14ee0cSDon Skidmore 	if (hw->phy.sfp_setup_needed) {
29686a14ee0cSDon Skidmore 		status = hw->mac.ops.setup_sfp(hw);
29696a14ee0cSDon Skidmore 		hw->phy.sfp_setup_needed = false;
29706a14ee0cSDon Skidmore 	}
29716a14ee0cSDon Skidmore 
29726a14ee0cSDon Skidmore 	/* Reset PHY */
29736a14ee0cSDon Skidmore 	if (!hw->phy.reset_disable && hw->phy.ops.reset)
29746a14ee0cSDon Skidmore 		hw->phy.ops.reset(hw);
29756a14ee0cSDon Skidmore 
29766a14ee0cSDon Skidmore mac_reset_top:
29776a14ee0cSDon Skidmore 	/* Issue global reset to the MAC.  Needs to be SW reset if link is up.
29786a14ee0cSDon Skidmore 	 * If link reset is used when link is up, it might reset the PHY when
29796a14ee0cSDon Skidmore 	 * mng is using it.  If link is down or the flag to force full link
29806a14ee0cSDon Skidmore 	 * reset is set, then perform link reset.
29816a14ee0cSDon Skidmore 	 */
29826a14ee0cSDon Skidmore 	ctrl = IXGBE_CTRL_LNK_RST;
29836a14ee0cSDon Skidmore 
29846a14ee0cSDon Skidmore 	if (!hw->force_full_reset) {
29856a14ee0cSDon Skidmore 		hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
29866a14ee0cSDon Skidmore 		if (link_up)
29876a14ee0cSDon Skidmore 			ctrl = IXGBE_CTRL_RST;
29886a14ee0cSDon Skidmore 	}
29896a14ee0cSDon Skidmore 
29906a14ee0cSDon Skidmore 	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
29916a14ee0cSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
29926a14ee0cSDon Skidmore 	IXGBE_WRITE_FLUSH(hw);
2993efff2e02SMark Rustad 	usleep_range(1000, 1200);
29946a14ee0cSDon Skidmore 
29956a14ee0cSDon Skidmore 	/* Poll for reset bit to self-clear meaning reset is complete */
29966a14ee0cSDon Skidmore 	for (i = 0; i < 10; i++) {
29976a14ee0cSDon Skidmore 		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
29986a14ee0cSDon Skidmore 		if (!(ctrl & IXGBE_CTRL_RST_MASK))
29996a14ee0cSDon Skidmore 			break;
3000efff2e02SMark Rustad 		udelay(1);
30016a14ee0cSDon Skidmore 	}
30026a14ee0cSDon Skidmore 
30036a14ee0cSDon Skidmore 	if (ctrl & IXGBE_CTRL_RST_MASK) {
30046a14ee0cSDon Skidmore 		status = IXGBE_ERR_RESET_FAILED;
30056a14ee0cSDon Skidmore 		hw_dbg(hw, "Reset polling failed to complete.\n");
30066a14ee0cSDon Skidmore 	}
30076a14ee0cSDon Skidmore 
30086a14ee0cSDon Skidmore 	msleep(50);
30096a14ee0cSDon Skidmore 
30106a14ee0cSDon Skidmore 	/* Double resets are required for recovery from certain error
30116a14ee0cSDon Skidmore 	 * clear the multicast table.  Also reset num_rar_entries to 128,
30126a14ee0cSDon Skidmore 	 * since we modify this value when programming the SAN MAC address.
30136a14ee0cSDon Skidmore 	 */
30146a14ee0cSDon Skidmore 	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
30156a14ee0cSDon Skidmore 		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
30166a14ee0cSDon Skidmore 		goto mac_reset_top;
30176a14ee0cSDon Skidmore 	}
30186a14ee0cSDon Skidmore 
30196a14ee0cSDon Skidmore 	/* Store the permanent mac address */
30206a14ee0cSDon Skidmore 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
30216a14ee0cSDon Skidmore 
30226a14ee0cSDon Skidmore 	/* Store MAC address from RAR0, clear receive address registers, and
30236a14ee0cSDon Skidmore 	 * clear the multicast table.  Also reset num_rar_entries to 128,
30246a14ee0cSDon Skidmore 	 * since we modify this value when programming the SAN MAC address.
30256a14ee0cSDon Skidmore 	 */
30266a14ee0cSDon Skidmore 	hw->mac.num_rar_entries = 128;
30276a14ee0cSDon Skidmore 	hw->mac.ops.init_rx_addrs(hw);
30286a14ee0cSDon Skidmore 
3029e84db727SMark Rustad 	ixgbe_set_mdio_speed(hw);
3030deda562aSDon Skidmore 
3031ab5fe0c5SDon Skidmore 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
3032ab5fe0c5SDon Skidmore 		ixgbe_setup_mux_ctl(hw);
3033ab5fe0c5SDon Skidmore 
30346a14ee0cSDon Skidmore 	return status;
30356a14ee0cSDon Skidmore }
30366a14ee0cSDon Skidmore 
30375b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype
30385b7f000fSDon Skidmore  *	anti-spoofing
30395b7f000fSDon Skidmore  *  @hw:  pointer to hardware structure
30405b7f000fSDon Skidmore  *  @enable: enable or disable switch for Ethertype anti-spoofing
30415b7f000fSDon Skidmore  *  @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing
30425b7f000fSDon Skidmore  **/
3043bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
3044bc035fc5SDon Skidmore 						   bool enable, int vf)
30455b7f000fSDon Skidmore {
30465b7f000fSDon Skidmore 	int vf_target_reg = vf >> 3;
30475b7f000fSDon Skidmore 	int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT;
30485b7f000fSDon Skidmore 	u32 pfvfspoof;
30495b7f000fSDon Skidmore 
30505b7f000fSDon Skidmore 	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
30515b7f000fSDon Skidmore 	if (enable)
3052b4f47a48SJacob Keller 		pfvfspoof |= BIT(vf_target_shift);
30535b7f000fSDon Skidmore 	else
3054b4f47a48SJacob Keller 		pfvfspoof &= ~BIT(vf_target_shift);
30555b7f000fSDon Skidmore 
30565b7f000fSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
30575b7f000fSDon Skidmore }
30585b7f000fSDon Skidmore 
30596d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning
30606d4c96adSDon Skidmore  *  @hw: pointer to hardware structure
30616d4c96adSDon Skidmore  *  @enable: enable or disable source address pruning
30626d4c96adSDon Skidmore  *  @pool: Rx pool to set source address pruning for
30636d4c96adSDon Skidmore  **/
30646d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
30656d4c96adSDon Skidmore 						  bool enable,
30666d4c96adSDon Skidmore 						  unsigned int pool)
30676d4c96adSDon Skidmore {
30686d4c96adSDon Skidmore 	u64 pfflp;
30696d4c96adSDon Skidmore 
30706d4c96adSDon Skidmore 	/* max rx pool is 63 */
30716d4c96adSDon Skidmore 	if (pool > 63)
30726d4c96adSDon Skidmore 		return;
30736d4c96adSDon Skidmore 
30746d4c96adSDon Skidmore 	pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL);
30756d4c96adSDon Skidmore 	pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32;
30766d4c96adSDon Skidmore 
30776d4c96adSDon Skidmore 	if (enable)
30786d4c96adSDon Skidmore 		pfflp |= (1ULL << pool);
30796d4c96adSDon Skidmore 	else
30806d4c96adSDon Skidmore 		pfflp &= ~(1ULL << pool);
30816d4c96adSDon Skidmore 
30826d4c96adSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp);
30836d4c96adSDon Skidmore 	IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32));
30846d4c96adSDon Skidmore }
30856d4c96adSDon Skidmore 
3086449e21a9SMark Rustad /**
30872916500dSDon Skidmore  *  ixgbe_setup_fc_backplane_x550em_a - Set up flow control
30882916500dSDon Skidmore  *  @hw: pointer to hardware structure
30892916500dSDon Skidmore  *
30902916500dSDon Skidmore  *  Called at init time to set up flow control.
30912916500dSDon Skidmore  **/
30922916500dSDon Skidmore static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw)
30932916500dSDon Skidmore {
30942916500dSDon Skidmore 	s32 status = 0;
30952916500dSDon Skidmore 	u32 an_cntl = 0;
30962916500dSDon Skidmore 
30972916500dSDon Skidmore 	/* Validate the requested mode */
30982916500dSDon Skidmore 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
30992916500dSDon Skidmore 		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
31002916500dSDon Skidmore 		return IXGBE_ERR_INVALID_LINK_SETTINGS;
31012916500dSDon Skidmore 	}
31022916500dSDon Skidmore 
31032916500dSDon Skidmore 	if (hw->fc.requested_mode == ixgbe_fc_default)
31042916500dSDon Skidmore 		hw->fc.requested_mode = ixgbe_fc_full;
31052916500dSDon Skidmore 
31062916500dSDon Skidmore 	/* Set up the 1G and 10G flow control advertisement registers so the
31072916500dSDon Skidmore 	 * HW will be able to do FC autoneg once the cable is plugged in.  If
31082916500dSDon Skidmore 	 * we link at 10G, the 1G advertisement is harmless and vice versa.
31092916500dSDon Skidmore 	 */
31102916500dSDon Skidmore 	status = hw->mac.ops.read_iosf_sb_reg(hw,
31112916500dSDon Skidmore 					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
31122916500dSDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl);
31132916500dSDon Skidmore 
31142916500dSDon Skidmore 	if (status) {
31152916500dSDon Skidmore 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
31162916500dSDon Skidmore 		return status;
31172916500dSDon Skidmore 	}
31182916500dSDon Skidmore 
31192916500dSDon Skidmore 	/* The possible values of fc.requested_mode are:
31202916500dSDon Skidmore 	 * 0: Flow control is completely disabled
31212916500dSDon Skidmore 	 * 1: Rx flow control is enabled (we can receive pause frames,
31222916500dSDon Skidmore 	 *    but not send pause frames).
31232916500dSDon Skidmore 	 * 2: Tx flow control is enabled (we can send pause frames but
31242916500dSDon Skidmore 	 *    we do not support receiving pause frames).
31252916500dSDon Skidmore 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
31262916500dSDon Skidmore 	 * other: Invalid.
31272916500dSDon Skidmore 	 */
31282916500dSDon Skidmore 	switch (hw->fc.requested_mode) {
31292916500dSDon Skidmore 	case ixgbe_fc_none:
31302916500dSDon Skidmore 		/* Flow control completely disabled by software override. */
31312916500dSDon Skidmore 		an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
31322916500dSDon Skidmore 			     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
31332916500dSDon Skidmore 		break;
31342916500dSDon Skidmore 	case ixgbe_fc_tx_pause:
31352916500dSDon Skidmore 		/* Tx Flow control is enabled, and Rx Flow control is
31362916500dSDon Skidmore 		 * disabled by software override.
31372916500dSDon Skidmore 		 */
31382916500dSDon Skidmore 		an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
31392916500dSDon Skidmore 		an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
31402916500dSDon Skidmore 		break;
31412916500dSDon Skidmore 	case ixgbe_fc_rx_pause:
31422916500dSDon Skidmore 		/* Rx Flow control is enabled and Tx Flow control is
31432916500dSDon Skidmore 		 * disabled by software override. Since there really
31442916500dSDon Skidmore 		 * isn't a way to advertise that we are capable of RX
31452916500dSDon Skidmore 		 * Pause ONLY, we will advertise that we support both
31462916500dSDon Skidmore 		 * symmetric and asymmetric Rx PAUSE, as such we fall
31472916500dSDon Skidmore 		 * through to the fc_full statement.  Later, we will
31482916500dSDon Skidmore 		 * disable the adapter's ability to send PAUSE frames.
31492916500dSDon Skidmore 		 */
31502916500dSDon Skidmore 	case ixgbe_fc_full:
31512916500dSDon Skidmore 		/* Flow control (both Rx and Tx) is enabled by SW override. */
31522916500dSDon Skidmore 		an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
31532916500dSDon Skidmore 			   IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
31542916500dSDon Skidmore 		break;
31552916500dSDon Skidmore 	default:
31562916500dSDon Skidmore 		hw_err(hw, "Flow control param set incorrectly\n");
31572916500dSDon Skidmore 		return IXGBE_ERR_CONFIG;
31582916500dSDon Skidmore 	}
31592916500dSDon Skidmore 
31602916500dSDon Skidmore 	status = hw->mac.ops.write_iosf_sb_reg(hw,
31612916500dSDon Skidmore 					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
31622916500dSDon Skidmore 					IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl);
31632916500dSDon Skidmore 
31642916500dSDon Skidmore 	/* Restart auto-negotiation. */
3165470739b5SDon Skidmore 	status = ixgbe_restart_an_internal_phy_x550em(hw);
31662916500dSDon Skidmore 
31672916500dSDon Skidmore 	return status;
31682916500dSDon Skidmore }
31692916500dSDon Skidmore 
31702916500dSDon Skidmore /**
3171449e21a9SMark Rustad  * ixgbe_set_mux - Set mux for port 1 access with CS4227
3172449e21a9SMark Rustad  * @hw: pointer to hardware structure
3173449e21a9SMark Rustad  * @state: set mux if 1, clear if 0
3174449e21a9SMark Rustad  */
3175449e21a9SMark Rustad static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state)
3176449e21a9SMark Rustad {
3177449e21a9SMark Rustad 	u32 esdp;
3178449e21a9SMark Rustad 
3179449e21a9SMark Rustad 	if (!hw->bus.lan_id)
3180449e21a9SMark Rustad 		return;
3181449e21a9SMark Rustad 	esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
3182449e21a9SMark Rustad 	if (state)
3183449e21a9SMark Rustad 		esdp |= IXGBE_ESDP_SDP1;
3184449e21a9SMark Rustad 	else
3185449e21a9SMark Rustad 		esdp &= ~IXGBE_ESDP_SDP1;
3186449e21a9SMark Rustad 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
3187449e21a9SMark Rustad 	IXGBE_WRITE_FLUSH(hw);
3188449e21a9SMark Rustad }
3189449e21a9SMark Rustad 
3190449e21a9SMark Rustad /**
3191449e21a9SMark Rustad  * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore
3192449e21a9SMark Rustad  * @hw: pointer to hardware structure
3193449e21a9SMark Rustad  * @mask: Mask to specify which semaphore to acquire
3194449e21a9SMark Rustad  *
3195449e21a9SMark Rustad  * Acquires the SWFW semaphore and sets the I2C MUX
3196449e21a9SMark Rustad  */
3197449e21a9SMark Rustad static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
3198449e21a9SMark Rustad {
3199449e21a9SMark Rustad 	s32 status;
3200449e21a9SMark Rustad 
3201449e21a9SMark Rustad 	status = ixgbe_acquire_swfw_sync_X540(hw, mask);
3202449e21a9SMark Rustad 	if (status)
3203449e21a9SMark Rustad 		return status;
3204449e21a9SMark Rustad 
3205449e21a9SMark Rustad 	if (mask & IXGBE_GSSR_I2C_MASK)
3206449e21a9SMark Rustad 		ixgbe_set_mux(hw, 1);
3207449e21a9SMark Rustad 
3208449e21a9SMark Rustad 	return 0;
3209449e21a9SMark Rustad }
3210449e21a9SMark Rustad 
3211449e21a9SMark Rustad /**
3212449e21a9SMark Rustad  * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore
3213449e21a9SMark Rustad  * @hw: pointer to hardware structure
3214449e21a9SMark Rustad  * @mask: Mask to specify which semaphore to release
3215449e21a9SMark Rustad  *
3216449e21a9SMark Rustad  * Releases the SWFW semaphore and sets the I2C MUX
3217449e21a9SMark Rustad  */
3218449e21a9SMark Rustad static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
3219449e21a9SMark Rustad {
3220449e21a9SMark Rustad 	if (mask & IXGBE_GSSR_I2C_MASK)
3221449e21a9SMark Rustad 		ixgbe_set_mux(hw, 0);
3222449e21a9SMark Rustad 
3223449e21a9SMark Rustad 	ixgbe_release_swfw_sync_X540(hw, mask);
3224449e21a9SMark Rustad }
3225449e21a9SMark Rustad 
322649425dfcSMark Rustad /**
322749425dfcSMark Rustad  * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore
322849425dfcSMark Rustad  * @hw: pointer to hardware structure
322949425dfcSMark Rustad  * @mask: Mask to specify which semaphore to acquire
323049425dfcSMark Rustad  *
323149425dfcSMark Rustad  * Acquires the SWFW semaphore and get the shared PHY token as needed
323249425dfcSMark Rustad  */
323349425dfcSMark Rustad static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask)
323449425dfcSMark Rustad {
323549425dfcSMark Rustad 	u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
323649425dfcSMark Rustad 	int retries = FW_PHY_TOKEN_RETRIES;
323749425dfcSMark Rustad 	s32 status;
323849425dfcSMark Rustad 
323949425dfcSMark Rustad 	while (--retries) {
324049425dfcSMark Rustad 		status = 0;
324149425dfcSMark Rustad 		if (hmask)
324249425dfcSMark Rustad 			status = ixgbe_acquire_swfw_sync_X540(hw, hmask);
324349425dfcSMark Rustad 		if (status)
324449425dfcSMark Rustad 			return status;
324549425dfcSMark Rustad 		if (!(mask & IXGBE_GSSR_TOKEN_SM))
324649425dfcSMark Rustad 			return 0;
324749425dfcSMark Rustad 
324849425dfcSMark Rustad 		status = ixgbe_get_phy_token(hw);
324949425dfcSMark Rustad 		if (!status)
325049425dfcSMark Rustad 			return 0;
325149425dfcSMark Rustad 		if (hmask)
325249425dfcSMark Rustad 			ixgbe_release_swfw_sync_X540(hw, hmask);
325349425dfcSMark Rustad 		if (status != IXGBE_ERR_TOKEN_RETRY)
325449425dfcSMark Rustad 			return status;
3255d4f90d9dSArnd Bergmann 		msleep(FW_PHY_TOKEN_DELAY);
325649425dfcSMark Rustad 	}
325749425dfcSMark Rustad 
325849425dfcSMark Rustad 	return status;
325949425dfcSMark Rustad }
326049425dfcSMark Rustad 
326149425dfcSMark Rustad /**
326249425dfcSMark Rustad  * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore
326349425dfcSMark Rustad  * @hw: pointer to hardware structure
326449425dfcSMark Rustad  * @mask: Mask to specify which semaphore to release
326549425dfcSMark Rustad  *
326649425dfcSMark Rustad  * Release the SWFW semaphore and puts the shared PHY token as needed
326749425dfcSMark Rustad  */
326849425dfcSMark Rustad static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask)
326949425dfcSMark Rustad {
327049425dfcSMark Rustad 	u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
327149425dfcSMark Rustad 
327249425dfcSMark Rustad 	if (mask & IXGBE_GSSR_TOKEN_SM)
327349425dfcSMark Rustad 		ixgbe_put_phy_token(hw);
327449425dfcSMark Rustad 
327549425dfcSMark Rustad 	if (hmask)
327649425dfcSMark Rustad 		ixgbe_release_swfw_sync_X540(hw, hmask);
327749425dfcSMark Rustad }
327849425dfcSMark Rustad 
3279d31afc8fSMark Rustad /**
3280d31afc8fSMark Rustad  * ixgbe_read_phy_reg_x550a - Reads specified PHY register
3281d31afc8fSMark Rustad  * @hw: pointer to hardware structure
3282d31afc8fSMark Rustad  * @reg_addr: 32 bit address of PHY register to read
3283d31afc8fSMark Rustad  * @phy_data: Pointer to read data from PHY register
3284d31afc8fSMark Rustad  *
3285d31afc8fSMark Rustad  * Reads a value from a specified PHY register using the SWFW lock and PHY
3286d31afc8fSMark Rustad  * Token. The PHY Token is needed since the MDIO is shared between to MAC
3287d31afc8fSMark Rustad  * instances.
3288d31afc8fSMark Rustad  */
3289d31afc8fSMark Rustad static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
3290d31afc8fSMark Rustad 				    u32 device_type, u16 *phy_data)
3291d31afc8fSMark Rustad {
3292d31afc8fSMark Rustad 	u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
3293d31afc8fSMark Rustad 	s32 status;
3294d31afc8fSMark Rustad 
3295d31afc8fSMark Rustad 	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
3296d31afc8fSMark Rustad 		return IXGBE_ERR_SWFW_SYNC;
3297d31afc8fSMark Rustad 
3298d31afc8fSMark Rustad 	status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data);
3299d31afc8fSMark Rustad 
3300d31afc8fSMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
3301d31afc8fSMark Rustad 
3302d31afc8fSMark Rustad 	return status;
3303d31afc8fSMark Rustad }
3304d31afc8fSMark Rustad 
3305d31afc8fSMark Rustad /**
3306d31afc8fSMark Rustad  * ixgbe_write_phy_reg_x550a - Writes specified PHY register
3307d31afc8fSMark Rustad  * @hw: pointer to hardware structure
3308d31afc8fSMark Rustad  * @reg_addr: 32 bit PHY register to write
3309d31afc8fSMark Rustad  * @device_type: 5 bit device type
3310d31afc8fSMark Rustad  * @phy_data: Data to write to the PHY register
3311d31afc8fSMark Rustad  *
3312d31afc8fSMark Rustad  * Writes a value to specified PHY register using the SWFW lock and PHY Token.
3313d31afc8fSMark Rustad  * The PHY Token is needed since the MDIO is shared between to MAC instances.
3314d31afc8fSMark Rustad  */
3315d31afc8fSMark Rustad static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
3316d31afc8fSMark Rustad 				     u32 device_type, u16 phy_data)
3317d31afc8fSMark Rustad {
3318d31afc8fSMark Rustad 	u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
3319d31afc8fSMark Rustad 	s32 status;
3320d31afc8fSMark Rustad 
3321d31afc8fSMark Rustad 	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
3322d31afc8fSMark Rustad 		return IXGBE_ERR_SWFW_SYNC;
3323d31afc8fSMark Rustad 
3324d31afc8fSMark Rustad 	status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data);
3325d31afc8fSMark Rustad 	hw->mac.ops.release_swfw_sync(hw, mask);
3326d31afc8fSMark Rustad 
3327d31afc8fSMark Rustad 	return status;
3328d31afc8fSMark Rustad }
3329d31afc8fSMark Rustad 
33306a14ee0cSDon Skidmore #define X550_COMMON_MAC \
33316a14ee0cSDon Skidmore 	.init_hw			= &ixgbe_init_hw_generic, \
33326a14ee0cSDon Skidmore 	.start_hw			= &ixgbe_start_hw_X540, \
33336a14ee0cSDon Skidmore 	.clear_hw_cntrs			= &ixgbe_clear_hw_cntrs_generic, \
33346a14ee0cSDon Skidmore 	.enable_rx_dma			= &ixgbe_enable_rx_dma_generic, \
33356a14ee0cSDon Skidmore 	.get_mac_addr			= &ixgbe_get_mac_addr_generic, \
33366a14ee0cSDon Skidmore 	.get_device_caps		= &ixgbe_get_device_caps_generic, \
33376a14ee0cSDon Skidmore 	.stop_adapter			= &ixgbe_stop_adapter_generic, \
33386a14ee0cSDon Skidmore 	.set_lan_id			= &ixgbe_set_lan_id_multi_port_pcie, \
33396a14ee0cSDon Skidmore 	.read_analog_reg8		= NULL, \
33406a14ee0cSDon Skidmore 	.write_analog_reg8		= NULL, \
33416a14ee0cSDon Skidmore 	.set_rxpba			= &ixgbe_set_rxpba_generic, \
33426a14ee0cSDon Skidmore 	.check_link			= &ixgbe_check_mac_link_generic, \
33436a14ee0cSDon Skidmore 	.blink_led_start		= &ixgbe_blink_led_start_X540, \
33446a14ee0cSDon Skidmore 	.blink_led_stop			= &ixgbe_blink_led_stop_X540, \
33456a14ee0cSDon Skidmore 	.set_rar			= &ixgbe_set_rar_generic, \
33466a14ee0cSDon Skidmore 	.clear_rar			= &ixgbe_clear_rar_generic, \
33476a14ee0cSDon Skidmore 	.set_vmdq			= &ixgbe_set_vmdq_generic, \
33486a14ee0cSDon Skidmore 	.set_vmdq_san_mac		= &ixgbe_set_vmdq_san_mac_generic, \
33496a14ee0cSDon Skidmore 	.clear_vmdq			= &ixgbe_clear_vmdq_generic, \
33506a14ee0cSDon Skidmore 	.init_rx_addrs			= &ixgbe_init_rx_addrs_generic, \
33516a14ee0cSDon Skidmore 	.update_mc_addr_list		= &ixgbe_update_mc_addr_list_generic, \
33526a14ee0cSDon Skidmore 	.enable_mc			= &ixgbe_enable_mc_generic, \
33536a14ee0cSDon Skidmore 	.disable_mc			= &ixgbe_disable_mc_generic, \
33546a14ee0cSDon Skidmore 	.clear_vfta			= &ixgbe_clear_vfta_generic, \
33556a14ee0cSDon Skidmore 	.set_vfta			= &ixgbe_set_vfta_generic, \
33566a14ee0cSDon Skidmore 	.fc_enable			= &ixgbe_fc_enable_generic, \
3357cb8e0514STony Nguyen 	.set_fw_drv_ver			= &ixgbe_set_fw_drv_ver_x550, \
33586a14ee0cSDon Skidmore 	.init_uta_tables		= &ixgbe_init_uta_tables_generic, \
33596a14ee0cSDon Skidmore 	.set_mac_anti_spoofing		= &ixgbe_set_mac_anti_spoofing, \
33606a14ee0cSDon Skidmore 	.set_vlan_anti_spoofing		= &ixgbe_set_vlan_anti_spoofing, \
33616d4c96adSDon Skidmore 	.set_source_address_pruning	= \
33626d4c96adSDon Skidmore 				&ixgbe_set_source_address_pruning_X550, \
33635b7f000fSDon Skidmore 	.set_ethertype_anti_spoofing	= \
33645b7f000fSDon Skidmore 				&ixgbe_set_ethertype_anti_spoofing_X550, \
33656a14ee0cSDon Skidmore 	.disable_rx_buff		= &ixgbe_disable_rx_buff_generic, \
33666a14ee0cSDon Skidmore 	.enable_rx_buff			= &ixgbe_enable_rx_buff_generic, \
33676a14ee0cSDon Skidmore 	.get_thermal_sensor_data	= NULL, \
33686a14ee0cSDon Skidmore 	.init_thermal_sensor_thresh	= NULL, \
33691f9ac57cSDon Skidmore 	.enable_rx			= &ixgbe_enable_rx_generic, \
33701f9ac57cSDon Skidmore 	.disable_rx			= &ixgbe_disable_rx_x550, \
33716a14ee0cSDon Skidmore 
337237689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550 = {
33736a14ee0cSDon Skidmore 	X550_COMMON_MAC
3374a0ad55a3SDon Skidmore 	.led_on			= ixgbe_led_on_generic,
3375a0ad55a3SDon Skidmore 	.led_off		= ixgbe_led_off_generic,
3376805cedd6SDon Skidmore 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
33776a14ee0cSDon Skidmore 	.reset_hw		= &ixgbe_reset_hw_X540,
33786a14ee0cSDon Skidmore 	.get_media_type		= &ixgbe_get_media_type_X540,
33796a14ee0cSDon Skidmore 	.get_san_mac_addr	= &ixgbe_get_san_mac_addr_generic,
33806a14ee0cSDon Skidmore 	.get_wwn_prefix		= &ixgbe_get_wwn_prefix_generic,
33816a14ee0cSDon Skidmore 	.setup_link		= &ixgbe_setup_mac_link_X540,
33826a14ee0cSDon Skidmore 	.get_link_capabilities	= &ixgbe_get_copper_link_capabilities_generic,
3383454c65ddSDon Skidmore 	.get_bus_info		= &ixgbe_get_bus_info_generic,
33846a14ee0cSDon Skidmore 	.setup_sfp		= NULL,
3385449e21a9SMark Rustad 	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X540,
3386449e21a9SMark Rustad 	.release_swfw_sync	= &ixgbe_release_swfw_sync_X540,
3387dbd15b8fSDon Skidmore 	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
3388afdc71e4SMark Rustad 	.prot_autoc_read	= prot_autoc_read_generic,
3389afdc71e4SMark Rustad 	.prot_autoc_write	= prot_autoc_write_generic,
3390afdc71e4SMark Rustad 	.setup_fc		= ixgbe_setup_fc_generic,
33912916500dSDon Skidmore 	.fc_autoneg		= ixgbe_fc_autoneg,
33926a14ee0cSDon Skidmore };
33936a14ee0cSDon Skidmore 
339437689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550EM_x = {
33956a14ee0cSDon Skidmore 	X550_COMMON_MAC
3396a0ad55a3SDon Skidmore 	.led_on			= ixgbe_led_on_t_x550em,
3397a0ad55a3SDon Skidmore 	.led_off		= ixgbe_led_off_t_x550em,
3398805cedd6SDon Skidmore 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
33996a14ee0cSDon Skidmore 	.reset_hw		= &ixgbe_reset_hw_X550em,
34006a14ee0cSDon Skidmore 	.get_media_type		= &ixgbe_get_media_type_X550em,
34016a14ee0cSDon Skidmore 	.get_san_mac_addr	= NULL,
34026a14ee0cSDon Skidmore 	.get_wwn_prefix		= NULL,
34034695886cSEmil Tantilov 	.setup_link		= &ixgbe_setup_mac_link_X540,
34046a14ee0cSDon Skidmore 	.get_link_capabilities	= &ixgbe_get_link_capabilities_X550em,
3405454c65ddSDon Skidmore 	.get_bus_info		= &ixgbe_get_bus_info_X550em,
34066a14ee0cSDon Skidmore 	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
3407449e21a9SMark Rustad 	.acquire_swfw_sync	= &ixgbe_acquire_swfw_sync_X550em,
3408449e21a9SMark Rustad 	.release_swfw_sync	= &ixgbe_release_swfw_sync_X550em,
3409dbd15b8fSDon Skidmore 	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
3410afdc71e4SMark Rustad 	.setup_fc		= NULL, /* defined later */
34112916500dSDon Skidmore 	.fc_autoneg		= ixgbe_fc_autoneg,
34129a5c27e6SMark Rustad 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550,
34139a5c27e6SMark Rustad 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550,
34146a14ee0cSDon Skidmore };
34156a14ee0cSDon Skidmore 
341649425dfcSMark Rustad static struct ixgbe_mac_operations mac_ops_x550em_a = {
341749425dfcSMark Rustad 	X550_COMMON_MAC
3418a0ad55a3SDon Skidmore 	.led_on			= ixgbe_led_on_t_x550em,
3419a0ad55a3SDon Skidmore 	.led_off		= ixgbe_led_off_t_x550em,
3420805cedd6SDon Skidmore 	.init_led_link_act	= ixgbe_init_led_link_act_generic,
342149425dfcSMark Rustad 	.reset_hw		= ixgbe_reset_hw_X550em,
342249425dfcSMark Rustad 	.get_media_type		= ixgbe_get_media_type_X550em,
342349425dfcSMark Rustad 	.get_san_mac_addr	= NULL,
342449425dfcSMark Rustad 	.get_wwn_prefix		= NULL,
3425a0254a70SMark Rustad 	.setup_link		= NULL, /* defined later */
342649425dfcSMark Rustad 	.get_link_capabilities	= ixgbe_get_link_capabilities_X550em,
342749425dfcSMark Rustad 	.get_bus_info		= ixgbe_get_bus_info_X550em,
342849425dfcSMark Rustad 	.setup_sfp		= ixgbe_setup_sfp_modules_X550em,
342949425dfcSMark Rustad 	.acquire_swfw_sync	= ixgbe_acquire_swfw_sync_x550em_a,
343049425dfcSMark Rustad 	.release_swfw_sync	= ixgbe_release_swfw_sync_x550em_a,
3431a0254a70SMark Rustad 	.setup_fc		= ixgbe_setup_fc_x550em,
3432470739b5SDon Skidmore 	.fc_autoneg		= ixgbe_fc_autoneg,
343349425dfcSMark Rustad 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550a,
343449425dfcSMark Rustad 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550a,
343549425dfcSMark Rustad };
343649425dfcSMark Rustad 
34376a14ee0cSDon Skidmore #define X550_COMMON_EEP \
34386a14ee0cSDon Skidmore 	.read			= &ixgbe_read_ee_hostif_X550, \
34396a14ee0cSDon Skidmore 	.read_buffer		= &ixgbe_read_ee_hostif_buffer_X550, \
34406a14ee0cSDon Skidmore 	.write			= &ixgbe_write_ee_hostif_X550, \
34416a14ee0cSDon Skidmore 	.write_buffer		= &ixgbe_write_ee_hostif_buffer_X550, \
34426a14ee0cSDon Skidmore 	.validate_checksum	= &ixgbe_validate_eeprom_checksum_X550, \
34436a14ee0cSDon Skidmore 	.update_checksum	= &ixgbe_update_eeprom_checksum_X550, \
34446a14ee0cSDon Skidmore 	.calc_checksum		= &ixgbe_calc_eeprom_checksum_X550, \
34456a14ee0cSDon Skidmore 
344637689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550 = {
34476a14ee0cSDon Skidmore 	X550_COMMON_EEP
34486a14ee0cSDon Skidmore 	.init_params		= &ixgbe_init_eeprom_params_X550,
34496a14ee0cSDon Skidmore };
34506a14ee0cSDon Skidmore 
345137689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = {
34526a14ee0cSDon Skidmore 	X550_COMMON_EEP
34536a14ee0cSDon Skidmore 	.init_params		= &ixgbe_init_eeprom_params_X540,
34546a14ee0cSDon Skidmore };
34556a14ee0cSDon Skidmore 
34566a14ee0cSDon Skidmore #define X550_COMMON_PHY	\
34576a14ee0cSDon Skidmore 	.identify_sfp		= &ixgbe_identify_module_generic, \
34586a14ee0cSDon Skidmore 	.reset			= NULL, \
34596a14ee0cSDon Skidmore 	.setup_link_speed	= &ixgbe_setup_phy_link_speed_generic, \
34606a14ee0cSDon Skidmore 	.read_i2c_byte		= &ixgbe_read_i2c_byte_generic, \
34616a14ee0cSDon Skidmore 	.write_i2c_byte		= &ixgbe_write_i2c_byte_generic, \
34626a14ee0cSDon Skidmore 	.read_i2c_sff8472	= &ixgbe_read_i2c_sff8472_generic, \
34636a14ee0cSDon Skidmore 	.read_i2c_eeprom	= &ixgbe_read_i2c_eeprom_generic, \
34646a14ee0cSDon Skidmore 	.write_i2c_eeprom	= &ixgbe_write_i2c_eeprom_generic, \
3465bef23de1SDon Skidmore 	.setup_link		= &ixgbe_setup_phy_link_generic, \
3466b5529ef5SDon Skidmore 	.set_phy_power		= NULL, \
3467d2a10ae7SMark Rustad 	.check_overtemp		= &ixgbe_tn_check_overtemp,
34686a14ee0cSDon Skidmore 
346937689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550 = {
34706a14ee0cSDon Skidmore 	X550_COMMON_PHY
34716a14ee0cSDon Skidmore 	.init			= NULL,
34726a14ee0cSDon Skidmore 	.identify		= &ixgbe_identify_phy_generic,
3473d31afc8fSMark Rustad 	.read_reg		= &ixgbe_read_phy_reg_generic,
3474d31afc8fSMark Rustad 	.write_reg		= &ixgbe_write_phy_reg_generic,
34756a14ee0cSDon Skidmore };
34766a14ee0cSDon Skidmore 
347737689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550EM_x = {
34786a14ee0cSDon Skidmore 	X550_COMMON_PHY
34796a14ee0cSDon Skidmore 	.init			= &ixgbe_init_phy_ops_X550em,
34806a14ee0cSDon Skidmore 	.identify		= &ixgbe_identify_phy_x550em,
3481d31afc8fSMark Rustad 	.read_reg		= &ixgbe_read_phy_reg_generic,
3482d31afc8fSMark Rustad 	.write_reg		= &ixgbe_write_phy_reg_generic,
34836a14ee0cSDon Skidmore };
34846a14ee0cSDon Skidmore 
3485d31afc8fSMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a = {
3486d31afc8fSMark Rustad 	X550_COMMON_PHY
3487d31afc8fSMark Rustad 	.init			= &ixgbe_init_phy_ops_X550em,
3488d31afc8fSMark Rustad 	.identify		= &ixgbe_identify_phy_x550em,
3489d31afc8fSMark Rustad 	.read_reg		= &ixgbe_read_phy_reg_x550a,
3490d31afc8fSMark Rustad 	.write_reg		= &ixgbe_write_phy_reg_x550a,
34918fe293aaSMark Rustad 	.read_reg_mdi		= &ixgbe_read_phy_reg_mdi,
34928fe293aaSMark Rustad 	.write_reg_mdi		= &ixgbe_write_phy_reg_mdi,
3493d31afc8fSMark Rustad };
3494d31afc8fSMark Rustad 
3495b71f6c40SEmil Tantilov static const struct ixgbe_link_operations link_ops_x550em_x = {
3496b71f6c40SEmil Tantilov 	.read_link		= &ixgbe_read_i2c_combined_generic,
3497b71f6c40SEmil Tantilov 	.read_link_unlocked	= &ixgbe_read_i2c_combined_generic_unlocked,
3498b71f6c40SEmil Tantilov 	.write_link		= &ixgbe_write_i2c_combined_generic,
3499b71f6c40SEmil Tantilov 	.write_link_unlocked	= &ixgbe_write_i2c_combined_generic_unlocked,
3500b71f6c40SEmil Tantilov };
3501b71f6c40SEmil Tantilov 
35029a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = {
35039a900ecaSDon Skidmore 	IXGBE_MVALS_INIT(X550)
35049a900ecaSDon Skidmore };
35059a900ecaSDon Skidmore 
35069a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = {
35079a900ecaSDon Skidmore 	IXGBE_MVALS_INIT(X550EM_x)
35089a900ecaSDon Skidmore };
35099a900ecaSDon Skidmore 
351049425dfcSMark Rustad static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = {
351149425dfcSMark Rustad 	IXGBE_MVALS_INIT(X550EM_a)
351249425dfcSMark Rustad };
351349425dfcSMark Rustad 
351437689010SMark Rustad const struct ixgbe_info ixgbe_X550_info = {
35156a14ee0cSDon Skidmore 	.mac			= ixgbe_mac_X550,
35166a14ee0cSDon Skidmore 	.get_invariants		= &ixgbe_get_invariants_X540,
35176a14ee0cSDon Skidmore 	.mac_ops		= &mac_ops_X550,
35186a14ee0cSDon Skidmore 	.eeprom_ops		= &eeprom_ops_X550,
35196a14ee0cSDon Skidmore 	.phy_ops		= &phy_ops_X550,
35206a14ee0cSDon Skidmore 	.mbx_ops		= &mbx_ops_generic,
35219a900ecaSDon Skidmore 	.mvals			= ixgbe_mvals_X550,
35226a14ee0cSDon Skidmore };
35236a14ee0cSDon Skidmore 
352437689010SMark Rustad const struct ixgbe_info ixgbe_X550EM_x_info = {
35256a14ee0cSDon Skidmore 	.mac			= ixgbe_mac_X550EM_x,
3526b5529ef5SDon Skidmore 	.get_invariants		= &ixgbe_get_invariants_X550_x,
35276a14ee0cSDon Skidmore 	.mac_ops		= &mac_ops_X550EM_x,
35286a14ee0cSDon Skidmore 	.eeprom_ops		= &eeprom_ops_X550EM_x,
35296a14ee0cSDon Skidmore 	.phy_ops		= &phy_ops_X550EM_x,
35306a14ee0cSDon Skidmore 	.mbx_ops		= &mbx_ops_generic,
35319a900ecaSDon Skidmore 	.mvals			= ixgbe_mvals_X550EM_x,
3532b71f6c40SEmil Tantilov 	.link_ops		= &link_ops_x550em_x,
35336a14ee0cSDon Skidmore };
353449425dfcSMark Rustad 
353549425dfcSMark Rustad const struct ixgbe_info ixgbe_x550em_a_info = {
353649425dfcSMark Rustad 	.mac			= ixgbe_mac_x550em_a,
3537b71f6c40SEmil Tantilov 	.get_invariants		= &ixgbe_get_invariants_X550_a,
353849425dfcSMark Rustad 	.mac_ops		= &mac_ops_x550em_a,
353949425dfcSMark Rustad 	.eeprom_ops		= &eeprom_ops_X550EM_x,
3540d31afc8fSMark Rustad 	.phy_ops		= &phy_ops_x550em_a,
354149425dfcSMark Rustad 	.mbx_ops		= &mbx_ops_generic,
354249425dfcSMark Rustad 	.mvals			= ixgbe_mvals_x550em_a,
354349425dfcSMark Rustad };
3544