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 
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)
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)
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) {
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)) {
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) {
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) {
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) {
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) {
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.