18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include "ixgbe_x540.h" 58c2ecf20Sopenharmony_ci#include "ixgbe_type.h" 68c2ecf20Sopenharmony_ci#include "ixgbe_common.h" 78c2ecf20Sopenharmony_ci#include "ixgbe_phy.h" 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed); 108c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *); 118c2ecf20Sopenharmony_cistatic void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *); 128c2ecf20Sopenharmony_cistatic void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *); 138c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *); 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 188c2ecf20Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 198c2ecf20Sopenharmony_ci struct ixgbe_link_info *link = &hw->link; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci /* Start with X540 invariants, since so simular */ 228c2ecf20Sopenharmony_ci ixgbe_get_invariants_X540(hw); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 258c2ecf20Sopenharmony_ci phy->ops.set_phy_power = NULL; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci link->addr = IXGBE_CS4227; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci return 0; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_x_fw(struct ixgbe_hw *hw) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci /* Start with X540 invariants, since so similar */ 378c2ecf20Sopenharmony_ci ixgbe_get_invariants_X540(hw); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci phy->ops.set_phy_power = NULL; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci return 0; 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 478c2ecf20Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci /* Start with X540 invariants, since so simular */ 508c2ecf20Sopenharmony_ci ixgbe_get_invariants_X540(hw); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 538c2ecf20Sopenharmony_ci phy->ops.set_phy_power = NULL; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return 0; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic s32 ixgbe_get_invariants_X550_a_fw(struct ixgbe_hw *hw) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci /* Start with X540 invariants, since so similar */ 638c2ecf20Sopenharmony_ci ixgbe_get_invariants_X540(hw); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci phy->ops.set_phy_power = NULL; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci return 0; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control 718c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 728c2ecf20Sopenharmony_ci **/ 738c2ecf20Sopenharmony_cistatic void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (hw->bus.lan_id) { 788c2ecf20Sopenharmony_ci esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 798c2ecf20Sopenharmony_ci esdp |= IXGBE_ESDP_SDP1_DIR; 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 828c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 838c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/** 878c2ecf20Sopenharmony_ci * ixgbe_read_cs4227 - Read CS4227 register 888c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 898c2ecf20Sopenharmony_ci * @reg: register number to write 908c2ecf20Sopenharmony_ci * @value: pointer to receive value read 918c2ecf20Sopenharmony_ci * 928c2ecf20Sopenharmony_ci * Returns status code 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_cistatic s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/** 1008c2ecf20Sopenharmony_ci * ixgbe_write_cs4227 - Write CS4227 register 1018c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 1028c2ecf20Sopenharmony_ci * @reg: register number to write 1038c2ecf20Sopenharmony_ci * @value: value to write to register 1048c2ecf20Sopenharmony_ci * 1058c2ecf20Sopenharmony_ci * Returns status code 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_cistatic s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/** 1138c2ecf20Sopenharmony_ci * ixgbe_read_pe - Read register from port expander 1148c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 1158c2ecf20Sopenharmony_ci * @reg: register number to read 1168c2ecf20Sopenharmony_ci * @value: pointer to receive read value 1178c2ecf20Sopenharmony_ci * 1188c2ecf20Sopenharmony_ci * Returns status code 1198c2ecf20Sopenharmony_ci */ 1208c2ecf20Sopenharmony_cistatic s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci s32 status; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, value); 1258c2ecf20Sopenharmony_ci if (status) 1268c2ecf20Sopenharmony_ci hw_err(hw, "port expander access failed with %d\n", status); 1278c2ecf20Sopenharmony_ci return status; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/** 1318c2ecf20Sopenharmony_ci * ixgbe_write_pe - Write register to port expander 1328c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 1338c2ecf20Sopenharmony_ci * @reg: register number to write 1348c2ecf20Sopenharmony_ci * @value: value to write 1358c2ecf20Sopenharmony_ci * 1368c2ecf20Sopenharmony_ci * Returns status code 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_cistatic s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci s32 status; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, 1438c2ecf20Sopenharmony_ci value); 1448c2ecf20Sopenharmony_ci if (status) 1458c2ecf20Sopenharmony_ci hw_err(hw, "port expander access failed with %d\n", status); 1468c2ecf20Sopenharmony_ci return status; 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/** 1508c2ecf20Sopenharmony_ci * ixgbe_reset_cs4227 - Reset CS4227 using port expander 1518c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 1528c2ecf20Sopenharmony_ci * 1538c2ecf20Sopenharmony_ci * This function assumes that the caller has acquired the proper semaphore. 1548c2ecf20Sopenharmony_ci * Returns error code 1558c2ecf20Sopenharmony_ci */ 1568c2ecf20Sopenharmony_cistatic s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci s32 status; 1598c2ecf20Sopenharmony_ci u32 retry; 1608c2ecf20Sopenharmony_ci u16 value; 1618c2ecf20Sopenharmony_ci u8 reg; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* Trigger hard reset. */ 1648c2ecf20Sopenharmony_ci status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 1658c2ecf20Sopenharmony_ci if (status) 1668c2ecf20Sopenharmony_ci return status; 1678c2ecf20Sopenharmony_ci reg |= IXGBE_PE_BIT1; 1688c2ecf20Sopenharmony_ci status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 1698c2ecf20Sopenharmony_ci if (status) 1708c2ecf20Sopenharmony_ci return status; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); 1738c2ecf20Sopenharmony_ci if (status) 1748c2ecf20Sopenharmony_ci return status; 1758c2ecf20Sopenharmony_ci reg &= ~IXGBE_PE_BIT1; 1768c2ecf20Sopenharmony_ci status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); 1778c2ecf20Sopenharmony_ci if (status) 1788c2ecf20Sopenharmony_ci return status; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 1818c2ecf20Sopenharmony_ci if (status) 1828c2ecf20Sopenharmony_ci return status; 1838c2ecf20Sopenharmony_ci reg &= ~IXGBE_PE_BIT1; 1848c2ecf20Sopenharmony_ci status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 1858c2ecf20Sopenharmony_ci if (status) 1868c2ecf20Sopenharmony_ci return status; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 1918c2ecf20Sopenharmony_ci if (status) 1928c2ecf20Sopenharmony_ci return status; 1938c2ecf20Sopenharmony_ci reg |= IXGBE_PE_BIT1; 1948c2ecf20Sopenharmony_ci status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 1958c2ecf20Sopenharmony_ci if (status) 1968c2ecf20Sopenharmony_ci return status; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci /* Wait for the reset to complete. */ 1998c2ecf20Sopenharmony_ci msleep(IXGBE_CS4227_RESET_DELAY); 2008c2ecf20Sopenharmony_ci for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 2018c2ecf20Sopenharmony_ci status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, 2028c2ecf20Sopenharmony_ci &value); 2038c2ecf20Sopenharmony_ci if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK) 2048c2ecf20Sopenharmony_ci break; 2058c2ecf20Sopenharmony_ci msleep(IXGBE_CS4227_CHECK_DELAY); 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci if (retry == IXGBE_CS4227_RETRIES) { 2088c2ecf20Sopenharmony_ci hw_err(hw, "CS4227 reset did not complete\n"); 2098c2ecf20Sopenharmony_ci return -EIO; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value); 2138c2ecf20Sopenharmony_ci if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { 2148c2ecf20Sopenharmony_ci hw_err(hw, "CS4227 EEPROM did not load successfully\n"); 2158c2ecf20Sopenharmony_ci return -EIO; 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci return 0; 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci/** 2228c2ecf20Sopenharmony_ci * ixgbe_check_cs4227 - Check CS4227 and reset as needed 2238c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_cistatic void ixgbe_check_cs4227(struct ixgbe_hw *hw) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci u32 swfw_mask = hw->phy.phy_semaphore_mask; 2288c2ecf20Sopenharmony_ci s32 status; 2298c2ecf20Sopenharmony_ci u16 value; 2308c2ecf20Sopenharmony_ci u8 retry; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 2338c2ecf20Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 2348c2ecf20Sopenharmony_ci if (status) { 2358c2ecf20Sopenharmony_ci hw_err(hw, "semaphore failed with %d\n", status); 2368c2ecf20Sopenharmony_ci msleep(IXGBE_CS4227_CHECK_DELAY); 2378c2ecf20Sopenharmony_ci continue; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci /* Get status of reset flow. */ 2418c2ecf20Sopenharmony_ci status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); 2428c2ecf20Sopenharmony_ci if (!status && value == IXGBE_CS4227_RESET_COMPLETE) 2438c2ecf20Sopenharmony_ci goto out; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (status || value != IXGBE_CS4227_RESET_PENDING) 2468c2ecf20Sopenharmony_ci break; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci /* Reset is pending. Wait and check again. */ 2498c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 2508c2ecf20Sopenharmony_ci msleep(IXGBE_CS4227_CHECK_DELAY); 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci /* If still pending, assume other instance failed. */ 2538c2ecf20Sopenharmony_ci if (retry == IXGBE_CS4227_RETRIES) { 2548c2ecf20Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 2558c2ecf20Sopenharmony_ci if (status) { 2568c2ecf20Sopenharmony_ci hw_err(hw, "semaphore failed with %d\n", status); 2578c2ecf20Sopenharmony_ci return; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* Reset the CS4227. */ 2628c2ecf20Sopenharmony_ci status = ixgbe_reset_cs4227(hw); 2638c2ecf20Sopenharmony_ci if (status) { 2648c2ecf20Sopenharmony_ci hw_err(hw, "CS4227 reset failed: %d", status); 2658c2ecf20Sopenharmony_ci goto out; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* Reset takes so long, temporarily release semaphore in case the 2698c2ecf20Sopenharmony_ci * other driver instance is waiting for the reset indication. 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_ci ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 2728c2ecf20Sopenharmony_ci IXGBE_CS4227_RESET_PENDING); 2738c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 2748c2ecf20Sopenharmony_ci usleep_range(10000, 12000); 2758c2ecf20Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 2768c2ecf20Sopenharmony_ci if (status) { 2778c2ecf20Sopenharmony_ci hw_err(hw, "semaphore failed with %d", status); 2788c2ecf20Sopenharmony_ci return; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci /* Record completion for next time. */ 2828c2ecf20Sopenharmony_ci status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 2838c2ecf20Sopenharmony_ci IXGBE_CS4227_RESET_COMPLETE); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ciout: 2868c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 2878c2ecf20Sopenharmony_ci msleep(hw->eeprom.semaphore_delay); 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/** ixgbe_identify_phy_x550em - Get PHY type based on device id 2918c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 2928c2ecf20Sopenharmony_ci * 2938c2ecf20Sopenharmony_ci * Returns error code 2948c2ecf20Sopenharmony_ci */ 2958c2ecf20Sopenharmony_cistatic s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci switch (hw->device_id) { 2988c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP: 2998c2ecf20Sopenharmony_ci if (hw->bus.lan_id) 3008c2ecf20Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 3018c2ecf20Sopenharmony_ci else 3028c2ecf20Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 3038c2ecf20Sopenharmony_ci return ixgbe_identify_module_generic(hw); 3048c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_SFP: 3058c2ecf20Sopenharmony_ci /* set up for CS4227 usage */ 3068c2ecf20Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 3078c2ecf20Sopenharmony_ci ixgbe_setup_mux_ctl(hw); 3088c2ecf20Sopenharmony_ci ixgbe_check_cs4227(hw); 3098c2ecf20Sopenharmony_ci fallthrough; 3108c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP_N: 3118c2ecf20Sopenharmony_ci return ixgbe_identify_module_generic(hw); 3128c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KX4: 3138c2ecf20Sopenharmony_ci hw->phy.type = ixgbe_phy_x550em_kx4; 3148c2ecf20Sopenharmony_ci break; 3158c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_XFI: 3168c2ecf20Sopenharmony_ci hw->phy.type = ixgbe_phy_x550em_xfi; 3178c2ecf20Sopenharmony_ci break; 3188c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KR: 3198c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR: 3208c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR_L: 3218c2ecf20Sopenharmony_ci hw->phy.type = ixgbe_phy_x550em_kr; 3228c2ecf20Sopenharmony_ci break; 3238c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_10G_T: 3248c2ecf20Sopenharmony_ci if (hw->bus.lan_id) 3258c2ecf20Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 3268c2ecf20Sopenharmony_ci else 3278c2ecf20Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 3288c2ecf20Sopenharmony_ci fallthrough; 3298c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_10G_T: 3308c2ecf20Sopenharmony_ci return ixgbe_identify_phy_generic(hw); 3318c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_1G_T: 3328c2ecf20Sopenharmony_ci hw->phy.type = ixgbe_phy_ext_1g_t; 3338c2ecf20Sopenharmony_ci break; 3348c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T: 3358c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T_L: 3368c2ecf20Sopenharmony_ci hw->phy.type = ixgbe_phy_fw; 3378c2ecf20Sopenharmony_ci hw->phy.ops.read_reg = NULL; 3388c2ecf20Sopenharmony_ci hw->phy.ops.write_reg = NULL; 3398c2ecf20Sopenharmony_ci if (hw->bus.lan_id) 3408c2ecf20Sopenharmony_ci hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; 3418c2ecf20Sopenharmony_ci else 3428c2ecf20Sopenharmony_ci hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM; 3438c2ecf20Sopenharmony_ci break; 3448c2ecf20Sopenharmony_ci default: 3458c2ecf20Sopenharmony_ci break; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci return 0; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 3518c2ecf20Sopenharmony_ci u32 device_type, u16 *phy_data) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 3578c2ecf20Sopenharmony_ci u32 device_type, u16 phy_data) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci/** 3638c2ecf20Sopenharmony_ci * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation 3648c2ecf20Sopenharmony_ci * @hw: pointer to the hardware structure 3658c2ecf20Sopenharmony_ci * @addr: I2C bus address to read from 3668c2ecf20Sopenharmony_ci * @reg: I2C device register to read from 3678c2ecf20Sopenharmony_ci * @val: pointer to location to receive read value 3688c2ecf20Sopenharmony_ci * 3698c2ecf20Sopenharmony_ci * Returns an error code on error. 3708c2ecf20Sopenharmony_ci **/ 3718c2ecf20Sopenharmony_cistatic s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, 3728c2ecf20Sopenharmony_ci u16 reg, u16 *val) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci/** 3788c2ecf20Sopenharmony_ci * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation 3798c2ecf20Sopenharmony_ci * @hw: pointer to the hardware structure 3808c2ecf20Sopenharmony_ci * @addr: I2C bus address to read from 3818c2ecf20Sopenharmony_ci * @reg: I2C device register to read from 3828c2ecf20Sopenharmony_ci * @val: pointer to location to receive read value 3838c2ecf20Sopenharmony_ci * 3848c2ecf20Sopenharmony_ci * Returns an error code on error. 3858c2ecf20Sopenharmony_ci **/ 3868c2ecf20Sopenharmony_cistatic s32 3878c2ecf20Sopenharmony_ciixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, 3888c2ecf20Sopenharmony_ci u16 reg, u16 *val) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); 3918c2ecf20Sopenharmony_ci} 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci/** 3948c2ecf20Sopenharmony_ci * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation 3958c2ecf20Sopenharmony_ci * @hw: pointer to the hardware structure 3968c2ecf20Sopenharmony_ci * @addr: I2C bus address to write to 3978c2ecf20Sopenharmony_ci * @reg: I2C device register to write to 3988c2ecf20Sopenharmony_ci * @val: value to write 3998c2ecf20Sopenharmony_ci * 4008c2ecf20Sopenharmony_ci * Returns an error code on error. 4018c2ecf20Sopenharmony_ci **/ 4028c2ecf20Sopenharmony_cistatic s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, 4038c2ecf20Sopenharmony_ci u8 addr, u16 reg, u16 val) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); 4068c2ecf20Sopenharmony_ci} 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci/** 4098c2ecf20Sopenharmony_ci * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation 4108c2ecf20Sopenharmony_ci * @hw: pointer to the hardware structure 4118c2ecf20Sopenharmony_ci * @addr: I2C bus address to write to 4128c2ecf20Sopenharmony_ci * @reg: I2C device register to write to 4138c2ecf20Sopenharmony_ci * @val: value to write 4148c2ecf20Sopenharmony_ci * 4158c2ecf20Sopenharmony_ci * Returns an error code on error. 4168c2ecf20Sopenharmony_ci **/ 4178c2ecf20Sopenharmony_cistatic s32 4188c2ecf20Sopenharmony_ciixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, 4198c2ecf20Sopenharmony_ci u8 addr, u16 reg, u16 val) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci/** 4258c2ecf20Sopenharmony_ci * ixgbe_fw_phy_activity - Perform an activity on a PHY 4268c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 4278c2ecf20Sopenharmony_ci * @activity: activity to perform 4288c2ecf20Sopenharmony_ci * @data: Pointer to 4 32-bit words of data 4298c2ecf20Sopenharmony_ci */ 4308c2ecf20Sopenharmony_cis32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity, 4318c2ecf20Sopenharmony_ci u32 (*data)[FW_PHY_ACT_DATA_COUNT]) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci union { 4348c2ecf20Sopenharmony_ci struct ixgbe_hic_phy_activity_req cmd; 4358c2ecf20Sopenharmony_ci struct ixgbe_hic_phy_activity_resp rsp; 4368c2ecf20Sopenharmony_ci } hic; 4378c2ecf20Sopenharmony_ci u16 retries = FW_PHY_ACT_RETRIES; 4388c2ecf20Sopenharmony_ci s32 rc; 4398c2ecf20Sopenharmony_ci u32 i; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci do { 4428c2ecf20Sopenharmony_ci memset(&hic, 0, sizeof(hic)); 4438c2ecf20Sopenharmony_ci hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD; 4448c2ecf20Sopenharmony_ci hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN; 4458c2ecf20Sopenharmony_ci hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 4468c2ecf20Sopenharmony_ci hic.cmd.port_number = hw->bus.lan_id; 4478c2ecf20Sopenharmony_ci hic.cmd.activity_id = cpu_to_le16(activity); 4488c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(hic.cmd.data); ++i) 4498c2ecf20Sopenharmony_ci hic.cmd.data[i] = cpu_to_be32((*data)[i]); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci rc = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 4528c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, 4538c2ecf20Sopenharmony_ci true); 4548c2ecf20Sopenharmony_ci if (rc) 4558c2ecf20Sopenharmony_ci return rc; 4568c2ecf20Sopenharmony_ci if (hic.rsp.hdr.cmd_or_resp.ret_status == 4578c2ecf20Sopenharmony_ci FW_CEM_RESP_STATUS_SUCCESS) { 4588c2ecf20Sopenharmony_ci for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i) 4598c2ecf20Sopenharmony_ci (*data)[i] = be32_to_cpu(hic.rsp.data[i]); 4608c2ecf20Sopenharmony_ci return 0; 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci usleep_range(20, 30); 4638c2ecf20Sopenharmony_ci --retries; 4648c2ecf20Sopenharmony_ci } while (retries > 0); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci return -EIO; 4678c2ecf20Sopenharmony_ci} 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_cistatic const struct { 4708c2ecf20Sopenharmony_ci u16 fw_speed; 4718c2ecf20Sopenharmony_ci ixgbe_link_speed phy_speed; 4728c2ecf20Sopenharmony_ci} ixgbe_fw_map[] = { 4738c2ecf20Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL }, 4748c2ecf20Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL }, 4758c2ecf20Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL }, 4768c2ecf20Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL }, 4778c2ecf20Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL }, 4788c2ecf20Sopenharmony_ci { FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL }, 4798c2ecf20Sopenharmony_ci}; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci/** 4828c2ecf20Sopenharmony_ci * ixgbe_get_phy_id_fw - Get the phy ID via firmware command 4838c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 4848c2ecf20Sopenharmony_ci * 4858c2ecf20Sopenharmony_ci * Returns error code 4868c2ecf20Sopenharmony_ci */ 4878c2ecf20Sopenharmony_cistatic s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 }; 4908c2ecf20Sopenharmony_ci u16 phy_speeds; 4918c2ecf20Sopenharmony_ci u16 phy_id_lo; 4928c2ecf20Sopenharmony_ci s32 rc; 4938c2ecf20Sopenharmony_ci u16 i; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci if (hw->phy.id) 4968c2ecf20Sopenharmony_ci return 0; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info); 4998c2ecf20Sopenharmony_ci if (rc) 5008c2ecf20Sopenharmony_ci return rc; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci hw->phy.speeds_supported = 0; 5038c2ecf20Sopenharmony_ci phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK; 5048c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) { 5058c2ecf20Sopenharmony_ci if (phy_speeds & ixgbe_fw_map[i].fw_speed) 5068c2ecf20Sopenharmony_ci hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK; 5108c2ecf20Sopenharmony_ci phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK; 5118c2ecf20Sopenharmony_ci hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK; 5128c2ecf20Sopenharmony_ci hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK; 5138c2ecf20Sopenharmony_ci if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK) 5148c2ecf20Sopenharmony_ci return -EFAULT; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci hw->phy.autoneg_advertised = hw->phy.speeds_supported; 5178c2ecf20Sopenharmony_ci hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL | 5188c2ecf20Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL; 5198c2ecf20Sopenharmony_ci hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported; 5208c2ecf20Sopenharmony_ci return 0; 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci/** 5248c2ecf20Sopenharmony_ci * ixgbe_identify_phy_fw - Get PHY type based on firmware command 5258c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 5268c2ecf20Sopenharmony_ci * 5278c2ecf20Sopenharmony_ci * Returns error code 5288c2ecf20Sopenharmony_ci */ 5298c2ecf20Sopenharmony_cistatic s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw) 5308c2ecf20Sopenharmony_ci{ 5318c2ecf20Sopenharmony_ci if (hw->bus.lan_id) 5328c2ecf20Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 5338c2ecf20Sopenharmony_ci else 5348c2ecf20Sopenharmony_ci hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci hw->phy.type = ixgbe_phy_fw; 5378c2ecf20Sopenharmony_ci hw->phy.ops.read_reg = NULL; 5388c2ecf20Sopenharmony_ci hw->phy.ops.write_reg = NULL; 5398c2ecf20Sopenharmony_ci return ixgbe_get_phy_id_fw(hw); 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci/** 5438c2ecf20Sopenharmony_ci * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY 5448c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 5458c2ecf20Sopenharmony_ci * 5468c2ecf20Sopenharmony_ci * Returns error code 5478c2ecf20Sopenharmony_ci */ 5488c2ecf20Sopenharmony_cistatic s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw) 5498c2ecf20Sopenharmony_ci{ 5508c2ecf20Sopenharmony_ci u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 }; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF; 5538c2ecf20Sopenharmony_ci return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup); 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci/** 5578c2ecf20Sopenharmony_ci * ixgbe_setup_fw_link - Setup firmware-controlled PHYs 5588c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 5598c2ecf20Sopenharmony_ci */ 5608c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 }; 5638c2ecf20Sopenharmony_ci s32 rc; 5648c2ecf20Sopenharmony_ci u16 i; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) 5678c2ecf20Sopenharmony_ci return 0; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 5708c2ecf20Sopenharmony_ci hw_err(hw, "rx_pause not valid in strict IEEE mode\n"); 5718c2ecf20Sopenharmony_ci return -EINVAL; 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci switch (hw->fc.requested_mode) { 5758c2ecf20Sopenharmony_ci case ixgbe_fc_full: 5768c2ecf20Sopenharmony_ci setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX << 5778c2ecf20Sopenharmony_ci FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 5788c2ecf20Sopenharmony_ci break; 5798c2ecf20Sopenharmony_ci case ixgbe_fc_rx_pause: 5808c2ecf20Sopenharmony_ci setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX << 5818c2ecf20Sopenharmony_ci FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 5828c2ecf20Sopenharmony_ci break; 5838c2ecf20Sopenharmony_ci case ixgbe_fc_tx_pause: 5848c2ecf20Sopenharmony_ci setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX << 5858c2ecf20Sopenharmony_ci FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 5868c2ecf20Sopenharmony_ci break; 5878c2ecf20Sopenharmony_ci default: 5888c2ecf20Sopenharmony_ci break; 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) { 5928c2ecf20Sopenharmony_ci if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed) 5938c2ecf20Sopenharmony_ci setup[0] |= ixgbe_fw_map[i].fw_speed; 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci if (hw->phy.eee_speeds_advertised) 5988c2ecf20Sopenharmony_ci setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup); 6018c2ecf20Sopenharmony_ci if (rc) 6028c2ecf20Sopenharmony_ci return rc; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN) 6058c2ecf20Sopenharmony_ci return -EIO; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci return 0; 6088c2ecf20Sopenharmony_ci} 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci/** 6118c2ecf20Sopenharmony_ci * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs 6128c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 6138c2ecf20Sopenharmony_ci * 6148c2ecf20Sopenharmony_ci * Called at init time to set up flow control. 6158c2ecf20Sopenharmony_ci */ 6168c2ecf20Sopenharmony_cistatic s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci if (hw->fc.requested_mode == ixgbe_fc_default) 6198c2ecf20Sopenharmony_ci hw->fc.requested_mode = ixgbe_fc_full; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci return ixgbe_setup_fw_link(hw); 6228c2ecf20Sopenharmony_ci} 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci/** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 6258c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 6268c2ecf20Sopenharmony_ci * 6278c2ecf20Sopenharmony_ci * Initializes the EEPROM parameters ixgbe_eeprom_info within the 6288c2ecf20Sopenharmony_ci * ixgbe_hw struct in order to set up EEPROM access. 6298c2ecf20Sopenharmony_ci **/ 6308c2ecf20Sopenharmony_cistatic s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 6318c2ecf20Sopenharmony_ci{ 6328c2ecf20Sopenharmony_ci struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 6338c2ecf20Sopenharmony_ci u32 eec; 6348c2ecf20Sopenharmony_ci u16 eeprom_size; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci if (eeprom->type == ixgbe_eeprom_uninitialized) { 6378c2ecf20Sopenharmony_ci eeprom->semaphore_delay = 10; 6388c2ecf20Sopenharmony_ci eeprom->type = ixgbe_flash; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 6418c2ecf20Sopenharmony_ci eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 6428c2ecf20Sopenharmony_ci IXGBE_EEC_SIZE_SHIFT); 6438c2ecf20Sopenharmony_ci eeprom->word_size = BIT(eeprom_size + 6448c2ecf20Sopenharmony_ci IXGBE_EEPROM_WORD_SIZE_SHIFT); 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 6478c2ecf20Sopenharmony_ci eeprom->type, eeprom->word_size); 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci return 0; 6518c2ecf20Sopenharmony_ci} 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci/** 6548c2ecf20Sopenharmony_ci * ixgbe_iosf_wait - Wait for IOSF command completion 6558c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 6568c2ecf20Sopenharmony_ci * @ctrl: pointer to location to receive final IOSF control value 6578c2ecf20Sopenharmony_ci * 6588c2ecf20Sopenharmony_ci * Return: failing status on timeout 6598c2ecf20Sopenharmony_ci * 6608c2ecf20Sopenharmony_ci * Note: ctrl can be NULL if the IOSF control register value is not needed 6618c2ecf20Sopenharmony_ci */ 6628c2ecf20Sopenharmony_cistatic s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 6638c2ecf20Sopenharmony_ci{ 6648c2ecf20Sopenharmony_ci u32 i, command; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /* Check every 10 usec to see if the address cycle completed. 6678c2ecf20Sopenharmony_ci * The SB IOSF BUSY bit will clear when the operation is 6688c2ecf20Sopenharmony_ci * complete. 6698c2ecf20Sopenharmony_ci */ 6708c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 6718c2ecf20Sopenharmony_ci command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 6728c2ecf20Sopenharmony_ci if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 6738c2ecf20Sopenharmony_ci break; 6748c2ecf20Sopenharmony_ci udelay(10); 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci if (ctrl) 6778c2ecf20Sopenharmony_ci *ctrl = command; 6788c2ecf20Sopenharmony_ci if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 6798c2ecf20Sopenharmony_ci hw_dbg(hw, "IOSF wait timed out\n"); 6808c2ecf20Sopenharmony_ci return -EIO; 6818c2ecf20Sopenharmony_ci } 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci return 0; 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci/** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 6878c2ecf20Sopenharmony_ci * IOSF device 6888c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 6898c2ecf20Sopenharmony_ci * @reg_addr: 32 bit PHY register to write 6908c2ecf20Sopenharmony_ci * @device_type: 3 bit device type 6918c2ecf20Sopenharmony_ci * @phy_data: Pointer to read data from the register 6928c2ecf20Sopenharmony_ci **/ 6938c2ecf20Sopenharmony_cistatic s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 6948c2ecf20Sopenharmony_ci u32 device_type, u32 *data) 6958c2ecf20Sopenharmony_ci{ 6968c2ecf20Sopenharmony_ci u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 6978c2ecf20Sopenharmony_ci u32 command, error; 6988c2ecf20Sopenharmony_ci s32 ret; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 7018c2ecf20Sopenharmony_ci if (ret) 7028c2ecf20Sopenharmony_ci return ret; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci ret = ixgbe_iosf_wait(hw, NULL); 7058c2ecf20Sopenharmony_ci if (ret) 7068c2ecf20Sopenharmony_ci goto out; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 7098c2ecf20Sopenharmony_ci (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci /* Write IOSF control register */ 7128c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci ret = ixgbe_iosf_wait(hw, &command); 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 7178c2ecf20Sopenharmony_ci error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 7188c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 7198c2ecf20Sopenharmony_ci hw_dbg(hw, "Failed to read, error %x\n", error); 7208c2ecf20Sopenharmony_ci ret = -EIO; 7218c2ecf20Sopenharmony_ci goto out; 7228c2ecf20Sopenharmony_ci } 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci if (!ret) 7258c2ecf20Sopenharmony_ci *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ciout: 7288c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, gssr); 7298c2ecf20Sopenharmony_ci return ret; 7308c2ecf20Sopenharmony_ci} 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci/** 7338c2ecf20Sopenharmony_ci * ixgbe_get_phy_token - Get the token for shared PHY access 7348c2ecf20Sopenharmony_ci * @hw: Pointer to hardware structure 7358c2ecf20Sopenharmony_ci */ 7368c2ecf20Sopenharmony_cistatic s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) 7378c2ecf20Sopenharmony_ci{ 7388c2ecf20Sopenharmony_ci struct ixgbe_hic_phy_token_req token_cmd; 7398c2ecf20Sopenharmony_ci s32 status; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 7428c2ecf20Sopenharmony_ci token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 7438c2ecf20Sopenharmony_ci token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 7448c2ecf20Sopenharmony_ci token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 7458c2ecf20Sopenharmony_ci token_cmd.port_number = hw->bus.lan_id; 7468c2ecf20Sopenharmony_ci token_cmd.command_type = FW_PHY_TOKEN_REQ; 7478c2ecf20Sopenharmony_ci token_cmd.pad = 0; 7488c2ecf20Sopenharmony_ci status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 7498c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, 7508c2ecf20Sopenharmony_ci true); 7518c2ecf20Sopenharmony_ci if (status) 7528c2ecf20Sopenharmony_ci return status; 7538c2ecf20Sopenharmony_ci if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 7548c2ecf20Sopenharmony_ci return 0; 7558c2ecf20Sopenharmony_ci if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) 7568c2ecf20Sopenharmony_ci return -EIO; 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci return -EAGAIN; 7598c2ecf20Sopenharmony_ci} 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci/** 7628c2ecf20Sopenharmony_ci * ixgbe_put_phy_token - Put the token for shared PHY access 7638c2ecf20Sopenharmony_ci * @hw: Pointer to hardware structure 7648c2ecf20Sopenharmony_ci */ 7658c2ecf20Sopenharmony_cistatic s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) 7668c2ecf20Sopenharmony_ci{ 7678c2ecf20Sopenharmony_ci struct ixgbe_hic_phy_token_req token_cmd; 7688c2ecf20Sopenharmony_ci s32 status; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 7718c2ecf20Sopenharmony_ci token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 7728c2ecf20Sopenharmony_ci token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 7738c2ecf20Sopenharmony_ci token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 7748c2ecf20Sopenharmony_ci token_cmd.port_number = hw->bus.lan_id; 7758c2ecf20Sopenharmony_ci token_cmd.command_type = FW_PHY_TOKEN_REL; 7768c2ecf20Sopenharmony_ci token_cmd.pad = 0; 7778c2ecf20Sopenharmony_ci status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 7788c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, 7798c2ecf20Sopenharmony_ci true); 7808c2ecf20Sopenharmony_ci if (status) 7818c2ecf20Sopenharmony_ci return status; 7828c2ecf20Sopenharmony_ci if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 7838c2ecf20Sopenharmony_ci return 0; 7848c2ecf20Sopenharmony_ci return -EIO; 7858c2ecf20Sopenharmony_ci} 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci/** 7888c2ecf20Sopenharmony_ci * ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register 7898c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 7908c2ecf20Sopenharmony_ci * @reg_addr: 32 bit PHY register to write 7918c2ecf20Sopenharmony_ci * @device_type: 3 bit device type 7928c2ecf20Sopenharmony_ci * @data: Data to write to the register 7938c2ecf20Sopenharmony_ci **/ 7948c2ecf20Sopenharmony_cistatic s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 7958c2ecf20Sopenharmony_ci __always_unused u32 device_type, 7968c2ecf20Sopenharmony_ci u32 data) 7978c2ecf20Sopenharmony_ci{ 7988c2ecf20Sopenharmony_ci struct ixgbe_hic_internal_phy_req write_cmd; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci memset(&write_cmd, 0, sizeof(write_cmd)); 8018c2ecf20Sopenharmony_ci write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 8028c2ecf20Sopenharmony_ci write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 8038c2ecf20Sopenharmony_ci write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 8048c2ecf20Sopenharmony_ci write_cmd.port_number = hw->bus.lan_id; 8058c2ecf20Sopenharmony_ci write_cmd.command_type = FW_INT_PHY_REQ_WRITE; 8068c2ecf20Sopenharmony_ci write_cmd.address = cpu_to_be16(reg_addr); 8078c2ecf20Sopenharmony_ci write_cmd.write_data = cpu_to_be32(data); 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd), 8108c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, false); 8118c2ecf20Sopenharmony_ci} 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci/** 8148c2ecf20Sopenharmony_ci * ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register 8158c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 8168c2ecf20Sopenharmony_ci * @reg_addr: 32 bit PHY register to write 8178c2ecf20Sopenharmony_ci * @device_type: 3 bit device type 8188c2ecf20Sopenharmony_ci * @data: Pointer to read data from the register 8198c2ecf20Sopenharmony_ci **/ 8208c2ecf20Sopenharmony_cistatic s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 8218c2ecf20Sopenharmony_ci __always_unused u32 device_type, 8228c2ecf20Sopenharmony_ci u32 *data) 8238c2ecf20Sopenharmony_ci{ 8248c2ecf20Sopenharmony_ci union { 8258c2ecf20Sopenharmony_ci struct ixgbe_hic_internal_phy_req cmd; 8268c2ecf20Sopenharmony_ci struct ixgbe_hic_internal_phy_resp rsp; 8278c2ecf20Sopenharmony_ci } hic; 8288c2ecf20Sopenharmony_ci s32 status; 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci memset(&hic, 0, sizeof(hic)); 8318c2ecf20Sopenharmony_ci hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 8328c2ecf20Sopenharmony_ci hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 8338c2ecf20Sopenharmony_ci hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 8348c2ecf20Sopenharmony_ci hic.cmd.port_number = hw->bus.lan_id; 8358c2ecf20Sopenharmony_ci hic.cmd.command_type = FW_INT_PHY_REQ_READ; 8368c2ecf20Sopenharmony_ci hic.cmd.address = cpu_to_be16(reg_addr); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 8398c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, true); 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci /* Extract the register value from the response. */ 8428c2ecf20Sopenharmony_ci *data = be32_to_cpu(hic.rsp.read_data); 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci return status; 8458c2ecf20Sopenharmony_ci} 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci/** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 8488c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 8498c2ecf20Sopenharmony_ci * @offset: offset of word in the EEPROM to read 8508c2ecf20Sopenharmony_ci * @words: number of words 8518c2ecf20Sopenharmony_ci * @data: word(s) read from the EEPROM 8528c2ecf20Sopenharmony_ci * 8538c2ecf20Sopenharmony_ci * Reads a 16 bit word(s) from the EEPROM using the hostif. 8548c2ecf20Sopenharmony_ci **/ 8558c2ecf20Sopenharmony_cistatic s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 8568c2ecf20Sopenharmony_ci u16 offset, u16 words, u16 *data) 8578c2ecf20Sopenharmony_ci{ 8588c2ecf20Sopenharmony_ci const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; 8598c2ecf20Sopenharmony_ci struct ixgbe_hic_read_shadow_ram buffer; 8608c2ecf20Sopenharmony_ci u32 current_word = 0; 8618c2ecf20Sopenharmony_ci u16 words_to_read; 8628c2ecf20Sopenharmony_ci s32 status; 8638c2ecf20Sopenharmony_ci u32 i; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci /* Take semaphore for the entire operation. */ 8668c2ecf20Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, mask); 8678c2ecf20Sopenharmony_ci if (status) { 8688c2ecf20Sopenharmony_ci hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 8698c2ecf20Sopenharmony_ci return status; 8708c2ecf20Sopenharmony_ci } 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci while (words) { 8738c2ecf20Sopenharmony_ci if (words > FW_MAX_READ_BUFFER_SIZE / 2) 8748c2ecf20Sopenharmony_ci words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 8758c2ecf20Sopenharmony_ci else 8768c2ecf20Sopenharmony_ci words_to_read = words; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 8798c2ecf20Sopenharmony_ci buffer.hdr.req.buf_lenh = 0; 8808c2ecf20Sopenharmony_ci buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 8818c2ecf20Sopenharmony_ci buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci /* convert offset from words to bytes */ 8848c2ecf20Sopenharmony_ci buffer.address = (__force u32)cpu_to_be32((offset + 8858c2ecf20Sopenharmony_ci current_word) * 2); 8868c2ecf20Sopenharmony_ci buffer.length = (__force u16)cpu_to_be16(words_to_read * 2); 8878c2ecf20Sopenharmony_ci buffer.pad2 = 0; 8888c2ecf20Sopenharmony_ci buffer.pad3 = 0; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), 8918c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT); 8928c2ecf20Sopenharmony_ci if (status) { 8938c2ecf20Sopenharmony_ci hw_dbg(hw, "Host interface command failed\n"); 8948c2ecf20Sopenharmony_ci goto out; 8958c2ecf20Sopenharmony_ci } 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci for (i = 0; i < words_to_read; i++) { 8988c2ecf20Sopenharmony_ci u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 8998c2ecf20Sopenharmony_ci 2 * i; 9008c2ecf20Sopenharmony_ci u32 value = IXGBE_READ_REG(hw, reg); 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci data[current_word] = (u16)(value & 0xffff); 9038c2ecf20Sopenharmony_ci current_word++; 9048c2ecf20Sopenharmony_ci i++; 9058c2ecf20Sopenharmony_ci if (i < words_to_read) { 9068c2ecf20Sopenharmony_ci value >>= 16; 9078c2ecf20Sopenharmony_ci data[current_word] = (u16)(value & 0xffff); 9088c2ecf20Sopenharmony_ci current_word++; 9098c2ecf20Sopenharmony_ci } 9108c2ecf20Sopenharmony_ci } 9118c2ecf20Sopenharmony_ci words -= words_to_read; 9128c2ecf20Sopenharmony_ci } 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ciout: 9158c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, mask); 9168c2ecf20Sopenharmony_ci return status; 9178c2ecf20Sopenharmony_ci} 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci/** ixgbe_checksum_ptr_x550 - Checksum one pointer region 9208c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 9218c2ecf20Sopenharmony_ci * @ptr: pointer offset in eeprom 9228c2ecf20Sopenharmony_ci * @size: size of section pointed by ptr, if 0 first word will be used as size 9238c2ecf20Sopenharmony_ci * @csum: address of checksum to update 9248c2ecf20Sopenharmony_ci * 9258c2ecf20Sopenharmony_ci * Returns error status for any failure 9268c2ecf20Sopenharmony_ci **/ 9278c2ecf20Sopenharmony_cistatic s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 9288c2ecf20Sopenharmony_ci u16 size, u16 *csum, u16 *buffer, 9298c2ecf20Sopenharmony_ci u32 buffer_size) 9308c2ecf20Sopenharmony_ci{ 9318c2ecf20Sopenharmony_ci u16 buf[256]; 9328c2ecf20Sopenharmony_ci s32 status; 9338c2ecf20Sopenharmony_ci u16 length, bufsz, i, start; 9348c2ecf20Sopenharmony_ci u16 *local_buffer; 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci bufsz = ARRAY_SIZE(buf); 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci /* Read a chunk at the pointer location */ 9398c2ecf20Sopenharmony_ci if (!buffer) { 9408c2ecf20Sopenharmony_ci status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 9418c2ecf20Sopenharmony_ci if (status) { 9428c2ecf20Sopenharmony_ci hw_dbg(hw, "Failed to read EEPROM image\n"); 9438c2ecf20Sopenharmony_ci return status; 9448c2ecf20Sopenharmony_ci } 9458c2ecf20Sopenharmony_ci local_buffer = buf; 9468c2ecf20Sopenharmony_ci } else { 9478c2ecf20Sopenharmony_ci if (buffer_size < ptr) 9488c2ecf20Sopenharmony_ci return -EINVAL; 9498c2ecf20Sopenharmony_ci local_buffer = &buffer[ptr]; 9508c2ecf20Sopenharmony_ci } 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci if (size) { 9538c2ecf20Sopenharmony_ci start = 0; 9548c2ecf20Sopenharmony_ci length = size; 9558c2ecf20Sopenharmony_ci } else { 9568c2ecf20Sopenharmony_ci start = 1; 9578c2ecf20Sopenharmony_ci length = local_buffer[0]; 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci /* Skip pointer section if length is invalid. */ 9608c2ecf20Sopenharmony_ci if (length == 0xFFFF || length == 0 || 9618c2ecf20Sopenharmony_ci (ptr + length) >= hw->eeprom.word_size) 9628c2ecf20Sopenharmony_ci return 0; 9638c2ecf20Sopenharmony_ci } 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci if (buffer && ((u32)start + (u32)length > buffer_size)) 9668c2ecf20Sopenharmony_ci return -EINVAL; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci for (i = start; length; i++, length--) { 9698c2ecf20Sopenharmony_ci if (i == bufsz && !buffer) { 9708c2ecf20Sopenharmony_ci ptr += bufsz; 9718c2ecf20Sopenharmony_ci i = 0; 9728c2ecf20Sopenharmony_ci if (length < bufsz) 9738c2ecf20Sopenharmony_ci bufsz = length; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci /* Read a chunk at the pointer location */ 9768c2ecf20Sopenharmony_ci status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 9778c2ecf20Sopenharmony_ci bufsz, buf); 9788c2ecf20Sopenharmony_ci if (status) { 9798c2ecf20Sopenharmony_ci hw_dbg(hw, "Failed to read EEPROM image\n"); 9808c2ecf20Sopenharmony_ci return status; 9818c2ecf20Sopenharmony_ci } 9828c2ecf20Sopenharmony_ci } 9838c2ecf20Sopenharmony_ci *csum += local_buffer[i]; 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci return 0; 9868c2ecf20Sopenharmony_ci} 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci/** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 9898c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 9908c2ecf20Sopenharmony_ci * @buffer: pointer to buffer containing calculated checksum 9918c2ecf20Sopenharmony_ci * @buffer_size: size of buffer 9928c2ecf20Sopenharmony_ci * 9938c2ecf20Sopenharmony_ci * Returns a negative error code on error, or the 16-bit checksum 9948c2ecf20Sopenharmony_ci **/ 9958c2ecf20Sopenharmony_cistatic s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 9968c2ecf20Sopenharmony_ci u32 buffer_size) 9978c2ecf20Sopenharmony_ci{ 9988c2ecf20Sopenharmony_ci u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 9998c2ecf20Sopenharmony_ci u16 *local_buffer; 10008c2ecf20Sopenharmony_ci s32 status; 10018c2ecf20Sopenharmony_ci u16 checksum = 0; 10028c2ecf20Sopenharmony_ci u16 pointer, i, size; 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci hw->eeprom.ops.init_params(hw); 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci if (!buffer) { 10078c2ecf20Sopenharmony_ci /* Read pointer area */ 10088c2ecf20Sopenharmony_ci status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 10098c2ecf20Sopenharmony_ci IXGBE_EEPROM_LAST_WORD + 1, 10108c2ecf20Sopenharmony_ci eeprom_ptrs); 10118c2ecf20Sopenharmony_ci if (status) { 10128c2ecf20Sopenharmony_ci hw_dbg(hw, "Failed to read EEPROM image\n"); 10138c2ecf20Sopenharmony_ci return status; 10148c2ecf20Sopenharmony_ci } 10158c2ecf20Sopenharmony_ci local_buffer = eeprom_ptrs; 10168c2ecf20Sopenharmony_ci } else { 10178c2ecf20Sopenharmony_ci if (buffer_size < IXGBE_EEPROM_LAST_WORD) 10188c2ecf20Sopenharmony_ci return -EINVAL; 10198c2ecf20Sopenharmony_ci local_buffer = buffer; 10208c2ecf20Sopenharmony_ci } 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci /* For X550 hardware include 0x0-0x41 in the checksum, skip the 10238c2ecf20Sopenharmony_ci * checksum word itself 10248c2ecf20Sopenharmony_ci */ 10258c2ecf20Sopenharmony_ci for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 10268c2ecf20Sopenharmony_ci if (i != IXGBE_EEPROM_CHECKSUM) 10278c2ecf20Sopenharmony_ci checksum += local_buffer[i]; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 10308c2ecf20Sopenharmony_ci * FW, PHY module, and PCIe Expansion/Option ROM pointers. 10318c2ecf20Sopenharmony_ci */ 10328c2ecf20Sopenharmony_ci for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 10338c2ecf20Sopenharmony_ci if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 10348c2ecf20Sopenharmony_ci continue; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci pointer = local_buffer[i]; 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci /* Skip pointer section if the pointer is invalid. */ 10398c2ecf20Sopenharmony_ci if (pointer == 0xFFFF || pointer == 0 || 10408c2ecf20Sopenharmony_ci pointer >= hw->eeprom.word_size) 10418c2ecf20Sopenharmony_ci continue; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci switch (i) { 10448c2ecf20Sopenharmony_ci case IXGBE_PCIE_GENERAL_PTR: 10458c2ecf20Sopenharmony_ci size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 10468c2ecf20Sopenharmony_ci break; 10478c2ecf20Sopenharmony_ci case IXGBE_PCIE_CONFIG0_PTR: 10488c2ecf20Sopenharmony_ci case IXGBE_PCIE_CONFIG1_PTR: 10498c2ecf20Sopenharmony_ci size = IXGBE_PCIE_CONFIG_SIZE; 10508c2ecf20Sopenharmony_ci break; 10518c2ecf20Sopenharmony_ci default: 10528c2ecf20Sopenharmony_ci size = 0; 10538c2ecf20Sopenharmony_ci break; 10548c2ecf20Sopenharmony_ci } 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 10578c2ecf20Sopenharmony_ci buffer, buffer_size); 10588c2ecf20Sopenharmony_ci if (status) 10598c2ecf20Sopenharmony_ci return status; 10608c2ecf20Sopenharmony_ci } 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci checksum = (u16)IXGBE_EEPROM_SUM - checksum; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci return (s32)checksum; 10658c2ecf20Sopenharmony_ci} 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci/** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 10688c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 10698c2ecf20Sopenharmony_ci * 10708c2ecf20Sopenharmony_ci * Returns a negative error code on error, or the 16-bit checksum 10718c2ecf20Sopenharmony_ci **/ 10728c2ecf20Sopenharmony_cistatic s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 10738c2ecf20Sopenharmony_ci{ 10748c2ecf20Sopenharmony_ci return ixgbe_calc_checksum_X550(hw, NULL, 0); 10758c2ecf20Sopenharmony_ci} 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci/** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 10788c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 10798c2ecf20Sopenharmony_ci * @offset: offset of word in the EEPROM to read 10808c2ecf20Sopenharmony_ci * @data: word read from the EEPROM 10818c2ecf20Sopenharmony_ci * 10828c2ecf20Sopenharmony_ci * Reads a 16 bit word from the EEPROM using the hostif. 10838c2ecf20Sopenharmony_ci **/ 10848c2ecf20Sopenharmony_cistatic s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 10858c2ecf20Sopenharmony_ci{ 10868c2ecf20Sopenharmony_ci const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; 10878c2ecf20Sopenharmony_ci struct ixgbe_hic_read_shadow_ram buffer; 10888c2ecf20Sopenharmony_ci s32 status; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 10918c2ecf20Sopenharmony_ci buffer.hdr.req.buf_lenh = 0; 10928c2ecf20Sopenharmony_ci buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 10938c2ecf20Sopenharmony_ci buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci /* convert offset from words to bytes */ 10968c2ecf20Sopenharmony_ci buffer.address = (__force u32)cpu_to_be32(offset * 2); 10978c2ecf20Sopenharmony_ci /* one word */ 10988c2ecf20Sopenharmony_ci buffer.length = (__force u16)cpu_to_be16(sizeof(u16)); 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, mask); 11018c2ecf20Sopenharmony_ci if (status) 11028c2ecf20Sopenharmony_ci return status; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), 11058c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT); 11068c2ecf20Sopenharmony_ci if (!status) { 11078c2ecf20Sopenharmony_ci *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 11088c2ecf20Sopenharmony_ci FW_NVM_DATA_OFFSET); 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, mask); 11128c2ecf20Sopenharmony_ci return status; 11138c2ecf20Sopenharmony_ci} 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci/** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 11168c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 11178c2ecf20Sopenharmony_ci * @checksum_val: calculated checksum 11188c2ecf20Sopenharmony_ci * 11198c2ecf20Sopenharmony_ci * Performs checksum calculation and validates the EEPROM checksum. If the 11208c2ecf20Sopenharmony_ci * caller does not need checksum_val, the value can be NULL. 11218c2ecf20Sopenharmony_ci **/ 11228c2ecf20Sopenharmony_cistatic s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 11238c2ecf20Sopenharmony_ci u16 *checksum_val) 11248c2ecf20Sopenharmony_ci{ 11258c2ecf20Sopenharmony_ci s32 status; 11268c2ecf20Sopenharmony_ci u16 checksum; 11278c2ecf20Sopenharmony_ci u16 read_checksum = 0; 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci /* Read the first word from the EEPROM. If this times out or fails, do 11308c2ecf20Sopenharmony_ci * not continue or we could be in for a very long wait while every 11318c2ecf20Sopenharmony_ci * EEPROM read fails 11328c2ecf20Sopenharmony_ci */ 11338c2ecf20Sopenharmony_ci status = hw->eeprom.ops.read(hw, 0, &checksum); 11348c2ecf20Sopenharmony_ci if (status) { 11358c2ecf20Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 11368c2ecf20Sopenharmony_ci return status; 11378c2ecf20Sopenharmony_ci } 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci status = hw->eeprom.ops.calc_checksum(hw); 11408c2ecf20Sopenharmony_ci if (status < 0) 11418c2ecf20Sopenharmony_ci return status; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci checksum = (u16)(status & 0xffff); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 11468c2ecf20Sopenharmony_ci &read_checksum); 11478c2ecf20Sopenharmony_ci if (status) 11488c2ecf20Sopenharmony_ci return status; 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci /* Verify read checksum from EEPROM is the same as 11518c2ecf20Sopenharmony_ci * calculated checksum 11528c2ecf20Sopenharmony_ci */ 11538c2ecf20Sopenharmony_ci if (read_checksum != checksum) { 11548c2ecf20Sopenharmony_ci status = -EIO; 11558c2ecf20Sopenharmony_ci hw_dbg(hw, "Invalid EEPROM checksum"); 11568c2ecf20Sopenharmony_ci } 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci /* If the user cares, return the calculated checksum */ 11598c2ecf20Sopenharmony_ci if (checksum_val) 11608c2ecf20Sopenharmony_ci *checksum_val = checksum; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci return status; 11638c2ecf20Sopenharmony_ci} 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci/** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 11668c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 11678c2ecf20Sopenharmony_ci * @offset: offset of word in the EEPROM to write 11688c2ecf20Sopenharmony_ci * @data: word write to the EEPROM 11698c2ecf20Sopenharmony_ci * 11708c2ecf20Sopenharmony_ci * Write a 16 bit word to the EEPROM using the hostif. 11718c2ecf20Sopenharmony_ci **/ 11728c2ecf20Sopenharmony_cistatic s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 11738c2ecf20Sopenharmony_ci u16 data) 11748c2ecf20Sopenharmony_ci{ 11758c2ecf20Sopenharmony_ci s32 status; 11768c2ecf20Sopenharmony_ci struct ixgbe_hic_write_shadow_ram buffer; 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 11798c2ecf20Sopenharmony_ci buffer.hdr.req.buf_lenh = 0; 11808c2ecf20Sopenharmony_ci buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 11818c2ecf20Sopenharmony_ci buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci /* one word */ 11848c2ecf20Sopenharmony_ci buffer.length = cpu_to_be16(sizeof(u16)); 11858c2ecf20Sopenharmony_ci buffer.data = data; 11868c2ecf20Sopenharmony_ci buffer.address = cpu_to_be32(offset * 2); 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 11898c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, false); 11908c2ecf20Sopenharmony_ci return status; 11918c2ecf20Sopenharmony_ci} 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci/** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 11948c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 11958c2ecf20Sopenharmony_ci * @offset: offset of word in the EEPROM to write 11968c2ecf20Sopenharmony_ci * @data: word write to the EEPROM 11978c2ecf20Sopenharmony_ci * 11988c2ecf20Sopenharmony_ci * Write a 16 bit word to the EEPROM using the hostif. 11998c2ecf20Sopenharmony_ci **/ 12008c2ecf20Sopenharmony_cistatic s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 12018c2ecf20Sopenharmony_ci{ 12028c2ecf20Sopenharmony_ci s32 status = 0; 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 12058c2ecf20Sopenharmony_ci status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 12068c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 12078c2ecf20Sopenharmony_ci } else { 12088c2ecf20Sopenharmony_ci hw_dbg(hw, "write ee hostif failed to get semaphore"); 12098c2ecf20Sopenharmony_ci status = -EBUSY; 12108c2ecf20Sopenharmony_ci } 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci return status; 12138c2ecf20Sopenharmony_ci} 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci/** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 12168c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 12178c2ecf20Sopenharmony_ci * 12188c2ecf20Sopenharmony_ci * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 12198c2ecf20Sopenharmony_ci **/ 12208c2ecf20Sopenharmony_cistatic s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 12218c2ecf20Sopenharmony_ci{ 12228c2ecf20Sopenharmony_ci s32 status = 0; 12238c2ecf20Sopenharmony_ci union ixgbe_hic_hdr2 buffer; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 12268c2ecf20Sopenharmony_ci buffer.req.buf_lenh = 0; 12278c2ecf20Sopenharmony_ci buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 12288c2ecf20Sopenharmony_ci buffer.req.checksum = FW_DEFAULT_CHECKSUM; 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 12318c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, false); 12328c2ecf20Sopenharmony_ci return status; 12338c2ecf20Sopenharmony_ci} 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci/** 12368c2ecf20Sopenharmony_ci * ixgbe_get_bus_info_X550em - Set PCI bus info 12378c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 12388c2ecf20Sopenharmony_ci * 12398c2ecf20Sopenharmony_ci * Sets bus link width and speed to unknown because X550em is 12408c2ecf20Sopenharmony_ci * not a PCI device. 12418c2ecf20Sopenharmony_ci **/ 12428c2ecf20Sopenharmony_cistatic s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) 12438c2ecf20Sopenharmony_ci{ 12448c2ecf20Sopenharmony_ci hw->bus.type = ixgbe_bus_type_internal; 12458c2ecf20Sopenharmony_ci hw->bus.width = ixgbe_bus_width_unknown; 12468c2ecf20Sopenharmony_ci hw->bus.speed = ixgbe_bus_speed_unknown; 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci hw->mac.ops.set_lan_id(hw); 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci return 0; 12518c2ecf20Sopenharmony_ci} 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci/** 12548c2ecf20Sopenharmony_ci * ixgbe_fw_recovery_mode - Check FW NVM recovery mode 12558c2ecf20Sopenharmony_ci * @hw: pointer t hardware structure 12568c2ecf20Sopenharmony_ci * 12578c2ecf20Sopenharmony_ci * Returns true if in FW NVM recovery mode. 12588c2ecf20Sopenharmony_ci */ 12598c2ecf20Sopenharmony_cistatic bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw) 12608c2ecf20Sopenharmony_ci{ 12618c2ecf20Sopenharmony_ci u32 fwsm; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw)); 12648c2ecf20Sopenharmony_ci return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE); 12658c2ecf20Sopenharmony_ci} 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci/** ixgbe_disable_rx_x550 - Disable RX unit 12688c2ecf20Sopenharmony_ci * 12698c2ecf20Sopenharmony_ci * Enables the Rx DMA unit for x550 12708c2ecf20Sopenharmony_ci **/ 12718c2ecf20Sopenharmony_cistatic void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 12728c2ecf20Sopenharmony_ci{ 12738c2ecf20Sopenharmony_ci u32 rxctrl, pfdtxgswc; 12748c2ecf20Sopenharmony_ci s32 status; 12758c2ecf20Sopenharmony_ci struct ixgbe_hic_disable_rxen fw_cmd; 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 12788c2ecf20Sopenharmony_ci if (rxctrl & IXGBE_RXCTRL_RXEN) { 12798c2ecf20Sopenharmony_ci pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 12808c2ecf20Sopenharmony_ci if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 12818c2ecf20Sopenharmony_ci pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 12828c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 12838c2ecf20Sopenharmony_ci hw->mac.set_lben = true; 12848c2ecf20Sopenharmony_ci } else { 12858c2ecf20Sopenharmony_ci hw->mac.set_lben = false; 12868c2ecf20Sopenharmony_ci } 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 12898c2ecf20Sopenharmony_ci fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 12908c2ecf20Sopenharmony_ci fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 12918c2ecf20Sopenharmony_ci fw_cmd.port_number = hw->bus.lan_id; 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci status = ixgbe_host_interface_command(hw, &fw_cmd, 12948c2ecf20Sopenharmony_ci sizeof(struct ixgbe_hic_disable_rxen), 12958c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, true); 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci /* If we fail - disable RX using register write */ 12988c2ecf20Sopenharmony_ci if (status) { 12998c2ecf20Sopenharmony_ci rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 13008c2ecf20Sopenharmony_ci if (rxctrl & IXGBE_RXCTRL_RXEN) { 13018c2ecf20Sopenharmony_ci rxctrl &= ~IXGBE_RXCTRL_RXEN; 13028c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 13038c2ecf20Sopenharmony_ci } 13048c2ecf20Sopenharmony_ci } 13058c2ecf20Sopenharmony_ci } 13068c2ecf20Sopenharmony_ci} 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci/** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 13098c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 13108c2ecf20Sopenharmony_ci * 13118c2ecf20Sopenharmony_ci * After writing EEPROM to shadow RAM using EEWR register, software calculates 13128c2ecf20Sopenharmony_ci * checksum and updates the EEPROM and instructs the hardware to update 13138c2ecf20Sopenharmony_ci * the flash. 13148c2ecf20Sopenharmony_ci **/ 13158c2ecf20Sopenharmony_cistatic s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 13168c2ecf20Sopenharmony_ci{ 13178c2ecf20Sopenharmony_ci s32 status; 13188c2ecf20Sopenharmony_ci u16 checksum = 0; 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci /* Read the first word from the EEPROM. If this times out or fails, do 13218c2ecf20Sopenharmony_ci * not continue or we could be in for a very long wait while every 13228c2ecf20Sopenharmony_ci * EEPROM read fails 13238c2ecf20Sopenharmony_ci */ 13248c2ecf20Sopenharmony_ci status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 13258c2ecf20Sopenharmony_ci if (status) { 13268c2ecf20Sopenharmony_ci hw_dbg(hw, "EEPROM read failed\n"); 13278c2ecf20Sopenharmony_ci return status; 13288c2ecf20Sopenharmony_ci } 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci status = ixgbe_calc_eeprom_checksum_X550(hw); 13318c2ecf20Sopenharmony_ci if (status < 0) 13328c2ecf20Sopenharmony_ci return status; 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci checksum = (u16)(status & 0xffff); 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 13378c2ecf20Sopenharmony_ci checksum); 13388c2ecf20Sopenharmony_ci if (status) 13398c2ecf20Sopenharmony_ci return status; 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci status = ixgbe_update_flash_X550(hw); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci return status; 13448c2ecf20Sopenharmony_ci} 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci/** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 13478c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 13488c2ecf20Sopenharmony_ci * @offset: offset of word in the EEPROM to write 13498c2ecf20Sopenharmony_ci * @words: number of words 13508c2ecf20Sopenharmony_ci * @data: word(s) write to the EEPROM 13518c2ecf20Sopenharmony_ci * 13528c2ecf20Sopenharmony_ci * 13538c2ecf20Sopenharmony_ci * Write a 16 bit word(s) to the EEPROM using the hostif. 13548c2ecf20Sopenharmony_ci **/ 13558c2ecf20Sopenharmony_cistatic s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 13568c2ecf20Sopenharmony_ci u16 offset, u16 words, 13578c2ecf20Sopenharmony_ci u16 *data) 13588c2ecf20Sopenharmony_ci{ 13598c2ecf20Sopenharmony_ci s32 status = 0; 13608c2ecf20Sopenharmony_ci u32 i = 0; 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci /* Take semaphore for the entire operation. */ 13638c2ecf20Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 13648c2ecf20Sopenharmony_ci if (status) { 13658c2ecf20Sopenharmony_ci hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 13668c2ecf20Sopenharmony_ci return status; 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci for (i = 0; i < words; i++) { 13708c2ecf20Sopenharmony_ci status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 13718c2ecf20Sopenharmony_ci data[i]); 13728c2ecf20Sopenharmony_ci if (status) { 13738c2ecf20Sopenharmony_ci hw_dbg(hw, "Eeprom buffered write failed\n"); 13748c2ecf20Sopenharmony_ci break; 13758c2ecf20Sopenharmony_ci } 13768c2ecf20Sopenharmony_ci } 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci return status; 13818c2ecf20Sopenharmony_ci} 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci/** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 13848c2ecf20Sopenharmony_ci * IOSF device 13858c2ecf20Sopenharmony_ci * 13868c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 13878c2ecf20Sopenharmony_ci * @reg_addr: 32 bit PHY register to write 13888c2ecf20Sopenharmony_ci * @device_type: 3 bit device type 13898c2ecf20Sopenharmony_ci * @data: Data to write to the register 13908c2ecf20Sopenharmony_ci **/ 13918c2ecf20Sopenharmony_cistatic s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 13928c2ecf20Sopenharmony_ci u32 device_type, u32 data) 13938c2ecf20Sopenharmony_ci{ 13948c2ecf20Sopenharmony_ci u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 13958c2ecf20Sopenharmony_ci u32 command, error; 13968c2ecf20Sopenharmony_ci s32 ret; 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 13998c2ecf20Sopenharmony_ci if (ret) 14008c2ecf20Sopenharmony_ci return ret; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci ret = ixgbe_iosf_wait(hw, NULL); 14038c2ecf20Sopenharmony_ci if (ret) 14048c2ecf20Sopenharmony_ci goto out; 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 14078c2ecf20Sopenharmony_ci (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci /* Write IOSF control register */ 14108c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci /* Write IOSF data register */ 14138c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci ret = ixgbe_iosf_wait(hw, &command); 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 14188c2ecf20Sopenharmony_ci error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 14198c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 14208c2ecf20Sopenharmony_ci hw_dbg(hw, "Failed to write, error %x\n", error); 14218c2ecf20Sopenharmony_ci return -EIO; 14228c2ecf20Sopenharmony_ci } 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_ciout: 14258c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, gssr); 14268c2ecf20Sopenharmony_ci return ret; 14278c2ecf20Sopenharmony_ci} 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci/** 14308c2ecf20Sopenharmony_ci * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration 14318c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 14328c2ecf20Sopenharmony_ci * 14338c2ecf20Sopenharmony_ci * iXfI configuration needed for ixgbe_mac_X550EM_x devices. 14348c2ecf20Sopenharmony_ci **/ 14358c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) 14368c2ecf20Sopenharmony_ci{ 14378c2ecf20Sopenharmony_ci s32 status; 14388c2ecf20Sopenharmony_ci u32 reg_val; 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci /* Disable training protocol FSM. */ 14418c2ecf20Sopenharmony_ci status = ixgbe_read_iosf_sb_reg_x550(hw, 14428c2ecf20Sopenharmony_ci IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 14438c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 14448c2ecf20Sopenharmony_ci if (status) 14458c2ecf20Sopenharmony_ci return status; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 14488c2ecf20Sopenharmony_ci status = ixgbe_write_iosf_sb_reg_x550(hw, 14498c2ecf20Sopenharmony_ci IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 14508c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 14518c2ecf20Sopenharmony_ci if (status) 14528c2ecf20Sopenharmony_ci return status; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci /* Disable Flex from training TXFFE. */ 14558c2ecf20Sopenharmony_ci status = ixgbe_read_iosf_sb_reg_x550(hw, 14568c2ecf20Sopenharmony_ci IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 14578c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 14588c2ecf20Sopenharmony_ci if (status) 14598c2ecf20Sopenharmony_ci return status; 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 14628c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 14638c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 14648c2ecf20Sopenharmony_ci status = ixgbe_write_iosf_sb_reg_x550(hw, 14658c2ecf20Sopenharmony_ci IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 14668c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 14678c2ecf20Sopenharmony_ci if (status) 14688c2ecf20Sopenharmony_ci return status; 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci status = ixgbe_read_iosf_sb_reg_x550(hw, 14718c2ecf20Sopenharmony_ci IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 14728c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 14738c2ecf20Sopenharmony_ci if (status) 14748c2ecf20Sopenharmony_ci return status; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 14778c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 14788c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 14798c2ecf20Sopenharmony_ci status = ixgbe_write_iosf_sb_reg_x550(hw, 14808c2ecf20Sopenharmony_ci IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 14818c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 14828c2ecf20Sopenharmony_ci if (status) 14838c2ecf20Sopenharmony_ci return status; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ci /* Enable override for coefficients. */ 14868c2ecf20Sopenharmony_ci status = ixgbe_read_iosf_sb_reg_x550(hw, 14878c2ecf20Sopenharmony_ci IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 14888c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 14898c2ecf20Sopenharmony_ci if (status) 14908c2ecf20Sopenharmony_ci return status; 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 14938c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 14948c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 14958c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 14968c2ecf20Sopenharmony_ci status = ixgbe_write_iosf_sb_reg_x550(hw, 14978c2ecf20Sopenharmony_ci IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 14988c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 14998c2ecf20Sopenharmony_ci return status; 15008c2ecf20Sopenharmony_ci} 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci/** 15038c2ecf20Sopenharmony_ci * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the 15048c2ecf20Sopenharmony_ci * internal PHY 15058c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 15068c2ecf20Sopenharmony_ci **/ 15078c2ecf20Sopenharmony_cistatic s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw) 15088c2ecf20Sopenharmony_ci{ 15098c2ecf20Sopenharmony_ci s32 status; 15108c2ecf20Sopenharmony_ci u32 link_ctrl; 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci /* Restart auto-negotiation. */ 15138c2ecf20Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 15148c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 15158c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci if (status) { 15188c2ecf20Sopenharmony_ci hw_dbg(hw, "Auto-negotiation did not complete\n"); 15198c2ecf20Sopenharmony_ci return status; 15208c2ecf20Sopenharmony_ci } 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 15238c2ecf20Sopenharmony_ci status = hw->mac.ops.write_iosf_sb_reg(hw, 15248c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 15258c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci if (hw->mac.type == ixgbe_mac_x550em_a) { 15288c2ecf20Sopenharmony_ci u32 flx_mask_st20; 15298c2ecf20Sopenharmony_ci 15308c2ecf20Sopenharmony_ci /* Indicate to FW that AN restart has been asserted */ 15318c2ecf20Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 15328c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 15338c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20); 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci if (status) { 15368c2ecf20Sopenharmony_ci hw_dbg(hw, "Auto-negotiation did not complete\n"); 15378c2ecf20Sopenharmony_ci return status; 15388c2ecf20Sopenharmony_ci } 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART; 15418c2ecf20Sopenharmony_ci status = hw->mac.ops.write_iosf_sb_reg(hw, 15428c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 15438c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20); 15448c2ecf20Sopenharmony_ci } 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci return status; 15478c2ecf20Sopenharmony_ci} 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 15508c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 15518c2ecf20Sopenharmony_ci * @speed: the link speed to force 15528c2ecf20Sopenharmony_ci * 15538c2ecf20Sopenharmony_ci * Configures the integrated KR PHY to use iXFI mode. Used to connect an 15548c2ecf20Sopenharmony_ci * internal and external PHY at a specific speed, without autonegotiation. 15558c2ecf20Sopenharmony_ci **/ 15568c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 15578c2ecf20Sopenharmony_ci{ 15588c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 15598c2ecf20Sopenharmony_ci s32 status; 15608c2ecf20Sopenharmony_ci u32 reg_val; 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci /* iXFI is only supported with X552 */ 15638c2ecf20Sopenharmony_ci if (mac->type != ixgbe_mac_X550EM_x) 15648c2ecf20Sopenharmony_ci return -EIO; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci /* Disable AN and force speed to 10G Serial. */ 15678c2ecf20Sopenharmony_ci status = ixgbe_read_iosf_sb_reg_x550(hw, 15688c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 15698c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 15708c2ecf20Sopenharmony_ci if (status) 15718c2ecf20Sopenharmony_ci return status; 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 15748c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci /* Select forced link speed for internal PHY. */ 15778c2ecf20Sopenharmony_ci switch (*speed) { 15788c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_10GB_FULL: 15798c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 15808c2ecf20Sopenharmony_ci break; 15818c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_1GB_FULL: 15828c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 15838c2ecf20Sopenharmony_ci break; 15848c2ecf20Sopenharmony_ci default: 15858c2ecf20Sopenharmony_ci /* Other link speeds are not supported by internal KR PHY. */ 15868c2ecf20Sopenharmony_ci return -EINVAL; 15878c2ecf20Sopenharmony_ci } 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci status = ixgbe_write_iosf_sb_reg_x550(hw, 15908c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 15918c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 15928c2ecf20Sopenharmony_ci if (status) 15938c2ecf20Sopenharmony_ci return status; 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci /* Additional configuration needed for x550em_x */ 15968c2ecf20Sopenharmony_ci if (hw->mac.type == ixgbe_mac_X550EM_x) { 15978c2ecf20Sopenharmony_ci status = ixgbe_setup_ixfi_x550em_x(hw); 15988c2ecf20Sopenharmony_ci if (status) 15998c2ecf20Sopenharmony_ci return status; 16008c2ecf20Sopenharmony_ci } 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci /* Toggle port SW reset by AN reset. */ 16038c2ecf20Sopenharmony_ci status = ixgbe_restart_an_internal_phy_x550em(hw); 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci return status; 16068c2ecf20Sopenharmony_ci} 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci/** 16098c2ecf20Sopenharmony_ci * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported 16108c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 16118c2ecf20Sopenharmony_ci * @linear: true if SFP module is linear 16128c2ecf20Sopenharmony_ci */ 16138c2ecf20Sopenharmony_cistatic s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) 16148c2ecf20Sopenharmony_ci{ 16158c2ecf20Sopenharmony_ci switch (hw->phy.sfp_type) { 16168c2ecf20Sopenharmony_ci case ixgbe_sfp_type_not_present: 16178c2ecf20Sopenharmony_ci return -ENOENT; 16188c2ecf20Sopenharmony_ci case ixgbe_sfp_type_da_cu_core0: 16198c2ecf20Sopenharmony_ci case ixgbe_sfp_type_da_cu_core1: 16208c2ecf20Sopenharmony_ci *linear = true; 16218c2ecf20Sopenharmony_ci break; 16228c2ecf20Sopenharmony_ci case ixgbe_sfp_type_srlr_core0: 16238c2ecf20Sopenharmony_ci case ixgbe_sfp_type_srlr_core1: 16248c2ecf20Sopenharmony_ci case ixgbe_sfp_type_da_act_lmt_core0: 16258c2ecf20Sopenharmony_ci case ixgbe_sfp_type_da_act_lmt_core1: 16268c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_sx_core0: 16278c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_sx_core1: 16288c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_lx_core0: 16298c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_lx_core1: 16308c2ecf20Sopenharmony_ci *linear = false; 16318c2ecf20Sopenharmony_ci break; 16328c2ecf20Sopenharmony_ci case ixgbe_sfp_type_unknown: 16338c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_cu_core0: 16348c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_cu_core1: 16358c2ecf20Sopenharmony_ci default: 16368c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 16378c2ecf20Sopenharmony_ci } 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci return 0; 16408c2ecf20Sopenharmony_ci} 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci/** 16438c2ecf20Sopenharmony_ci * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. 16448c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 16458c2ecf20Sopenharmony_ci * @speed: the link speed to force 16468c2ecf20Sopenharmony_ci * @autoneg_wait_to_complete: unused 16478c2ecf20Sopenharmony_ci * 16488c2ecf20Sopenharmony_ci * Configures the extern PHY and the integrated KR PHY for SFP support. 16498c2ecf20Sopenharmony_ci */ 16508c2ecf20Sopenharmony_cistatic s32 16518c2ecf20Sopenharmony_ciixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, 16528c2ecf20Sopenharmony_ci ixgbe_link_speed speed, 16538c2ecf20Sopenharmony_ci __always_unused bool autoneg_wait_to_complete) 16548c2ecf20Sopenharmony_ci{ 16558c2ecf20Sopenharmony_ci s32 status; 16568c2ecf20Sopenharmony_ci u16 reg_slice, reg_val; 16578c2ecf20Sopenharmony_ci bool setup_linear = false; 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci /* Check if SFP module is supported and linear */ 16608c2ecf20Sopenharmony_ci status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci /* If no SFP module present, then return success. Return success since 16638c2ecf20Sopenharmony_ci * there is no reason to configure CS4227 and SFP not present error is 16648c2ecf20Sopenharmony_ci * not accepted in the setup MAC link flow. 16658c2ecf20Sopenharmony_ci */ 16668c2ecf20Sopenharmony_ci if (status == -ENOENT) 16678c2ecf20Sopenharmony_ci return 0; 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci if (status) 16708c2ecf20Sopenharmony_ci return status; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci /* Configure internal PHY for KR/KX. */ 16738c2ecf20Sopenharmony_ci ixgbe_setup_kr_speed_x550em(hw, speed); 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci /* Configure CS4227 LINE side to proper mode. */ 16768c2ecf20Sopenharmony_ci reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 16778c2ecf20Sopenharmony_ci if (setup_linear) 16788c2ecf20Sopenharmony_ci reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; 16798c2ecf20Sopenharmony_ci else 16808c2ecf20Sopenharmony_ci reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, 16838c2ecf20Sopenharmony_ci reg_val); 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci return status; 16868c2ecf20Sopenharmony_ci} 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci/** 16898c2ecf20Sopenharmony_ci * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode 16908c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 16918c2ecf20Sopenharmony_ci * @speed: the link speed to force 16928c2ecf20Sopenharmony_ci * 16938c2ecf20Sopenharmony_ci * Configures the integrated PHY for native SFI mode. Used to connect the 16948c2ecf20Sopenharmony_ci * internal PHY directly to an SFP cage, without autonegotiation. 16958c2ecf20Sopenharmony_ci **/ 16968c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 16978c2ecf20Sopenharmony_ci{ 16988c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 16998c2ecf20Sopenharmony_ci s32 status; 17008c2ecf20Sopenharmony_ci u32 reg_val; 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci /* Disable all AN and force speed to 10G Serial. */ 17038c2ecf20Sopenharmony_ci status = mac->ops.read_iosf_sb_reg(hw, 17048c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 17058c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 17068c2ecf20Sopenharmony_ci if (status) 17078c2ecf20Sopenharmony_ci return status; 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 17108c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 17118c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 17128c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci /* Select forced link speed for internal PHY. */ 17158c2ecf20Sopenharmony_ci switch (*speed) { 17168c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_10GB_FULL: 17178c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G; 17188c2ecf20Sopenharmony_ci break; 17198c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_1GB_FULL: 17208c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; 17218c2ecf20Sopenharmony_ci break; 17228c2ecf20Sopenharmony_ci default: 17238c2ecf20Sopenharmony_ci /* Other link speeds are not supported by internal PHY. */ 17248c2ecf20Sopenharmony_ci return -EINVAL; 17258c2ecf20Sopenharmony_ci } 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci status = mac->ops.write_iosf_sb_reg(hw, 17288c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 17298c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci /* Toggle port SW reset by AN reset. */ 17328c2ecf20Sopenharmony_ci status = ixgbe_restart_an_internal_phy_x550em(hw); 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci return status; 17358c2ecf20Sopenharmony_ci} 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci/** 17388c2ecf20Sopenharmony_ci * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP 17398c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 17408c2ecf20Sopenharmony_ci * @speed: link speed 17418c2ecf20Sopenharmony_ci * @autoneg_wait_to_complete: unused 17428c2ecf20Sopenharmony_ci * 17438c2ecf20Sopenharmony_ci * Configure the the integrated PHY for native SFP support. 17448c2ecf20Sopenharmony_ci */ 17458c2ecf20Sopenharmony_cistatic s32 17468c2ecf20Sopenharmony_ciixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, 17478c2ecf20Sopenharmony_ci __always_unused bool autoneg_wait_to_complete) 17488c2ecf20Sopenharmony_ci{ 17498c2ecf20Sopenharmony_ci bool setup_linear = false; 17508c2ecf20Sopenharmony_ci u32 reg_phy_int; 17518c2ecf20Sopenharmony_ci s32 ret_val; 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci /* Check if SFP module is supported and linear */ 17548c2ecf20Sopenharmony_ci ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci /* If no SFP module present, then return success. Return success since 17578c2ecf20Sopenharmony_ci * SFP not present error is not excepted in the setup MAC link flow. 17588c2ecf20Sopenharmony_ci */ 17598c2ecf20Sopenharmony_ci if (ret_val == -ENOENT) 17608c2ecf20Sopenharmony_ci return 0; 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci if (ret_val) 17638c2ecf20Sopenharmony_ci return ret_val; 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci /* Configure internal PHY for native SFI based on module type */ 17668c2ecf20Sopenharmony_ci ret_val = hw->mac.ops.read_iosf_sb_reg(hw, 17678c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 17688c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int); 17698c2ecf20Sopenharmony_ci if (ret_val) 17708c2ecf20Sopenharmony_ci return ret_val; 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA; 17738c2ecf20Sopenharmony_ci if (!setup_linear) 17748c2ecf20Sopenharmony_ci reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci ret_val = hw->mac.ops.write_iosf_sb_reg(hw, 17778c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 17788c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int); 17798c2ecf20Sopenharmony_ci if (ret_val) 17808c2ecf20Sopenharmony_ci return ret_val; 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci /* Setup SFI internal link. */ 17838c2ecf20Sopenharmony_ci return ixgbe_setup_sfi_x550a(hw, &speed); 17848c2ecf20Sopenharmony_ci} 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_ci/** 17878c2ecf20Sopenharmony_ci * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP 17888c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 17898c2ecf20Sopenharmony_ci * @speed: link speed 17908c2ecf20Sopenharmony_ci * @autoneg_wait_to_complete: unused 17918c2ecf20Sopenharmony_ci * 17928c2ecf20Sopenharmony_ci * Configure the the integrated PHY for SFP support. 17938c2ecf20Sopenharmony_ci */ 17948c2ecf20Sopenharmony_cistatic s32 17958c2ecf20Sopenharmony_ciixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, 17968c2ecf20Sopenharmony_ci __always_unused bool autoneg_wait_to_complete) 17978c2ecf20Sopenharmony_ci{ 17988c2ecf20Sopenharmony_ci u32 reg_slice, slice_offset; 17998c2ecf20Sopenharmony_ci bool setup_linear = false; 18008c2ecf20Sopenharmony_ci u16 reg_phy_ext; 18018c2ecf20Sopenharmony_ci s32 ret_val; 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci /* Check if SFP module is supported and linear */ 18048c2ecf20Sopenharmony_ci ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci /* If no SFP module present, then return success. Return success since 18078c2ecf20Sopenharmony_ci * SFP not present error is not excepted in the setup MAC link flow. 18088c2ecf20Sopenharmony_ci */ 18098c2ecf20Sopenharmony_ci if (ret_val == -ENOENT) 18108c2ecf20Sopenharmony_ci return 0; 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci if (ret_val) 18138c2ecf20Sopenharmony_ci return ret_val; 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci /* Configure internal PHY for KR/KX. */ 18168c2ecf20Sopenharmony_ci ixgbe_setup_kr_speed_x550em(hw, speed); 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE) 18198c2ecf20Sopenharmony_ci return -EFAULT; 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci /* Get external PHY SKU id */ 18228c2ecf20Sopenharmony_ci ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU, 18238c2ecf20Sopenharmony_ci IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 18248c2ecf20Sopenharmony_ci if (ret_val) 18258c2ecf20Sopenharmony_ci return ret_val; 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci /* When configuring quad port CS4223, the MAC instance is part 18288c2ecf20Sopenharmony_ci * of the slice offset. 18298c2ecf20Sopenharmony_ci */ 18308c2ecf20Sopenharmony_ci if (reg_phy_ext == IXGBE_CS4223_SKU_ID) 18318c2ecf20Sopenharmony_ci slice_offset = (hw->bus.lan_id + 18328c2ecf20Sopenharmony_ci (hw->bus.instance_id << 1)) << 12; 18338c2ecf20Sopenharmony_ci else 18348c2ecf20Sopenharmony_ci slice_offset = hw->bus.lan_id << 12; 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci /* Configure CS4227/CS4223 LINE side to proper mode. */ 18378c2ecf20Sopenharmony_ci reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci ret_val = hw->phy.ops.read_reg(hw, reg_slice, 18408c2ecf20Sopenharmony_ci IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 18418c2ecf20Sopenharmony_ci if (ret_val) 18428c2ecf20Sopenharmony_ci return ret_val; 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) | 18458c2ecf20Sopenharmony_ci (IXGBE_CS4227_EDC_MODE_SR << 1)); 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci if (setup_linear) 18488c2ecf20Sopenharmony_ci reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 18498c2ecf20Sopenharmony_ci else 18508c2ecf20Sopenharmony_ci reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci ret_val = hw->phy.ops.write_reg(hw, reg_slice, 18538c2ecf20Sopenharmony_ci IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext); 18548c2ecf20Sopenharmony_ci if (ret_val) 18558c2ecf20Sopenharmony_ci return ret_val; 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci /* Flush previous write with a read */ 18588c2ecf20Sopenharmony_ci return hw->phy.ops.read_reg(hw, reg_slice, 18598c2ecf20Sopenharmony_ci IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 18608c2ecf20Sopenharmony_ci} 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci/** 18638c2ecf20Sopenharmony_ci * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 18648c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 18658c2ecf20Sopenharmony_ci * @speed: new link speed 18668c2ecf20Sopenharmony_ci * @autoneg_wait: true when waiting for completion is needed 18678c2ecf20Sopenharmony_ci * 18688c2ecf20Sopenharmony_ci * Setup internal/external PHY link speed based on link speed, then set 18698c2ecf20Sopenharmony_ci * external PHY auto advertised link speed. 18708c2ecf20Sopenharmony_ci * 18718c2ecf20Sopenharmony_ci * Returns error status for any failure 18728c2ecf20Sopenharmony_ci **/ 18738c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 18748c2ecf20Sopenharmony_ci ixgbe_link_speed speed, 18758c2ecf20Sopenharmony_ci bool autoneg_wait) 18768c2ecf20Sopenharmony_ci{ 18778c2ecf20Sopenharmony_ci s32 status; 18788c2ecf20Sopenharmony_ci ixgbe_link_speed force_speed; 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci /* Setup internal/external PHY link speed to iXFI (10G), unless 18818c2ecf20Sopenharmony_ci * only 1G is auto advertised then setup KX link. 18828c2ecf20Sopenharmony_ci */ 18838c2ecf20Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_10GB_FULL) 18848c2ecf20Sopenharmony_ci force_speed = IXGBE_LINK_SPEED_10GB_FULL; 18858c2ecf20Sopenharmony_ci else 18868c2ecf20Sopenharmony_ci force_speed = IXGBE_LINK_SPEED_1GB_FULL; 18878c2ecf20Sopenharmony_ci 18888c2ecf20Sopenharmony_ci /* If X552 and internal link mode is XFI, then setup XFI internal link. 18898c2ecf20Sopenharmony_ci */ 18908c2ecf20Sopenharmony_ci if (hw->mac.type == ixgbe_mac_X550EM_x && 18918c2ecf20Sopenharmony_ci !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 18928c2ecf20Sopenharmony_ci status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci if (status) 18958c2ecf20Sopenharmony_ci return status; 18968c2ecf20Sopenharmony_ci } 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 18998c2ecf20Sopenharmony_ci} 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_ci/** ixgbe_check_link_t_X550em - Determine link and speed status 19028c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 19038c2ecf20Sopenharmony_ci * @speed: pointer to link speed 19048c2ecf20Sopenharmony_ci * @link_up: true when link is up 19058c2ecf20Sopenharmony_ci * @link_up_wait_to_complete: bool used to wait for link up or not 19068c2ecf20Sopenharmony_ci * 19078c2ecf20Sopenharmony_ci * Check that both the MAC and X557 external PHY have link. 19088c2ecf20Sopenharmony_ci **/ 19098c2ecf20Sopenharmony_cistatic s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, 19108c2ecf20Sopenharmony_ci ixgbe_link_speed *speed, 19118c2ecf20Sopenharmony_ci bool *link_up, 19128c2ecf20Sopenharmony_ci bool link_up_wait_to_complete) 19138c2ecf20Sopenharmony_ci{ 19148c2ecf20Sopenharmony_ci u32 status; 19158c2ecf20Sopenharmony_ci u16 i, autoneg_status; 19168c2ecf20Sopenharmony_ci 19178c2ecf20Sopenharmony_ci if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 19188c2ecf20Sopenharmony_ci return -EIO; 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci status = ixgbe_check_mac_link_generic(hw, speed, link_up, 19218c2ecf20Sopenharmony_ci link_up_wait_to_complete); 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci /* If check link fails or MAC link is not up, then return */ 19248c2ecf20Sopenharmony_ci if (status || !(*link_up)) 19258c2ecf20Sopenharmony_ci return status; 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci /* MAC link is up, so check external PHY link. 19288c2ecf20Sopenharmony_ci * Link status is latching low, and can only be used to detect link 19298c2ecf20Sopenharmony_ci * drop, and not the current status of the link without performing 19308c2ecf20Sopenharmony_ci * back-to-back reads. 19318c2ecf20Sopenharmony_ci */ 19328c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 19338c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 19348c2ecf20Sopenharmony_ci &autoneg_status); 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci if (status) 19378c2ecf20Sopenharmony_ci return status; 19388c2ecf20Sopenharmony_ci } 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_ci /* If external PHY link is not up, then indicate link not up */ 19418c2ecf20Sopenharmony_ci if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 19428c2ecf20Sopenharmony_ci *link_up = false; 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci return 0; 19458c2ecf20Sopenharmony_ci} 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci/** 19488c2ecf20Sopenharmony_ci * ixgbe_setup_sgmii - Set up link for sgmii 19498c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 19508c2ecf20Sopenharmony_ci * @speed: unused 19518c2ecf20Sopenharmony_ci * @autoneg_wait_to_complete: unused 19528c2ecf20Sopenharmony_ci */ 19538c2ecf20Sopenharmony_cistatic s32 19548c2ecf20Sopenharmony_ciixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, 19558c2ecf20Sopenharmony_ci __always_unused bool autoneg_wait_to_complete) 19568c2ecf20Sopenharmony_ci{ 19578c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 19588c2ecf20Sopenharmony_ci u32 lval, sval, flx_val; 19598c2ecf20Sopenharmony_ci s32 rc; 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 19628c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 19638c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 19648c2ecf20Sopenharmony_ci if (rc) 19658c2ecf20Sopenharmony_ci return rc; 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_ci lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 19688c2ecf20Sopenharmony_ci lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 19698c2ecf20Sopenharmony_ci lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 19708c2ecf20Sopenharmony_ci lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 19718c2ecf20Sopenharmony_ci lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 19728c2ecf20Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 19738c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 19748c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 19758c2ecf20Sopenharmony_ci if (rc) 19768c2ecf20Sopenharmony_ci return rc; 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 19798c2ecf20Sopenharmony_ci IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 19808c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 19818c2ecf20Sopenharmony_ci if (rc) 19828c2ecf20Sopenharmony_ci return rc; 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_ci sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 19858c2ecf20Sopenharmony_ci sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 19868c2ecf20Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 19878c2ecf20Sopenharmony_ci IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 19888c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 19898c2ecf20Sopenharmony_ci if (rc) 19908c2ecf20Sopenharmony_ci return rc; 19918c2ecf20Sopenharmony_ci 19928c2ecf20Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 19938c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 19948c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 19958c2ecf20Sopenharmony_ci if (rc) 19968c2ecf20Sopenharmony_ci return rc; 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 19998c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 20008c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 20018c2ecf20Sopenharmony_ci if (rc) 20028c2ecf20Sopenharmony_ci return rc; 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 20058c2ecf20Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; 20068c2ecf20Sopenharmony_ci flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 20078c2ecf20Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 20088c2ecf20Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 20118c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 20128c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); 20138c2ecf20Sopenharmony_ci if (rc) 20148c2ecf20Sopenharmony_ci return rc; 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci rc = ixgbe_restart_an_internal_phy_x550em(hw); 20178c2ecf20Sopenharmony_ci return rc; 20188c2ecf20Sopenharmony_ci} 20198c2ecf20Sopenharmony_ci 20208c2ecf20Sopenharmony_ci/** 20218c2ecf20Sopenharmony_ci * ixgbe_setup_sgmii_fw - Set up link for sgmii with firmware-controlled PHYs 20228c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 20238c2ecf20Sopenharmony_ci * @speed: the link speed to force 20248c2ecf20Sopenharmony_ci * @autoneg_wait: true when waiting for completion is needed 20258c2ecf20Sopenharmony_ci */ 20268c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed, 20278c2ecf20Sopenharmony_ci bool autoneg_wait) 20288c2ecf20Sopenharmony_ci{ 20298c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 20308c2ecf20Sopenharmony_ci u32 lval, sval, flx_val; 20318c2ecf20Sopenharmony_ci s32 rc; 20328c2ecf20Sopenharmony_ci 20338c2ecf20Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 20348c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 20358c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 20368c2ecf20Sopenharmony_ci if (rc) 20378c2ecf20Sopenharmony_ci return rc; 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_ci lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 20408c2ecf20Sopenharmony_ci lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 20418c2ecf20Sopenharmony_ci lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 20428c2ecf20Sopenharmony_ci lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 20438c2ecf20Sopenharmony_ci lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 20448c2ecf20Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 20458c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 20468c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 20478c2ecf20Sopenharmony_ci if (rc) 20488c2ecf20Sopenharmony_ci return rc; 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 20518c2ecf20Sopenharmony_ci IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 20528c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 20538c2ecf20Sopenharmony_ci if (rc) 20548c2ecf20Sopenharmony_ci return rc; 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 20578c2ecf20Sopenharmony_ci sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 20588c2ecf20Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 20598c2ecf20Sopenharmony_ci IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 20608c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 20618c2ecf20Sopenharmony_ci if (rc) 20628c2ecf20Sopenharmony_ci return rc; 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 20658c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 20668c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 20678c2ecf20Sopenharmony_ci if (rc) 20688c2ecf20Sopenharmony_ci return rc; 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_ci rc = mac->ops.read_iosf_sb_reg(hw, 20718c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 20728c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 20738c2ecf20Sopenharmony_ci if (rc) 20748c2ecf20Sopenharmony_ci return rc; 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 20778c2ecf20Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; 20788c2ecf20Sopenharmony_ci flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 20798c2ecf20Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 20808c2ecf20Sopenharmony_ci flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci rc = mac->ops.write_iosf_sb_reg(hw, 20838c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 20848c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); 20858c2ecf20Sopenharmony_ci if (rc) 20868c2ecf20Sopenharmony_ci return rc; 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_ci ixgbe_restart_an_internal_phy_x550em(hw); 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 20918c2ecf20Sopenharmony_ci} 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci/** 20948c2ecf20Sopenharmony_ci * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37 20958c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 20968c2ecf20Sopenharmony_ci * 20978c2ecf20Sopenharmony_ci * Enable flow control according to IEEE clause 37. 20988c2ecf20Sopenharmony_ci */ 20998c2ecf20Sopenharmony_cistatic void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw) 21008c2ecf20Sopenharmony_ci{ 21018c2ecf20Sopenharmony_ci u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 }; 21028c2ecf20Sopenharmony_ci ixgbe_link_speed speed; 21038c2ecf20Sopenharmony_ci s32 status = -EIO; 21048c2ecf20Sopenharmony_ci bool link_up; 21058c2ecf20Sopenharmony_ci 21068c2ecf20Sopenharmony_ci /* AN should have completed when the cable was plugged in. 21078c2ecf20Sopenharmony_ci * Look for reasons to bail out. Bail out if: 21088c2ecf20Sopenharmony_ci * - FC autoneg is disabled, or if 21098c2ecf20Sopenharmony_ci * - link is not up. 21108c2ecf20Sopenharmony_ci */ 21118c2ecf20Sopenharmony_ci if (hw->fc.disable_fc_autoneg) 21128c2ecf20Sopenharmony_ci goto out; 21138c2ecf20Sopenharmony_ci 21148c2ecf20Sopenharmony_ci hw->mac.ops.check_link(hw, &speed, &link_up, false); 21158c2ecf20Sopenharmony_ci if (!link_up) 21168c2ecf20Sopenharmony_ci goto out; 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci /* Check if auto-negotiation has completed */ 21198c2ecf20Sopenharmony_ci status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info); 21208c2ecf20Sopenharmony_ci if (status || !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) { 21218c2ecf20Sopenharmony_ci status = -EIO; 21228c2ecf20Sopenharmony_ci goto out; 21238c2ecf20Sopenharmony_ci } 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci /* Negotiate the flow control */ 21268c2ecf20Sopenharmony_ci status = ixgbe_negotiate_fc(hw, info[0], info[0], 21278c2ecf20Sopenharmony_ci FW_PHY_ACT_GET_LINK_INFO_FC_RX, 21288c2ecf20Sopenharmony_ci FW_PHY_ACT_GET_LINK_INFO_FC_TX, 21298c2ecf20Sopenharmony_ci FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX, 21308c2ecf20Sopenharmony_ci FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX); 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_ciout: 21338c2ecf20Sopenharmony_ci if (!status) { 21348c2ecf20Sopenharmony_ci hw->fc.fc_was_autonegged = true; 21358c2ecf20Sopenharmony_ci } else { 21368c2ecf20Sopenharmony_ci hw->fc.fc_was_autonegged = false; 21378c2ecf20Sopenharmony_ci hw->fc.current_mode = hw->fc.requested_mode; 21388c2ecf20Sopenharmony_ci } 21398c2ecf20Sopenharmony_ci} 21408c2ecf20Sopenharmony_ci 21418c2ecf20Sopenharmony_ci/** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers 21428c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 21438c2ecf20Sopenharmony_ci **/ 21448c2ecf20Sopenharmony_cistatic void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw) 21458c2ecf20Sopenharmony_ci{ 21468c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 21478c2ecf20Sopenharmony_ci 21488c2ecf20Sopenharmony_ci switch (mac->ops.get_media_type(hw)) { 21498c2ecf20Sopenharmony_ci case ixgbe_media_type_fiber: 21508c2ecf20Sopenharmony_ci mac->ops.setup_fc = NULL; 21518c2ecf20Sopenharmony_ci mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; 21528c2ecf20Sopenharmony_ci break; 21538c2ecf20Sopenharmony_ci case ixgbe_media_type_copper: 21548c2ecf20Sopenharmony_ci if (hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T && 21558c2ecf20Sopenharmony_ci hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T_L) { 21568c2ecf20Sopenharmony_ci mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 21578c2ecf20Sopenharmony_ci break; 21588c2ecf20Sopenharmony_ci } 21598c2ecf20Sopenharmony_ci mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a; 21608c2ecf20Sopenharmony_ci mac->ops.setup_fc = ixgbe_fc_autoneg_fw; 21618c2ecf20Sopenharmony_ci mac->ops.setup_link = ixgbe_setup_sgmii_fw; 21628c2ecf20Sopenharmony_ci mac->ops.check_link = ixgbe_check_mac_link_generic; 21638c2ecf20Sopenharmony_ci break; 21648c2ecf20Sopenharmony_ci case ixgbe_media_type_backplane: 21658c2ecf20Sopenharmony_ci mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; 21668c2ecf20Sopenharmony_ci mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; 21678c2ecf20Sopenharmony_ci break; 21688c2ecf20Sopenharmony_ci default: 21698c2ecf20Sopenharmony_ci break; 21708c2ecf20Sopenharmony_ci } 21718c2ecf20Sopenharmony_ci} 21728c2ecf20Sopenharmony_ci 21738c2ecf20Sopenharmony_ci/** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 21748c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 21758c2ecf20Sopenharmony_ci **/ 21768c2ecf20Sopenharmony_cistatic void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 21778c2ecf20Sopenharmony_ci{ 21788c2ecf20Sopenharmony_ci struct ixgbe_mac_info *mac = &hw->mac; 21798c2ecf20Sopenharmony_ci 21808c2ecf20Sopenharmony_ci mac->ops.setup_fc = ixgbe_setup_fc_x550em; 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_ci switch (mac->ops.get_media_type(hw)) { 21838c2ecf20Sopenharmony_ci case ixgbe_media_type_fiber: 21848c2ecf20Sopenharmony_ci /* CS4227 does not support autoneg, so disable the laser control 21858c2ecf20Sopenharmony_ci * functions for SFP+ fiber 21868c2ecf20Sopenharmony_ci */ 21878c2ecf20Sopenharmony_ci mac->ops.disable_tx_laser = NULL; 21888c2ecf20Sopenharmony_ci mac->ops.enable_tx_laser = NULL; 21898c2ecf20Sopenharmony_ci mac->ops.flap_tx_laser = NULL; 21908c2ecf20Sopenharmony_ci mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; 21918c2ecf20Sopenharmony_ci switch (hw->device_id) { 21928c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP_N: 21938c2ecf20Sopenharmony_ci mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; 21948c2ecf20Sopenharmony_ci break; 21958c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP: 21968c2ecf20Sopenharmony_ci mac->ops.setup_mac_link = 21978c2ecf20Sopenharmony_ci ixgbe_setup_mac_link_sfp_x550a; 21988c2ecf20Sopenharmony_ci break; 21998c2ecf20Sopenharmony_ci default: 22008c2ecf20Sopenharmony_ci mac->ops.setup_mac_link = 22018c2ecf20Sopenharmony_ci ixgbe_setup_mac_link_sfp_x550em; 22028c2ecf20Sopenharmony_ci break; 22038c2ecf20Sopenharmony_ci } 22048c2ecf20Sopenharmony_ci mac->ops.set_rate_select_speed = 22058c2ecf20Sopenharmony_ci ixgbe_set_soft_rate_select_speed; 22068c2ecf20Sopenharmony_ci break; 22078c2ecf20Sopenharmony_ci case ixgbe_media_type_copper: 22088c2ecf20Sopenharmony_ci if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T) 22098c2ecf20Sopenharmony_ci break; 22108c2ecf20Sopenharmony_ci mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 22118c2ecf20Sopenharmony_ci mac->ops.setup_fc = ixgbe_setup_fc_generic; 22128c2ecf20Sopenharmony_ci mac->ops.check_link = ixgbe_check_link_t_X550em; 22138c2ecf20Sopenharmony_ci break; 22148c2ecf20Sopenharmony_ci case ixgbe_media_type_backplane: 22158c2ecf20Sopenharmony_ci if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || 22168c2ecf20Sopenharmony_ci hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) 22178c2ecf20Sopenharmony_ci mac->ops.setup_link = ixgbe_setup_sgmii; 22188c2ecf20Sopenharmony_ci break; 22198c2ecf20Sopenharmony_ci default: 22208c2ecf20Sopenharmony_ci break; 22218c2ecf20Sopenharmony_ci } 22228c2ecf20Sopenharmony_ci 22238c2ecf20Sopenharmony_ci /* Additional modification for X550em_a devices */ 22248c2ecf20Sopenharmony_ci if (hw->mac.type == ixgbe_mac_x550em_a) 22258c2ecf20Sopenharmony_ci ixgbe_init_mac_link_ops_X550em_a(hw); 22268c2ecf20Sopenharmony_ci} 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci/** ixgbe_setup_sfp_modules_X550em - Setup SFP module 22298c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 22308c2ecf20Sopenharmony_ci */ 22318c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 22328c2ecf20Sopenharmony_ci{ 22338c2ecf20Sopenharmony_ci s32 status; 22348c2ecf20Sopenharmony_ci bool linear; 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci /* Check if SFP module is supported */ 22378c2ecf20Sopenharmony_ci status = ixgbe_supported_sfp_modules_X550em(hw, &linear); 22388c2ecf20Sopenharmony_ci if (status) 22398c2ecf20Sopenharmony_ci return status; 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci ixgbe_init_mac_link_ops_X550em(hw); 22428c2ecf20Sopenharmony_ci hw->phy.ops.reset = NULL; 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci return 0; 22458c2ecf20Sopenharmony_ci} 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci/** ixgbe_get_link_capabilities_x550em - Determines link capabilities 22488c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 22498c2ecf20Sopenharmony_ci * @speed: pointer to link speed 22508c2ecf20Sopenharmony_ci * @autoneg: true when autoneg or autotry is enabled 22518c2ecf20Sopenharmony_ci **/ 22528c2ecf20Sopenharmony_cistatic s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 22538c2ecf20Sopenharmony_ci ixgbe_link_speed *speed, 22548c2ecf20Sopenharmony_ci bool *autoneg) 22558c2ecf20Sopenharmony_ci{ 22568c2ecf20Sopenharmony_ci if (hw->phy.type == ixgbe_phy_fw) { 22578c2ecf20Sopenharmony_ci *autoneg = true; 22588c2ecf20Sopenharmony_ci *speed = hw->phy.speeds_supported; 22598c2ecf20Sopenharmony_ci return 0; 22608c2ecf20Sopenharmony_ci } 22618c2ecf20Sopenharmony_ci 22628c2ecf20Sopenharmony_ci /* SFP */ 22638c2ecf20Sopenharmony_ci if (hw->phy.media_type == ixgbe_media_type_fiber) { 22648c2ecf20Sopenharmony_ci /* CS4227 SFP must not enable auto-negotiation */ 22658c2ecf20Sopenharmony_ci *autoneg = false; 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_ci if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 22688c2ecf20Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 || 22698c2ecf20Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || 22708c2ecf20Sopenharmony_ci hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) { 22718c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 22728c2ecf20Sopenharmony_ci return 0; 22738c2ecf20Sopenharmony_ci } 22748c2ecf20Sopenharmony_ci 22758c2ecf20Sopenharmony_ci /* Link capabilities are based on SFP */ 22768c2ecf20Sopenharmony_ci if (hw->phy.multispeed_fiber) 22778c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL | 22788c2ecf20Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL; 22798c2ecf20Sopenharmony_ci else 22808c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL; 22818c2ecf20Sopenharmony_ci } else { 22828c2ecf20Sopenharmony_ci switch (hw->phy.type) { 22838c2ecf20Sopenharmony_ci case ixgbe_phy_x550em_kx4: 22848c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL | 22858c2ecf20Sopenharmony_ci IXGBE_LINK_SPEED_2_5GB_FULL | 22868c2ecf20Sopenharmony_ci IXGBE_LINK_SPEED_10GB_FULL; 22878c2ecf20Sopenharmony_ci break; 22888c2ecf20Sopenharmony_ci case ixgbe_phy_x550em_xfi: 22898c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL | 22908c2ecf20Sopenharmony_ci IXGBE_LINK_SPEED_10GB_FULL; 22918c2ecf20Sopenharmony_ci break; 22928c2ecf20Sopenharmony_ci case ixgbe_phy_ext_1g_t: 22938c2ecf20Sopenharmony_ci case ixgbe_phy_sgmii: 22948c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 22958c2ecf20Sopenharmony_ci break; 22968c2ecf20Sopenharmony_ci case ixgbe_phy_x550em_kr: 22978c2ecf20Sopenharmony_ci if (hw->mac.type == ixgbe_mac_x550em_a) { 22988c2ecf20Sopenharmony_ci /* check different backplane modes */ 22998c2ecf20Sopenharmony_ci if (hw->phy.nw_mng_if_sel & 23008c2ecf20Sopenharmony_ci IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) { 23018c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 23028c2ecf20Sopenharmony_ci break; 23038c2ecf20Sopenharmony_ci } else if (hw->device_id == 23048c2ecf20Sopenharmony_ci IXGBE_DEV_ID_X550EM_A_KR_L) { 23058c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_1GB_FULL; 23068c2ecf20Sopenharmony_ci break; 23078c2ecf20Sopenharmony_ci } 23088c2ecf20Sopenharmony_ci } 23098c2ecf20Sopenharmony_ci fallthrough; 23108c2ecf20Sopenharmony_ci default: 23118c2ecf20Sopenharmony_ci *speed = IXGBE_LINK_SPEED_10GB_FULL | 23128c2ecf20Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL; 23138c2ecf20Sopenharmony_ci break; 23148c2ecf20Sopenharmony_ci } 23158c2ecf20Sopenharmony_ci *autoneg = true; 23168c2ecf20Sopenharmony_ci } 23178c2ecf20Sopenharmony_ci return 0; 23188c2ecf20Sopenharmony_ci} 23198c2ecf20Sopenharmony_ci 23208c2ecf20Sopenharmony_ci/** 23218c2ecf20Sopenharmony_ci * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause 23228c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 23238c2ecf20Sopenharmony_ci * @lsc: pointer to boolean flag which indicates whether external Base T 23248c2ecf20Sopenharmony_ci * PHY interrupt is lsc 23258c2ecf20Sopenharmony_ci * @is_overtemp: indicate whether an overtemp event encountered 23268c2ecf20Sopenharmony_ci * 23278c2ecf20Sopenharmony_ci * Determime if external Base T PHY interrupt cause is high temperature 23288c2ecf20Sopenharmony_ci * failure alarm or link status change. 23298c2ecf20Sopenharmony_ci **/ 23308c2ecf20Sopenharmony_cistatic s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc, 23318c2ecf20Sopenharmony_ci bool *is_overtemp) 23328c2ecf20Sopenharmony_ci{ 23338c2ecf20Sopenharmony_ci u32 status; 23348c2ecf20Sopenharmony_ci u16 reg; 23358c2ecf20Sopenharmony_ci 23368c2ecf20Sopenharmony_ci *is_overtemp = false; 23378c2ecf20Sopenharmony_ci *lsc = false; 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci /* Vendor alarm triggered */ 23408c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 23418c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 23428c2ecf20Sopenharmony_ci ®); 23438c2ecf20Sopenharmony_ci 23448c2ecf20Sopenharmony_ci if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 23458c2ecf20Sopenharmony_ci return status; 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 23488c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 23498c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 23508c2ecf20Sopenharmony_ci ®); 23518c2ecf20Sopenharmony_ci 23528c2ecf20Sopenharmony_ci if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 23538c2ecf20Sopenharmony_ci IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 23548c2ecf20Sopenharmony_ci return status; 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_ci /* Global alarm triggered */ 23578c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 23588c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 23598c2ecf20Sopenharmony_ci ®); 23608c2ecf20Sopenharmony_ci 23618c2ecf20Sopenharmony_ci if (status) 23628c2ecf20Sopenharmony_ci return status; 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci /* If high temperature failure, then return over temp error and exit */ 23658c2ecf20Sopenharmony_ci if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 23668c2ecf20Sopenharmony_ci /* power down the PHY in case the PHY FW didn't already */ 23678c2ecf20Sopenharmony_ci ixgbe_set_copper_phy_power(hw, false); 23688c2ecf20Sopenharmony_ci *is_overtemp = true; 23698c2ecf20Sopenharmony_ci return -EIO; 23708c2ecf20Sopenharmony_ci } 23718c2ecf20Sopenharmony_ci if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { 23728c2ecf20Sopenharmony_ci /* device fault alarm triggered */ 23738c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, 23748c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 23758c2ecf20Sopenharmony_ci ®); 23768c2ecf20Sopenharmony_ci if (status) 23778c2ecf20Sopenharmony_ci return status; 23788c2ecf20Sopenharmony_ci 23798c2ecf20Sopenharmony_ci /* if device fault was due to high temp alarm handle and exit */ 23808c2ecf20Sopenharmony_ci if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { 23818c2ecf20Sopenharmony_ci /* power down the PHY in case the PHY FW didn't */ 23828c2ecf20Sopenharmony_ci ixgbe_set_copper_phy_power(hw, false); 23838c2ecf20Sopenharmony_ci *is_overtemp = true; 23848c2ecf20Sopenharmony_ci return -EIO; 23858c2ecf20Sopenharmony_ci } 23868c2ecf20Sopenharmony_ci } 23878c2ecf20Sopenharmony_ci 23888c2ecf20Sopenharmony_ci /* Vendor alarm 2 triggered */ 23898c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 23908c2ecf20Sopenharmony_ci MDIO_MMD_AN, ®); 23918c2ecf20Sopenharmony_ci 23928c2ecf20Sopenharmony_ci if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 23938c2ecf20Sopenharmony_ci return status; 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_ci /* link connect/disconnect event occurred */ 23968c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 23978c2ecf20Sopenharmony_ci MDIO_MMD_AN, ®); 23988c2ecf20Sopenharmony_ci 23998c2ecf20Sopenharmony_ci if (status) 24008c2ecf20Sopenharmony_ci return status; 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_ci /* Indicate LSC */ 24038c2ecf20Sopenharmony_ci if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 24048c2ecf20Sopenharmony_ci *lsc = true; 24058c2ecf20Sopenharmony_ci 24068c2ecf20Sopenharmony_ci return 0; 24078c2ecf20Sopenharmony_ci} 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci/** 24108c2ecf20Sopenharmony_ci * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 24118c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 24128c2ecf20Sopenharmony_ci * 24138c2ecf20Sopenharmony_ci * Enable link status change and temperature failure alarm for the external 24148c2ecf20Sopenharmony_ci * Base T PHY 24158c2ecf20Sopenharmony_ci * 24168c2ecf20Sopenharmony_ci * Returns PHY access status 24178c2ecf20Sopenharmony_ci **/ 24188c2ecf20Sopenharmony_cistatic s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 24198c2ecf20Sopenharmony_ci{ 24208c2ecf20Sopenharmony_ci bool lsc, overtemp; 24218c2ecf20Sopenharmony_ci u32 status; 24228c2ecf20Sopenharmony_ci u16 reg; 24238c2ecf20Sopenharmony_ci 24248c2ecf20Sopenharmony_ci /* Clear interrupt flags */ 24258c2ecf20Sopenharmony_ci status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, &overtemp); 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci /* Enable link status change alarm */ 24288c2ecf20Sopenharmony_ci 24298c2ecf20Sopenharmony_ci /* Enable the LASI interrupts on X552 devices to receive notifications 24308c2ecf20Sopenharmony_ci * of the link configurations of the external PHY and correspondingly 24318c2ecf20Sopenharmony_ci * support the configuration of the internal iXFI link, since iXFI does 24328c2ecf20Sopenharmony_ci * not support auto-negotiation. This is not required for X553 devices 24338c2ecf20Sopenharmony_ci * having KR support, which performs auto-negotiations and which is used 24348c2ecf20Sopenharmony_ci * as the internal link to the external PHY. Hence adding a check here 24358c2ecf20Sopenharmony_ci * to avoid enabling LASI interrupts for X553 devices. 24368c2ecf20Sopenharmony_ci */ 24378c2ecf20Sopenharmony_ci if (hw->mac.type != ixgbe_mac_x550em_a) { 24388c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, 24398c2ecf20Sopenharmony_ci IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 24408c2ecf20Sopenharmony_ci MDIO_MMD_AN, ®); 24418c2ecf20Sopenharmony_ci if (status) 24428c2ecf20Sopenharmony_ci return status; 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_ci reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 24458c2ecf20Sopenharmony_ci 24468c2ecf20Sopenharmony_ci status = hw->phy.ops.write_reg(hw, 24478c2ecf20Sopenharmony_ci IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 24488c2ecf20Sopenharmony_ci MDIO_MMD_AN, reg); 24498c2ecf20Sopenharmony_ci if (status) 24508c2ecf20Sopenharmony_ci return status; 24518c2ecf20Sopenharmony_ci } 24528c2ecf20Sopenharmony_ci 24538c2ecf20Sopenharmony_ci /* Enable high temperature failure and global fault alarms */ 24548c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 24558c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 24568c2ecf20Sopenharmony_ci ®); 24578c2ecf20Sopenharmony_ci if (status) 24588c2ecf20Sopenharmony_ci return status; 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | 24618c2ecf20Sopenharmony_ci IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_ci status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 24648c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 24658c2ecf20Sopenharmony_ci reg); 24668c2ecf20Sopenharmony_ci if (status) 24678c2ecf20Sopenharmony_ci return status; 24688c2ecf20Sopenharmony_ci 24698c2ecf20Sopenharmony_ci /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 24708c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 24718c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 24728c2ecf20Sopenharmony_ci ®); 24738c2ecf20Sopenharmony_ci if (status) 24748c2ecf20Sopenharmony_ci return status; 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_ci reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 24778c2ecf20Sopenharmony_ci IXGBE_MDIO_GLOBAL_ALARM_1_INT); 24788c2ecf20Sopenharmony_ci 24798c2ecf20Sopenharmony_ci status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 24808c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 24818c2ecf20Sopenharmony_ci reg); 24828c2ecf20Sopenharmony_ci if (status) 24838c2ecf20Sopenharmony_ci return status; 24848c2ecf20Sopenharmony_ci 24858c2ecf20Sopenharmony_ci /* Enable chip-wide vendor alarm */ 24868c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 24878c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 24888c2ecf20Sopenharmony_ci ®); 24898c2ecf20Sopenharmony_ci if (status) 24908c2ecf20Sopenharmony_ci return status; 24918c2ecf20Sopenharmony_ci 24928c2ecf20Sopenharmony_ci reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 24938c2ecf20Sopenharmony_ci 24948c2ecf20Sopenharmony_ci status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 24958c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 24968c2ecf20Sopenharmony_ci reg); 24978c2ecf20Sopenharmony_ci 24988c2ecf20Sopenharmony_ci return status; 24998c2ecf20Sopenharmony_ci} 25008c2ecf20Sopenharmony_ci 25018c2ecf20Sopenharmony_ci/** 25028c2ecf20Sopenharmony_ci * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 25038c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 25048c2ecf20Sopenharmony_ci * @is_overtemp: indicate whether an overtemp event encountered 25058c2ecf20Sopenharmony_ci * 25068c2ecf20Sopenharmony_ci * Handle external Base T PHY interrupt. If high temperature 25078c2ecf20Sopenharmony_ci * failure alarm then return error, else if link status change 25088c2ecf20Sopenharmony_ci * then setup internal/external PHY link 25098c2ecf20Sopenharmony_ci **/ 25108c2ecf20Sopenharmony_cistatic s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw, 25118c2ecf20Sopenharmony_ci bool *is_overtemp) 25128c2ecf20Sopenharmony_ci{ 25138c2ecf20Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 25148c2ecf20Sopenharmony_ci bool lsc; 25158c2ecf20Sopenharmony_ci u32 status; 25168c2ecf20Sopenharmony_ci 25178c2ecf20Sopenharmony_ci status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, is_overtemp); 25188c2ecf20Sopenharmony_ci if (status) 25198c2ecf20Sopenharmony_ci return status; 25208c2ecf20Sopenharmony_ci 25218c2ecf20Sopenharmony_ci if (lsc && phy->ops.setup_internal_link) 25228c2ecf20Sopenharmony_ci return phy->ops.setup_internal_link(hw); 25238c2ecf20Sopenharmony_ci 25248c2ecf20Sopenharmony_ci return 0; 25258c2ecf20Sopenharmony_ci} 25268c2ecf20Sopenharmony_ci 25278c2ecf20Sopenharmony_ci/** 25288c2ecf20Sopenharmony_ci * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 25298c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 25308c2ecf20Sopenharmony_ci * @speed: link speed 25318c2ecf20Sopenharmony_ci * 25328c2ecf20Sopenharmony_ci * Configures the integrated KR PHY. 25338c2ecf20Sopenharmony_ci **/ 25348c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 25358c2ecf20Sopenharmony_ci ixgbe_link_speed speed) 25368c2ecf20Sopenharmony_ci{ 25378c2ecf20Sopenharmony_ci s32 status; 25388c2ecf20Sopenharmony_ci u32 reg_val; 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 25418c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 25428c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 25438c2ecf20Sopenharmony_ci if (status) 25448c2ecf20Sopenharmony_ci return status; 25458c2ecf20Sopenharmony_ci 25468c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 25478c2ecf20Sopenharmony_ci reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 25488c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 25498c2ecf20Sopenharmony_ci 25508c2ecf20Sopenharmony_ci /* Advertise 10G support. */ 25518c2ecf20Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_10GB_FULL) 25528c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci /* Advertise 1G support. */ 25558c2ecf20Sopenharmony_ci if (speed & IXGBE_LINK_SPEED_1GB_FULL) 25568c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_ci status = hw->mac.ops.write_iosf_sb_reg(hw, 25598c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 25608c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 25618c2ecf20Sopenharmony_ci 25628c2ecf20Sopenharmony_ci if (hw->mac.type == ixgbe_mac_x550em_a) { 25638c2ecf20Sopenharmony_ci /* Set lane mode to KR auto negotiation */ 25648c2ecf20Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 25658c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 25668c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 25678c2ecf20Sopenharmony_ci 25688c2ecf20Sopenharmony_ci if (status) 25698c2ecf20Sopenharmony_ci return status; 25708c2ecf20Sopenharmony_ci 25718c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 25728c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; 25738c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 25748c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 25758c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci status = hw->mac.ops.write_iosf_sb_reg(hw, 25788c2ecf20Sopenharmony_ci IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 25798c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 25808c2ecf20Sopenharmony_ci } 25818c2ecf20Sopenharmony_ci 25828c2ecf20Sopenharmony_ci return ixgbe_restart_an_internal_phy_x550em(hw); 25838c2ecf20Sopenharmony_ci} 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_ci/** 25868c2ecf20Sopenharmony_ci * ixgbe_setup_kr_x550em - Configure the KR PHY 25878c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 25888c2ecf20Sopenharmony_ci **/ 25898c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 25908c2ecf20Sopenharmony_ci{ 25918c2ecf20Sopenharmony_ci /* leave link alone for 2.5G */ 25928c2ecf20Sopenharmony_ci if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) 25938c2ecf20Sopenharmony_ci return 0; 25948c2ecf20Sopenharmony_ci 25958c2ecf20Sopenharmony_ci if (ixgbe_check_reset_blocked(hw)) 25968c2ecf20Sopenharmony_ci return 0; 25978c2ecf20Sopenharmony_ci 25988c2ecf20Sopenharmony_ci return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 25998c2ecf20Sopenharmony_ci} 26008c2ecf20Sopenharmony_ci 26018c2ecf20Sopenharmony_ci/** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 26028c2ecf20Sopenharmony_ci * @hw: address of hardware structure 26038c2ecf20Sopenharmony_ci * @link_up: address of boolean to indicate link status 26048c2ecf20Sopenharmony_ci * 26058c2ecf20Sopenharmony_ci * Returns error code if unable to get link status. 26068c2ecf20Sopenharmony_ci **/ 26078c2ecf20Sopenharmony_cistatic s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 26088c2ecf20Sopenharmony_ci{ 26098c2ecf20Sopenharmony_ci u32 ret; 26108c2ecf20Sopenharmony_ci u16 autoneg_status; 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_ci *link_up = false; 26138c2ecf20Sopenharmony_ci 26148c2ecf20Sopenharmony_ci /* read this twice back to back to indicate current status */ 26158c2ecf20Sopenharmony_ci ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 26168c2ecf20Sopenharmony_ci &autoneg_status); 26178c2ecf20Sopenharmony_ci if (ret) 26188c2ecf20Sopenharmony_ci return ret; 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_ci ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 26218c2ecf20Sopenharmony_ci &autoneg_status); 26228c2ecf20Sopenharmony_ci if (ret) 26238c2ecf20Sopenharmony_ci return ret; 26248c2ecf20Sopenharmony_ci 26258c2ecf20Sopenharmony_ci *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 26268c2ecf20Sopenharmony_ci 26278c2ecf20Sopenharmony_ci return 0; 26288c2ecf20Sopenharmony_ci} 26298c2ecf20Sopenharmony_ci 26308c2ecf20Sopenharmony_ci/** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 26318c2ecf20Sopenharmony_ci * @hw: point to hardware structure 26328c2ecf20Sopenharmony_ci * 26338c2ecf20Sopenharmony_ci * Configures the link between the integrated KR PHY and the external X557 PHY 26348c2ecf20Sopenharmony_ci * The driver will call this function when it gets a link status change 26358c2ecf20Sopenharmony_ci * interrupt from the X557 PHY. This function configures the link speed 26368c2ecf20Sopenharmony_ci * between the PHYs to match the link speed of the BASE-T link. 26378c2ecf20Sopenharmony_ci * 26388c2ecf20Sopenharmony_ci * A return of a non-zero value indicates an error, and the base driver should 26398c2ecf20Sopenharmony_ci * not report link up. 26408c2ecf20Sopenharmony_ci **/ 26418c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 26428c2ecf20Sopenharmony_ci{ 26438c2ecf20Sopenharmony_ci ixgbe_link_speed force_speed; 26448c2ecf20Sopenharmony_ci bool link_up; 26458c2ecf20Sopenharmony_ci u32 status; 26468c2ecf20Sopenharmony_ci u16 speed; 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_ci if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 26498c2ecf20Sopenharmony_ci return -EIO; 26508c2ecf20Sopenharmony_ci 26518c2ecf20Sopenharmony_ci if (!(hw->mac.type == ixgbe_mac_X550EM_x && 26528c2ecf20Sopenharmony_ci !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))) { 26538c2ecf20Sopenharmony_ci speed = IXGBE_LINK_SPEED_10GB_FULL | 26548c2ecf20Sopenharmony_ci IXGBE_LINK_SPEED_1GB_FULL; 26558c2ecf20Sopenharmony_ci return ixgbe_setup_kr_speed_x550em(hw, speed); 26568c2ecf20Sopenharmony_ci } 26578c2ecf20Sopenharmony_ci 26588c2ecf20Sopenharmony_ci /* If link is not up, then there is no setup necessary so return */ 26598c2ecf20Sopenharmony_ci status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 26608c2ecf20Sopenharmony_ci if (status) 26618c2ecf20Sopenharmony_ci return status; 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ci if (!link_up) 26648c2ecf20Sopenharmony_ci return 0; 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 26678c2ecf20Sopenharmony_ci MDIO_MMD_AN, 26688c2ecf20Sopenharmony_ci &speed); 26698c2ecf20Sopenharmony_ci if (status) 26708c2ecf20Sopenharmony_ci return status; 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ci /* If link is not still up, then no setup is necessary so return */ 26738c2ecf20Sopenharmony_ci status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 26748c2ecf20Sopenharmony_ci if (status) 26758c2ecf20Sopenharmony_ci return status; 26768c2ecf20Sopenharmony_ci 26778c2ecf20Sopenharmony_ci if (!link_up) 26788c2ecf20Sopenharmony_ci return 0; 26798c2ecf20Sopenharmony_ci 26808c2ecf20Sopenharmony_ci /* clear everything but the speed and duplex bits */ 26818c2ecf20Sopenharmony_ci speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 26828c2ecf20Sopenharmony_ci 26838c2ecf20Sopenharmony_ci switch (speed) { 26848c2ecf20Sopenharmony_ci case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 26858c2ecf20Sopenharmony_ci force_speed = IXGBE_LINK_SPEED_10GB_FULL; 26868c2ecf20Sopenharmony_ci break; 26878c2ecf20Sopenharmony_ci case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 26888c2ecf20Sopenharmony_ci force_speed = IXGBE_LINK_SPEED_1GB_FULL; 26898c2ecf20Sopenharmony_ci break; 26908c2ecf20Sopenharmony_ci default: 26918c2ecf20Sopenharmony_ci /* Internal PHY does not support anything else */ 26928c2ecf20Sopenharmony_ci return -EINVAL; 26938c2ecf20Sopenharmony_ci } 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci return ixgbe_setup_ixfi_x550em(hw, &force_speed); 26968c2ecf20Sopenharmony_ci} 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_ci/** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 26998c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 27008c2ecf20Sopenharmony_ci **/ 27018c2ecf20Sopenharmony_cistatic s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 27028c2ecf20Sopenharmony_ci{ 27038c2ecf20Sopenharmony_ci s32 status; 27048c2ecf20Sopenharmony_ci 27058c2ecf20Sopenharmony_ci status = ixgbe_reset_phy_generic(hw); 27068c2ecf20Sopenharmony_ci 27078c2ecf20Sopenharmony_ci if (status) 27088c2ecf20Sopenharmony_ci return status; 27098c2ecf20Sopenharmony_ci 27108c2ecf20Sopenharmony_ci /* Configure Link Status Alarm and Temperature Threshold interrupts */ 27118c2ecf20Sopenharmony_ci return ixgbe_enable_lasi_ext_t_x550em(hw); 27128c2ecf20Sopenharmony_ci} 27138c2ecf20Sopenharmony_ci 27148c2ecf20Sopenharmony_ci/** 27158c2ecf20Sopenharmony_ci * ixgbe_led_on_t_x550em - Turns on the software controllable LEDs. 27168c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 27178c2ecf20Sopenharmony_ci * @led_idx: led number to turn on 27188c2ecf20Sopenharmony_ci **/ 27198c2ecf20Sopenharmony_cistatic s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 27208c2ecf20Sopenharmony_ci{ 27218c2ecf20Sopenharmony_ci u16 phy_data; 27228c2ecf20Sopenharmony_ci 27238c2ecf20Sopenharmony_ci if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 27248c2ecf20Sopenharmony_ci return -EINVAL; 27258c2ecf20Sopenharmony_ci 27268c2ecf20Sopenharmony_ci /* To turn on the LED, set mode to ON. */ 27278c2ecf20Sopenharmony_ci hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 27288c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, &phy_data); 27298c2ecf20Sopenharmony_ci phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; 27308c2ecf20Sopenharmony_ci hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 27318c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, phy_data); 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci return 0; 27348c2ecf20Sopenharmony_ci} 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci/** 27378c2ecf20Sopenharmony_ci * ixgbe_led_off_t_x550em - Turns off the software controllable LEDs. 27388c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 27398c2ecf20Sopenharmony_ci * @led_idx: led number to turn off 27408c2ecf20Sopenharmony_ci **/ 27418c2ecf20Sopenharmony_cistatic s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 27428c2ecf20Sopenharmony_ci{ 27438c2ecf20Sopenharmony_ci u16 phy_data; 27448c2ecf20Sopenharmony_ci 27458c2ecf20Sopenharmony_ci if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 27468c2ecf20Sopenharmony_ci return -EINVAL; 27478c2ecf20Sopenharmony_ci 27488c2ecf20Sopenharmony_ci /* To turn on the LED, set mode to ON. */ 27498c2ecf20Sopenharmony_ci hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 27508c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, &phy_data); 27518c2ecf20Sopenharmony_ci phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; 27528c2ecf20Sopenharmony_ci hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 27538c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, phy_data); 27548c2ecf20Sopenharmony_ci 27558c2ecf20Sopenharmony_ci return 0; 27568c2ecf20Sopenharmony_ci} 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci/** 27598c2ecf20Sopenharmony_ci * ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware 27608c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 27618c2ecf20Sopenharmony_ci * @maj: driver version major number 27628c2ecf20Sopenharmony_ci * @min: driver version minor number 27638c2ecf20Sopenharmony_ci * @build: driver version build number 27648c2ecf20Sopenharmony_ci * @sub: driver version sub build number 27658c2ecf20Sopenharmony_ci * @len: length of driver_ver string 27668c2ecf20Sopenharmony_ci * @driver_ver: driver string 27678c2ecf20Sopenharmony_ci * 27688c2ecf20Sopenharmony_ci * Sends driver version number to firmware through the manageability 27698c2ecf20Sopenharmony_ci * block. On success return 0 27708c2ecf20Sopenharmony_ci * else returns -EBUSY when encountering an error acquiring 27718c2ecf20Sopenharmony_ci * semaphore, -EIO when command fails or -ENIVAL when incorrect 27728c2ecf20Sopenharmony_ci * params passed. 27738c2ecf20Sopenharmony_ci **/ 27748c2ecf20Sopenharmony_cistatic s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min, 27758c2ecf20Sopenharmony_ci u8 build, u8 sub, u16 len, 27768c2ecf20Sopenharmony_ci const char *driver_ver) 27778c2ecf20Sopenharmony_ci{ 27788c2ecf20Sopenharmony_ci struct ixgbe_hic_drv_info2 fw_cmd; 27798c2ecf20Sopenharmony_ci s32 ret_val; 27808c2ecf20Sopenharmony_ci int i; 27818c2ecf20Sopenharmony_ci 27828c2ecf20Sopenharmony_ci if (!len || !driver_ver || (len > sizeof(fw_cmd.driver_string))) 27838c2ecf20Sopenharmony_ci return -EINVAL; 27848c2ecf20Sopenharmony_ci 27858c2ecf20Sopenharmony_ci fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 27868c2ecf20Sopenharmony_ci fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len; 27878c2ecf20Sopenharmony_ci fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 27888c2ecf20Sopenharmony_ci fw_cmd.port_num = (u8)hw->bus.func; 27898c2ecf20Sopenharmony_ci fw_cmd.ver_maj = maj; 27908c2ecf20Sopenharmony_ci fw_cmd.ver_min = min; 27918c2ecf20Sopenharmony_ci fw_cmd.ver_build = build; 27928c2ecf20Sopenharmony_ci fw_cmd.ver_sub = sub; 27938c2ecf20Sopenharmony_ci fw_cmd.hdr.checksum = 0; 27948c2ecf20Sopenharmony_ci memcpy(fw_cmd.driver_string, driver_ver, len); 27958c2ecf20Sopenharmony_ci fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 27968c2ecf20Sopenharmony_ci (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 27978c2ecf20Sopenharmony_ci 27988c2ecf20Sopenharmony_ci for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 27998c2ecf20Sopenharmony_ci ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 28008c2ecf20Sopenharmony_ci sizeof(fw_cmd), 28018c2ecf20Sopenharmony_ci IXGBE_HI_COMMAND_TIMEOUT, 28028c2ecf20Sopenharmony_ci true); 28038c2ecf20Sopenharmony_ci if (ret_val) 28048c2ecf20Sopenharmony_ci continue; 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_ci if (fw_cmd.hdr.cmd_or_resp.ret_status != 28078c2ecf20Sopenharmony_ci FW_CEM_RESP_STATUS_SUCCESS) 28088c2ecf20Sopenharmony_ci return -EIO; 28098c2ecf20Sopenharmony_ci return 0; 28108c2ecf20Sopenharmony_ci } 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci return ret_val; 28138c2ecf20Sopenharmony_ci} 28148c2ecf20Sopenharmony_ci 28158c2ecf20Sopenharmony_ci/** ixgbe_get_lcd_x550em - Determine lowest common denominator 28168c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 28178c2ecf20Sopenharmony_ci * @lcd_speed: pointer to lowest common link speed 28188c2ecf20Sopenharmony_ci * 28198c2ecf20Sopenharmony_ci * Determine lowest common link speed with link partner. 28208c2ecf20Sopenharmony_ci **/ 28218c2ecf20Sopenharmony_cistatic s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, 28228c2ecf20Sopenharmony_ci ixgbe_link_speed *lcd_speed) 28238c2ecf20Sopenharmony_ci{ 28248c2ecf20Sopenharmony_ci u16 an_lp_status; 28258c2ecf20Sopenharmony_ci s32 status; 28268c2ecf20Sopenharmony_ci u16 word = hw->eeprom.ctrl_word_3; 28278c2ecf20Sopenharmony_ci 28288c2ecf20Sopenharmony_ci *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, 28318c2ecf20Sopenharmony_ci MDIO_MMD_AN, 28328c2ecf20Sopenharmony_ci &an_lp_status); 28338c2ecf20Sopenharmony_ci if (status) 28348c2ecf20Sopenharmony_ci return status; 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_ci /* If link partner advertised 1G, return 1G */ 28378c2ecf20Sopenharmony_ci if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { 28388c2ecf20Sopenharmony_ci *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; 28398c2ecf20Sopenharmony_ci return status; 28408c2ecf20Sopenharmony_ci } 28418c2ecf20Sopenharmony_ci 28428c2ecf20Sopenharmony_ci /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ 28438c2ecf20Sopenharmony_ci if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || 28448c2ecf20Sopenharmony_ci (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) 28458c2ecf20Sopenharmony_ci return status; 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_ci /* Link partner not capable of lower speeds, return 10G */ 28488c2ecf20Sopenharmony_ci *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; 28498c2ecf20Sopenharmony_ci return status; 28508c2ecf20Sopenharmony_ci} 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci/** 28538c2ecf20Sopenharmony_ci * ixgbe_setup_fc_x550em - Set up flow control 28548c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 28558c2ecf20Sopenharmony_ci */ 28568c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) 28578c2ecf20Sopenharmony_ci{ 28588c2ecf20Sopenharmony_ci bool pause, asm_dir; 28598c2ecf20Sopenharmony_ci u32 reg_val; 28608c2ecf20Sopenharmony_ci s32 rc = 0; 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_ci /* Validate the requested mode */ 28638c2ecf20Sopenharmony_ci if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 28648c2ecf20Sopenharmony_ci hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 28658c2ecf20Sopenharmony_ci return -EINVAL; 28668c2ecf20Sopenharmony_ci } 28678c2ecf20Sopenharmony_ci 28688c2ecf20Sopenharmony_ci /* 10gig parts do not have a word in the EEPROM to determine the 28698c2ecf20Sopenharmony_ci * default flow control setting, so we explicitly set it to full. 28708c2ecf20Sopenharmony_ci */ 28718c2ecf20Sopenharmony_ci if (hw->fc.requested_mode == ixgbe_fc_default) 28728c2ecf20Sopenharmony_ci hw->fc.requested_mode = ixgbe_fc_full; 28738c2ecf20Sopenharmony_ci 28748c2ecf20Sopenharmony_ci /* Determine PAUSE and ASM_DIR bits. */ 28758c2ecf20Sopenharmony_ci switch (hw->fc.requested_mode) { 28768c2ecf20Sopenharmony_ci case ixgbe_fc_none: 28778c2ecf20Sopenharmony_ci pause = false; 28788c2ecf20Sopenharmony_ci asm_dir = false; 28798c2ecf20Sopenharmony_ci break; 28808c2ecf20Sopenharmony_ci case ixgbe_fc_tx_pause: 28818c2ecf20Sopenharmony_ci pause = false; 28828c2ecf20Sopenharmony_ci asm_dir = true; 28838c2ecf20Sopenharmony_ci break; 28848c2ecf20Sopenharmony_ci case ixgbe_fc_rx_pause: 28858c2ecf20Sopenharmony_ci /* Rx Flow control is enabled and Tx Flow control is 28868c2ecf20Sopenharmony_ci * disabled by software override. Since there really 28878c2ecf20Sopenharmony_ci * isn't a way to advertise that we are capable of RX 28888c2ecf20Sopenharmony_ci * Pause ONLY, we will advertise that we support both 28898c2ecf20Sopenharmony_ci * symmetric and asymmetric Rx PAUSE, as such we fall 28908c2ecf20Sopenharmony_ci * through to the fc_full statement. Later, we will 28918c2ecf20Sopenharmony_ci * disable the adapter's ability to send PAUSE frames. 28928c2ecf20Sopenharmony_ci */ 28938c2ecf20Sopenharmony_ci fallthrough; 28948c2ecf20Sopenharmony_ci case ixgbe_fc_full: 28958c2ecf20Sopenharmony_ci pause = true; 28968c2ecf20Sopenharmony_ci asm_dir = true; 28978c2ecf20Sopenharmony_ci break; 28988c2ecf20Sopenharmony_ci default: 28998c2ecf20Sopenharmony_ci hw_err(hw, "Flow control param set incorrectly\n"); 29008c2ecf20Sopenharmony_ci return -EIO; 29018c2ecf20Sopenharmony_ci } 29028c2ecf20Sopenharmony_ci 29038c2ecf20Sopenharmony_ci switch (hw->device_id) { 29048c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KR: 29058c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR: 29068c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR_L: 29078c2ecf20Sopenharmony_ci rc = hw->mac.ops.read_iosf_sb_reg(hw, 29088c2ecf20Sopenharmony_ci IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 29098c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, 29108c2ecf20Sopenharmony_ci ®_val); 29118c2ecf20Sopenharmony_ci if (rc) 29128c2ecf20Sopenharmony_ci return rc; 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_ci reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 29158c2ecf20Sopenharmony_ci IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 29168c2ecf20Sopenharmony_ci if (pause) 29178c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 29188c2ecf20Sopenharmony_ci if (asm_dir) 29198c2ecf20Sopenharmony_ci reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 29208c2ecf20Sopenharmony_ci rc = hw->mac.ops.write_iosf_sb_reg(hw, 29218c2ecf20Sopenharmony_ci IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 29228c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, 29238c2ecf20Sopenharmony_ci reg_val); 29248c2ecf20Sopenharmony_ci 29258c2ecf20Sopenharmony_ci /* This device does not fully support AN. */ 29268c2ecf20Sopenharmony_ci hw->fc.disable_fc_autoneg = true; 29278c2ecf20Sopenharmony_ci break; 29288c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_XFI: 29298c2ecf20Sopenharmony_ci hw->fc.disable_fc_autoneg = true; 29308c2ecf20Sopenharmony_ci break; 29318c2ecf20Sopenharmony_ci default: 29328c2ecf20Sopenharmony_ci break; 29338c2ecf20Sopenharmony_ci } 29348c2ecf20Sopenharmony_ci return rc; 29358c2ecf20Sopenharmony_ci} 29368c2ecf20Sopenharmony_ci 29378c2ecf20Sopenharmony_ci/** 29388c2ecf20Sopenharmony_ci * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 29398c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 29408c2ecf20Sopenharmony_ci **/ 29418c2ecf20Sopenharmony_cistatic void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) 29428c2ecf20Sopenharmony_ci{ 29438c2ecf20Sopenharmony_ci u32 link_s1, lp_an_page_low, an_cntl_1; 29448c2ecf20Sopenharmony_ci ixgbe_link_speed speed; 29458c2ecf20Sopenharmony_ci s32 status = -EIO; 29468c2ecf20Sopenharmony_ci bool link_up; 29478c2ecf20Sopenharmony_ci 29488c2ecf20Sopenharmony_ci /* AN should have completed when the cable was plugged in. 29498c2ecf20Sopenharmony_ci * Look for reasons to bail out. Bail out if: 29508c2ecf20Sopenharmony_ci * - FC autoneg is disabled, or if 29518c2ecf20Sopenharmony_ci * - link is not up. 29528c2ecf20Sopenharmony_ci */ 29538c2ecf20Sopenharmony_ci if (hw->fc.disable_fc_autoneg) { 29548c2ecf20Sopenharmony_ci hw_err(hw, "Flow control autoneg is disabled"); 29558c2ecf20Sopenharmony_ci goto out; 29568c2ecf20Sopenharmony_ci } 29578c2ecf20Sopenharmony_ci 29588c2ecf20Sopenharmony_ci hw->mac.ops.check_link(hw, &speed, &link_up, false); 29598c2ecf20Sopenharmony_ci if (!link_up) { 29608c2ecf20Sopenharmony_ci hw_err(hw, "The link is down"); 29618c2ecf20Sopenharmony_ci goto out; 29628c2ecf20Sopenharmony_ci } 29638c2ecf20Sopenharmony_ci 29648c2ecf20Sopenharmony_ci /* Check at auto-negotiation has completed */ 29658c2ecf20Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 29668c2ecf20Sopenharmony_ci IXGBE_KRM_LINK_S1(hw->bus.lan_id), 29678c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); 29688c2ecf20Sopenharmony_ci 29698c2ecf20Sopenharmony_ci if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { 29708c2ecf20Sopenharmony_ci hw_dbg(hw, "Auto-Negotiation did not complete\n"); 29718c2ecf20Sopenharmony_ci status = -EIO; 29728c2ecf20Sopenharmony_ci goto out; 29738c2ecf20Sopenharmony_ci } 29748c2ecf20Sopenharmony_ci 29758c2ecf20Sopenharmony_ci /* Read the 10g AN autoc and LP ability registers and resolve 29768c2ecf20Sopenharmony_ci * local flow control settings accordingly 29778c2ecf20Sopenharmony_ci */ 29788c2ecf20Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 29798c2ecf20Sopenharmony_ci IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 29808c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1); 29818c2ecf20Sopenharmony_ci 29828c2ecf20Sopenharmony_ci if (status) { 29838c2ecf20Sopenharmony_ci hw_dbg(hw, "Auto-Negotiation did not complete\n"); 29848c2ecf20Sopenharmony_ci goto out; 29858c2ecf20Sopenharmony_ci } 29868c2ecf20Sopenharmony_ci 29878c2ecf20Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 29888c2ecf20Sopenharmony_ci IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id), 29898c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low); 29908c2ecf20Sopenharmony_ci 29918c2ecf20Sopenharmony_ci if (status) { 29928c2ecf20Sopenharmony_ci hw_dbg(hw, "Auto-Negotiation did not complete\n"); 29938c2ecf20Sopenharmony_ci goto out; 29948c2ecf20Sopenharmony_ci } 29958c2ecf20Sopenharmony_ci 29968c2ecf20Sopenharmony_ci status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low, 29978c2ecf20Sopenharmony_ci IXGBE_KRM_AN_CNTL_1_SYM_PAUSE, 29988c2ecf20Sopenharmony_ci IXGBE_KRM_AN_CNTL_1_ASM_PAUSE, 29998c2ecf20Sopenharmony_ci IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE, 30008c2ecf20Sopenharmony_ci IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE); 30018c2ecf20Sopenharmony_ci 30028c2ecf20Sopenharmony_ciout: 30038c2ecf20Sopenharmony_ci if (!status) { 30048c2ecf20Sopenharmony_ci hw->fc.fc_was_autonegged = true; 30058c2ecf20Sopenharmony_ci } else { 30068c2ecf20Sopenharmony_ci hw->fc.fc_was_autonegged = false; 30078c2ecf20Sopenharmony_ci hw->fc.current_mode = hw->fc.requested_mode; 30088c2ecf20Sopenharmony_ci } 30098c2ecf20Sopenharmony_ci} 30108c2ecf20Sopenharmony_ci 30118c2ecf20Sopenharmony_ci/** 30128c2ecf20Sopenharmony_ci * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings 30138c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 30148c2ecf20Sopenharmony_ci **/ 30158c2ecf20Sopenharmony_cistatic void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) 30168c2ecf20Sopenharmony_ci{ 30178c2ecf20Sopenharmony_ci hw->fc.fc_was_autonegged = false; 30188c2ecf20Sopenharmony_ci hw->fc.current_mode = hw->fc.requested_mode; 30198c2ecf20Sopenharmony_ci} 30208c2ecf20Sopenharmony_ci 30218c2ecf20Sopenharmony_ci/** ixgbe_enter_lplu_x550em - Transition to low power states 30228c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 30238c2ecf20Sopenharmony_ci * 30248c2ecf20Sopenharmony_ci * Configures Low Power Link Up on transition to low power states 30258c2ecf20Sopenharmony_ci * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting 30268c2ecf20Sopenharmony_ci * the X557 PHY immediately prior to entering LPLU. 30278c2ecf20Sopenharmony_ci **/ 30288c2ecf20Sopenharmony_cistatic s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) 30298c2ecf20Sopenharmony_ci{ 30308c2ecf20Sopenharmony_ci u16 an_10g_cntl_reg, autoneg_reg, speed; 30318c2ecf20Sopenharmony_ci s32 status; 30328c2ecf20Sopenharmony_ci ixgbe_link_speed lcd_speed; 30338c2ecf20Sopenharmony_ci u32 save_autoneg; 30348c2ecf20Sopenharmony_ci bool link_up; 30358c2ecf20Sopenharmony_ci 30368c2ecf20Sopenharmony_ci /* If blocked by MNG FW, then don't restart AN */ 30378c2ecf20Sopenharmony_ci if (ixgbe_check_reset_blocked(hw)) 30388c2ecf20Sopenharmony_ci return 0; 30398c2ecf20Sopenharmony_ci 30408c2ecf20Sopenharmony_ci status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 30418c2ecf20Sopenharmony_ci if (status) 30428c2ecf20Sopenharmony_ci return status; 30438c2ecf20Sopenharmony_ci 30448c2ecf20Sopenharmony_ci status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, 30458c2ecf20Sopenharmony_ci &hw->eeprom.ctrl_word_3); 30468c2ecf20Sopenharmony_ci if (status) 30478c2ecf20Sopenharmony_ci return status; 30488c2ecf20Sopenharmony_ci 30498c2ecf20Sopenharmony_ci /* If link is down, LPLU disabled in NVM, WoL disabled, or 30508c2ecf20Sopenharmony_ci * manageability disabled, then force link down by entering 30518c2ecf20Sopenharmony_ci * low power mode. 30528c2ecf20Sopenharmony_ci */ 30538c2ecf20Sopenharmony_ci if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || 30548c2ecf20Sopenharmony_ci !(hw->wol_enabled || ixgbe_mng_present(hw))) 30558c2ecf20Sopenharmony_ci return ixgbe_set_copper_phy_power(hw, false); 30568c2ecf20Sopenharmony_ci 30578c2ecf20Sopenharmony_ci /* Determine LCD */ 30588c2ecf20Sopenharmony_ci status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); 30598c2ecf20Sopenharmony_ci if (status) 30608c2ecf20Sopenharmony_ci return status; 30618c2ecf20Sopenharmony_ci 30628c2ecf20Sopenharmony_ci /* If no valid LCD link speed, then force link down and exit. */ 30638c2ecf20Sopenharmony_ci if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) 30648c2ecf20Sopenharmony_ci return ixgbe_set_copper_phy_power(hw, false); 30658c2ecf20Sopenharmony_ci 30668c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 30678c2ecf20Sopenharmony_ci MDIO_MMD_AN, 30688c2ecf20Sopenharmony_ci &speed); 30698c2ecf20Sopenharmony_ci if (status) 30708c2ecf20Sopenharmony_ci return status; 30718c2ecf20Sopenharmony_ci 30728c2ecf20Sopenharmony_ci /* If no link now, speed is invalid so take link down */ 30738c2ecf20Sopenharmony_ci status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 30748c2ecf20Sopenharmony_ci if (status) 30758c2ecf20Sopenharmony_ci return ixgbe_set_copper_phy_power(hw, false); 30768c2ecf20Sopenharmony_ci 30778c2ecf20Sopenharmony_ci /* clear everything but the speed bits */ 30788c2ecf20Sopenharmony_ci speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; 30798c2ecf20Sopenharmony_ci 30808c2ecf20Sopenharmony_ci /* If current speed is already LCD, then exit. */ 30818c2ecf20Sopenharmony_ci if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && 30828c2ecf20Sopenharmony_ci (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || 30838c2ecf20Sopenharmony_ci ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && 30848c2ecf20Sopenharmony_ci (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) 30858c2ecf20Sopenharmony_ci return status; 30868c2ecf20Sopenharmony_ci 30878c2ecf20Sopenharmony_ci /* Clear AN completed indication */ 30888c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, 30898c2ecf20Sopenharmony_ci MDIO_MMD_AN, 30908c2ecf20Sopenharmony_ci &autoneg_reg); 30918c2ecf20Sopenharmony_ci if (status) 30928c2ecf20Sopenharmony_ci return status; 30938c2ecf20Sopenharmony_ci 30948c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, 30958c2ecf20Sopenharmony_ci MDIO_MMD_AN, 30968c2ecf20Sopenharmony_ci &an_10g_cntl_reg); 30978c2ecf20Sopenharmony_ci if (status) 30988c2ecf20Sopenharmony_ci return status; 30998c2ecf20Sopenharmony_ci 31008c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, 31018c2ecf20Sopenharmony_ci IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, 31028c2ecf20Sopenharmony_ci MDIO_MMD_AN, 31038c2ecf20Sopenharmony_ci &autoneg_reg); 31048c2ecf20Sopenharmony_ci if (status) 31058c2ecf20Sopenharmony_ci return status; 31068c2ecf20Sopenharmony_ci 31078c2ecf20Sopenharmony_ci save_autoneg = hw->phy.autoneg_advertised; 31088c2ecf20Sopenharmony_ci 31098c2ecf20Sopenharmony_ci /* Setup link at least common link speed */ 31108c2ecf20Sopenharmony_ci status = hw->mac.ops.setup_link(hw, lcd_speed, false); 31118c2ecf20Sopenharmony_ci 31128c2ecf20Sopenharmony_ci /* restore autoneg from before setting lplu speed */ 31138c2ecf20Sopenharmony_ci hw->phy.autoneg_advertised = save_autoneg; 31148c2ecf20Sopenharmony_ci 31158c2ecf20Sopenharmony_ci return status; 31168c2ecf20Sopenharmony_ci} 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci/** 31198c2ecf20Sopenharmony_ci * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs 31208c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 31218c2ecf20Sopenharmony_ci */ 31228c2ecf20Sopenharmony_cistatic s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw) 31238c2ecf20Sopenharmony_ci{ 31248c2ecf20Sopenharmony_ci u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 }; 31258c2ecf20Sopenharmony_ci s32 rc; 31268c2ecf20Sopenharmony_ci 31278c2ecf20Sopenharmony_ci if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) 31288c2ecf20Sopenharmony_ci return 0; 31298c2ecf20Sopenharmony_ci 31308c2ecf20Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store); 31318c2ecf20Sopenharmony_ci if (rc) 31328c2ecf20Sopenharmony_ci return rc; 31338c2ecf20Sopenharmony_ci memset(store, 0, sizeof(store)); 31348c2ecf20Sopenharmony_ci 31358c2ecf20Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store); 31368c2ecf20Sopenharmony_ci if (rc) 31378c2ecf20Sopenharmony_ci return rc; 31388c2ecf20Sopenharmony_ci 31398c2ecf20Sopenharmony_ci return ixgbe_setup_fw_link(hw); 31408c2ecf20Sopenharmony_ci} 31418c2ecf20Sopenharmony_ci 31428c2ecf20Sopenharmony_ci/** 31438c2ecf20Sopenharmony_ci * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp 31448c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 31458c2ecf20Sopenharmony_ci * 31468c2ecf20Sopenharmony_ci * Return true when an overtemp event detected, otherwise false. 31478c2ecf20Sopenharmony_ci */ 31488c2ecf20Sopenharmony_cistatic bool ixgbe_check_overtemp_fw(struct ixgbe_hw *hw) 31498c2ecf20Sopenharmony_ci{ 31508c2ecf20Sopenharmony_ci u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 }; 31518c2ecf20Sopenharmony_ci s32 rc; 31528c2ecf20Sopenharmony_ci 31538c2ecf20Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store); 31548c2ecf20Sopenharmony_ci if (rc) 31558c2ecf20Sopenharmony_ci return false; 31568c2ecf20Sopenharmony_ci 31578c2ecf20Sopenharmony_ci if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) { 31588c2ecf20Sopenharmony_ci ixgbe_shutdown_fw_phy(hw); 31598c2ecf20Sopenharmony_ci return true; 31608c2ecf20Sopenharmony_ci } 31618c2ecf20Sopenharmony_ci return false; 31628c2ecf20Sopenharmony_ci} 31638c2ecf20Sopenharmony_ci 31648c2ecf20Sopenharmony_ci/** 31658c2ecf20Sopenharmony_ci * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register 31668c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 31678c2ecf20Sopenharmony_ci * 31688c2ecf20Sopenharmony_ci * Read NW_MNG_IF_SEL register and save field values. 31698c2ecf20Sopenharmony_ci */ 31708c2ecf20Sopenharmony_cistatic void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) 31718c2ecf20Sopenharmony_ci{ 31728c2ecf20Sopenharmony_ci /* Save NW management interface connected on board. This is used 31738c2ecf20Sopenharmony_ci * to determine internal PHY mode. 31748c2ecf20Sopenharmony_ci */ 31758c2ecf20Sopenharmony_ci hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 31768c2ecf20Sopenharmony_ci 31778c2ecf20Sopenharmony_ci /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set 31788c2ecf20Sopenharmony_ci * PHY address. This register field was has only been used for X552. 31798c2ecf20Sopenharmony_ci */ 31808c2ecf20Sopenharmony_ci if (hw->mac.type == ixgbe_mac_x550em_a && 31818c2ecf20Sopenharmony_ci hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) { 31828c2ecf20Sopenharmony_ci hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel & 31838c2ecf20Sopenharmony_ci IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> 31848c2ecf20Sopenharmony_ci IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; 31858c2ecf20Sopenharmony_ci } 31868c2ecf20Sopenharmony_ci} 31878c2ecf20Sopenharmony_ci 31888c2ecf20Sopenharmony_ci/** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 31898c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 31908c2ecf20Sopenharmony_ci * 31918c2ecf20Sopenharmony_ci * Initialize any function pointers that were not able to be 31928c2ecf20Sopenharmony_ci * set during init_shared_code because the PHY/SFP type was 31938c2ecf20Sopenharmony_ci * not known. Perform the SFP init if necessary. 31948c2ecf20Sopenharmony_ci **/ 31958c2ecf20Sopenharmony_cistatic s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 31968c2ecf20Sopenharmony_ci{ 31978c2ecf20Sopenharmony_ci struct ixgbe_phy_info *phy = &hw->phy; 31988c2ecf20Sopenharmony_ci s32 ret_val; 31998c2ecf20Sopenharmony_ci 32008c2ecf20Sopenharmony_ci hw->mac.ops.set_lan_id(hw); 32018c2ecf20Sopenharmony_ci 32028c2ecf20Sopenharmony_ci ixgbe_read_mng_if_sel_x550em(hw); 32038c2ecf20Sopenharmony_ci 32048c2ecf20Sopenharmony_ci if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 32058c2ecf20Sopenharmony_ci phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 32068c2ecf20Sopenharmony_ci ixgbe_setup_mux_ctl(hw); 32078c2ecf20Sopenharmony_ci } 32088c2ecf20Sopenharmony_ci 32098c2ecf20Sopenharmony_ci /* Identify the PHY or SFP module */ 32108c2ecf20Sopenharmony_ci ret_val = phy->ops.identify(hw); 32118c2ecf20Sopenharmony_ci if (ret_val == -EOPNOTSUPP || ret_val == -EFAULT) 32128c2ecf20Sopenharmony_ci return ret_val; 32138c2ecf20Sopenharmony_ci 32148c2ecf20Sopenharmony_ci /* Setup function pointers based on detected hardware */ 32158c2ecf20Sopenharmony_ci ixgbe_init_mac_link_ops_X550em(hw); 32168c2ecf20Sopenharmony_ci if (phy->sfp_type != ixgbe_sfp_type_unknown) 32178c2ecf20Sopenharmony_ci phy->ops.reset = NULL; 32188c2ecf20Sopenharmony_ci 32198c2ecf20Sopenharmony_ci /* Set functions pointers based on phy type */ 32208c2ecf20Sopenharmony_ci switch (hw->phy.type) { 32218c2ecf20Sopenharmony_ci case ixgbe_phy_x550em_kx4: 32228c2ecf20Sopenharmony_ci phy->ops.setup_link = NULL; 32238c2ecf20Sopenharmony_ci phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 32248c2ecf20Sopenharmony_ci phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 32258c2ecf20Sopenharmony_ci break; 32268c2ecf20Sopenharmony_ci case ixgbe_phy_x550em_kr: 32278c2ecf20Sopenharmony_ci phy->ops.setup_link = ixgbe_setup_kr_x550em; 32288c2ecf20Sopenharmony_ci phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 32298c2ecf20Sopenharmony_ci phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 32308c2ecf20Sopenharmony_ci break; 32318c2ecf20Sopenharmony_ci case ixgbe_phy_x550em_xfi: 32328c2ecf20Sopenharmony_ci /* link is managed by HW */ 32338c2ecf20Sopenharmony_ci phy->ops.setup_link = NULL; 32348c2ecf20Sopenharmony_ci phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 32358c2ecf20Sopenharmony_ci phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 32368c2ecf20Sopenharmony_ci break; 32378c2ecf20Sopenharmony_ci case ixgbe_phy_x550em_ext_t: 32388c2ecf20Sopenharmony_ci /* Save NW management interface connected on board. This is used 32398c2ecf20Sopenharmony_ci * to determine internal PHY mode 32408c2ecf20Sopenharmony_ci */ 32418c2ecf20Sopenharmony_ci phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 32428c2ecf20Sopenharmony_ci 32438c2ecf20Sopenharmony_ci /* If internal link mode is XFI, then setup iXFI internal link, 32448c2ecf20Sopenharmony_ci * else setup KR now. 32458c2ecf20Sopenharmony_ci */ 32468c2ecf20Sopenharmony_ci phy->ops.setup_internal_link = 32478c2ecf20Sopenharmony_ci ixgbe_setup_internal_phy_t_x550em; 32488c2ecf20Sopenharmony_ci 32498c2ecf20Sopenharmony_ci /* setup SW LPLU only for first revision */ 32508c2ecf20Sopenharmony_ci if (hw->mac.type == ixgbe_mac_X550EM_x && 32518c2ecf20Sopenharmony_ci !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) & 32528c2ecf20Sopenharmony_ci IXGBE_FUSES0_REV_MASK)) 32538c2ecf20Sopenharmony_ci phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; 32548c2ecf20Sopenharmony_ci 32558c2ecf20Sopenharmony_ci phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 32568c2ecf20Sopenharmony_ci phy->ops.reset = ixgbe_reset_phy_t_X550em; 32578c2ecf20Sopenharmony_ci break; 32588c2ecf20Sopenharmony_ci case ixgbe_phy_sgmii: 32598c2ecf20Sopenharmony_ci phy->ops.setup_link = NULL; 32608c2ecf20Sopenharmony_ci break; 32618c2ecf20Sopenharmony_ci case ixgbe_phy_fw: 32628c2ecf20Sopenharmony_ci phy->ops.setup_link = ixgbe_setup_fw_link; 32638c2ecf20Sopenharmony_ci phy->ops.reset = ixgbe_reset_phy_fw; 32648c2ecf20Sopenharmony_ci break; 32658c2ecf20Sopenharmony_ci case ixgbe_phy_ext_1g_t: 32668c2ecf20Sopenharmony_ci phy->ops.setup_link = NULL; 32678c2ecf20Sopenharmony_ci phy->ops.read_reg = NULL; 32688c2ecf20Sopenharmony_ci phy->ops.write_reg = NULL; 32698c2ecf20Sopenharmony_ci phy->ops.reset = NULL; 32708c2ecf20Sopenharmony_ci break; 32718c2ecf20Sopenharmony_ci default: 32728c2ecf20Sopenharmony_ci break; 32738c2ecf20Sopenharmony_ci } 32748c2ecf20Sopenharmony_ci 32758c2ecf20Sopenharmony_ci return ret_val; 32768c2ecf20Sopenharmony_ci} 32778c2ecf20Sopenharmony_ci 32788c2ecf20Sopenharmony_ci/** ixgbe_get_media_type_X550em - Get media type 32798c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 32808c2ecf20Sopenharmony_ci * 32818c2ecf20Sopenharmony_ci * Returns the media type (fiber, copper, backplane) 32828c2ecf20Sopenharmony_ci * 32838c2ecf20Sopenharmony_ci */ 32848c2ecf20Sopenharmony_cistatic enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 32858c2ecf20Sopenharmony_ci{ 32868c2ecf20Sopenharmony_ci enum ixgbe_media_type media_type; 32878c2ecf20Sopenharmony_ci 32888c2ecf20Sopenharmony_ci /* Detect if there is a copper PHY attached. */ 32898c2ecf20Sopenharmony_ci switch (hw->device_id) { 32908c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SGMII: 32918c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SGMII_L: 32928c2ecf20Sopenharmony_ci hw->phy.type = ixgbe_phy_sgmii; 32938c2ecf20Sopenharmony_ci fallthrough; 32948c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KR: 32958c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KX4: 32968c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_XFI: 32978c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR: 32988c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_KR_L: 32998c2ecf20Sopenharmony_ci media_type = ixgbe_media_type_backplane; 33008c2ecf20Sopenharmony_ci break; 33018c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_SFP: 33028c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP: 33038c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP_N: 33048c2ecf20Sopenharmony_ci media_type = ixgbe_media_type_fiber; 33058c2ecf20Sopenharmony_ci break; 33068c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_1G_T: 33078c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_10G_T: 33088c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_10G_T: 33098c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T: 33108c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T_L: 33118c2ecf20Sopenharmony_ci media_type = ixgbe_media_type_copper; 33128c2ecf20Sopenharmony_ci break; 33138c2ecf20Sopenharmony_ci default: 33148c2ecf20Sopenharmony_ci media_type = ixgbe_media_type_unknown; 33158c2ecf20Sopenharmony_ci break; 33168c2ecf20Sopenharmony_ci } 33178c2ecf20Sopenharmony_ci return media_type; 33188c2ecf20Sopenharmony_ci} 33198c2ecf20Sopenharmony_ci 33208c2ecf20Sopenharmony_ci/** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 33218c2ecf20Sopenharmony_ci ** @hw: pointer to hardware structure 33228c2ecf20Sopenharmony_ci **/ 33238c2ecf20Sopenharmony_cistatic s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 33248c2ecf20Sopenharmony_ci{ 33258c2ecf20Sopenharmony_ci s32 status; 33268c2ecf20Sopenharmony_ci u16 reg; 33278c2ecf20Sopenharmony_ci 33288c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, 33298c2ecf20Sopenharmony_ci IXGBE_MDIO_TX_VENDOR_ALARMS_3, 33308c2ecf20Sopenharmony_ci MDIO_MMD_PMAPMD, 33318c2ecf20Sopenharmony_ci ®); 33328c2ecf20Sopenharmony_ci if (status) 33338c2ecf20Sopenharmony_ci return status; 33348c2ecf20Sopenharmony_ci 33358c2ecf20Sopenharmony_ci /* If PHY FW reset completed bit is set then this is the first 33368c2ecf20Sopenharmony_ci * SW instance after a power on so the PHY FW must be un-stalled. 33378c2ecf20Sopenharmony_ci */ 33388c2ecf20Sopenharmony_ci if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 33398c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg(hw, 33408c2ecf20Sopenharmony_ci IXGBE_MDIO_GLOBAL_RES_PR_10, 33418c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 33428c2ecf20Sopenharmony_ci ®); 33438c2ecf20Sopenharmony_ci if (status) 33448c2ecf20Sopenharmony_ci return status; 33458c2ecf20Sopenharmony_ci 33468c2ecf20Sopenharmony_ci reg &= ~IXGBE_MDIO_POWER_UP_STALL; 33478c2ecf20Sopenharmony_ci 33488c2ecf20Sopenharmony_ci status = hw->phy.ops.write_reg(hw, 33498c2ecf20Sopenharmony_ci IXGBE_MDIO_GLOBAL_RES_PR_10, 33508c2ecf20Sopenharmony_ci MDIO_MMD_VEND1, 33518c2ecf20Sopenharmony_ci reg); 33528c2ecf20Sopenharmony_ci if (status) 33538c2ecf20Sopenharmony_ci return status; 33548c2ecf20Sopenharmony_ci } 33558c2ecf20Sopenharmony_ci 33568c2ecf20Sopenharmony_ci return status; 33578c2ecf20Sopenharmony_ci} 33588c2ecf20Sopenharmony_ci 33598c2ecf20Sopenharmony_ci/** 33608c2ecf20Sopenharmony_ci * ixgbe_set_mdio_speed - Set MDIO clock speed 33618c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 33628c2ecf20Sopenharmony_ci */ 33638c2ecf20Sopenharmony_cistatic void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) 33648c2ecf20Sopenharmony_ci{ 33658c2ecf20Sopenharmony_ci u32 hlreg0; 33668c2ecf20Sopenharmony_ci 33678c2ecf20Sopenharmony_ci switch (hw->device_id) { 33688c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_10G_T: 33698c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SGMII: 33708c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SGMII_L: 33718c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_10G_T: 33728c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_SFP: 33738c2ecf20Sopenharmony_ci /* Config MDIO clock speed before the first MDIO PHY access */ 33748c2ecf20Sopenharmony_ci hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 33758c2ecf20Sopenharmony_ci hlreg0 &= ~IXGBE_HLREG0_MDCSPD; 33768c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 33778c2ecf20Sopenharmony_ci break; 33788c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T: 33798c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_A_1G_T_L: 33808c2ecf20Sopenharmony_ci /* Select fast MDIO clock speed for these devices */ 33818c2ecf20Sopenharmony_ci hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 33828c2ecf20Sopenharmony_ci hlreg0 |= IXGBE_HLREG0_MDCSPD; 33838c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 33848c2ecf20Sopenharmony_ci break; 33858c2ecf20Sopenharmony_ci default: 33868c2ecf20Sopenharmony_ci break; 33878c2ecf20Sopenharmony_ci } 33888c2ecf20Sopenharmony_ci} 33898c2ecf20Sopenharmony_ci 33908c2ecf20Sopenharmony_ci/** ixgbe_reset_hw_X550em - Perform hardware reset 33918c2ecf20Sopenharmony_ci ** @hw: pointer to hardware structure 33928c2ecf20Sopenharmony_ci ** 33938c2ecf20Sopenharmony_ci ** Resets the hardware by resetting the transmit and receive units, masks 33948c2ecf20Sopenharmony_ci ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 33958c2ecf20Sopenharmony_ci ** reset. 33968c2ecf20Sopenharmony_ci **/ 33978c2ecf20Sopenharmony_cistatic s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 33988c2ecf20Sopenharmony_ci{ 33998c2ecf20Sopenharmony_ci ixgbe_link_speed link_speed; 34008c2ecf20Sopenharmony_ci s32 status; 34018c2ecf20Sopenharmony_ci u32 ctrl = 0; 34028c2ecf20Sopenharmony_ci u32 i; 34038c2ecf20Sopenharmony_ci bool link_up = false; 34048c2ecf20Sopenharmony_ci u32 swfw_mask = hw->phy.phy_semaphore_mask; 34058c2ecf20Sopenharmony_ci 34068c2ecf20Sopenharmony_ci /* Call adapter stop to disable Tx/Rx and clear interrupts */ 34078c2ecf20Sopenharmony_ci status = hw->mac.ops.stop_adapter(hw); 34088c2ecf20Sopenharmony_ci if (status) 34098c2ecf20Sopenharmony_ci return status; 34108c2ecf20Sopenharmony_ci 34118c2ecf20Sopenharmony_ci /* flush pending Tx transactions */ 34128c2ecf20Sopenharmony_ci ixgbe_clear_tx_pending(hw); 34138c2ecf20Sopenharmony_ci 34148c2ecf20Sopenharmony_ci /* set MDIO speed before talking to the PHY in case it's the 1st time */ 34158c2ecf20Sopenharmony_ci ixgbe_set_mdio_speed(hw); 34168c2ecf20Sopenharmony_ci 34178c2ecf20Sopenharmony_ci /* PHY ops must be identified and initialized prior to reset */ 34188c2ecf20Sopenharmony_ci status = hw->phy.ops.init(hw); 34198c2ecf20Sopenharmony_ci if (status == -EOPNOTSUPP || status == -EFAULT) 34208c2ecf20Sopenharmony_ci return status; 34218c2ecf20Sopenharmony_ci 34228c2ecf20Sopenharmony_ci /* start the external PHY */ 34238c2ecf20Sopenharmony_ci if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 34248c2ecf20Sopenharmony_ci status = ixgbe_init_ext_t_x550em(hw); 34258c2ecf20Sopenharmony_ci if (status) 34268c2ecf20Sopenharmony_ci return status; 34278c2ecf20Sopenharmony_ci } 34288c2ecf20Sopenharmony_ci 34298c2ecf20Sopenharmony_ci /* Setup SFP module if there is one present. */ 34308c2ecf20Sopenharmony_ci if (hw->phy.sfp_setup_needed) { 34318c2ecf20Sopenharmony_ci status = hw->mac.ops.setup_sfp(hw); 34328c2ecf20Sopenharmony_ci hw->phy.sfp_setup_needed = false; 34338c2ecf20Sopenharmony_ci } 34348c2ecf20Sopenharmony_ci 34358c2ecf20Sopenharmony_ci if (status == -EOPNOTSUPP) 34368c2ecf20Sopenharmony_ci return status; 34378c2ecf20Sopenharmony_ci 34388c2ecf20Sopenharmony_ci /* Reset PHY */ 34398c2ecf20Sopenharmony_ci if (!hw->phy.reset_disable && hw->phy.ops.reset) 34408c2ecf20Sopenharmony_ci hw->phy.ops.reset(hw); 34418c2ecf20Sopenharmony_ci 34428c2ecf20Sopenharmony_cimac_reset_top: 34438c2ecf20Sopenharmony_ci /* Issue global reset to the MAC. Needs to be SW reset if link is up. 34448c2ecf20Sopenharmony_ci * If link reset is used when link is up, it might reset the PHY when 34458c2ecf20Sopenharmony_ci * mng is using it. If link is down or the flag to force full link 34468c2ecf20Sopenharmony_ci * reset is set, then perform link reset. 34478c2ecf20Sopenharmony_ci */ 34488c2ecf20Sopenharmony_ci ctrl = IXGBE_CTRL_LNK_RST; 34498c2ecf20Sopenharmony_ci 34508c2ecf20Sopenharmony_ci if (!hw->force_full_reset) { 34518c2ecf20Sopenharmony_ci hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 34528c2ecf20Sopenharmony_ci if (link_up) 34538c2ecf20Sopenharmony_ci ctrl = IXGBE_CTRL_RST; 34548c2ecf20Sopenharmony_ci } 34558c2ecf20Sopenharmony_ci 34568c2ecf20Sopenharmony_ci status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 34578c2ecf20Sopenharmony_ci if (status) { 34588c2ecf20Sopenharmony_ci hw_dbg(hw, "semaphore failed with %d", status); 34598c2ecf20Sopenharmony_ci return -EBUSY; 34608c2ecf20Sopenharmony_ci } 34618c2ecf20Sopenharmony_ci 34628c2ecf20Sopenharmony_ci ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 34638c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 34648c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 34658c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 34668c2ecf20Sopenharmony_ci usleep_range(1000, 1200); 34678c2ecf20Sopenharmony_ci 34688c2ecf20Sopenharmony_ci /* Poll for reset bit to self-clear meaning reset is complete */ 34698c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) { 34708c2ecf20Sopenharmony_ci ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 34718c2ecf20Sopenharmony_ci if (!(ctrl & IXGBE_CTRL_RST_MASK)) 34728c2ecf20Sopenharmony_ci break; 34738c2ecf20Sopenharmony_ci udelay(1); 34748c2ecf20Sopenharmony_ci } 34758c2ecf20Sopenharmony_ci 34768c2ecf20Sopenharmony_ci if (ctrl & IXGBE_CTRL_RST_MASK) { 34778c2ecf20Sopenharmony_ci status = -EIO; 34788c2ecf20Sopenharmony_ci hw_dbg(hw, "Reset polling failed to complete.\n"); 34798c2ecf20Sopenharmony_ci } 34808c2ecf20Sopenharmony_ci 34818c2ecf20Sopenharmony_ci msleep(50); 34828c2ecf20Sopenharmony_ci 34838c2ecf20Sopenharmony_ci /* Double resets are required for recovery from certain error 34848c2ecf20Sopenharmony_ci * clear the multicast table. Also reset num_rar_entries to 128, 34858c2ecf20Sopenharmony_ci * since we modify this value when programming the SAN MAC address. 34868c2ecf20Sopenharmony_ci */ 34878c2ecf20Sopenharmony_ci if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 34888c2ecf20Sopenharmony_ci hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 34898c2ecf20Sopenharmony_ci goto mac_reset_top; 34908c2ecf20Sopenharmony_ci } 34918c2ecf20Sopenharmony_ci 34928c2ecf20Sopenharmony_ci /* Store the permanent mac address */ 34938c2ecf20Sopenharmony_ci hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 34948c2ecf20Sopenharmony_ci 34958c2ecf20Sopenharmony_ci /* Store MAC address from RAR0, clear receive address registers, and 34968c2ecf20Sopenharmony_ci * clear the multicast table. Also reset num_rar_entries to 128, 34978c2ecf20Sopenharmony_ci * since we modify this value when programming the SAN MAC address. 34988c2ecf20Sopenharmony_ci */ 34998c2ecf20Sopenharmony_ci hw->mac.num_rar_entries = 128; 35008c2ecf20Sopenharmony_ci hw->mac.ops.init_rx_addrs(hw); 35018c2ecf20Sopenharmony_ci 35028c2ecf20Sopenharmony_ci ixgbe_set_mdio_speed(hw); 35038c2ecf20Sopenharmony_ci 35048c2ecf20Sopenharmony_ci if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 35058c2ecf20Sopenharmony_ci ixgbe_setup_mux_ctl(hw); 35068c2ecf20Sopenharmony_ci 35078c2ecf20Sopenharmony_ci return status; 35088c2ecf20Sopenharmony_ci} 35098c2ecf20Sopenharmony_ci 35108c2ecf20Sopenharmony_ci/** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 35118c2ecf20Sopenharmony_ci * anti-spoofing 35128c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 35138c2ecf20Sopenharmony_ci * @enable: enable or disable switch for Ethertype anti-spoofing 35148c2ecf20Sopenharmony_ci * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 35158c2ecf20Sopenharmony_ci **/ 35168c2ecf20Sopenharmony_cistatic void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 35178c2ecf20Sopenharmony_ci bool enable, int vf) 35188c2ecf20Sopenharmony_ci{ 35198c2ecf20Sopenharmony_ci int vf_target_reg = vf >> 3; 35208c2ecf20Sopenharmony_ci int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 35218c2ecf20Sopenharmony_ci u32 pfvfspoof; 35228c2ecf20Sopenharmony_ci 35238c2ecf20Sopenharmony_ci pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 35248c2ecf20Sopenharmony_ci if (enable) 35258c2ecf20Sopenharmony_ci pfvfspoof |= BIT(vf_target_shift); 35268c2ecf20Sopenharmony_ci else 35278c2ecf20Sopenharmony_ci pfvfspoof &= ~BIT(vf_target_shift); 35288c2ecf20Sopenharmony_ci 35298c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 35308c2ecf20Sopenharmony_ci} 35318c2ecf20Sopenharmony_ci 35328c2ecf20Sopenharmony_ci/** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 35338c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 35348c2ecf20Sopenharmony_ci * @enable: enable or disable source address pruning 35358c2ecf20Sopenharmony_ci * @pool: Rx pool to set source address pruning for 35368c2ecf20Sopenharmony_ci **/ 35378c2ecf20Sopenharmony_cistatic void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 35388c2ecf20Sopenharmony_ci bool enable, 35398c2ecf20Sopenharmony_ci unsigned int pool) 35408c2ecf20Sopenharmony_ci{ 35418c2ecf20Sopenharmony_ci u64 pfflp; 35428c2ecf20Sopenharmony_ci 35438c2ecf20Sopenharmony_ci /* max rx pool is 63 */ 35448c2ecf20Sopenharmony_ci if (pool > 63) 35458c2ecf20Sopenharmony_ci return; 35468c2ecf20Sopenharmony_ci 35478c2ecf20Sopenharmony_ci pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 35488c2ecf20Sopenharmony_ci pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 35498c2ecf20Sopenharmony_ci 35508c2ecf20Sopenharmony_ci if (enable) 35518c2ecf20Sopenharmony_ci pfflp |= (1ULL << pool); 35528c2ecf20Sopenharmony_ci else 35538c2ecf20Sopenharmony_ci pfflp &= ~(1ULL << pool); 35548c2ecf20Sopenharmony_ci 35558c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 35568c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 35578c2ecf20Sopenharmony_ci} 35588c2ecf20Sopenharmony_ci 35598c2ecf20Sopenharmony_ci/** 35608c2ecf20Sopenharmony_ci * ixgbe_setup_fc_backplane_x550em_a - Set up flow control 35618c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 35628c2ecf20Sopenharmony_ci * 35638c2ecf20Sopenharmony_ci * Called at init time to set up flow control. 35648c2ecf20Sopenharmony_ci **/ 35658c2ecf20Sopenharmony_cistatic s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) 35668c2ecf20Sopenharmony_ci{ 35678c2ecf20Sopenharmony_ci s32 status = 0; 35688c2ecf20Sopenharmony_ci u32 an_cntl = 0; 35698c2ecf20Sopenharmony_ci 35708c2ecf20Sopenharmony_ci /* Validate the requested mode */ 35718c2ecf20Sopenharmony_ci if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 35728c2ecf20Sopenharmony_ci hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 35738c2ecf20Sopenharmony_ci return -EINVAL; 35748c2ecf20Sopenharmony_ci } 35758c2ecf20Sopenharmony_ci 35768c2ecf20Sopenharmony_ci if (hw->fc.requested_mode == ixgbe_fc_default) 35778c2ecf20Sopenharmony_ci hw->fc.requested_mode = ixgbe_fc_full; 35788c2ecf20Sopenharmony_ci 35798c2ecf20Sopenharmony_ci /* Set up the 1G and 10G flow control advertisement registers so the 35808c2ecf20Sopenharmony_ci * HW will be able to do FC autoneg once the cable is plugged in. If 35818c2ecf20Sopenharmony_ci * we link at 10G, the 1G advertisement is harmless and vice versa. 35828c2ecf20Sopenharmony_ci */ 35838c2ecf20Sopenharmony_ci status = hw->mac.ops.read_iosf_sb_reg(hw, 35848c2ecf20Sopenharmony_ci IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 35858c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl); 35868c2ecf20Sopenharmony_ci 35878c2ecf20Sopenharmony_ci if (status) { 35888c2ecf20Sopenharmony_ci hw_dbg(hw, "Auto-Negotiation did not complete\n"); 35898c2ecf20Sopenharmony_ci return status; 35908c2ecf20Sopenharmony_ci } 35918c2ecf20Sopenharmony_ci 35928c2ecf20Sopenharmony_ci /* The possible values of fc.requested_mode are: 35938c2ecf20Sopenharmony_ci * 0: Flow control is completely disabled 35948c2ecf20Sopenharmony_ci * 1: Rx flow control is enabled (we can receive pause frames, 35958c2ecf20Sopenharmony_ci * but not send pause frames). 35968c2ecf20Sopenharmony_ci * 2: Tx flow control is enabled (we can send pause frames but 35978c2ecf20Sopenharmony_ci * we do not support receiving pause frames). 35988c2ecf20Sopenharmony_ci * 3: Both Rx and Tx flow control (symmetric) are enabled. 35998c2ecf20Sopenharmony_ci * other: Invalid. 36008c2ecf20Sopenharmony_ci */ 36018c2ecf20Sopenharmony_ci switch (hw->fc.requested_mode) { 36028c2ecf20Sopenharmony_ci case ixgbe_fc_none: 36038c2ecf20Sopenharmony_ci /* Flow control completely disabled by software override. */ 36048c2ecf20Sopenharmony_ci an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 36058c2ecf20Sopenharmony_ci IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 36068c2ecf20Sopenharmony_ci break; 36078c2ecf20Sopenharmony_ci case ixgbe_fc_tx_pause: 36088c2ecf20Sopenharmony_ci /* Tx Flow control is enabled, and Rx Flow control is 36098c2ecf20Sopenharmony_ci * disabled by software override. 36108c2ecf20Sopenharmony_ci */ 36118c2ecf20Sopenharmony_ci an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 36128c2ecf20Sopenharmony_ci an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 36138c2ecf20Sopenharmony_ci break; 36148c2ecf20Sopenharmony_ci case ixgbe_fc_rx_pause: 36158c2ecf20Sopenharmony_ci /* Rx Flow control is enabled and Tx Flow control is 36168c2ecf20Sopenharmony_ci * disabled by software override. Since there really 36178c2ecf20Sopenharmony_ci * isn't a way to advertise that we are capable of RX 36188c2ecf20Sopenharmony_ci * Pause ONLY, we will advertise that we support both 36198c2ecf20Sopenharmony_ci * symmetric and asymmetric Rx PAUSE, as such we fall 36208c2ecf20Sopenharmony_ci * through to the fc_full statement. Later, we will 36218c2ecf20Sopenharmony_ci * disable the adapter's ability to send PAUSE frames. 36228c2ecf20Sopenharmony_ci */ 36238c2ecf20Sopenharmony_ci case ixgbe_fc_full: 36248c2ecf20Sopenharmony_ci /* Flow control (both Rx and Tx) is enabled by SW override. */ 36258c2ecf20Sopenharmony_ci an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 36268c2ecf20Sopenharmony_ci IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 36278c2ecf20Sopenharmony_ci break; 36288c2ecf20Sopenharmony_ci default: 36298c2ecf20Sopenharmony_ci hw_err(hw, "Flow control param set incorrectly\n"); 36308c2ecf20Sopenharmony_ci return -EIO; 36318c2ecf20Sopenharmony_ci } 36328c2ecf20Sopenharmony_ci 36338c2ecf20Sopenharmony_ci status = hw->mac.ops.write_iosf_sb_reg(hw, 36348c2ecf20Sopenharmony_ci IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 36358c2ecf20Sopenharmony_ci IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); 36368c2ecf20Sopenharmony_ci 36378c2ecf20Sopenharmony_ci /* Restart auto-negotiation. */ 36388c2ecf20Sopenharmony_ci status = ixgbe_restart_an_internal_phy_x550em(hw); 36398c2ecf20Sopenharmony_ci 36408c2ecf20Sopenharmony_ci return status; 36418c2ecf20Sopenharmony_ci} 36428c2ecf20Sopenharmony_ci 36438c2ecf20Sopenharmony_ci/** 36448c2ecf20Sopenharmony_ci * ixgbe_set_mux - Set mux for port 1 access with CS4227 36458c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 36468c2ecf20Sopenharmony_ci * @state: set mux if 1, clear if 0 36478c2ecf20Sopenharmony_ci */ 36488c2ecf20Sopenharmony_cistatic void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) 36498c2ecf20Sopenharmony_ci{ 36508c2ecf20Sopenharmony_ci u32 esdp; 36518c2ecf20Sopenharmony_ci 36528c2ecf20Sopenharmony_ci if (!hw->bus.lan_id) 36538c2ecf20Sopenharmony_ci return; 36548c2ecf20Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 36558c2ecf20Sopenharmony_ci if (state) 36568c2ecf20Sopenharmony_ci esdp |= IXGBE_ESDP_SDP1; 36578c2ecf20Sopenharmony_ci else 36588c2ecf20Sopenharmony_ci esdp &= ~IXGBE_ESDP_SDP1; 36598c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 36608c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 36618c2ecf20Sopenharmony_ci} 36628c2ecf20Sopenharmony_ci 36638c2ecf20Sopenharmony_ci/** 36648c2ecf20Sopenharmony_ci * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore 36658c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 36668c2ecf20Sopenharmony_ci * @mask: Mask to specify which semaphore to acquire 36678c2ecf20Sopenharmony_ci * 36688c2ecf20Sopenharmony_ci * Acquires the SWFW semaphore and sets the I2C MUX 36698c2ecf20Sopenharmony_ci */ 36708c2ecf20Sopenharmony_cistatic s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 36718c2ecf20Sopenharmony_ci{ 36728c2ecf20Sopenharmony_ci s32 status; 36738c2ecf20Sopenharmony_ci 36748c2ecf20Sopenharmony_ci status = ixgbe_acquire_swfw_sync_X540(hw, mask); 36758c2ecf20Sopenharmony_ci if (status) 36768c2ecf20Sopenharmony_ci return status; 36778c2ecf20Sopenharmony_ci 36788c2ecf20Sopenharmony_ci if (mask & IXGBE_GSSR_I2C_MASK) 36798c2ecf20Sopenharmony_ci ixgbe_set_mux(hw, 1); 36808c2ecf20Sopenharmony_ci 36818c2ecf20Sopenharmony_ci return 0; 36828c2ecf20Sopenharmony_ci} 36838c2ecf20Sopenharmony_ci 36848c2ecf20Sopenharmony_ci/** 36858c2ecf20Sopenharmony_ci * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore 36868c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 36878c2ecf20Sopenharmony_ci * @mask: Mask to specify which semaphore to release 36888c2ecf20Sopenharmony_ci * 36898c2ecf20Sopenharmony_ci * Releases the SWFW semaphore and sets the I2C MUX 36908c2ecf20Sopenharmony_ci */ 36918c2ecf20Sopenharmony_cistatic void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 36928c2ecf20Sopenharmony_ci{ 36938c2ecf20Sopenharmony_ci if (mask & IXGBE_GSSR_I2C_MASK) 36948c2ecf20Sopenharmony_ci ixgbe_set_mux(hw, 0); 36958c2ecf20Sopenharmony_ci 36968c2ecf20Sopenharmony_ci ixgbe_release_swfw_sync_X540(hw, mask); 36978c2ecf20Sopenharmony_ci} 36988c2ecf20Sopenharmony_ci 36998c2ecf20Sopenharmony_ci/** 37008c2ecf20Sopenharmony_ci * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore 37018c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 37028c2ecf20Sopenharmony_ci * @mask: Mask to specify which semaphore to acquire 37038c2ecf20Sopenharmony_ci * 37048c2ecf20Sopenharmony_ci * Acquires the SWFW semaphore and get the shared PHY token as needed 37058c2ecf20Sopenharmony_ci */ 37068c2ecf20Sopenharmony_cistatic s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 37078c2ecf20Sopenharmony_ci{ 37088c2ecf20Sopenharmony_ci u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 37098c2ecf20Sopenharmony_ci int retries = FW_PHY_TOKEN_RETRIES; 37108c2ecf20Sopenharmony_ci s32 status; 37118c2ecf20Sopenharmony_ci 37128c2ecf20Sopenharmony_ci while (--retries) { 37138c2ecf20Sopenharmony_ci status = 0; 37148c2ecf20Sopenharmony_ci if (hmask) 37158c2ecf20Sopenharmony_ci status = ixgbe_acquire_swfw_sync_X540(hw, hmask); 37168c2ecf20Sopenharmony_ci if (status) 37178c2ecf20Sopenharmony_ci return status; 37188c2ecf20Sopenharmony_ci if (!(mask & IXGBE_GSSR_TOKEN_SM)) 37198c2ecf20Sopenharmony_ci return 0; 37208c2ecf20Sopenharmony_ci 37218c2ecf20Sopenharmony_ci status = ixgbe_get_phy_token(hw); 37228c2ecf20Sopenharmony_ci if (!status) 37238c2ecf20Sopenharmony_ci return 0; 37248c2ecf20Sopenharmony_ci if (hmask) 37258c2ecf20Sopenharmony_ci ixgbe_release_swfw_sync_X540(hw, hmask); 37268c2ecf20Sopenharmony_ci if (status != -EAGAIN) 37278c2ecf20Sopenharmony_ci return status; 37288c2ecf20Sopenharmony_ci msleep(FW_PHY_TOKEN_DELAY); 37298c2ecf20Sopenharmony_ci } 37308c2ecf20Sopenharmony_ci 37318c2ecf20Sopenharmony_ci return status; 37328c2ecf20Sopenharmony_ci} 37338c2ecf20Sopenharmony_ci 37348c2ecf20Sopenharmony_ci/** 37358c2ecf20Sopenharmony_ci * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore 37368c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 37378c2ecf20Sopenharmony_ci * @mask: Mask to specify which semaphore to release 37388c2ecf20Sopenharmony_ci * 37398c2ecf20Sopenharmony_ci * Release the SWFW semaphore and puts the shared PHY token as needed 37408c2ecf20Sopenharmony_ci */ 37418c2ecf20Sopenharmony_cistatic void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 37428c2ecf20Sopenharmony_ci{ 37438c2ecf20Sopenharmony_ci u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 37448c2ecf20Sopenharmony_ci 37458c2ecf20Sopenharmony_ci if (mask & IXGBE_GSSR_TOKEN_SM) 37468c2ecf20Sopenharmony_ci ixgbe_put_phy_token(hw); 37478c2ecf20Sopenharmony_ci 37488c2ecf20Sopenharmony_ci if (hmask) 37498c2ecf20Sopenharmony_ci ixgbe_release_swfw_sync_X540(hw, hmask); 37508c2ecf20Sopenharmony_ci} 37518c2ecf20Sopenharmony_ci 37528c2ecf20Sopenharmony_ci/** 37538c2ecf20Sopenharmony_ci * ixgbe_read_phy_reg_x550a - Reads specified PHY register 37548c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 37558c2ecf20Sopenharmony_ci * @reg_addr: 32 bit address of PHY register to read 37568c2ecf20Sopenharmony_ci * @device_type: 5 bit device type 37578c2ecf20Sopenharmony_ci * @phy_data: Pointer to read data from PHY register 37588c2ecf20Sopenharmony_ci * 37598c2ecf20Sopenharmony_ci * Reads a value from a specified PHY register using the SWFW lock and PHY 37608c2ecf20Sopenharmony_ci * Token. The PHY Token is needed since the MDIO is shared between to MAC 37618c2ecf20Sopenharmony_ci * instances. 37628c2ecf20Sopenharmony_ci */ 37638c2ecf20Sopenharmony_cistatic s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 37648c2ecf20Sopenharmony_ci u32 device_type, u16 *phy_data) 37658c2ecf20Sopenharmony_ci{ 37668c2ecf20Sopenharmony_ci u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 37678c2ecf20Sopenharmony_ci s32 status; 37688c2ecf20Sopenharmony_ci 37698c2ecf20Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 37708c2ecf20Sopenharmony_ci return -EBUSY; 37718c2ecf20Sopenharmony_ci 37728c2ecf20Sopenharmony_ci status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); 37738c2ecf20Sopenharmony_ci 37748c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, mask); 37758c2ecf20Sopenharmony_ci 37768c2ecf20Sopenharmony_ci return status; 37778c2ecf20Sopenharmony_ci} 37788c2ecf20Sopenharmony_ci 37798c2ecf20Sopenharmony_ci/** 37808c2ecf20Sopenharmony_ci * ixgbe_write_phy_reg_x550a - Writes specified PHY register 37818c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 37828c2ecf20Sopenharmony_ci * @reg_addr: 32 bit PHY register to write 37838c2ecf20Sopenharmony_ci * @device_type: 5 bit device type 37848c2ecf20Sopenharmony_ci * @phy_data: Data to write to the PHY register 37858c2ecf20Sopenharmony_ci * 37868c2ecf20Sopenharmony_ci * Writes a value to specified PHY register using the SWFW lock and PHY Token. 37878c2ecf20Sopenharmony_ci * The PHY Token is needed since the MDIO is shared between to MAC instances. 37888c2ecf20Sopenharmony_ci */ 37898c2ecf20Sopenharmony_cistatic s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 37908c2ecf20Sopenharmony_ci u32 device_type, u16 phy_data) 37918c2ecf20Sopenharmony_ci{ 37928c2ecf20Sopenharmony_ci u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 37938c2ecf20Sopenharmony_ci s32 status; 37948c2ecf20Sopenharmony_ci 37958c2ecf20Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 37968c2ecf20Sopenharmony_ci return -EBUSY; 37978c2ecf20Sopenharmony_ci 37988c2ecf20Sopenharmony_ci status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data); 37998c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, mask); 38008c2ecf20Sopenharmony_ci 38018c2ecf20Sopenharmony_ci return status; 38028c2ecf20Sopenharmony_ci} 38038c2ecf20Sopenharmony_ci 38048c2ecf20Sopenharmony_ci#define X550_COMMON_MAC \ 38058c2ecf20Sopenharmony_ci .init_hw = &ixgbe_init_hw_generic, \ 38068c2ecf20Sopenharmony_ci .start_hw = &ixgbe_start_hw_X540, \ 38078c2ecf20Sopenharmony_ci .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 38088c2ecf20Sopenharmony_ci .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 38098c2ecf20Sopenharmony_ci .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 38108c2ecf20Sopenharmony_ci .get_device_caps = &ixgbe_get_device_caps_generic, \ 38118c2ecf20Sopenharmony_ci .stop_adapter = &ixgbe_stop_adapter_generic, \ 38128c2ecf20Sopenharmony_ci .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 38138c2ecf20Sopenharmony_ci .read_analog_reg8 = NULL, \ 38148c2ecf20Sopenharmony_ci .write_analog_reg8 = NULL, \ 38158c2ecf20Sopenharmony_ci .set_rxpba = &ixgbe_set_rxpba_generic, \ 38168c2ecf20Sopenharmony_ci .check_link = &ixgbe_check_mac_link_generic, \ 38178c2ecf20Sopenharmony_ci .blink_led_start = &ixgbe_blink_led_start_X540, \ 38188c2ecf20Sopenharmony_ci .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 38198c2ecf20Sopenharmony_ci .set_rar = &ixgbe_set_rar_generic, \ 38208c2ecf20Sopenharmony_ci .clear_rar = &ixgbe_clear_rar_generic, \ 38218c2ecf20Sopenharmony_ci .set_vmdq = &ixgbe_set_vmdq_generic, \ 38228c2ecf20Sopenharmony_ci .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 38238c2ecf20Sopenharmony_ci .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 38248c2ecf20Sopenharmony_ci .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 38258c2ecf20Sopenharmony_ci .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 38268c2ecf20Sopenharmony_ci .enable_mc = &ixgbe_enable_mc_generic, \ 38278c2ecf20Sopenharmony_ci .disable_mc = &ixgbe_disable_mc_generic, \ 38288c2ecf20Sopenharmony_ci .clear_vfta = &ixgbe_clear_vfta_generic, \ 38298c2ecf20Sopenharmony_ci .set_vfta = &ixgbe_set_vfta_generic, \ 38308c2ecf20Sopenharmony_ci .fc_enable = &ixgbe_fc_enable_generic, \ 38318c2ecf20Sopenharmony_ci .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_x550, \ 38328c2ecf20Sopenharmony_ci .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 38338c2ecf20Sopenharmony_ci .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 38348c2ecf20Sopenharmony_ci .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 38358c2ecf20Sopenharmony_ci .set_source_address_pruning = \ 38368c2ecf20Sopenharmony_ci &ixgbe_set_source_address_pruning_X550, \ 38378c2ecf20Sopenharmony_ci .set_ethertype_anti_spoofing = \ 38388c2ecf20Sopenharmony_ci &ixgbe_set_ethertype_anti_spoofing_X550, \ 38398c2ecf20Sopenharmony_ci .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 38408c2ecf20Sopenharmony_ci .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 38418c2ecf20Sopenharmony_ci .get_thermal_sensor_data = NULL, \ 38428c2ecf20Sopenharmony_ci .init_thermal_sensor_thresh = NULL, \ 38438c2ecf20Sopenharmony_ci .fw_recovery_mode = &ixgbe_fw_recovery_mode_X550, \ 38448c2ecf20Sopenharmony_ci .enable_rx = &ixgbe_enable_rx_generic, \ 38458c2ecf20Sopenharmony_ci .disable_rx = &ixgbe_disable_rx_x550, \ 38468c2ecf20Sopenharmony_ci 38478c2ecf20Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_X550 = { 38488c2ecf20Sopenharmony_ci X550_COMMON_MAC 38498c2ecf20Sopenharmony_ci .led_on = ixgbe_led_on_generic, 38508c2ecf20Sopenharmony_ci .led_off = ixgbe_led_off_generic, 38518c2ecf20Sopenharmony_ci .init_led_link_act = ixgbe_init_led_link_act_generic, 38528c2ecf20Sopenharmony_ci .reset_hw = &ixgbe_reset_hw_X540, 38538c2ecf20Sopenharmony_ci .get_media_type = &ixgbe_get_media_type_X540, 38548c2ecf20Sopenharmony_ci .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 38558c2ecf20Sopenharmony_ci .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 38568c2ecf20Sopenharmony_ci .setup_link = &ixgbe_setup_mac_link_X540, 38578c2ecf20Sopenharmony_ci .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 38588c2ecf20Sopenharmony_ci .get_bus_info = &ixgbe_get_bus_info_generic, 38598c2ecf20Sopenharmony_ci .setup_sfp = NULL, 38608c2ecf20Sopenharmony_ci .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, 38618c2ecf20Sopenharmony_ci .release_swfw_sync = &ixgbe_release_swfw_sync_X540, 38628c2ecf20Sopenharmony_ci .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 38638c2ecf20Sopenharmony_ci .prot_autoc_read = prot_autoc_read_generic, 38648c2ecf20Sopenharmony_ci .prot_autoc_write = prot_autoc_write_generic, 38658c2ecf20Sopenharmony_ci .setup_fc = ixgbe_setup_fc_generic, 38668c2ecf20Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 38678c2ecf20Sopenharmony_ci}; 38688c2ecf20Sopenharmony_ci 38698c2ecf20Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_X550EM_x = { 38708c2ecf20Sopenharmony_ci X550_COMMON_MAC 38718c2ecf20Sopenharmony_ci .led_on = ixgbe_led_on_t_x550em, 38728c2ecf20Sopenharmony_ci .led_off = ixgbe_led_off_t_x550em, 38738c2ecf20Sopenharmony_ci .init_led_link_act = ixgbe_init_led_link_act_generic, 38748c2ecf20Sopenharmony_ci .reset_hw = &ixgbe_reset_hw_X550em, 38758c2ecf20Sopenharmony_ci .get_media_type = &ixgbe_get_media_type_X550em, 38768c2ecf20Sopenharmony_ci .get_san_mac_addr = NULL, 38778c2ecf20Sopenharmony_ci .get_wwn_prefix = NULL, 38788c2ecf20Sopenharmony_ci .setup_link = &ixgbe_setup_mac_link_X540, 38798c2ecf20Sopenharmony_ci .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 38808c2ecf20Sopenharmony_ci .get_bus_info = &ixgbe_get_bus_info_X550em, 38818c2ecf20Sopenharmony_ci .setup_sfp = ixgbe_setup_sfp_modules_X550em, 38828c2ecf20Sopenharmony_ci .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 38838c2ecf20Sopenharmony_ci .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 38848c2ecf20Sopenharmony_ci .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 38858c2ecf20Sopenharmony_ci .setup_fc = NULL, /* defined later */ 38868c2ecf20Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 38878c2ecf20Sopenharmony_ci .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, 38888c2ecf20Sopenharmony_ci .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, 38898c2ecf20Sopenharmony_ci}; 38908c2ecf20Sopenharmony_ci 38918c2ecf20Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_X550EM_x_fw = { 38928c2ecf20Sopenharmony_ci X550_COMMON_MAC 38938c2ecf20Sopenharmony_ci .led_on = NULL, 38948c2ecf20Sopenharmony_ci .led_off = NULL, 38958c2ecf20Sopenharmony_ci .init_led_link_act = NULL, 38968c2ecf20Sopenharmony_ci .reset_hw = &ixgbe_reset_hw_X550em, 38978c2ecf20Sopenharmony_ci .get_media_type = &ixgbe_get_media_type_X550em, 38988c2ecf20Sopenharmony_ci .get_san_mac_addr = NULL, 38998c2ecf20Sopenharmony_ci .get_wwn_prefix = NULL, 39008c2ecf20Sopenharmony_ci .setup_link = &ixgbe_setup_mac_link_X540, 39018c2ecf20Sopenharmony_ci .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 39028c2ecf20Sopenharmony_ci .get_bus_info = &ixgbe_get_bus_info_X550em, 39038c2ecf20Sopenharmony_ci .setup_sfp = ixgbe_setup_sfp_modules_X550em, 39048c2ecf20Sopenharmony_ci .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 39058c2ecf20Sopenharmony_ci .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 39068c2ecf20Sopenharmony_ci .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 39078c2ecf20Sopenharmony_ci .setup_fc = NULL, 39088c2ecf20Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 39098c2ecf20Sopenharmony_ci .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, 39108c2ecf20Sopenharmony_ci .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, 39118c2ecf20Sopenharmony_ci}; 39128c2ecf20Sopenharmony_ci 39138c2ecf20Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_x550em_a = { 39148c2ecf20Sopenharmony_ci X550_COMMON_MAC 39158c2ecf20Sopenharmony_ci .led_on = ixgbe_led_on_t_x550em, 39168c2ecf20Sopenharmony_ci .led_off = ixgbe_led_off_t_x550em, 39178c2ecf20Sopenharmony_ci .init_led_link_act = ixgbe_init_led_link_act_generic, 39188c2ecf20Sopenharmony_ci .reset_hw = ixgbe_reset_hw_X550em, 39198c2ecf20Sopenharmony_ci .get_media_type = ixgbe_get_media_type_X550em, 39208c2ecf20Sopenharmony_ci .get_san_mac_addr = NULL, 39218c2ecf20Sopenharmony_ci .get_wwn_prefix = NULL, 39228c2ecf20Sopenharmony_ci .setup_link = &ixgbe_setup_mac_link_X540, 39238c2ecf20Sopenharmony_ci .get_link_capabilities = ixgbe_get_link_capabilities_X550em, 39248c2ecf20Sopenharmony_ci .get_bus_info = ixgbe_get_bus_info_X550em, 39258c2ecf20Sopenharmony_ci .setup_sfp = ixgbe_setup_sfp_modules_X550em, 39268c2ecf20Sopenharmony_ci .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, 39278c2ecf20Sopenharmony_ci .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, 39288c2ecf20Sopenharmony_ci .setup_fc = ixgbe_setup_fc_x550em, 39298c2ecf20Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 39308c2ecf20Sopenharmony_ci .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, 39318c2ecf20Sopenharmony_ci .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, 39328c2ecf20Sopenharmony_ci}; 39338c2ecf20Sopenharmony_ci 39348c2ecf20Sopenharmony_cistatic const struct ixgbe_mac_operations mac_ops_x550em_a_fw = { 39358c2ecf20Sopenharmony_ci X550_COMMON_MAC 39368c2ecf20Sopenharmony_ci .led_on = ixgbe_led_on_generic, 39378c2ecf20Sopenharmony_ci .led_off = ixgbe_led_off_generic, 39388c2ecf20Sopenharmony_ci .init_led_link_act = ixgbe_init_led_link_act_generic, 39398c2ecf20Sopenharmony_ci .reset_hw = ixgbe_reset_hw_X550em, 39408c2ecf20Sopenharmony_ci .get_media_type = ixgbe_get_media_type_X550em, 39418c2ecf20Sopenharmony_ci .get_san_mac_addr = NULL, 39428c2ecf20Sopenharmony_ci .get_wwn_prefix = NULL, 39438c2ecf20Sopenharmony_ci .setup_link = NULL, /* defined later */ 39448c2ecf20Sopenharmony_ci .get_link_capabilities = ixgbe_get_link_capabilities_X550em, 39458c2ecf20Sopenharmony_ci .get_bus_info = ixgbe_get_bus_info_X550em, 39468c2ecf20Sopenharmony_ci .setup_sfp = ixgbe_setup_sfp_modules_X550em, 39478c2ecf20Sopenharmony_ci .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, 39488c2ecf20Sopenharmony_ci .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, 39498c2ecf20Sopenharmony_ci .setup_fc = ixgbe_setup_fc_x550em, 39508c2ecf20Sopenharmony_ci .fc_autoneg = ixgbe_fc_autoneg, 39518c2ecf20Sopenharmony_ci .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, 39528c2ecf20Sopenharmony_ci .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, 39538c2ecf20Sopenharmony_ci}; 39548c2ecf20Sopenharmony_ci 39558c2ecf20Sopenharmony_ci#define X550_COMMON_EEP \ 39568c2ecf20Sopenharmony_ci .read = &ixgbe_read_ee_hostif_X550, \ 39578c2ecf20Sopenharmony_ci .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 39588c2ecf20Sopenharmony_ci .write = &ixgbe_write_ee_hostif_X550, \ 39598c2ecf20Sopenharmony_ci .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 39608c2ecf20Sopenharmony_ci .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 39618c2ecf20Sopenharmony_ci .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 39628c2ecf20Sopenharmony_ci .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 39638c2ecf20Sopenharmony_ci 39648c2ecf20Sopenharmony_cistatic const struct ixgbe_eeprom_operations eeprom_ops_X550 = { 39658c2ecf20Sopenharmony_ci X550_COMMON_EEP 39668c2ecf20Sopenharmony_ci .init_params = &ixgbe_init_eeprom_params_X550, 39678c2ecf20Sopenharmony_ci}; 39688c2ecf20Sopenharmony_ci 39698c2ecf20Sopenharmony_cistatic const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 39708c2ecf20Sopenharmony_ci X550_COMMON_EEP 39718c2ecf20Sopenharmony_ci .init_params = &ixgbe_init_eeprom_params_X540, 39728c2ecf20Sopenharmony_ci}; 39738c2ecf20Sopenharmony_ci 39748c2ecf20Sopenharmony_ci#define X550_COMMON_PHY \ 39758c2ecf20Sopenharmony_ci .identify_sfp = &ixgbe_identify_module_generic, \ 39768c2ecf20Sopenharmony_ci .reset = NULL, \ 39778c2ecf20Sopenharmony_ci .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 39788c2ecf20Sopenharmony_ci .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 39798c2ecf20Sopenharmony_ci .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 39808c2ecf20Sopenharmony_ci .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 39818c2ecf20Sopenharmony_ci .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 39828c2ecf20Sopenharmony_ci .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 39838c2ecf20Sopenharmony_ci .setup_link = &ixgbe_setup_phy_link_generic, \ 39848c2ecf20Sopenharmony_ci .set_phy_power = NULL, 39858c2ecf20Sopenharmony_ci 39868c2ecf20Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_X550 = { 39878c2ecf20Sopenharmony_ci X550_COMMON_PHY 39888c2ecf20Sopenharmony_ci .check_overtemp = &ixgbe_tn_check_overtemp, 39898c2ecf20Sopenharmony_ci .init = NULL, 39908c2ecf20Sopenharmony_ci .identify = &ixgbe_identify_phy_generic, 39918c2ecf20Sopenharmony_ci .read_reg = &ixgbe_read_phy_reg_generic, 39928c2ecf20Sopenharmony_ci .write_reg = &ixgbe_write_phy_reg_generic, 39938c2ecf20Sopenharmony_ci}; 39948c2ecf20Sopenharmony_ci 39958c2ecf20Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_X550EM_x = { 39968c2ecf20Sopenharmony_ci X550_COMMON_PHY 39978c2ecf20Sopenharmony_ci .check_overtemp = &ixgbe_tn_check_overtemp, 39988c2ecf20Sopenharmony_ci .init = &ixgbe_init_phy_ops_X550em, 39998c2ecf20Sopenharmony_ci .identify = &ixgbe_identify_phy_x550em, 40008c2ecf20Sopenharmony_ci .read_reg = &ixgbe_read_phy_reg_generic, 40018c2ecf20Sopenharmony_ci .write_reg = &ixgbe_write_phy_reg_generic, 40028c2ecf20Sopenharmony_ci}; 40038c2ecf20Sopenharmony_ci 40048c2ecf20Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_x550em_x_fw = { 40058c2ecf20Sopenharmony_ci X550_COMMON_PHY 40068c2ecf20Sopenharmony_ci .check_overtemp = NULL, 40078c2ecf20Sopenharmony_ci .init = ixgbe_init_phy_ops_X550em, 40088c2ecf20Sopenharmony_ci .identify = ixgbe_identify_phy_x550em, 40098c2ecf20Sopenharmony_ci .read_reg = NULL, 40108c2ecf20Sopenharmony_ci .write_reg = NULL, 40118c2ecf20Sopenharmony_ci .read_reg_mdi = NULL, 40128c2ecf20Sopenharmony_ci .write_reg_mdi = NULL, 40138c2ecf20Sopenharmony_ci}; 40148c2ecf20Sopenharmony_ci 40158c2ecf20Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_x550em_a = { 40168c2ecf20Sopenharmony_ci X550_COMMON_PHY 40178c2ecf20Sopenharmony_ci .check_overtemp = &ixgbe_tn_check_overtemp, 40188c2ecf20Sopenharmony_ci .init = &ixgbe_init_phy_ops_X550em, 40198c2ecf20Sopenharmony_ci .identify = &ixgbe_identify_phy_x550em, 40208c2ecf20Sopenharmony_ci .read_reg = &ixgbe_read_phy_reg_x550a, 40218c2ecf20Sopenharmony_ci .write_reg = &ixgbe_write_phy_reg_x550a, 40228c2ecf20Sopenharmony_ci .read_reg_mdi = &ixgbe_read_phy_reg_mdi, 40238c2ecf20Sopenharmony_ci .write_reg_mdi = &ixgbe_write_phy_reg_mdi, 40248c2ecf20Sopenharmony_ci}; 40258c2ecf20Sopenharmony_ci 40268c2ecf20Sopenharmony_cistatic const struct ixgbe_phy_operations phy_ops_x550em_a_fw = { 40278c2ecf20Sopenharmony_ci X550_COMMON_PHY 40288c2ecf20Sopenharmony_ci .check_overtemp = ixgbe_check_overtemp_fw, 40298c2ecf20Sopenharmony_ci .init = ixgbe_init_phy_ops_X550em, 40308c2ecf20Sopenharmony_ci .identify = ixgbe_identify_phy_fw, 40318c2ecf20Sopenharmony_ci .read_reg = NULL, 40328c2ecf20Sopenharmony_ci .write_reg = NULL, 40338c2ecf20Sopenharmony_ci .read_reg_mdi = NULL, 40348c2ecf20Sopenharmony_ci .write_reg_mdi = NULL, 40358c2ecf20Sopenharmony_ci}; 40368c2ecf20Sopenharmony_ci 40378c2ecf20Sopenharmony_cistatic const struct ixgbe_link_operations link_ops_x550em_x = { 40388c2ecf20Sopenharmony_ci .read_link = &ixgbe_read_i2c_combined_generic, 40398c2ecf20Sopenharmony_ci .read_link_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, 40408c2ecf20Sopenharmony_ci .write_link = &ixgbe_write_i2c_combined_generic, 40418c2ecf20Sopenharmony_ci .write_link_unlocked = &ixgbe_write_i2c_combined_generic_unlocked, 40428c2ecf20Sopenharmony_ci}; 40438c2ecf20Sopenharmony_ci 40448c2ecf20Sopenharmony_cistatic const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 40458c2ecf20Sopenharmony_ci IXGBE_MVALS_INIT(X550) 40468c2ecf20Sopenharmony_ci}; 40478c2ecf20Sopenharmony_ci 40488c2ecf20Sopenharmony_cistatic const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 40498c2ecf20Sopenharmony_ci IXGBE_MVALS_INIT(X550EM_x) 40508c2ecf20Sopenharmony_ci}; 40518c2ecf20Sopenharmony_ci 40528c2ecf20Sopenharmony_cistatic const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = { 40538c2ecf20Sopenharmony_ci IXGBE_MVALS_INIT(X550EM_a) 40548c2ecf20Sopenharmony_ci}; 40558c2ecf20Sopenharmony_ci 40568c2ecf20Sopenharmony_ciconst struct ixgbe_info ixgbe_X550_info = { 40578c2ecf20Sopenharmony_ci .mac = ixgbe_mac_X550, 40588c2ecf20Sopenharmony_ci .get_invariants = &ixgbe_get_invariants_X540, 40598c2ecf20Sopenharmony_ci .mac_ops = &mac_ops_X550, 40608c2ecf20Sopenharmony_ci .eeprom_ops = &eeprom_ops_X550, 40618c2ecf20Sopenharmony_ci .phy_ops = &phy_ops_X550, 40628c2ecf20Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 40638c2ecf20Sopenharmony_ci .mvals = ixgbe_mvals_X550, 40648c2ecf20Sopenharmony_ci}; 40658c2ecf20Sopenharmony_ci 40668c2ecf20Sopenharmony_ciconst struct ixgbe_info ixgbe_X550EM_x_info = { 40678c2ecf20Sopenharmony_ci .mac = ixgbe_mac_X550EM_x, 40688c2ecf20Sopenharmony_ci .get_invariants = &ixgbe_get_invariants_X550_x, 40698c2ecf20Sopenharmony_ci .mac_ops = &mac_ops_X550EM_x, 40708c2ecf20Sopenharmony_ci .eeprom_ops = &eeprom_ops_X550EM_x, 40718c2ecf20Sopenharmony_ci .phy_ops = &phy_ops_X550EM_x, 40728c2ecf20Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 40738c2ecf20Sopenharmony_ci .mvals = ixgbe_mvals_X550EM_x, 40748c2ecf20Sopenharmony_ci .link_ops = &link_ops_x550em_x, 40758c2ecf20Sopenharmony_ci}; 40768c2ecf20Sopenharmony_ci 40778c2ecf20Sopenharmony_ciconst struct ixgbe_info ixgbe_x550em_x_fw_info = { 40788c2ecf20Sopenharmony_ci .mac = ixgbe_mac_X550EM_x, 40798c2ecf20Sopenharmony_ci .get_invariants = ixgbe_get_invariants_X550_x_fw, 40808c2ecf20Sopenharmony_ci .mac_ops = &mac_ops_X550EM_x_fw, 40818c2ecf20Sopenharmony_ci .eeprom_ops = &eeprom_ops_X550EM_x, 40828c2ecf20Sopenharmony_ci .phy_ops = &phy_ops_x550em_x_fw, 40838c2ecf20Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 40848c2ecf20Sopenharmony_ci .mvals = ixgbe_mvals_X550EM_x, 40858c2ecf20Sopenharmony_ci}; 40868c2ecf20Sopenharmony_ci 40878c2ecf20Sopenharmony_ciconst struct ixgbe_info ixgbe_x550em_a_info = { 40888c2ecf20Sopenharmony_ci .mac = ixgbe_mac_x550em_a, 40898c2ecf20Sopenharmony_ci .get_invariants = &ixgbe_get_invariants_X550_a, 40908c2ecf20Sopenharmony_ci .mac_ops = &mac_ops_x550em_a, 40918c2ecf20Sopenharmony_ci .eeprom_ops = &eeprom_ops_X550EM_x, 40928c2ecf20Sopenharmony_ci .phy_ops = &phy_ops_x550em_a, 40938c2ecf20Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 40948c2ecf20Sopenharmony_ci .mvals = ixgbe_mvals_x550em_a, 40958c2ecf20Sopenharmony_ci}; 40968c2ecf20Sopenharmony_ci 40978c2ecf20Sopenharmony_ciconst struct ixgbe_info ixgbe_x550em_a_fw_info = { 40988c2ecf20Sopenharmony_ci .mac = ixgbe_mac_x550em_a, 40998c2ecf20Sopenharmony_ci .get_invariants = ixgbe_get_invariants_X550_a_fw, 41008c2ecf20Sopenharmony_ci .mac_ops = &mac_ops_x550em_a_fw, 41018c2ecf20Sopenharmony_ci .eeprom_ops = &eeprom_ops_X550EM_x, 41028c2ecf20Sopenharmony_ci .phy_ops = &phy_ops_x550em_a_fw, 41038c2ecf20Sopenharmony_ci .mbx_ops = &mbx_ops_generic, 41048c2ecf20Sopenharmony_ci .mvals = ixgbe_mvals_x550em_a, 41058c2ecf20Sopenharmony_ci}; 4106