1dc0cb1cdSDale Ghent /******************************************************************************
2dc0cb1cdSDale Ghent 
3*48ed61a7SRobert Mustacchi   Copyright (c) 2001-2017, Intel Corporation
4dc0cb1cdSDale Ghent   All rights reserved.
5*48ed61a7SRobert Mustacchi 
6*48ed61a7SRobert Mustacchi   Redistribution and use in source and binary forms, with or without
7dc0cb1cdSDale Ghent   modification, are permitted provided that the following conditions are met:
8*48ed61a7SRobert Mustacchi 
9*48ed61a7SRobert Mustacchi    1. Redistributions of source code must retain the above copyright notice,
10dc0cb1cdSDale Ghent       this list of conditions and the following disclaimer.
11*48ed61a7SRobert Mustacchi 
12*48ed61a7SRobert Mustacchi    2. Redistributions in binary form must reproduce the above copyright
13*48ed61a7SRobert Mustacchi       notice, this list of conditions and the following disclaimer in the
14dc0cb1cdSDale Ghent       documentation and/or other materials provided with the distribution.
15*48ed61a7SRobert Mustacchi 
16*48ed61a7SRobert Mustacchi    3. Neither the name of the Intel Corporation nor the names of its
17*48ed61a7SRobert Mustacchi       contributors may be used to endorse or promote products derived from
18dc0cb1cdSDale Ghent       this software without specific prior written permission.
19*48ed61a7SRobert Mustacchi 
20dc0cb1cdSDale Ghent   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21*48ed61a7SRobert Mustacchi   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*48ed61a7SRobert Mustacchi   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*48ed61a7SRobert Mustacchi   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24*48ed61a7SRobert Mustacchi   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25*48ed61a7SRobert Mustacchi   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26*48ed61a7SRobert Mustacchi   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27*48ed61a7SRobert Mustacchi   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28*48ed61a7SRobert Mustacchi   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29dc0cb1cdSDale Ghent   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30dc0cb1cdSDale Ghent   POSSIBILITY OF SUCH DAMAGE.
31dc0cb1cdSDale Ghent 
32dc0cb1cdSDale Ghent ******************************************************************************/
33dc0cb1cdSDale Ghent /*$FreeBSD$*/
34dc0cb1cdSDale Ghent 
35dc0cb1cdSDale Ghent #include "ixgbe_x550.h"
36dc0cb1cdSDale Ghent #include "ixgbe_x540.h"
37dc0cb1cdSDale Ghent #include "ixgbe_type.h"
38dc0cb1cdSDale Ghent #include "ixgbe_api.h"
39dc0cb1cdSDale Ghent #include "ixgbe_common.h"
40dc0cb1cdSDale Ghent #include "ixgbe_phy.h"
41dc0cb1cdSDale Ghent 
42dc0cb1cdSDale Ghent static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed);
43*48ed61a7SRobert Mustacchi static s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
44*48ed61a7SRobert Mustacchi static void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
45*48ed61a7SRobert Mustacchi static s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw);
46dc0cb1cdSDale Ghent 
47dc0cb1cdSDale Ghent /**
48dc0cb1cdSDale Ghent  *  ixgbe_init_ops_X550 - Inits func ptrs and MAC type
49dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
50dc0cb1cdSDale Ghent  *
51dc0cb1cdSDale Ghent  *  Initialize the function pointers and assign the MAC type for X550.
52dc0cb1cdSDale Ghent  *  Does not touch the hardware.
53dc0cb1cdSDale Ghent  **/
ixgbe_init_ops_X550(struct ixgbe_hw * hw)54dc0cb1cdSDale Ghent s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw)
55dc0cb1cdSDale Ghent {
56dc0cb1cdSDale Ghent 	struct ixgbe_mac_info *mac = &hw->mac;
57dc0cb1cdSDale Ghent 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
58dc0cb1cdSDale Ghent 	s32 ret_val;
59dc0cb1cdSDale Ghent 
60dc0cb1cdSDale Ghent 	DEBUGFUNC("ixgbe_init_ops_X550");
61dc0cb1cdSDale Ghent 
62dc0cb1cdSDale Ghent 	ret_val = ixgbe_init_ops_X540(hw);
63dc0cb1cdSDale Ghent 	mac->ops.dmac_config = ixgbe_dmac_config_X550;
64dc0cb1cdSDale Ghent 	mac->ops.dmac_config_tcs = ixgbe_dmac_config_tcs_X550;
65dc0cb1cdSDale Ghent 	mac->ops.dmac_update_tcs = ixgbe_dmac_update_tcs_X550;
66*48ed61a7SRobert Mustacchi 	mac->ops.setup_eee = NULL;
67dc0cb1cdSDale Ghent 	mac->ops.set_source_address_pruning =
68dc0cb1cdSDale Ghent 			ixgbe_set_source_address_pruning_X550;
69dc0cb1cdSDale Ghent 	mac->ops.set_ethertype_anti_spoofing =
70dc0cb1cdSDale Ghent 			ixgbe_set_ethertype_anti_spoofing_X550;
71dc0cb1cdSDale Ghent 
72dc0cb1cdSDale Ghent 	mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
73dc0cb1cdSDale Ghent 	eeprom->ops.init_params = ixgbe_init_eeprom_params_X550;
74dc0cb1cdSDale Ghent 	eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
75dc0cb1cdSDale Ghent 	eeprom->ops.read = ixgbe_read_ee_hostif_X550;
76dc0cb1cdSDale Ghent 	eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550;
77dc0cb1cdSDale Ghent 	eeprom->ops.write = ixgbe_write_ee_hostif_X550;
78dc0cb1cdSDale Ghent 	eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550;
79dc0cb1cdSDale Ghent 	eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
80dc0cb1cdSDale Ghent 	eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
81dc0cb1cdSDale Ghent 
82dc0cb1cdSDale Ghent 	mac->ops.disable_mdd = ixgbe_disable_mdd_X550;
83dc0cb1cdSDale Ghent 	mac->ops.enable_mdd = ixgbe_enable_mdd_X550;
84dc0cb1cdSDale Ghent 	mac->ops.mdd_event = ixgbe_mdd_event_X550;
85dc0cb1cdSDale Ghent 	mac->ops.restore_mdd_vf = ixgbe_restore_mdd_vf_X550;
86dc0cb1cdSDale Ghent 	mac->ops.disable_rx = ixgbe_disable_rx_x550;
87*48ed61a7SRobert Mustacchi 	/* Manageability interface */
88*48ed61a7SRobert Mustacchi 	mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_x550;
89*48ed61a7SRobert Mustacchi 	switch (hw->device_id) {
90*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_X_1G_T:
91*48ed61a7SRobert Mustacchi 		hw->mac.ops.led_on = NULL;
92*48ed61a7SRobert Mustacchi 		hw->mac.ops.led_off = NULL;
93*48ed61a7SRobert Mustacchi 		break;
94*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_X_10G_T:
95*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_A_10G_T:
96dc0cb1cdSDale Ghent 		hw->mac.ops.led_on = ixgbe_led_on_t_X550em;
97dc0cb1cdSDale Ghent 		hw->mac.ops.led_off = ixgbe_led_off_t_X550em;
98*48ed61a7SRobert Mustacchi 		break;
99*48ed61a7SRobert Mustacchi 	default:
100*48ed61a7SRobert Mustacchi 		break;
101dc0cb1cdSDale Ghent 	}
102dc0cb1cdSDale Ghent 	return ret_val;
103dc0cb1cdSDale Ghent }
104dc0cb1cdSDale Ghent 
105dc0cb1cdSDale Ghent /**
106dc0cb1cdSDale Ghent  * ixgbe_read_cs4227 - Read CS4227 register
107dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
108dc0cb1cdSDale Ghent  * @reg: register number to write
109dc0cb1cdSDale Ghent  * @value: pointer to receive value read
110dc0cb1cdSDale Ghent  *
111dc0cb1cdSDale Ghent  * Returns status code
112dc0cb1cdSDale Ghent  **/
ixgbe_read_cs4227(struct ixgbe_hw * hw,u16 reg,u16 * value)113dc0cb1cdSDale Ghent static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
114dc0cb1cdSDale Ghent {
115*48ed61a7SRobert Mustacchi 	return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);
116dc0cb1cdSDale Ghent }
117dc0cb1cdSDale Ghent 
118dc0cb1cdSDale Ghent /**
119dc0cb1cdSDale Ghent  * ixgbe_write_cs4227 - Write CS4227 register
120dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
121dc0cb1cdSDale Ghent  * @reg: register number to write
122dc0cb1cdSDale Ghent  * @value: value to write to register
123dc0cb1cdSDale Ghent  *
124dc0cb1cdSDale Ghent  * Returns status code
125dc0cb1cdSDale Ghent  **/
ixgbe_write_cs4227(struct ixgbe_hw * hw,u16 reg,u16 value)126dc0cb1cdSDale Ghent static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
127dc0cb1cdSDale Ghent {
128*48ed61a7SRobert Mustacchi 	return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);
129dc0cb1cdSDale Ghent }
130dc0cb1cdSDale Ghent 
131dc0cb1cdSDale Ghent /**
132dc0cb1cdSDale Ghent  * ixgbe_read_pe - Read register from port expander
133dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
134dc0cb1cdSDale Ghent  * @reg: register number to read
135dc0cb1cdSDale Ghent  * @value: pointer to receive read value
136dc0cb1cdSDale Ghent  *
137dc0cb1cdSDale Ghent  * Returns status code
138dc0cb1cdSDale Ghent  **/
ixgbe_read_pe(struct ixgbe_hw * hw,u8 reg,u8 * value)139dc0cb1cdSDale Ghent static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value)
140dc0cb1cdSDale Ghent {
141dc0cb1cdSDale Ghent 	s32 status;
142dc0cb1cdSDale Ghent 
143dc0cb1cdSDale Ghent 	status = ixgbe_read_i2c_byte_unlocked(hw, reg, IXGBE_PE, value);
144dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
145dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_CAUTION,
146dc0cb1cdSDale Ghent 			      "port expander access failed with %d\n", status);
147dc0cb1cdSDale Ghent 	return status;
148dc0cb1cdSDale Ghent }
149dc0cb1cdSDale Ghent 
150dc0cb1cdSDale Ghent /**
151dc0cb1cdSDale Ghent  * ixgbe_write_pe - Write register to port expander
152dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
153dc0cb1cdSDale Ghent  * @reg: register number to write
154dc0cb1cdSDale Ghent  * @value: value to write
155dc0cb1cdSDale Ghent  *
156dc0cb1cdSDale Ghent  * Returns status code
157dc0cb1cdSDale Ghent  **/
ixgbe_write_pe(struct ixgbe_hw * hw,u8 reg,u8 value)158dc0cb1cdSDale Ghent static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value)
159dc0cb1cdSDale Ghent {
160dc0cb1cdSDale Ghent 	s32 status;
161dc0cb1cdSDale Ghent 
162dc0cb1cdSDale Ghent 	status = ixgbe_write_i2c_byte_unlocked(hw, reg, IXGBE_PE, value);
163dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
164dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_CAUTION,
165dc0cb1cdSDale Ghent 			      "port expander access failed with %d\n", status);
166dc0cb1cdSDale Ghent 	return status;
167dc0cb1cdSDale Ghent }
168dc0cb1cdSDale Ghent 
169dc0cb1cdSDale Ghent /**
170dc0cb1cdSDale Ghent  * ixgbe_reset_cs4227 - Reset CS4227 using port expander
171dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
172dc0cb1cdSDale Ghent  *
173dc0cb1cdSDale Ghent  * This function assumes that the caller has acquired the proper semaphore.
174dc0cb1cdSDale Ghent  * Returns error code
175dc0cb1cdSDale Ghent  **/
ixgbe_reset_cs4227(struct ixgbe_hw * hw)176dc0cb1cdSDale Ghent static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
177dc0cb1cdSDale Ghent {
178dc0cb1cdSDale Ghent 	s32 status;
179dc0cb1cdSDale Ghent 	u32 retry;
180dc0cb1cdSDale Ghent 	u16 value;
181dc0cb1cdSDale Ghent 	u8 reg;
182dc0cb1cdSDale Ghent 
183dc0cb1cdSDale Ghent 	/* Trigger hard reset. */
184dc0cb1cdSDale Ghent 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
185dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
186dc0cb1cdSDale Ghent 		return status;
187dc0cb1cdSDale Ghent 	reg |= IXGBE_PE_BIT1;
188dc0cb1cdSDale Ghent 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
189dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
190dc0cb1cdSDale Ghent 		return status;
191dc0cb1cdSDale Ghent 
192dc0cb1cdSDale Ghent 	status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, &reg);
193dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
194dc0cb1cdSDale Ghent 		return status;
195dc0cb1cdSDale Ghent 	reg &= ~IXGBE_PE_BIT1;
196dc0cb1cdSDale Ghent 	status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg);
197dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
198dc0cb1cdSDale Ghent 		return status;
199dc0cb1cdSDale Ghent 
200dc0cb1cdSDale Ghent 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
201dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
202dc0cb1cdSDale Ghent 		return status;
203dc0cb1cdSDale Ghent 	reg &= ~IXGBE_PE_BIT1;
204dc0cb1cdSDale Ghent 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
205dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
206dc0cb1cdSDale Ghent 		return status;
207dc0cb1cdSDale Ghent 
208dc0cb1cdSDale Ghent 	usec_delay(IXGBE_CS4227_RESET_HOLD);
209dc0cb1cdSDale Ghent 
210dc0cb1cdSDale Ghent 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
211dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
212dc0cb1cdSDale Ghent 		return status;
213dc0cb1cdSDale Ghent 	reg |= IXGBE_PE_BIT1;
214dc0cb1cdSDale Ghent 	status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
215dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
216dc0cb1cdSDale Ghent 		return status;
217dc0cb1cdSDale Ghent 
218dc0cb1cdSDale Ghent 	/* Wait for the reset to complete. */
219dc0cb1cdSDale Ghent 	msec_delay(IXGBE_CS4227_RESET_DELAY);
220dc0cb1cdSDale Ghent 	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
221dc0cb1cdSDale Ghent 		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
222dc0cb1cdSDale Ghent 					   &value);
223dc0cb1cdSDale Ghent 		if (status == IXGBE_SUCCESS &&
224dc0cb1cdSDale Ghent 		    value == IXGBE_CS4227_EEPROM_LOAD_OK)
225dc0cb1cdSDale Ghent 			break;
226dc0cb1cdSDale Ghent 		msec_delay(IXGBE_CS4227_CHECK_DELAY);
227dc0cb1cdSDale Ghent 	}
228dc0cb1cdSDale Ghent 	if (retry == IXGBE_CS4227_RETRIES) {
229dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
230dc0cb1cdSDale Ghent 			"CS4227 reset did not complete.");
231dc0cb1cdSDale Ghent 		return IXGBE_ERR_PHY;
232dc0cb1cdSDale Ghent 	}
233dc0cb1cdSDale Ghent 
234dc0cb1cdSDale Ghent 	status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
235dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS ||
236dc0cb1cdSDale Ghent 	    !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
237dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
238dc0cb1cdSDale Ghent 			"CS4227 EEPROM did not load successfully.");
239dc0cb1cdSDale Ghent 		return IXGBE_ERR_PHY;
240dc0cb1cdSDale Ghent 	}
241dc0cb1cdSDale Ghent 
242dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
243dc0cb1cdSDale Ghent }
244dc0cb1cdSDale Ghent 
245dc0cb1cdSDale Ghent /**
246dc0cb1cdSDale Ghent  * ixgbe_check_cs4227 - Check CS4227 and reset as needed
247dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
248dc0cb1cdSDale Ghent  **/
ixgbe_check_cs4227(struct ixgbe_hw * hw)249dc0cb1cdSDale Ghent static void ixgbe_check_cs4227(struct ixgbe_hw *hw)
250dc0cb1cdSDale Ghent {
251dc0cb1cdSDale Ghent 	s32 status = IXGBE_SUCCESS;
252dc0cb1cdSDale Ghent 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
253dc0cb1cdSDale Ghent 	u16 value = 0;
254dc0cb1cdSDale Ghent 	u8 retry;
255dc0cb1cdSDale Ghent 
256dc0cb1cdSDale Ghent 	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
257dc0cb1cdSDale Ghent 		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
258dc0cb1cdSDale Ghent 		if (status != IXGBE_SUCCESS) {
259dc0cb1cdSDale Ghent 			ERROR_REPORT2(IXGBE_ERROR_CAUTION,
260dc0cb1cdSDale Ghent 				"semaphore failed with %d", status);
261dc0cb1cdSDale Ghent 			msec_delay(IXGBE_CS4227_CHECK_DELAY);
262dc0cb1cdSDale Ghent 			continue;
263dc0cb1cdSDale Ghent 		}
264dc0cb1cdSDale Ghent 
265dc0cb1cdSDale Ghent 		/* Get status of reset flow. */
266dc0cb1cdSDale Ghent 		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
267dc0cb1cdSDale Ghent 
268dc0cb1cdSDale Ghent 		if (status == IXGBE_SUCCESS &&
269dc0cb1cdSDale Ghent 		    value == IXGBE_CS4227_RESET_COMPLETE)
270dc0cb1cdSDale Ghent 			goto out;
271dc0cb1cdSDale Ghent 
272dc0cb1cdSDale Ghent 		if (status != IXGBE_SUCCESS ||
273dc0cb1cdSDale Ghent 		    value != IXGBE_CS4227_RESET_PENDING)
274dc0cb1cdSDale Ghent 			break;
275dc0cb1cdSDale Ghent 
276dc0cb1cdSDale Ghent 		/* Reset is pending. Wait and check again. */
277dc0cb1cdSDale Ghent 		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
278dc0cb1cdSDale Ghent 		msec_delay(IXGBE_CS4227_CHECK_DELAY);
279dc0cb1cdSDale Ghent 	}
280dc0cb1cdSDale Ghent 
281dc0cb1cdSDale Ghent 	/* If still pending, assume other instance failed. */
282dc0cb1cdSDale Ghent 	if (retry == IXGBE_CS4227_RETRIES) {
283dc0cb1cdSDale Ghent 		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
284dc0cb1cdSDale Ghent 		if (status != IXGBE_SUCCESS) {
285dc0cb1cdSDale Ghent 			ERROR_REPORT2(IXGBE_ERROR_CAUTION,
286dc0cb1cdSDale Ghent 				      "semaphore failed with %d", status);
287dc0cb1cdSDale Ghent 			return;
288dc0cb1cdSDale Ghent 		}
289dc0cb1cdSDale Ghent 	}
290dc0cb1cdSDale Ghent 
291dc0cb1cdSDale Ghent 	/* Reset the CS4227. */
292dc0cb1cdSDale Ghent 	status = ixgbe_reset_cs4227(hw);
293dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS) {
294dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
295dc0cb1cdSDale Ghent 			"CS4227 reset failed: %d", status);
296dc0cb1cdSDale Ghent 		goto out;
297dc0cb1cdSDale Ghent 	}
298dc0cb1cdSDale Ghent 
299dc0cb1cdSDale Ghent 	/* Reset takes so long, temporarily release semaphore in case the
300dc0cb1cdSDale Ghent 	 * other driver instance is waiting for the reset indication.
301dc0cb1cdSDale Ghent 	 */
302dc0cb1cdSDale Ghent 	ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
303dc0cb1cdSDale Ghent 			   IXGBE_CS4227_RESET_PENDING);
304dc0cb1cdSDale Ghent 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
305dc0cb1cdSDale Ghent 	msec_delay(10);
306dc0cb1cdSDale Ghent 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
307dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS) {
308dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_CAUTION,
309dc0cb1cdSDale Ghent 			"semaphore failed with %d", status);
310dc0cb1cdSDale Ghent 		return;
311dc0cb1cdSDale Ghent 	}
312dc0cb1cdSDale Ghent 
313dc0cb1cdSDale Ghent 	/* Record completion for next time. */
314dc0cb1cdSDale Ghent 	status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
315dc0cb1cdSDale Ghent 		IXGBE_CS4227_RESET_COMPLETE);
316dc0cb1cdSDale Ghent 
317dc0cb1cdSDale Ghent out:
318dc0cb1cdSDale Ghent 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
319dc0cb1cdSDale Ghent 	msec_delay(hw->eeprom.semaphore_delay);
320dc0cb1cdSDale Ghent }
321dc0cb1cdSDale Ghent 
322dc0cb1cdSDale Ghent /**
323dc0cb1cdSDale Ghent  * ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control
324dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
325dc0cb1cdSDale Ghent  **/
ixgbe_setup_mux_ctl(struct ixgbe_hw * hw)326dc0cb1cdSDale Ghent static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
327dc0cb1cdSDale Ghent {
328dc0cb1cdSDale Ghent 	u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
329dc0cb1cdSDale Ghent 
330dc0cb1cdSDale Ghent 	if (hw->bus.lan_id) {
331dc0cb1cdSDale Ghent 		esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
332dc0cb1cdSDale Ghent 		esdp |= IXGBE_ESDP_SDP1_DIR;
333dc0cb1cdSDale Ghent 	}
334dc0cb1cdSDale Ghent 	esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
335dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
336dc0cb1cdSDale Ghent 	IXGBE_WRITE_FLUSH(hw);
337dc0cb1cdSDale Ghent }
338dc0cb1cdSDale Ghent 
339dc0cb1cdSDale Ghent /**
340dc0cb1cdSDale Ghent  * ixgbe_identify_phy_x550em - Get PHY type based on device id
341dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
342dc0cb1cdSDale Ghent  *
343dc0cb1cdSDale Ghent  * Returns error code
344dc0cb1cdSDale Ghent  */
ixgbe_identify_phy_x550em(struct ixgbe_hw * hw)345dc0cb1cdSDale Ghent static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
346dc0cb1cdSDale Ghent {
347*48ed61a7SRobert Mustacchi 	hw->mac.ops.set_lan_id(hw);
348*48ed61a7SRobert Mustacchi 
349*48ed61a7SRobert Mustacchi 	ixgbe_read_mng_if_sel_x550em(hw);
350*48ed61a7SRobert Mustacchi 
351dc0cb1cdSDale Ghent 	switch (hw->device_id) {
352*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_A_SFP:
353*48ed61a7SRobert Mustacchi 		return ixgbe_identify_module_generic(hw);
354dc0cb1cdSDale Ghent 	case IXGBE_DEV_ID_X550EM_X_SFP:
355dc0cb1cdSDale Ghent 		/* set up for CS4227 usage */
356dc0cb1cdSDale Ghent 		ixgbe_setup_mux_ctl(hw);
357dc0cb1cdSDale Ghent 		ixgbe_check_cs4227(hw);
358*48ed61a7SRobert Mustacchi 		/* Fallthrough */
359dc0cb1cdSDale Ghent 
360*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_A_SFP_N:
361dc0cb1cdSDale Ghent 		return ixgbe_identify_module_generic(hw);
362dc0cb1cdSDale Ghent 		break;
363dc0cb1cdSDale Ghent 	case IXGBE_DEV_ID_X550EM_X_KX4:
364dc0cb1cdSDale Ghent 		hw->phy.type = ixgbe_phy_x550em_kx4;
365dc0cb1cdSDale Ghent 		break;
366*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_X_XFI:
367*48ed61a7SRobert Mustacchi 		hw->phy.type = ixgbe_phy_x550em_xfi;
368*48ed61a7SRobert Mustacchi 		break;
369dc0cb1cdSDale Ghent 	case IXGBE_DEV_ID_X550EM_X_KR:
370*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_A_KR:
371*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_A_KR_L:
372dc0cb1cdSDale Ghent 		hw->phy.type = ixgbe_phy_x550em_kr;
373dc0cb1cdSDale Ghent 		break;
374*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_A_10G_T:
375dc0cb1cdSDale Ghent 	case IXGBE_DEV_ID_X550EM_X_10G_T:
376dc0cb1cdSDale Ghent 		return ixgbe_identify_phy_generic(hw);
377*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_X_1G_T:
378*48ed61a7SRobert Mustacchi 		hw->phy.type = ixgbe_phy_ext_1g_t;
379*48ed61a7SRobert Mustacchi 		break;
380*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_A_1G_T:
381*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
382*48ed61a7SRobert Mustacchi 		hw->phy.type = ixgbe_phy_fw;
383*48ed61a7SRobert Mustacchi 		if (hw->bus.lan_id)
384*48ed61a7SRobert Mustacchi 			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
385*48ed61a7SRobert Mustacchi 		else
386*48ed61a7SRobert Mustacchi 			hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
387*48ed61a7SRobert Mustacchi 		break;
388dc0cb1cdSDale Ghent 	default:
389dc0cb1cdSDale Ghent 		break;
390dc0cb1cdSDale Ghent 	}
391dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
392dc0cb1cdSDale Ghent }
393dc0cb1cdSDale Ghent 
394*48ed61a7SRobert Mustacchi /**
395*48ed61a7SRobert Mustacchi  * ixgbe_fw_phy_activity - Perform an activity on a PHY
396*48ed61a7SRobert Mustacchi  * @hw: pointer to hardware structure
397*48ed61a7SRobert Mustacchi  * @activity: activity to perform
398*48ed61a7SRobert Mustacchi  * @data: Pointer to 4 32-bit words of data
399*48ed61a7SRobert Mustacchi  */
ixgbe_fw_phy_activity(struct ixgbe_hw * hw,u16 activity,u32 (* data)[FW_PHY_ACT_DATA_COUNT])400*48ed61a7SRobert Mustacchi s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity,
401*48ed61a7SRobert Mustacchi 			  u32 (*data)[FW_PHY_ACT_DATA_COUNT])
402*48ed61a7SRobert Mustacchi {
403*48ed61a7SRobert Mustacchi 	union {
404*48ed61a7SRobert Mustacchi 		struct ixgbe_hic_phy_activity_req cmd;
405*48ed61a7SRobert Mustacchi 		struct ixgbe_hic_phy_activity_resp rsp;
406*48ed61a7SRobert Mustacchi 	} hic;
407*48ed61a7SRobert Mustacchi 	u16 retries = FW_PHY_ACT_RETRIES;
408*48ed61a7SRobert Mustacchi 	s32 rc;
409*48ed61a7SRobert Mustacchi 	u16 i;
410*48ed61a7SRobert Mustacchi 
411*48ed61a7SRobert Mustacchi 	do {
412*48ed61a7SRobert Mustacchi 		memset(&hic, 0, sizeof(hic));
413*48ed61a7SRobert Mustacchi 		hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD;
414*48ed61a7SRobert Mustacchi 		hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN;
415*48ed61a7SRobert Mustacchi 		hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
416*48ed61a7SRobert Mustacchi 		hic.cmd.port_number = hw->bus.lan_id;
417*48ed61a7SRobert Mustacchi 		hic.cmd.activity_id = IXGBE_CPU_TO_LE16(activity);
418*48ed61a7SRobert Mustacchi 		for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
419*48ed61a7SRobert Mustacchi 			hic.cmd.data[i] = IXGBE_CPU_TO_BE32((*data)[i]);
420*48ed61a7SRobert Mustacchi 
421*48ed61a7SRobert Mustacchi 		rc = ixgbe_host_interface_command(hw, (u32 *)&hic.cmd,
422*48ed61a7SRobert Mustacchi 						  sizeof(hic.cmd),
423*48ed61a7SRobert Mustacchi 						  IXGBE_HI_COMMAND_TIMEOUT,
424*48ed61a7SRobert Mustacchi 						  TRUE);
425*48ed61a7SRobert Mustacchi 		if (rc != IXGBE_SUCCESS)
426*48ed61a7SRobert Mustacchi 			return rc;
427*48ed61a7SRobert Mustacchi 		if (hic.rsp.hdr.cmd_or_resp.ret_status ==
428*48ed61a7SRobert Mustacchi 		    FW_CEM_RESP_STATUS_SUCCESS) {
429*48ed61a7SRobert Mustacchi 			for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
430*48ed61a7SRobert Mustacchi 				(*data)[i] = IXGBE_BE32_TO_CPU(hic.rsp.data[i]);
431*48ed61a7SRobert Mustacchi 			return IXGBE_SUCCESS;
432*48ed61a7SRobert Mustacchi 		}
433*48ed61a7SRobert Mustacchi 		usec_delay(20);
434*48ed61a7SRobert Mustacchi 		--retries;
435*48ed61a7SRobert Mustacchi 	} while (retries > 0);
436*48ed61a7SRobert Mustacchi 
437*48ed61a7SRobert Mustacchi 	return IXGBE_ERR_HOST_INTERFACE_COMMAND;
438*48ed61a7SRobert Mustacchi }
439*48ed61a7SRobert Mustacchi 
440*48ed61a7SRobert Mustacchi static const struct {
441*48ed61a7SRobert Mustacchi 	u16 fw_speed;
442*48ed61a7SRobert Mustacchi 	ixgbe_link_speed phy_speed;
443*48ed61a7SRobert Mustacchi } ixgbe_fw_map[] = {
444*48ed61a7SRobert Mustacchi 	{ FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL },
445*48ed61a7SRobert Mustacchi 	{ FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL },
446*48ed61a7SRobert Mustacchi 	{ FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL },
447*48ed61a7SRobert Mustacchi 	{ FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL },
448*48ed61a7SRobert Mustacchi 	{ FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL },
449*48ed61a7SRobert Mustacchi 	{ FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL },
450*48ed61a7SRobert Mustacchi };
451*48ed61a7SRobert Mustacchi 
452*48ed61a7SRobert Mustacchi /**
453*48ed61a7SRobert Mustacchi  * ixgbe_get_phy_id_fw - Get the phy ID via firmware command
454*48ed61a7SRobert Mustacchi  * @hw: pointer to hardware structure
455*48ed61a7SRobert Mustacchi  *
456*48ed61a7SRobert Mustacchi  * Returns error code
457*48ed61a7SRobert Mustacchi  */
ixgbe_get_phy_id_fw(struct ixgbe_hw * hw)458*48ed61a7SRobert Mustacchi static s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw)
459*48ed61a7SRobert Mustacchi {
460*48ed61a7SRobert Mustacchi 	u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
461*48ed61a7SRobert Mustacchi 	u16 phy_speeds;
462*48ed61a7SRobert Mustacchi 	u16 phy_id_lo;
463*48ed61a7SRobert Mustacchi 	s32 rc;
464*48ed61a7SRobert Mustacchi 	u16 i;
465*48ed61a7SRobert Mustacchi 
466*48ed61a7SRobert Mustacchi 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info);
467*48ed61a7SRobert Mustacchi 	if (rc)
468*48ed61a7SRobert Mustacchi 		return rc;
469*48ed61a7SRobert Mustacchi 
470*48ed61a7SRobert Mustacchi 	hw->phy.speeds_supported = 0;
471*48ed61a7SRobert Mustacchi 	phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK;
472*48ed61a7SRobert Mustacchi 	for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) {
473*48ed61a7SRobert Mustacchi 		if (phy_speeds & ixgbe_fw_map[i].fw_speed)
474*48ed61a7SRobert Mustacchi 			hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed;
475*48ed61a7SRobert Mustacchi 	}
476*48ed61a7SRobert Mustacchi 	if (!hw->phy.autoneg_advertised)
477*48ed61a7SRobert Mustacchi 		hw->phy.autoneg_advertised = hw->phy.speeds_supported;
478*48ed61a7SRobert Mustacchi 
479*48ed61a7SRobert Mustacchi 	hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK;
480*48ed61a7SRobert Mustacchi 	phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK;
481*48ed61a7SRobert Mustacchi 	hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK;
482*48ed61a7SRobert Mustacchi 	hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK;
483*48ed61a7SRobert Mustacchi 	if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK)
484*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_PHY_ADDR_INVALID;
485*48ed61a7SRobert Mustacchi 	return IXGBE_SUCCESS;
486*48ed61a7SRobert Mustacchi }
487*48ed61a7SRobert Mustacchi 
488*48ed61a7SRobert Mustacchi /**
489*48ed61a7SRobert Mustacchi  * ixgbe_identify_phy_fw - Get PHY type based on firmware command
490*48ed61a7SRobert Mustacchi  * @hw: pointer to hardware structure
491*48ed61a7SRobert Mustacchi  *
492*48ed61a7SRobert Mustacchi  * Returns error code
493*48ed61a7SRobert Mustacchi  */
ixgbe_identify_phy_fw(struct ixgbe_hw * hw)494*48ed61a7SRobert Mustacchi static s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw)
495*48ed61a7SRobert Mustacchi {
496*48ed61a7SRobert Mustacchi 	if (hw->bus.lan_id)
497*48ed61a7SRobert Mustacchi 		hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
498*48ed61a7SRobert Mustacchi 	else
499*48ed61a7SRobert Mustacchi 		hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
500*48ed61a7SRobert Mustacchi 
501*48ed61a7SRobert Mustacchi 	hw->phy.type = ixgbe_phy_fw;
502*48ed61a7SRobert Mustacchi 	hw->phy.ops.read_reg = NULL;
503*48ed61a7SRobert Mustacchi 	hw->phy.ops.write_reg = NULL;
504*48ed61a7SRobert Mustacchi 	return ixgbe_get_phy_id_fw(hw);
505*48ed61a7SRobert Mustacchi }
506*48ed61a7SRobert Mustacchi 
507*48ed61a7SRobert Mustacchi /**
508*48ed61a7SRobert Mustacchi  * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY
509*48ed61a7SRobert Mustacchi  * @hw: pointer to hardware structure
510*48ed61a7SRobert Mustacchi  *
511*48ed61a7SRobert Mustacchi  * Returns error code
512*48ed61a7SRobert Mustacchi  */
ixgbe_shutdown_fw_phy(struct ixgbe_hw * hw)513*48ed61a7SRobert Mustacchi s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw)
514*48ed61a7SRobert Mustacchi {
515*48ed61a7SRobert Mustacchi 	u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
516*48ed61a7SRobert Mustacchi 
517*48ed61a7SRobert Mustacchi 	setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF;
518*48ed61a7SRobert Mustacchi 	return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup);
519*48ed61a7SRobert Mustacchi }
520*48ed61a7SRobert Mustacchi 
ixgbe_read_phy_reg_x550em(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)521dc0cb1cdSDale Ghent static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
522dc0cb1cdSDale Ghent 				     u32 device_type, u16 *phy_data)
523dc0cb1cdSDale Ghent {
524dc0cb1cdSDale Ghent 	UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, *phy_data);
525dc0cb1cdSDale Ghent 	return IXGBE_NOT_IMPLEMENTED;
526dc0cb1cdSDale Ghent }
527dc0cb1cdSDale Ghent 
ixgbe_write_phy_reg_x550em(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)528dc0cb1cdSDale Ghent static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
529dc0cb1cdSDale Ghent 				      u32 device_type, u16 phy_data)
530dc0cb1cdSDale Ghent {
531dc0cb1cdSDale Ghent 	UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, phy_data);
532dc0cb1cdSDale Ghent 	return IXGBE_NOT_IMPLEMENTED;
533dc0cb1cdSDale Ghent }
534dc0cb1cdSDale Ghent 
535*48ed61a7SRobert Mustacchi /**
536*48ed61a7SRobert Mustacchi  * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
537*48ed61a7SRobert Mustacchi  * @hw: pointer to the hardware structure
538*48ed61a7SRobert Mustacchi  * @addr: I2C bus address to read from
539*48ed61a7SRobert Mustacchi  * @reg: I2C device register to read from
540*48ed61a7SRobert Mustacchi  * @val: pointer to location to receive read value
541*48ed61a7SRobert Mustacchi  *
542*48ed61a7SRobert Mustacchi  * Returns an error code on error.
543*48ed61a7SRobert Mustacchi  **/
ixgbe_read_i2c_combined_generic(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 * val)544*48ed61a7SRobert Mustacchi static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
545*48ed61a7SRobert Mustacchi 					   u16 reg, u16 *val)
546*48ed61a7SRobert Mustacchi {
547*48ed61a7SRobert Mustacchi 	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, TRUE);
548*48ed61a7SRobert Mustacchi }
549*48ed61a7SRobert Mustacchi 
550*48ed61a7SRobert Mustacchi /**
551*48ed61a7SRobert Mustacchi  * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
552*48ed61a7SRobert Mustacchi  * @hw: pointer to the hardware structure
553*48ed61a7SRobert Mustacchi  * @addr: I2C bus address to read from
554*48ed61a7SRobert Mustacchi  * @reg: I2C device register to read from
555*48ed61a7SRobert Mustacchi  * @val: pointer to location to receive read value
556*48ed61a7SRobert Mustacchi  *
557*48ed61a7SRobert Mustacchi  * Returns an error code on error.
558*48ed61a7SRobert Mustacchi  **/
559*48ed61a7SRobert Mustacchi static s32
ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 * val)560*48ed61a7SRobert Mustacchi ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
561*48ed61a7SRobert Mustacchi 					 u16 reg, u16 *val)
562*48ed61a7SRobert Mustacchi {
563*48ed61a7SRobert Mustacchi 	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, FALSE);
564*48ed61a7SRobert Mustacchi }
565*48ed61a7SRobert Mustacchi 
566*48ed61a7SRobert Mustacchi /**
567*48ed61a7SRobert Mustacchi  * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
568*48ed61a7SRobert Mustacchi  * @hw: pointer to the hardware structure
569*48ed61a7SRobert Mustacchi  * @addr: I2C bus address to write to
570*48ed61a7SRobert Mustacchi  * @reg: I2C device register to write to
571*48ed61a7SRobert Mustacchi  * @val: value to write
572*48ed61a7SRobert Mustacchi  *
573*48ed61a7SRobert Mustacchi  * Returns an error code on error.
574*48ed61a7SRobert Mustacchi  **/
ixgbe_write_i2c_combined_generic(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 val)575*48ed61a7SRobert Mustacchi static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
576*48ed61a7SRobert Mustacchi 					    u8 addr, u16 reg, u16 val)
577*48ed61a7SRobert Mustacchi {
578*48ed61a7SRobert Mustacchi 	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, TRUE);
579*48ed61a7SRobert Mustacchi }
580*48ed61a7SRobert Mustacchi 
581*48ed61a7SRobert Mustacchi /**
582*48ed61a7SRobert Mustacchi  * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
583*48ed61a7SRobert Mustacchi  * @hw: pointer to the hardware structure
584*48ed61a7SRobert Mustacchi  * @addr: I2C bus address to write to
585*48ed61a7SRobert Mustacchi  * @reg: I2C device register to write to
586*48ed61a7SRobert Mustacchi  * @val: value to write
587*48ed61a7SRobert Mustacchi  *
588*48ed61a7SRobert Mustacchi  * Returns an error code on error.
589*48ed61a7SRobert Mustacchi  **/
590*48ed61a7SRobert Mustacchi static s32
ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 val)591*48ed61a7SRobert Mustacchi ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
592*48ed61a7SRobert Mustacchi 					  u8 addr, u16 reg, u16 val)
593*48ed61a7SRobert Mustacchi {
594*48ed61a7SRobert Mustacchi 	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, FALSE);
595*48ed61a7SRobert Mustacchi }
596*48ed61a7SRobert Mustacchi 
597dc0cb1cdSDale Ghent /**
598dc0cb1cdSDale Ghent *  ixgbe_init_ops_X550EM - Inits func ptrs and MAC type
599dc0cb1cdSDale Ghent *  @hw: pointer to hardware structure
600dc0cb1cdSDale Ghent *
601dc0cb1cdSDale Ghent *  Initialize the function pointers and for MAC type X550EM.
602dc0cb1cdSDale Ghent *  Does not touch the hardware.
603dc0cb1cdSDale Ghent **/
ixgbe_init_ops_X550EM(struct ixgbe_hw * hw)604dc0cb1cdSDale Ghent s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw)
605dc0cb1cdSDale Ghent {
606dc0cb1cdSDale Ghent 	struct ixgbe_mac_info *mac = &hw->mac;
607dc0cb1cdSDale Ghent 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
608dc0cb1cdSDale Ghent 	struct ixgbe_phy_info *phy = &hw->phy;
609dc0cb1cdSDale Ghent 	s32 ret_val;
610dc0cb1cdSDale Ghent 
611dc0cb1cdSDale Ghent 	DEBUGFUNC("ixgbe_init_ops_X550EM");
612dc0cb1cdSDale Ghent 
613dc0cb1cdSDale Ghent 	/* Similar to X550 so start there. */
614dc0cb1cdSDale Ghent 	ret_val = ixgbe_init_ops_X550(hw);
615dc0cb1cdSDale Ghent 
616dc0cb1cdSDale Ghent 	/* Since this function eventually calls
617dc0cb1cdSDale Ghent 	 * ixgbe_init_ops_540 by design, we are setting
618dc0cb1cdSDale Ghent 	 * the pointers to NULL explicitly here to overwrite
619dc0cb1cdSDale Ghent 	 * the values being set in the x540 function.
620dc0cb1cdSDale Ghent 	 */
621dc0cb1cdSDale Ghent 
622*48ed61a7SRobert Mustacchi 	/* Bypass not supported in x550EM */
623*48ed61a7SRobert Mustacchi 	mac->ops.bypass_rw = NULL;
624*48ed61a7SRobert Mustacchi 	mac->ops.bypass_valid_rd = NULL;
625*48ed61a7SRobert Mustacchi 	mac->ops.bypass_set = NULL;
626*48ed61a7SRobert Mustacchi 	mac->ops.bypass_rd_eep = NULL;
627*48ed61a7SRobert Mustacchi 
628dc0cb1cdSDale Ghent 	/* FCOE not supported in x550EM */
629dc0cb1cdSDale Ghent 	mac->ops.get_san_mac_addr = NULL;
630dc0cb1cdSDale Ghent 	mac->ops.set_san_mac_addr = NULL;
631dc0cb1cdSDale Ghent 	mac->ops.get_wwn_prefix = NULL;
632dc0cb1cdSDale Ghent 	mac->ops.get_fcoe_boot_status = NULL;
633dc0cb1cdSDale Ghent 
634dc0cb1cdSDale Ghent 	/* IPsec not supported in x550EM */
635dc0cb1cdSDale Ghent 	mac->ops.disable_sec_rx_path = NULL;
636dc0cb1cdSDale Ghent 	mac->ops.enable_sec_rx_path = NULL;
637dc0cb1cdSDale Ghent 
638dc0cb1cdSDale Ghent 	/* AUTOC register is not present in x550EM. */
639dc0cb1cdSDale Ghent 	mac->ops.prot_autoc_read = NULL;
640dc0cb1cdSDale Ghent 	mac->ops.prot_autoc_write = NULL;
641dc0cb1cdSDale Ghent 
642dc0cb1cdSDale Ghent 	/* X550EM bus type is internal*/
643dc0cb1cdSDale Ghent 	hw->bus.type = ixgbe_bus_type_internal;
644dc0cb1cdSDale Ghent 	mac->ops.get_bus_info = ixgbe_get_bus_info_X550em;
645dc0cb1cdSDale Ghent 
646dc0cb1cdSDale Ghent 
647dc0cb1cdSDale Ghent 	mac->ops.get_media_type = ixgbe_get_media_type_X550em;
648dc0cb1cdSDale Ghent 	mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em;
649dc0cb1cdSDale Ghent 	mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em;
650dc0cb1cdSDale Ghent 	mac->ops.reset_hw = ixgbe_reset_hw_X550em;
651dc0cb1cdSDale Ghent 	mac->ops.get_supported_physical_layer =
652dc0cb1cdSDale Ghent 				    ixgbe_get_supported_physical_layer_X550em;
653dc0cb1cdSDale Ghent 
654dc0cb1cdSDale Ghent 	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper)
655dc0cb1cdSDale Ghent 		mac->ops.setup_fc = ixgbe_setup_fc_generic;
656dc0cb1cdSDale Ghent 	else
657dc0cb1cdSDale Ghent 		mac->ops.setup_fc = ixgbe_setup_fc_X550em;
658dc0cb1cdSDale Ghent 
659dc0cb1cdSDale Ghent 	/* PHY */
660dc0cb1cdSDale Ghent 	phy->ops.init = ixgbe_init_phy_ops_X550em;
661*48ed61a7SRobert Mustacchi 	switch (hw->device_id) {
662*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_A_1G_T:
663*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
664*48ed61a7SRobert Mustacchi 		mac->ops.setup_fc = NULL;
665*48ed61a7SRobert Mustacchi 		phy->ops.identify = ixgbe_identify_phy_fw;
666*48ed61a7SRobert Mustacchi 		phy->ops.set_phy_power = NULL;
667*48ed61a7SRobert Mustacchi 		phy->ops.get_firmware_version = NULL;
668*48ed61a7SRobert Mustacchi 		break;
669*48ed61a7SRobert Mustacchi 	case IXGBE_DEV_ID_X550EM_X_1G_T:
670*48ed61a7SRobert Mustacchi 		mac->ops.setup_fc = NULL;
671*48ed61a7SRobert Mustacchi 		phy->ops.identify = ixgbe_identify_phy_x550em;
672*48ed61a7SRobert Mustacchi 		phy->ops.set_phy_power = NULL;
673*48ed61a7SRobert Mustacchi 		break;
674*48ed61a7SRobert Mustacchi 	default:
675*48ed61a7SRobert Mustacchi 		phy->ops.identify = ixgbe_identify_phy_x550em;
676*48ed61a7SRobert Mustacchi 	}
677*48ed61a7SRobert Mustacchi 
678dc0cb1cdSDale Ghent 	if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
679dc0cb1cdSDale Ghent 		phy->ops.set_phy_power = NULL;
680dc0cb1cdSDale Ghent 
681dc0cb1cdSDale Ghent 
682dc0cb1cdSDale Ghent 	/* EEPROM */
683dc0cb1cdSDale Ghent 	eeprom->ops.init_params = ixgbe_init_eeprom_params_X540;
684dc0cb1cdSDale Ghent 	eeprom->ops.read = ixgbe_read_ee_hostif_X550;
685dc0cb1cdSDale Ghent 	eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550;
686dc0cb1cdSDale Ghent 	eeprom->ops.write = ixgbe_write_ee_hostif_X550;
687dc0cb1cdSDale Ghent 	eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550;
688dc0cb1cdSDale Ghent 	eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
689dc0cb1cdSDale Ghent 	eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
690dc0cb1cdSDale Ghent 	eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
691dc0cb1cdSDale Ghent 
692dc0cb1cdSDale Ghent 	return ret_val;
693dc0cb1cdSDale Ghent }
694dc0cb1cdSDale Ghent 
695*48ed61a7SRobert Mustacchi /**
696*48ed61a7SRobert Mustacchi  * ixgbe_setup_fw_link - Setup firmware-controlled PHYs
697*48ed61a7SRobert Mustacchi  * @hw: pointer to hardware structure
698*48ed61a7SRobert Mustacchi  */
ixgbe_setup_fw_link(struct ixgbe_hw * hw)699*48ed61a7SRobert Mustacchi static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw)
700*48ed61a7SRobert Mustacchi {
701*48ed61a7SRobert Mustacchi 	u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
702*48ed61a7SRobert Mustacchi 	s32 rc;
703*48ed61a7SRobert Mustacchi 	u16 i;
704*48ed61a7SRobert Mustacchi 
705*48ed61a7SRobert Mustacchi 	if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
706*48ed61a7SRobert Mustacchi 		return 0;
707*48ed61a7SRobert Mustacchi 
708*48ed61a7SRobert Mustacchi 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
709*48ed61a7SRobert Mustacchi 		ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
710*48ed61a7SRobert Mustacchi 			      "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
711*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_INVALID_LINK_SETTINGS;
712*48ed61a7SRobert Mustacchi 	}
713*48ed61a7SRobert Mustacchi 
714*48ed61a7SRobert Mustacchi 	switch (hw->fc.requested_mode) {
715*48ed61a7SRobert Mustacchi 	case ixgbe_fc_full:
716*48ed61a7SRobert Mustacchi 		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX <<
717*48ed61a7SRobert Mustacchi 			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
718*48ed61a7SRobert Mustacchi 		break;
719*48ed61a7SRobert Mustacchi 	case ixgbe_fc_rx_pause:
720*48ed61a7SRobert Mustacchi 		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX <<
721*48ed61a7SRobert Mustacchi 			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
722*48ed61a7SRobert Mustacchi 		break;
723*48ed61a7SRobert Mustacchi 	case ixgbe_fc_tx_pause:
724*48ed61a7SRobert Mustacchi 		setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX <<
725*48ed61a7SRobert Mustacchi 			    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
726*48ed61a7SRobert Mustacchi 		break;
727*48ed61a7SRobert Mustacchi 	default:
728*48ed61a7SRobert Mustacchi 		break;
729*48ed61a7SRobert Mustacchi 	}
730*48ed61a7SRobert Mustacchi 
731*48ed61a7SRobert Mustacchi 	for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) {
732*48ed61a7SRobert Mustacchi 		if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed)
733*48ed61a7SRobert Mustacchi 			setup[0] |= ixgbe_fw_map[i].fw_speed;
734*48ed61a7SRobert Mustacchi 	}
735*48ed61a7SRobert Mustacchi 	setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN;
736*48ed61a7SRobert Mustacchi 
737*48ed61a7SRobert Mustacchi 	if (hw->phy.eee_speeds_advertised)
738*48ed61a7SRobert Mustacchi 		setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE;
739*48ed61a7SRobert Mustacchi 
740*48ed61a7SRobert Mustacchi 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);
741*48ed61a7SRobert Mustacchi 	if (rc)
742*48ed61a7SRobert Mustacchi 		return rc;
743*48ed61a7SRobert Mustacchi 	if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
744*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_OVERTEMP;
745*48ed61a7SRobert Mustacchi 	return IXGBE_SUCCESS;
746*48ed61a7SRobert Mustacchi }
747*48ed61a7SRobert Mustacchi 
748*48ed61a7SRobert Mustacchi /**
749*48ed61a7SRobert Mustacchi  * ixgbe_fc_autoneg_fw _ Set up flow control for FW-controlled PHYs
750*48ed61a7SRobert Mustacchi  * @hw: pointer to hardware structure
751*48ed61a7SRobert Mustacchi  *
752*48ed61a7SRobert Mustacchi  *  Called at init time to set up flow control.
753