16f37f232SEric Joyner /******************************************************************************
26f37f232SEric Joyner
38455e365SKevin Bowling Copyright (c) 2001-2020, Intel Corporation
46f37f232SEric Joyner All rights reserved.
56f37f232SEric Joyner
66f37f232SEric Joyner Redistribution and use in source and binary forms, with or without
76f37f232SEric Joyner modification, are permitted provided that the following conditions are met:
86f37f232SEric Joyner
96f37f232SEric Joyner 1. Redistributions of source code must retain the above copyright notice,
106f37f232SEric Joyner this list of conditions and the following disclaimer.
116f37f232SEric Joyner
126f37f232SEric Joyner 2. Redistributions in binary form must reproduce the above copyright
136f37f232SEric Joyner notice, this list of conditions and the following disclaimer in the
146f37f232SEric Joyner documentation and/or other materials provided with the distribution.
156f37f232SEric Joyner
166f37f232SEric Joyner 3. Neither the name of the Intel Corporation nor the names of its
176f37f232SEric Joyner contributors may be used to endorse or promote products derived from
186f37f232SEric Joyner this software without specific prior written permission.
196f37f232SEric Joyner
206f37f232SEric Joyner THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
216f37f232SEric Joyner AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226f37f232SEric Joyner IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236f37f232SEric Joyner ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
246f37f232SEric Joyner LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
256f37f232SEric Joyner CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
266f37f232SEric Joyner SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
276f37f232SEric Joyner INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
286f37f232SEric Joyner CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
296f37f232SEric Joyner ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
306f37f232SEric Joyner POSSIBILITY OF SUCH DAMAGE.
316f37f232SEric Joyner
326f37f232SEric Joyner ******************************************************************************/
336f37f232SEric Joyner
346f37f232SEric Joyner #include "ixgbe_x550.h"
356f37f232SEric Joyner #include "ixgbe_x540.h"
366f37f232SEric Joyner #include "ixgbe_type.h"
376f37f232SEric Joyner #include "ixgbe_api.h"
386f37f232SEric Joyner #include "ixgbe_common.h"
396f37f232SEric Joyner #include "ixgbe_phy.h"
406f37f232SEric Joyner
416f37f232SEric Joyner static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed);
428eb6488eSEric Joyner static s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
438eb6488eSEric Joyner static void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
448eb6488eSEric Joyner static s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw);
456f37f232SEric Joyner
466f37f232SEric Joyner /**
476f37f232SEric Joyner * ixgbe_init_ops_X550 - Inits func ptrs and MAC type
486f37f232SEric Joyner * @hw: pointer to hardware structure
496f37f232SEric Joyner *
506f37f232SEric Joyner * Initialize the function pointers and assign the MAC type for X550.
516f37f232SEric Joyner * Does not touch the hardware.
526f37f232SEric Joyner **/
ixgbe_init_ops_X550(struct ixgbe_hw * hw)536f37f232SEric Joyner s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw)
546f37f232SEric Joyner {
556f37f232SEric Joyner struct ixgbe_mac_info *mac = &hw->mac;
566f37f232SEric Joyner struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
576f37f232SEric Joyner s32 ret_val;
586f37f232SEric Joyner
596f37f232SEric Joyner DEBUGFUNC("ixgbe_init_ops_X550");
606f37f232SEric Joyner
616f37f232SEric Joyner ret_val = ixgbe_init_ops_X540(hw);
626f37f232SEric Joyner mac->ops.dmac_config = ixgbe_dmac_config_X550;
636f37f232SEric Joyner mac->ops.dmac_config_tcs = ixgbe_dmac_config_tcs_X550;
646f37f232SEric Joyner mac->ops.dmac_update_tcs = ixgbe_dmac_update_tcs_X550;
658eb6488eSEric Joyner mac->ops.setup_eee = NULL;
666f37f232SEric Joyner mac->ops.set_source_address_pruning =
676f37f232SEric Joyner ixgbe_set_source_address_pruning_X550;
686f37f232SEric Joyner mac->ops.set_ethertype_anti_spoofing =
696f37f232SEric Joyner ixgbe_set_ethertype_anti_spoofing_X550;
706f37f232SEric Joyner
716f37f232SEric Joyner mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
726f37f232SEric Joyner eeprom->ops.init_params = ixgbe_init_eeprom_params_X550;
736f37f232SEric Joyner eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
746f37f232SEric Joyner eeprom->ops.read = ixgbe_read_ee_hostif_X550;
756f37f232SEric Joyner eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550;
766f37f232SEric Joyner eeprom->ops.write = ixgbe_write_ee_hostif_X550;
776f37f232SEric Joyner eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550;
786f37f232SEric Joyner eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
796f37f232SEric Joyner eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
806f37f232SEric Joyner
816f37f232SEric Joyner mac->ops.disable_mdd = ixgbe_disable_mdd_X550;
826f37f232SEric Joyner mac->ops.enable_mdd = ixgbe_enable_mdd_X550;
836f37f232SEric Joyner mac->ops.mdd_event = ixgbe_mdd_event_X550;
846f37f232SEric Joyner mac->ops.restore_mdd_vf = ixgbe_restore_mdd_vf_X550;
85b622bdb4SXiaoyun Li mac->ops.fw_recovery_mode = ixgbe_fw_recovery_mode_X550;
866f37f232SEric Joyner mac->ops.disable_rx = ixgbe_disable_rx_x550;
878eb6488eSEric Joyner /* Manageability interface */
888eb6488eSEric Joyner mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_x550;
898eb6488eSEric Joyner switch (hw->device_id) {
908eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_X_1G_T:
918eb6488eSEric Joyner hw->mac.ops.led_on = NULL;
928eb6488eSEric Joyner hw->mac.ops.led_off = NULL;
938eb6488eSEric Joyner break;
948eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_X_10G_T:
958eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_10G_T:
966f37f232SEric Joyner hw->mac.ops.led_on = ixgbe_led_on_t_X550em;
976f37f232SEric Joyner hw->mac.ops.led_off = ixgbe_led_off_t_X550em;
988eb6488eSEric Joyner break;
998eb6488eSEric Joyner default:
1008eb6488eSEric Joyner break;
1016f37f232SEric Joyner }
1026f37f232SEric Joyner return ret_val;
1036f37f232SEric Joyner }
1046f37f232SEric Joyner
1056f37f232SEric Joyner /**
1066f37f232SEric Joyner * ixgbe_read_cs4227 - Read CS4227 register
1076f37f232SEric Joyner * @hw: pointer to hardware structure
1086f37f232SEric Joyner * @reg: register number to write
1096f37f232SEric Joyner * @value: pointer to receive value read
1106f37f232SEric Joyner *
1116f37f232SEric Joyner * Returns status code
1126f37f232SEric Joyner **/
ixgbe_read_cs4227(struct ixgbe_hw * hw,u16 reg,u16 * value)1136f37f232SEric Joyner static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
1146f37f232SEric Joyner {
1158eb6488eSEric Joyner return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);
1166f37f232SEric Joyner }
1176f37f232SEric Joyner
1186f37f232SEric Joyner /**
1196f37f232SEric Joyner * ixgbe_write_cs4227 - Write CS4227 register
1206f37f232SEric Joyner * @hw: pointer to hardware structure
1216f37f232SEric Joyner * @reg: register number to write
1226f37f232SEric Joyner * @value: value to write to register
1236f37f232SEric Joyner *
1246f37f232SEric Joyner * Returns status code
1256f37f232SEric Joyner **/
ixgbe_write_cs4227(struct ixgbe_hw * hw,u16 reg,u16 value)1266f37f232SEric Joyner static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
1276f37f232SEric Joyner {
1288eb6488eSEric Joyner return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);
1296f37f232SEric Joyner }
1306f37f232SEric Joyner
1316f37f232SEric Joyner /**
1326f37f232SEric Joyner * ixgbe_read_pe - Read register from port expander
1336f37f232SEric Joyner * @hw: pointer to hardware structure
1346f37f232SEric Joyner * @reg: register number to read
1356f37f232SEric Joyner * @value: pointer to receive read value
1366f37f232SEric Joyner *
1376f37f232SEric Joyner * Returns status code
1386f37f232SEric Joyner **/
ixgbe_read_pe(struct ixgbe_hw * hw,u8 reg,u8 * value)1396f37f232SEric Joyner static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value)
1406f37f232SEric Joyner {
1416f37f232SEric Joyner s32 status;
1426f37f232SEric Joyner
1436f37f232SEric Joyner status = ixgbe_read_i2c_byte_unlocked(hw, reg, IXGBE_PE, value);
1446f37f232SEric Joyner if (status != IXGBE_SUCCESS)
1456f37f232SEric Joyner ERROR_REPORT2(IXGBE_ERROR_CAUTION,
1466f37f232SEric Joyner "port expander access failed with %d\n", status);
1476f37f232SEric Joyner return status;
1486f37f232SEric Joyner }
1496f37f232SEric Joyner
1506f37f232SEric Joyner /**
1516f37f232SEric Joyner * ixgbe_write_pe - Write register to port expander
1526f37f232SEric Joyner * @hw: pointer to hardware structure
1536f37f232SEric Joyner * @reg: register number to write
1546f37f232SEric Joyner * @value: value to write
1556f37f232SEric Joyner *
1566f37f232SEric Joyner * Returns status code
1576f37f232SEric Joyner **/
ixgbe_write_pe(struct ixgbe_hw * hw,u8 reg,u8 value)1586f37f232SEric Joyner static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value)
1596f37f232SEric Joyner {
1606f37f232SEric Joyner s32 status;
1616f37f232SEric Joyner
1626f37f232SEric Joyner status = ixgbe_write_i2c_byte_unlocked(hw, reg, IXGBE_PE, value);
1636f37f232SEric Joyner if (status != IXGBE_SUCCESS)
1646f37f232SEric Joyner ERROR_REPORT2(IXGBE_ERROR_CAUTION,
1656f37f232SEric Joyner "port expander access failed with %d\n", status);
1666f37f232SEric Joyner return status;
1676f37f232SEric Joyner }
1686f37f232SEric Joyner
1696f37f232SEric Joyner /**
1706f37f232SEric Joyner * ixgbe_reset_cs4227 - Reset CS4227 using port expander
1716f37f232SEric Joyner * @hw: pointer to hardware structure
1726f37f232SEric Joyner *
173a9ca1c79SSean Bruno * This function assumes that the caller has acquired the proper semaphore.
1746f37f232SEric Joyner * Returns error code
1756f37f232SEric Joyner **/
ixgbe_reset_cs4227(struct ixgbe_hw * hw)1766f37f232SEric Joyner static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
1776f37f232SEric Joyner {
1786f37f232SEric Joyner s32 status;
179a9ca1c79SSean Bruno u32 retry;
180a9ca1c79SSean Bruno u16 value;
1816f37f232SEric Joyner u8 reg;
1826f37f232SEric Joyner
183a9ca1c79SSean Bruno /* Trigger hard reset. */
1846f37f232SEric Joyner status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®);
1856f37f232SEric Joyner if (status != IXGBE_SUCCESS)
1866f37f232SEric Joyner return status;
1876f37f232SEric Joyner reg |= IXGBE_PE_BIT1;
1886f37f232SEric Joyner status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
1896f37f232SEric Joyner if (status != IXGBE_SUCCESS)
1906f37f232SEric Joyner return status;
1916f37f232SEric Joyner
1926f37f232SEric Joyner status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®);
1936f37f232SEric Joyner if (status != IXGBE_SUCCESS)
1946f37f232SEric Joyner return status;
1956f37f232SEric Joyner reg &= ~IXGBE_PE_BIT1;
1966f37f232SEric Joyner status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg);
1976f37f232SEric Joyner if (status != IXGBE_SUCCESS)
1986f37f232SEric Joyner return status;
1996f37f232SEric Joyner
2006f37f232SEric Joyner status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®);
2016f37f232SEric Joyner if (status != IXGBE_SUCCESS)
2026f37f232SEric Joyner return status;
2036f37f232SEric Joyner reg &= ~IXGBE_PE_BIT1;
2046f37f232SEric Joyner status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
2056f37f232SEric Joyner if (status != IXGBE_SUCCESS)
2066f37f232SEric Joyner return status;
2076f37f232SEric Joyner
2086f37f232SEric Joyner usec_delay(IXGBE_CS4227_RESET_HOLD);
2096f37f232SEric Joyner
2106f37f232SEric Joyner status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®);
2116f37f232SEric Joyner if (status != IXGBE_SUCCESS)
2126f37f232SEric Joyner return status;
2136f37f232SEric Joyner reg |= IXGBE_PE_BIT1;
2146f37f232SEric Joyner status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
2156f37f232SEric Joyner if (status != IXGBE_SUCCESS)
2166f37f232SEric Joyner return status;
2176f37f232SEric Joyner
218a9ca1c79SSean Bruno /* Wait for the reset to complete. */
2196f37f232SEric Joyner msec_delay(IXGBE_CS4227_RESET_DELAY);
220a9ca1c79SSean Bruno for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
221a9ca1c79SSean Bruno status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
222a9ca1c79SSean Bruno &value);
223a9ca1c79SSean Bruno if (status == IXGBE_SUCCESS &&
224a9ca1c79SSean Bruno value == IXGBE_CS4227_EEPROM_LOAD_OK)
225a9ca1c79SSean Bruno break;
226a9ca1c79SSean Bruno msec_delay(IXGBE_CS4227_CHECK_DELAY);
227a9ca1c79SSean Bruno }
228a9ca1c79SSean Bruno if (retry == IXGBE_CS4227_RETRIES) {
229a9ca1c79SSean Bruno ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
230a9ca1c79SSean Bruno "CS4227 reset did not complete.");
231a9ca1c79SSean Bruno return IXGBE_ERR_PHY;
232a9ca1c79SSean Bruno }
233a9ca1c79SSean Bruno
234a9ca1c79SSean Bruno status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
235a9ca1c79SSean Bruno if (status != IXGBE_SUCCESS ||
236a9ca1c79SSean Bruno !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
237a9ca1c79SSean Bruno ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
238a9ca1c79SSean Bruno "CS4227 EEPROM did not load successfully.");
239a9ca1c79SSean Bruno return IXGBE_ERR_PHY;
240a9ca1c79SSean Bruno }
2416f37f232SEric Joyner
2426f37f232SEric Joyner return IXGBE_SUCCESS;
2436f37f232SEric Joyner }
2446f37f232SEric Joyner
2456f37f232SEric Joyner /**
2466f37f232SEric Joyner * ixgbe_check_cs4227 - Check CS4227 and reset as needed
2476f37f232SEric Joyner * @hw: pointer to hardware structure
2486f37f232SEric Joyner **/
ixgbe_check_cs4227(struct ixgbe_hw * hw)2496f37f232SEric Joyner static void ixgbe_check_cs4227(struct ixgbe_hw *hw)
2506f37f232SEric Joyner {
251a9ca1c79SSean Bruno s32 status = IXGBE_SUCCESS;
2526f37f232SEric Joyner u32 swfw_mask = hw->phy.phy_semaphore_mask;
253a9ca1c79SSean Bruno u16 value = 0;
2546f37f232SEric Joyner u8 retry;
2556f37f232SEric Joyner
2566f37f232SEric Joyner for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
2576f37f232SEric Joyner status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
2586f37f232SEric Joyner if (status != IXGBE_SUCCESS) {
2596f37f232SEric Joyner ERROR_REPORT2(IXGBE_ERROR_CAUTION,
260a9ca1c79SSean Bruno "semaphore failed with %d", status);
261a9ca1c79SSean Bruno msec_delay(IXGBE_CS4227_CHECK_DELAY);
262a9ca1c79SSean Bruno continue;
2636f37f232SEric Joyner }
264a9ca1c79SSean Bruno
265a9ca1c79SSean Bruno /* Get status of reset flow. */
266a9ca1c79SSean Bruno status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
267a9ca1c79SSean Bruno
268a9ca1c79SSean Bruno if (status == IXGBE_SUCCESS &&
269a9ca1c79SSean Bruno value == IXGBE_CS4227_RESET_COMPLETE)
270a9ca1c79SSean Bruno goto out;
271a9ca1c79SSean Bruno
272a9ca1c79SSean Bruno if (status != IXGBE_SUCCESS ||
273a9ca1c79SSean Bruno value != IXGBE_CS4227_RESET_PENDING)
274a9ca1c79SSean Bruno break;
275a9ca1c79SSean Bruno
276a9ca1c79SSean Bruno /* Reset is pending. Wait and check again. */
2776f37f232SEric Joyner hw->mac.ops.release_swfw_sync(hw, swfw_mask);
278a9ca1c79SSean Bruno msec_delay(IXGBE_CS4227_CHECK_DELAY);
2796f37f232SEric Joyner }
280a9ca1c79SSean Bruno
281a9ca1c79SSean Bruno /* If still pending, assume other instance failed. */
282a9ca1c79SSean Bruno if (retry == IXGBE_CS4227_RETRIES) {
283a9ca1c79SSean Bruno status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
284a9ca1c79SSean Bruno if (status != IXGBE_SUCCESS) {
2856f37f232SEric Joyner ERROR_REPORT2(IXGBE_ERROR_CAUTION,
286a9ca1c79SSean Bruno "semaphore failed with %d", status);
287a9ca1c79SSean Bruno return;
288a9ca1c79SSean Bruno }
289a9ca1c79SSean Bruno }
290a9ca1c79SSean Bruno
291a9ca1c79SSean Bruno /* Reset the CS4227. */
292a9ca1c79SSean Bruno status = ixgbe_reset_cs4227(hw);
293a9ca1c79SSean Bruno if (status != IXGBE_SUCCESS) {
294a9ca1c79SSean Bruno ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
295a9ca1c79SSean Bruno "CS4227 reset failed: %d", status);
296a9ca1c79SSean Bruno goto out;
297a9ca1c79SSean Bruno }
298a9ca1c79SSean Bruno
299a9ca1c79SSean Bruno /* Reset takes so long, temporarily release semaphore in case the
300a9ca1c79SSean Bruno * other driver instance is waiting for the reset indication.
301a9ca1c79SSean Bruno */
302a9ca1c79SSean Bruno ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
303a9ca1c79SSean Bruno IXGBE_CS4227_RESET_PENDING);
304a9ca1c79SSean Bruno hw->mac.ops.release_swfw_sync(hw, swfw_mask);
305a9ca1c79SSean Bruno msec_delay(10);
306a9ca1c79SSean Bruno status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
307a9ca1c79SSean Bruno if (status != IXGBE_SUCCESS) {
308a9ca1c79SSean Bruno ERROR_REPORT2(IXGBE_ERROR_CAUTION,
309a9ca1c79SSean Bruno "semaphore failed with %d", status);
310a9ca1c79SSean Bruno return;
311a9ca1c79SSean Bruno }
312a9ca1c79SSean Bruno
313a9ca1c79SSean Bruno /* Record completion for next time. */
314a9ca1c79SSean Bruno status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
315a9ca1c79SSean Bruno IXGBE_CS4227_RESET_COMPLETE);
316a9ca1c79SSean Bruno
317a9ca1c79SSean Bruno out:
318a9ca1c79SSean Bruno hw->mac.ops.release_swfw_sync(hw, swfw_mask);
319a9ca1c79SSean Bruno msec_delay(hw->eeprom.semaphore_delay);
3206f37f232SEric Joyner }
3216f37f232SEric Joyner
3226f37f232SEric Joyner /**
3236f37f232SEric Joyner * ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control
3246f37f232SEric Joyner * @hw: pointer to hardware structure
3256f37f232SEric Joyner **/
ixgbe_setup_mux_ctl(struct ixgbe_hw * hw)3266f37f232SEric Joyner static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
3276f37f232SEric Joyner {
3286f37f232SEric Joyner u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
3296f37f232SEric Joyner
3306f37f232SEric Joyner if (hw->bus.lan_id) {
3316f37f232SEric Joyner esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
3326f37f232SEric Joyner esdp |= IXGBE_ESDP_SDP1_DIR;
3336f37f232SEric Joyner }
3346f37f232SEric Joyner esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
3356f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
3366f37f232SEric Joyner IXGBE_WRITE_FLUSH(hw);
3376f37f232SEric Joyner }
3386f37f232SEric Joyner
3396f37f232SEric Joyner /**
3406f37f232SEric Joyner * ixgbe_identify_phy_x550em - Get PHY type based on device id
3416f37f232SEric Joyner * @hw: pointer to hardware structure
3426f37f232SEric Joyner *
3436f37f232SEric Joyner * Returns error code
3446f37f232SEric Joyner */
ixgbe_identify_phy_x550em(struct ixgbe_hw * hw)3456f37f232SEric Joyner static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
3466f37f232SEric Joyner {
3478eb6488eSEric Joyner hw->mac.ops.set_lan_id(hw);
3488eb6488eSEric Joyner
3498eb6488eSEric Joyner ixgbe_read_mng_if_sel_x550em(hw);
3508eb6488eSEric Joyner
3516f37f232SEric Joyner switch (hw->device_id) {
3528eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP:
3530a4f0befSXiaoyun Li return ixgbe_identify_sfp_module_X550em(hw);
3546f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_SFP:
3556f37f232SEric Joyner /* set up for CS4227 usage */
3566f37f232SEric Joyner ixgbe_setup_mux_ctl(hw);
3576f37f232SEric Joyner ixgbe_check_cs4227(hw);
35850455f73SPiotr Skajewski return ixgbe_identify_sfp_module_X550em(hw);
3598eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP_N:
3600a4f0befSXiaoyun Li return ixgbe_identify_sfp_module_X550em(hw);
3616f37f232SEric Joyner break;
3626f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_KX4:
3636f37f232SEric Joyner hw->phy.type = ixgbe_phy_x550em_kx4;
3646f37f232SEric Joyner break;
3658eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_X_XFI:
3668eb6488eSEric Joyner hw->phy.type = ixgbe_phy_x550em_xfi;
3678eb6488eSEric Joyner break;
3686f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_KR:
3698eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_KR:
3708eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_KR_L:
3716f37f232SEric Joyner hw->phy.type = ixgbe_phy_x550em_kr;
3726f37f232SEric Joyner break;
3738eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_10G_T:
3746f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_10G_T:
3756f37f232SEric Joyner return ixgbe_identify_phy_generic(hw);
3768eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_X_1G_T:
3778eb6488eSEric Joyner hw->phy.type = ixgbe_phy_ext_1g_t;
3788eb6488eSEric Joyner break;
3798eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T:
3808eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T_L:
3818eb6488eSEric Joyner hw->phy.type = ixgbe_phy_fw;
3828eb6488eSEric Joyner if (hw->bus.lan_id)
3838eb6488eSEric Joyner hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
3848eb6488eSEric Joyner else
3858eb6488eSEric Joyner hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
3868eb6488eSEric Joyner break;
3876f37f232SEric Joyner default:
3886f37f232SEric Joyner break;
3896f37f232SEric Joyner }
3906f37f232SEric Joyner return IXGBE_SUCCESS;
3916f37f232SEric Joyner }
3926f37f232SEric Joyner
3938eb6488eSEric Joyner /**
3948eb6488eSEric Joyner * ixgbe_fw_phy_activity - Perform an activity on a PHY
3958eb6488eSEric Joyner * @hw: pointer to hardware structure
3968eb6488eSEric Joyner * @activity: activity to perform
3978eb6488eSEric Joyner * @data: Pointer to 4 32-bit words of data
3988eb6488eSEric Joyner */
ixgbe_fw_phy_activity(struct ixgbe_hw * hw,u16 activity,u32 (* data)[FW_PHY_ACT_DATA_COUNT])3998eb6488eSEric Joyner s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity,
4008eb6488eSEric Joyner u32 (*data)[FW_PHY_ACT_DATA_COUNT])
4018eb6488eSEric Joyner {
4028eb6488eSEric Joyner union {
4038eb6488eSEric Joyner struct ixgbe_hic_phy_activity_req cmd;
4048eb6488eSEric Joyner struct ixgbe_hic_phy_activity_resp rsp;
4058eb6488eSEric Joyner } hic;
4068eb6488eSEric Joyner u16 retries = FW_PHY_ACT_RETRIES;
4078eb6488eSEric Joyner s32 rc;
4088eb6488eSEric Joyner u16 i;
4098eb6488eSEric Joyner
4108eb6488eSEric Joyner do {
4118eb6488eSEric Joyner memset(&hic, 0, sizeof(hic));
4128eb6488eSEric Joyner hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD;
4138eb6488eSEric Joyner hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN;
4148eb6488eSEric Joyner hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
4158eb6488eSEric Joyner hic.cmd.port_number = hw->bus.lan_id;
4168eb6488eSEric Joyner hic.cmd.activity_id = IXGBE_CPU_TO_LE16(activity);
4178eb6488eSEric Joyner for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
4188eb6488eSEric Joyner hic.cmd.data[i] = IXGBE_CPU_TO_BE32((*data)[i]);
4198eb6488eSEric Joyner
4208eb6488eSEric Joyner rc = ixgbe_host_interface_command(hw, (u32 *)&hic.cmd,
4218eb6488eSEric Joyner sizeof(hic.cmd),
4228eb6488eSEric Joyner IXGBE_HI_COMMAND_TIMEOUT,
42379b36ec9SKevin Bowling true);
4248eb6488eSEric Joyner if (rc != IXGBE_SUCCESS)
4258eb6488eSEric Joyner return rc;
4268eb6488eSEric Joyner if (hic.rsp.hdr.cmd_or_resp.ret_status ==
4278eb6488eSEric Joyner FW_CEM_RESP_STATUS_SUCCESS) {
4288eb6488eSEric Joyner for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
4298eb6488eSEric Joyner (*data)[i] = IXGBE_BE32_TO_CPU(hic.rsp.data[i]);
4308eb6488eSEric Joyner return IXGBE_SUCCESS;
4318eb6488eSEric Joyner }
4328eb6488eSEric Joyner usec_delay(20);
4338eb6488eSEric Joyner --retries;
4348eb6488eSEric Joyner } while (retries > 0);
4358eb6488eSEric Joyner
4368eb6488eSEric Joyner return IXGBE_ERR_HOST_INTERFACE_COMMAND;
4378eb6488eSEric Joyner }
4388eb6488eSEric Joyner
4398eb6488eSEric Joyner static const struct {
4408eb6488eSEric Joyner u16 fw_speed;
4418eb6488eSEric Joyner ixgbe_link_speed phy_speed;
4428eb6488eSEric Joyner } ixgbe_fw_map[] = {
4438eb6488eSEric Joyner { FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL },
4448eb6488eSEric Joyner { FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL },
4458eb6488eSEric Joyner { FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL },
4468eb6488eSEric Joyner { FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL },
4478eb6488eSEric Joyner { FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL },
4488eb6488eSEric Joyner { FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL },
4498eb6488eSEric Joyner };
4508eb6488eSEric Joyner
4518eb6488eSEric Joyner /**
4528eb6488eSEric Joyner * ixgbe_get_phy_id_fw - Get the phy ID via firmware command
4538eb6488eSEric Joyner * @hw: pointer to hardware structure
4548eb6488eSEric Joyner *
4558eb6488eSEric Joyner * Returns error code
4568eb6488eSEric Joyner */
ixgbe_get_phy_id_fw(struct ixgbe_hw * hw)4578eb6488eSEric Joyner static s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw)
4588eb6488eSEric Joyner {
4598eb6488eSEric Joyner u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
4608eb6488eSEric Joyner u16 phy_speeds;
4618eb6488eSEric Joyner u16 phy_id_lo;
4628eb6488eSEric Joyner s32 rc;
4638eb6488eSEric Joyner u16 i;
4648eb6488eSEric Joyner
4658eb6488eSEric Joyner rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info);
4668eb6488eSEric Joyner if (rc)
4678eb6488eSEric Joyner return rc;
4688eb6488eSEric Joyner
4698eb6488eSEric Joyner hw->phy.speeds_supported = 0;
4708eb6488eSEric Joyner phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK;
4718eb6488eSEric Joyner for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) {
4728eb6488eSEric Joyner if (phy_speeds & ixgbe_fw_map[i].fw_speed)
4738eb6488eSEric Joyner hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed;
4748eb6488eSEric Joyner }
4758eb6488eSEric Joyner if (!hw->phy.autoneg_advertised)
4768eb6488eSEric Joyner hw->phy.autoneg_advertised = hw->phy.speeds_supported;
4778eb6488eSEric Joyner
4788eb6488eSEric Joyner hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK;
4798eb6488eSEric Joyner phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK;
4808eb6488eSEric Joyner hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK;
4818eb6488eSEric Joyner hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK;
4828eb6488eSEric Joyner if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK)
4838eb6488eSEric Joyner return IXGBE_ERR_PHY_ADDR_INVALID;
4848eb6488eSEric Joyner return IXGBE_SUCCESS;
4858eb6488eSEric Joyner }
4868eb6488eSEric Joyner
4878eb6488eSEric Joyner /**
4888eb6488eSEric Joyner * ixgbe_identify_phy_fw - Get PHY type based on firmware command
4898eb6488eSEric Joyner * @hw: pointer to hardware structure
4908eb6488eSEric Joyner *
4918eb6488eSEric Joyner * Returns error code
4928eb6488eSEric Joyner */
ixgbe_identify_phy_fw(struct ixgbe_hw * hw)4938eb6488eSEric Joyner static s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw)
4948eb6488eSEric Joyner {
4958eb6488eSEric Joyner if (hw->bus.lan_id)
4968eb6488eSEric Joyner hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
4978eb6488eSEric Joyner else
4988eb6488eSEric Joyner hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
4998eb6488eSEric Joyner
5008eb6488eSEric Joyner hw->phy.type = ixgbe_phy_fw;
5018eb6488eSEric Joyner hw->phy.ops.read_reg = NULL;
5028eb6488eSEric Joyner hw->phy.ops.write_reg = NULL;
5038eb6488eSEric Joyner return ixgbe_get_phy_id_fw(hw);
5048eb6488eSEric Joyner }
5058eb6488eSEric Joyner
5068eb6488eSEric Joyner /**
5078eb6488eSEric Joyner * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY
5088eb6488eSEric Joyner * @hw: pointer to hardware structure
5098eb6488eSEric Joyner *
5108eb6488eSEric Joyner * Returns error code
5118eb6488eSEric Joyner */
ixgbe_shutdown_fw_phy(struct ixgbe_hw * hw)5128eb6488eSEric Joyner s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw)
5138eb6488eSEric Joyner {
5148eb6488eSEric Joyner u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
5158eb6488eSEric Joyner
5168eb6488eSEric Joyner setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF;
5178eb6488eSEric Joyner return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup);
5188eb6488eSEric Joyner }
5198eb6488eSEric Joyner
ixgbe_read_phy_reg_x550em(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)5206f37f232SEric Joyner static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
5216f37f232SEric Joyner u32 device_type, u16 *phy_data)
5226f37f232SEric Joyner {
5236f37f232SEric Joyner UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, *phy_data);
5246f37f232SEric Joyner return IXGBE_NOT_IMPLEMENTED;
5256f37f232SEric Joyner }
5266f37f232SEric Joyner
ixgbe_write_phy_reg_x550em(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)5276f37f232SEric Joyner static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
5286f37f232SEric Joyner u32 device_type, u16 phy_data)
5296f37f232SEric Joyner {
5306f37f232SEric Joyner UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, phy_data);
5316f37f232SEric Joyner return IXGBE_NOT_IMPLEMENTED;
5326f37f232SEric Joyner }
5336f37f232SEric Joyner
5346f37f232SEric Joyner /**
5358eb6488eSEric Joyner * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
5368eb6488eSEric Joyner * @hw: pointer to the hardware structure
5378eb6488eSEric Joyner * @addr: I2C bus address to read from
5388eb6488eSEric Joyner * @reg: I2C device register to read from
5398eb6488eSEric Joyner * @val: pointer to location to receive read value
5408eb6488eSEric Joyner *
5418eb6488eSEric Joyner * Returns an error code on error.
5428eb6488eSEric Joyner **/
ixgbe_read_i2c_combined_generic(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 * val)5438eb6488eSEric Joyner static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
5448eb6488eSEric Joyner u16 reg, u16 *val)
5458eb6488eSEric Joyner {
54679b36ec9SKevin Bowling return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true);
5478eb6488eSEric Joyner }
5488eb6488eSEric Joyner
5498eb6488eSEric Joyner /**
5508eb6488eSEric Joyner * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
5518eb6488eSEric Joyner * @hw: pointer to the hardware structure
5528eb6488eSEric Joyner * @addr: I2C bus address to read from
5538eb6488eSEric Joyner * @reg: I2C device register to read from
5548eb6488eSEric Joyner * @val: pointer to location to receive read value
5558eb6488eSEric Joyner *
5568eb6488eSEric Joyner * Returns an error code on error.
5578eb6488eSEric Joyner **/
5588eb6488eSEric Joyner static s32
ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 * val)5598eb6488eSEric Joyner ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
5608eb6488eSEric Joyner u16 reg, u16 *val)
5618eb6488eSEric Joyner {
56279b36ec9SKevin Bowling return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false);
5638eb6488eSEric Joyner }
5648eb6488eSEric Joyner
5658eb6488eSEric Joyner /**
5668eb6488eSEric Joyner * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
5678eb6488eSEric Joyner * @hw: pointer to the hardware structure
5688eb6488eSEric Joyner * @addr: I2C bus address to write to
5698eb6488eSEric Joyner * @reg: I2C device register to write to
5708eb6488eSEric Joyner * @val: value to write
5718eb6488eSEric Joyner *
5728eb6488eSEric Joyner * Returns an error code on error.
5738eb6488eSEric Joyner **/
ixgbe_write_i2c_combined_generic(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 val)5748eb6488eSEric Joyner static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
5758eb6488eSEric Joyner u8 addr, u16 reg, u16 val)
5768eb6488eSEric Joyner {
57779b36ec9SKevin Bowling return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
5788eb6488eSEric Joyner }
5798eb6488eSEric Joyner
5808eb6488eSEric Joyner /**
5818eb6488eSEric Joyner * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
5828eb6488eSEric Joyner * @hw: pointer to the hardware structure
5838eb6488eSEric Joyner * @addr: I2C bus address to write to
5848eb6488eSEric Joyner * @reg: I2C device register to write to
5858eb6488eSEric Joyner * @val: value to write
5868eb6488eSEric Joyner *
5878eb6488eSEric Joyner * Returns an error code on error.
5888eb6488eSEric Joyner **/
5898eb6488eSEric Joyner static s32
ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 val)5908eb6488eSEric Joyner ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
5918eb6488eSEric Joyner u8 addr, u16 reg, u16 val)
5928eb6488eSEric Joyner {
59379b36ec9SKevin Bowling return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false);
5948eb6488eSEric Joyner }
5958eb6488eSEric Joyner
5968eb6488eSEric Joyner /**
5976f37f232SEric Joyner * ixgbe_init_ops_X550EM - Inits func ptrs and MAC type
5986f37f232SEric Joyner * @hw: pointer to hardware structure
5996f37f232SEric Joyner *
6006f37f232SEric Joyner * Initialize the function pointers and for MAC type X550EM.
6016f37f232SEric Joyner * Does not touch the hardware.
6026f37f232SEric Joyner **/
ixgbe_init_ops_X550EM(struct ixgbe_hw * hw)6036f37f232SEric Joyner s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw)
6046f37f232SEric Joyner {
6056f37f232SEric Joyner struct ixgbe_mac_info *mac = &hw->mac;
6066f37f232SEric Joyner struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
6076f37f232SEric Joyner struct ixgbe_phy_info *phy = &hw->phy;
6086f37f232SEric Joyner s32 ret_val;
6096f37f232SEric Joyner
6106f37f232SEric Joyner DEBUGFUNC("ixgbe_init_ops_X550EM");
6116f37f232SEric Joyner
6126f37f232SEric Joyner /* Similar to X550 so start there. */
6136f37f232SEric Joyner ret_val = ixgbe_init_ops_X550(hw);
6146f37f232SEric Joyner
6156f37f232SEric Joyner /* Since this function eventually calls
6166f37f232SEric Joyner * ixgbe_init_ops_540 by design, we are setting
6176f37f232SEric Joyner * the pointers to NULL explicitly here to overwrite
6186f37f232SEric Joyner * the values being set in the x540 function.
6196f37f232SEric Joyner */
6203f66b96dSKevin Bowling /* Thermal sensor not supported in x550EM */
6213f66b96dSKevin Bowling mac->ops.get_thermal_sensor_data = NULL;
6223f66b96dSKevin Bowling mac->ops.init_thermal_sensor_thresh = NULL;
6233f66b96dSKevin Bowling mac->thermal_sensor_enabled = false;
6246f37f232SEric Joyner
6258eb6488eSEric Joyner /* Bypass not supported in x550EM */
6268eb6488eSEric Joyner mac->ops.bypass_rw = NULL;
6278eb6488eSEric Joyner mac->ops.bypass_valid_rd = NULL;
6288eb6488eSEric Joyner mac->ops.bypass_set = NULL;
6298eb6488eSEric Joyner mac->ops.bypass_rd_eep = NULL;
6308eb6488eSEric Joyner
6316f37f232SEric Joyner /* FCOE not supported in x550EM */
6326f37f232SEric Joyner mac->ops.get_san_mac_addr = NULL;
6336f37f232SEric Joyner mac->ops.set_san_mac_addr = NULL;
6346f37f232SEric Joyner mac->ops.get_wwn_prefix = NULL;
6356f37f232SEric Joyner mac->ops.get_fcoe_boot_status = NULL;
6366f37f232SEric Joyner
6376f37f232SEric Joyner /* IPsec not supported in x550EM */
6386f37f232SEric Joyner mac->ops.disable_sec_rx_path = NULL;
6396f37f232SEric Joyner mac->ops.enable_sec_rx_path = NULL;
6406f37f232SEric Joyner
6416f37f232SEric Joyner /* AUTOC register is not present in x550EM. */
6426f37f232SEric Joyner mac->ops.prot_autoc_read = NULL;
6436f37f232SEric Joyner mac->ops.prot_autoc_write = NULL;
6446f37f232SEric Joyner
6456f37f232SEric Joyner /* X550EM bus type is internal*/
6466f37f232SEric Joyner hw->bus.type = ixgbe_bus_type_internal;
6476f37f232SEric Joyner mac->ops.get_bus_info = ixgbe_get_bus_info_X550em;
6486f37f232SEric Joyner
649a9ca1c79SSean Bruno
6506f37f232SEric Joyner mac->ops.get_media_type = ixgbe_get_media_type_X550em;
6516f37f232SEric Joyner mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em;
6526f37f232SEric Joyner mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em;
6536f37f232SEric Joyner mac->ops.reset_hw = ixgbe_reset_hw_X550em;
6546f37f232SEric Joyner mac->ops.get_supported_physical_layer =
6556f37f232SEric Joyner ixgbe_get_supported_physical_layer_X550em;
6566f37f232SEric Joyner
6576f37f232SEric Joyner if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper)
6586f37f232SEric Joyner mac->ops.setup_fc = ixgbe_setup_fc_generic;
6596f37f232SEric Joyner else
6606f37f232SEric Joyner mac->ops.setup_fc = ixgbe_setup_fc_X550em;
6616f37f232SEric Joyner
6626f37f232SEric Joyner /* PHY */
6636f37f232SEric Joyner phy->ops.init = ixgbe_init_phy_ops_X550em;
6648eb6488eSEric Joyner switch (hw->device_id) {
6658eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T:
6668eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T_L:
6678eb6488eSEric Joyner mac->ops.setup_fc = NULL;
6688eb6488eSEric Joyner phy->ops.identify = ixgbe_identify_phy_fw;
6698eb6488eSEric Joyner phy->ops.set_phy_power = NULL;
6708eb6488eSEric Joyner phy->ops.get_firmware_version = NULL;
6718eb6488eSEric Joyner break;
6728eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_X_1G_T:
6738eb6488eSEric Joyner mac->ops.setup_fc = NULL;
6746f37f232SEric Joyner phy->ops.identify = ixgbe_identify_phy_x550em;
6758eb6488eSEric Joyner phy->ops.set_phy_power = NULL;
6768eb6488eSEric Joyner break;
6778eb6488eSEric Joyner default:
6788eb6488eSEric Joyner phy->ops.identify = ixgbe_identify_phy_x550em;
6798eb6488eSEric Joyner }
6808eb6488eSEric Joyner
6816f37f232SEric Joyner if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
6826f37f232SEric Joyner phy->ops.set_phy_power = NULL;
6836f37f232SEric Joyner
6846f37f232SEric Joyner
6856f37f232SEric Joyner /* EEPROM */
6866f37f232SEric Joyner eeprom->ops.init_params = ixgbe_init_eeprom_params_X540;
6876f37f232SEric Joyner eeprom->ops.read = ixgbe_read_ee_hostif_X550;
6886f37f232SEric Joyner eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550;
6896f37f232SEric Joyner eeprom->ops.write = ixgbe_write_ee_hostif_X550;
6906f37f232SEric Joyner eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550;
6916f37f232SEric Joyner eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
6926f37f232SEric Joyner eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
6936f37f232SEric Joyner eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
6946f37f232SEric Joyner
6956f37f232SEric Joyner return ret_val;
6966f37f232SEric Joyner }
6976f37f232SEric Joyner
6986f37f232SEric Joyner /**
6998eb6488eSEric Joyner * ixgbe_setup_fw_link - Setup firmware-controlled PHYs
7008eb6488eSEric Joyner * @hw: pointer to hardware structure
7018eb6488eSEric Joyner */
ixgbe_setup_fw_link(struct ixgbe_hw * hw)7028eb6488eSEric Joyner static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw)
7038eb6488eSEric Joyner {
7048eb6488eSEric Joyner u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
7058eb6488eSEric Joyner s32 rc;
7068eb6488eSEric Joyner u16 i;
7078eb6488eSEric Joyner
7088eb6488eSEric Joyner if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
7098eb6488eSEric Joyner return 0;
7108eb6488eSEric Joyner
7118eb6488eSEric Joyner if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
7128eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
7138eb6488eSEric Joyner "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
7148eb6488eSEric Joyner return IXGBE_ERR_INVALID_LINK_SETTINGS;
7158eb6488eSEric Joyner }
7168eb6488eSEric Joyner
7178eb6488eSEric Joyner switch (hw->fc.requested_mode) {
7188eb6488eSEric Joyner case ixgbe_fc_full:
7198eb6488eSEric Joyner setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX <<
7208eb6488eSEric Joyner FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
7218eb6488eSEric Joyner break;
7228eb6488eSEric Joyner case ixgbe_fc_rx_pause:
7238eb6488eSEric Joyner setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX <<
7248eb6488eSEric Joyner FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
7258eb6488eSEric Joyner break;
7268eb6488eSEric Joyner case ixgbe_fc_tx_pause:
7278eb6488eSEric Joyner setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX <<
7288eb6488eSEric Joyner FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
7298eb6488eSEric Joyner break;
7308eb6488eSEric Joyner default:
7318eb6488eSEric Joyner break;
7328eb6488eSEric Joyner }
7338eb6488eSEric Joyner
7348eb6488eSEric Joyner for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) {
7358eb6488eSEric Joyner if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed)
736994dd632SGuinan Sun setup[0] |= (u32)(ixgbe_fw_map[i].fw_speed);
7378eb6488eSEric Joyner }
7388eb6488eSEric Joyner setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN;
7398eb6488eSEric Joyner
7408eb6488eSEric Joyner if (hw->phy.eee_speeds_advertised)
7418eb6488eSEric Joyner setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE;
7428eb6488eSEric Joyner
7438eb6488eSEric Joyner rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);
7448eb6488eSEric Joyner if (rc)
7458eb6488eSEric Joyner return rc;
7468eb6488eSEric Joyner if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
7478eb6488eSEric Joyner return IXGBE_ERR_OVERTEMP;
7488eb6488eSEric Joyner return IXGBE_SUCCESS;
7498eb6488eSEric Joyner }
7508eb6488eSEric Joyner
7518eb6488eSEric Joyner /**
752edef2769SRadoslaw Tyl * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs
7538eb6488eSEric Joyner * @hw: pointer to hardware structure
7548eb6488eSEric Joyner *
7558eb6488eSEric Joyner * Called at init time to set up flow control.
7568eb6488eSEric Joyner */
ixgbe_fc_autoneg_fw(struct ixgbe_hw * hw)7578eb6488eSEric Joyner static s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw)
7588eb6488eSEric Joyner {
7598eb6488eSEric Joyner if (hw->fc.requested_mode == ixgbe_fc_default)
7608eb6488eSEric Joyner hw->fc.requested_mode = ixgbe_fc_full;
7618eb6488eSEric Joyner
7628eb6488eSEric Joyner return ixgbe_setup_fw_link(hw);
7638eb6488eSEric Joyner }
7648eb6488eSEric Joyner
7658eb6488eSEric Joyner /**
7668eb6488eSEric Joyner * ixgbe_setup_eee_fw - Enable/disable EEE support
7678eb6488eSEric Joyner * @hw: pointer to the HW structure
7688eb6488eSEric Joyner * @enable_eee: boolean flag to enable EEE
7698eb6488eSEric Joyner *
7708eb6488eSEric Joyner * Enable/disable EEE based on enable_eee flag.
7718eb6488eSEric Joyner * This function controls EEE for firmware-based PHY implementations.
7728eb6488eSEric Joyner */
ixgbe_setup_eee_fw(struct ixgbe_hw * hw,bool enable_eee)7738eb6488eSEric Joyner static s32 ixgbe_setup_eee_fw(struct ixgbe_hw *hw, bool enable_eee)
7748eb6488eSEric Joyner {
7758eb6488eSEric Joyner if (!!hw->phy.eee_speeds_advertised == enable_eee)
7768eb6488eSEric Joyner return IXGBE_SUCCESS;
7778eb6488eSEric Joyner if (enable_eee)
7788eb6488eSEric Joyner hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
7798eb6488eSEric Joyner else
7808eb6488eSEric Joyner hw->phy.eee_speeds_advertised = 0;
7818eb6488eSEric Joyner return hw->phy.ops.setup_link(hw);
7828eb6488eSEric Joyner }
7838eb6488eSEric Joyner
7848eb6488eSEric Joyner /**
7858eb6488eSEric Joyner * ixgbe_init_ops_X550EM_a - Inits func ptrs and MAC type
7868eb6488eSEric Joyner * @hw: pointer to hardware structure
7878eb6488eSEric Joyner *
7888eb6488eSEric Joyner * Initialize the function pointers and for MAC type X550EM_a.
7898eb6488eSEric Joyner * Does not touch the hardware.
7908eb6488eSEric Joyner **/
ixgbe_init_ops_X550EM_a(struct ixgbe_hw * hw)7918eb6488eSEric Joyner s32 ixgbe_init_ops_X550EM_a(struct ixgbe_hw *hw)
7928eb6488eSEric Joyner {
7938eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac;
7948eb6488eSEric Joyner s32 ret_val;
7958eb6488eSEric Joyner
7968eb6488eSEric Joyner DEBUGFUNC("ixgbe_init_ops_X550EM_a");
7978eb6488eSEric Joyner
7988eb6488eSEric Joyner /* Start with generic X550EM init */
7998eb6488eSEric Joyner ret_val = ixgbe_init_ops_X550EM(hw);
8008eb6488eSEric Joyner
8018eb6488eSEric Joyner mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
8028eb6488eSEric Joyner mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
8038eb6488eSEric Joyner mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550a;
8048eb6488eSEric Joyner mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550a;
8058eb6488eSEric Joyner
8068eb6488eSEric Joyner switch (mac->ops.get_media_type(hw)) {
8078eb6488eSEric Joyner case ixgbe_media_type_fiber:
8088eb6488eSEric Joyner mac->ops.setup_fc = NULL;
8098eb6488eSEric Joyner mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;
8108eb6488eSEric Joyner break;
8118eb6488eSEric Joyner case ixgbe_media_type_backplane:
8128eb6488eSEric Joyner mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;
8138eb6488eSEric Joyner mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;
8148eb6488eSEric Joyner break;
8158eb6488eSEric Joyner default:
8168eb6488eSEric Joyner break;
8178eb6488eSEric Joyner }
8188eb6488eSEric Joyner
8198eb6488eSEric Joyner switch (hw->device_id) {
8208eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T:
8218eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T_L:
8228eb6488eSEric Joyner mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a;
8238eb6488eSEric Joyner mac->ops.setup_fc = ixgbe_fc_autoneg_fw;
8248eb6488eSEric Joyner mac->ops.setup_eee = ixgbe_setup_eee_fw;
8258eb6488eSEric Joyner hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL |
8268eb6488eSEric Joyner IXGBE_LINK_SPEED_1GB_FULL;
8278eb6488eSEric Joyner hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
8288eb6488eSEric Joyner break;
8298eb6488eSEric Joyner default:
8308eb6488eSEric Joyner break;
8318eb6488eSEric Joyner }
8328eb6488eSEric Joyner
8338eb6488eSEric Joyner return ret_val;
8348eb6488eSEric Joyner }
8358eb6488eSEric Joyner
8368eb6488eSEric Joyner /**
8378eb6488eSEric Joyner * ixgbe_init_ops_X550EM_x - Inits func ptrs and MAC type
8388eb6488eSEric Joyner * @hw: pointer to hardware structure
8398eb6488eSEric Joyner *
8408eb6488eSEric Joyner * Initialize the function pointers and for MAC type X550EM_x.
8418eb6488eSEric Joyner * Does not touch the hardware.
8428eb6488eSEric Joyner **/
ixgbe_init_ops_X550EM_x(struct ixgbe_hw * hw)8438eb6488eSEric Joyner s32 ixgbe_init_ops_X550EM_x(struct ixgbe_hw *hw)
8448eb6488eSEric Joyner {
8458eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac;
8468eb6488eSEric Joyner struct ixgbe_link_info *link = &hw->link;
8478eb6488eSEric Joyner s32 ret_val;
8488eb6488eSEric Joyner
8498eb6488eSEric Joyner DEBUGFUNC("ixgbe_init_ops_X550EM_x");
8508eb6488eSEric Joyner
8518eb6488eSEric Joyner /* Start with generic X550EM init */
8528eb6488eSEric Joyner ret_val = ixgbe_init_ops_X550EM(hw);
8538eb6488eSEric Joyner
8548eb6488eSEric Joyner mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
8558eb6488eSEric Joyner mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
8568eb6488eSEric Joyner mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550em;
8578eb6488eSEric Joyner mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550em;
8588eb6488eSEric Joyner link->ops.read_link = ixgbe_read_i2c_combined_generic;
8598eb6488eSEric Joyner link->ops.read_link_unlocked = ixgbe_read_i2c_combined_generic_unlocked;
8608eb6488eSEric Joyner link->ops.write_link = ixgbe_write_i2c_combined_generic;
8618eb6488eSEric Joyner link->ops.write_link_unlocked =
8628eb6488eSEric Joyner ixgbe_write_i2c_combined_generic_unlocked;
8638eb6488eSEric Joyner link->addr = IXGBE_CS4227;
8648eb6488eSEric Joyner
8658eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T) {
8668eb6488eSEric Joyner mac->ops.setup_fc = NULL;
8678eb6488eSEric Joyner mac->ops.setup_eee = NULL;
8688eb6488eSEric Joyner mac->ops.init_led_link_act = NULL;
8698eb6488eSEric Joyner }
8708eb6488eSEric Joyner
8718eb6488eSEric Joyner return ret_val;
8728eb6488eSEric Joyner }
8738eb6488eSEric Joyner
8748eb6488eSEric Joyner /**
8756f37f232SEric Joyner * ixgbe_dmac_config_X550
8766f37f232SEric Joyner * @hw: pointer to hardware structure
8776f37f232SEric Joyner *
8786f37f232SEric Joyner * Configure DMA coalescing. If enabling dmac, dmac is activated.
8796f37f232SEric Joyner * When disabling dmac, dmac enable dmac bit is cleared.
8806f37f232SEric Joyner **/
ixgbe_dmac_config_X550(struct ixgbe_hw * hw)8816f37f232SEric Joyner s32 ixgbe_dmac_config_X550(struct ixgbe_hw *hw)
8826f37f232SEric Joyner {
8836f37f232SEric Joyner u32 reg, high_pri_tc;
8846f37f232SEric Joyner
8856f37f232SEric Joyner DEBUGFUNC("ixgbe_dmac_config_X550");
8866f37f232SEric Joyner
8876f37f232SEric Joyner /* Disable DMA coalescing before configuring */
8886f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
8896f37f232SEric Joyner reg &= ~IXGBE_DMACR_DMAC_EN;
8906f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
8916f37f232SEric Joyner
8926f37f232SEric Joyner /* Disable DMA Coalescing if the watchdog timer is 0 */
8936f37f232SEric Joyner if (!hw->mac.dmac_config.watchdog_timer)
8946f37f232SEric Joyner goto out;
8956f37f232SEric Joyner
8966f37f232SEric Joyner ixgbe_dmac_config_tcs_X550(hw);
8976f37f232SEric Joyner
8986f37f232SEric Joyner /* Configure DMA Coalescing Control Register */
8996f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
9006f37f232SEric Joyner
9016f37f232SEric Joyner /* Set the watchdog timer in units of 40.96 usec */
9026f37f232SEric Joyner reg &= ~IXGBE_DMACR_DMACWT_MASK;
9036f37f232SEric Joyner reg |= (hw->mac.dmac_config.watchdog_timer * 100) / 4096;
9046f37f232SEric Joyner
9056f37f232SEric Joyner reg &= ~IXGBE_DMACR_HIGH_PRI_TC_MASK;
9066f37f232SEric Joyner /* If fcoe is enabled, set high priority traffic class */
9076f37f232SEric Joyner if (hw->mac.dmac_config.fcoe_en) {
9086f37f232SEric Joyner high_pri_tc = 1 << hw->mac.dmac_config.fcoe_tc;
9096f37f232SEric Joyner reg |= ((high_pri_tc << IXGBE_DMACR_HIGH_PRI_TC_SHIFT) &
9106f37f232SEric Joyner IXGBE_DMACR_HIGH_PRI_TC_MASK);
9116f37f232SEric Joyner }
9126f37f232SEric Joyner reg |= IXGBE_DMACR_EN_MNG_IND;
9136f37f232SEric Joyner
9146f37f232SEric Joyner /* Enable DMA coalescing after configuration */
9156f37f232SEric Joyner reg |= IXGBE_DMACR_DMAC_EN;
9166f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
9176f37f232SEric Joyner
9186f37f232SEric Joyner out:
9196f37f232SEric Joyner return IXGBE_SUCCESS;
9206f37f232SEric Joyner }
9216f37f232SEric Joyner
9226f37f232SEric Joyner /**
9236f37f232SEric Joyner * ixgbe_dmac_config_tcs_X550
9246f37f232SEric Joyner * @hw: pointer to hardware structure
9256f37f232SEric Joyner *
9266f37f232SEric Joyner * Configure DMA coalescing threshold per TC. The dmac enable bit must
9276f37f232SEric Joyner * be cleared before configuring.
9286f37f232SEric Joyner **/
ixgbe_dmac_config_tcs_X550(struct ixgbe_hw * hw)9296f37f232SEric Joyner s32 ixgbe_dmac_config_tcs_X550(struct ixgbe_hw *hw)
9306f37f232SEric Joyner {
9316f37f232SEric Joyner u32 tc, reg, pb_headroom, rx_pb_size, maxframe_size_kb;
9326f37f232SEric Joyner
9336f37f232SEric Joyner DEBUGFUNC("ixgbe_dmac_config_tcs_X550");
9346f37f232SEric Joyner
9356f37f232SEric Joyner /* Configure DMA coalescing enabled */
9366f37f232SEric Joyner switch (hw->mac.dmac_config.link_speed) {
9378eb6488eSEric Joyner case IXGBE_LINK_SPEED_10_FULL:
9386f37f232SEric Joyner case IXGBE_LINK_SPEED_100_FULL:
9396f37f232SEric Joyner pb_headroom = IXGBE_DMACRXT_100M;
9406f37f232SEric Joyner break;
9416f37f232SEric Joyner case IXGBE_LINK_SPEED_1GB_FULL:
9426f37f232SEric Joyner pb_headroom = IXGBE_DMACRXT_1G;
9436f37f232SEric Joyner break;
9446f37f232SEric Joyner default:
9456f37f232SEric Joyner pb_headroom = IXGBE_DMACRXT_10G;
9466f37f232SEric Joyner break;
9476f37f232SEric Joyner }
9486f37f232SEric Joyner
9496f37f232SEric Joyner maxframe_size_kb = ((IXGBE_READ_REG(hw, IXGBE_MAXFRS) >>
9506f37f232SEric Joyner IXGBE_MHADD_MFS_SHIFT) / 1024);
9516f37f232SEric Joyner
9526f37f232SEric Joyner /* Set the per Rx packet buffer receive threshold */
9536f37f232SEric Joyner for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) {
9546f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_DMCTH(tc));
9556f37f232SEric Joyner reg &= ~IXGBE_DMCTH_DMACRXT_MASK;
9566f37f232SEric Joyner
9576f37f232SEric Joyner if (tc < hw->mac.dmac_config.num_tcs) {
9586f37f232SEric Joyner /* Get Rx PB size */
9596f37f232SEric Joyner rx_pb_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(tc));
9606f37f232SEric Joyner rx_pb_size = (rx_pb_size & IXGBE_RXPBSIZE_MASK) >>
9616f37f232SEric Joyner IXGBE_RXPBSIZE_SHIFT;
9626f37f232SEric Joyner
9636f37f232SEric Joyner /* Calculate receive buffer threshold in kilobytes */
9646f37f232SEric Joyner if (rx_pb_size > pb_headroom)
9656f37f232SEric Joyner rx_pb_size = rx_pb_size - pb_headroom;
9666f37f232SEric Joyner else
9676f37f232SEric Joyner rx_pb_size = 0;
9686f37f232SEric Joyner
9696f37f232SEric Joyner /* Minimum of MFS shall be set for DMCTH */
9706f37f232SEric Joyner reg |= (rx_pb_size > maxframe_size_kb) ?
9716f37f232SEric Joyner rx_pb_size : maxframe_size_kb;
9726f37f232SEric Joyner }
9736f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_DMCTH(tc), reg);
9746f37f232SEric Joyner }
9756f37f232SEric Joyner return IXGBE_SUCCESS;
9766f37f232SEric Joyner }
9776f37f232SEric Joyner
9786f37f232SEric Joyner /**
9796f37f232SEric Joyner * ixgbe_dmac_update_tcs_X550
9806f37f232SEric Joyner * @hw: pointer to hardware structure
9816f37f232SEric Joyner *
9826f37f232SEric Joyner * Disables dmac, updates per TC settings, and then enables dmac.
9836f37f232SEric Joyner **/
ixgbe_dmac_update_tcs_X550(struct ixgbe_hw * hw)9846f37f232SEric Joyner s32 ixgbe_dmac_update_tcs_X550(struct ixgbe_hw *hw)
9856f37f232SEric Joyner {
9866f37f232SEric Joyner u32 reg;
9876f37f232SEric Joyner
9886f37f232SEric Joyner DEBUGFUNC("ixgbe_dmac_update_tcs_X550");
9896f37f232SEric Joyner
9906f37f232SEric Joyner /* Disable DMA coalescing before configuring */
9916f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
9926f37f232SEric Joyner reg &= ~IXGBE_DMACR_DMAC_EN;
9936f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
9946f37f232SEric Joyner
9956f37f232SEric Joyner ixgbe_dmac_config_tcs_X550(hw);
9966f37f232SEric Joyner
9976f37f232SEric Joyner /* Enable DMA coalescing after configuration */
9986f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
9996f37f232SEric Joyner reg |= IXGBE_DMACR_DMAC_EN;
10006f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
10016f37f232SEric Joyner
10026f37f232SEric Joyner return IXGBE_SUCCESS;
10036f37f232SEric Joyner }
10046f37f232SEric Joyner
10056f37f232SEric Joyner /**
10066f37f232SEric Joyner * ixgbe_init_eeprom_params_X550 - Initialize EEPROM params
10076f37f232SEric Joyner * @hw: pointer to hardware structure
10086f37f232SEric Joyner *
10096f37f232SEric Joyner * Initializes the EEPROM parameters ixgbe_eeprom_info within the
10106f37f232SEric Joyner * ixgbe_hw struct in order to set up EEPROM access.
10116f37f232SEric Joyner **/
ixgbe_init_eeprom_params_X550(struct ixgbe_hw * hw)10126f37f232SEric Joyner s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
10136f37f232SEric Joyner {
10146f37f232SEric Joyner struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
10156f37f232SEric Joyner u32 eec;
10166f37f232SEric Joyner u16 eeprom_size;
10176f37f232SEric Joyner
10186f37f232SEric Joyner DEBUGFUNC("ixgbe_init_eeprom_params_X550");
10196f37f232SEric Joyner
10206f37f232SEric Joyner if (eeprom->type == ixgbe_eeprom_uninitialized) {
10216f37f232SEric Joyner eeprom->semaphore_delay = 10;
10226f37f232SEric Joyner eeprom->type = ixgbe_flash;
10236f37f232SEric Joyner
10246f37f232SEric Joyner eec = IXGBE_READ_REG(hw, IXGBE_EEC);
10256f37f232SEric Joyner eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
10266f37f232SEric Joyner IXGBE_EEC_SIZE_SHIFT);
10276f37f232SEric Joyner eeprom->word_size = 1 << (eeprom_size +
10286f37f232SEric Joyner IXGBE_EEPROM_WORD_SIZE_SHIFT);
10296f37f232SEric Joyner
10306f37f232SEric Joyner DEBUGOUT2("Eeprom params: type = %d, size = %d\n",
10316f37f232SEric Joyner eeprom->type, eeprom->word_size);
10326f37f232SEric Joyner }
10336f37f232SEric Joyner
10346f37f232SEric Joyner return IXGBE_SUCCESS;
10356f37f232SEric Joyner }
10366f37f232SEric Joyner
10376f37f232SEric Joyner /**
10386f37f232SEric Joyner * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning
10396f37f232SEric Joyner * @hw: pointer to hardware structure
10406f37f232SEric Joyner * @enable: enable or disable source address pruning
10416f37f232SEric Joyner * @pool: Rx pool to set source address pruning for
10426f37f232SEric Joyner **/
ixgbe_set_source_address_pruning_X550(struct ixgbe_hw * hw,bool enable,unsigned int pool)10436f37f232SEric Joyner void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable,
10446f37f232SEric Joyner unsigned int pool)
10456f37f232SEric Joyner {
10466f37f232SEric Joyner u64 pfflp;
10476f37f232SEric Joyner
10486f37f232SEric Joyner /* max rx pool is 63 */
10496f37f232SEric Joyner if (pool > 63)
10506f37f232SEric Joyner return;
10516f37f232SEric Joyner
10526f37f232SEric Joyner pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL);
10536f37f232SEric Joyner pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32;
10546f37f232SEric Joyner
10556f37f232SEric Joyner if (enable)
10566f37f232SEric Joyner pfflp |= (1ULL << pool);
10576f37f232SEric Joyner else
10586f37f232SEric Joyner pfflp &= ~(1ULL << pool);
10596f37f232SEric Joyner
10606f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp);
10616f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32));
10626f37f232SEric Joyner }
10636f37f232SEric Joyner
10646f37f232SEric Joyner /**
106546981e90SGuinan Sun * ixgbe_set_ethertype_anti_spoofing_X550 - Configure Ethertype anti-spoofing
10666f37f232SEric Joyner * @hw: pointer to hardware structure
10676f37f232SEric Joyner * @enable: enable or disable switch for Ethertype anti-spoofing
10686f37f232SEric Joyner * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing
10696f37f232SEric Joyner *
10706f37f232SEric Joyner **/
ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw * hw,bool enable,int vf)10716f37f232SEric Joyner void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
10726f37f232SEric Joyner bool enable, int vf)
10736f37f232SEric Joyner {
10746f37f232SEric Joyner int vf_target_reg = vf >> 3;
10756f37f232SEric Joyner int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT;
10766f37f232SEric Joyner u32 pfvfspoof;
10776f37f232SEric Joyner
10786f37f232SEric Joyner DEBUGFUNC("ixgbe_set_ethertype_anti_spoofing_X550");
10796f37f232SEric Joyner
10806f37f232SEric Joyner pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
10816f37f232SEric Joyner if (enable)
10826f37f232SEric Joyner pfvfspoof |= (1 << vf_target_shift);
10836f37f232SEric Joyner else
10846f37f232SEric Joyner pfvfspoof &= ~(1 << vf_target_shift);
10856f37f232SEric Joyner
10866f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
10876f37f232SEric Joyner }
10886f37f232SEric Joyner
10896f37f232SEric Joyner /**
10906f37f232SEric Joyner * ixgbe_iosf_wait - Wait for IOSF command completion
10916f37f232SEric Joyner * @hw: pointer to hardware structure
10926f37f232SEric Joyner * @ctrl: pointer to location to receive final IOSF control value
10936f37f232SEric Joyner *
10946f37f232SEric Joyner * Returns failing status on timeout
10956f37f232SEric Joyner *
10966f37f232SEric Joyner * Note: ctrl can be NULL if the IOSF control register value is not needed
10976f37f232SEric Joyner **/
ixgbe_iosf_wait(struct ixgbe_hw * hw,u32 * ctrl)10986f37f232SEric Joyner static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl)
10996f37f232SEric Joyner {
1100a9ca1c79SSean Bruno u32 i, command = 0;
11016f37f232SEric Joyner
11026f37f232SEric Joyner /* Check every 10 usec to see if the address cycle completed.
11036f37f232SEric Joyner * The SB IOSF BUSY bit will clear when the operation is
11046f37f232SEric Joyner * complete
11056f37f232SEric Joyner */
11066f37f232SEric Joyner for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
11076f37f232SEric Joyner command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
11086f37f232SEric Joyner if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0)
11096f37f232SEric Joyner break;
11106f37f232SEric Joyner usec_delay(10);
11116f37f232SEric Joyner }
11126f37f232SEric Joyner if (ctrl)
11136f37f232SEric Joyner *ctrl = command;
11146f37f232SEric Joyner if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
11156f37f232SEric Joyner ERROR_REPORT1(IXGBE_ERROR_POLLING, "Wait timed out\n");
11166f37f232SEric Joyner return IXGBE_ERR_PHY;
11176f37f232SEric Joyner }
11186f37f232SEric Joyner
11196f37f232SEric Joyner return IXGBE_SUCCESS;
11206f37f232SEric Joyner }
11216f37f232SEric Joyner
11226f37f232SEric Joyner /**
11238eb6488eSEric Joyner * ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register
11248eb6488eSEric Joyner * of the IOSF device
11256f37f232SEric Joyner * @hw: pointer to hardware structure
11266f37f232SEric Joyner * @reg_addr: 32 bit PHY register to write
11276f37f232SEric Joyner * @device_type: 3 bit device type
11286f37f232SEric Joyner * @data: Data to write to the register
11296f37f232SEric Joyner **/
ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u32 data)11306f37f232SEric Joyner s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
11316f37f232SEric Joyner u32 device_type, u32 data)
11326f37f232SEric Joyner {
11336f37f232SEric Joyner u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
1134c1710eafSJohn Baldwin u32 command, error __unused;
11356f37f232SEric Joyner s32 ret;
11366f37f232SEric Joyner
11376f37f232SEric Joyner ret = ixgbe_acquire_swfw_semaphore(hw, gssr);
11386f37f232SEric Joyner if (ret != IXGBE_SUCCESS)
11396f37f232SEric Joyner return ret;
11406f37f232SEric Joyner
11416f37f232SEric Joyner ret = ixgbe_iosf_wait(hw, NULL);
11426f37f232SEric Joyner if (ret != IXGBE_SUCCESS)
11436f37f232SEric Joyner goto out;
11446f37f232SEric Joyner
11456f37f232SEric Joyner command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
11466f37f232SEric Joyner (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
11476f37f232SEric Joyner
11486f37f232SEric Joyner /* Write IOSF control register */
11496f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
11506f37f232SEric Joyner
11516f37f232SEric Joyner /* Write IOSF data register */
11526f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data);
11536f37f232SEric Joyner
11546f37f232SEric Joyner ret = ixgbe_iosf_wait(hw, &command);
11556f37f232SEric Joyner
11566f37f232SEric Joyner if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
11576f37f232SEric Joyner error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
11586f37f232SEric Joyner IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
11596f37f232SEric Joyner ERROR_REPORT2(IXGBE_ERROR_POLLING,
11606f37f232SEric Joyner "Failed to write, error %x\n", error);
11616f37f232SEric Joyner ret = IXGBE_ERR_PHY;
11626f37f232SEric Joyner }
11636f37f232SEric Joyner
11646f37f232SEric Joyner out:
11656f37f232SEric Joyner ixgbe_release_swfw_semaphore(hw, gssr);
11666f37f232SEric Joyner return ret;
11676f37f232SEric Joyner }
11686f37f232SEric Joyner
11696f37f232SEric Joyner /**
11708eb6488eSEric Joyner * ixgbe_read_iosf_sb_reg_x550 - Reads specified register of the IOSF device
11716f37f232SEric Joyner * @hw: pointer to hardware structure
11726f37f232SEric Joyner * @reg_addr: 32 bit PHY register to write
11736f37f232SEric Joyner * @device_type: 3 bit device type
11748eb6488eSEric Joyner * @data: Pointer to read data from the register
11756f37f232SEric Joyner **/
ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u32 * data)11766f37f232SEric Joyner s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
11776f37f232SEric Joyner u32 device_type, u32 *data)
11786f37f232SEric Joyner {
11796f37f232SEric Joyner u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
1180c1710eafSJohn Baldwin u32 command, error __unused;
11816f37f232SEric Joyner s32 ret;
11826f37f232SEric Joyner
11836f37f232SEric Joyner ret = ixgbe_acquire_swfw_semaphore(hw, gssr);
11846f37f232SEric Joyner if (ret != IXGBE_SUCCESS)
11856f37f232SEric Joyner return ret;
11866f37f232SEric Joyner
11876f37f232SEric Joyner ret = ixgbe_iosf_wait(hw, NULL);
11886f37f232SEric Joyner if (ret != IXGBE_SUCCESS)
11896f37f232SEric Joyner goto out;
11906f37f232SEric Joyner
11916f37f232SEric Joyner command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
11926f37f232SEric Joyner (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
11936f37f232SEric Joyner
11946f37f232SEric Joyner /* Write IOSF control register */
11956f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
11966f37f232SEric Joyner
11976f37f232SEric Joyner ret = ixgbe_iosf_wait(hw, &command);
11986f37f232SEric Joyner
11996f37f232SEric Joyner if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
12006f37f232SEric Joyner error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
12016f37f232SEric Joyner IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
12026f37f232SEric Joyner ERROR_REPORT2(IXGBE_ERROR_POLLING,
12036f37f232SEric Joyner "Failed to read, error %x\n", error);
12046f37f232SEric Joyner ret = IXGBE_ERR_PHY;
12056f37f232SEric Joyner }
12066f37f232SEric Joyner
12076f37f232SEric Joyner if (ret == IXGBE_SUCCESS)
12086f37f232SEric Joyner *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
12096f37f232SEric Joyner
12106f37f232SEric Joyner out:
12116f37f232SEric Joyner ixgbe_release_swfw_semaphore(hw, gssr);
12126f37f232SEric Joyner return ret;
12136f37f232SEric Joyner }
12146f37f232SEric Joyner
12156f37f232SEric Joyner /**
12168eb6488eSEric Joyner * ixgbe_get_phy_token - Get the token for shared phy access
12178eb6488eSEric Joyner * @hw: Pointer to hardware structure
12188eb6488eSEric Joyner */
12198eb6488eSEric Joyner
ixgbe_get_phy_token(struct ixgbe_hw * hw)12208eb6488eSEric Joyner s32 ixgbe_get_phy_token(struct ixgbe_hw *hw)
12218eb6488eSEric Joyner {
12228eb6488eSEric Joyner struct ixgbe_hic_phy_token_req token_cmd;
12238eb6488eSEric Joyner s32 status;
12248eb6488eSEric Joyner
12258eb6488eSEric Joyner token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
12268eb6488eSEric Joyner token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
12278eb6488eSEric Joyner token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
12288eb6488eSEric Joyner token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
12298eb6488eSEric Joyner token_cmd.port_number = hw->bus.lan_id;
12308eb6488eSEric Joyner token_cmd.command_type = FW_PHY_TOKEN_REQ;
12318eb6488eSEric Joyner token_cmd.pad = 0;
12328eb6488eSEric Joyner status = ixgbe_host_interface_command(hw, (u32 *)&token_cmd,
12338eb6488eSEric Joyner sizeof(token_cmd),
12348eb6488eSEric Joyner IXGBE_HI_COMMAND_TIMEOUT,
123579b36ec9SKevin Bowling true);
12368eb6488eSEric Joyner if (status) {
12378eb6488eSEric Joyner DEBUGOUT1("Issuing host interface command failed with Status = %d\n",
12388eb6488eSEric Joyner status);
12398eb6488eSEric Joyner return status;
12408eb6488eSEric Joyner }
12418eb6488eSEric Joyner if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
12428eb6488eSEric Joyner return IXGBE_SUCCESS;
12438eb6488eSEric Joyner if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) {
12448eb6488eSEric Joyner DEBUGOUT1("Host interface command returned 0x%08x , returning IXGBE_ERR_FW_RESP_INVALID\n",
12458eb6488eSEric Joyner token_cmd.hdr.cmd_or_resp.ret_status);
12468eb6488eSEric Joyner return IXGBE_ERR_FW_RESP_INVALID;
12478eb6488eSEric Joyner }
12488eb6488eSEric Joyner
12498eb6488eSEric Joyner DEBUGOUT("Returning IXGBE_ERR_TOKEN_RETRY\n");
12508eb6488eSEric Joyner return IXGBE_ERR_TOKEN_RETRY;
12518eb6488eSEric Joyner }
12528eb6488eSEric Joyner
12538eb6488eSEric Joyner /**
12548eb6488eSEric Joyner * ixgbe_put_phy_token - Put the token for shared phy access
12558eb6488eSEric Joyner * @hw: Pointer to hardware structure
12568eb6488eSEric Joyner */
12578eb6488eSEric Joyner
ixgbe_put_phy_token(struct ixgbe_hw * hw)12588eb6488eSEric Joyner s32 ixgbe_put_phy_token(struct ixgbe_hw *hw)
12598eb6488eSEric Joyner {
12608eb6488eSEric Joyner struct ixgbe_hic_phy_token_req token_cmd;
12618eb6488eSEric Joyner s32 status;
12628eb6488eSEric Joyner
12638eb6488eSEric Joyner token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
12648eb6488eSEric Joyner token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
12658eb6488eSEric Joyner token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
12668eb6488eSEric Joyner token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
12678eb6488eSEric Joyner token_cmd.port_number = hw->bus.lan_id;
12688eb6488eSEric Joyner token_cmd.command_type = FW_PHY_TOKEN_REL;
12698eb6488eSEric Joyner token_cmd.pad = 0;
12708eb6488eSEric Joyner status = ixgbe_host_interface_command(hw, (u32 *)&token_cmd,
12718eb6488eSEric Joyner sizeof(token_cmd),
12728eb6488eSEric Joyner IXGBE_HI_COMMAND_TIMEOUT,
127379b36ec9SKevin Bowling true);
12748eb6488eSEric Joyner if (status)
12758eb6488eSEric Joyner return status;
12768eb6488eSEric Joyner if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
12778eb6488eSEric Joyner return IXGBE_SUCCESS;
12788eb6488eSEric Joyner
12798eb6488eSEric Joyner DEBUGOUT("Put PHY Token host interface command failed");
12808eb6488eSEric Joyner return IXGBE_ERR_FW_RESP_INVALID;
12818eb6488eSEric Joyner }
12828eb6488eSEric Joyner
12838eb6488eSEric Joyner /**
12846f37f232SEric Joyner * ixgbe_disable_mdd_X550
12856f37f232SEric Joyner * @hw: pointer to hardware structure
12866f37f232SEric Joyner *
12876f37f232SEric Joyner * Disable malicious driver detection
12886f37f232SEric Joyner **/
ixgbe_disable_mdd_X550(struct ixgbe_hw * hw)12896f37f232SEric Joyner void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw)
12906f37f232SEric Joyner {
12916f37f232SEric Joyner u32 reg;
12926f37f232SEric Joyner
12936f37f232SEric Joyner DEBUGFUNC("ixgbe_disable_mdd_X550");
12946f37f232SEric Joyner
12956f37f232SEric Joyner /* Disable MDD for TX DMA and interrupt */
12966f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
12976f37f232SEric Joyner reg &= ~(IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN);
12986f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg);
12996f37f232SEric Joyner
13006f37f232SEric Joyner /* Disable MDD for RX and interrupt */
13016f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
13026f37f232SEric Joyner reg &= ~(IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN);
13036f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg);
13046f37f232SEric Joyner }
13056f37f232SEric Joyner
13066f37f232SEric Joyner /**
13076f37f232SEric Joyner * ixgbe_enable_mdd_X550
13086f37f232SEric Joyner * @hw: pointer to hardware structure
13096f37f232SEric Joyner *
13106f37f232SEric Joyner * Enable malicious driver detection
13116f37f232SEric Joyner **/
ixgbe_enable_mdd_X550(struct ixgbe_hw * hw)13126f37f232SEric Joyner void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw)
13136f37f232SEric Joyner {
13146f37f232SEric Joyner u32 reg;
13156f37f232SEric Joyner
13166f37f232SEric Joyner DEBUGFUNC("ixgbe_enable_mdd_X550");
13176f37f232SEric Joyner
13186f37f232SEric Joyner /* Enable MDD for TX DMA and interrupt */
13196f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
13206f37f232SEric Joyner reg |= (IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN);
13216f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg);
13226f37f232SEric Joyner
13236f37f232SEric Joyner /* Enable MDD for RX and interrupt */
13246f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
13256f37f232SEric Joyner reg |= (IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN);
13266f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg);
13276f37f232SEric Joyner }
13286f37f232SEric Joyner
13296f37f232SEric Joyner /**
13306f37f232SEric Joyner * ixgbe_restore_mdd_vf_X550
13316f37f232SEric Joyner * @hw: pointer to hardware structure
13326f37f232SEric Joyner * @vf: vf index
13336f37f232SEric Joyner *
13346f37f232SEric Joyner * Restore VF that was disabled during malicious driver detection event
13356f37f232SEric Joyner **/
ixgbe_restore_mdd_vf_X550(struct ixgbe_hw * hw,u32 vf)13366f37f232SEric Joyner void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf)
13376f37f232SEric Joyner {
13386f37f232SEric Joyner u32 idx, reg, num_qs, start_q, bitmask;
13396f37f232SEric Joyner
13406f37f232SEric Joyner DEBUGFUNC("ixgbe_restore_mdd_vf_X550");
13416f37f232SEric Joyner
13426f37f232SEric Joyner /* Map VF to queues */
13436f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_MRQC);
13446f37f232SEric Joyner switch (reg & IXGBE_MRQC_MRQE_MASK) {
13456f37f232SEric Joyner case IXGBE_MRQC_VMDQRT8TCEN:
13466f37f232SEric Joyner num_qs = 8; /* 16 VFs / pools */
13476f37f232SEric Joyner bitmask = 0x000000FF;
13486f37f232SEric Joyner break;
13496f37f232SEric Joyner case IXGBE_MRQC_VMDQRSS32EN:
13506f37f232SEric Joyner case IXGBE_MRQC_VMDQRT4TCEN:
13516f37f232SEric Joyner num_qs = 4; /* 32 VFs / pools */
13526f37f232SEric Joyner bitmask = 0x0000000F;
13536f37f232SEric Joyner break;
13546f37f232SEric Joyner default: /* 64 VFs / pools */
13556f37f232SEric Joyner num_qs = 2;
13566f37f232SEric Joyner bitmask = 0x00000003;
13576f37f232SEric Joyner break;
13586f37f232SEric Joyner }
13596f37f232SEric Joyner start_q = vf * num_qs;
13606f37f232SEric Joyner
13616f37f232SEric Joyner /* Release vf's queues by clearing WQBR_TX and WQBR_RX (RW1C) */
13626f37f232SEric Joyner idx = start_q / 32;
13636f37f232SEric Joyner reg = 0;
13646f37f232SEric Joyner reg |= (bitmask << (start_q % 32));
13656f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WQBR_TX(idx), reg);
13666f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_WQBR_RX(idx), reg);
13676f37f232SEric Joyner }
13686f37f232SEric Joyner
13696f37f232SEric Joyner /**
13706f37f232SEric Joyner * ixgbe_mdd_event_X550
13716f37f232SEric Joyner * @hw: pointer to hardware structure
13726f37f232SEric Joyner * @vf_bitmap: vf bitmap of malicious vfs
13736f37f232SEric Joyner *
13746f37f232SEric Joyner * Handle malicious driver detection event.
13756f37f232SEric Joyner **/
ixgbe_mdd_event_X550(struct ixgbe_hw * hw,u32 * vf_bitmap)13766f37f232SEric Joyner void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap)
13776f37f232SEric Joyner {
13786f37f232SEric Joyner u32 wqbr;
13796f37f232SEric Joyner u32 i, j, reg, q, shift, vf, idx;
13806f37f232SEric Joyner
13816f37f232SEric Joyner DEBUGFUNC("ixgbe_mdd_event_X550");
13826f37f232SEric Joyner
13836f37f232SEric Joyner /* figure out pool size for mapping to vf's */
13846f37f232SEric Joyner reg = IXGBE_READ_REG(hw, IXGBE_MRQC);
13856f37f232SEric Joyner switch (reg & IXGBE_MRQC_MRQE_MASK) {
13866f37f232SEric Joyner case IXGBE_MRQC_VMDQRT8TCEN:
13876f37f232SEric Joyner shift = 3; /* 16 VFs / pools */
13886f37f232SEric Joyner break;
13896f37f232SEric Joyner case IXGBE_MRQC_VMDQRSS32EN:
13906f37f232SEric Joyner case IXGBE_MRQC_VMDQRT4TCEN:
13916f37f232SEric Joyner shift = 2; /* 32 VFs / pools */
13926f37f232SEric Joyner break;
13936f37f232SEric Joyner default:
13946f37f232SEric Joyner shift = 1; /* 64 VFs / pools */
13956f37f232SEric Joyner break;
13966f37f232SEric Joyner }
13976f37f232SEric Joyner
13986f37f232SEric Joyner /* Read WQBR_TX and WQBR_RX and check for malicious queues */
13996f37f232SEric Joyner for (i = 0; i < 4; i++) {
14006f37f232SEric Joyner wqbr = IXGBE_READ_REG(hw, IXGBE_WQBR_TX(i));
14016f37f232SEric Joyner wqbr |= IXGBE_READ_REG(hw, IXGBE_WQBR_RX(i));
14026f37f232SEric Joyner
14036f37f232SEric Joyner if (!wqbr)
14046f37f232SEric Joyner continue;
14056f37f232SEric Joyner
14066f37f232SEric Joyner /* Get malicious queue */
14076f37f232SEric Joyner for (j = 0; j < 32 && wqbr; j++) {
14086f37f232SEric Joyner
14096f37f232SEric Joyner if (!(wqbr & (1 << j)))
14106f37f232SEric Joyner continue;
14116f37f232SEric Joyner
14126f37f232SEric Joyner /* Get queue from bitmask */
14136f37f232SEric Joyner q = j + (i * 32);
14146f37f232SEric Joyner
14156f37f232SEric Joyner /* Map queue to vf */
14166f37f232SEric Joyner vf = (q >> shift);
14176f37f232SEric Joyner
14186f37f232SEric Joyner /* Set vf bit in vf_bitmap */
14196f37f232SEric Joyner idx = vf / 32;
14206f37f232SEric Joyner vf_bitmap[idx] |= (1 << (vf % 32));
14216f37f232SEric Joyner wqbr &= ~(1 << j);
14226f37f232SEric Joyner }
14236f37f232SEric Joyner }
14246f37f232SEric Joyner }
14256f37f232SEric Joyner
14266f37f232SEric Joyner /**
14276f37f232SEric Joyner * ixgbe_get_media_type_X550em - Get media type
14286f37f232SEric Joyner * @hw: pointer to hardware structure
14296f37f232SEric Joyner *
14306f37f232SEric Joyner * Returns the media type (fiber, copper, backplane)
14316f37f232SEric Joyner */
ixgbe_get_media_type_X550em(struct ixgbe_hw * hw)14326f37f232SEric Joyner enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
14336f37f232SEric Joyner {
14346f37f232SEric Joyner enum ixgbe_media_type media_type;
14356f37f232SEric Joyner
14366f37f232SEric Joyner DEBUGFUNC("ixgbe_get_media_type_X550em");
14376f37f232SEric Joyner
14386f37f232SEric Joyner /* Detect if there is a copper PHY attached. */
14396f37f232SEric Joyner switch (hw->device_id) {
14406f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_KR:
14416f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_KX4:
14428eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_X_XFI:
14438eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_KR:
14448eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_KR_L:
14456f37f232SEric Joyner media_type = ixgbe_media_type_backplane;
14466f37f232SEric Joyner break;
14476f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_SFP:
14488eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP:
14498eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP_N:
14508eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP:
14518eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP_N:
14526f37f232SEric Joyner media_type = ixgbe_media_type_fiber;
14536f37f232SEric Joyner break;
14546f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_1G_T:
14556f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_10G_T:
14568eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_10G_T:
14578eb6488eSEric Joyner media_type = ixgbe_media_type_copper;
14588eb6488eSEric Joyner break;
14598eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SGMII:
14608eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SGMII_L:
14618eb6488eSEric Joyner media_type = ixgbe_media_type_backplane;
14628eb6488eSEric Joyner hw->phy.type = ixgbe_phy_sgmii;
14638eb6488eSEric Joyner break;
14648eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T:
14658eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T_L:
14666f37f232SEric Joyner media_type = ixgbe_media_type_copper;
14676f37f232SEric Joyner break;
14686f37f232SEric Joyner default:
14696f37f232SEric Joyner media_type = ixgbe_media_type_unknown;
14706f37f232SEric Joyner break;
14716f37f232SEric Joyner }
14726f37f232SEric Joyner return media_type;
14736f37f232SEric Joyner }
14746f37f232SEric Joyner
14756f37f232SEric Joyner /**
14766f37f232SEric Joyner * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported
14776f37f232SEric Joyner * @hw: pointer to hardware structure
147879b36ec9SKevin Bowling * @linear: true if SFP module is linear
14796f37f232SEric Joyner */
ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw * hw,bool * linear)14806f37f232SEric Joyner static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear)
14816f37f232SEric Joyner {
14826f37f232SEric Joyner DEBUGFUNC("ixgbe_supported_sfp_modules_X550em");
14836f37f232SEric Joyner
14846f37f232SEric Joyner switch (hw->phy.sfp_type) {
14856f37f232SEric Joyner case ixgbe_sfp_type_not_present:
14866f37f232SEric Joyner return IXGBE_ERR_SFP_NOT_PRESENT;
14876f37f232SEric Joyner case ixgbe_sfp_type_da_cu_core0:
14886f37f232SEric Joyner case ixgbe_sfp_type_da_cu_core1:
148979b36ec9SKevin Bowling *linear = true;
14906f37f232SEric Joyner break;
14916f37f232SEric Joyner case ixgbe_sfp_type_srlr_core0:
14926f37f232SEric Joyner case ixgbe_sfp_type_srlr_core1:
14936f37f232SEric Joyner case ixgbe_sfp_type_da_act_lmt_core0:
14946f37f232SEric Joyner case ixgbe_sfp_type_da_act_lmt_core1:
14956f37f232SEric Joyner case ixgbe_sfp_type_1g_sx_core0:
14966f37f232SEric Joyner case ixgbe_sfp_type_1g_sx_core1:
14976f37f232SEric Joyner case ixgbe_sfp_type_1g_lx_core0:
14986f37f232SEric Joyner case ixgbe_sfp_type_1g_lx_core1:
1499*18362165SKevin Bowling case ixgbe_sfp_type_1g_bx_core0:
1500*18362165SKevin Bowling case ixgbe_sfp_type_1g_bx_core1:
150179b36ec9SKevin Bowling *linear = false;
15026f37f232SEric Joyner break;
15036f37f232SEric Joyner case ixgbe_sfp_type_unknown:
15046f37f232SEric Joyner case ixgbe_sfp_type_1g_cu_core0:
15056f37f232SEric Joyner case ixgbe_sfp_type_1g_cu_core1:
15066f37f232SEric Joyner default:
15076f37f232SEric Joyner return IXGBE_ERR_SFP_NOT_SUPPORTED;
15086f37f232SEric Joyner }
15096f37f232SEric Joyner
15106f37f232SEric Joyner return IXGBE_SUCCESS;
15116f37f232SEric Joyner }
15126f37f232SEric Joyner
15136f37f232SEric Joyner /**
15146f37f232SEric Joyner * ixgbe_identify_sfp_module_X550em - Identifies SFP modules
15156f37f232SEric Joyner * @hw: pointer to hardware structure
15166f37f232SEric Joyner *
15176f37f232SEric Joyner * Searches for and identifies the SFP module and assigns appropriate PHY type.
15186f37f232SEric Joyner **/
ixgbe_identify_sfp_module_X550em(struct ixgbe_hw * hw)15196f37f232SEric Joyner s32 ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw)
15206f37f232SEric Joyner {
15216f37f232SEric Joyner s32 status;
15226f37f232SEric Joyner bool linear;
15236f37f232SEric Joyner
15246f37f232SEric Joyner DEBUGFUNC("ixgbe_identify_sfp_module_X550em");
15256f37f232SEric Joyner
15266f37f232SEric Joyner status = ixgbe_identify_module_generic(hw);
15276f37f232SEric Joyner
15286f37f232SEric Joyner if (status != IXGBE_SUCCESS)
15296f37f232SEric Joyner return status;
15306f37f232SEric Joyner
15316f37f232SEric Joyner /* Check if SFP module is supported */
15326f37f232SEric Joyner status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
15336f37f232SEric Joyner
15346f37f232SEric Joyner return status;
15356f37f232SEric Joyner }
15366f37f232SEric Joyner
15376f37f232SEric Joyner /**
15386f37f232SEric Joyner * ixgbe_setup_sfp_modules_X550em - Setup MAC link ops
15396f37f232SEric Joyner * @hw: pointer to hardware structure
15406f37f232SEric Joyner */
ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw * hw)15416f37f232SEric Joyner s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
15426f37f232SEric Joyner {
15436f37f232SEric Joyner s32 status;
15446f37f232SEric Joyner bool linear;
15456f37f232SEric Joyner
15466f37f232SEric Joyner DEBUGFUNC("ixgbe_setup_sfp_modules_X550em");
15476f37f232SEric Joyner
15486f37f232SEric Joyner /* Check if SFP module is supported */
15496f37f232SEric Joyner status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
15506f37f232SEric Joyner
15516f37f232SEric Joyner if (status != IXGBE_SUCCESS)
15526f37f232SEric Joyner return status;
15536f37f232SEric Joyner
15546f37f232SEric Joyner ixgbe_init_mac_link_ops_X550em(hw);
15556f37f232SEric Joyner hw->phy.ops.reset = NULL;
15566f37f232SEric Joyner
15576f37f232SEric Joyner return IXGBE_SUCCESS;
15586f37f232SEric Joyner }
15596f37f232SEric Joyner
15606f37f232SEric Joyner /**
15618eb6488eSEric Joyner * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the
15628eb6488eSEric Joyner * internal PHY
15638eb6488eSEric Joyner * @hw: pointer to hardware structure
15648eb6488eSEric Joyner **/
ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw * hw)15658eb6488eSEric Joyner static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
15668eb6488eSEric Joyner {
15678eb6488eSEric Joyner s32 status;
15688eb6488eSEric Joyner u32 link_ctrl;
15698eb6488eSEric Joyner
15708eb6488eSEric Joyner /* Restart auto-negotiation. */
15718eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
15728eb6488eSEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
15738eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl);
15748eb6488eSEric Joyner
15758eb6488eSEric Joyner if (status) {
15768eb6488eSEric Joyner DEBUGOUT("Auto-negotiation did not complete\n");
15778eb6488eSEric Joyner return status;
15788eb6488eSEric Joyner }
15798eb6488eSEric Joyner
15808eb6488eSEric Joyner link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
15818eb6488eSEric Joyner status = hw->mac.ops.write_iosf_sb_reg(hw,
15828eb6488eSEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
15838eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl);
15848eb6488eSEric Joyner
15858eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550EM_a) {
15868eb6488eSEric Joyner u32 flx_mask_st20;
15878eb6488eSEric Joyner
15888eb6488eSEric Joyner /* Indicate to FW that AN restart has been asserted */
15898eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
15908eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
15918eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20);
15928eb6488eSEric Joyner
15938eb6488eSEric Joyner if (status) {
15948eb6488eSEric Joyner DEBUGOUT("Auto-negotiation did not complete\n");
15958eb6488eSEric Joyner return status;
15968eb6488eSEric Joyner }
15978eb6488eSEric Joyner
15988eb6488eSEric Joyner flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART;
15998eb6488eSEric Joyner status = hw->mac.ops.write_iosf_sb_reg(hw,
16008eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
16018eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20);
16028eb6488eSEric Joyner }
16038eb6488eSEric Joyner
16048eb6488eSEric Joyner return status;
16058eb6488eSEric Joyner }
16068eb6488eSEric Joyner
16078eb6488eSEric Joyner /**
16088eb6488eSEric Joyner * ixgbe_setup_sgmii - Set up link for sgmii
16098eb6488eSEric Joyner * @hw: pointer to hardware structure
16107d48aa4cSEric Joyner * @speed: new link speed
161179b36ec9SKevin Bowling * @autoneg_wait: true when waiting for completion is needed
16128eb6488eSEric Joyner */
ixgbe_setup_sgmii(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait)16138eb6488eSEric Joyner static s32 ixgbe_setup_sgmii(struct ixgbe_hw *hw, ixgbe_link_speed speed,
16148eb6488eSEric Joyner bool autoneg_wait)
16158eb6488eSEric Joyner {
16168eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac;
16178eb6488eSEric Joyner u32 lval, sval, flx_val;
16188eb6488eSEric Joyner s32 rc;
16198eb6488eSEric Joyner
16208eb6488eSEric Joyner rc = mac->ops.read_iosf_sb_reg(hw,
16218eb6488eSEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
16228eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
16238eb6488eSEric Joyner if (rc)
16248eb6488eSEric Joyner return rc;
16258eb6488eSEric Joyner
16268eb6488eSEric Joyner lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
16278eb6488eSEric Joyner lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
16288eb6488eSEric Joyner lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
16298eb6488eSEric Joyner lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
16308eb6488eSEric Joyner lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
16318eb6488eSEric Joyner rc = mac->ops.write_iosf_sb_reg(hw,
16328eb6488eSEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
16338eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
16348eb6488eSEric Joyner if (rc)
16358eb6488eSEric Joyner return rc;
16368eb6488eSEric Joyner
16378eb6488eSEric Joyner rc = mac->ops.read_iosf_sb_reg(hw,
16388eb6488eSEric Joyner IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
16398eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
16408eb6488eSEric Joyner if (rc)
16418eb6488eSEric Joyner return rc;
16428eb6488eSEric Joyner
16438eb6488eSEric Joyner sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
16448eb6488eSEric Joyner sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
16458eb6488eSEric Joyner rc = mac->ops.write_iosf_sb_reg(hw,
16468eb6488eSEric Joyner IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
16478eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
16488eb6488eSEric Joyner if (rc)
16498eb6488eSEric Joyner return rc;
16508eb6488eSEric Joyner
16518eb6488eSEric Joyner rc = mac->ops.read_iosf_sb_reg(hw,
16528eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
16538eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
16548eb6488eSEric Joyner if (rc)
16558eb6488eSEric Joyner return rc;
16568eb6488eSEric Joyner
16578eb6488eSEric Joyner flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
16588eb6488eSEric Joyner flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
16598eb6488eSEric Joyner flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
16608eb6488eSEric Joyner flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
16618eb6488eSEric Joyner flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
16628eb6488eSEric Joyner
16638eb6488eSEric Joyner rc = mac->ops.write_iosf_sb_reg(hw,
16648eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
16658eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
16668eb6488eSEric Joyner if (rc)
16678eb6488eSEric Joyner return rc;
16688eb6488eSEric Joyner
16698eb6488eSEric Joyner rc = ixgbe_restart_an_internal_phy_x550em(hw);
16708eb6488eSEric Joyner if (rc)
16718eb6488eSEric Joyner return rc;
16728eb6488eSEric Joyner
16738eb6488eSEric Joyner return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
16748eb6488eSEric Joyner }
16758eb6488eSEric Joyner
16768eb6488eSEric Joyner /**
16777d48aa4cSEric Joyner * ixgbe_setup_sgmii_fw - Set up link for internal PHY SGMII auto-negotiation
16788eb6488eSEric Joyner * @hw: pointer to hardware structure
16797d48aa4cSEric Joyner * @speed: new link speed
168079b36ec9SKevin Bowling * @autoneg_wait: true when waiting for completion is needed
16818eb6488eSEric Joyner */
ixgbe_setup_sgmii_fw(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait)16828eb6488eSEric Joyner static s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed,
16838eb6488eSEric Joyner bool autoneg_wait)
16848eb6488eSEric Joyner {
16858eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac;
16868eb6488eSEric Joyner u32 lval, sval, flx_val;
16878eb6488eSEric Joyner s32 rc;
16888eb6488eSEric Joyner
16898eb6488eSEric Joyner rc = mac->ops.read_iosf_sb_reg(hw,
16908eb6488eSEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
16918eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
16928eb6488eSEric Joyner if (rc)
16938eb6488eSEric Joyner return rc;
16948eb6488eSEric Joyner
16958eb6488eSEric Joyner lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
16968eb6488eSEric Joyner lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
16978eb6488eSEric Joyner lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
16988eb6488eSEric Joyner lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
16998eb6488eSEric Joyner lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
17008eb6488eSEric Joyner rc = mac->ops.write_iosf_sb_reg(hw,
17018eb6488eSEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
17028eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
17038eb6488eSEric Joyner if (rc)
17048eb6488eSEric Joyner return rc;
17058eb6488eSEric Joyner
17068eb6488eSEric Joyner rc = mac->ops.read_iosf_sb_reg(hw,
17078eb6488eSEric Joyner IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
17088eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
17098eb6488eSEric Joyner if (rc)
17108eb6488eSEric Joyner return rc;
17118eb6488eSEric Joyner
17128eb6488eSEric Joyner sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
17138eb6488eSEric Joyner sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
17148eb6488eSEric Joyner rc = mac->ops.write_iosf_sb_reg(hw,
17158eb6488eSEric Joyner IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
17168eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
17178eb6488eSEric Joyner if (rc)
17188eb6488eSEric Joyner return rc;
17198eb6488eSEric Joyner
17208eb6488eSEric Joyner rc = mac->ops.write_iosf_sb_reg(hw,
17218eb6488eSEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
17228eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
17238eb6488eSEric Joyner if (rc)
17248eb6488eSEric Joyner return rc;
17258eb6488eSEric Joyner
17268eb6488eSEric Joyner rc = mac->ops.read_iosf_sb_reg(hw,
17278eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
17288eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
17298eb6488eSEric Joyner if (rc)
17308eb6488eSEric Joyner return rc;
17318eb6488eSEric Joyner
17328eb6488eSEric Joyner flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
17338eb6488eSEric Joyner flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
17348eb6488eSEric Joyner flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
17358eb6488eSEric Joyner flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
17368eb6488eSEric Joyner flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
17378eb6488eSEric Joyner
17388eb6488eSEric Joyner rc = mac->ops.write_iosf_sb_reg(hw,
17398eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
17408eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
17418eb6488eSEric Joyner if (rc)
17428eb6488eSEric Joyner return rc;
17438eb6488eSEric Joyner
17448eb6488eSEric Joyner rc = ixgbe_restart_an_internal_phy_x550em(hw);
17458eb6488eSEric Joyner
17468eb6488eSEric Joyner return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
17478eb6488eSEric Joyner }
17488eb6488eSEric Joyner
17498eb6488eSEric Joyner /**
17506f37f232SEric Joyner * ixgbe_init_mac_link_ops_X550em - init mac link function pointers
17516f37f232SEric Joyner * @hw: pointer to hardware structure
17526f37f232SEric Joyner */
ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw * hw)17536f37f232SEric Joyner void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
17546f37f232SEric Joyner {
17556f37f232SEric Joyner struct ixgbe_mac_info *mac = &hw->mac;
17566f37f232SEric Joyner
17576f37f232SEric Joyner DEBUGFUNC("ixgbe_init_mac_link_ops_X550em");
17586f37f232SEric Joyner
17596f37f232SEric Joyner switch (hw->mac.ops.get_media_type(hw)) {
17606f37f232SEric Joyner case ixgbe_media_type_fiber:
17616f37f232SEric Joyner /* CS4227 does not support autoneg, so disable the laser control
17626f37f232SEric Joyner * functions for SFP+ fiber
17636f37f232SEric Joyner */
17646f37f232SEric Joyner mac->ops.disable_tx_laser = NULL;
17656f37f232SEric Joyner mac->ops.enable_tx_laser = NULL;
17666f37f232SEric Joyner mac->ops.flap_tx_laser = NULL;
17676f37f232SEric Joyner mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
17686f37f232SEric Joyner mac->ops.set_rate_select_speed =
17696f37f232SEric Joyner ixgbe_set_soft_rate_select_speed;
17708eb6488eSEric Joyner
17718eb6488eSEric Joyner if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) ||
17728eb6488eSEric Joyner (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP))
17738eb6488eSEric Joyner mac->ops.setup_mac_link =
17748eb6488eSEric Joyner ixgbe_setup_mac_link_sfp_x550a;
17758eb6488eSEric Joyner else
17768eb6488eSEric Joyner mac->ops.setup_mac_link =
17778eb6488eSEric Joyner ixgbe_setup_mac_link_sfp_x550em;
17786f37f232SEric Joyner break;
17796f37f232SEric Joyner case ixgbe_media_type_copper:
17808eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T)
17818eb6488eSEric Joyner break;
17828eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550EM_a) {
17838eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
17848eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) {
17858eb6488eSEric Joyner mac->ops.setup_link = ixgbe_setup_sgmii_fw;
17868eb6488eSEric Joyner mac->ops.check_link =
17878eb6488eSEric Joyner ixgbe_check_mac_link_generic;
17888eb6488eSEric Joyner } else {
17898eb6488eSEric Joyner mac->ops.setup_link =
17908eb6488eSEric Joyner ixgbe_setup_mac_link_t_X550em;
17918eb6488eSEric Joyner }
17928eb6488eSEric Joyner } else {
17936f37f232SEric Joyner mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
17946f37f232SEric Joyner mac->ops.check_link = ixgbe_check_link_t_X550em;
17958eb6488eSEric Joyner }
17968eb6488eSEric Joyner break;
17978eb6488eSEric Joyner case ixgbe_media_type_backplane:
17988eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
17998eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)
18008eb6488eSEric Joyner mac->ops.setup_link = ixgbe_setup_sgmii;
18016f37f232SEric Joyner break;
18026f37f232SEric Joyner default:
18036f37f232SEric Joyner break;
18046f37f232SEric Joyner }
18056f37f232SEric Joyner }
18066f37f232SEric Joyner
18076f37f232SEric Joyner /**
1808edef2769SRadoslaw Tyl * ixgbe_get_link_capabilities_X550em - Determines link capabilities
18096f37f232SEric Joyner * @hw: pointer to hardware structure
18106f37f232SEric Joyner * @speed: pointer to link speed
181179b36ec9SKevin Bowling * @autoneg: true when autoneg or autotry is enabled
18126f37f232SEric Joyner */
ixgbe_get_link_capabilities_X550em(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * autoneg)18136f37f232SEric Joyner s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
18146f37f232SEric Joyner ixgbe_link_speed *speed,
18156f37f232SEric Joyner bool *autoneg)
18166f37f232SEric Joyner {
18176f37f232SEric Joyner DEBUGFUNC("ixgbe_get_link_capabilities_X550em");
18186f37f232SEric Joyner
18198eb6488eSEric Joyner
18208eb6488eSEric Joyner if (hw->phy.type == ixgbe_phy_fw) {
182179b36ec9SKevin Bowling *autoneg = true;
18228eb6488eSEric Joyner *speed = hw->phy.speeds_supported;
18238eb6488eSEric Joyner return 0;
18248eb6488eSEric Joyner }
18258eb6488eSEric Joyner
18266f37f232SEric Joyner /* SFP */
18276f37f232SEric Joyner if (hw->phy.media_type == ixgbe_media_type_fiber) {
18286f37f232SEric Joyner
18296f37f232SEric Joyner /* CS4227 SFP must not enable auto-negotiation */
183079b36ec9SKevin Bowling *autoneg = false;
18316f37f232SEric Joyner
18326f37f232SEric Joyner /* Check if 1G SFP module. */
18336f37f232SEric Joyner if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
1834*18362165SKevin Bowling hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
1835*18362165SKevin Bowling hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
1836*18362165SKevin Bowling hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
1837*18362165SKevin Bowling hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core0 ||
1838*18362165SKevin Bowling hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core1) {
18396f37f232SEric Joyner *speed = IXGBE_LINK_SPEED_1GB_FULL;
18406f37f232SEric Joyner return IXGBE_SUCCESS;
18416f37f232SEric Joyner }
18426f37f232SEric Joyner
18436f37f232SEric Joyner /* Link capabilities are based on SFP */
18446f37f232SEric Joyner if (hw->phy.multispeed_fiber)
18456f37f232SEric Joyner *speed = IXGBE_LINK_SPEED_10GB_FULL |
18466f37f232SEric Joyner IXGBE_LINK_SPEED_1GB_FULL;
18476f37f232SEric Joyner else
18486f37f232SEric Joyner *speed = IXGBE_LINK_SPEED_10GB_FULL;
18496f37f232SEric Joyner } else {
18508e9f1b23SGuinan Sun *autoneg = true;
18518e9f1b23SGuinan Sun
18528eb6488eSEric Joyner switch (hw->phy.type) {
18538e9f1b23SGuinan Sun case ixgbe_phy_x550em_xfi:
18548e9f1b23SGuinan Sun *speed = IXGBE_LINK_SPEED_1GB_FULL |
18558e9f1b23SGuinan Sun IXGBE_LINK_SPEED_10GB_FULL;
18568e9f1b23SGuinan Sun *autoneg = false;
18578e9f1b23SGuinan Sun break;
18588eb6488eSEric Joyner case ixgbe_phy_ext_1g_t:
18598eb6488eSEric Joyner case ixgbe_phy_sgmii:
18608eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_1GB_FULL;
18618eb6488eSEric Joyner break;
18628eb6488eSEric Joyner case ixgbe_phy_x550em_kr:
18638eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550EM_a) {
18648eb6488eSEric Joyner /* check different backplane modes */
18658eb6488eSEric Joyner if (hw->phy.nw_mng_if_sel &
18668eb6488eSEric Joyner IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
18678eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_2_5GB_FULL;
18688eb6488eSEric Joyner break;
18698eb6488eSEric Joyner } else if (hw->device_id ==
18708eb6488eSEric Joyner IXGBE_DEV_ID_X550EM_A_KR_L) {
18718eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_1GB_FULL;
18728eb6488eSEric Joyner break;
18738eb6488eSEric Joyner }
18748eb6488eSEric Joyner }
187550455f73SPiotr Skajewski *speed = IXGBE_LINK_SPEED_10GB_FULL |
187650455f73SPiotr Skajewski IXGBE_LINK_SPEED_1GB_FULL;
187750455f73SPiotr Skajewski break;
18788eb6488eSEric Joyner default:
18796f37f232SEric Joyner *speed = IXGBE_LINK_SPEED_10GB_FULL |
18806f37f232SEric Joyner IXGBE_LINK_SPEED_1GB_FULL;
18818eb6488eSEric Joyner break;
18828eb6488eSEric Joyner }
18836f37f232SEric Joyner }
18846f37f232SEric Joyner
18856f37f232SEric Joyner return IXGBE_SUCCESS;
18866f37f232SEric Joyner }
18876f37f232SEric Joyner
18886f37f232SEric Joyner /**
18896f37f232SEric Joyner * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause
18906f37f232SEric Joyner * @hw: pointer to hardware structure
18916f37f232SEric Joyner * @lsc: pointer to boolean flag which indicates whether external Base T
18926f37f232SEric Joyner * PHY interrupt is lsc
18936f37f232SEric Joyner *
18946f37f232SEric Joyner * Determime if external Base T PHY interrupt cause is high temperature
18956f37f232SEric Joyner * failure alarm or link status change.
18966f37f232SEric Joyner *
18976f37f232SEric Joyner * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
18986f37f232SEric Joyner * failure alarm, else return PHY access status.
18996f37f232SEric Joyner */
ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw * hw,bool * lsc)19006f37f232SEric Joyner static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
19016f37f232SEric Joyner {
19026f37f232SEric Joyner u32 status;
19036f37f232SEric Joyner u16 reg;
19046f37f232SEric Joyner
190579b36ec9SKevin Bowling *lsc = false;
19066f37f232SEric Joyner
19076f37f232SEric Joyner /* Vendor alarm triggered */
19086f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
19096f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
19106f37f232SEric Joyner ®);
19116f37f232SEric Joyner
19126f37f232SEric Joyner if (status != IXGBE_SUCCESS ||
19136f37f232SEric Joyner !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
19146f37f232SEric Joyner return status;
19156f37f232SEric Joyner
19166f37f232SEric Joyner /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
19176f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
19186f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
19196f37f232SEric Joyner ®);
19206f37f232SEric Joyner
19216f37f232SEric Joyner if (status != IXGBE_SUCCESS ||
19226f37f232SEric Joyner !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
19236f37f232SEric Joyner IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
19246f37f232SEric Joyner return status;
19256f37f232SEric Joyner
19261ebf555bSSteven Hartland /* Global alarm triggered */
19276f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
19286f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
19296f37f232SEric Joyner ®);
19306f37f232SEric Joyner
19316f37f232SEric Joyner if (status != IXGBE_SUCCESS)
19326f37f232SEric Joyner return status;
19336f37f232SEric Joyner
19346f37f232SEric Joyner /* If high temperature failure, then return over temp error and exit */
19356f37f232SEric Joyner if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
19366f37f232SEric Joyner /* power down the PHY in case the PHY FW didn't already */
193779b36ec9SKevin Bowling ixgbe_set_copper_phy_power(hw, false);
19386f37f232SEric Joyner return IXGBE_ERR_OVERTEMP;
19391ebf555bSSteven Hartland } else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
19401ebf555bSSteven Hartland /* device fault alarm triggered */
19411ebf555bSSteven Hartland status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
19421ebf555bSSteven Hartland IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
19431ebf555bSSteven Hartland ®);
19441ebf555bSSteven Hartland
19451ebf555bSSteven Hartland if (status != IXGBE_SUCCESS)
19461ebf555bSSteven Hartland return status;
19471ebf555bSSteven Hartland
19481ebf555bSSteven Hartland /* if device fault was due to high temp alarm handle and exit */
19491ebf555bSSteven Hartland if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
19501ebf555bSSteven Hartland /* power down the PHY in case the PHY FW didn't */
195179b36ec9SKevin Bowling ixgbe_set_copper_phy_power(hw, false);
19521ebf555bSSteven Hartland return IXGBE_ERR_OVERTEMP;
19531ebf555bSSteven Hartland }
19546f37f232SEric Joyner }
19556f37f232SEric Joyner
19566f37f232SEric Joyner /* Vendor alarm 2 triggered */
19576f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
19586f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®);
19596f37f232SEric Joyner
19606f37f232SEric Joyner if (status != IXGBE_SUCCESS ||
19616f37f232SEric Joyner !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
19626f37f232SEric Joyner return status;
19636f37f232SEric Joyner
19646f37f232SEric Joyner /* link connect/disconnect event occurred */
19656f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
19666f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®);
19676f37f232SEric Joyner
19686f37f232SEric Joyner if (status != IXGBE_SUCCESS)
19696f37f232SEric Joyner return status;
19706f37f232SEric Joyner
19716f37f232SEric Joyner /* Indicate LSC */
19726f37f232SEric Joyner if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC)
197379b36ec9SKevin Bowling *lsc = true;
19746f37f232SEric Joyner
19756f37f232SEric Joyner return IXGBE_SUCCESS;
19766f37f232SEric Joyner }
19776f37f232SEric Joyner
19786f37f232SEric Joyner /**
19796f37f232SEric Joyner * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts
19806f37f232SEric Joyner * @hw: pointer to hardware structure
19816f37f232SEric Joyner *
19826f37f232SEric Joyner * Enable link status change and temperature failure alarm for the external
19836f37f232SEric Joyner * Base T PHY
19846f37f232SEric Joyner *
19856f37f232SEric Joyner * Returns PHY access status
19866f37f232SEric Joyner */
ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw * hw)19876f37f232SEric Joyner static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
19886f37f232SEric Joyner {
19896f37f232SEric Joyner u32 status;
19906f37f232SEric Joyner u16 reg;
19916f37f232SEric Joyner bool lsc;
19926f37f232SEric Joyner
19936f37f232SEric Joyner /* Clear interrupt flags */
19946f37f232SEric Joyner status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
19956f37f232SEric Joyner
19966f37f232SEric Joyner /* Enable link status change alarm */
19978eb6488eSEric Joyner
19988eb6488eSEric Joyner /* Enable the LASI interrupts on X552 devices to receive notifications
19998eb6488eSEric Joyner * of the link configurations of the external PHY and correspondingly
20008eb6488eSEric Joyner * support the configuration of the internal iXFI link, since iXFI does
20018eb6488eSEric Joyner * not support auto-negotiation. This is not required for X553 devices
20028eb6488eSEric Joyner * having KR support, which performs auto-negotiations and which is used
20038eb6488eSEric Joyner * as the internal link to the external PHY. Hence adding a check here
20048eb6488eSEric Joyner * to avoid enabling LASI interrupts for X553 devices.
20058eb6488eSEric Joyner */
20068eb6488eSEric Joyner if (hw->mac.type != ixgbe_mac_X550EM_a) {
20078eb6488eSEric Joyner status = hw->phy.ops.read_reg(hw,
20088eb6488eSEric Joyner IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
20096f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®);
20106f37f232SEric Joyner
20116f37f232SEric Joyner if (status != IXGBE_SUCCESS)
20126f37f232SEric Joyner return status;
20136f37f232SEric Joyner
20146f37f232SEric Joyner reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
20156f37f232SEric Joyner
20168eb6488eSEric Joyner status = hw->phy.ops.write_reg(hw,
20178eb6488eSEric Joyner IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
20186f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg);
20196f37f232SEric Joyner
20206f37f232SEric Joyner if (status != IXGBE_SUCCESS)
20216f37f232SEric Joyner return status;
20228eb6488eSEric Joyner }
20236f37f232SEric Joyner
20248eb6488eSEric Joyner /* Enable high temperature failure and global fault alarms */
20256f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
20266f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20276f37f232SEric Joyner ®);
20286f37f232SEric Joyner
20296f37f232SEric Joyner if (status != IXGBE_SUCCESS)
20306f37f232SEric Joyner return status;
20316f37f232SEric Joyner
20328eb6488eSEric Joyner reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN |
20338eb6488eSEric Joyner IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);
20346f37f232SEric Joyner
20356f37f232SEric Joyner status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
20366f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20376f37f232SEric Joyner reg);
20386f37f232SEric Joyner
20396f37f232SEric Joyner if (status != IXGBE_SUCCESS)
20406f37f232SEric Joyner return status;
20416f37f232SEric Joyner
20426f37f232SEric Joyner /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
20436f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
20446f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20456f37f232SEric Joyner ®);
20466f37f232SEric Joyner
20476f37f232SEric Joyner if (status != IXGBE_SUCCESS)
20486f37f232SEric Joyner return status;
20496f37f232SEric Joyner
20506f37f232SEric Joyner reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
20516f37f232SEric Joyner IXGBE_MDIO_GLOBAL_ALARM_1_INT);
20526f37f232SEric Joyner
20536f37f232SEric Joyner status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
20546f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20556f37f232SEric Joyner reg);
20566f37f232SEric Joyner
20576f37f232SEric Joyner if (status != IXGBE_SUCCESS)
20586f37f232SEric Joyner return status;
20596f37f232SEric Joyner
20606f37f232SEric Joyner /* Enable chip-wide vendor alarm */
20616f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
20626f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20636f37f232SEric Joyner ®);
20646f37f232SEric Joyner
20656f37f232SEric Joyner if (status != IXGBE_SUCCESS)
20666f37f232SEric Joyner return status;
20676f37f232SEric Joyner
20686f37f232SEric Joyner reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
20696f37f232SEric Joyner
20706f37f232SEric Joyner status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
20716f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
20726f37f232SEric Joyner reg);
20736f37f232SEric Joyner
20746f37f232SEric Joyner return status;
20756f37f232SEric Joyner }
20766f37f232SEric Joyner
20776f37f232SEric Joyner /**
20786f37f232SEric Joyner * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed.
20796f37f232SEric Joyner * @hw: pointer to hardware structure
20806f37f232SEric Joyner * @speed: link speed
20816f37f232SEric Joyner *
20826f37f232SEric Joyner * Configures the integrated KR PHY.
20836f37f232SEric Joyner **/
ixgbe_setup_kr_speed_x550em(struct ixgbe_hw * hw,ixgbe_link_speed speed)20846f37f232SEric Joyner static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
20856f37f232SEric Joyner ixgbe_link_speed speed)
20866f37f232SEric Joyner {
20876f37f232SEric Joyner s32 status;
20886f37f232SEric Joyner u32 reg_val;
20896f37f232SEric Joyner
20908eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
20916f37f232SEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
20926f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
20936f37f232SEric Joyner if (status)
20946f37f232SEric Joyner return status;
20956f37f232SEric Joyner
20966f37f232SEric Joyner reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
20976f37f232SEric Joyner reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
20986f37f232SEric Joyner IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
20996f37f232SEric Joyner
21006f37f232SEric Joyner /* Advertise 10G support. */
21016f37f232SEric Joyner if (speed & IXGBE_LINK_SPEED_10GB_FULL)
21026f37f232SEric Joyner reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR;
21036f37f232SEric Joyner
21046f37f232SEric Joyner /* Advertise 1G support. */
21056f37f232SEric Joyner if (speed & IXGBE_LINK_SPEED_1GB_FULL)
21066f37f232SEric Joyner reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
21076f37f232SEric Joyner
21088eb6488eSEric Joyner status = hw->mac.ops.write_iosf_sb_reg(hw,
21096f37f232SEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
21106f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
21116f37f232SEric Joyner
21128eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550EM_a) {
21138eb6488eSEric Joyner /* Set lane mode to KR auto negotiation */
21148eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
21158eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
21168eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
21178eb6488eSEric Joyner
21188eb6488eSEric Joyner if (status)
21196f37f232SEric Joyner return status;
21208eb6488eSEric Joyner
21218eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
21228eb6488eSEric Joyner reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
21238eb6488eSEric Joyner reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
21248eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
21258eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
21268eb6488eSEric Joyner
21278eb6488eSEric Joyner status = hw->mac.ops.write_iosf_sb_reg(hw,
21288eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
21298eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
21308eb6488eSEric Joyner }
21318eb6488eSEric Joyner
21328eb6488eSEric Joyner return ixgbe_restart_an_internal_phy_x550em(hw);
21338eb6488eSEric Joyner }
21348eb6488eSEric Joyner
21358eb6488eSEric Joyner /**
21368eb6488eSEric Joyner * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs
21378eb6488eSEric Joyner * @hw: pointer to hardware structure
21388eb6488eSEric Joyner */
ixgbe_reset_phy_fw(struct ixgbe_hw * hw)21398eb6488eSEric Joyner static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw)
21408eb6488eSEric Joyner {
21418eb6488eSEric Joyner u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
21428eb6488eSEric Joyner s32 rc;
21438eb6488eSEric Joyner
21448eb6488eSEric Joyner if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
21458eb6488eSEric Joyner return IXGBE_SUCCESS;
21468eb6488eSEric Joyner
21478eb6488eSEric Joyner rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store);
21488eb6488eSEric Joyner if (rc)
21498eb6488eSEric Joyner return rc;
21508eb6488eSEric Joyner memset(store, 0, sizeof(store));
21518eb6488eSEric Joyner
21528eb6488eSEric Joyner rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store);
21538eb6488eSEric Joyner if (rc)
21548eb6488eSEric Joyner return rc;
21558eb6488eSEric Joyner
21568eb6488eSEric Joyner return ixgbe_setup_fw_link(hw);
21578eb6488eSEric Joyner }
21588eb6488eSEric Joyner
21598eb6488eSEric Joyner /**
21608eb6488eSEric Joyner * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp
21618eb6488eSEric Joyner * @hw: pointer to hardware structure
21628eb6488eSEric Joyner */
ixgbe_check_overtemp_fw(struct ixgbe_hw * hw)21638eb6488eSEric Joyner static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
21648eb6488eSEric Joyner {
21658eb6488eSEric Joyner u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
21668eb6488eSEric Joyner s32 rc;
21678eb6488eSEric Joyner
21688eb6488eSEric Joyner rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);
21698eb6488eSEric Joyner if (rc)
21708eb6488eSEric Joyner return rc;
21718eb6488eSEric Joyner
21728eb6488eSEric Joyner if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {
21738eb6488eSEric Joyner ixgbe_shutdown_fw_phy(hw);
21748eb6488eSEric Joyner return IXGBE_ERR_OVERTEMP;
21758eb6488eSEric Joyner }
21768eb6488eSEric Joyner return IXGBE_SUCCESS;
21778eb6488eSEric Joyner }
21788eb6488eSEric Joyner
21798eb6488eSEric Joyner /**
21808eb6488eSEric Joyner * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register
21818eb6488eSEric Joyner * @hw: pointer to hardware structure
21828eb6488eSEric Joyner *
21838eb6488eSEric Joyner * Read NW_MNG_IF_SEL register and save field values, and check for valid field
21848eb6488eSEric Joyner * values.
21858eb6488eSEric Joyner **/
ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw * hw)21868eb6488eSEric Joyner static s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw)
21878eb6488eSEric Joyner {
21888eb6488eSEric Joyner /* Save NW management interface connected on board. This is used
21898eb6488eSEric Joyner * to determine internal PHY mode.
21908eb6488eSEric Joyner */
21918eb6488eSEric Joyner hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
21928eb6488eSEric Joyner
21938eb6488eSEric Joyner /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set
21948eb6488eSEric Joyner * PHY address. This register field was has only been used for X552.
21958eb6488eSEric Joyner */
21968eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550EM_a &&
21978eb6488eSEric Joyner hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) {
21988eb6488eSEric Joyner hw->phy.addr = (hw->phy.nw_mng_if_sel &
21998eb6488eSEric Joyner IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
22008eb6488eSEric Joyner IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
22018eb6488eSEric Joyner }
22028eb6488eSEric Joyner
22038eb6488eSEric Joyner return IXGBE_SUCCESS;
22046f37f232SEric Joyner }
22056f37f232SEric Joyner
22066f37f232SEric Joyner /**
22076f37f232SEric Joyner * ixgbe_init_phy_ops_X550em - PHY/SFP specific init
22086f37f232SEric Joyner * @hw: pointer to hardware structure
22096f37f232SEric Joyner *
22106f37f232SEric Joyner * Initialize any function pointers that were not able to be
22116f37f232SEric Joyner * set during init_shared_code because the PHY/SFP type was
22126f37f232SEric Joyner * not known. Perform the SFP init if necessary.
22136f37f232SEric Joyner */
ixgbe_init_phy_ops_X550em(struct ixgbe_hw * hw)22146f37f232SEric Joyner s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
22156f37f232SEric Joyner {
22166f37f232SEric Joyner struct ixgbe_phy_info *phy = &hw->phy;
22176f37f232SEric Joyner s32 ret_val;
22186f37f232SEric Joyner
22196f37f232SEric Joyner DEBUGFUNC("ixgbe_init_phy_ops_X550em");
22206f37f232SEric Joyner
22216f37f232SEric Joyner hw->mac.ops.set_lan_id(hw);
22228eb6488eSEric Joyner ixgbe_read_mng_if_sel_x550em(hw);
22236f37f232SEric Joyner
22246f37f232SEric Joyner if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) {
22256f37f232SEric Joyner phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
22266f37f232SEric Joyner ixgbe_setup_mux_ctl(hw);
22276f37f232SEric Joyner phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em;
22286f37f232SEric Joyner }
22296f37f232SEric Joyner
22308eb6488eSEric Joyner switch (hw->device_id) {
22318eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T:
22328eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T_L:
22337d48aa4cSEric Joyner phy->ops.read_reg_mdi = NULL;
22347d48aa4cSEric Joyner phy->ops.write_reg_mdi = NULL;
22357d48aa4cSEric Joyner hw->phy.ops.read_reg = NULL;
22367d48aa4cSEric Joyner hw->phy.ops.write_reg = NULL;
22378eb6488eSEric Joyner phy->ops.check_overtemp = ixgbe_check_overtemp_fw;
22388eb6488eSEric Joyner if (hw->bus.lan_id)
22398eb6488eSEric Joyner hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
22408eb6488eSEric Joyner else
22418eb6488eSEric Joyner hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
22428eb6488eSEric Joyner
22438eb6488eSEric Joyner break;
22448eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_10G_T:
22458eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP:
22468eb6488eSEric Joyner hw->phy.ops.read_reg = ixgbe_read_phy_reg_x550a;
22478eb6488eSEric Joyner hw->phy.ops.write_reg = ixgbe_write_phy_reg_x550a;
22488eb6488eSEric Joyner if (hw->bus.lan_id)
22498eb6488eSEric Joyner hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
22508eb6488eSEric Joyner else
22518eb6488eSEric Joyner hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
22528eb6488eSEric Joyner break;
22538eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_X_SFP:
22548eb6488eSEric Joyner /* set up for CS4227 usage */
22558eb6488eSEric Joyner hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
22568eb6488eSEric Joyner break;
22577d48aa4cSEric Joyner case IXGBE_DEV_ID_X550EM_X_1G_T:
22587d48aa4cSEric Joyner phy->ops.read_reg_mdi = NULL;
22597d48aa4cSEric Joyner phy->ops.write_reg_mdi = NULL;
22608eb6488eSEric Joyner default:
22618eb6488eSEric Joyner break;
22628eb6488eSEric Joyner }
22638eb6488eSEric Joyner
22646f37f232SEric Joyner /* Identify the PHY or SFP module */
22656f37f232SEric Joyner ret_val = phy->ops.identify(hw);
22668eb6488eSEric Joyner if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED ||
22678eb6488eSEric Joyner ret_val == IXGBE_ERR_PHY_ADDR_INVALID)
22686f37f232SEric Joyner return ret_val;
22696f37f232SEric Joyner
22706f37f232SEric Joyner /* Setup function pointers based on detected hardware */
22716f37f232SEric Joyner ixgbe_init_mac_link_ops_X550em(hw);
22726f37f232SEric Joyner if (phy->sfp_type != ixgbe_sfp_type_unknown)
22736f37f232SEric Joyner phy->ops.reset = NULL;
22746f37f232SEric Joyner
22756f37f232SEric Joyner /* Set functions pointers based on phy type */
22766f37f232SEric Joyner switch (hw->phy.type) {
22776f37f232SEric Joyner case ixgbe_phy_x550em_kx4:
2278a9ca1c79SSean Bruno phy->ops.setup_link = NULL;
22796f37f232SEric Joyner phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
22806f37f232SEric Joyner phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
22816f37f232SEric Joyner break;
22826f37f232SEric Joyner case ixgbe_phy_x550em_kr:
22836f37f232SEric Joyner phy->ops.setup_link = ixgbe_setup_kr_x550em;
22846f37f232SEric Joyner phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
22856f37f232SEric Joyner phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
22866f37f232SEric Joyner break;
22878eb6488eSEric Joyner case ixgbe_phy_ext_1g_t:
22888eb6488eSEric Joyner /* link is managed by FW */
22898eb6488eSEric Joyner phy->ops.setup_link = NULL;
22908eb6488eSEric Joyner phy->ops.reset = NULL;
22918eb6488eSEric Joyner break;
22928eb6488eSEric Joyner case ixgbe_phy_x550em_xfi:
22938eb6488eSEric Joyner /* link is managed by HW */
22948eb6488eSEric Joyner phy->ops.setup_link = NULL;
22958eb6488eSEric Joyner phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
22968eb6488eSEric Joyner phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
22978eb6488eSEric Joyner break;
22986f37f232SEric Joyner case ixgbe_phy_x550em_ext_t:
22996f37f232SEric Joyner /* If internal link mode is XFI, then setup iXFI internal link,
23006f37f232SEric Joyner * else setup KR now.
23016f37f232SEric Joyner */
23026f37f232SEric Joyner phy->ops.setup_internal_link =
23036f37f232SEric Joyner ixgbe_setup_internal_phy_t_x550em;
23046f37f232SEric Joyner
23058eb6488eSEric Joyner /* setup SW LPLU only for first revision of X550EM_x */
23068eb6488eSEric Joyner if ((hw->mac.type == ixgbe_mac_X550EM_x) &&
23078eb6488eSEric Joyner !(IXGBE_FUSES0_REV_MASK &
23088eb6488eSEric Joyner IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))))
23096f37f232SEric Joyner phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
2310a9ca1c79SSean Bruno
23116f37f232SEric Joyner phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
23126f37f232SEric Joyner phy->ops.reset = ixgbe_reset_phy_t_X550em;
23136f37f232SEric Joyner break;
23148eb6488eSEric Joyner case ixgbe_phy_sgmii:
23158eb6488eSEric Joyner phy->ops.setup_link = NULL;
23168eb6488eSEric Joyner break;
23178eb6488eSEric Joyner case ixgbe_phy_fw:
23188eb6488eSEric Joyner phy->ops.setup_link = ixgbe_setup_fw_link;
23198eb6488eSEric Joyner phy->ops.reset = ixgbe_reset_phy_fw;
23208eb6488eSEric Joyner break;
23216f37f232SEric Joyner default:
23226f37f232SEric Joyner break;
23236f37f232SEric Joyner }
23246f37f232SEric Joyner return ret_val;
23256f37f232SEric Joyner }
23266f37f232SEric Joyner
23276f37f232SEric Joyner /**
23288eb6488eSEric Joyner * ixgbe_set_mdio_speed - Set MDIO clock speed
23298eb6488eSEric Joyner * @hw: pointer to hardware structure
23308eb6488eSEric Joyner */
ixgbe_set_mdio_speed(struct ixgbe_hw * hw)23318eb6488eSEric Joyner static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw)
23328eb6488eSEric Joyner {
23338eb6488eSEric Joyner u32 hlreg0;
23348eb6488eSEric Joyner
23358eb6488eSEric Joyner switch (hw->device_id) {
23368eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_X_10G_T:
23378eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SGMII:
23388eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SGMII_L:
23398eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_10G_T:
23408eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP:
23418eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP:
23428eb6488eSEric Joyner /* Config MDIO clock speed before the first MDIO PHY access */
23438eb6488eSEric Joyner hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
23448eb6488eSEric Joyner hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
23458eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
23468eb6488eSEric Joyner break;
23478eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T:
23488eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T_L:
23498eb6488eSEric Joyner /* Select fast MDIO clock speed for these devices */
23508eb6488eSEric Joyner hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
23518eb6488eSEric Joyner hlreg0 |= IXGBE_HLREG0_MDCSPD;
23528eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
23538eb6488eSEric Joyner break;
23548eb6488eSEric Joyner default:
23558eb6488eSEric Joyner break;
23568eb6488eSEric Joyner }
23578eb6488eSEric Joyner }
23588eb6488eSEric Joyner
23598eb6488eSEric Joyner /**
23606f37f232SEric Joyner * ixgbe_reset_hw_X550em - Perform hardware reset
23616f37f232SEric Joyner * @hw: pointer to hardware structure
23626f37f232SEric Joyner *
23636f37f232SEric Joyner * Resets the hardware by resetting the transmit and receive units, masks
23646f37f232SEric Joyner * and clears all interrupts, perform a PHY reset, and perform a link (MAC)
23656f37f232SEric Joyner * reset.
23666f37f232SEric Joyner */
ixgbe_reset_hw_X550em(struct ixgbe_hw * hw)23676f37f232SEric Joyner s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
23686f37f232SEric Joyner {
23696f37f232SEric Joyner ixgbe_link_speed link_speed;
23706f37f232SEric Joyner s32 status;
23716f37f232SEric Joyner u32 ctrl = 0;
23726f37f232SEric Joyner u32 i;
237379b36ec9SKevin Bowling bool link_up = false;
23748eb6488eSEric Joyner u32 swfw_mask = hw->phy.phy_semaphore_mask;
23756f37f232SEric Joyner
23766f37f232SEric Joyner DEBUGFUNC("ixgbe_reset_hw_X550em");
23776f37f232SEric Joyner
23786f37f232SEric Joyner /* Call adapter stop to disable Tx/Rx and clear interrupts */
23796f37f232SEric Joyner status = hw->mac.ops.stop_adapter(hw);
23808eb6488eSEric Joyner if (status != IXGBE_SUCCESS) {
23818eb6488eSEric Joyner DEBUGOUT1("Failed to stop adapter, STATUS = %d\n", status);
23826f37f232SEric Joyner return status;
23838eb6488eSEric Joyner }
23846f37f232SEric Joyner /* flush pending Tx transactions */
23856f37f232SEric Joyner ixgbe_clear_tx_pending(hw);
23866f37f232SEric Joyner
23878eb6488eSEric Joyner ixgbe_set_mdio_speed(hw);
23886f37f232SEric Joyner
2389a9ca1c79SSean Bruno /* PHY ops must be identified and initialized prior to reset */
23906f37f232SEric Joyner status = hw->phy.ops.init(hw);
23916f37f232SEric Joyner
23928eb6488eSEric Joyner if (status)
23938eb6488eSEric Joyner DEBUGOUT1("Failed to initialize PHY ops, STATUS = %d\n",
23948eb6488eSEric Joyner status);
23958eb6488eSEric Joyner
23967d48aa4cSEric Joyner if (status == IXGBE_ERR_SFP_NOT_SUPPORTED ||
23977d48aa4cSEric Joyner status == IXGBE_ERR_PHY_ADDR_INVALID) {
23988eb6488eSEric Joyner DEBUGOUT("Returning from reset HW due to PHY init failure\n");
23996f37f232SEric Joyner return status;
24008eb6488eSEric Joyner }
24016f37f232SEric Joyner
24026f37f232SEric Joyner /* start the external PHY */
24036f37f232SEric Joyner if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
24046f37f232SEric Joyner status = ixgbe_init_ext_t_x550em(hw);
24058eb6488eSEric Joyner if (status) {
24068eb6488eSEric Joyner DEBUGOUT1("Failed to start the external PHY, STATUS = %d\n",
24078eb6488eSEric Joyner status);
24086f37f232SEric Joyner return status;
24096f37f232SEric Joyner }
24108eb6488eSEric Joyner }
24116f37f232SEric Joyner
24126f37f232SEric Joyner /* Setup SFP module if there is one present. */
24136f37f232SEric Joyner if (hw->phy.sfp_setup_needed) {
24146f37f232SEric Joyner status = hw->mac.ops.setup_sfp(hw);
241579b36ec9SKevin Bowling hw->phy.sfp_setup_needed = false;
24166f37f232SEric Joyner }
24176f37f232SEric Joyner
24186f37f232SEric Joyner if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
24196f37f232SEric Joyner return status;
24206f37f232SEric Joyner
24216f37f232SEric Joyner /* Reset PHY */
24228eb6488eSEric Joyner if (!hw->phy.reset_disable && hw->phy.ops.reset) {
24238eb6488eSEric Joyner if (hw->phy.ops.reset(hw) == IXGBE_ERR_OVERTEMP)
24248eb6488eSEric Joyner return IXGBE_ERR_OVERTEMP;
24258eb6488eSEric Joyner }
24266f37f232SEric Joyner
24276f37f232SEric Joyner mac_reset_top:
24286f37f232SEric Joyner /* Issue global reset to the MAC. Needs to be SW reset if link is up.
24296f37f232SEric Joyner * If link reset is used when link is up, it might reset the PHY when
24306f37f232SEric Joyner * mng is using it. If link is down or the flag to force full link
24316f37f232SEric Joyner * reset is set, then perform link reset.
24326f37f232SEric Joyner */
24336f37f232SEric Joyner ctrl = IXGBE_CTRL_LNK_RST;
24346f37f232SEric Joyner if (!hw->force_full_reset) {
243579b36ec9SKevin Bowling hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
24366f37f232SEric Joyner if (link_up)
24376f37f232SEric Joyner ctrl = IXGBE_CTRL_RST;
24386f37f232SEric Joyner }
24396f37f232SEric Joyner
24408eb6488eSEric Joyner status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
24418eb6488eSEric Joyner if (status != IXGBE_SUCCESS) {
24428eb6488eSEric Joyner ERROR_REPORT2(IXGBE_ERROR_CAUTION,
24438eb6488eSEric Joyner "semaphore failed with %d", status);
24448eb6488eSEric Joyner return IXGBE_ERR_SWFW_SYNC;
24458eb6488eSEric Joyner }
24466f37f232SEric Joyner ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
24476f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
24486f37f232SEric Joyner IXGBE_WRITE_FLUSH(hw);
24498eb6488eSEric Joyner hw->mac.ops.release_swfw_sync(hw, swfw_mask);
24506f37f232SEric Joyner
24516f37f232SEric Joyner /* Poll for reset bit to self-clear meaning reset is complete */
24526f37f232SEric Joyner for (i = 0; i < 10; i++) {
24536f37f232SEric Joyner usec_delay(1);
24546f37f232SEric Joyner ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
24556f37f232SEric Joyner if (!(ctrl & IXGBE_CTRL_RST_MASK))
24566f37f232SEric Joyner break;
24576f37f232SEric Joyner }
24586f37f232SEric Joyner
24596f37f232SEric Joyner if (ctrl & IXGBE_CTRL_RST_MASK) {
24606f37f232SEric Joyner status = IXGBE_ERR_RESET_FAILED;
24616f37f232SEric Joyner DEBUGOUT("Reset polling failed to complete.\n");
24626f37f232SEric Joyner }
24636f37f232SEric Joyner
24646f37f232SEric Joyner msec_delay(50);
24656f37f232SEric Joyner
24666f37f232SEric Joyner /* Double resets are required for recovery from certain error
24676f37f232SEric Joyner * conditions. Between resets, it is necessary to stall to
24686f37f232SEric Joyner * allow time for any pending HW events to complete.
24696f37f232SEric Joyner */
24706f37f232SEric Joyner if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
24716f37f232SEric Joyner hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
24726f37f232SEric Joyner goto mac_reset_top;
24736f37f232SEric Joyner }
24746f37f232SEric Joyner
24756f37f232SEric Joyner /* Store the permanent mac address */
24766f37f232SEric Joyner hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
24776f37f232SEric Joyner
24786f37f232SEric Joyner /* Store MAC address from RAR0, clear receive address registers, and
24796f37f232SEric Joyner * clear the multicast table. Also reset num_rar_entries to 128,
24806f37f232SEric Joyner * since we modify this value when programming the SAN MAC address.
24816f37f232SEric Joyner */
24826f37f232SEric Joyner hw->mac.num_rar_entries = 128;
24836f37f232SEric Joyner hw->mac.ops.init_rx_addrs(hw);
24846f37f232SEric Joyner
24858eb6488eSEric Joyner ixgbe_set_mdio_speed(hw);
24868eb6488eSEric Joyner
24876f37f232SEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
24886f37f232SEric Joyner ixgbe_setup_mux_ctl(hw);
24896f37f232SEric Joyner
24908eb6488eSEric Joyner if (status != IXGBE_SUCCESS)
24918eb6488eSEric Joyner DEBUGOUT1("Reset HW failed, STATUS = %d\n", status);
24928eb6488eSEric Joyner
24936f37f232SEric Joyner return status;
24946f37f232SEric Joyner }
24956f37f232SEric Joyner
24966f37f232SEric Joyner /**
24976f37f232SEric Joyner * ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY.
24986f37f232SEric Joyner * @hw: pointer to hardware structure
24996f37f232SEric Joyner */
ixgbe_init_ext_t_x550em(struct ixgbe_hw * hw)25006f37f232SEric Joyner s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
25016f37f232SEric Joyner {
25026f37f232SEric Joyner u32 status;
25036f37f232SEric Joyner u16 reg;
25046f37f232SEric Joyner
25056f37f232SEric Joyner status = hw->phy.ops.read_reg(hw,
25066f37f232SEric Joyner IXGBE_MDIO_TX_VENDOR_ALARMS_3,
25076f37f232SEric Joyner IXGBE_MDIO_PMA_PMD_DEV_TYPE,
25086f37f232SEric Joyner ®);
25096f37f232SEric Joyner
25106f37f232SEric Joyner if (status != IXGBE_SUCCESS)
25116f37f232SEric Joyner return status;
25126f37f232SEric Joyner
25136f37f232SEric Joyner /* If PHY FW reset completed bit is set then this is the first
25146f37f232SEric Joyner * SW instance after a power on so the PHY FW must be un-stalled.
25156f37f232SEric Joyner */
25166f37f232SEric Joyner if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
25176f37f232SEric Joyner status = hw->phy.ops.read_reg(hw,
25186f37f232SEric Joyner IXGBE_MDIO_GLOBAL_RES_PR_10,
25196f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
25206f37f232SEric Joyner ®);
25216f37f232SEric Joyner
25226f37f232SEric Joyner if (status != IXGBE_SUCCESS)
25236f37f232SEric Joyner return status;
25246f37f232SEric Joyner
25256f37f232SEric Joyner reg &= ~IXGBE_MDIO_POWER_UP_STALL;
25266f37f232SEric Joyner
25276f37f232SEric Joyner status = hw->phy.ops.write_reg(hw,
25286f37f232SEric Joyner IXGBE_MDIO_GLOBAL_RES_PR_10,
25296f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
25306f37f232SEric Joyner reg);
25316f37f232SEric Joyner
25326f37f232SEric Joyner if (status != IXGBE_SUCCESS)
25336f37f232SEric Joyner return status;
25346f37f232SEric Joyner }
25356f37f232SEric Joyner
25366f37f232SEric Joyner return status;
25376f37f232SEric Joyner }
25386f37f232SEric Joyner
25396f37f232SEric Joyner /**
25406f37f232SEric Joyner * ixgbe_setup_kr_x550em - Configure the KR PHY.
25416f37f232SEric Joyner * @hw: pointer to hardware structure
25426f37f232SEric Joyner **/
ixgbe_setup_kr_x550em(struct ixgbe_hw * hw)25436f37f232SEric Joyner s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
25446f37f232SEric Joyner {
25458eb6488eSEric Joyner /* leave link alone for 2.5G */
25468eb6488eSEric Joyner if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
25478eb6488eSEric Joyner return IXGBE_SUCCESS;
25488eb6488eSEric Joyner
25498eb6488eSEric Joyner if (ixgbe_check_reset_blocked(hw))
25508eb6488eSEric Joyner return 0;
25518eb6488eSEric Joyner
25526f37f232SEric Joyner return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised);
25536f37f232SEric Joyner }
25546f37f232SEric Joyner
25556f37f232SEric Joyner /**
25566f37f232SEric Joyner * ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP
25576f37f232SEric Joyner * @hw: pointer to hardware structure
25587d48aa4cSEric Joyner * @speed: new link speed
25597d48aa4cSEric Joyner * @autoneg_wait_to_complete: unused
25606f37f232SEric Joyner *
25616f37f232SEric Joyner * Configure the external PHY and the integrated KR PHY for SFP support.
25626f37f232SEric Joyner **/
ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)25636f37f232SEric Joyner s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
25646f37f232SEric Joyner ixgbe_link_speed speed,
25656f37f232SEric Joyner bool autoneg_wait_to_complete)
25666f37f232SEric Joyner {
25676f37f232SEric Joyner s32 ret_val;
25686f37f232SEric Joyner u16 reg_slice, reg_val;
256979b36ec9SKevin Bowling bool setup_linear = false;
25706f37f232SEric Joyner UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
25716f37f232SEric Joyner
25726f37f232SEric Joyner /* Check if SFP module is supported and linear */
25736f37f232SEric Joyner ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
25746f37f232SEric Joyner
25756f37f232SEric Joyner /* If no SFP module present, then return success. Return success since
25766f37f232SEric Joyner * there is no reason to configure CS4227 and SFP not present error is
25776f37f232SEric Joyner * not excepted in the setup MAC link flow.
25786f37f232SEric Joyner */
25796f37f232SEric Joyner if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
25806f37f232SEric Joyner return IXGBE_SUCCESS;
25816f37f232SEric Joyner
25826f37f232SEric Joyner if (ret_val != IXGBE_SUCCESS)
25836f37f232SEric Joyner return ret_val;
25846f37f232SEric Joyner
2585a9ca1c79SSean Bruno /* Configure internal PHY for KR/KX. */
2586a9ca1c79SSean Bruno ixgbe_setup_kr_speed_x550em(hw, speed);
25876f37f232SEric Joyner
2588a9ca1c79SSean Bruno /* Configure CS4227 LINE side to proper mode. */
2589a9ca1c79SSean Bruno reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
2590a9ca1c79SSean Bruno (hw->bus.lan_id << 12);
2591a9ca1c79SSean Bruno if (setup_linear)
2592a9ca1c79SSean Bruno reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
2593a9ca1c79SSean Bruno else
2594a9ca1c79SSean Bruno reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
25958eb6488eSEric Joyner ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice,
2596a9ca1c79SSean Bruno reg_val);
25978eb6488eSEric Joyner return ret_val;
25988eb6488eSEric Joyner }
25998eb6488eSEric Joyner
26008eb6488eSEric Joyner /**
26018eb6488eSEric Joyner * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode
26028eb6488eSEric Joyner * @hw: pointer to hardware structure
26038eb6488eSEric Joyner * @speed: the link speed to force
26048eb6488eSEric Joyner *
26058eb6488eSEric Joyner * Configures the integrated PHY for native SFI mode. Used to connect the
26068eb6488eSEric Joyner * internal PHY directly to an SFP cage, without autonegotiation.
26078eb6488eSEric Joyner **/
ixgbe_setup_sfi_x550a(struct ixgbe_hw * hw,ixgbe_link_speed * speed)26088eb6488eSEric Joyner static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
26098eb6488eSEric Joyner {
26108eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac;
26118eb6488eSEric Joyner s32 status;
26128eb6488eSEric Joyner u32 reg_val;
26138eb6488eSEric Joyner
26148eb6488eSEric Joyner /* Disable all AN and force speed to 10G Serial. */
26158eb6488eSEric Joyner status = mac->ops.read_iosf_sb_reg(hw,
26168eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
26178eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
26188eb6488eSEric Joyner if (status != IXGBE_SUCCESS)
26198eb6488eSEric Joyner return status;
26208eb6488eSEric Joyner
26218eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
26228eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
26238eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
26248eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
26258eb6488eSEric Joyner
26268eb6488eSEric Joyner /* Select forced link speed for internal PHY. */
26278eb6488eSEric Joyner switch (*speed) {
26288eb6488eSEric Joyner case IXGBE_LINK_SPEED_10GB_FULL:
26298eb6488eSEric Joyner reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G;
26308eb6488eSEric Joyner break;
26318eb6488eSEric Joyner case IXGBE_LINK_SPEED_1GB_FULL:
26328eb6488eSEric Joyner reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
26338eb6488eSEric Joyner break;
26348eb6488eSEric Joyner default:
26358eb6488eSEric Joyner /* Other link speeds are not supported by internal PHY. */
26368eb6488eSEric Joyner return IXGBE_ERR_LINK_SETUP;
26378eb6488eSEric Joyner }
26388eb6488eSEric Joyner
26398eb6488eSEric Joyner status = mac->ops.write_iosf_sb_reg(hw,
26408eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
26418eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
26428eb6488eSEric Joyner
26438eb6488eSEric Joyner /* Toggle port SW reset by AN reset. */
26448eb6488eSEric Joyner status = ixgbe_restart_an_internal_phy_x550em(hw);
26458eb6488eSEric Joyner
26468eb6488eSEric Joyner return status;
26478eb6488eSEric Joyner }
26488eb6488eSEric Joyner
26498eb6488eSEric Joyner /**
26508eb6488eSEric Joyner * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP
26518eb6488eSEric Joyner * @hw: pointer to hardware structure
26527d48aa4cSEric Joyner * @speed: new link speed
26537d48aa4cSEric Joyner * @autoneg_wait_to_complete: unused
26548eb6488eSEric Joyner *
26553f66b96dSKevin Bowling * Configure the integrated PHY for SFP support.
26568eb6488eSEric Joyner **/
ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)26578eb6488eSEric Joyner s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
26588eb6488eSEric Joyner ixgbe_link_speed speed,
26598eb6488eSEric Joyner bool autoneg_wait_to_complete)
26608eb6488eSEric Joyner {
26618eb6488eSEric Joyner s32 ret_val;
26628eb6488eSEric Joyner u16 reg_phy_ext;
266379b36ec9SKevin Bowling bool setup_linear = false;
26648eb6488eSEric Joyner u32 reg_slice, reg_phy_int, slice_offset;
26658eb6488eSEric Joyner
26668eb6488eSEric Joyner UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
26678eb6488eSEric Joyner
26688eb6488eSEric Joyner /* Check if SFP module is supported and linear */
26698eb6488eSEric Joyner ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
26708eb6488eSEric Joyner
26718eb6488eSEric Joyner /* If no SFP module present, then return success. Return success since
26728eb6488eSEric Joyner * SFP not present error is not excepted in the setup MAC link flow.
26738eb6488eSEric Joyner */
26748eb6488eSEric Joyner if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
26758eb6488eSEric Joyner return IXGBE_SUCCESS;
26768eb6488eSEric Joyner
26778eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS)
26788eb6488eSEric Joyner return ret_val;
26798eb6488eSEric Joyner
26808eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) {
26818eb6488eSEric Joyner /* Configure internal PHY for native SFI based on module type */
26828eb6488eSEric Joyner ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
26838eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
26848eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int);
26858eb6488eSEric Joyner
26868eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS)
26878eb6488eSEric Joyner return ret_val;
26888eb6488eSEric Joyner
26898eb6488eSEric Joyner reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA;
26908eb6488eSEric Joyner if (!setup_linear)
26918eb6488eSEric Joyner reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR;
26928eb6488eSEric Joyner
26938eb6488eSEric Joyner ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
26948eb6488eSEric Joyner IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
26958eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
26968eb6488eSEric Joyner
26978eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS)
26988eb6488eSEric Joyner return ret_val;
26998eb6488eSEric Joyner
27008eb6488eSEric Joyner /* Setup SFI internal link. */
27018eb6488eSEric Joyner ret_val = ixgbe_setup_sfi_x550a(hw, &speed);
27028eb6488eSEric Joyner } else {
27038eb6488eSEric Joyner /* Configure internal PHY for KR/KX. */
27048eb6488eSEric Joyner ixgbe_setup_kr_speed_x550em(hw, speed);
27058eb6488eSEric Joyner
27068eb6488eSEric Joyner if (hw->phy.addr == 0x0 || hw->phy.addr == 0xFFFF) {
27078eb6488eSEric Joyner /* Find Address */
27088eb6488eSEric Joyner DEBUGOUT("Invalid NW_MNG_IF_SEL.MDIO_PHY_ADD value\n");
27098eb6488eSEric Joyner return IXGBE_ERR_PHY_ADDR_INVALID;
27108eb6488eSEric Joyner }
27118eb6488eSEric Joyner
27128eb6488eSEric Joyner /* Get external PHY SKU id */
27138eb6488eSEric Joyner ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU,
27148eb6488eSEric Joyner IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext);
27158eb6488eSEric Joyner
27168eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS)
27178eb6488eSEric Joyner return ret_val;
27188eb6488eSEric Joyner
27198eb6488eSEric Joyner /* When configuring quad port CS4223, the MAC instance is part
27208eb6488eSEric Joyner * of the slice offset.
27218eb6488eSEric Joyner */
27228eb6488eSEric Joyner if (reg_phy_ext == IXGBE_CS4223_SKU_ID)
27238eb6488eSEric Joyner slice_offset = (hw->bus.lan_id +
27248eb6488eSEric Joyner (hw->bus.instance_id << 1)) << 12;
27258eb6488eSEric Joyner else
27268eb6488eSEric Joyner slice_offset = hw->bus.lan_id << 12;
27278eb6488eSEric Joyner
27288eb6488eSEric Joyner /* Configure CS4227/CS4223 LINE side to proper mode. */
27298eb6488eSEric Joyner reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
27308eb6488eSEric Joyner
27318eb6488eSEric Joyner ret_val = hw->phy.ops.read_reg(hw, reg_slice,
27328eb6488eSEric Joyner IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext);
27338eb6488eSEric Joyner
27348eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS)
27358eb6488eSEric Joyner return ret_val;
27368eb6488eSEric Joyner
27378eb6488eSEric Joyner reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) |
27388eb6488eSEric Joyner (IXGBE_CS4227_EDC_MODE_SR << 1));
27398eb6488eSEric Joyner
27408eb6488eSEric Joyner if (setup_linear)
2741c85b6f29SXiaoyun Li reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
27428eb6488eSEric Joyner else
2743c85b6f29SXiaoyun Li reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
27448eb6488eSEric Joyner ret_val = hw->phy.ops.write_reg(hw, reg_slice,
27458eb6488eSEric Joyner IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
27468eb6488eSEric Joyner
27478eb6488eSEric Joyner /* Flush previous write with a read */
27488eb6488eSEric Joyner ret_val = hw->phy.ops.read_reg(hw, reg_slice,
27498eb6488eSEric Joyner IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext);
2750a9ca1c79SSean Bruno }
27516f37f232SEric Joyner return ret_val;
27526f37f232SEric Joyner }
27536f37f232SEric Joyner
27546f37f232SEric Joyner /**
27558eb6488eSEric Joyner * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration
27568eb6488eSEric Joyner * @hw: pointer to hardware structure
27578eb6488eSEric Joyner *
27588eb6488eSEric Joyner * iXfI configuration needed for ixgbe_mac_X550EM_x devices.
27598eb6488eSEric Joyner **/
ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw * hw)27608eb6488eSEric Joyner static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)
27618eb6488eSEric Joyner {
27628eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac;
27638eb6488eSEric Joyner s32 status;
27648eb6488eSEric Joyner u32 reg_val;
27658eb6488eSEric Joyner
27668eb6488eSEric Joyner /* Disable training protocol FSM. */
27678eb6488eSEric Joyner status = mac->ops.read_iosf_sb_reg(hw,
27688eb6488eSEric Joyner IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
27698eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
27708eb6488eSEric Joyner if (status != IXGBE_SUCCESS)
27718eb6488eSEric Joyner return status;
27728eb6488eSEric Joyner reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL;
27738eb6488eSEric Joyner status = mac->ops.write_iosf_sb_reg(hw,
27748eb6488eSEric Joyner IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
27758eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
27768eb6488eSEric Joyner if (status != IXGBE_SUCCESS)
27778eb6488eSEric Joyner return status;
27788eb6488eSEric Joyner
27798eb6488eSEric Joyner /* Disable Flex from training TXFFE. */
27808eb6488eSEric Joyner status = mac->ops.read_iosf_sb_reg(hw,
27818eb6488eSEric Joyner IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
27828eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
27838eb6488eSEric Joyner if (status != IXGBE_SUCCESS)
27848eb6488eSEric Joyner return status;
27858eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
27868eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
27878eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
27888eb6488eSEric Joyner status = mac->ops.write_iosf_sb_reg(hw,
27898eb6488eSEric Joyner IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
27908eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
27918eb6488eSEric Joyner if (status != IXGBE_SUCCESS)
27928eb6488eSEric Joyner return status;
27938eb6488eSEric Joyner status = mac->ops.read_iosf_sb_reg(hw,
27948eb6488eSEric Joyner IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
27958eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
27968eb6488eSEric Joyner if (status != IXGBE_SUCCESS)
27978eb6488eSEric Joyner return status;
27988eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
27998eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
28008eb6488eSEric Joyner reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
28018eb6488eSEric Joyner status = mac->ops.write_iosf_sb_reg(hw,
28028eb6488eSEric Joyner IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
28038eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
28048eb6488eSEric Joyner if (status != IXGBE_SUCCESS)
28058eb6488eSEric Joyner return status;
28068eb6488eSEric Joyner
28078eb6488eSEric Joyner /* Enable override for coefficients. */
28088eb6488eSEric Joyner status = mac->ops.read_iosf_sb_reg(hw,
28098eb6488eSEric Joyner IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
28108eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
28118eb6488eSEric Joyner if (status != IXGBE_SUCCESS)
28128eb6488eSEric Joyner return status;
28138eb6488eSEric Joyner reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN;
28148eb6488eSEric Joyner reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN;
28158eb6488eSEric Joyner reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN;
28168eb6488eSEric Joyner reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN;
28178eb6488eSEric Joyner status = mac->ops.write_iosf_sb_reg(hw,
28188eb6488eSEric Joyner IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
28198eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
28208eb6488eSEric Joyner return status;
28218eb6488eSEric Joyner }
28228eb6488eSEric Joyner
28238eb6488eSEric Joyner /**
28246f37f232SEric Joyner * ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
28256f37f232SEric Joyner * @hw: pointer to hardware structure
28266f37f232SEric Joyner * @speed: the link speed to force
28276f37f232SEric Joyner *
28286f37f232SEric Joyner * Configures the integrated KR PHY to use iXFI mode. Used to connect an
28296f37f232SEric Joyner * internal and external PHY at a specific speed, without autonegotiation.
28306f37f232SEric Joyner **/
ixgbe_setup_ixfi_x550em(struct ixgbe_hw * hw,ixgbe_link_speed * speed)28316f37f232SEric Joyner static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
28326f37f232SEric Joyner {
28338eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac;
28346f37f232SEric Joyner s32 status;
28356f37f232SEric Joyner u32 reg_val;
28366f37f232SEric Joyner
28378eb6488eSEric Joyner /* iXFI is only supported with X552 */
28388eb6488eSEric Joyner if (mac->type != ixgbe_mac_X550EM_x)
28398eb6488eSEric Joyner return IXGBE_ERR_LINK_SETUP;
28408eb6488eSEric Joyner
28416f37f232SEric Joyner /* Disable AN and force speed to 10G Serial. */
28428eb6488eSEric Joyner status = mac->ops.read_iosf_sb_reg(hw,
28436f37f232SEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
28446f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
28456f37f232SEric Joyner if (status != IXGBE_SUCCESS)
28466f37f232SEric Joyner return status;
28476f37f232SEric Joyner
28486f37f232SEric Joyner reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
28496f37f232SEric Joyner reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
28506f37f232SEric Joyner
28516f37f232SEric Joyner /* Select forced link speed for internal PHY. */
28526f37f232SEric Joyner switch (*speed) {
28536f37f232SEric Joyner case IXGBE_LINK_SPEED_10GB_FULL:
28546f37f232SEric Joyner reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
28556f37f232SEric Joyner break;
28566f37f232SEric Joyner case IXGBE_LINK_SPEED_1GB_FULL:
28576f37f232SEric Joyner reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
28586f37f232SEric Joyner break;
28596f37f232SEric Joyner default:
28606f37f232SEric Joyner /* Other link speeds are not supported by internal KR PHY. */
28616f37f232SEric Joyner return IXGBE_ERR_LINK_SETUP;
28626f37f232SEric Joyner }
28636f37f232SEric Joyner
28648eb6488eSEric Joyner status = mac->ops.write_iosf_sb_reg(hw,
28656f37f232SEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
28666f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
28676f37f232SEric Joyner if (status != IXGBE_SUCCESS)
28686f37f232SEric Joyner return status;
28696f37f232SEric Joyner
28708eb6488eSEric Joyner /* Additional configuration needed for x550em_x */
28718eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550EM_x) {
28728eb6488eSEric Joyner status = ixgbe_setup_ixfi_x550em_x(hw);
28736f37f232SEric Joyner if (status != IXGBE_SUCCESS)
28746f37f232SEric Joyner return status;
28758eb6488eSEric Joyner }
28766f37f232SEric Joyner
28776f37f232SEric Joyner /* Toggle port SW reset by AN reset. */
28788eb6488eSEric Joyner status = ixgbe_restart_an_internal_phy_x550em(hw);
28796f37f232SEric Joyner
28806f37f232SEric Joyner return status;
28816f37f232SEric Joyner }
28826f37f232SEric Joyner
28836f37f232SEric Joyner /**
28846f37f232SEric Joyner * ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status
28856f37f232SEric Joyner * @hw: address of hardware structure
28866f37f232SEric Joyner * @link_up: address of boolean to indicate link status
28876f37f232SEric Joyner *
28886f37f232SEric Joyner * Returns error code if unable to get link status.
28896f37f232SEric Joyner */
ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw * hw,bool * link_up)28906f37f232SEric Joyner static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
28916f37f232SEric Joyner {
28926f37f232SEric Joyner u32 ret;
28936f37f232SEric Joyner u16 autoneg_status;
28946f37f232SEric Joyner
289579b36ec9SKevin Bowling *link_up = false;
28966f37f232SEric Joyner
28976f37f232SEric Joyner /* read this twice back to back to indicate current status */
28986f37f232SEric Joyner ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
28996f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
29006f37f232SEric Joyner &autoneg_status);
29016f37f232SEric Joyner if (ret != IXGBE_SUCCESS)
29026f37f232SEric Joyner return ret;
29036f37f232SEric Joyner
29046f37f232SEric Joyner ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
29056f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
29066f37f232SEric Joyner &autoneg_status);
29076f37f232SEric Joyner if (ret != IXGBE_SUCCESS)
29086f37f232SEric Joyner return ret;
29096f37f232SEric Joyner
29106f37f232SEric Joyner *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS);
29116f37f232SEric Joyner
29126f37f232SEric Joyner return IXGBE_SUCCESS;
29136f37f232SEric Joyner }
29146f37f232SEric Joyner
29156f37f232SEric Joyner /**
29166f37f232SEric Joyner * ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link
29176f37f232SEric Joyner * @hw: point to hardware structure
29186f37f232SEric Joyner *
29196f37f232SEric Joyner * Configures the link between the integrated KR PHY and the external X557 PHY
29206f37f232SEric Joyner * The driver will call this function when it gets a link status change
29216f37f232SEric Joyner * interrupt from the X557 PHY. This function configures the link speed
29226f37f232SEric Joyner * between the PHYs to match the link speed of the BASE-T link.
29236f37f232SEric Joyner *
29246f37f232SEric Joyner * A return of a non-zero value indicates an error, and the base driver should
29256f37f232SEric Joyner * not report link up.
29266f37f232SEric Joyner */
ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw * hw)29276f37f232SEric Joyner s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
29286f37f232SEric Joyner {
29296f37f232SEric Joyner ixgbe_link_speed force_speed;
29306f37f232SEric Joyner bool link_up;
29316f37f232SEric Joyner u32 status;
29326f37f232SEric Joyner u16 speed;
29336f37f232SEric Joyner
29346f37f232SEric Joyner if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
29356f37f232SEric Joyner return IXGBE_ERR_CONFIG;
29366f37f232SEric Joyner
29378eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550EM_x &&
29388eb6488eSEric Joyner !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
29398eb6488eSEric Joyner /* If link is down, there is no setup necessary so return */
29406f37f232SEric Joyner status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
29416f37f232SEric Joyner if (status != IXGBE_SUCCESS)
29426f37f232SEric Joyner return status;
29436f37f232SEric Joyner
29446f37f232SEric Joyner if (!link_up)
29456f37f232SEric Joyner return IXGBE_SUCCESS;
29466f37f232SEric Joyner
29478eb6488eSEric Joyner status = hw->phy.ops.read_reg(hw,
29488eb6488eSEric Joyner IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
29496f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
29506f37f232SEric Joyner &speed);
29516f37f232SEric Joyner if (status != IXGBE_SUCCESS)
29526f37f232SEric Joyner return status;
29536f37f232SEric Joyner
29548eb6488eSEric Joyner /* If link is still down - no setup is required so return */
29556f37f232SEric Joyner status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
29566f37f232SEric Joyner if (status != IXGBE_SUCCESS)
29576f37f232SEric Joyner return status;
29586f37f232SEric Joyner if (!link_up)
29596f37f232SEric Joyner return IXGBE_SUCCESS;
29606f37f232SEric Joyner
29616f37f232SEric Joyner /* clear everything but the speed and duplex bits */
29626f37f232SEric Joyner speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
29636f37f232SEric Joyner
29646f37f232SEric Joyner switch (speed) {
29656f37f232SEric Joyner case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
29666f37f232SEric Joyner force_speed = IXGBE_LINK_SPEED_10GB_FULL;
29676f37f232SEric Joyner break;
29686f37f232SEric Joyner case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
29696f37f232SEric Joyner force_speed = IXGBE_LINK_SPEED_1GB_FULL;
29706f37f232SEric Joyner break;
29716f37f232SEric Joyner default:
29726f37f232SEric Joyner /* Internal PHY does not support anything else */
29736f37f232SEric Joyner return IXGBE_ERR_INVALID_LINK_SETTINGS;
29746f37f232SEric Joyner }
29756f37f232SEric Joyner
29766f37f232SEric Joyner return ixgbe_setup_ixfi_x550em(hw, &force_speed);
29778eb6488eSEric Joyner } else {
29788eb6488eSEric Joyner speed = IXGBE_LINK_SPEED_10GB_FULL |
29798eb6488eSEric Joyner IXGBE_LINK_SPEED_1GB_FULL;
29808eb6488eSEric Joyner return ixgbe_setup_kr_speed_x550em(hw, speed);
29818eb6488eSEric Joyner }
29826f37f232SEric Joyner }
29836f37f232SEric Joyner
29846f37f232SEric Joyner /**
29856f37f232SEric Joyner * ixgbe_setup_phy_loopback_x550em - Configure the KR PHY for loopback.
29866f37f232SEric Joyner * @hw: pointer to hardware structure
29876f37f232SEric Joyner *
29886f37f232SEric Joyner * Configures the integrated KR PHY to use internal loopback mode.
29896f37f232SEric Joyner **/
ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw * hw)29906f37f232SEric Joyner s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw)
29916f37f232SEric Joyner {
29926f37f232SEric Joyner s32 status;
29936f37f232SEric Joyner u32 reg_val;
29946f37f232SEric Joyner
29956f37f232SEric Joyner /* Disable AN and force speed to 10G Serial. */
29968eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
29976f37f232SEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
29986f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
29996f37f232SEric Joyner if (status != IXGBE_SUCCESS)
30006f37f232SEric Joyner return status;
30016f37f232SEric Joyner reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
30026f37f232SEric Joyner reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
30036f37f232SEric Joyner reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
30048eb6488eSEric Joyner status = hw->mac.ops.write_iosf_sb_reg(hw,
30056f37f232SEric Joyner IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
30066f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
30076f37f232SEric Joyner if (status != IXGBE_SUCCESS)
30086f37f232SEric Joyner return status;
30096f37f232SEric Joyner
30106f37f232SEric Joyner /* Set near-end loopback clocks. */
30118eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
30126f37f232SEric Joyner IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
30136f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
30146f37f232SEric Joyner if (status != IXGBE_SUCCESS)
30156f37f232SEric Joyner return status;
30166f37f232SEric Joyner reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B;
30176f37f232SEric Joyner reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS;
30188eb6488eSEric Joyner status = hw->mac.ops.write_iosf_sb_reg(hw,
30196f37f232SEric Joyner IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
30206f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
30216f37f232SEric Joyner if (status != IXGBE_SUCCESS)
30226f37f232SEric Joyner return status;
30236f37f232SEric Joyner
30246f37f232SEric Joyner /* Set loopback enable. */
30258eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
30266f37f232SEric Joyner IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
30276f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
30286f37f232SEric Joyner if (status != IXGBE_SUCCESS)
30296f37f232SEric Joyner return status;
30306f37f232SEric Joyner reg_val |= IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK;
30318eb6488eSEric Joyner status = hw->mac.ops.write_iosf_sb_reg(hw,
30326f37f232SEric Joyner IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
30336f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
30346f37f232SEric Joyner if (status != IXGBE_SUCCESS)
30356f37f232SEric Joyner return status;
30366f37f232SEric Joyner
30376f37f232SEric Joyner /* Training bypass. */
30388eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
30396f37f232SEric Joyner IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
30406f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
30416f37f232SEric Joyner if (status != IXGBE_SUCCESS)
30426f37f232SEric Joyner return status;
30436f37f232SEric Joyner reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS;
30448eb6488eSEric Joyner status = hw->mac.ops.write_iosf_sb_reg(hw,
30456f37f232SEric Joyner IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
30466f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
30476f37f232SEric Joyner
30486f37f232SEric Joyner return status;
30496f37f232SEric Joyner }
30506f37f232SEric Joyner
30516f37f232SEric Joyner /**
30526f37f232SEric Joyner * ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command
30536f37f232SEric Joyner * assuming that the semaphore is already obtained.
30546f37f232SEric Joyner * @hw: pointer to hardware structure
30556f37f232SEric Joyner * @offset: offset of word in the EEPROM to read
30566f37f232SEric Joyner * @data: word read from the EEPROM
30576f37f232SEric Joyner *
30586f37f232SEric Joyner * Reads a 16 bit word from the EEPROM using the hostif.
30596f37f232SEric Joyner **/
ixgbe_read_ee_hostif_X550(struct ixgbe_hw * hw,u16 offset,u16 * data)30608eb6488eSEric Joyner s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data)
30616f37f232SEric Joyner {
30628eb6488eSEric Joyner const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
30636f37f232SEric Joyner struct ixgbe_hic_read_shadow_ram buffer;
30648eb6488eSEric Joyner s32 status;
30656f37f232SEric Joyner
30668eb6488eSEric Joyner DEBUGFUNC("ixgbe_read_ee_hostif_X550");
30676f37f232SEric Joyner buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
30686f37f232SEric Joyner buffer.hdr.req.buf_lenh = 0;
30696f37f232SEric Joyner buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
30706f37f232SEric Joyner buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
30716f37f232SEric Joyner
30726f37f232SEric Joyner /* convert offset from words to bytes */
30736f37f232SEric Joyner buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
30746f37f232SEric Joyner /* one word */
30756f37f232SEric Joyner buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
30767d48aa4cSEric Joyner buffer.pad2 = 0;
3077b3ebe337SGuinan Sun buffer.data = 0;
30787d48aa4cSEric Joyner buffer.pad3 = 0;
30796f37f232SEric Joyner
30808eb6488eSEric Joyner status = hw->mac.ops.acquire_swfw_sync(hw, mask);
30816f37f232SEric Joyner if (status)
30826f37f232SEric Joyner return status;
30836f37f232SEric Joyner
30848eb6488eSEric Joyner status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
30858eb6488eSEric Joyner IXGBE_HI_COMMAND_TIMEOUT);
30868eb6488eSEric Joyner if (!status) {
30876f37f232SEric Joyner *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
30886f37f232SEric Joyner FW_NVM_DATA_OFFSET);
30896f37f232SEric Joyner }
30906f37f232SEric Joyner
30918eb6488eSEric Joyner hw->mac.ops.release_swfw_sync(hw, mask);
30926f37f232SEric Joyner return status;
30936f37f232SEric Joyner }
30946f37f232SEric Joyner
30956f37f232SEric Joyner /**
30966f37f232SEric Joyner * ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif
30976f37f232SEric Joyner * @hw: pointer to hardware structure
30986f37f232SEric Joyner * @offset: offset of word in the EEPROM to read
30996f37f232SEric Joyner * @words: number of words
31006f37f232SEric Joyner * @data: word(s) read from the EEPROM
31016f37f232SEric Joyner *
31026f37f232SEric Joyner * Reads a 16 bit word(s) from the EEPROM using the hostif.
31036f37f232SEric Joyner **/
ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)31046f37f232SEric Joyner s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
31056f37f232SEric Joyner u16 offset, u16 words, u16 *data)
31066f37f232SEric Joyner {
31078eb6488eSEric Joyner const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
31086f37f232SEric Joyner struct ixgbe_hic_read_shadow_ram buffer;
31096f37f232SEric Joyner u32 current_word = 0;
31106f37f232SEric Joyner u16 words_to_read;
31116f37f232SEric Joyner s32 status;
31126f37f232SEric Joyner u32 i;
31136f37f232SEric Joyner
31146f37f232SEric Joyner DEBUGFUNC("ixgbe_read_ee_hostif_buffer_X550");
31156f37f232SEric Joyner
31166f37f232SEric Joyner /* Take semaphore for the entire operation. */
31178eb6488eSEric Joyner status = hw->mac.ops.acquire_swfw_sync(hw, mask);
31186f37f232SEric Joyner if (status) {
31196f37f232SEric Joyner DEBUGOUT("EEPROM read buffer - semaphore failed\n");
31206f37f232SEric Joyner return status;
31216f37f232SEric Joyner }
31228eb6488eSEric Joyner
31236f37f232SEric Joyner while (words) {
31246f37f232SEric Joyner if (words > FW_MAX_READ_BUFFER_SIZE / 2)
31256f37f232SEric Joyner words_to_read = FW_MAX_READ_BUFFER_SIZE / 2;
31266f37f232SEric Joyner else
31276f37f232SEric Joyner words_to_read = words;
31286f37f232SEric Joyner
31296f37f232SEric Joyner buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
31306f37f232SEric Joyner buffer.hdr.req.buf_lenh = 0;
31316f37f232SEric Joyner buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
31326f37f232SEric Joyner buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
31336f37f232SEric Joyner
31346f37f232SEric Joyner /* convert offset from words to bytes */
31356f37f232SEric Joyner buffer.address = IXGBE_CPU_TO_BE32((offset + current_word) * 2);
31366f37f232SEric Joyner buffer.length = IXGBE_CPU_TO_BE16(words_to_read * 2);
31377d48aa4cSEric Joyner buffer.pad2 = 0;
3138b3ebe337SGuinan Sun buffer.data = 0;
31397d48aa4cSEric Joyner buffer.pad3 = 0;
31406f37f232SEric Joyner
31418eb6488eSEric Joyner status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
31428eb6488eSEric Joyner IXGBE_HI_COMMAND_TIMEOUT);
31436f37f232SEric Joyner
31446f37f232SEric Joyner if (status) {
31456f37f232SEric Joyner DEBUGOUT("Host interface command failed\n");
31466f37f232SEric Joyner goto out;
31476f37f232SEric Joyner }
31486f37f232SEric Joyner
31496f37f232SEric Joyner for (i = 0; i < words_to_read; i++) {
31506f37f232SEric Joyner u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) +
31516f37f232SEric Joyner 2 * i;
31526f37f232SEric Joyner u32 value = IXGBE_READ_REG(hw, reg);
31536f37f232SEric Joyner
31546f37f232SEric Joyner data[current_word] = (u16)(value & 0xffff);
31556f37f232SEric Joyner current_word++;
31566f37f232SEric Joyner i++;
31576f37f232SEric Joyner if (i < words_to_read) {
31586f37f232SEric Joyner value >>= 16;
31596f37f232SEric Joyner data[current_word] = (u16)(value & 0xffff);
31606f37f232SEric Joyner current_word++;
31616f37f232SEric Joyner }
31626f37f232SEric Joyner }
31636f37f232SEric Joyner words -= words_to_read;
31646f37f232SEric Joyner }
31656f37f232SEric Joyner
31666f37f232SEric Joyner out:
31678eb6488eSEric Joyner hw->mac.ops.release_swfw_sync(hw, mask);
31686f37f232SEric Joyner return status;
31696f37f232SEric Joyner }
31706f37f232SEric Joyner
31716f37f232SEric Joyner /**
3172edef2769SRadoslaw Tyl * ixgbe_write_ee_hostif_data_X550 - Write EEPROM word using hostif
31736f37f232SEric Joyner * @hw: pointer to hardware structure
31746f37f232SEric Joyner * @offset: offset of word in the EEPROM to write
31756f37f232SEric Joyner * @data: word write to the EEPROM
31766f37f232SEric Joyner *
31776f37f232SEric Joyner * Write a 16 bit word to the EEPROM using the hostif.
31786f37f232SEric Joyner **/
ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw * hw,u16 offset,u16 data)31796f37f232SEric Joyner s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
31806f37f232SEric Joyner u16 data)
31816f37f232SEric Joyner {
31826f37f232SEric Joyner s32 status;
31836f37f232SEric Joyner struct ixgbe_hic_write_shadow_ram buffer;
31846f37f232SEric Joyner
31856f37f232SEric Joyner DEBUGFUNC("ixgbe_write_ee_hostif_data_X550");
31866f37f232SEric Joyner
31876f37f232SEric Joyner buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
31886f37f232SEric Joyner buffer.hdr.req.buf_lenh = 0;
31896f37f232SEric Joyner buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
31906f37f232SEric Joyner buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
31916f37f232SEric Joyner
31926f37f232SEric Joyner /* one word */
31936f37f232SEric Joyner buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
31946f37f232SEric Joyner buffer.data = data;
31956f37f232SEric Joyner buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
31966f37f232SEric Joyner
31976f37f232SEric Joyner status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
31986f37f232SEric Joyner sizeof(buffer),
319979b36ec9SKevin Bowling IXGBE_HI_COMMAND_TIMEOUT, true);
3200c1a56b6fSGuinan Sun if (status != IXGBE_SUCCESS) {
3201c1a56b6fSGuinan Sun DEBUGOUT2("for offset %04x failed with status %d\n",
3202c1a56b6fSGuinan Sun offset, status);
3203c1a56b6fSGuinan Sun return status;
3204c1a56b6fSGuinan Sun }
3205c1a56b6fSGuinan Sun
3206c1a56b6fSGuinan Sun if (buffer.hdr.rsp.buf_lenh_status != FW_CEM_RESP_STATUS_SUCCESS) {
3207c1a56b6fSGuinan Sun DEBUGOUT2("for offset %04x host interface return status %02x\n",
3208c1a56b6fSGuinan Sun offset, buffer.hdr.rsp.buf_lenh_status);
3209c1a56b6fSGuinan Sun return IXGBE_ERR_HOST_INTERFACE_COMMAND;
3210c1a56b6fSGuinan Sun }
32116f37f232SEric Joyner
32126f37f232SEric Joyner return status;
32136f37f232SEric Joyner }
32146f37f232SEric Joyner
32156f37f232SEric Joyner /**
32166f37f232SEric Joyner * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
32176f37f232SEric Joyner * @hw: pointer to hardware structure
32186f37f232SEric Joyner * @offset: offset of word in the EEPROM to write
32196f37f232SEric Joyner * @data: word write to the EEPROM
32206f37f232SEric Joyner *
32216f37f232SEric Joyner * Write a 16 bit word to the EEPROM using the hostif.
32226f37f232SEric Joyner **/
ixgbe_write_ee_hostif_X550(struct ixgbe_hw * hw,u16 offset,u16 data)32236f37f232SEric Joyner s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset,
32246f37f232SEric Joyner u16 data)
32256f37f232SEric Joyner {
32266f37f232SEric Joyner s32 status = IXGBE_SUCCESS;
32276f37f232SEric Joyner
32286f37f232SEric Joyner DEBUGFUNC("ixgbe_write_ee_hostif_X550");
32296f37f232SEric Joyner
32306f37f232SEric Joyner if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
32316f37f232SEric Joyner IXGBE_SUCCESS) {
32326f37f232SEric Joyner status = ixgbe_write_ee_hostif_data_X550(hw, offset, data);
32336f37f232SEric Joyner hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
32346f37f232SEric Joyner } else {
32356f37f232SEric Joyner DEBUGOUT("write ee hostif failed to get semaphore");
32366f37f232SEric Joyner status = IXGBE_ERR_SWFW_SYNC;
32376f37f232SEric Joyner }
32386f37f232SEric Joyner
32396f37f232SEric Joyner return status;
32406f37f232SEric Joyner }
32416f37f232SEric Joyner
32426f37f232SEric Joyner /**
32436f37f232SEric Joyner * ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif
32446f37f232SEric Joyner * @hw: pointer to hardware structure
32456f37f232SEric Joyner * @offset: offset of word in the EEPROM to write
32466f37f232SEric Joyner * @words: number of words
32476f37f232SEric Joyner * @data: word(s) write to the EEPROM
32486f37f232SEric Joyner *
32496f37f232SEric Joyner * Write a 16 bit word(s) to the EEPROM using the hostif.
32506f37f232SEric Joyner **/
ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)32516f37f232SEric Joyner s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
32526f37f232SEric Joyner u16 offset, u16 words, u16 *data)
32536f37f232SEric Joyner {
32546f37f232SEric Joyner s32 status = IXGBE_SUCCESS;
32556f37f232SEric Joyner u32 i = 0;
32566f37f232SEric Joyner
32576f37f232SEric Joyner DEBUGFUNC("ixgbe_write_ee_hostif_buffer_X550");
32586f37f232SEric Joyner
32596f37f232SEric Joyner /* Take semaphore for the entire operation. */
32606f37f232SEric Joyner status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
32616f37f232SEric Joyner if (status != IXGBE_SUCCESS) {
32626f37f232SEric Joyner DEBUGOUT("EEPROM write buffer - semaphore failed\n");
32636f37f232SEric Joyner goto out;
32646f37f232SEric Joyner }
32656f37f232SEric Joyner
32666f37f232SEric Joyner for (i = 0; i < words; i++) {
32676f37f232SEric Joyner status = ixgbe_write_ee_hostif_data_X550(hw, offset + i,
32686f37f232SEric Joyner data[i]);
32696f37f232SEric Joyner
32706f37f232SEric Joyner if (status != IXGBE_SUCCESS) {
32716f37f232SEric Joyner DEBUGOUT("Eeprom buffered write failed\n");
32726f37f232SEric Joyner break;
32736f37f232SEric Joyner }
32746f37f232SEric Joyner }
32756f37f232SEric Joyner
32766f37f232SEric Joyner hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
32776f37f232SEric Joyner out:
32786f37f232SEric Joyner
32796f37f232SEric Joyner return status;
32806f37f232SEric Joyner }
32816f37f232SEric Joyner
32826f37f232SEric Joyner /**
32836f37f232SEric Joyner * ixgbe_checksum_ptr_x550 - Checksum one pointer region
32846f37f232SEric Joyner * @hw: pointer to hardware structure
32856f37f232SEric Joyner * @ptr: pointer offset in eeprom
32866f37f232SEric Joyner * @size: size of section pointed by ptr, if 0 first word will be used as size
32876f37f232SEric Joyner * @csum: address of checksum to update
32887d48aa4cSEric Joyner * @buffer: pointer to buffer containing calculated checksum
32897d48aa4cSEric Joyner * @buffer_size: size of buffer
32906f37f232SEric Joyner *
32916f37f232SEric Joyner * Returns error status for any failure
32926f37f232SEric Joyner */
ixgbe_checksum_ptr_x550(struct ixgbe_hw * hw,u16 ptr,u16 size,u16 * csum,u16 * buffer,u32 buffer_size)32936f37f232SEric Joyner static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
32946f37f232SEric Joyner u16 size, u16 *csum, u16 *buffer,
32956f37f232SEric Joyner u32 buffer_size)
32966f37f232SEric Joyner {
32976f37f232SEric Joyner u16 buf[256];
32986f37f232SEric Joyner s32 status;
32996f37f232SEric Joyner u16 length, bufsz, i, start;
33006f37f232SEric Joyner u16 *local_buffer;
33016f37f232SEric Joyner
33026f37f232SEric Joyner bufsz = sizeof(buf) / sizeof(buf[0]);
33036f37f232SEric Joyner
33046f37f232SEric Joyner /* Read a chunk at the pointer location */
33056f37f232SEric Joyner if (!buffer) {
33066f37f232SEric Joyner status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf);
33076f37f232SEric Joyner if (status) {
33086f37f232SEric Joyner DEBUGOUT("Failed to read EEPROM image\n");
33096f37f232SEric Joyner return status;
33106f37f232SEric Joyner }
33116f37f232SEric Joyner local_buffer = buf;
33126f37f232SEric Joyner } else {
33136f37f232SEric Joyner if (buffer_size < ptr)
33146f37f232SEric Joyner return IXGBE_ERR_PARAM;
33156f37f232SEric Joyner local_buffer = &buffer[ptr];
33166f37f232SEric Joyner }
33176f37f232SEric Joyner
33186f37f232SEric Joyner if (size) {
33196f37f232SEric Joyner start = 0;
33206f37f232SEric Joyner length = size;
33216f37f232SEric Joyner } else {
33226f37f232SEric Joyner start = 1;
33236f37f232SEric Joyner length = local_buffer[0];
33246f37f232SEric Joyner
33256f37f232SEric Joyner /* Skip pointer section if length is invalid. */
33266f37f232SEric Joyner if (length == 0xFFFF || length == 0 ||
33276f37f232SEric Joyner (ptr + length) >= hw->eeprom.word_size)
33286f37f232SEric Joyner return IXGBE_SUCCESS;
33296f37f232SEric Joyner }
33306f37f232SEric Joyner
33316f37f232SEric Joyner if (buffer && ((u32)start + (u32)length > buffer_size))
33326f37f232SEric Joyner return IXGBE_ERR_PARAM;
33336f37f232SEric Joyner
33346f37f232SEric Joyner for (i = start; length; i++, length--) {
33356f37f232SEric Joyner if (i == bufsz && !buffer) {
33366f37f232SEric Joyner ptr += bufsz;
33376f37f232SEric Joyner i = 0;
33386f37f232SEric Joyner if (length < bufsz)
33396f37f232SEric Joyner bufsz = length;
33406f37f232SEric Joyner
33416f37f232SEric Joyner /* Read a chunk at the pointer location */
33426f37f232SEric Joyner status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr,
33436f37f232SEric Joyner bufsz, buf);
33446f37f232SEric Joyner if (status) {
33456f37f232SEric Joyner DEBUGOUT("Failed to read EEPROM image\n");
33466f37f232SEric Joyner return status;
33476f37f232SEric Joyner }
33486f37f232SEric Joyner }
33496f37f232SEric Joyner *csum += local_buffer[i];
33506f37f232SEric Joyner }
33516f37f232SEric Joyner return IXGBE_SUCCESS;
33526f37f232SEric Joyner }
33536f37f232SEric Joyner
33546f37f232SEric Joyner /**
33556f37f232SEric Joyner * ixgbe_calc_checksum_X550 - Calculates and returns the checksum
33566f37f232SEric Joyner * @hw: pointer to hardware structure
33576f37f232SEric Joyner * @buffer: pointer to buffer containing calculated checksum
33586f37f232SEric Joyner * @buffer_size: size of buffer
33596f37f232SEric Joyner *
33606f37f232SEric Joyner * Returns a negative error code on error, or the 16-bit checksum
33616f37f232SEric Joyner **/
ixgbe_calc_checksum_X550(struct ixgbe_hw * hw,u16 * buffer,u32 buffer_size)33626f37f232SEric Joyner s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, u32 buffer_size)
33636f37f232SEric Joyner {
33646f37f232SEric Joyner u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1];
33656f37f232SEric Joyner u16 *local_buffer;
33666f37f232SEric Joyner s32 status;
33676f37f232SEric Joyner u16 checksum = 0;
33686f37f232SEric Joyner u16 pointer, i, size;
33696f37f232SEric Joyner
33706f37f232SEric Joyner DEBUGFUNC("ixgbe_calc_eeprom_checksum_X550");
33716f37f232SEric Joyner
33726f37f232SEric Joyner hw->eeprom.ops.init_params(hw);
33736f37f232SEric Joyner
33746f37f232SEric Joyner if (!buffer) {
33756f37f232SEric Joyner /* Read pointer area */
33766f37f232SEric Joyner status = ixgbe_read_ee_hostif_buffer_X550(hw, 0,
33776f37f232SEric Joyner IXGBE_EEPROM_LAST_WORD + 1,
33786f37f232SEric Joyner eeprom_ptrs);
33796f37f232SEric Joyner if (status) {
33806f37f232SEric Joyner DEBUGOUT("Failed to read EEPROM image\n");
33816f37f232SEric Joyner return status;
33826f37f232SEric Joyner }
33836f37f232SEric Joyner local_buffer = eeprom_ptrs;
33846f37f232SEric Joyner } else {
33856f37f232SEric Joyner if (buffer_size < IXGBE_EEPROM_LAST_WORD)
33866f37f232SEric Joyner return IXGBE_ERR_PARAM;
33876f37f232SEric Joyner local_buffer = buffer;
33886f37f232SEric Joyner }
33896f37f232SEric Joyner
33906f37f232SEric Joyner /*
33916f37f232SEric Joyner * For X550 hardware include 0x0-0x41 in the checksum, skip the
33926f37f232SEric Joyner * checksum word itself
33936f37f232SEric Joyner */
33946f37f232SEric Joyner for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++)
33956f37f232SEric Joyner if (i != IXGBE_EEPROM_CHECKSUM)
33966f37f232SEric Joyner checksum += local_buffer[i];
33976f37f232SEric Joyner
33986f37f232SEric Joyner /*
33996f37f232SEric Joyner * Include all data from pointers 0x3, 0x6-0xE. This excludes the
34006f37f232SEric Joyner * FW, PHY module, and PCIe Expansion/Option ROM pointers.
34016f37f232SEric Joyner */
34026f37f232SEric Joyner for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) {
34036f37f232SEric Joyner if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
34046f37f232SEric Joyner continue;
34056f37f232SEric Joyner
34066f37f232SEric Joyner pointer = local_buffer[i];
34076f37f232SEric Joyner
34086f37f232SEric Joyner /* Skip pointer section if the pointer is invalid. */
34096f37f232SEric Joyner if (pointer == 0xFFFF || pointer == 0 ||
34106f37f232SEric Joyner pointer >= hw->eeprom.word_size)
34116f37f232SEric Joyner continue;
34126f37f232SEric Joyner
34136f37f232SEric Joyner switch (i) {
34146f37f232SEric Joyner case IXGBE_PCIE_GENERAL_PTR:
34156f37f232SEric Joyner size = IXGBE_IXGBE_PCIE_GENERAL_SIZE;
34166f37f232SEric Joyner break;
34176f37f232SEric Joyner case IXGBE_PCIE_CONFIG0_PTR:
34186f37f232SEric Joyner case IXGBE_PCIE_CONFIG1_PTR:
34196f37f232SEric Joyner size = IXGBE_PCIE_CONFIG_SIZE;
34206f37f232SEric Joyner break;
34216f37f232SEric Joyner default:
34226f37f232SEric Joyner size = 0;
34236f37f232SEric Joyner break;
34246f37f232SEric Joyner }
34256f37f232SEric Joyner
34266f37f232SEric Joyner status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum,
34276f37f232SEric Joyner buffer, buffer_size);
34286f37f232SEric Joyner if (status)
34296f37f232SEric Joyner return status;
34306f37f232SEric Joyner }
34316f37f232SEric Joyner
34326f37f232SEric Joyner checksum = (u16)IXGBE_EEPROM_SUM - checksum;
34336f37f232SEric Joyner
34346f37f232SEric Joyner return (s32)checksum;
34356f37f232SEric Joyner }
34366f37f232SEric Joyner
34376f37f232SEric Joyner /**
34386f37f232SEric Joyner * ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum
34396f37f232SEric Joyner * @hw: pointer to hardware structure
34406f37f232SEric Joyner *
34416f37f232SEric Joyner * Returns a negative error code on error, or the 16-bit checksum
34426f37f232SEric Joyner **/
ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw * hw)34436f37f232SEric Joyner s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
34446f37f232SEric Joyner {
34456f37f232SEric Joyner return ixgbe_calc_checksum_X550(hw, NULL, 0);
34466f37f232SEric Joyner }
34476f37f232SEric Joyner
34486f37f232SEric Joyner /**
34496f37f232SEric Joyner * ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum
34506f37f232SEric Joyner * @hw: pointer to hardware structure
34516f37f232SEric Joyner * @checksum_val: calculated checksum
34526f37f232SEric Joyner *
34536f37f232SEric Joyner * Performs checksum calculation and validates the EEPROM checksum. If the
34546f37f232SEric Joyner * caller does not need checksum_val, the value can be NULL.
34556f37f232SEric Joyner **/
ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw * hw,u16 * checksum_val)34566f37f232SEric Joyner s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, u16 *checksum_val)
34576f37f232SEric Joyner {
34586f37f232SEric Joyner s32 status;
34596f37f232SEric Joyner u16 checksum;
34606f37f232SEric Joyner u16 read_checksum = 0;
34616f37f232SEric Joyner
34626f37f232SEric Joyner DEBUGFUNC("ixgbe_validate_eeprom_checksum_X550");
34636f37f232SEric Joyner
34646f37f232SEric Joyner /* Read the first word from the EEPROM. If this times out or fails, do
34656f37f232SEric Joyner * not continue or we could be in for a very long wait while every
34666f37f232SEric Joyner * EEPROM read fails
34676f37f232SEric Joyner */
34686f37f232SEric Joyner status = hw->eeprom.ops.read(hw, 0, &checksum);
34696f37f232SEric Joyner if (status) {
34706f37f232SEric Joyner DEBUGOUT("EEPROM read failed\n");
34716f37f232SEric Joyner return status;
34726f37f232SEric Joyner }
34736f37f232SEric Joyner
34746f37f232SEric Joyner status = hw->eeprom.ops.calc_checksum(hw);
34756f37f232SEric Joyner if (status < 0)
34766f37f232SEric Joyner return status;
34776f37f232SEric Joyner
34786f37f232SEric Joyner checksum = (u16)(status & 0xffff);
34796f37f232SEric Joyner
34806f37f232SEric Joyner status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
34816f37f232SEric Joyner &read_checksum);
34826f37f232SEric Joyner if (status)
34836f37f232SEric Joyner return status;
34846f37f232SEric Joyner
34856f37f232SEric Joyner /* Verify read checksum from EEPROM is the same as
34866f37f232SEric Joyner * calculated checksum
34876f37f232SEric Joyner */
34886f37f232SEric Joyner if (read_checksum != checksum) {
34896f37f232SEric Joyner status = IXGBE_ERR_EEPROM_CHECKSUM;
34906f37f232SEric Joyner ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
34916f37f232SEric Joyner "Invalid EEPROM checksum");
34926f37f232SEric Joyner }
34936f37f232SEric Joyner
34946f37f232SEric Joyner /* If the user cares, return the calculated checksum */
34956f37f232SEric Joyner if (checksum_val)
34966f37f232SEric Joyner *checksum_val = checksum;
34976f37f232SEric Joyner
34986f37f232SEric Joyner return status;
34996f37f232SEric Joyner }
35006f37f232SEric Joyner
35016f37f232SEric Joyner /**
35026f37f232SEric Joyner * ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash
35036f37f232SEric Joyner * @hw: pointer to hardware structure
35046f37f232SEric Joyner *
35056f37f232SEric Joyner * After writing EEPROM to shadow RAM using EEWR register, software calculates
35066f37f232SEric Joyner * checksum and updates the EEPROM and instructs the hardware to update
35076f37f232SEric Joyner * the flash.
35086f37f232SEric Joyner **/
ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw * hw)35096f37f232SEric Joyner s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw)
35106f37f232SEric Joyner {
35116f37f232SEric Joyner s32 status;
35126f37f232SEric Joyner u16 checksum = 0;
35136f37f232SEric Joyner
35146f37f232SEric Joyner DEBUGFUNC("ixgbe_update_eeprom_checksum_X550");
35156f37f232SEric Joyner
35166f37f232SEric Joyner /* Read the first word from the EEPROM. If this times out or fails, do
35176f37f232SEric Joyner * not continue or we could be in for a very long wait while every
35186f37f232SEric Joyner * EEPROM read fails
35196f37f232SEric Joyner */
35206f37f232SEric Joyner status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum);
35216f37f232SEric Joyner if (status) {
35226f37f232SEric Joyner DEBUGOUT("EEPROM read failed\n");
35236f37f232SEric Joyner return status;
35246f37f232SEric Joyner }
35256f37f232SEric Joyner
35266f37f232SEric Joyner status = ixgbe_calc_eeprom_checksum_X550(hw);
35276f37f232SEric Joyner if (status < 0)
35286f37f232SEric Joyner return status;
35296f37f232SEric Joyner
35306f37f232SEric Joyner checksum = (u16)(status & 0xffff);
35316f37f232SEric Joyner
35326f37f232SEric Joyner status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
35336f37f232SEric Joyner checksum);
35346f37f232SEric Joyner if (status)
35356f37f232SEric Joyner return status;
35366f37f232SEric Joyner
35376f37f232SEric Joyner status = ixgbe_update_flash_X550(hw);
35386f37f232SEric Joyner
35396f37f232SEric Joyner return status;
35406f37f232SEric Joyner }
35416f37f232SEric Joyner
35426f37f232SEric Joyner /**
35436f37f232SEric Joyner * ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device
35446f37f232SEric Joyner * @hw: pointer to hardware structure
35456f37f232SEric Joyner *
35466f37f232SEric Joyner * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash.
35476f37f232SEric Joyner **/
ixgbe_update_flash_X550(struct ixgbe_hw * hw)35486f37f232SEric Joyner s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw)
35496f37f232SEric Joyner {
35506f37f232SEric Joyner s32 status = IXGBE_SUCCESS;
35516f37f232SEric Joyner union ixgbe_hic_hdr2 buffer;
35526f37f232SEric Joyner
35536f37f232SEric Joyner DEBUGFUNC("ixgbe_update_flash_X550");
35546f37f232SEric Joyner
35556f37f232SEric Joyner buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD;
35566f37f232SEric Joyner buffer.req.buf_lenh = 0;
35576f37f232SEric Joyner buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN;
35586f37f232SEric Joyner buffer.req.checksum = FW_DEFAULT_CHECKSUM;
35596f37f232SEric Joyner
35606f37f232SEric Joyner status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
35616f37f232SEric Joyner sizeof(buffer),
356279b36ec9SKevin Bowling IXGBE_HI_COMMAND_TIMEOUT, false);
35636f37f232SEric Joyner
35646f37f232SEric Joyner return status;
35656f37f232SEric Joyner }
35666f37f232SEric Joyner
35676f37f232SEric Joyner /**
35686f37f232SEric Joyner * ixgbe_get_supported_physical_layer_X550em - Returns physical layer type
35696f37f232SEric Joyner * @hw: pointer to hardware structure
35706f37f232SEric Joyner *
35716f37f232SEric Joyner * Determines physical layer capabilities of the current configuration.
35726f37f232SEric Joyner **/
ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw * hw)35738eb6488eSEric Joyner u64 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
35746f37f232SEric Joyner {
35758eb6488eSEric Joyner u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
35766f37f232SEric Joyner u16 ext_ability = 0;
35776f37f232SEric Joyner
35786f37f232SEric Joyner DEBUGFUNC("ixgbe_get_supported_physical_layer_X550em");
35796f37f232SEric Joyner
35806f37f232SEric Joyner hw->phy.ops.identify(hw);
35816f37f232SEric Joyner
35826f37f232SEric Joyner switch (hw->phy.type) {
35836f37f232SEric Joyner case ixgbe_phy_x550em_kr:
35848eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550EM_a) {
35858eb6488eSEric Joyner if (hw->phy.nw_mng_if_sel &
35868eb6488eSEric Joyner IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
35878eb6488eSEric Joyner physical_layer =
35888eb6488eSEric Joyner IXGBE_PHYSICAL_LAYER_2500BASE_KX;
35898eb6488eSEric Joyner break;
35908eb6488eSEric Joyner } else if (hw->device_id ==
35918eb6488eSEric Joyner IXGBE_DEV_ID_X550EM_A_KR_L) {
35928eb6488eSEric Joyner physical_layer =
35938eb6488eSEric Joyner IXGBE_PHYSICAL_LAYER_1000BASE_KX;
35948eb6488eSEric Joyner break;
35958eb6488eSEric Joyner }
35968eb6488eSEric Joyner }
359750455f73SPiotr Skajewski physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR |
359850455f73SPiotr Skajewski IXGBE_PHYSICAL_LAYER_1000BASE_KX;
359950455f73SPiotr Skajewski break;
36008eb6488eSEric Joyner case ixgbe_phy_x550em_xfi:
36016f37f232SEric Joyner physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR |
36026f37f232SEric Joyner IXGBE_PHYSICAL_LAYER_1000BASE_KX;
36036f37f232SEric Joyner break;
36046f37f232SEric Joyner case ixgbe_phy_x550em_kx4:
36056f37f232SEric Joyner physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
36066f37f232SEric Joyner IXGBE_PHYSICAL_LAYER_1000BASE_KX;
36076f37f232SEric Joyner break;
36086f37f232SEric Joyner case ixgbe_phy_x550em_ext_t:
36096f37f232SEric Joyner hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
36106f37f232SEric Joyner IXGBE_MDIO_PMA_PMD_DEV_TYPE,
36116f37f232SEric Joyner &ext_ability);
36126f37f232SEric Joyner if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
36136f37f232SEric Joyner physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
36146f37f232SEric Joyner if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
36156f37f232SEric Joyner physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
36166f37f232SEric Joyner break;
36178eb6488eSEric Joyner case ixgbe_phy_fw:
36188eb6488eSEric Joyner if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_1GB_FULL)
36198eb6488eSEric Joyner physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
36208eb6488eSEric Joyner if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_100_FULL)
36218eb6488eSEric Joyner physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
36228eb6488eSEric Joyner if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_10_FULL)
36238eb6488eSEric Joyner physical_layer |= IXGBE_PHYSICAL_LAYER_10BASE_T;
36248eb6488eSEric Joyner break;
36258eb6488eSEric Joyner case ixgbe_phy_sgmii:
36268eb6488eSEric Joyner physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
36278eb6488eSEric Joyner break;
36288eb6488eSEric Joyner case ixgbe_phy_ext_1g_t:
36293f66b96dSKevin Bowling physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
36308eb6488eSEric Joyner break;
36316f37f232SEric Joyner default:
36326f37f232SEric Joyner break;
36336f37f232SEric Joyner }
36346f37f232SEric Joyner
36356f37f232SEric Joyner if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber)
36366f37f232SEric Joyner physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw);
36376f37f232SEric Joyner
36386f37f232SEric Joyner return physical_layer;
36396f37f232SEric Joyner }
36406f37f232SEric Joyner
36416f37f232SEric Joyner /**
3642edef2769SRadoslaw Tyl * ixgbe_get_bus_info_X550em - Set PCI bus info
36436f37f232SEric Joyner * @hw: pointer to hardware structure
36446f37f232SEric Joyner *
36456f37f232SEric Joyner * Sets bus link width and speed to unknown because X550em is
36466f37f232SEric Joyner * not a PCI device.
36476f37f232SEric Joyner **/
ixgbe_get_bus_info_X550em(struct ixgbe_hw * hw)36486f37f232SEric Joyner s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
36496f37f232SEric Joyner {
36506f37f232SEric Joyner
36516f37f232SEric Joyner DEBUGFUNC("ixgbe_get_bus_info_x550em");
36526f37f232SEric Joyner
36536f37f232SEric Joyner hw->bus.width = ixgbe_bus_width_unknown;
36546f37f232SEric Joyner hw->bus.speed = ixgbe_bus_speed_unknown;
36556f37f232SEric Joyner
36566f37f232SEric Joyner hw->mac.ops.set_lan_id(hw);
36576f37f232SEric Joyner
36586f37f232SEric Joyner return IXGBE_SUCCESS;
36596f37f232SEric Joyner }
36606f37f232SEric Joyner
36616f37f232SEric Joyner /**
36626f37f232SEric Joyner * ixgbe_disable_rx_x550 - Disable RX unit
36637d48aa4cSEric Joyner * @hw: pointer to hardware structure
36646f37f232SEric Joyner *
36656f37f232SEric Joyner * Enables the Rx DMA unit for x550
36666f37f232SEric Joyner **/
ixgbe_disable_rx_x550(struct ixgbe_hw * hw)36676f37f232SEric Joyner void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
36686f37f232SEric Joyner {
36696f37f232SEric Joyner u32 rxctrl, pfdtxgswc;
36706f37f232SEric Joyner s32 status;
36716f37f232SEric Joyner struct ixgbe_hic_disable_rxen fw_cmd;
36726f37f232SEric Joyner
36736f37f232SEric Joyner DEBUGFUNC("ixgbe_enable_rx_dma_x550");
36746f37f232SEric Joyner
36756f37f232SEric Joyner rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
36766f37f232SEric Joyner if (rxctrl & IXGBE_RXCTRL_RXEN) {
36776f37f232SEric Joyner pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
36786f37f232SEric Joyner if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
36796f37f232SEric Joyner pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
36806f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
368179b36ec9SKevin Bowling hw->mac.set_lben = true;
36826f37f232SEric Joyner } else {
368379b36ec9SKevin Bowling hw->mac.set_lben = false;
36846f37f232SEric Joyner }
36856f37f232SEric Joyner
36866f37f232SEric Joyner fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD;
36876f37f232SEric Joyner fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN;
36886f37f232SEric Joyner fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
36896f37f232SEric Joyner fw_cmd.port_number = (u8)hw->bus.lan_id;
36906f37f232SEric Joyner
36916f37f232SEric Joyner status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
36926f37f232SEric Joyner sizeof(struct ixgbe_hic_disable_rxen),
369379b36ec9SKevin Bowling IXGBE_HI_COMMAND_TIMEOUT, true);
36946f37f232SEric Joyner
36956f37f232SEric Joyner /* If we fail - disable RX using register write */
36966f37f232SEric Joyner if (status) {
36976f37f232SEric Joyner rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
36986f37f232SEric Joyner if (rxctrl & IXGBE_RXCTRL_RXEN) {
36996f37f232SEric Joyner rxctrl &= ~IXGBE_RXCTRL_RXEN;
37006f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
37016f37f232SEric Joyner }
37026f37f232SEric Joyner }
37036f37f232SEric Joyner }
37046f37f232SEric Joyner }
37056f37f232SEric Joyner
37066f37f232SEric Joyner /**
3707edef2769SRadoslaw Tyl * ixgbe_enter_lplu_t_x550em - Transition to low power states
37086f37f232SEric Joyner * @hw: pointer to hardware structure
37096f37f232SEric Joyner *
37106f37f232SEric Joyner * Configures Low Power Link Up on transition to low power states
37116f37f232SEric Joyner * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting the
37126f37f232SEric Joyner * X557 PHY immediately prior to entering LPLU.
37136f37f232SEric Joyner **/
ixgbe_enter_lplu_t_x550em(struct ixgbe_hw * hw)37146f37f232SEric Joyner s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
37156f37f232SEric Joyner {
37166f37f232SEric Joyner u16 an_10g_cntl_reg, autoneg_reg, speed;
37176f37f232SEric Joyner s32 status;
37186f37f232SEric Joyner ixgbe_link_speed lcd_speed;
37196f37f232SEric Joyner u32 save_autoneg;
37206f37f232SEric Joyner bool link_up;
37216f37f232SEric Joyner
3722a9ca1c79SSean Bruno /* SW LPLU not required on later HW revisions. */
37238eb6488eSEric Joyner if ((hw->mac.type == ixgbe_mac_X550EM_x) &&
37248eb6488eSEric Joyner (IXGBE_FUSES0_REV_MASK &
37258eb6488eSEric Joyner IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))))
3726a9ca1c79SSean Bruno return IXGBE_SUCCESS;
3727a9ca1c79SSean Bruno
37286f37f232SEric Joyner /* If blocked by MNG FW, then don't restart AN */
37296f37f232SEric Joyner if (ixgbe_check_reset_blocked(hw))
37306f37f232SEric Joyner return IXGBE_SUCCESS;
37316f37f232SEric Joyner
37326f37f232SEric Joyner status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
37336f37f232SEric Joyner if (status != IXGBE_SUCCESS)
37346f37f232SEric Joyner return status;
37356f37f232SEric Joyner
37366f37f232SEric Joyner status = ixgbe_read_eeprom(hw, NVM_INIT_CTRL_3, &hw->eeprom.ctrl_word_3);
37376f37f232SEric Joyner
37386f37f232SEric Joyner if (status != IXGBE_SUCCESS)
37396f37f232SEric Joyner return status;
37406f37f232SEric Joyner
37416f37f232SEric Joyner /* If link is down, LPLU disabled in NVM, WoL disabled, or manageability
37426f37f232SEric Joyner * disabled, then force link down by entering low power mode.
37436f37f232SEric Joyner */
37446f37f232SEric Joyner if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
37456f37f232SEric Joyner !(hw->wol_enabled || ixgbe_mng_present(hw)))
374679b36ec9SKevin Bowling return ixgbe_set_copper_phy_power(hw, false);
37476f37f232SEric Joyner
37486f37f232SEric Joyner /* Determine LCD */
37496f37f232SEric Joyner status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed);
37506f37f232SEric Joyner
37516f37f232SEric Joyner if (status != IXGBE_SUCCESS)
37526f37f232SEric Joyner return status;
37536f37f232SEric Joyner
37546f37f232SEric Joyner /* If no valid LCD link speed, then force link down and exit. */
37556f37f232SEric Joyner if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN)
375679b36ec9SKevin Bowling return ixgbe_set_copper_phy_power(hw, false);
37576f37f232SEric Joyner
37586f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
37596f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
37606f37f232SEric Joyner &speed);
37616f37f232SEric Joyner
37626f37f232SEric Joyner if (status != IXGBE_SUCCESS)
37636f37f232SEric Joyner return status;
37646f37f232SEric Joyner
37656f37f232SEric Joyner /* If no link now, speed is invalid so take link down */
37666f37f232SEric Joyner status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
37676f37f232SEric Joyner if (status != IXGBE_SUCCESS)
376879b36ec9SKevin Bowling return ixgbe_set_copper_phy_power(hw, false);
37696f37f232SEric Joyner
37706f37f232SEric Joyner /* clear everything but the speed bits */
37716f37f232SEric Joyner speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK;
37726f37f232SEric Joyner
37736f37f232SEric Joyner /* If current speed is already LCD, then exit. */
37746f37f232SEric Joyner if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) &&
37756f37f232SEric Joyner (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) ||
37766f37f232SEric Joyner ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) &&
37776f37f232SEric Joyner (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL)))
37786f37f232SEric Joyner return status;
37796f37f232SEric Joyner
37806f37f232SEric Joyner /* Clear AN completed indication */
37816f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
37826f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
37836f37f232SEric Joyner &autoneg_reg);
37846f37f232SEric Joyner
37856f37f232SEric Joyner if (status != IXGBE_SUCCESS)
37866f37f232SEric Joyner return status;
37876f37f232SEric Joyner
37886f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
37896f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
37906f37f232SEric Joyner &an_10g_cntl_reg);
37916f37f232SEric Joyner
37926f37f232SEric Joyner if (status != IXGBE_SUCCESS)
37936f37f232SEric Joyner return status;
37946f37f232SEric Joyner
37956f37f232SEric Joyner status = hw->phy.ops.read_reg(hw,
37966f37f232SEric Joyner IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
37976f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
37986f37f232SEric Joyner &autoneg_reg);
37996f37f232SEric Joyner
38006f37f232SEric Joyner if (status != IXGBE_SUCCESS)
38016f37f232SEric Joyner return status;
38026f37f232SEric Joyner
38036f37f232SEric Joyner save_autoneg = hw->phy.autoneg_advertised;
38046f37f232SEric Joyner
38056f37f232SEric Joyner /* Setup link at least common link speed */
380679b36ec9SKevin Bowling status = hw->mac.ops.setup_link(hw, lcd_speed, false);
38076f37f232SEric Joyner
38086f37f232SEric Joyner /* restore autoneg from before setting lplu speed */
38096f37f232SEric Joyner hw->phy.autoneg_advertised = save_autoneg;
38106f37f232SEric Joyner
38116f37f232SEric Joyner return status;
38126f37f232SEric Joyner }
38136f37f232SEric Joyner
38146f37f232SEric Joyner /**
3815edef2769SRadoslaw Tyl * ixgbe_get_lcd_t_x550em - Determine lowest common denominator
38166f37f232SEric Joyner * @hw: pointer to hardware structure
38176f37f232SEric Joyner * @lcd_speed: pointer to lowest common link speed
38186f37f232SEric Joyner *
38196f37f232SEric Joyner * Determine lowest common link speed with link partner.
38206f37f232SEric Joyner **/
ixgbe_get_lcd_t_x550em(struct ixgbe_hw * hw,ixgbe_link_speed * lcd_speed)38216f37f232SEric Joyner s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed)
38226f37f232SEric Joyner {
38236f37f232SEric Joyner u16 an_lp_status;
38246f37f232SEric Joyner s32 status;
38256f37f232SEric Joyner u16 word = hw->eeprom.ctrl_word_3;
38266f37f232SEric Joyner
38276f37f232SEric Joyner *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
38286f37f232SEric Joyner
38296f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
38306f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
38316f37f232SEric Joyner &an_lp_status);
38326f37f232SEric Joyner
38336f37f232SEric Joyner if (status != IXGBE_SUCCESS)
38346f37f232SEric Joyner return status;
38356f37f232SEric Joyner
38366f37f232SEric Joyner /* If link partner advertised 1G, return 1G */
38376f37f232SEric Joyner if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) {
38386f37f232SEric Joyner *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL;
38396f37f232SEric Joyner return status;
38406f37f232SEric Joyner }
38416f37f232SEric Joyner
38426f37f232SEric Joyner /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */
38436f37f232SEric Joyner if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) ||
38446f37f232SEric Joyner (word & NVM_INIT_CTRL_3_D10GMP_PORT0))
38456f37f232SEric Joyner return status;
38466f37f232SEric Joyner
38476f37f232SEric Joyner /* Link partner not capable of lower speeds, return 10G */
38486f37f232SEric Joyner *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL;
38496f37f232SEric Joyner return status;
38506f37f232SEric Joyner }
38516f37f232SEric Joyner
38526f37f232SEric Joyner /**
38536f37f232SEric Joyner * ixgbe_setup_fc_X550em - Set up flow control
38546f37f232SEric Joyner * @hw: pointer to hardware structure
38556f37f232SEric Joyner *
38566f37f232SEric Joyner * Called at init time to set up flow control.
38576f37f232SEric Joyner **/
ixgbe_setup_fc_X550em(struct ixgbe_hw * hw)38586f37f232SEric Joyner s32 ixgbe_setup_fc_X550em(struct ixgbe_hw *hw)
38596f37f232SEric Joyner {
38606f37f232SEric Joyner s32 ret_val = IXGBE_SUCCESS;
38616f37f232SEric Joyner u32 pause, asm_dir, reg_val;
38626f37f232SEric Joyner
38636f37f232SEric Joyner DEBUGFUNC("ixgbe_setup_fc_X550em");
38646f37f232SEric Joyner
38656f37f232SEric Joyner /* Validate the requested mode */
38666f37f232SEric Joyner if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
38676f37f232SEric Joyner ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
38686f37f232SEric Joyner "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
38696f37f232SEric Joyner ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
38706f37f232SEric Joyner goto out;
38716f37f232SEric Joyner }
38726f37f232SEric Joyner
38736f37f232SEric Joyner /* 10gig parts do not have a word in the EEPROM to determine the
38746f37f232SEric Joyner * default flow control setting, so we explicitly set it to full.
38756f37f232SEric Joyner */
38766f37f232SEric Joyner if (hw->fc.requested_mode == ixgbe_fc_default)
38776f37f232SEric Joyner hw->fc.requested_mode = ixgbe_fc_full;
38786f37f232SEric Joyner
38796f37f232SEric Joyner /* Determine PAUSE and ASM_DIR bits. */
38806f37f232SEric Joyner switch (hw->fc.requested_mode) {
38816f37f232SEric Joyner case ixgbe_fc_none:
38826f37f232SEric Joyner pause = 0;
38836f37f232SEric Joyner asm_dir = 0;
38846f37f232SEric Joyner break;
38856f37f232SEric Joyner case ixgbe_fc_tx_pause:
38866f37f232SEric Joyner pause = 0;
38876f37f232SEric Joyner asm_dir = 1;
38886f37f232SEric Joyner break;
38896f37f232SEric Joyner case ixgbe_fc_rx_pause:
38906f37f232SEric Joyner /* Rx Flow control is enabled and Tx Flow control is
38916f37f232SEric Joyner * disabled by software override. Since there really
38926f37f232SEric Joyner * isn't a way to advertise that we are capable of RX
38936f37f232SEric Joyner * Pause ONLY, we will advertise that we support both
38946f37f232SEric Joyner * symmetric and asymmetric Rx PAUSE, as such we fall
38956f37f232SEric Joyner * through to the fc_full statement. Later, we will
38966f37f232SEric Joyner * disable the adapter's ability to send PAUSE frames.
38976f37f232SEric Joyner */
38986f37f232SEric Joyner case ixgbe_fc_full:
38996f37f232SEric Joyner pause = 1;
39006f37f232SEric Joyner asm_dir = 1;
39016f37f232SEric Joyner break;
39026f37f232SEric Joyner default:
39036f37f232SEric Joyner ERROR_REPORT1(IXGBE_ERROR_ARGUMENT,
39046f37f232SEric Joyner "Flow control param set incorrectly\n");
39056f37f232SEric Joyner ret_val = IXGBE_ERR_CONFIG;
39066f37f232SEric Joyner goto out;
39076f37f232SEric Joyner }
39086f37f232SEric Joyner
39098eb6488eSEric Joyner switch (hw->device_id) {
39108eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_X_KR:
39118eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_KR:
39128eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_KR_L:
39138eb6488eSEric Joyner ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
39146f37f232SEric Joyner IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
39156f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
39166f37f232SEric Joyner if (ret_val != IXGBE_SUCCESS)
39176f37f232SEric Joyner goto out;
39186f37f232SEric Joyner reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
39196f37f232SEric Joyner IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
39206f37f232SEric Joyner if (pause)
39216f37f232SEric Joyner reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
39226f37f232SEric Joyner if (asm_dir)
39236f37f232SEric Joyner reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
39248eb6488eSEric Joyner ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
39256f37f232SEric Joyner IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
39266f37f232SEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
39276f37f232SEric Joyner
3928a9ca1c79SSean Bruno /* This device does not fully support AN. */
392979b36ec9SKevin Bowling hw->fc.disable_fc_autoneg = true;
39308eb6488eSEric Joyner break;
39318eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_X_XFI:
393279b36ec9SKevin Bowling hw->fc.disable_fc_autoneg = true;
39338eb6488eSEric Joyner break;
39348eb6488eSEric Joyner default:
39358eb6488eSEric Joyner break;
39366f37f232SEric Joyner }
39376f37f232SEric Joyner
39386f37f232SEric Joyner out:
39396f37f232SEric Joyner return ret_val;
39406f37f232SEric Joyner }
39416f37f232SEric Joyner
39426f37f232SEric Joyner /**
39438eb6488eSEric Joyner * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37
39448eb6488eSEric Joyner * @hw: pointer to hardware structure
39458eb6488eSEric Joyner *
39468eb6488eSEric Joyner * Enable flow control according to IEEE clause 37.
39478eb6488eSEric Joyner **/
ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw * hw)39488eb6488eSEric Joyner void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
39498eb6488eSEric Joyner {
39508eb6488eSEric Joyner u32 link_s1, lp_an_page_low, an_cntl_1;
39518eb6488eSEric Joyner s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
39528eb6488eSEric Joyner ixgbe_link_speed speed;
39538eb6488eSEric Joyner bool link_up;
39548eb6488eSEric Joyner
39558eb6488eSEric Joyner /* AN should have completed when the cable was plugged in.
39568eb6488eSEric Joyner * Look for reasons to bail out. Bail out if:
39578eb6488eSEric Joyner * - FC autoneg is disabled, or if
39588eb6488eSEric Joyner * - link is not up.
39598eb6488eSEric Joyner */
39608eb6488eSEric Joyner if (hw->fc.disable_fc_autoneg) {
39618eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
39628eb6488eSEric Joyner "Flow control autoneg is disabled");
39638eb6488eSEric Joyner goto out;
39648eb6488eSEric Joyner }
39658eb6488eSEric Joyner
396679b36ec9SKevin Bowling hw->mac.ops.check_link(hw, &speed, &link_up, false);
39678eb6488eSEric Joyner if (!link_up) {
39688eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down");
39698eb6488eSEric Joyner goto out;
39708eb6488eSEric Joyner }
39718eb6488eSEric Joyner
39728eb6488eSEric Joyner /* Check at auto-negotiation has completed */
39738eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
39748eb6488eSEric Joyner IXGBE_KRM_LINK_S1(hw->bus.lan_id),
39758eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1);
39768eb6488eSEric Joyner
39778eb6488eSEric Joyner if (status != IXGBE_SUCCESS ||
39788eb6488eSEric Joyner (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
39798eb6488eSEric Joyner DEBUGOUT("Auto-Negotiation did not complete\n");
39808eb6488eSEric Joyner status = IXGBE_ERR_FC_NOT_NEGOTIATED;
39818eb6488eSEric Joyner goto out;
39828eb6488eSEric Joyner }
39838eb6488eSEric Joyner
39848eb6488eSEric Joyner /* Read the 10g AN autoc and LP ability registers and resolve
39858eb6488eSEric Joyner * local flow control settings accordingly
39868eb6488eSEric Joyner */
39878eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
39888eb6488eSEric Joyner IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
39898eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1);
39908eb6488eSEric Joyner
39918eb6488eSEric Joyner if (status != IXGBE_SUCCESS) {
39928eb6488eSEric Joyner DEBUGOUT("Auto-Negotiation did not complete\n");
39938eb6488eSEric Joyner goto out;
39948eb6488eSEric Joyner }
39958eb6488eSEric Joyner
39968eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
39978eb6488eSEric Joyner IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id),
39988eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low);
39998eb6488eSEric Joyner
40008eb6488eSEric Joyner if (status != IXGBE_SUCCESS) {
40018eb6488eSEric Joyner DEBUGOUT("Auto-Negotiation did not complete\n");
40028eb6488eSEric Joyner goto out;
40038eb6488eSEric Joyner }
40048eb6488eSEric Joyner
40058eb6488eSEric Joyner status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low,
40068eb6488eSEric Joyner IXGBE_KRM_AN_CNTL_1_SYM_PAUSE,
40078eb6488eSEric Joyner IXGBE_KRM_AN_CNTL_1_ASM_PAUSE,
40088eb6488eSEric Joyner IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE,
40098eb6488eSEric Joyner IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE);
40108eb6488eSEric Joyner
40118eb6488eSEric Joyner out:
40128eb6488eSEric Joyner if (status == IXGBE_SUCCESS) {
401379b36ec9SKevin Bowling hw->fc.fc_was_autonegged = true;
40148eb6488eSEric Joyner } else {
401579b36ec9SKevin Bowling hw->fc.fc_was_autonegged = false;
40168eb6488eSEric Joyner hw->fc.current_mode = hw->fc.requested_mode;
40178eb6488eSEric Joyner }
40188eb6488eSEric Joyner }
40198eb6488eSEric Joyner
40208eb6488eSEric Joyner /**
40218eb6488eSEric Joyner * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings
40228eb6488eSEric Joyner * @hw: pointer to hardware structure
40238eb6488eSEric Joyner *
40248eb6488eSEric Joyner **/
ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw * hw)40258eb6488eSEric Joyner void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw)
40268eb6488eSEric Joyner {
402779b36ec9SKevin Bowling hw->fc.fc_was_autonegged = false;
40288eb6488eSEric Joyner hw->fc.current_mode = hw->fc.requested_mode;
40298eb6488eSEric Joyner }
40308eb6488eSEric Joyner
40318eb6488eSEric Joyner /**
40328eb6488eSEric Joyner * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37
40338eb6488eSEric Joyner * @hw: pointer to hardware structure
40348eb6488eSEric Joyner *
40358eb6488eSEric Joyner * Enable flow control according to IEEE clause 37.
40368eb6488eSEric Joyner **/
ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw * hw)40378eb6488eSEric Joyner void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)
40388eb6488eSEric Joyner {
40398eb6488eSEric Joyner s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
40408eb6488eSEric Joyner u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
40418eb6488eSEric Joyner ixgbe_link_speed speed;
40428eb6488eSEric Joyner bool link_up;
40438eb6488eSEric Joyner
40448eb6488eSEric Joyner /* AN should have completed when the cable was plugged in.
40458eb6488eSEric Joyner * Look for reasons to bail out. Bail out if:
40468eb6488eSEric Joyner * - FC autoneg is disabled, or if
40478eb6488eSEric Joyner * - link is not up.
40488eb6488eSEric Joyner */
40498eb6488eSEric Joyner if (hw->fc.disable_fc_autoneg) {
40508eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
40518eb6488eSEric Joyner "Flow control autoneg is disabled");
40528eb6488eSEric Joyner goto out;
40538eb6488eSEric Joyner }
40548eb6488eSEric Joyner
405579b36ec9SKevin Bowling hw->mac.ops.check_link(hw, &speed, &link_up, false);
40568eb6488eSEric Joyner if (!link_up) {
40578eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down");
40588eb6488eSEric Joyner goto out;
40598eb6488eSEric Joyner }
40608eb6488eSEric Joyner
40618eb6488eSEric Joyner /* Check if auto-negotiation has completed */
40628eb6488eSEric Joyner status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info);
40638eb6488eSEric Joyner if (status != IXGBE_SUCCESS ||
40648eb6488eSEric Joyner !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) {
40658eb6488eSEric Joyner DEBUGOUT("Auto-Negotiation did not complete\n");
40668eb6488eSEric Joyner status = IXGBE_ERR_FC_NOT_NEGOTIATED;
40678eb6488eSEric Joyner goto out;
40688eb6488eSEric Joyner }
40698eb6488eSEric Joyner
40708eb6488eSEric Joyner /* Negotiate the flow control */
40718eb6488eSEric Joyner status = ixgbe_negotiate_fc(hw, info[0], info[0],
40728eb6488eSEric Joyner FW_PHY_ACT_GET_LINK_INFO_FC_RX,
40738eb6488eSEric Joyner FW_PHY_ACT_GET_LINK_INFO_FC_TX,
40748eb6488eSEric Joyner FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX,
40758eb6488eSEric Joyner FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX);
40768eb6488eSEric Joyner
40778eb6488eSEric Joyner out:
40788eb6488eSEric Joyner if (status == IXGBE_SUCCESS) {
407979b36ec9SKevin Bowling hw->fc.fc_was_autonegged = true;
40808eb6488eSEric Joyner } else {
408179b36ec9SKevin Bowling hw->fc.fc_was_autonegged = false;
40828eb6488eSEric Joyner hw->fc.current_mode = hw->fc.requested_mode;
40838eb6488eSEric Joyner }
40848eb6488eSEric Joyner }
40858eb6488eSEric Joyner
40868eb6488eSEric Joyner /**
40878eb6488eSEric Joyner * ixgbe_setup_fc_backplane_x550em_a - Set up flow control
40888eb6488eSEric Joyner * @hw: pointer to hardware structure
40898eb6488eSEric Joyner *
40908eb6488eSEric Joyner * Called at init time to set up flow control.
40918eb6488eSEric Joyner **/
ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw * hw)40928eb6488eSEric Joyner s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw)
40938eb6488eSEric Joyner {
40948eb6488eSEric Joyner s32 status = IXGBE_SUCCESS;
40958eb6488eSEric Joyner u32 an_cntl = 0;
40968eb6488eSEric Joyner
40978eb6488eSEric Joyner DEBUGFUNC("ixgbe_setup_fc_backplane_x550em_a");
40988eb6488eSEric Joyner
40998eb6488eSEric Joyner /* Validate the requested mode */
41008eb6488eSEric Joyner if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
41018eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
41028eb6488eSEric Joyner "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
41038eb6488eSEric Joyner return IXGBE_ERR_INVALID_LINK_SETTINGS;
41048eb6488eSEric Joyner }
41058eb6488eSEric Joyner
41068eb6488eSEric Joyner if (hw->fc.requested_mode == ixgbe_fc_default)
41078eb6488eSEric Joyner hw->fc.requested_mode = ixgbe_fc_full;
41088eb6488eSEric Joyner
41098eb6488eSEric Joyner /* Set up the 1G and 10G flow control advertisement registers so the
41108eb6488eSEric Joyner * HW will be able to do FC autoneg once the cable is plugged in. If
41118eb6488eSEric Joyner * we link at 10G, the 1G advertisement is harmless and vice versa.
41128eb6488eSEric Joyner */
41138eb6488eSEric Joyner status = hw->mac.ops.read_iosf_sb_reg(hw,
41148eb6488eSEric Joyner IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
41158eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl);
41168eb6488eSEric Joyner
41178eb6488eSEric Joyner if (status != IXGBE_SUCCESS) {
41188eb6488eSEric Joyner DEBUGOUT("Auto-Negotiation did not complete\n");
41198eb6488eSEric Joyner return status;
41208eb6488eSEric Joyner }
41218eb6488eSEric Joyner
41228eb6488eSEric Joyner /* The possible values of fc.requested_mode are:
41238eb6488eSEric Joyner * 0: Flow control is completely disabled
41248eb6488eSEric Joyner * 1: Rx flow control is enabled (we can receive pause frames,
41258eb6488eSEric Joyner * but not send pause frames).
41268eb6488eSEric Joyner * 2: Tx flow control is enabled (we can send pause frames but
41278eb6488eSEric Joyner * we do not support receiving pause frames).
41288eb6488eSEric Joyner * 3: Both Rx and Tx flow control (symmetric) are enabled.
41298eb6488eSEric Joyner * other: Invalid.
41308eb6488eSEric Joyner */
41318eb6488eSEric Joyner switch (hw->fc.requested_mode) {
41328eb6488eSEric Joyner case ixgbe_fc_none:
41338eb6488eSEric Joyner /* Flow control completely disabled by software override. */
41348eb6488eSEric Joyner an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
41358eb6488eSEric Joyner IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
41368eb6488eSEric Joyner break;
41378eb6488eSEric Joyner case ixgbe_fc_tx_pause:
41388eb6488eSEric Joyner /* Tx Flow control is enabled, and Rx Flow control is
41398eb6488eSEric Joyner * disabled by software override.
41408eb6488eSEric Joyner */
41418eb6488eSEric Joyner an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
41428eb6488eSEric Joyner an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
41438eb6488eSEric Joyner break;
41448eb6488eSEric Joyner case ixgbe_fc_rx_pause:
41458eb6488eSEric Joyner /* Rx Flow control is enabled and Tx Flow control is
41468eb6488eSEric Joyner * disabled by software override. Since there really
41478eb6488eSEric Joyner * isn't a way to advertise that we are capable of RX
41488eb6488eSEric Joyner * Pause ONLY, we will advertise that we support both
41498eb6488eSEric Joyner * symmetric and asymmetric Rx PAUSE, as such we fall
41508eb6488eSEric Joyner * through to the fc_full statement. Later, we will
41518eb6488eSEric Joyner * disable the adapter's ability to send PAUSE frames.
41528eb6488eSEric Joyner */
41538eb6488eSEric Joyner case ixgbe_fc_full:
41548eb6488eSEric Joyner /* Flow control (both Rx and Tx) is enabled by SW override. */
41558eb6488eSEric Joyner an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
41568eb6488eSEric Joyner IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
41578eb6488eSEric Joyner break;
41588eb6488eSEric Joyner default:
41598eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_ARGUMENT,
41608eb6488eSEric Joyner "Flow control param set incorrectly\n");
41618eb6488eSEric Joyner return IXGBE_ERR_CONFIG;
41628eb6488eSEric Joyner }
41638eb6488eSEric Joyner
41648eb6488eSEric Joyner status = hw->mac.ops.write_iosf_sb_reg(hw,
41658eb6488eSEric Joyner IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
41668eb6488eSEric Joyner IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl);
41678eb6488eSEric Joyner
41688eb6488eSEric Joyner /* Restart auto-negotiation. */
41698eb6488eSEric Joyner status = ixgbe_restart_an_internal_phy_x550em(hw);
41708eb6488eSEric Joyner
41718eb6488eSEric Joyner return status;
41728eb6488eSEric Joyner }
41738eb6488eSEric Joyner
41748eb6488eSEric Joyner /**
41756f37f232SEric Joyner * ixgbe_set_mux - Set mux for port 1 access with CS4227
41766f37f232SEric Joyner * @hw: pointer to hardware structure
41776f37f232SEric Joyner * @state: set mux if 1, clear if 0
41786f37f232SEric Joyner */
ixgbe_set_mux(struct ixgbe_hw * hw,u8 state)41796f37f232SEric Joyner static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state)
41806f37f232SEric Joyner {
41816f37f232SEric Joyner u32 esdp;
41826f37f232SEric Joyner
41836f37f232SEric Joyner if (!hw->bus.lan_id)
41846f37f232SEric Joyner return;
41856f37f232SEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
41866f37f232SEric Joyner if (state)
41876f37f232SEric Joyner esdp |= IXGBE_ESDP_SDP1;
41886f37f232SEric Joyner else
41896f37f232SEric Joyner esdp &= ~IXGBE_ESDP_SDP1;
41906f37f232SEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
41916f37f232SEric Joyner IXGBE_WRITE_FLUSH(hw);
41926f37f232SEric Joyner }
41936f37f232SEric Joyner
41946f37f232SEric Joyner /**
41956f37f232SEric Joyner * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore
41966f37f232SEric Joyner * @hw: pointer to hardware structure
41976f37f232SEric Joyner * @mask: Mask to specify which semaphore to acquire
41986f37f232SEric Joyner *
41996f37f232SEric Joyner * Acquires the SWFW semaphore and sets the I2C MUX
42006f37f232SEric Joyner **/
ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw * hw,u32 mask)42016f37f232SEric Joyner s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
42026f37f232SEric Joyner {
42036f37f232SEric Joyner s32 status;
42046f37f232SEric Joyner
42056f37f232SEric Joyner DEBUGFUNC("ixgbe_acquire_swfw_sync_X550em");
42066f37f232SEric Joyner
42076f37f232SEric Joyner status = ixgbe_acquire_swfw_sync_X540(hw, mask);
42086f37f232SEric Joyner if (status)
42096f37f232SEric Joyner return status;
42106f37f232SEric Joyner
42116f37f232SEric Joyner if (mask & IXGBE_GSSR_I2C_MASK)
42126f37f232SEric Joyner ixgbe_set_mux(hw, 1);
42136f37f232SEric Joyner
42146f37f232SEric Joyner return IXGBE_SUCCESS;
42156f37f232SEric Joyner }
42166f37f232SEric Joyner
42176f37f232SEric Joyner /**
42186f37f232SEric Joyner * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore
42196f37f232SEric Joyner * @hw: pointer to hardware structure
42206f37f232SEric Joyner * @mask: Mask to specify which semaphore to release
42216f37f232SEric Joyner *
42226f37f232SEric Joyner * Releases the SWFW semaphore and sets the I2C MUX
42236f37f232SEric Joyner **/
ixgbe_release_swfw_sync_X550em(struct ixgbe_hw * hw,u32 mask)42246f37f232SEric Joyner void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
42256f37f232SEric Joyner {
42266f37f232SEric Joyner DEBUGFUNC("ixgbe_release_swfw_sync_X550em");
42276f37f232SEric Joyner
42286f37f232SEric Joyner if (mask & IXGBE_GSSR_I2C_MASK)
42296f37f232SEric Joyner ixgbe_set_mux(hw, 0);
42306f37f232SEric Joyner
42316f37f232SEric Joyner ixgbe_release_swfw_sync_X540(hw, mask);
42326f37f232SEric Joyner }
42336f37f232SEric Joyner
42346f37f232SEric Joyner /**
42358eb6488eSEric Joyner * ixgbe_acquire_swfw_sync_X550a - Acquire SWFW semaphore
42368eb6488eSEric Joyner * @hw: pointer to hardware structure
42378eb6488eSEric Joyner * @mask: Mask to specify which semaphore to acquire
42388eb6488eSEric Joyner *
42398eb6488eSEric Joyner * Acquires the SWFW semaphore and get the shared phy token as needed
42408eb6488eSEric Joyner */
ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw * hw,u32 mask)42418eb6488eSEric Joyner static s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *hw, u32 mask)
42428eb6488eSEric Joyner {
42438eb6488eSEric Joyner u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
42448eb6488eSEric Joyner int retries = FW_PHY_TOKEN_RETRIES;
42458eb6488eSEric Joyner s32 status = IXGBE_SUCCESS;
42468eb6488eSEric Joyner
42478eb6488eSEric Joyner DEBUGFUNC("ixgbe_acquire_swfw_sync_X550a");
42488eb6488eSEric Joyner
42498eb6488eSEric Joyner status = IXGBE_SUCCESS;
42508eb6488eSEric Joyner if (hmask)
42518eb6488eSEric Joyner status = ixgbe_acquire_swfw_sync_X540(hw, hmask);
4252cc994418SBarbara Skobiej
42538eb6488eSEric Joyner if (status) {
4254cc994418SBarbara Skobiej DEBUGOUT1("Could not acquire SWFW semaphore, Status = %d\n", status);
42558eb6488eSEric Joyner return status;
42568eb6488eSEric Joyner }
4257cc994418SBarbara Skobiej
42588eb6488eSEric Joyner if (!(mask & IXGBE_GSSR_TOKEN_SM))
42598eb6488eSEric Joyner return IXGBE_SUCCESS;
42608eb6488eSEric Joyner
4261cc994418SBarbara Skobiej while (--retries) {
42628eb6488eSEric Joyner status = ixgbe_get_phy_token(hw);
42638eb6488eSEric Joyner
42648eb6488eSEric Joyner if (status == IXGBE_SUCCESS)
42658eb6488eSEric Joyner return IXGBE_SUCCESS;
42668eb6488eSEric Joyner
4267cc994418SBarbara Skobiej if (status != IXGBE_ERR_TOKEN_RETRY) {
4268cc994418SBarbara Skobiej DEBUGOUT1("Retry acquiring the PHY token failed, Status = %d\n", status);
42698eb6488eSEric Joyner if (hmask)
42708eb6488eSEric Joyner ixgbe_release_swfw_sync_X540(hw, hmask);
42718eb6488eSEric Joyner return status;
42728eb6488eSEric Joyner }
4273cc994418SBarbara Skobiej
4274cc994418SBarbara Skobiej if (status == IXGBE_ERR_TOKEN_RETRY)
4275cc994418SBarbara Skobiej DEBUGOUT1("Could not acquire PHY token, Status = %d\n",
4276cc994418SBarbara Skobiej status);
42778eb6488eSEric Joyner }
42788eb6488eSEric Joyner
4279cc994418SBarbara Skobiej if (hmask)
4280cc994418SBarbara Skobiej ixgbe_release_swfw_sync_X540(hw, hmask);
4281cc994418SBarbara Skobiej
42828eb6488eSEric Joyner DEBUGOUT1("Semaphore acquisition retries failed!: PHY ID = 0x%08X\n",
42838eb6488eSEric Joyner hw->phy.id);
42848eb6488eSEric Joyner return status;
42858eb6488eSEric Joyner }
42868eb6488eSEric Joyner
42878eb6488eSEric Joyner /**
42888eb6488eSEric Joyner * ixgbe_release_swfw_sync_X550a - Release SWFW semaphore
42898eb6488eSEric Joyner * @hw: pointer to hardware structure
42908eb6488eSEric Joyner * @mask: Mask to specify which semaphore to release
42918eb6488eSEric Joyner *
42928eb6488eSEric Joyner * Releases the SWFW semaphore and puts the shared phy token as needed
42938eb6488eSEric Joyner */
ixgbe_release_swfw_sync_X550a(struct ixgbe_hw * hw,u32 mask)42948eb6488eSEric Joyner static void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *hw, u32 mask)
42958eb6488eSEric Joyner {
42968eb6488eSEric Joyner u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
42978eb6488eSEric Joyner
42988eb6488eSEric Joyner DEBUGFUNC("ixgbe_release_swfw_sync_X550a");
42998eb6488eSEric Joyner
43008eb6488eSEric Joyner if (mask & IXGBE_GSSR_TOKEN_SM)
43018eb6488eSEric Joyner ixgbe_put_phy_token(hw);
43028eb6488eSEric Joyner
43038eb6488eSEric Joyner if (hmask)
43048eb6488eSEric Joyner ixgbe_release_swfw_sync_X540(hw, hmask);
43058eb6488eSEric Joyner }
43068eb6488eSEric Joyner
43078eb6488eSEric Joyner /**
43088eb6488eSEric Joyner * ixgbe_read_phy_reg_x550a - Reads specified PHY register
43098eb6488eSEric Joyner * @hw: pointer to hardware structure
43108eb6488eSEric Joyner * @reg_addr: 32 bit address of PHY register to read
43117d48aa4cSEric Joyner * @device_type: 5 bit device type
43128eb6488eSEric Joyner * @phy_data: Pointer to read data from PHY register
43138eb6488eSEric Joyner *
43148eb6488eSEric Joyner * Reads a value from a specified PHY register using the SWFW lock and PHY
43158eb6488eSEric Joyner * Token. The PHY Token is needed since the MDIO is shared between to MAC
43168eb6488eSEric Joyner * instances.
43178eb6488eSEric Joyner **/
ixgbe_read_phy_reg_x550a(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)43188eb6488eSEric Joyner s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
43198eb6488eSEric Joyner u32 device_type, u16 *phy_data)
43208eb6488eSEric Joyner {
43218eb6488eSEric Joyner s32 status;
43228eb6488eSEric Joyner u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
43238eb6488eSEric Joyner
43248eb6488eSEric Joyner DEBUGFUNC("ixgbe_read_phy_reg_x550a");
43258eb6488eSEric Joyner
43268eb6488eSEric Joyner if (hw->mac.ops.acquire_swfw_sync(hw, mask))
43278eb6488eSEric Joyner return IXGBE_ERR_SWFW_SYNC;
43288eb6488eSEric Joyner
43298eb6488eSEric Joyner status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data);
43308eb6488eSEric Joyner
43318eb6488eSEric Joyner hw->mac.ops.release_swfw_sync(hw, mask);
43328eb6488eSEric Joyner
43338eb6488eSEric Joyner return status;
43348eb6488eSEric Joyner }
43358eb6488eSEric Joyner
43368eb6488eSEric Joyner /**
43378eb6488eSEric Joyner * ixgbe_write_phy_reg_x550a - Writes specified PHY register
43388eb6488eSEric Joyner * @hw: pointer to hardware structure
43398eb6488eSEric Joyner * @reg_addr: 32 bit PHY register to write
43408eb6488eSEric Joyner * @device_type: 5 bit device type
43418eb6488eSEric Joyner * @phy_data: Data to write to the PHY register
43428eb6488eSEric Joyner *
43438eb6488eSEric Joyner * Writes a value to specified PHY register using the SWFW lock and PHY Token.
43448eb6488eSEric Joyner * The PHY Token is needed since the MDIO is shared between to MAC instances.
43458eb6488eSEric Joyner **/
ixgbe_write_phy_reg_x550a(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)43468eb6488eSEric Joyner s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
43478eb6488eSEric Joyner u32 device_type, u16 phy_data)
43488eb6488eSEric Joyner {
43498eb6488eSEric Joyner s32 status;
43508eb6488eSEric Joyner u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
43518eb6488eSEric Joyner
43528eb6488eSEric Joyner DEBUGFUNC("ixgbe_write_phy_reg_x550a");
43538eb6488eSEric Joyner
43548eb6488eSEric Joyner if (hw->mac.ops.acquire_swfw_sync(hw, mask) == IXGBE_SUCCESS) {
43558eb6488eSEric Joyner status = hw->phy.ops.write_reg_mdi(hw, reg_addr, device_type,
43568eb6488eSEric Joyner phy_data);
43578eb6488eSEric Joyner hw->mac.ops.release_swfw_sync(hw, mask);
43588eb6488eSEric Joyner } else {
43598eb6488eSEric Joyner status = IXGBE_ERR_SWFW_SYNC;
43608eb6488eSEric Joyner }
43618eb6488eSEric Joyner
43628eb6488eSEric Joyner return status;
43638eb6488eSEric Joyner }
43648eb6488eSEric Joyner
43658eb6488eSEric Joyner /**
43666f37f232SEric Joyner * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
43676f37f232SEric Joyner * @hw: pointer to hardware structure
43686f37f232SEric Joyner *
43696f37f232SEric Joyner * Handle external Base T PHY interrupt. If high temperature
43706f37f232SEric Joyner * failure alarm then return error, else if link status change
43716f37f232SEric Joyner * then setup internal/external PHY link
43726f37f232SEric Joyner *
43736f37f232SEric Joyner * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
43746f37f232SEric Joyner * failure alarm, else return PHY access status.
43756f37f232SEric Joyner */
ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw * hw)43766f37f232SEric Joyner s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
43776f37f232SEric Joyner {
43786f37f232SEric Joyner bool lsc;
43796f37f232SEric Joyner u32 status;
43806f37f232SEric Joyner
43816f37f232SEric Joyner status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
43826f37f232SEric Joyner
43836f37f232SEric Joyner if (status != IXGBE_SUCCESS)
43846f37f232SEric Joyner return status;
43856f37f232SEric Joyner
43866f37f232SEric Joyner if (lsc)
43876f37f232SEric Joyner return ixgbe_setup_internal_phy(hw);
43886f37f232SEric Joyner
43896f37f232SEric Joyner return IXGBE_SUCCESS;
43906f37f232SEric Joyner }
43916f37f232SEric Joyner
43926f37f232SEric Joyner /**
43936f37f232SEric Joyner * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
43946f37f232SEric Joyner * @hw: pointer to hardware structure
43956f37f232SEric Joyner * @speed: new link speed
439679b36ec9SKevin Bowling * @autoneg_wait_to_complete: true when waiting for completion is needed
43976f37f232SEric Joyner *
43986f37f232SEric Joyner * Setup internal/external PHY link speed based on link speed, then set
43996f37f232SEric Joyner * external PHY auto advertised link speed.
44006f37f232SEric Joyner *
44016f37f232SEric Joyner * Returns error status for any failure
44026f37f232SEric Joyner **/
ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)44036f37f232SEric Joyner s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
44046f37f232SEric Joyner ixgbe_link_speed speed,
44056f37f232SEric Joyner bool autoneg_wait_to_complete)
44066f37f232SEric Joyner {
44076f37f232SEric Joyner s32 status;
44086f37f232SEric Joyner ixgbe_link_speed force_speed;
4409d5bbb550SAshijeet Acharya u32 i;
4410d5bbb550SAshijeet Acharya bool link_up = false;
44116f37f232SEric Joyner
44126f37f232SEric Joyner DEBUGFUNC("ixgbe_setup_mac_link_t_X550em");
44136f37f232SEric Joyner
44146f37f232SEric Joyner /* Setup internal/external PHY link speed to iXFI (10G), unless
44156f37f232SEric Joyner * only 1G is auto advertised then setup KX link.
44166f37f232SEric Joyner */
44176f37f232SEric Joyner if (speed & IXGBE_LINK_SPEED_10GB_FULL)
44186f37f232SEric Joyner force_speed = IXGBE_LINK_SPEED_10GB_FULL;
44196f37f232SEric Joyner else
44206f37f232SEric Joyner force_speed = IXGBE_LINK_SPEED_1GB_FULL;
44216f37f232SEric Joyner
44228eb6488eSEric Joyner /* If X552 and internal link mode is XFI, then setup XFI internal link.
44238eb6488eSEric Joyner */
44248eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550EM_x &&
44258eb6488eSEric Joyner !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
44266f37f232SEric Joyner status = ixgbe_setup_ixfi_x550em(hw, &force_speed);
44276f37f232SEric Joyner
44286f37f232SEric Joyner if (status != IXGBE_SUCCESS)
44296f37f232SEric Joyner return status;
4430d5bbb550SAshijeet Acharya
4431d5bbb550SAshijeet Acharya /* Wait for the controller to acquire link */
4432d5bbb550SAshijeet Acharya for (i = 0; i < 10; i++) {
4433d5bbb550SAshijeet Acharya msec_delay(100);
4434d5bbb550SAshijeet Acharya
4435d5bbb550SAshijeet Acharya status = ixgbe_check_link(hw, &force_speed, &link_up,
4436d5bbb550SAshijeet Acharya false);
4437d5bbb550SAshijeet Acharya if (status != IXGBE_SUCCESS)
4438d5bbb550SAshijeet Acharya return status;
4439d5bbb550SAshijeet Acharya
4440d5bbb550SAshijeet Acharya if (link_up)
4441d5bbb550SAshijeet Acharya break;
4442d5bbb550SAshijeet Acharya }
44436f37f232SEric Joyner }
44446f37f232SEric Joyner
44456f37f232SEric Joyner return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete);
44466f37f232SEric Joyner }
44476f37f232SEric Joyner
44486f37f232SEric Joyner /**
44496f37f232SEric Joyner * ixgbe_check_link_t_X550em - Determine link and speed status
44506f37f232SEric Joyner * @hw: pointer to hardware structure
44516f37f232SEric Joyner * @speed: pointer to link speed
445279b36ec9SKevin Bowling * @link_up: true when link is up
44536f37f232SEric Joyner * @link_up_wait_to_complete: bool used to wait for link up or not
44546f37f232SEric Joyner *
44556f37f232SEric Joyner * Check that both the MAC and X557 external PHY have link.
44566f37f232SEric Joyner **/
ixgbe_check_link_t_X550em(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * link_up,bool link_up_wait_to_complete)44576f37f232SEric Joyner s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
44586f37f232SEric Joyner bool *link_up, bool link_up_wait_to_complete)
44596f37f232SEric Joyner {
44606f37f232SEric Joyner u32 status;
44618eb6488eSEric Joyner u16 i, autoneg_status = 0;
44626f37f232SEric Joyner
44636f37f232SEric Joyner if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
44646f37f232SEric Joyner return IXGBE_ERR_CONFIG;
44656f37f232SEric Joyner
44666f37f232SEric Joyner status = ixgbe_check_mac_link_generic(hw, speed, link_up,
44676f37f232SEric Joyner link_up_wait_to_complete);
44686f37f232SEric Joyner
44696f37f232SEric Joyner /* If check link fails or MAC link is not up, then return */
44706f37f232SEric Joyner if (status != IXGBE_SUCCESS || !(*link_up))
44716f37f232SEric Joyner return status;
44726f37f232SEric Joyner
44736f37f232SEric Joyner /* MAC link is up, so check external PHY link.
44748eb6488eSEric Joyner * X557 PHY. Link status is latching low, and can only be used to detect
44758eb6488eSEric Joyner * link drop, and not the current status of the link without performing
44768eb6488eSEric Joyner * back-to-back reads.
44776f37f232SEric Joyner */
44788eb6488eSEric Joyner for (i = 0; i < 2; i++) {
44796f37f232SEric Joyner status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
44806f37f232SEric Joyner IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
44816f37f232SEric Joyner &autoneg_status);
44826f37f232SEric Joyner
44836f37f232SEric Joyner if (status != IXGBE_SUCCESS)
44846f37f232SEric Joyner return status;
44858eb6488eSEric Joyner }
44866f37f232SEric Joyner
44876f37f232SEric Joyner /* If external PHY link is not up, then indicate link not up */
44886f37f232SEric Joyner if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
448979b36ec9SKevin Bowling *link_up = false;
44906f37f232SEric Joyner
44916f37f232SEric Joyner return IXGBE_SUCCESS;
44926f37f232SEric Joyner }
44936f37f232SEric Joyner
44946f37f232SEric Joyner /**
44956f37f232SEric Joyner * ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI
44966f37f232SEric Joyner * @hw: pointer to hardware structure
44976f37f232SEric Joyner **/
ixgbe_reset_phy_t_X550em(struct ixgbe_hw * hw)44986f37f232SEric Joyner s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw)
44996f37f232SEric Joyner {
45006f37f232SEric Joyner s32 status;
45016f37f232SEric Joyner
45026f37f232SEric Joyner status = ixgbe_reset_phy_generic(hw);
45036f37f232SEric Joyner
45046f37f232SEric Joyner if (status != IXGBE_SUCCESS)
45056f37f232SEric Joyner return status;
45066f37f232SEric Joyner
45076f37f232SEric Joyner /* Configure Link Status Alarm and Temperature Threshold interrupts */
45086f37f232SEric Joyner return ixgbe_enable_lasi_ext_t_x550em(hw);
45096f37f232SEric Joyner }
45106f37f232SEric Joyner
45116f37f232SEric Joyner /**
45126f37f232SEric Joyner * ixgbe_led_on_t_X550em - Turns on the software controllable LEDs.
45136f37f232SEric Joyner * @hw: pointer to hardware structure
45146f37f232SEric Joyner * @led_idx: led number to turn on
45156f37f232SEric Joyner **/
ixgbe_led_on_t_X550em(struct ixgbe_hw * hw,u32 led_idx)45166f37f232SEric Joyner s32 ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, u32 led_idx)
45176f37f232SEric Joyner {
45186f37f232SEric Joyner u16 phy_data;
45196f37f232SEric Joyner
45206f37f232SEric Joyner DEBUGFUNC("ixgbe_led_on_t_X550em");
45216f37f232SEric Joyner
45226f37f232SEric Joyner if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
45236f37f232SEric Joyner return IXGBE_ERR_PARAM;
45246f37f232SEric Joyner
45256f37f232SEric Joyner /* To turn on the LED, set mode to ON. */
45266f37f232SEric Joyner ixgbe_read_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
45276f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
45286f37f232SEric Joyner phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;
45296f37f232SEric Joyner ixgbe_write_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
45306f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
45316f37f232SEric Joyner
45328eb6488eSEric Joyner /* Some designs have the LEDs wired to the MAC */
45338eb6488eSEric Joyner return ixgbe_led_on_generic(hw, led_idx);
45346f37f232SEric Joyner }
45356f37f232SEric Joyner
45366f37f232SEric Joyner /**
45376f37f232SEric Joyner * ixgbe_led_off_t_X550em - Turns off the software controllable LEDs.
45386f37f232SEric Joyner * @hw: pointer to hardware structure
45396f37f232SEric Joyner * @led_idx: led number to turn off
45406f37f232SEric Joyner **/
ixgbe_led_off_t_X550em(struct ixgbe_hw * hw,u32 led_idx)45416f37f232SEric Joyner s32 ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, u32 led_idx)
45426f37f232SEric Joyner {
45436f37f232SEric Joyner u16 phy_data;
45446f37f232SEric Joyner
45456f37f232SEric Joyner DEBUGFUNC("ixgbe_led_off_t_X550em");
45466f37f232SEric Joyner
45476f37f232SEric Joyner if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
45486f37f232SEric Joyner return IXGBE_ERR_PARAM;
45496f37f232SEric Joyner
45506f37f232SEric Joyner /* To turn on the LED, set mode to ON. */
45516f37f232SEric Joyner ixgbe_read_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
45526f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
45536f37f232SEric Joyner phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;
45546f37f232SEric Joyner ixgbe_write_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
45556f37f232SEric Joyner IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
45566f37f232SEric Joyner
45578eb6488eSEric Joyner /* Some designs have the LEDs wired to the MAC */
45588eb6488eSEric Joyner return ixgbe_led_off_generic(hw, led_idx);
45596f37f232SEric Joyner }
45606f37f232SEric Joyner
45618eb6488eSEric Joyner /**
45628eb6488eSEric Joyner * ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware
45638eb6488eSEric Joyner * @hw: pointer to the HW structure
45648eb6488eSEric Joyner * @maj: driver version major number
45658eb6488eSEric Joyner * @min: driver version minor number
45668eb6488eSEric Joyner * @build: driver version build number
45678eb6488eSEric Joyner * @sub: driver version sub build number
45688eb6488eSEric Joyner * @len: length of driver_ver string
45698eb6488eSEric Joyner * @driver_ver: driver string
45708eb6488eSEric Joyner *
45718eb6488eSEric Joyner * Sends driver version number to firmware through the manageability
45728eb6488eSEric Joyner * block. On success return IXGBE_SUCCESS
45738eb6488eSEric Joyner * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
45748eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
45758eb6488eSEric Joyner **/
ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw * hw,u8 maj,u8 min,u8 build,u8 sub,u16 len,const char * driver_ver)45768eb6488eSEric Joyner s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
45778eb6488eSEric Joyner u8 build, u8 sub, u16 len, const char *driver_ver)
45788eb6488eSEric Joyner {
45798eb6488eSEric Joyner struct ixgbe_hic_drv_info2 fw_cmd;
45808eb6488eSEric Joyner s32 ret_val = IXGBE_SUCCESS;
45818eb6488eSEric Joyner int i;
45828eb6488eSEric Joyner
45838eb6488eSEric Joyner DEBUGFUNC("ixgbe_set_fw_drv_ver_x550");
45848eb6488eSEric Joyner
45858eb6488eSEric Joyner if ((len == 0) || (driver_ver == NULL) ||
45868eb6488eSEric Joyner (len > sizeof(fw_cmd.driver_string)))
45878eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT;
45888eb6488eSEric Joyner
45898eb6488eSEric Joyner fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
45908eb6488eSEric Joyner fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len;
45918eb6488eSEric Joyner fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
45928eb6488eSEric Joyner fw_cmd.port_num = (u8)hw->bus.func;
45938eb6488eSEric Joyner fw_cmd.ver_maj = maj;
45948eb6488eSEric Joyner fw_cmd.ver_min = min;
45958eb6488eSEric Joyner fw_cmd.ver_build = build;
45968eb6488eSEric Joyner fw_cmd.ver_sub = sub;
45978eb6488eSEric Joyner fw_cmd.hdr.checksum = 0;
45988eb6488eSEric Joyner memcpy(fw_cmd.driver_string, driver_ver, len);
45998eb6488eSEric Joyner fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
46008eb6488eSEric Joyner (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
46018eb6488eSEric Joyner
46028eb6488eSEric Joyner for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
46038eb6488eSEric Joyner ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
46048eb6488eSEric Joyner sizeof(fw_cmd),
46058eb6488eSEric Joyner IXGBE_HI_COMMAND_TIMEOUT,
460679b36ec9SKevin Bowling true);
46078eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS)
46088eb6488eSEric Joyner continue;
46098eb6488eSEric Joyner
46108eb6488eSEric Joyner if (fw_cmd.hdr.cmd_or_resp.ret_status ==
46118eb6488eSEric Joyner FW_CEM_RESP_STATUS_SUCCESS)
46128eb6488eSEric Joyner ret_val = IXGBE_SUCCESS;
46138eb6488eSEric Joyner else
46148eb6488eSEric Joyner ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
46158eb6488eSEric Joyner
46168eb6488eSEric Joyner break;
46178eb6488eSEric Joyner }
46188eb6488eSEric Joyner
46198eb6488eSEric Joyner return ret_val;
46208eb6488eSEric Joyner }
4621b622bdb4SXiaoyun Li
4622b622bdb4SXiaoyun Li /**
4623b622bdb4SXiaoyun Li * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode
4624b622bdb4SXiaoyun Li * @hw: pointer t hardware structure
4625b622bdb4SXiaoyun Li *
4626b622bdb4SXiaoyun Li * Returns true if in FW NVM recovery mode.
4627b622bdb4SXiaoyun Li **/
ixgbe_fw_recovery_mode_X550(struct ixgbe_hw * hw)4628b622bdb4SXiaoyun Li bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw)
4629b622bdb4SXiaoyun Li {
4630b622bdb4SXiaoyun Li u32 fwsm;
4631b622bdb4SXiaoyun Li
4632b622bdb4SXiaoyun Li fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
4633b622bdb4SXiaoyun Li
4634b622bdb4SXiaoyun Li return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE);
4635b622bdb4SXiaoyun Li }
4636