16a14ee0cSDon Skidmore /******************************************************************************* 26a14ee0cSDon Skidmore * 36a14ee0cSDon Skidmore * Intel 10 Gigabit PCI Express Linux driver 437689010SMark Rustad * Copyright(c) 1999 - 2016 Intel Corporation. 56a14ee0cSDon Skidmore * 66a14ee0cSDon Skidmore * This program is free software; you can redistribute it and/or modify it 76a14ee0cSDon Skidmore * under the terms and conditions of the GNU General Public License, 86a14ee0cSDon Skidmore * version 2, as published by the Free Software Foundation. 96a14ee0cSDon Skidmore * 106a14ee0cSDon Skidmore * This program is distributed in the hope it will be useful, but WITHOUT 116a14ee0cSDon Skidmore * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 126a14ee0cSDon Skidmore * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 136a14ee0cSDon Skidmore * more details. 146a14ee0cSDon Skidmore * 156a14ee0cSDon Skidmore * The full GNU General Public License is included in this distribution in 166a14ee0cSDon Skidmore * the file called "COPYING". 176a14ee0cSDon Skidmore * 186a14ee0cSDon Skidmore * Contact Information: 196a14ee0cSDon Skidmore * Linux NICS <linux.nics@intel.com> 206a14ee0cSDon Skidmore * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 216a14ee0cSDon Skidmore * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 226a14ee0cSDon Skidmore * 236a14ee0cSDon Skidmore ******************************************************************************/ 246a14ee0cSDon Skidmore #include "ixgbe_x540.h" 256a14ee0cSDon Skidmore #include "ixgbe_type.h" 266a14ee0cSDon Skidmore #include "ixgbe_common.h" 276a14ee0cSDon Skidmore #include "ixgbe_phy.h" 286a14ee0cSDon Skidmore 29d91e3a7dSMark Rustad static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed); 30afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *); 31d91e3a7dSMark Rustad 32b5529ef5SDon Skidmore static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) 33b5529ef5SDon Skidmore { 34b5529ef5SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 35b5529ef5SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 36b5529ef5SDon Skidmore 37b5529ef5SDon Skidmore /* Start with X540 invariants, since so simular */ 38b5529ef5SDon Skidmore ixgbe_get_invariants_X540(hw); 39b5529ef5SDon Skidmore 40b5529ef5SDon Skidmore if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 41b5529ef5SDon Skidmore phy->ops.set_phy_power = NULL; 42b5529ef5SDon Skidmore 43b5529ef5SDon Skidmore return 0; 44b5529ef5SDon Skidmore } 45b5529ef5SDon Skidmore 46ab5fe0c5SDon Skidmore /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control 47ab5fe0c5SDon Skidmore * @hw: pointer to hardware structure 48ab5fe0c5SDon Skidmore **/ 49ab5fe0c5SDon Skidmore static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) 50ab5fe0c5SDon Skidmore { 51ab5fe0c5SDon Skidmore u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 52ab5fe0c5SDon Skidmore 53ab5fe0c5SDon Skidmore if (hw->bus.lan_id) { 54ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 55ab5fe0c5SDon Skidmore esdp |= IXGBE_ESDP_SDP1_DIR; 56ab5fe0c5SDon Skidmore } 57ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 58ab5fe0c5SDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 59ab5fe0c5SDon Skidmore IXGBE_WRITE_FLUSH(hw); 60ab5fe0c5SDon Skidmore } 61ab5fe0c5SDon Skidmore 62542b6eecSMark Rustad /** 63542b6eecSMark Rustad * ixgbe_read_cs4227 - Read CS4227 register 64542b6eecSMark Rustad * @hw: pointer to hardware structure 65542b6eecSMark Rustad * @reg: register number to write 66542b6eecSMark Rustad * @value: pointer to receive value read 67542b6eecSMark Rustad * 68542b6eecSMark Rustad * Returns status code 69542b6eecSMark Rustad */ 70542b6eecSMark Rustad static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) 71542b6eecSMark Rustad { 72542b6eecSMark Rustad return hw->phy.ops.read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, 73542b6eecSMark Rustad value); 74542b6eecSMark Rustad } 75542b6eecSMark Rustad 76542b6eecSMark Rustad /** 77542b6eecSMark Rustad * ixgbe_write_cs4227 - Write CS4227 register 78542b6eecSMark Rustad * @hw: pointer to hardware structure 79542b6eecSMark Rustad * @reg: register number to write 80542b6eecSMark Rustad * @value: value to write to register 81542b6eecSMark Rustad * 82542b6eecSMark Rustad * Returns status code 83542b6eecSMark Rustad */ 84542b6eecSMark Rustad static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) 85542b6eecSMark Rustad { 86542b6eecSMark Rustad return hw->phy.ops.write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, 87542b6eecSMark Rustad value); 88542b6eecSMark Rustad } 89542b6eecSMark Rustad 90542b6eecSMark Rustad /** 91542b6eecSMark Rustad * ixgbe_read_pe - Read register from port expander 92542b6eecSMark Rustad * @hw: pointer to hardware structure 93542b6eecSMark Rustad * @reg: register number to read 94542b6eecSMark Rustad * @value: pointer to receive read value 95542b6eecSMark Rustad * 96542b6eecSMark Rustad * Returns status code 97542b6eecSMark Rustad */ 98542b6eecSMark Rustad static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) 99542b6eecSMark Rustad { 100542b6eecSMark Rustad s32 status; 101542b6eecSMark Rustad 102542b6eecSMark Rustad status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, value); 103542b6eecSMark Rustad if (status) 104542b6eecSMark Rustad hw_err(hw, "port expander access failed with %d\n", status); 105542b6eecSMark Rustad return status; 106542b6eecSMark Rustad } 107542b6eecSMark Rustad 108542b6eecSMark Rustad /** 109542b6eecSMark Rustad * ixgbe_write_pe - Write register to port expander 110542b6eecSMark Rustad * @hw: pointer to hardware structure 111542b6eecSMark Rustad * @reg: register number to write 112542b6eecSMark Rustad * @value: value to write 113542b6eecSMark Rustad * 114542b6eecSMark Rustad * Returns status code 115542b6eecSMark Rustad */ 116542b6eecSMark Rustad static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) 117542b6eecSMark Rustad { 118542b6eecSMark Rustad s32 status; 119542b6eecSMark Rustad 120542b6eecSMark Rustad status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, 121542b6eecSMark Rustad value); 122542b6eecSMark Rustad if (status) 123542b6eecSMark Rustad hw_err(hw, "port expander access failed with %d\n", status); 124542b6eecSMark Rustad return status; 125542b6eecSMark Rustad } 126542b6eecSMark Rustad 127542b6eecSMark Rustad /** 128542b6eecSMark Rustad * ixgbe_reset_cs4227 - Reset CS4227 using port expander 129542b6eecSMark Rustad * @hw: pointer to hardware structure 130542b6eecSMark Rustad * 1318bf7a7b8SMark Rustad * This function assumes that the caller has acquired the proper semaphore. 132542b6eecSMark Rustad * Returns error code 133542b6eecSMark Rustad */ 134542b6eecSMark Rustad static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) 135542b6eecSMark Rustad { 136542b6eecSMark Rustad s32 status; 137542b6eecSMark Rustad u32 retry; 138542b6eecSMark Rustad u16 value; 139542b6eecSMark Rustad u8 reg; 140542b6eecSMark Rustad 141542b6eecSMark Rustad /* Trigger hard reset. */ 142542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 143542b6eecSMark Rustad if (status) 144542b6eecSMark Rustad return status; 145542b6eecSMark Rustad reg |= IXGBE_PE_BIT1; 146542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 147542b6eecSMark Rustad if (status) 148542b6eecSMark Rustad return status; 149542b6eecSMark Rustad 150542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); 151542b6eecSMark Rustad if (status) 152542b6eecSMark Rustad return status; 153542b6eecSMark Rustad reg &= ~IXGBE_PE_BIT1; 154542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); 155542b6eecSMark Rustad if (status) 156542b6eecSMark Rustad return status; 157542b6eecSMark Rustad 158542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 159542b6eecSMark Rustad if (status) 160542b6eecSMark Rustad return status; 161542b6eecSMark Rustad reg &= ~IXGBE_PE_BIT1; 162542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 163542b6eecSMark Rustad if (status) 164542b6eecSMark Rustad return status; 165542b6eecSMark Rustad 166542b6eecSMark Rustad usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100); 167542b6eecSMark Rustad 168542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 169542b6eecSMark Rustad if (status) 170542b6eecSMark Rustad return status; 171542b6eecSMark Rustad reg |= IXGBE_PE_BIT1; 172542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 173542b6eecSMark Rustad if (status) 174542b6eecSMark Rustad return status; 175542b6eecSMark Rustad 176542b6eecSMark Rustad /* Wait for the reset to complete. */ 177542b6eecSMark Rustad msleep(IXGBE_CS4227_RESET_DELAY); 178542b6eecSMark Rustad for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 179542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, 180542b6eecSMark Rustad &value); 181542b6eecSMark Rustad if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK) 182542b6eecSMark Rustad break; 183542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 184542b6eecSMark Rustad } 185542b6eecSMark Rustad if (retry == IXGBE_CS4227_RETRIES) { 186542b6eecSMark Rustad hw_err(hw, "CS4227 reset did not complete\n"); 187542b6eecSMark Rustad return IXGBE_ERR_PHY; 188542b6eecSMark Rustad } 189542b6eecSMark Rustad 190542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value); 191542b6eecSMark Rustad if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { 192542b6eecSMark Rustad hw_err(hw, "CS4227 EEPROM did not load successfully\n"); 193542b6eecSMark Rustad return IXGBE_ERR_PHY; 194542b6eecSMark Rustad } 195542b6eecSMark Rustad 196542b6eecSMark Rustad return 0; 197542b6eecSMark Rustad } 198542b6eecSMark Rustad 199542b6eecSMark Rustad /** 200542b6eecSMark Rustad * ixgbe_check_cs4227 - Check CS4227 and reset as needed 201542b6eecSMark Rustad * @hw: pointer to hardware structure 202542b6eecSMark Rustad */ 203542b6eecSMark Rustad static void ixgbe_check_cs4227(struct ixgbe_hw *hw) 204542b6eecSMark Rustad { 205542b6eecSMark Rustad u32 swfw_mask = hw->phy.phy_semaphore_mask; 206542b6eecSMark Rustad s32 status; 207542b6eecSMark Rustad u16 value; 208542b6eecSMark Rustad u8 retry; 209542b6eecSMark Rustad 210542b6eecSMark Rustad for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 211542b6eecSMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 212542b6eecSMark Rustad if (status) { 213542b6eecSMark Rustad hw_err(hw, "semaphore failed with %d\n", status); 214542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 215542b6eecSMark Rustad continue; 216542b6eecSMark Rustad } 217542b6eecSMark Rustad 218542b6eecSMark Rustad /* Get status of reset flow. */ 219542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); 220542b6eecSMark Rustad if (!status && value == IXGBE_CS4227_RESET_COMPLETE) 221542b6eecSMark Rustad goto out; 222542b6eecSMark Rustad 223542b6eecSMark Rustad if (status || value != IXGBE_CS4227_RESET_PENDING) 224542b6eecSMark Rustad break; 225542b6eecSMark Rustad 226542b6eecSMark Rustad /* Reset is pending. Wait and check again. */ 227542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 228542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 229542b6eecSMark Rustad } 2308bf7a7b8SMark Rustad /* If still pending, assume other instance failed. */ 2318bf7a7b8SMark Rustad if (retry == IXGBE_CS4227_RETRIES) { 2328bf7a7b8SMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 2338bf7a7b8SMark Rustad if (status) { 2348bf7a7b8SMark Rustad hw_err(hw, "semaphore failed with %d\n", status); 2358bf7a7b8SMark Rustad return; 2368bf7a7b8SMark Rustad } 2378bf7a7b8SMark Rustad } 238542b6eecSMark Rustad 239542b6eecSMark Rustad /* Reset the CS4227. */ 240542b6eecSMark Rustad status = ixgbe_reset_cs4227(hw); 241542b6eecSMark Rustad if (status) { 242542b6eecSMark Rustad hw_err(hw, "CS4227 reset failed: %d", status); 243542b6eecSMark Rustad goto out; 244542b6eecSMark Rustad } 245542b6eecSMark Rustad 246542b6eecSMark Rustad /* Reset takes so long, temporarily release semaphore in case the 247542b6eecSMark Rustad * other driver instance is waiting for the reset indication. 248542b6eecSMark Rustad */ 249542b6eecSMark Rustad ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 250542b6eecSMark Rustad IXGBE_CS4227_RESET_PENDING); 251542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 252542b6eecSMark Rustad usleep_range(10000, 12000); 253542b6eecSMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 254542b6eecSMark Rustad if (status) { 255542b6eecSMark Rustad hw_err(hw, "semaphore failed with %d", status); 256542b6eecSMark Rustad return; 257542b6eecSMark Rustad } 258542b6eecSMark Rustad 259542b6eecSMark Rustad /* Record completion for next time. */ 260542b6eecSMark Rustad status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 261542b6eecSMark Rustad IXGBE_CS4227_RESET_COMPLETE); 262542b6eecSMark Rustad 263542b6eecSMark Rustad out: 264542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 265542b6eecSMark Rustad msleep(hw->eeprom.semaphore_delay); 266542b6eecSMark Rustad } 267542b6eecSMark Rustad 2686a14ee0cSDon Skidmore /** ixgbe_identify_phy_x550em - Get PHY type based on device id 2696a14ee0cSDon Skidmore * @hw: pointer to hardware structure 2706a14ee0cSDon Skidmore * 2716a14ee0cSDon Skidmore * Returns error code 2726a14ee0cSDon Skidmore */ 2736a14ee0cSDon Skidmore static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) 2746a14ee0cSDon Skidmore { 2756a14ee0cSDon Skidmore switch (hw->device_id) { 2762d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 2772d40cd17SMark Rustad if (hw->bus.lan_id) 2782d40cd17SMark Rustad hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 2792d40cd17SMark Rustad else 2802d40cd17SMark Rustad hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 2812d40cd17SMark Rustad return ixgbe_identify_module_generic(hw); 2826a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 2836a14ee0cSDon Skidmore /* set up for CS4227 usage */ 2846a14ee0cSDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 285ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 286542b6eecSMark Rustad ixgbe_check_cs4227(hw); 28749425dfcSMark Rustad /* Fallthrough */ 28849425dfcSMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 2896a14ee0cSDon Skidmore return ixgbe_identify_module_generic(hw); 2906a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 2916a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kx4; 2926a14ee0cSDon Skidmore break; 2936a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 294f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR: 295f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR_L: 2966a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kr; 2976a14ee0cSDon Skidmore break; 29892ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 29992ed8430SDon Skidmore if (hw->bus.lan_id) 30092ed8430SDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 30192ed8430SDon Skidmore else 30292ed8430SDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 30392ed8430SDon Skidmore /* Fallthrough */ 3046a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 3056a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 3066a14ee0cSDon Skidmore return ixgbe_identify_phy_generic(hw); 3076a14ee0cSDon Skidmore default: 3086a14ee0cSDon Skidmore break; 3096a14ee0cSDon Skidmore } 3106a14ee0cSDon Skidmore return 0; 3116a14ee0cSDon Skidmore } 3126a14ee0cSDon Skidmore 3136a14ee0cSDon Skidmore static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 3146a14ee0cSDon Skidmore u32 device_type, u16 *phy_data) 3156a14ee0cSDon Skidmore { 3166a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 3176a14ee0cSDon Skidmore } 3186a14ee0cSDon Skidmore 3196a14ee0cSDon Skidmore static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 3206a14ee0cSDon Skidmore u32 device_type, u16 phy_data) 3216a14ee0cSDon Skidmore { 3226a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 3236a14ee0cSDon Skidmore } 3246a14ee0cSDon Skidmore 3256a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 3266a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3276a14ee0cSDon Skidmore * 3286a14ee0cSDon Skidmore * Initializes the EEPROM parameters ixgbe_eeprom_info within the 3296a14ee0cSDon Skidmore * ixgbe_hw struct in order to set up EEPROM access. 3306a14ee0cSDon Skidmore **/ 3317ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 3326a14ee0cSDon Skidmore { 3336a14ee0cSDon Skidmore struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 3346a14ee0cSDon Skidmore u32 eec; 3356a14ee0cSDon Skidmore u16 eeprom_size; 3366a14ee0cSDon Skidmore 3376a14ee0cSDon Skidmore if (eeprom->type == ixgbe_eeprom_uninitialized) { 3386a14ee0cSDon Skidmore eeprom->semaphore_delay = 10; 3396a14ee0cSDon Skidmore eeprom->type = ixgbe_flash; 3406a14ee0cSDon Skidmore 3419a900ecaSDon Skidmore eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 3426a14ee0cSDon Skidmore eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 3436a14ee0cSDon Skidmore IXGBE_EEC_SIZE_SHIFT); 344b4f47a48SJacob Keller eeprom->word_size = BIT(eeprom_size + 3456a14ee0cSDon Skidmore IXGBE_EEPROM_WORD_SIZE_SHIFT); 3466a14ee0cSDon Skidmore 3476a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 3486a14ee0cSDon Skidmore eeprom->type, eeprom->word_size); 3496a14ee0cSDon Skidmore } 3506a14ee0cSDon Skidmore 3516a14ee0cSDon Skidmore return 0; 3526a14ee0cSDon Skidmore } 3536a14ee0cSDon Skidmore 354ae14a1d8SMark Rustad /** 355ae14a1d8SMark Rustad * ixgbe_iosf_wait - Wait for IOSF command completion 356ae14a1d8SMark Rustad * @hw: pointer to hardware structure 357ae14a1d8SMark Rustad * @ctrl: pointer to location to receive final IOSF control value 358ae14a1d8SMark Rustad * 359ae14a1d8SMark Rustad * Return: failing status on timeout 360ae14a1d8SMark Rustad * 361ae14a1d8SMark Rustad * Note: ctrl can be NULL if the IOSF control register value is not needed 362ae14a1d8SMark Rustad */ 363ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 364ae14a1d8SMark Rustad { 365ae14a1d8SMark Rustad u32 i, command; 366ae14a1d8SMark Rustad 367ae14a1d8SMark Rustad /* Check every 10 usec to see if the address cycle completed. 368ae14a1d8SMark Rustad * The SB IOSF BUSY bit will clear when the operation is 369ae14a1d8SMark Rustad * complete. 370ae14a1d8SMark Rustad */ 371ae14a1d8SMark Rustad for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 372ae14a1d8SMark Rustad command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 373ae14a1d8SMark Rustad if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 374ae14a1d8SMark Rustad break; 375d90b5b0eSMark Rustad udelay(10); 376ae14a1d8SMark Rustad } 377ae14a1d8SMark Rustad if (ctrl) 378ae14a1d8SMark Rustad *ctrl = command; 379ae14a1d8SMark Rustad if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 380ae14a1d8SMark Rustad hw_dbg(hw, "IOSF wait timed out\n"); 381ae14a1d8SMark Rustad return IXGBE_ERR_PHY; 382ae14a1d8SMark Rustad } 383ae14a1d8SMark Rustad 384ae14a1d8SMark Rustad return 0; 385ae14a1d8SMark Rustad } 386ae14a1d8SMark Rustad 3876a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 3886a14ee0cSDon Skidmore * IOSF device 3896a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3906a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 3916a14ee0cSDon Skidmore * @device_type: 3 bit device type 3926a14ee0cSDon Skidmore * @phy_data: Pointer to read data from the register 3936a14ee0cSDon Skidmore **/ 3947ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 3956a14ee0cSDon Skidmore u32 device_type, u32 *data) 3966a14ee0cSDon Skidmore { 397ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 398ae14a1d8SMark Rustad u32 command, error; 399ae14a1d8SMark Rustad s32 ret; 400ae14a1d8SMark Rustad 401ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 402ae14a1d8SMark Rustad if (ret) 403ae14a1d8SMark Rustad return ret; 404ae14a1d8SMark Rustad 405ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 406ae14a1d8SMark Rustad if (ret) 407ae14a1d8SMark Rustad goto out; 4086a14ee0cSDon Skidmore 4096a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 4106a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 4116a14ee0cSDon Skidmore 4126a14ee0cSDon Skidmore /* Write IOSF control register */ 4136a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 4146a14ee0cSDon Skidmore 415ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 4166a14ee0cSDon Skidmore 4176a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 4186a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 4196a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 4206a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read, error %x\n", error); 4216a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 4226a14ee0cSDon Skidmore } 4236a14ee0cSDon Skidmore 424ae14a1d8SMark Rustad if (!ret) 4256a14ee0cSDon Skidmore *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 4266a14ee0cSDon Skidmore 427ae14a1d8SMark Rustad out: 428ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 429ae14a1d8SMark Rustad return ret; 4306a14ee0cSDon Skidmore } 4316a14ee0cSDon Skidmore 43249425dfcSMark Rustad /** 43349425dfcSMark Rustad * ixgbe_get_phy_token - Get the token for shared PHY access 43449425dfcSMark Rustad * @hw: Pointer to hardware structure 43549425dfcSMark Rustad */ 43649425dfcSMark Rustad static s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) 43749425dfcSMark Rustad { 43849425dfcSMark Rustad struct ixgbe_hic_phy_token_req token_cmd; 43949425dfcSMark Rustad s32 status; 44049425dfcSMark Rustad 44149425dfcSMark Rustad token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 44249425dfcSMark Rustad token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 44349425dfcSMark Rustad token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 44449425dfcSMark Rustad token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 44549425dfcSMark Rustad token_cmd.port_number = hw->bus.lan_id; 44649425dfcSMark Rustad token_cmd.command_type = FW_PHY_TOKEN_REQ; 44749425dfcSMark Rustad token_cmd.pad = 0; 44849425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 44949425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 45049425dfcSMark Rustad true); 45149425dfcSMark Rustad if (status) 45249425dfcSMark Rustad return status; 45349425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 45449425dfcSMark Rustad return 0; 45549425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) 45649425dfcSMark Rustad return IXGBE_ERR_FW_RESP_INVALID; 45749425dfcSMark Rustad 45849425dfcSMark Rustad return IXGBE_ERR_TOKEN_RETRY; 45949425dfcSMark Rustad } 46049425dfcSMark Rustad 46149425dfcSMark Rustad /** 46249425dfcSMark Rustad * ixgbe_put_phy_token - Put the token for shared PHY access 46349425dfcSMark Rustad * @hw: Pointer to hardware structure 46449425dfcSMark Rustad */ 46549425dfcSMark Rustad static s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) 46649425dfcSMark Rustad { 46749425dfcSMark Rustad struct ixgbe_hic_phy_token_req token_cmd; 46849425dfcSMark Rustad s32 status; 46949425dfcSMark Rustad 47049425dfcSMark Rustad token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 47149425dfcSMark Rustad token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 47249425dfcSMark Rustad token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 47349425dfcSMark Rustad token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 47449425dfcSMark Rustad token_cmd.port_number = hw->bus.lan_id; 47549425dfcSMark Rustad token_cmd.command_type = FW_PHY_TOKEN_REL; 47649425dfcSMark Rustad token_cmd.pad = 0; 47749425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 47849425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 47949425dfcSMark Rustad true); 48049425dfcSMark Rustad if (status) 48149425dfcSMark Rustad return status; 48249425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 48349425dfcSMark Rustad return 0; 48449425dfcSMark Rustad return IXGBE_ERR_FW_RESP_INVALID; 48549425dfcSMark Rustad } 48649425dfcSMark Rustad 48749425dfcSMark Rustad /** 48849425dfcSMark Rustad * ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register 48949425dfcSMark Rustad * @hw: pointer to hardware structure 49049425dfcSMark Rustad * @reg_addr: 32 bit PHY register to write 49149425dfcSMark Rustad * @device_type: 3 bit device type 49249425dfcSMark Rustad * @data: Data to write to the register 49349425dfcSMark Rustad **/ 49449425dfcSMark Rustad static s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 49549425dfcSMark Rustad __always_unused u32 device_type, 49649425dfcSMark Rustad u32 data) 49749425dfcSMark Rustad { 49849425dfcSMark Rustad struct ixgbe_hic_internal_phy_req write_cmd; 49949425dfcSMark Rustad 50049425dfcSMark Rustad memset(&write_cmd, 0, sizeof(write_cmd)); 50149425dfcSMark Rustad write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 50249425dfcSMark Rustad write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 50349425dfcSMark Rustad write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 50449425dfcSMark Rustad write_cmd.port_number = hw->bus.lan_id; 50549425dfcSMark Rustad write_cmd.command_type = FW_INT_PHY_REQ_WRITE; 50649425dfcSMark Rustad write_cmd.address = cpu_to_be16(reg_addr); 50749425dfcSMark Rustad write_cmd.write_data = cpu_to_be32(data); 50849425dfcSMark Rustad 50949425dfcSMark Rustad return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd), 51049425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, false); 51149425dfcSMark Rustad } 51249425dfcSMark Rustad 51349425dfcSMark Rustad /** 51449425dfcSMark Rustad * ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register 51549425dfcSMark Rustad * @hw: pointer to hardware structure 51649425dfcSMark Rustad * @reg_addr: 32 bit PHY register to write 51749425dfcSMark Rustad * @device_type: 3 bit device type 51849425dfcSMark Rustad * @data: Pointer to read data from the register 51949425dfcSMark Rustad **/ 52049425dfcSMark Rustad static s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 52149425dfcSMark Rustad __always_unused u32 device_type, 52249425dfcSMark Rustad u32 *data) 52349425dfcSMark Rustad { 52449425dfcSMark Rustad union { 52549425dfcSMark Rustad struct ixgbe_hic_internal_phy_req cmd; 52649425dfcSMark Rustad struct ixgbe_hic_internal_phy_resp rsp; 52749425dfcSMark Rustad } hic; 52849425dfcSMark Rustad s32 status; 52949425dfcSMark Rustad 53049425dfcSMark Rustad memset(&hic, 0, sizeof(hic)); 53149425dfcSMark Rustad hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 53249425dfcSMark Rustad hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 53349425dfcSMark Rustad hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 53449425dfcSMark Rustad hic.cmd.port_number = hw->bus.lan_id; 53549425dfcSMark Rustad hic.cmd.command_type = FW_INT_PHY_REQ_READ; 53649425dfcSMark Rustad hic.cmd.address = cpu_to_be16(reg_addr); 53749425dfcSMark Rustad 53849425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 53949425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, true); 54049425dfcSMark Rustad 54149425dfcSMark Rustad /* Extract the register value from the response. */ 54249425dfcSMark Rustad *data = be32_to_cpu(hic.rsp.read_data); 54349425dfcSMark Rustad 54449425dfcSMark Rustad return status; 54549425dfcSMark Rustad } 54649425dfcSMark Rustad 5476a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface 5486a14ee0cSDon Skidmore * command assuming that the semaphore is already obtained. 5496a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5506a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 5516a14ee0cSDon Skidmore * @data: word read from the EEPROM 5526a14ee0cSDon Skidmore * 5536a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 5546a14ee0cSDon Skidmore **/ 5557ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 5567ddbde3fSDon Skidmore u16 *data) 5576a14ee0cSDon Skidmore { 5586a14ee0cSDon Skidmore s32 status; 5596a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 5606a14ee0cSDon Skidmore 5616a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 5626a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 5636a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 5646a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 5656a14ee0cSDon Skidmore 5666a14ee0cSDon Skidmore /* convert offset from words to bytes */ 5676a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 5686a14ee0cSDon Skidmore /* one word */ 5696a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 5706a14ee0cSDon Skidmore 5715cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 5726a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 5736a14ee0cSDon Skidmore if (status) 5746a14ee0cSDon Skidmore return status; 5756a14ee0cSDon Skidmore 5766a14ee0cSDon Skidmore *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 5776a14ee0cSDon Skidmore FW_NVM_DATA_OFFSET); 5786a14ee0cSDon Skidmore 5796a14ee0cSDon Skidmore return 0; 5806a14ee0cSDon Skidmore } 5816a14ee0cSDon Skidmore 5826a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 5836a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5846a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 5856a14ee0cSDon Skidmore * @words: number of words 5866a14ee0cSDon Skidmore * @data: word(s) read from the EEPROM 5876a14ee0cSDon Skidmore * 5886a14ee0cSDon Skidmore * Reads a 16 bit word(s) from the EEPROM using the hostif. 5896a14ee0cSDon Skidmore **/ 5907ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 5916a14ee0cSDon Skidmore u16 offset, u16 words, u16 *data) 5926a14ee0cSDon Skidmore { 5936a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 5946a14ee0cSDon Skidmore u32 current_word = 0; 5956a14ee0cSDon Skidmore u16 words_to_read; 5966a14ee0cSDon Skidmore s32 status; 5976a14ee0cSDon Skidmore u32 i; 5986a14ee0cSDon Skidmore 5996a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 6006a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 6016a14ee0cSDon Skidmore if (status) { 6026a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 6036a14ee0cSDon Skidmore return status; 6046a14ee0cSDon Skidmore } 6056a14ee0cSDon Skidmore 6066a14ee0cSDon Skidmore while (words) { 6076a14ee0cSDon Skidmore if (words > FW_MAX_READ_BUFFER_SIZE / 2) 6086a14ee0cSDon Skidmore words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 6096a14ee0cSDon Skidmore else 6106a14ee0cSDon Skidmore words_to_read = words; 6116a14ee0cSDon Skidmore 6126a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 6136a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 6146a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 6156a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 6166a14ee0cSDon Skidmore 6176a14ee0cSDon Skidmore /* convert offset from words to bytes */ 6186a14ee0cSDon Skidmore buffer.address = cpu_to_be32((offset + current_word) * 2); 6196a14ee0cSDon Skidmore buffer.length = cpu_to_be16(words_to_read * 2); 6206a14ee0cSDon Skidmore 6215cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, 6226a14ee0cSDon Skidmore sizeof(buffer), 6236a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, 6246a14ee0cSDon Skidmore false); 6256a14ee0cSDon Skidmore if (status) { 6266a14ee0cSDon Skidmore hw_dbg(hw, "Host interface command failed\n"); 6276a14ee0cSDon Skidmore goto out; 6286a14ee0cSDon Skidmore } 6296a14ee0cSDon Skidmore 6306a14ee0cSDon Skidmore for (i = 0; i < words_to_read; i++) { 6316a14ee0cSDon Skidmore u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 6326a14ee0cSDon Skidmore 2 * i; 6336a14ee0cSDon Skidmore u32 value = IXGBE_READ_REG(hw, reg); 6346a14ee0cSDon Skidmore 6356a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 6366a14ee0cSDon Skidmore current_word++; 6376a14ee0cSDon Skidmore i++; 6386a14ee0cSDon Skidmore if (i < words_to_read) { 6396a14ee0cSDon Skidmore value >>= 16; 6406a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 6416a14ee0cSDon Skidmore current_word++; 6426a14ee0cSDon Skidmore } 6436a14ee0cSDon Skidmore } 6446a14ee0cSDon Skidmore words -= words_to_read; 6456a14ee0cSDon Skidmore } 6466a14ee0cSDon Skidmore 6476a14ee0cSDon Skidmore out: 6486a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 6496a14ee0cSDon Skidmore return status; 6506a14ee0cSDon Skidmore } 6516a14ee0cSDon Skidmore 6526a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region 6536a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6546a14ee0cSDon Skidmore * @ptr: pointer offset in eeprom 6556a14ee0cSDon Skidmore * @size: size of section pointed by ptr, if 0 first word will be used as size 6566a14ee0cSDon Skidmore * @csum: address of checksum to update 6576a14ee0cSDon Skidmore * 6586a14ee0cSDon Skidmore * Returns error status for any failure 6596a14ee0cSDon Skidmore **/ 6606a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 6616a14ee0cSDon Skidmore u16 size, u16 *csum, u16 *buffer, 6626a14ee0cSDon Skidmore u32 buffer_size) 6636a14ee0cSDon Skidmore { 6646a14ee0cSDon Skidmore u16 buf[256]; 6656a14ee0cSDon Skidmore s32 status; 6666a14ee0cSDon Skidmore u16 length, bufsz, i, start; 6676a14ee0cSDon Skidmore u16 *local_buffer; 6686a14ee0cSDon Skidmore 6696a14ee0cSDon Skidmore bufsz = sizeof(buf) / sizeof(buf[0]); 6706a14ee0cSDon Skidmore 6716a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 6726a14ee0cSDon Skidmore if (!buffer) { 6736a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 6746a14ee0cSDon Skidmore if (status) { 6756a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 6766a14ee0cSDon Skidmore return status; 6776a14ee0cSDon Skidmore } 6786a14ee0cSDon Skidmore local_buffer = buf; 6796a14ee0cSDon Skidmore } else { 6806a14ee0cSDon Skidmore if (buffer_size < ptr) 6816a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 6826a14ee0cSDon Skidmore local_buffer = &buffer[ptr]; 6836a14ee0cSDon Skidmore } 6846a14ee0cSDon Skidmore 6856a14ee0cSDon Skidmore if (size) { 6866a14ee0cSDon Skidmore start = 0; 6876a14ee0cSDon Skidmore length = size; 6886a14ee0cSDon Skidmore } else { 6896a14ee0cSDon Skidmore start = 1; 6906a14ee0cSDon Skidmore length = local_buffer[0]; 6916a14ee0cSDon Skidmore 6926a14ee0cSDon Skidmore /* Skip pointer section if length is invalid. */ 6936a14ee0cSDon Skidmore if (length == 0xFFFF || length == 0 || 6946a14ee0cSDon Skidmore (ptr + length) >= hw->eeprom.word_size) 6956a14ee0cSDon Skidmore return 0; 6966a14ee0cSDon Skidmore } 6976a14ee0cSDon Skidmore 6986a14ee0cSDon Skidmore if (buffer && ((u32)start + (u32)length > buffer_size)) 6996a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 7006a14ee0cSDon Skidmore 7016a14ee0cSDon Skidmore for (i = start; length; i++, length--) { 7026a14ee0cSDon Skidmore if (i == bufsz && !buffer) { 7036a14ee0cSDon Skidmore ptr += bufsz; 7046a14ee0cSDon Skidmore i = 0; 7056a14ee0cSDon Skidmore if (length < bufsz) 7066a14ee0cSDon Skidmore bufsz = length; 7076a14ee0cSDon Skidmore 7086a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 7096a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 7106a14ee0cSDon Skidmore bufsz, buf); 7116a14ee0cSDon Skidmore if (status) { 7126a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 7136a14ee0cSDon Skidmore return status; 7146a14ee0cSDon Skidmore } 7156a14ee0cSDon Skidmore } 7166a14ee0cSDon Skidmore *csum += local_buffer[i]; 7176a14ee0cSDon Skidmore } 7186a14ee0cSDon Skidmore return 0; 7196a14ee0cSDon Skidmore } 7206a14ee0cSDon Skidmore 7216a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 7226a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7236a14ee0cSDon Skidmore * @buffer: pointer to buffer containing calculated checksum 7246a14ee0cSDon Skidmore * @buffer_size: size of buffer 7256a14ee0cSDon Skidmore * 7266a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 7276a14ee0cSDon Skidmore **/ 7287ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 7297ddbde3fSDon Skidmore u32 buffer_size) 7306a14ee0cSDon Skidmore { 7316a14ee0cSDon Skidmore u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 7326a14ee0cSDon Skidmore u16 *local_buffer; 7336a14ee0cSDon Skidmore s32 status; 7346a14ee0cSDon Skidmore u16 checksum = 0; 7356a14ee0cSDon Skidmore u16 pointer, i, size; 7366a14ee0cSDon Skidmore 7376a14ee0cSDon Skidmore hw->eeprom.ops.init_params(hw); 7386a14ee0cSDon Skidmore 7396a14ee0cSDon Skidmore if (!buffer) { 7406a14ee0cSDon Skidmore /* Read pointer area */ 7416a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 7426a14ee0cSDon Skidmore IXGBE_EEPROM_LAST_WORD + 1, 7436a14ee0cSDon Skidmore eeprom_ptrs); 7446a14ee0cSDon Skidmore if (status) { 7456a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 7466a14ee0cSDon Skidmore return status; 7476a14ee0cSDon Skidmore } 7486a14ee0cSDon Skidmore local_buffer = eeprom_ptrs; 7496a14ee0cSDon Skidmore } else { 7506a14ee0cSDon Skidmore if (buffer_size < IXGBE_EEPROM_LAST_WORD) 7516a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 7526a14ee0cSDon Skidmore local_buffer = buffer; 7536a14ee0cSDon Skidmore } 7546a14ee0cSDon Skidmore 7556a14ee0cSDon Skidmore /* For X550 hardware include 0x0-0x41 in the checksum, skip the 7566a14ee0cSDon Skidmore * checksum word itself 7576a14ee0cSDon Skidmore */ 7586a14ee0cSDon Skidmore for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 7596a14ee0cSDon Skidmore if (i != IXGBE_EEPROM_CHECKSUM) 7606a14ee0cSDon Skidmore checksum += local_buffer[i]; 7616a14ee0cSDon Skidmore 7626a14ee0cSDon Skidmore /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 7636a14ee0cSDon Skidmore * FW, PHY module, and PCIe Expansion/Option ROM pointers. 7646a14ee0cSDon Skidmore */ 7656a14ee0cSDon Skidmore for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 7666a14ee0cSDon Skidmore if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 7676a14ee0cSDon Skidmore continue; 7686a14ee0cSDon Skidmore 7696a14ee0cSDon Skidmore pointer = local_buffer[i]; 7706a14ee0cSDon Skidmore 7716a14ee0cSDon Skidmore /* Skip pointer section if the pointer is invalid. */ 7726a14ee0cSDon Skidmore if (pointer == 0xFFFF || pointer == 0 || 7736a14ee0cSDon Skidmore pointer >= hw->eeprom.word_size) 7746a14ee0cSDon Skidmore continue; 7756a14ee0cSDon Skidmore 7766a14ee0cSDon Skidmore switch (i) { 7776a14ee0cSDon Skidmore case IXGBE_PCIE_GENERAL_PTR: 7786a14ee0cSDon Skidmore size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 7796a14ee0cSDon Skidmore break; 7806a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG0_PTR: 7816a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG1_PTR: 7826a14ee0cSDon Skidmore size = IXGBE_PCIE_CONFIG_SIZE; 7836a14ee0cSDon Skidmore break; 7846a14ee0cSDon Skidmore default: 7856a14ee0cSDon Skidmore size = 0; 7866a14ee0cSDon Skidmore break; 7876a14ee0cSDon Skidmore } 7886a14ee0cSDon Skidmore 7896a14ee0cSDon Skidmore status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 7906a14ee0cSDon Skidmore buffer, buffer_size); 7916a14ee0cSDon Skidmore if (status) 7926a14ee0cSDon Skidmore return status; 7936a14ee0cSDon Skidmore } 7946a14ee0cSDon Skidmore 7956a14ee0cSDon Skidmore checksum = (u16)IXGBE_EEPROM_SUM - checksum; 7966a14ee0cSDon Skidmore 7976a14ee0cSDon Skidmore return (s32)checksum; 7986a14ee0cSDon Skidmore } 7996a14ee0cSDon Skidmore 8006a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 8016a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8026a14ee0cSDon Skidmore * 8036a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 8046a14ee0cSDon Skidmore **/ 8057ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 8066a14ee0cSDon Skidmore { 8076a14ee0cSDon Skidmore return ixgbe_calc_checksum_X550(hw, NULL, 0); 8086a14ee0cSDon Skidmore } 8096a14ee0cSDon Skidmore 8106a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 8116a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8126a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 8136a14ee0cSDon Skidmore * @data: word read from the EEPROM 8146a14ee0cSDon Skidmore * 8156a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 8166a14ee0cSDon Skidmore **/ 8177ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 8186a14ee0cSDon Skidmore { 8196a14ee0cSDon Skidmore s32 status = 0; 8206a14ee0cSDon Skidmore 8216a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 8226a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_data_X550(hw, offset, data); 8236a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 8246a14ee0cSDon Skidmore } else { 8256a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 8266a14ee0cSDon Skidmore } 8276a14ee0cSDon Skidmore 8286a14ee0cSDon Skidmore return status; 8296a14ee0cSDon Skidmore } 8306a14ee0cSDon Skidmore 8316a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 8326a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8336a14ee0cSDon Skidmore * @checksum_val: calculated checksum 8346a14ee0cSDon Skidmore * 8356a14ee0cSDon Skidmore * Performs checksum calculation and validates the EEPROM checksum. If the 8366a14ee0cSDon Skidmore * caller does not need checksum_val, the value can be NULL. 8376a14ee0cSDon Skidmore **/ 8387ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 8397ddbde3fSDon Skidmore u16 *checksum_val) 8406a14ee0cSDon Skidmore { 8416a14ee0cSDon Skidmore s32 status; 8426a14ee0cSDon Skidmore u16 checksum; 8436a14ee0cSDon Skidmore u16 read_checksum = 0; 8446a14ee0cSDon Skidmore 8456a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 8466a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 8476a14ee0cSDon Skidmore * EEPROM read fails 8486a14ee0cSDon Skidmore */ 8496a14ee0cSDon Skidmore status = hw->eeprom.ops.read(hw, 0, &checksum); 8506a14ee0cSDon Skidmore if (status) { 8516a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 8526a14ee0cSDon Skidmore return status; 8536a14ee0cSDon Skidmore } 8546a14ee0cSDon Skidmore 8556a14ee0cSDon Skidmore status = hw->eeprom.ops.calc_checksum(hw); 8566a14ee0cSDon Skidmore if (status < 0) 8576a14ee0cSDon Skidmore return status; 8586a14ee0cSDon Skidmore 8596a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 8606a14ee0cSDon Skidmore 8616a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 8626a14ee0cSDon Skidmore &read_checksum); 8636a14ee0cSDon Skidmore if (status) 8646a14ee0cSDon Skidmore return status; 8656a14ee0cSDon Skidmore 8666a14ee0cSDon Skidmore /* Verify read checksum from EEPROM is the same as 8676a14ee0cSDon Skidmore * calculated checksum 8686a14ee0cSDon Skidmore */ 8696a14ee0cSDon Skidmore if (read_checksum != checksum) { 8706a14ee0cSDon Skidmore status = IXGBE_ERR_EEPROM_CHECKSUM; 8716a14ee0cSDon Skidmore hw_dbg(hw, "Invalid EEPROM checksum"); 8726a14ee0cSDon Skidmore } 8736a14ee0cSDon Skidmore 8746a14ee0cSDon Skidmore /* If the user cares, return the calculated checksum */ 8756a14ee0cSDon Skidmore if (checksum_val) 8766a14ee0cSDon Skidmore *checksum_val = checksum; 8776a14ee0cSDon Skidmore 8786a14ee0cSDon Skidmore return status; 8796a14ee0cSDon Skidmore } 8806a14ee0cSDon Skidmore 8816a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 8826a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8836a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 8846a14ee0cSDon Skidmore * @data: word write to the EEPROM 8856a14ee0cSDon Skidmore * 8866a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 8876a14ee0cSDon Skidmore **/ 8887ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 8897ddbde3fSDon Skidmore u16 data) 8906a14ee0cSDon Skidmore { 8916a14ee0cSDon Skidmore s32 status; 8926a14ee0cSDon Skidmore struct ixgbe_hic_write_shadow_ram buffer; 8936a14ee0cSDon Skidmore 8946a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 8956a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 8966a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 8976a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 8986a14ee0cSDon Skidmore 8996a14ee0cSDon Skidmore /* one word */ 9006a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 9016a14ee0cSDon Skidmore buffer.data = data; 9026a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 9036a14ee0cSDon Skidmore 9045cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 9056a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 9066a14ee0cSDon Skidmore return status; 9076a14ee0cSDon Skidmore } 9086a14ee0cSDon Skidmore 9096a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 9106a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9116a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 9126a14ee0cSDon Skidmore * @data: word write to the EEPROM 9136a14ee0cSDon Skidmore * 9146a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 9156a14ee0cSDon Skidmore **/ 9167ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 9176a14ee0cSDon Skidmore { 9186a14ee0cSDon Skidmore s32 status = 0; 9196a14ee0cSDon Skidmore 9206a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 9216a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 9226a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 9236a14ee0cSDon Skidmore } else { 9246a14ee0cSDon Skidmore hw_dbg(hw, "write ee hostif failed to get semaphore"); 9256a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 9266a14ee0cSDon Skidmore } 9276a14ee0cSDon Skidmore 9286a14ee0cSDon Skidmore return status; 9296a14ee0cSDon Skidmore } 9306a14ee0cSDon Skidmore 9316a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 9326a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9336a14ee0cSDon Skidmore * 9346a14ee0cSDon Skidmore * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 9356a14ee0cSDon Skidmore **/ 9367ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 9376a14ee0cSDon Skidmore { 9386a14ee0cSDon Skidmore s32 status = 0; 9396a14ee0cSDon Skidmore union ixgbe_hic_hdr2 buffer; 9406a14ee0cSDon Skidmore 9416a14ee0cSDon Skidmore buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 9426a14ee0cSDon Skidmore buffer.req.buf_lenh = 0; 9436a14ee0cSDon Skidmore buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 9446a14ee0cSDon Skidmore buffer.req.checksum = FW_DEFAULT_CHECKSUM; 9456a14ee0cSDon Skidmore 9465cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 9476a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 9486a14ee0cSDon Skidmore return status; 9496a14ee0cSDon Skidmore } 9506a14ee0cSDon Skidmore 951454c65ddSDon Skidmore /** 952454c65ddSDon Skidmore * ixgbe_get_bus_info_X550em - Set PCI bus info 953454c65ddSDon Skidmore * @hw: pointer to hardware structure 954454c65ddSDon Skidmore * 955454c65ddSDon Skidmore * Sets bus link width and speed to unknown because X550em is 956454c65ddSDon Skidmore * not a PCI device. 957454c65ddSDon Skidmore **/ 958454c65ddSDon Skidmore static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) 959454c65ddSDon Skidmore { 960f9328bc6SDon Skidmore hw->bus.type = ixgbe_bus_type_internal; 961454c65ddSDon Skidmore hw->bus.width = ixgbe_bus_width_unknown; 962454c65ddSDon Skidmore hw->bus.speed = ixgbe_bus_speed_unknown; 963454c65ddSDon Skidmore 964454c65ddSDon Skidmore hw->mac.ops.set_lan_id(hw); 965454c65ddSDon Skidmore 966454c65ddSDon Skidmore return 0; 967454c65ddSDon Skidmore } 968454c65ddSDon Skidmore 9691f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit 9701f9ac57cSDon Skidmore * 9711f9ac57cSDon Skidmore * Enables the Rx DMA unit for x550 9721f9ac57cSDon Skidmore **/ 9731f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 9741f9ac57cSDon Skidmore { 9751f9ac57cSDon Skidmore u32 rxctrl, pfdtxgswc; 9761f9ac57cSDon Skidmore s32 status; 9771f9ac57cSDon Skidmore struct ixgbe_hic_disable_rxen fw_cmd; 9781f9ac57cSDon Skidmore 9791f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 9801f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 9811f9ac57cSDon Skidmore pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 9821f9ac57cSDon Skidmore if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 9831f9ac57cSDon Skidmore pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 9841f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 9851f9ac57cSDon Skidmore hw->mac.set_lben = true; 9861f9ac57cSDon Skidmore } else { 9871f9ac57cSDon Skidmore hw->mac.set_lben = false; 9881f9ac57cSDon Skidmore } 9891f9ac57cSDon Skidmore 9901f9ac57cSDon Skidmore fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 9911f9ac57cSDon Skidmore fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 9921f9ac57cSDon Skidmore fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 9933775b814SMark Rustad fw_cmd.port_number = hw->bus.lan_id; 9941f9ac57cSDon Skidmore 9955cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &fw_cmd, 9961f9ac57cSDon Skidmore sizeof(struct ixgbe_hic_disable_rxen), 9971f9ac57cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, true); 9981f9ac57cSDon Skidmore 9991f9ac57cSDon Skidmore /* If we fail - disable RX using register write */ 10001f9ac57cSDon Skidmore if (status) { 10011f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 10021f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 10031f9ac57cSDon Skidmore rxctrl &= ~IXGBE_RXCTRL_RXEN; 10041f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 10051f9ac57cSDon Skidmore } 10061f9ac57cSDon Skidmore } 10071f9ac57cSDon Skidmore } 10081f9ac57cSDon Skidmore } 10091f9ac57cSDon Skidmore 10106a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 10116a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10126a14ee0cSDon Skidmore * 10136a14ee0cSDon Skidmore * After writing EEPROM to shadow RAM using EEWR register, software calculates 10146a14ee0cSDon Skidmore * checksum and updates the EEPROM and instructs the hardware to update 10156a14ee0cSDon Skidmore * the flash. 10166a14ee0cSDon Skidmore **/ 10177ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 10186a14ee0cSDon Skidmore { 10196a14ee0cSDon Skidmore s32 status; 10206a14ee0cSDon Skidmore u16 checksum = 0; 10216a14ee0cSDon Skidmore 10226a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 10236a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 10246a14ee0cSDon Skidmore * EEPROM read fails 10256a14ee0cSDon Skidmore */ 10266a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 10276a14ee0cSDon Skidmore if (status) { 10286a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 10296a14ee0cSDon Skidmore return status; 10306a14ee0cSDon Skidmore } 10316a14ee0cSDon Skidmore 10326a14ee0cSDon Skidmore status = ixgbe_calc_eeprom_checksum_X550(hw); 10336a14ee0cSDon Skidmore if (status < 0) 10346a14ee0cSDon Skidmore return status; 10356a14ee0cSDon Skidmore 10366a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 10376a14ee0cSDon Skidmore 10386a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 10396a14ee0cSDon Skidmore checksum); 10406a14ee0cSDon Skidmore if (status) 10416a14ee0cSDon Skidmore return status; 10426a14ee0cSDon Skidmore 10436a14ee0cSDon Skidmore status = ixgbe_update_flash_X550(hw); 10446a14ee0cSDon Skidmore 10456a14ee0cSDon Skidmore return status; 10466a14ee0cSDon Skidmore } 10476a14ee0cSDon Skidmore 10486a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 10496a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10506a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 10516a14ee0cSDon Skidmore * @words: number of words 10526a14ee0cSDon Skidmore * @data: word(s) write to the EEPROM 10536a14ee0cSDon Skidmore * 10546a14ee0cSDon Skidmore * 10556a14ee0cSDon Skidmore * Write a 16 bit word(s) to the EEPROM using the hostif. 10566a14ee0cSDon Skidmore **/ 10577ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 10587ddbde3fSDon Skidmore u16 offset, u16 words, 10597ddbde3fSDon Skidmore u16 *data) 10606a14ee0cSDon Skidmore { 10616a14ee0cSDon Skidmore s32 status = 0; 10626a14ee0cSDon Skidmore u32 i = 0; 10636a14ee0cSDon Skidmore 10646a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 10656a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 10666a14ee0cSDon Skidmore if (status) { 10676a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 10686a14ee0cSDon Skidmore return status; 10696a14ee0cSDon Skidmore } 10706a14ee0cSDon Skidmore 10716a14ee0cSDon Skidmore for (i = 0; i < words; i++) { 10726a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 10736a14ee0cSDon Skidmore data[i]); 10746a14ee0cSDon Skidmore if (status) { 10756a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom buffered write failed\n"); 10766a14ee0cSDon Skidmore break; 10776a14ee0cSDon Skidmore } 10786a14ee0cSDon Skidmore } 10796a14ee0cSDon Skidmore 10806a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 10816a14ee0cSDon Skidmore 10826a14ee0cSDon Skidmore return status; 10836a14ee0cSDon Skidmore } 10846a14ee0cSDon Skidmore 10856a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 10866a14ee0cSDon Skidmore * IOSF device 10876a14ee0cSDon Skidmore * 10886a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10896a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 10906a14ee0cSDon Skidmore * @device_type: 3 bit device type 10916a14ee0cSDon Skidmore * @data: Data to write to the register 10926a14ee0cSDon Skidmore **/ 10937ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 10946a14ee0cSDon Skidmore u32 device_type, u32 data) 10956a14ee0cSDon Skidmore { 1096ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 1097ae14a1d8SMark Rustad u32 command, error; 1098ae14a1d8SMark Rustad s32 ret; 1099ae14a1d8SMark Rustad 1100ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 1101ae14a1d8SMark Rustad if (ret) 1102ae14a1d8SMark Rustad return ret; 1103ae14a1d8SMark Rustad 1104ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 1105ae14a1d8SMark Rustad if (ret) 1106ae14a1d8SMark Rustad goto out; 11076a14ee0cSDon Skidmore 11086a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 11096a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 11106a14ee0cSDon Skidmore 11116a14ee0cSDon Skidmore /* Write IOSF control register */ 11126a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 11136a14ee0cSDon Skidmore 11146a14ee0cSDon Skidmore /* Write IOSF data register */ 11156a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 11166a14ee0cSDon Skidmore 1117ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 11186a14ee0cSDon Skidmore 11196a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 11206a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 11216a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 11226a14ee0cSDon Skidmore hw_dbg(hw, "Failed to write, error %x\n", error); 11236a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 11246a14ee0cSDon Skidmore } 11256a14ee0cSDon Skidmore 1126ae14a1d8SMark Rustad out: 1127ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 1128ae14a1d8SMark Rustad return ret; 11296a14ee0cSDon Skidmore } 11306a14ee0cSDon Skidmore 11310c1b7de4SDon Skidmore /** 11320c1b7de4SDon Skidmore * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration 11336a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11346a14ee0cSDon Skidmore * 11350c1b7de4SDon Skidmore * iXfI configuration needed for ixgbe_mac_X550EM_x devices. 11366a14ee0cSDon Skidmore **/ 11370c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) 11386a14ee0cSDon Skidmore { 11396a14ee0cSDon Skidmore s32 status; 11406a14ee0cSDon Skidmore u32 reg_val; 11416a14ee0cSDon Skidmore 11426a14ee0cSDon Skidmore /* Disable training protocol FSM. */ 11436a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 11446a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 11456a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 11466a14ee0cSDon Skidmore if (status) 11476a14ee0cSDon Skidmore return status; 11486a14ee0cSDon Skidmore 11496a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 11506a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 11516a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 11526a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 11536a14ee0cSDon Skidmore if (status) 11546a14ee0cSDon Skidmore return status; 11556a14ee0cSDon Skidmore 11566a14ee0cSDon Skidmore /* Disable Flex from training TXFFE. */ 11576a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 11586a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 11596a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 11606a14ee0cSDon Skidmore if (status) 11616a14ee0cSDon Skidmore return status; 11626a14ee0cSDon Skidmore 11636a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 11646a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 11656a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 11666a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 11676a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 11686a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 11696a14ee0cSDon Skidmore if (status) 11706a14ee0cSDon Skidmore return status; 11716a14ee0cSDon Skidmore 11726a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 11736a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 11746a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 11756a14ee0cSDon Skidmore if (status) 11766a14ee0cSDon Skidmore return status; 11776a14ee0cSDon Skidmore 11786a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 11796a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 11806a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 11816a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 11826a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 11836a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 11846a14ee0cSDon Skidmore if (status) 11856a14ee0cSDon Skidmore return status; 11866a14ee0cSDon Skidmore 11876a14ee0cSDon Skidmore /* Enable override for coefficients. */ 11886a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 11896a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 11906a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 11916a14ee0cSDon Skidmore if (status) 11926a14ee0cSDon Skidmore return status; 11936a14ee0cSDon Skidmore 11946a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 11956a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 11966a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 11976a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 11986a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 11996a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 12006a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12010c1b7de4SDon Skidmore return status; 12020c1b7de4SDon Skidmore } 12030c1b7de4SDon Skidmore 12040c1b7de4SDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 12050c1b7de4SDon Skidmore * @hw: pointer to hardware structure 12060c1b7de4SDon Skidmore * @speed: the link speed to force 12070c1b7de4SDon Skidmore * 12080c1b7de4SDon Skidmore * Configures the integrated KR PHY to use iXFI mode. Used to connect an 12090c1b7de4SDon Skidmore * internal and external PHY at a specific speed, without autonegotiation. 12100c1b7de4SDon Skidmore **/ 12110c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 12120c1b7de4SDon Skidmore { 12130c1b7de4SDon Skidmore s32 status; 12140c1b7de4SDon Skidmore u32 reg_val; 12150c1b7de4SDon Skidmore 12160c1b7de4SDon Skidmore /* Disable AN and force speed to 10G Serial. */ 12170c1b7de4SDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12180c1b7de4SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 12190c1b7de4SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12206a14ee0cSDon Skidmore if (status) 12216a14ee0cSDon Skidmore return status; 12226a14ee0cSDon Skidmore 12230c1b7de4SDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 12240c1b7de4SDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 12250c1b7de4SDon Skidmore 12260c1b7de4SDon Skidmore /* Select forced link speed for internal PHY. */ 12270c1b7de4SDon Skidmore switch (*speed) { 12280c1b7de4SDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 12290c1b7de4SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 12300c1b7de4SDon Skidmore break; 12310c1b7de4SDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 12320c1b7de4SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 12330c1b7de4SDon Skidmore break; 12340c1b7de4SDon Skidmore default: 12350c1b7de4SDon Skidmore /* Other link speeds are not supported by internal KR PHY. */ 12360c1b7de4SDon Skidmore return IXGBE_ERR_LINK_SETUP; 12370c1b7de4SDon Skidmore } 12380c1b7de4SDon Skidmore 12390c1b7de4SDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12400c1b7de4SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 12410c1b7de4SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12420c1b7de4SDon Skidmore if (status) 12430c1b7de4SDon Skidmore return status; 12440c1b7de4SDon Skidmore 12450c1b7de4SDon Skidmore /* Additional configuration needed for x550em_x */ 12460c1b7de4SDon Skidmore if (hw->mac.type == ixgbe_mac_X550EM_x) { 12470c1b7de4SDon Skidmore status = ixgbe_setup_ixfi_x550em_x(hw); 12480c1b7de4SDon Skidmore if (status) 12490c1b7de4SDon Skidmore return status; 12500c1b7de4SDon Skidmore } 12510c1b7de4SDon Skidmore 12526a14ee0cSDon Skidmore /* Toggle port SW reset by AN reset. */ 12536a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12546a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 12556a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12566a14ee0cSDon Skidmore if (status) 12576a14ee0cSDon Skidmore return status; 12586a14ee0cSDon Skidmore 12596a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 12606a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12616a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 12626a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12636a14ee0cSDon Skidmore 12646a14ee0cSDon Skidmore return status; 12656a14ee0cSDon Skidmore } 12666a14ee0cSDon Skidmore 1267c3dc4c09SDon Skidmore /** 1268e23f3336SMark Rustad * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported 1269e23f3336SMark Rustad * @hw: pointer to hardware structure 1270e23f3336SMark Rustad * @linear: true if SFP module is linear 1271e23f3336SMark Rustad */ 1272e23f3336SMark Rustad static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) 1273e23f3336SMark Rustad { 1274e23f3336SMark Rustad switch (hw->phy.sfp_type) { 1275e23f3336SMark Rustad case ixgbe_sfp_type_not_present: 1276e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_PRESENT; 1277e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core0: 1278e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core1: 1279e23f3336SMark Rustad *linear = true; 1280e23f3336SMark Rustad break; 1281e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core0: 1282e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core1: 1283e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core0: 1284e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core1: 1285e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core0: 1286e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core1: 1287e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core0: 1288e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core1: 1289e23f3336SMark Rustad *linear = false; 1290e23f3336SMark Rustad break; 1291e23f3336SMark Rustad case ixgbe_sfp_type_unknown: 1292e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core0: 1293e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core1: 1294e23f3336SMark Rustad default: 1295e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_SUPPORTED; 1296e23f3336SMark Rustad } 1297e23f3336SMark Rustad 1298e23f3336SMark Rustad return 0; 1299e23f3336SMark Rustad } 1300e23f3336SMark Rustad 1301e23f3336SMark Rustad /** 13026d373a1bSMark Rustad * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. 13036d373a1bSMark Rustad * @hw: pointer to hardware structure 13046d373a1bSMark Rustad * 13056d373a1bSMark Rustad * Configures the extern PHY and the integrated KR PHY for SFP support. 13066d373a1bSMark Rustad */ 13076d373a1bSMark Rustad static s32 13086d373a1bSMark Rustad ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, 13096d373a1bSMark Rustad ixgbe_link_speed speed, 13106d373a1bSMark Rustad __always_unused bool autoneg_wait_to_complete) 13116d373a1bSMark Rustad { 1312e23f3336SMark Rustad s32 status; 1313e23f3336SMark Rustad u16 slice, value; 1314e23f3336SMark Rustad bool setup_linear = false; 1315e23f3336SMark Rustad 1316e23f3336SMark Rustad /* Check if SFP module is supported and linear */ 1317e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 1318e23f3336SMark Rustad 1319e23f3336SMark Rustad /* If no SFP module present, then return success. Return success since 1320e23f3336SMark Rustad * there is no reason to configure CS4227 and SFP not present error is 1321e23f3336SMark Rustad * not accepted in the setup MAC link flow. 1322e23f3336SMark Rustad */ 1323e23f3336SMark Rustad if (status == IXGBE_ERR_SFP_NOT_PRESENT) 1324e23f3336SMark Rustad return 0; 1325e23f3336SMark Rustad 1326e23f3336SMark Rustad if (status) 1327e23f3336SMark Rustad return status; 1328e23f3336SMark Rustad 1329d91e3a7dSMark Rustad if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1330e23f3336SMark Rustad /* Configure CS4227 LINE side to 10G SR. */ 1331e23f3336SMark Rustad slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12); 1332e23f3336SMark Rustad value = IXGBE_CS4227_SPEED_10G; 1333d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1334d91e3a7dSMark Rustad slice, value); 1335d91e3a7dSMark Rustad if (status) 1336d91e3a7dSMark Rustad goto i2c_err; 1337d91e3a7dSMark Rustad 1338d91e3a7dSMark Rustad slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 1339d91e3a7dSMark Rustad value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 1340d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1341d91e3a7dSMark Rustad slice, value); 1342d91e3a7dSMark Rustad if (status) 1343d91e3a7dSMark Rustad goto i2c_err; 1344e23f3336SMark Rustad 1345e23f3336SMark Rustad /* Configure CS4227 for HOST connection rate then type. */ 1346e23f3336SMark Rustad slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12); 1347e23f3336SMark Rustad value = speed & IXGBE_LINK_SPEED_10GB_FULL ? 1348e23f3336SMark Rustad IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; 1349d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1350d91e3a7dSMark Rustad slice, value); 1351d91e3a7dSMark Rustad if (status) 1352d91e3a7dSMark Rustad goto i2c_err; 1353e23f3336SMark Rustad 1354e23f3336SMark Rustad slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12); 1355e23f3336SMark Rustad if (setup_linear) 1356e23f3336SMark Rustad value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 1357e23f3336SMark Rustad else 1358e23f3336SMark Rustad value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 1359d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1360d91e3a7dSMark Rustad slice, value); 1361d91e3a7dSMark Rustad if (status) 1362d91e3a7dSMark Rustad goto i2c_err; 1363e23f3336SMark Rustad 1364d91e3a7dSMark Rustad /* Setup XFI internal link. */ 1365e23f3336SMark Rustad status = ixgbe_setup_ixfi_x550em(hw, &speed); 1366d91e3a7dSMark Rustad if (status) { 1367d91e3a7dSMark Rustad hw_dbg(hw, "setup_ixfi failed with %d\n", status); 1368d91e3a7dSMark Rustad return status; 1369d91e3a7dSMark Rustad } 1370d91e3a7dSMark Rustad } else { 1371d91e3a7dSMark Rustad /* Configure internal PHY for KR/KX. */ 1372d91e3a7dSMark Rustad status = ixgbe_setup_kr_speed_x550em(hw, speed); 1373d91e3a7dSMark Rustad if (status) { 1374d91e3a7dSMark Rustad hw_dbg(hw, "setup_kr_speed failed with %d\n", status); 1375d91e3a7dSMark Rustad return status; 1376d91e3a7dSMark Rustad } 1377e23f3336SMark Rustad 1378d91e3a7dSMark Rustad /* Configure CS4227 LINE side to proper mode. */ 1379d91e3a7dSMark Rustad slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 1380d91e3a7dSMark Rustad if (setup_linear) 1381d91e3a7dSMark Rustad value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 1382d91e3a7dSMark Rustad else 1383d91e3a7dSMark Rustad value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 1384d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1385d91e3a7dSMark Rustad slice, value); 1386d91e3a7dSMark Rustad if (status) 1387d91e3a7dSMark Rustad goto i2c_err; 1388d91e3a7dSMark Rustad } 1389d91e3a7dSMark Rustad 1390d91e3a7dSMark Rustad return 0; 1391d91e3a7dSMark Rustad 1392d91e3a7dSMark Rustad i2c_err: 1393d91e3a7dSMark Rustad hw_dbg(hw, "combined i2c access failed with %d\n", status); 1394e23f3336SMark Rustad return status; 13956d373a1bSMark Rustad } 13966d373a1bSMark Rustad 13976d373a1bSMark Rustad /** 13982d40cd17SMark Rustad * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP 13992d40cd17SMark Rustad * @hw: pointer to hardware structure 14002d40cd17SMark Rustad * 14012d40cd17SMark Rustad * Configure the the integrated PHY for native SFP support. 14022d40cd17SMark Rustad */ 14032d40cd17SMark Rustad static s32 14042d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, 14052d40cd17SMark Rustad __always_unused bool autoneg_wait_to_complete) 14062d40cd17SMark Rustad { 14072d40cd17SMark Rustad bool setup_linear = false; 14082d40cd17SMark Rustad u32 reg_phy_int; 14092d40cd17SMark Rustad s32 rc; 14102d40cd17SMark Rustad 14112d40cd17SMark Rustad /* Check if SFP module is supported and linear */ 14122d40cd17SMark Rustad rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 14132d40cd17SMark Rustad 14142d40cd17SMark Rustad /* If no SFP module present, then return success. Return success since 14152d40cd17SMark Rustad * SFP not present error is not excepted in the setup MAC link flow. 14162d40cd17SMark Rustad */ 14172d40cd17SMark Rustad if (rc == IXGBE_ERR_SFP_NOT_PRESENT) 14182d40cd17SMark Rustad return 0; 14192d40cd17SMark Rustad 14202d40cd17SMark Rustad if (!rc) 14212d40cd17SMark Rustad return rc; 14222d40cd17SMark Rustad 14232d40cd17SMark Rustad /* Configure internal PHY for native SFI */ 14242d40cd17SMark Rustad rc = hw->mac.ops.read_iosf_sb_reg(hw, 14252d40cd17SMark Rustad IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), 14262d40cd17SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 14272d40cd17SMark Rustad ®_phy_int); 14282d40cd17SMark Rustad if (rc) 14292d40cd17SMark Rustad return rc; 14302d40cd17SMark Rustad 14312d40cd17SMark Rustad if (setup_linear) { 14322d40cd17SMark Rustad reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING; 14332d40cd17SMark Rustad reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR; 14342d40cd17SMark Rustad } else { 14352d40cd17SMark Rustad reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING; 14362d40cd17SMark Rustad reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR; 14372d40cd17SMark Rustad } 14382d40cd17SMark Rustad 14392d40cd17SMark Rustad rc = hw->mac.ops.write_iosf_sb_reg(hw, 14402d40cd17SMark Rustad IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), 14412d40cd17SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 14422d40cd17SMark Rustad reg_phy_int); 14432d40cd17SMark Rustad if (rc) 14442d40cd17SMark Rustad return rc; 14452d40cd17SMark Rustad 14462d40cd17SMark Rustad /* Setup XFI/SFI internal link */ 14472d40cd17SMark Rustad return ixgbe_setup_ixfi_x550em(hw, &speed); 14482d40cd17SMark Rustad } 14492d40cd17SMark Rustad 14502d40cd17SMark Rustad /** 14512d40cd17SMark Rustad * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP 14522d40cd17SMark Rustad * @hw: pointer to hardware structure 14532d40cd17SMark Rustad * 14542d40cd17SMark Rustad * Configure the the integrated PHY for SFP support. 14552d40cd17SMark Rustad */ 14562d40cd17SMark Rustad static s32 14572d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, 14582d40cd17SMark Rustad __always_unused bool autoneg_wait_to_complete) 14592d40cd17SMark Rustad { 14602d40cd17SMark Rustad u32 reg_slice, slice_offset; 14612d40cd17SMark Rustad bool setup_linear = false; 14622d40cd17SMark Rustad u16 reg_phy_ext; 14632d40cd17SMark Rustad s32 rc; 14642d40cd17SMark Rustad 14652d40cd17SMark Rustad /* Check if SFP module is supported and linear */ 14662d40cd17SMark Rustad rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 14672d40cd17SMark Rustad 14682d40cd17SMark Rustad /* If no SFP module present, then return success. Return success since 14692d40cd17SMark Rustad * SFP not present error is not excepted in the setup MAC link flow. 14702d40cd17SMark Rustad */ 14712d40cd17SMark Rustad if (rc == IXGBE_ERR_SFP_NOT_PRESENT) 14722d40cd17SMark Rustad return 0; 14732d40cd17SMark Rustad 14742d40cd17SMark Rustad if (!rc) 14752d40cd17SMark Rustad return rc; 14762d40cd17SMark Rustad 14772d40cd17SMark Rustad /* Configure internal PHY for KR/KX. */ 14782d40cd17SMark Rustad ixgbe_setup_kr_speed_x550em(hw, speed); 14792d40cd17SMark Rustad 14807564a888SMark Rustad if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE) 14812d40cd17SMark Rustad return IXGBE_ERR_PHY_ADDR_INVALID; 14822d40cd17SMark Rustad 14832d40cd17SMark Rustad /* Get external PHY device id */ 14842d40cd17SMark Rustad rc = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, 14852d40cd17SMark Rustad IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 14862d40cd17SMark Rustad if (rc) 14872d40cd17SMark Rustad return rc; 14882d40cd17SMark Rustad 14892d40cd17SMark Rustad /* When configuring quad port CS4223, the MAC instance is part 14902d40cd17SMark Rustad * of the slice offset. 14912d40cd17SMark Rustad */ 14922d40cd17SMark Rustad if (reg_phy_ext == IXGBE_CS4223_PHY_ID) 14932d40cd17SMark Rustad slice_offset = (hw->bus.lan_id + 14942d40cd17SMark Rustad (hw->bus.instance_id << 1)) << 12; 14952d40cd17SMark Rustad else 14962d40cd17SMark Rustad slice_offset = hw->bus.lan_id << 12; 14972d40cd17SMark Rustad 14982d40cd17SMark Rustad /* Configure CS4227/CS4223 LINE side to proper mode. */ 14992d40cd17SMark Rustad reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; 15002d40cd17SMark Rustad if (setup_linear) 15012d40cd17SMark Rustad reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 15022d40cd17SMark Rustad else 15032d40cd17SMark Rustad reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 15042d40cd17SMark Rustad return hw->phy.ops.write_reg(hw, reg_slice, IXGBE_MDIO_ZERO_DEV_TYPE, 15052d40cd17SMark Rustad reg_phy_ext); 15062d40cd17SMark Rustad } 15072d40cd17SMark Rustad 15082d40cd17SMark Rustad /** 1509c3dc4c09SDon Skidmore * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 1510c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1511c3dc4c09SDon Skidmore * @speed: new link speed 1512c3dc4c09SDon Skidmore * @autoneg_wait_to_complete: true when waiting for completion is needed 1513c3dc4c09SDon Skidmore * 1514c3dc4c09SDon Skidmore * Setup internal/external PHY link speed based on link speed, then set 1515c3dc4c09SDon Skidmore * external PHY auto advertised link speed. 1516c3dc4c09SDon Skidmore * 1517c3dc4c09SDon Skidmore * Returns error status for any failure 1518c3dc4c09SDon Skidmore **/ 1519c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 1520c3dc4c09SDon Skidmore ixgbe_link_speed speed, 1521c3dc4c09SDon Skidmore bool autoneg_wait) 1522c3dc4c09SDon Skidmore { 1523c3dc4c09SDon Skidmore s32 status; 1524c3dc4c09SDon Skidmore ixgbe_link_speed force_speed; 1525c3dc4c09SDon Skidmore 1526c3dc4c09SDon Skidmore /* Setup internal/external PHY link speed to iXFI (10G), unless 1527c3dc4c09SDon Skidmore * only 1G is auto advertised then setup KX link. 1528c3dc4c09SDon Skidmore */ 1529c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1530c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 1531c3dc4c09SDon Skidmore else 1532c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 1533c3dc4c09SDon Skidmore 1534c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup XFI internal link. */ 1535c3dc4c09SDon Skidmore if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1536c3dc4c09SDon Skidmore status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 1537c3dc4c09SDon Skidmore 1538c3dc4c09SDon Skidmore if (status) 1539c3dc4c09SDon Skidmore return status; 1540c3dc4c09SDon Skidmore } 1541c3dc4c09SDon Skidmore 1542c3dc4c09SDon Skidmore return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 1543c3dc4c09SDon Skidmore } 1544c3dc4c09SDon Skidmore 1545a4e293a5SDon Skidmore /** ixgbe_check_link_t_X550em - Determine link and speed status 1546a4e293a5SDon Skidmore * @hw: pointer to hardware structure 1547a4e293a5SDon Skidmore * @speed: pointer to link speed 1548a4e293a5SDon Skidmore * @link_up: true when link is up 1549a4e293a5SDon Skidmore * @link_up_wait_to_complete: bool used to wait for link up or not 1550a4e293a5SDon Skidmore * 1551a4e293a5SDon Skidmore * Check that both the MAC and X557 external PHY have link. 1552a4e293a5SDon Skidmore **/ 1553a4e293a5SDon Skidmore static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, 1554a4e293a5SDon Skidmore ixgbe_link_speed *speed, 1555a4e293a5SDon Skidmore bool *link_up, 1556a4e293a5SDon Skidmore bool link_up_wait_to_complete) 1557a4e293a5SDon Skidmore { 1558a4e293a5SDon Skidmore u32 status; 1559a4e293a5SDon Skidmore u16 autoneg_status; 1560a4e293a5SDon Skidmore 1561a4e293a5SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 1562a4e293a5SDon Skidmore return IXGBE_ERR_CONFIG; 1563a4e293a5SDon Skidmore 1564a4e293a5SDon Skidmore status = ixgbe_check_mac_link_generic(hw, speed, link_up, 1565a4e293a5SDon Skidmore link_up_wait_to_complete); 1566a4e293a5SDon Skidmore 1567a4e293a5SDon Skidmore /* If check link fails or MAC link is not up, then return */ 1568a4e293a5SDon Skidmore if (status || !(*link_up)) 1569a4e293a5SDon Skidmore return status; 1570a4e293a5SDon Skidmore 1571a4e293a5SDon Skidmore /* MAC link is up, so check external PHY link. 1572a4e293a5SDon Skidmore * Read this twice back to back to indicate current status. 1573a4e293a5SDon Skidmore */ 15744dc4000bSEmil Tantilov status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 1575a4e293a5SDon Skidmore &autoneg_status); 1576a4e293a5SDon Skidmore if (status) 1577a4e293a5SDon Skidmore return status; 1578a4e293a5SDon Skidmore 1579a4e293a5SDon Skidmore /* If external PHY link is not up, then indicate link not up */ 1580a4e293a5SDon Skidmore if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 1581a4e293a5SDon Skidmore *link_up = false; 1582a4e293a5SDon Skidmore 1583a4e293a5SDon Skidmore return 0; 1584a4e293a5SDon Skidmore } 1585a4e293a5SDon Skidmore 1586200157c2SMark Rustad /** 1587200157c2SMark Rustad * ixgbe_setup_sgmii - Set up link for sgmii 1588200157c2SMark Rustad * @hw: pointer to hardware structure 1589200157c2SMark Rustad */ 1590200157c2SMark Rustad static s32 1591200157c2SMark Rustad ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, 1592200157c2SMark Rustad __always_unused bool autoneg_wait_to_complete) 1593200157c2SMark Rustad { 1594200157c2SMark Rustad struct ixgbe_mac_info *mac = &hw->mac; 1595200157c2SMark Rustad u32 lval, sval; 1596200157c2SMark Rustad s32 rc; 1597200157c2SMark Rustad 1598200157c2SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 1599200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1600200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 1601200157c2SMark Rustad if (rc) 1602200157c2SMark Rustad return rc; 1603200157c2SMark Rustad 1604200157c2SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1605200157c2SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 1606200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 1607200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 1608200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 1609200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1610200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1611200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1612200157c2SMark Rustad if (rc) 1613200157c2SMark Rustad return rc; 1614200157c2SMark Rustad 1615200157c2SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 1616200157c2SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1617200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 1618200157c2SMark Rustad if (rc) 1619200157c2SMark Rustad return rc; 1620200157c2SMark Rustad 1621200157c2SMark Rustad sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 1622200157c2SMark Rustad sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 1623200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1624200157c2SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1625200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 1626200157c2SMark Rustad if (rc) 1627200157c2SMark Rustad return rc; 1628200157c2SMark Rustad 1629200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 1630200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1631200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1632200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1633200157c2SMark Rustad 1634200157c2SMark Rustad return rc; 1635200157c2SMark Rustad } 1636200157c2SMark Rustad 1637c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 1638c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1639c3dc4c09SDon Skidmore **/ 1640c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 1641c3dc4c09SDon Skidmore { 1642c3dc4c09SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 1643c3dc4c09SDon Skidmore 1644abf76d76SEmil Tantilov mac->ops.setup_fc = ixgbe_setup_fc_x550em; 1645abf76d76SEmil Tantilov 1646c3dc4c09SDon Skidmore switch (mac->ops.get_media_type(hw)) { 1647c3dc4c09SDon Skidmore case ixgbe_media_type_fiber: 1648c3dc4c09SDon Skidmore /* CS4227 does not support autoneg, so disable the laser control 1649c3dc4c09SDon Skidmore * functions for SFP+ fiber 1650c3dc4c09SDon Skidmore */ 1651c3dc4c09SDon Skidmore mac->ops.disable_tx_laser = NULL; 1652c3dc4c09SDon Skidmore mac->ops.enable_tx_laser = NULL; 1653c3dc4c09SDon Skidmore mac->ops.flap_tx_laser = NULL; 16546d373a1bSMark Rustad mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; 16552d40cd17SMark Rustad switch (hw->device_id) { 16562d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 16572d40cd17SMark Rustad mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; 16582d40cd17SMark Rustad break; 16592d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 16602d40cd17SMark Rustad mac->ops.setup_mac_link = 16612d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a; 16622d40cd17SMark Rustad break; 16632d40cd17SMark Rustad default: 16642d40cd17SMark Rustad mac->ops.setup_mac_link = 16652d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550em; 16662d40cd17SMark Rustad break; 16672d40cd17SMark Rustad } 16686d373a1bSMark Rustad mac->ops.set_rate_select_speed = 16696d373a1bSMark Rustad ixgbe_set_soft_rate_select_speed; 1670c3dc4c09SDon Skidmore break; 1671c3dc4c09SDon Skidmore case ixgbe_media_type_copper: 1672c3dc4c09SDon Skidmore mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 1673afdc71e4SMark Rustad mac->ops.setup_fc = ixgbe_setup_fc_generic; 1674a4e293a5SDon Skidmore mac->ops.check_link = ixgbe_check_link_t_X550em; 167549425dfcSMark Rustad return; 167649425dfcSMark Rustad case ixgbe_media_type_backplane: 1677200157c2SMark Rustad if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || 1678200157c2SMark Rustad hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) 1679200157c2SMark Rustad mac->ops.setup_link = ixgbe_setup_sgmii; 1680c3dc4c09SDon Skidmore break; 1681c3dc4c09SDon Skidmore default: 1682c3dc4c09SDon Skidmore break; 1683c3dc4c09SDon Skidmore } 1684c3dc4c09SDon Skidmore } 1685c3dc4c09SDon Skidmore 1686c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module 1687c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1688c3dc4c09SDon Skidmore */ 1689c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 1690c3dc4c09SDon Skidmore { 1691e23f3336SMark Rustad s32 status; 1692e23f3336SMark Rustad bool linear; 1693c3dc4c09SDon Skidmore 1694e23f3336SMark Rustad /* Check if SFP module is supported */ 1695e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &linear); 1696e23f3336SMark Rustad if (status) 1697e23f3336SMark Rustad return status; 1698c3dc4c09SDon Skidmore 1699c3dc4c09SDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 1700c3dc4c09SDon Skidmore hw->phy.ops.reset = NULL; 1701c3dc4c09SDon Skidmore 1702e23f3336SMark Rustad return 0; 1703c3dc4c09SDon Skidmore } 1704c3dc4c09SDon Skidmore 1705c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities 1706c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1707c3dc4c09SDon Skidmore * @speed: pointer to link speed 1708c3dc4c09SDon Skidmore * @autoneg: true when autoneg or autotry is enabled 1709c3dc4c09SDon Skidmore **/ 1710c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 1711c3dc4c09SDon Skidmore ixgbe_link_speed *speed, 1712c3dc4c09SDon Skidmore bool *autoneg) 1713c3dc4c09SDon Skidmore { 1714c3dc4c09SDon Skidmore /* SFP */ 1715c3dc4c09SDon Skidmore if (hw->phy.media_type == ixgbe_media_type_fiber) { 1716c3dc4c09SDon Skidmore /* CS4227 SFP must not enable auto-negotiation */ 1717c3dc4c09SDon Skidmore *autoneg = false; 1718c3dc4c09SDon Skidmore 1719c3dc4c09SDon Skidmore if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 1720c3dc4c09SDon Skidmore hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { 1721c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 1722c3dc4c09SDon Skidmore return 0; 1723c3dc4c09SDon Skidmore } 1724c3dc4c09SDon Skidmore 1725c3dc4c09SDon Skidmore /* Link capabilities are based on SFP */ 1726c3dc4c09SDon Skidmore if (hw->phy.multispeed_fiber) 1727c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1728c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1729c3dc4c09SDon Skidmore else 1730c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL; 1731c3dc4c09SDon Skidmore } else { 1732c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1733c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1734c3dc4c09SDon Skidmore *autoneg = true; 1735c3dc4c09SDon Skidmore } 1736c3dc4c09SDon Skidmore return 0; 1737c3dc4c09SDon Skidmore } 1738c3dc4c09SDon Skidmore 1739c3dc4c09SDon Skidmore /** 1740c3dc4c09SDon Skidmore * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause 1741c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1742c3dc4c09SDon Skidmore * @lsc: pointer to boolean flag which indicates whether external Base T 1743c3dc4c09SDon Skidmore * PHY interrupt is lsc 1744c3dc4c09SDon Skidmore * 1745c3dc4c09SDon Skidmore * Determime if external Base T PHY interrupt cause is high temperature 1746c3dc4c09SDon Skidmore * failure alarm or link status change. 1747c3dc4c09SDon Skidmore * 1748c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1749c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1750c3dc4c09SDon Skidmore **/ 1751c3dc4c09SDon Skidmore static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) 1752c3dc4c09SDon Skidmore { 1753c3dc4c09SDon Skidmore u32 status; 1754c3dc4c09SDon Skidmore u16 reg; 1755c3dc4c09SDon Skidmore 1756c3dc4c09SDon Skidmore *lsc = false; 1757c3dc4c09SDon Skidmore 1758c3dc4c09SDon Skidmore /* Vendor alarm triggered */ 1759c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 17604dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1761c3dc4c09SDon Skidmore ®); 1762c3dc4c09SDon Skidmore 1763c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 1764c3dc4c09SDon Skidmore return status; 1765c3dc4c09SDon Skidmore 1766c3dc4c09SDon Skidmore /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 1767c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 17684dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1769c3dc4c09SDon Skidmore ®); 1770c3dc4c09SDon Skidmore 1771c3dc4c09SDon Skidmore if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1772c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 1773c3dc4c09SDon Skidmore return status; 1774c3dc4c09SDon Skidmore 177583a9fb20SMark Rustad /* Global alarm triggered */ 1776c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 17774dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1778c3dc4c09SDon Skidmore ®); 1779c3dc4c09SDon Skidmore 1780c3dc4c09SDon Skidmore if (status) 1781c3dc4c09SDon Skidmore return status; 1782c3dc4c09SDon Skidmore 1783c3dc4c09SDon Skidmore /* If high temperature failure, then return over temp error and exit */ 1784c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 1785c3dc4c09SDon Skidmore /* power down the PHY in case the PHY FW didn't already */ 1786c3dc4c09SDon Skidmore ixgbe_set_copper_phy_power(hw, false); 1787c3dc4c09SDon Skidmore return IXGBE_ERR_OVERTEMP; 1788c3dc4c09SDon Skidmore } 178983a9fb20SMark Rustad if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { 179083a9fb20SMark Rustad /* device fault alarm triggered */ 179183a9fb20SMark Rustad status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, 17924dc4000bSEmil Tantilov MDIO_MMD_VEND1, 179383a9fb20SMark Rustad ®); 179483a9fb20SMark Rustad if (status) 179583a9fb20SMark Rustad return status; 179683a9fb20SMark Rustad 179783a9fb20SMark Rustad /* if device fault was due to high temp alarm handle and exit */ 179883a9fb20SMark Rustad if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { 179983a9fb20SMark Rustad /* power down the PHY in case the PHY FW didn't */ 180083a9fb20SMark Rustad ixgbe_set_copper_phy_power(hw, false); 180183a9fb20SMark Rustad return IXGBE_ERR_OVERTEMP; 180283a9fb20SMark Rustad } 180383a9fb20SMark Rustad } 1804c3dc4c09SDon Skidmore 1805c3dc4c09SDon Skidmore /* Vendor alarm 2 triggered */ 1806c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 18074dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 1808c3dc4c09SDon Skidmore 1809c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 1810c3dc4c09SDon Skidmore return status; 1811c3dc4c09SDon Skidmore 1812c3dc4c09SDon Skidmore /* link connect/disconnect event occurred */ 1813c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 18144dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 1815c3dc4c09SDon Skidmore 1816c3dc4c09SDon Skidmore if (status) 1817c3dc4c09SDon Skidmore return status; 1818c3dc4c09SDon Skidmore 1819c3dc4c09SDon Skidmore /* Indicate LSC */ 1820c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 1821c3dc4c09SDon Skidmore *lsc = true; 1822c3dc4c09SDon Skidmore 1823c3dc4c09SDon Skidmore return 0; 1824c3dc4c09SDon Skidmore } 1825c3dc4c09SDon Skidmore 1826c3dc4c09SDon Skidmore /** 1827c3dc4c09SDon Skidmore * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 1828c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1829c3dc4c09SDon Skidmore * 1830c3dc4c09SDon Skidmore * Enable link status change and temperature failure alarm for the external 1831c3dc4c09SDon Skidmore * Base T PHY 1832c3dc4c09SDon Skidmore * 1833c3dc4c09SDon Skidmore * Returns PHY access status 1834c3dc4c09SDon Skidmore **/ 1835c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1836c3dc4c09SDon Skidmore { 1837c3dc4c09SDon Skidmore u32 status; 1838c3dc4c09SDon Skidmore u16 reg; 1839c3dc4c09SDon Skidmore bool lsc; 1840c3dc4c09SDon Skidmore 1841c3dc4c09SDon Skidmore /* Clear interrupt flags */ 1842c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1843c3dc4c09SDon Skidmore 1844c3dc4c09SDon Skidmore /* Enable link status change alarm */ 1845c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 18464dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 1847c3dc4c09SDon Skidmore if (status) 1848c3dc4c09SDon Skidmore return status; 1849c3dc4c09SDon Skidmore 1850c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 1851c3dc4c09SDon Skidmore 1852c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 18534dc4000bSEmil Tantilov MDIO_MMD_AN, reg); 1854c3dc4c09SDon Skidmore if (status) 1855c3dc4c09SDon Skidmore return status; 1856c3dc4c09SDon Skidmore 185783a9fb20SMark Rustad /* Enable high temperature failure and global fault alarms */ 1858c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 18594dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1860c3dc4c09SDon Skidmore ®); 1861c3dc4c09SDon Skidmore if (status) 1862c3dc4c09SDon Skidmore return status; 1863c3dc4c09SDon Skidmore 186483a9fb20SMark Rustad reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | 186583a9fb20SMark Rustad IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); 1866c3dc4c09SDon Skidmore 1867c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 18684dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1869c3dc4c09SDon Skidmore reg); 1870c3dc4c09SDon Skidmore if (status) 1871c3dc4c09SDon Skidmore return status; 1872c3dc4c09SDon Skidmore 1873c3dc4c09SDon Skidmore /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 1874c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 18754dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1876c3dc4c09SDon Skidmore ®); 1877c3dc4c09SDon Skidmore if (status) 1878c3dc4c09SDon Skidmore return status; 1879c3dc4c09SDon Skidmore 1880c3dc4c09SDon Skidmore reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1881c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT); 1882c3dc4c09SDon Skidmore 1883c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 18844dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1885c3dc4c09SDon Skidmore reg); 1886c3dc4c09SDon Skidmore if (status) 1887c3dc4c09SDon Skidmore return status; 1888c3dc4c09SDon Skidmore 1889c3dc4c09SDon Skidmore /* Enable chip-wide vendor alarm */ 1890c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 18914dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1892c3dc4c09SDon Skidmore ®); 1893c3dc4c09SDon Skidmore if (status) 1894c3dc4c09SDon Skidmore return status; 1895c3dc4c09SDon Skidmore 1896c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 1897c3dc4c09SDon Skidmore 1898c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 18994dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1900c3dc4c09SDon Skidmore reg); 1901c3dc4c09SDon Skidmore 1902c3dc4c09SDon Skidmore return status; 1903c3dc4c09SDon Skidmore } 1904c3dc4c09SDon Skidmore 1905c3dc4c09SDon Skidmore /** 1906c3dc4c09SDon Skidmore * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 1907c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1908c3dc4c09SDon Skidmore * 1909c3dc4c09SDon Skidmore * Handle external Base T PHY interrupt. If high temperature 1910c3dc4c09SDon Skidmore * failure alarm then return error, else if link status change 1911c3dc4c09SDon Skidmore * then setup internal/external PHY link 1912c3dc4c09SDon Skidmore * 1913c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1914c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1915c3dc4c09SDon Skidmore **/ 1916c3dc4c09SDon Skidmore static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1917c3dc4c09SDon Skidmore { 1918c3dc4c09SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 1919c3dc4c09SDon Skidmore bool lsc; 1920c3dc4c09SDon Skidmore u32 status; 1921c3dc4c09SDon Skidmore 1922c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1923c3dc4c09SDon Skidmore if (status) 1924c3dc4c09SDon Skidmore return status; 1925c3dc4c09SDon Skidmore 1926a85ce532SMark Rustad if (lsc && phy->ops.setup_internal_link) 1927c3dc4c09SDon Skidmore return phy->ops.setup_internal_link(hw); 1928c3dc4c09SDon Skidmore 1929c3dc4c09SDon Skidmore return 0; 1930c3dc4c09SDon Skidmore } 1931c3dc4c09SDon Skidmore 1932c3dc4c09SDon Skidmore /** 1933c3dc4c09SDon Skidmore * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 1934c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1935c3dc4c09SDon Skidmore * @speed: link speed 1936c3dc4c09SDon Skidmore * 1937c3dc4c09SDon Skidmore * Configures the integrated KR PHY. 1938c3dc4c09SDon Skidmore **/ 1939c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 1940c3dc4c09SDon Skidmore ixgbe_link_speed speed) 1941c3dc4c09SDon Skidmore { 1942c3dc4c09SDon Skidmore s32 status; 1943c3dc4c09SDon Skidmore u32 reg_val; 1944c3dc4c09SDon Skidmore 19459a5c27e6SMark Rustad status = hw->mac.ops.read_iosf_sb_reg(hw, 1946c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1947c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 1948c3dc4c09SDon Skidmore if (status) 1949c3dc4c09SDon Skidmore return status; 1950c3dc4c09SDon Skidmore 1951c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1952c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ | 1953c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC); 1954c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 1955c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 1956c3dc4c09SDon Skidmore 1957c3dc4c09SDon Skidmore /* Advertise 10G support. */ 1958c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1959c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 1960c3dc4c09SDon Skidmore 1961c3dc4c09SDon Skidmore /* Advertise 1G support. */ 1962c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_1GB_FULL) 1963c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 1964c3dc4c09SDon Skidmore 1965c3dc4c09SDon Skidmore /* Restart auto-negotiation. */ 1966c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 19679a5c27e6SMark Rustad status = hw->mac.ops.write_iosf_sb_reg(hw, 1968c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1969c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 1970c3dc4c09SDon Skidmore 1971c3dc4c09SDon Skidmore return status; 1972c3dc4c09SDon Skidmore } 1973c3dc4c09SDon Skidmore 19746a14ee0cSDon Skidmore /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. 19756a14ee0cSDon Skidmore * @hw: pointer to hardware structure 19766a14ee0cSDon Skidmore * 19776a14ee0cSDon Skidmore * Configures the integrated KX4 PHY. 19786a14ee0cSDon Skidmore **/ 19797ddbde3fSDon Skidmore static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) 19806a14ee0cSDon Skidmore { 19816a14ee0cSDon Skidmore s32 status; 19826a14ee0cSDon Skidmore u32 reg_val; 19836a14ee0cSDon Skidmore 19849a5c27e6SMark Rustad status = hw->mac.ops.read_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, 19856a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 19866a14ee0cSDon Skidmore hw->bus.lan_id, ®_val); 19876a14ee0cSDon Skidmore if (status) 19886a14ee0cSDon Skidmore return status; 19896a14ee0cSDon Skidmore 19906a14ee0cSDon Skidmore reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | 19916a14ee0cSDon Skidmore IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); 19926a14ee0cSDon Skidmore 19936a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; 19946a14ee0cSDon Skidmore 19956a14ee0cSDon Skidmore /* Advertise 10G support. */ 19966a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) 19976a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; 19986a14ee0cSDon Skidmore 19996a14ee0cSDon Skidmore /* Advertise 1G support. */ 20006a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) 20016a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; 20026a14ee0cSDon Skidmore 20036a14ee0cSDon Skidmore /* Restart auto-negotiation. */ 20046a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; 20059a5c27e6SMark Rustad status = hw->mac.ops.write_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, 20066a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 20076a14ee0cSDon Skidmore hw->bus.lan_id, reg_val); 20086a14ee0cSDon Skidmore 20096a14ee0cSDon Skidmore return status; 20106a14ee0cSDon Skidmore } 20116a14ee0cSDon Skidmore 2012f572b2c4SMark Rustad /** 2013f572b2c4SMark Rustad * ixgbe_setup_kr_x550em - Configure the KR PHY 20146a14ee0cSDon Skidmore * @hw: pointer to hardware structure 20156a14ee0cSDon Skidmore * 2016f572b2c4SMark Rustad * Configures the integrated KR PHY for X550EM_x. 20176a14ee0cSDon Skidmore **/ 20187ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 20196a14ee0cSDon Skidmore { 2020f572b2c4SMark Rustad if (hw->mac.type != ixgbe_mac_X550EM_x) 2021f572b2c4SMark Rustad return 0; 2022f572b2c4SMark Rustad 2023c3dc4c09SDon Skidmore return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 20246a14ee0cSDon Skidmore } 20256a14ee0cSDon Skidmore 2026c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 2027c3dc4c09SDon Skidmore * @hw: address of hardware structure 2028c3dc4c09SDon Skidmore * @link_up: address of boolean to indicate link status 2029c3dc4c09SDon Skidmore * 2030c3dc4c09SDon Skidmore * Returns error code if unable to get link status. 2031c3dc4c09SDon Skidmore **/ 2032c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 2033c3dc4c09SDon Skidmore { 2034c3dc4c09SDon Skidmore u32 ret; 2035c3dc4c09SDon Skidmore u16 autoneg_status; 2036c3dc4c09SDon Skidmore 2037c3dc4c09SDon Skidmore *link_up = false; 2038c3dc4c09SDon Skidmore 2039c3dc4c09SDon Skidmore /* read this twice back to back to indicate current status */ 20404dc4000bSEmil Tantilov ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 2041c3dc4c09SDon Skidmore &autoneg_status); 2042c3dc4c09SDon Skidmore if (ret) 2043c3dc4c09SDon Skidmore return ret; 2044c3dc4c09SDon Skidmore 20454dc4000bSEmil Tantilov ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 2046c3dc4c09SDon Skidmore &autoneg_status); 2047c3dc4c09SDon Skidmore if (ret) 2048c3dc4c09SDon Skidmore return ret; 2049c3dc4c09SDon Skidmore 2050c3dc4c09SDon Skidmore *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 2051c3dc4c09SDon Skidmore 2052c3dc4c09SDon Skidmore return 0; 2053c3dc4c09SDon Skidmore } 2054c3dc4c09SDon Skidmore 2055c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 20566a14ee0cSDon Skidmore * @hw: point to hardware structure 20576a14ee0cSDon Skidmore * 2058c3dc4c09SDon Skidmore * Configures the link between the integrated KR PHY and the external X557 PHY 2059c3dc4c09SDon Skidmore * The driver will call this function when it gets a link status change 2060c3dc4c09SDon Skidmore * interrupt from the X557 PHY. This function configures the link speed 2061c3dc4c09SDon Skidmore * between the PHYs to match the link speed of the BASE-T link. 20626a14ee0cSDon Skidmore * 20636a14ee0cSDon Skidmore * A return of a non-zero value indicates an error, and the base driver should 20646a14ee0cSDon Skidmore * not report link up. 20656a14ee0cSDon Skidmore **/ 2066c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 20676a14ee0cSDon Skidmore { 20686a14ee0cSDon Skidmore ixgbe_link_speed force_speed; 2069c3dc4c09SDon Skidmore bool link_up; 2070c3dc4c09SDon Skidmore u32 status; 2071c3dc4c09SDon Skidmore u16 speed; 20726a14ee0cSDon Skidmore 2073c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 2074c3dc4c09SDon Skidmore return IXGBE_ERR_CONFIG; 2075c3dc4c09SDon Skidmore 2076f164b845SMark Rustad if (hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { 2077f164b845SMark Rustad speed = IXGBE_LINK_SPEED_10GB_FULL | 2078f164b845SMark Rustad IXGBE_LINK_SPEED_1GB_FULL; 2079f164b845SMark Rustad return ixgbe_setup_kr_speed_x550em(hw, speed); 2080f164b845SMark Rustad } 2081f164b845SMark Rustad 2082c3dc4c09SDon Skidmore /* If link is not up, then there is no setup necessary so return */ 2083c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 20846a14ee0cSDon Skidmore if (status) 20856a14ee0cSDon Skidmore return status; 20866a14ee0cSDon Skidmore 2087c3dc4c09SDon Skidmore if (!link_up) 20886a14ee0cSDon Skidmore return 0; 20896a14ee0cSDon Skidmore 20906a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 20914dc4000bSEmil Tantilov MDIO_MMD_AN, 20926a14ee0cSDon Skidmore &speed); 2093c3dc4c09SDon Skidmore if (status) 2094c3dc4c09SDon Skidmore return status; 2095c3dc4c09SDon Skidmore 2096c3dc4c09SDon Skidmore /* If link is not still up, then no setup is necessary so return */ 2097c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 2098c3dc4c09SDon Skidmore if (status) 2099c3dc4c09SDon Skidmore return status; 2100c3dc4c09SDon Skidmore 2101c3dc4c09SDon Skidmore if (!link_up) 2102c3dc4c09SDon Skidmore return 0; 21036a14ee0cSDon Skidmore 21046a14ee0cSDon Skidmore /* clear everything but the speed and duplex bits */ 21056a14ee0cSDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 21066a14ee0cSDon Skidmore 21076a14ee0cSDon Skidmore switch (speed) { 21086a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 21096a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 21106a14ee0cSDon Skidmore break; 21116a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 21126a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 21136a14ee0cSDon Skidmore break; 21146a14ee0cSDon Skidmore default: 21156a14ee0cSDon Skidmore /* Internal PHY does not support anything else */ 21166a14ee0cSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 21176a14ee0cSDon Skidmore } 21186a14ee0cSDon Skidmore 21196a14ee0cSDon Skidmore return ixgbe_setup_ixfi_x550em(hw, &force_speed); 21206a14ee0cSDon Skidmore } 21216a14ee0cSDon Skidmore 2122f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 2123f4410d2cSDon Skidmore * @hw: pointer to hardware structure 2124f4410d2cSDon Skidmore **/ 2125f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 2126f4410d2cSDon Skidmore { 2127f4410d2cSDon Skidmore s32 status; 2128f4410d2cSDon Skidmore 2129f4410d2cSDon Skidmore status = ixgbe_reset_phy_generic(hw); 2130f4410d2cSDon Skidmore 2131f4410d2cSDon Skidmore if (status) 2132f4410d2cSDon Skidmore return status; 2133f4410d2cSDon Skidmore 2134f4410d2cSDon Skidmore /* Configure Link Status Alarm and Temperature Threshold interrupts */ 2135f4410d2cSDon Skidmore return ixgbe_enable_lasi_ext_t_x550em(hw); 2136f4410d2cSDon Skidmore } 2137f4410d2cSDon Skidmore 2138a0ad55a3SDon Skidmore /** 2139a0ad55a3SDon Skidmore * ixgbe_led_on_t_x550em - Turns on the software controllable LEDs. 2140a0ad55a3SDon Skidmore * @hw: pointer to hardware structure 2141a0ad55a3SDon Skidmore * @led_idx: led number to turn on 2142a0ad55a3SDon Skidmore **/ 2143d2d43e5bSEmil Tantilov static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 2144a0ad55a3SDon Skidmore { 2145a0ad55a3SDon Skidmore u16 phy_data; 2146a0ad55a3SDon Skidmore 2147a0ad55a3SDon Skidmore if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 2148a0ad55a3SDon Skidmore return IXGBE_ERR_PARAM; 2149a0ad55a3SDon Skidmore 2150a0ad55a3SDon Skidmore /* To turn on the LED, set mode to ON. */ 2151a0ad55a3SDon Skidmore hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 21524dc4000bSEmil Tantilov MDIO_MMD_VEND1, &phy_data); 2153a0ad55a3SDon Skidmore phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; 2154a0ad55a3SDon Skidmore hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 21554dc4000bSEmil Tantilov MDIO_MMD_VEND1, phy_data); 2156a0ad55a3SDon Skidmore 2157a0ad55a3SDon Skidmore return 0; 2158a0ad55a3SDon Skidmore } 2159a0ad55a3SDon Skidmore 2160a0ad55a3SDon Skidmore /** 2161a0ad55a3SDon Skidmore * ixgbe_led_off_t_x550em - Turns off the software controllable LEDs. 2162a0ad55a3SDon Skidmore * @hw: pointer to hardware structure 2163a0ad55a3SDon Skidmore * @led_idx: led number to turn off 2164a0ad55a3SDon Skidmore **/ 2165d2d43e5bSEmil Tantilov static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 2166a0ad55a3SDon Skidmore { 2167a0ad55a3SDon Skidmore u16 phy_data; 2168a0ad55a3SDon Skidmore 2169a0ad55a3SDon Skidmore if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 2170a0ad55a3SDon Skidmore return IXGBE_ERR_PARAM; 2171a0ad55a3SDon Skidmore 2172a0ad55a3SDon Skidmore /* To turn on the LED, set mode to ON. */ 2173a0ad55a3SDon Skidmore hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 21744dc4000bSEmil Tantilov MDIO_MMD_VEND1, &phy_data); 2175a0ad55a3SDon Skidmore phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; 2176a0ad55a3SDon Skidmore hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 21774dc4000bSEmil Tantilov MDIO_MMD_VEND1, phy_data); 2178a0ad55a3SDon Skidmore 2179a0ad55a3SDon Skidmore return 0; 2180a0ad55a3SDon Skidmore } 2181a0ad55a3SDon Skidmore 21826ac74394SDon Skidmore /** ixgbe_get_lcd_x550em - Determine lowest common denominator 21836ac74394SDon Skidmore * @hw: pointer to hardware structure 21846ac74394SDon Skidmore * @lcd_speed: pointer to lowest common link speed 21856ac74394SDon Skidmore * 21866ac74394SDon Skidmore * Determine lowest common link speed with link partner. 21876ac74394SDon Skidmore **/ 21886ac74394SDon Skidmore static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, 21896ac74394SDon Skidmore ixgbe_link_speed *lcd_speed) 21906ac74394SDon Skidmore { 21916ac74394SDon Skidmore u16 an_lp_status; 21926ac74394SDon Skidmore s32 status; 21936ac74394SDon Skidmore u16 word = hw->eeprom.ctrl_word_3; 21946ac74394SDon Skidmore 21956ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; 21966ac74394SDon Skidmore 21976ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, 21984dc4000bSEmil Tantilov MDIO_MMD_AN, 21996ac74394SDon Skidmore &an_lp_status); 22006ac74394SDon Skidmore if (status) 22016ac74394SDon Skidmore return status; 22026ac74394SDon Skidmore 22036ac74394SDon Skidmore /* If link partner advertised 1G, return 1G */ 22046ac74394SDon Skidmore if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { 22056ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; 22066ac74394SDon Skidmore return status; 22076ac74394SDon Skidmore } 22086ac74394SDon Skidmore 22096ac74394SDon Skidmore /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ 22106ac74394SDon Skidmore if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || 22116ac74394SDon Skidmore (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) 22126ac74394SDon Skidmore return status; 22136ac74394SDon Skidmore 22146ac74394SDon Skidmore /* Link partner not capable of lower speeds, return 10G */ 22156ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; 22166ac74394SDon Skidmore return status; 22176ac74394SDon Skidmore } 22186ac74394SDon Skidmore 2219afdc71e4SMark Rustad /** 2220afdc71e4SMark Rustad * ixgbe_setup_fc_x550em - Set up flow control 2221afdc71e4SMark Rustad * @hw: pointer to hardware structure 2222afdc71e4SMark Rustad */ 2223afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) 2224afdc71e4SMark Rustad { 2225afdc71e4SMark Rustad bool pause, asm_dir; 2226afdc71e4SMark Rustad u32 reg_val; 2227afdc71e4SMark Rustad s32 rc; 2228afdc71e4SMark Rustad 2229afdc71e4SMark Rustad /* Validate the requested mode */ 2230afdc71e4SMark Rustad if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 2231afdc71e4SMark Rustad hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 2232afdc71e4SMark Rustad return IXGBE_ERR_INVALID_LINK_SETTINGS; 2233afdc71e4SMark Rustad } 2234afdc71e4SMark Rustad 2235afdc71e4SMark Rustad /* 10gig parts do not have a word in the EEPROM to determine the 2236afdc71e4SMark Rustad * default flow control setting, so we explicitly set it to full. 2237afdc71e4SMark Rustad */ 2238afdc71e4SMark Rustad if (hw->fc.requested_mode == ixgbe_fc_default) 2239afdc71e4SMark Rustad hw->fc.requested_mode = ixgbe_fc_full; 2240afdc71e4SMark Rustad 2241afdc71e4SMark Rustad /* Determine PAUSE and ASM_DIR bits. */ 2242afdc71e4SMark Rustad switch (hw->fc.requested_mode) { 2243afdc71e4SMark Rustad case ixgbe_fc_none: 2244afdc71e4SMark Rustad pause = false; 2245afdc71e4SMark Rustad asm_dir = false; 2246afdc71e4SMark Rustad break; 2247afdc71e4SMark Rustad case ixgbe_fc_tx_pause: 2248afdc71e4SMark Rustad pause = false; 2249afdc71e4SMark Rustad asm_dir = true; 2250afdc71e4SMark Rustad break; 2251afdc71e4SMark Rustad case ixgbe_fc_rx_pause: 2252afdc71e4SMark Rustad /* Rx Flow control is enabled and Tx Flow control is 2253afdc71e4SMark Rustad * disabled by software override. Since there really 2254afdc71e4SMark Rustad * isn't a way to advertise that we are capable of RX 2255afdc71e4SMark Rustad * Pause ONLY, we will advertise that we support both 2256afdc71e4SMark Rustad * symmetric and asymmetric Rx PAUSE, as such we fall 2257afdc71e4SMark Rustad * through to the fc_full statement. Later, we will 2258afdc71e4SMark Rustad * disable the adapter's ability to send PAUSE frames. 2259afdc71e4SMark Rustad */ 2260afdc71e4SMark Rustad /* Fallthrough */ 2261afdc71e4SMark Rustad case ixgbe_fc_full: 2262afdc71e4SMark Rustad pause = true; 2263afdc71e4SMark Rustad asm_dir = true; 2264afdc71e4SMark Rustad break; 2265afdc71e4SMark Rustad default: 2266afdc71e4SMark Rustad hw_err(hw, "Flow control param set incorrectly\n"); 2267afdc71e4SMark Rustad return IXGBE_ERR_CONFIG; 2268afdc71e4SMark Rustad } 2269afdc71e4SMark Rustad 2270f572b2c4SMark Rustad if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR && 2271f572b2c4SMark Rustad hw->device_id != IXGBE_DEV_ID_X550EM_A_KR && 2272f572b2c4SMark Rustad hw->device_id != IXGBE_DEV_ID_X550EM_A_KR_L) 2273afdc71e4SMark Rustad return 0; 2274afdc71e4SMark Rustad 22759a5c27e6SMark Rustad rc = hw->mac.ops.read_iosf_sb_reg(hw, 2276afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 22779a5c27e6SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 22789a5c27e6SMark Rustad ®_val); 2279afdc71e4SMark Rustad if (rc) 2280afdc71e4SMark Rustad return rc; 2281afdc71e4SMark Rustad 2282afdc71e4SMark Rustad reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 2283afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 2284afdc71e4SMark Rustad if (pause) 2285afdc71e4SMark Rustad reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 2286afdc71e4SMark Rustad if (asm_dir) 2287afdc71e4SMark Rustad reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 22889a5c27e6SMark Rustad rc = hw->mac.ops.write_iosf_sb_reg(hw, 2289afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 22909a5c27e6SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 22919a5c27e6SMark Rustad reg_val); 2292afdc71e4SMark Rustad 2293afdc71e4SMark Rustad /* This device does not fully support AN. */ 2294afdc71e4SMark Rustad hw->fc.disable_fc_autoneg = true; 2295afdc71e4SMark Rustad 2296afdc71e4SMark Rustad return rc; 2297afdc71e4SMark Rustad } 2298afdc71e4SMark Rustad 22996ac74394SDon Skidmore /** ixgbe_enter_lplu_x550em - Transition to low power states 23006ac74394SDon Skidmore * @hw: pointer to hardware structure 23016ac74394SDon Skidmore * 23026ac74394SDon Skidmore * Configures Low Power Link Up on transition to low power states 23036ac74394SDon Skidmore * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting 23046ac74394SDon Skidmore * the X557 PHY immediately prior to entering LPLU. 23056ac74394SDon Skidmore **/ 23066ac74394SDon Skidmore static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) 23076ac74394SDon Skidmore { 23086ac74394SDon Skidmore u16 an_10g_cntl_reg, autoneg_reg, speed; 23096ac74394SDon Skidmore s32 status; 23106ac74394SDon Skidmore ixgbe_link_speed lcd_speed; 23116ac74394SDon Skidmore u32 save_autoneg; 23126ac74394SDon Skidmore bool link_up; 23136ac74394SDon Skidmore 23146ac74394SDon Skidmore /* If blocked by MNG FW, then don't restart AN */ 23156ac74394SDon Skidmore if (ixgbe_check_reset_blocked(hw)) 23166ac74394SDon Skidmore return 0; 23176ac74394SDon Skidmore 23186ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 23196ac74394SDon Skidmore if (status) 23206ac74394SDon Skidmore return status; 23216ac74394SDon Skidmore 23226ac74394SDon Skidmore status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, 23236ac74394SDon Skidmore &hw->eeprom.ctrl_word_3); 23246ac74394SDon Skidmore if (status) 23256ac74394SDon Skidmore return status; 23266ac74394SDon Skidmore 23276ac74394SDon Skidmore /* If link is down, LPLU disabled in NVM, WoL disabled, or 23286ac74394SDon Skidmore * manageability disabled, then force link down by entering 23296ac74394SDon Skidmore * low power mode. 23306ac74394SDon Skidmore */ 23316ac74394SDon Skidmore if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || 23326ac74394SDon Skidmore !(hw->wol_enabled || ixgbe_mng_present(hw))) 23336ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 23346ac74394SDon Skidmore 23356ac74394SDon Skidmore /* Determine LCD */ 23366ac74394SDon Skidmore status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); 23376ac74394SDon Skidmore if (status) 23386ac74394SDon Skidmore return status; 23396ac74394SDon Skidmore 23406ac74394SDon Skidmore /* If no valid LCD link speed, then force link down and exit. */ 23416ac74394SDon Skidmore if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) 23426ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 23436ac74394SDon Skidmore 23446ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 23454dc4000bSEmil Tantilov MDIO_MMD_AN, 23466ac74394SDon Skidmore &speed); 23476ac74394SDon Skidmore if (status) 23486ac74394SDon Skidmore return status; 23496ac74394SDon Skidmore 23506ac74394SDon Skidmore /* If no link now, speed is invalid so take link down */ 23516ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 23526ac74394SDon Skidmore if (status) 23536ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 23546ac74394SDon Skidmore 23556ac74394SDon Skidmore /* clear everything but the speed bits */ 23566ac74394SDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; 23576ac74394SDon Skidmore 23586ac74394SDon Skidmore /* If current speed is already LCD, then exit. */ 23596ac74394SDon Skidmore if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && 23606ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || 23616ac74394SDon Skidmore ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && 23626ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) 23636ac74394SDon Skidmore return status; 23646ac74394SDon Skidmore 23656ac74394SDon Skidmore /* Clear AN completed indication */ 23666ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, 23674dc4000bSEmil Tantilov MDIO_MMD_AN, 23686ac74394SDon Skidmore &autoneg_reg); 23696ac74394SDon Skidmore if (status) 23706ac74394SDon Skidmore return status; 23716ac74394SDon Skidmore 23724dc4000bSEmil Tantilov status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, 23734dc4000bSEmil Tantilov MDIO_MMD_AN, 23746ac74394SDon Skidmore &an_10g_cntl_reg); 23756ac74394SDon Skidmore if (status) 23766ac74394SDon Skidmore return status; 23776ac74394SDon Skidmore 23786ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, 23796ac74394SDon Skidmore IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, 23804dc4000bSEmil Tantilov MDIO_MMD_AN, 23816ac74394SDon Skidmore &autoneg_reg); 23826ac74394SDon Skidmore if (status) 23836ac74394SDon Skidmore return status; 23846ac74394SDon Skidmore 23856ac74394SDon Skidmore save_autoneg = hw->phy.autoneg_advertised; 23866ac74394SDon Skidmore 23876ac74394SDon Skidmore /* Setup link at least common link speed */ 23886ac74394SDon Skidmore status = hw->mac.ops.setup_link(hw, lcd_speed, false); 23896ac74394SDon Skidmore 23906ac74394SDon Skidmore /* restore autoneg from before setting lplu speed */ 23916ac74394SDon Skidmore hw->phy.autoneg_advertised = save_autoneg; 23926ac74394SDon Skidmore 23936ac74394SDon Skidmore return status; 23946ac74394SDon Skidmore } 23956ac74394SDon Skidmore 2396537cc5dfSMark Rustad /** 2397537cc5dfSMark Rustad * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register 2398537cc5dfSMark Rustad * @hw: pointer to hardware structure 2399537cc5dfSMark Rustad * 2400537cc5dfSMark Rustad * Read NW_MNG_IF_SEL register and save field values. 2401537cc5dfSMark Rustad */ 2402537cc5dfSMark Rustad static void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) 2403537cc5dfSMark Rustad { 2404537cc5dfSMark Rustad /* Save NW management interface connected on board. This is used 2405537cc5dfSMark Rustad * to determine internal PHY mode. 2406537cc5dfSMark Rustad */ 2407537cc5dfSMark Rustad hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 2408537cc5dfSMark Rustad 2409537cc5dfSMark Rustad /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set 2410537cc5dfSMark Rustad * PHY address. This register field was has only been used for X552. 2411537cc5dfSMark Rustad */ 2412ae3cb8cbSMark Rustad if (hw->mac.type == ixgbe_mac_x550em_a && 2413ae3cb8cbSMark Rustad hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) { 2414537cc5dfSMark Rustad hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel & 2415537cc5dfSMark Rustad IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> 2416537cc5dfSMark Rustad IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; 2417537cc5dfSMark Rustad } 2418ae3cb8cbSMark Rustad } 2419537cc5dfSMark Rustad 24206a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 24216a14ee0cSDon Skidmore * @hw: pointer to hardware structure 24226a14ee0cSDon Skidmore * 24236a14ee0cSDon Skidmore * Initialize any function pointers that were not able to be 24246a14ee0cSDon Skidmore * set during init_shared_code because the PHY/SFP type was 24256a14ee0cSDon Skidmore * not known. Perform the SFP init if necessary. 24266a14ee0cSDon Skidmore **/ 24277ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 24286a14ee0cSDon Skidmore { 24296a14ee0cSDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 24306a14ee0cSDon Skidmore s32 ret_val; 24316a14ee0cSDon Skidmore 24327e49d616SDon Skidmore hw->mac.ops.set_lan_id(hw); 24337e49d616SDon Skidmore 2434537cc5dfSMark Rustad ixgbe_read_mng_if_sel_x550em(hw); 2435537cc5dfSMark Rustad 2436c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 24376a14ee0cSDon Skidmore phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 2438ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 24396a14ee0cSDon Skidmore } 24406a14ee0cSDon Skidmore 24416a14ee0cSDon Skidmore /* Identify the PHY or SFP module */ 24426a14ee0cSDon Skidmore ret_val = phy->ops.identify(hw); 24436a14ee0cSDon Skidmore 2444c3dc4c09SDon Skidmore /* Setup function pointers based on detected hardware */ 24456a14ee0cSDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 24466a14ee0cSDon Skidmore if (phy->sfp_type != ixgbe_sfp_type_unknown) 24476a14ee0cSDon Skidmore phy->ops.reset = NULL; 24486a14ee0cSDon Skidmore 24496a14ee0cSDon Skidmore /* Set functions pointers based on phy type */ 24506a14ee0cSDon Skidmore switch (hw->phy.type) { 24516a14ee0cSDon Skidmore case ixgbe_phy_x550em_kx4: 24526a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kx4_x550em; 24536a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 24546a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 24556a14ee0cSDon Skidmore break; 24566a14ee0cSDon Skidmore case ixgbe_phy_x550em_kr: 24576a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kr_x550em; 24586a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 24596a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 24606a14ee0cSDon Skidmore break; 24616a14ee0cSDon Skidmore case ixgbe_phy_x550em_ext_t: 2462c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 2463c3dc4c09SDon Skidmore * to determine internal PHY mode 2464c3dc4c09SDon Skidmore */ 2465c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 2466c3dc4c09SDon Skidmore 2467c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup iXFI internal link, 2468c3dc4c09SDon Skidmore * else setup KR now. 2469c3dc4c09SDon Skidmore */ 2470c3dc4c09SDon Skidmore phy->ops.setup_internal_link = 2471c3dc4c09SDon Skidmore ixgbe_setup_internal_phy_t_x550em; 2472c3dc4c09SDon Skidmore 24736ac74394SDon Skidmore /* setup SW LPLU only for first revision */ 24743ca2b250SMark Rustad if (hw->mac.type == ixgbe_mac_X550EM_x && 24753ca2b250SMark Rustad !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) & 24763ca2b250SMark Rustad IXGBE_FUSES0_REV_MASK)) 24776ac74394SDon Skidmore phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; 24786ac74394SDon Skidmore 2479c3dc4c09SDon Skidmore phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 2480f4410d2cSDon Skidmore phy->ops.reset = ixgbe_reset_phy_t_X550em; 24816a14ee0cSDon Skidmore break; 24826a14ee0cSDon Skidmore default: 24836a14ee0cSDon Skidmore break; 24846a14ee0cSDon Skidmore } 2485c3dc4c09SDon Skidmore 24866a14ee0cSDon Skidmore return ret_val; 24876a14ee0cSDon Skidmore } 24886a14ee0cSDon Skidmore 24896a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type 24906a14ee0cSDon Skidmore * @hw: pointer to hardware structure 24916a14ee0cSDon Skidmore * 24926a14ee0cSDon Skidmore * Returns the media type (fiber, copper, backplane) 24936a14ee0cSDon Skidmore * 24946a14ee0cSDon Skidmore */ 24957ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 24966a14ee0cSDon Skidmore { 24976a14ee0cSDon Skidmore enum ixgbe_media_type media_type; 24986a14ee0cSDon Skidmore 24996a14ee0cSDon Skidmore /* Detect if there is a copper PHY attached. */ 25006a14ee0cSDon Skidmore switch (hw->device_id) { 2501200157c2SMark Rustad case IXGBE_DEV_ID_X550EM_A_SGMII: 2502200157c2SMark Rustad case IXGBE_DEV_ID_X550EM_A_SGMII_L: 2503200157c2SMark Rustad hw->phy.type = ixgbe_phy_sgmii; 2504200157c2SMark Rustad /* Fallthrough */ 25056a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 25066a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 2507f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR: 2508f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR_L: 25096a14ee0cSDon Skidmore media_type = ixgbe_media_type_backplane; 25106a14ee0cSDon Skidmore break; 25116a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 25122d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 251349425dfcSMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 25146a14ee0cSDon Skidmore media_type = ixgbe_media_type_fiber; 25156a14ee0cSDon Skidmore break; 25166a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 25176a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 251892ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 25196a14ee0cSDon Skidmore media_type = ixgbe_media_type_copper; 25206a14ee0cSDon Skidmore break; 25216a14ee0cSDon Skidmore default: 25226a14ee0cSDon Skidmore media_type = ixgbe_media_type_unknown; 25236a14ee0cSDon Skidmore break; 25246a14ee0cSDon Skidmore } 25256a14ee0cSDon Skidmore return media_type; 25266a14ee0cSDon Skidmore } 25276a14ee0cSDon Skidmore 25286a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 25296a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 25306a14ee0cSDon Skidmore **/ 25317ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 25326a14ee0cSDon Skidmore { 2533a1e869deSMark Rustad s32 status; 25346a14ee0cSDon Skidmore u16 reg; 25356a14ee0cSDon Skidmore 25366a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 25376a14ee0cSDon Skidmore IXGBE_MDIO_TX_VENDOR_ALARMS_3, 25384dc4000bSEmil Tantilov MDIO_MMD_PMAPMD, 25396a14ee0cSDon Skidmore ®); 25406a14ee0cSDon Skidmore if (status) 25416a14ee0cSDon Skidmore return status; 25426a14ee0cSDon Skidmore 2543e2261bccSDon Skidmore /* If PHY FW reset completed bit is set then this is the first 2544e2261bccSDon Skidmore * SW instance after a power on so the PHY FW must be un-stalled. 2545e2261bccSDon Skidmore */ 2546e2261bccSDon Skidmore if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 25476a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 25486a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 25494dc4000bSEmil Tantilov MDIO_MMD_VEND1, 25506a14ee0cSDon Skidmore ®); 25516a14ee0cSDon Skidmore if (status) 25526a14ee0cSDon Skidmore return status; 25536a14ee0cSDon Skidmore 25546a14ee0cSDon Skidmore reg &= ~IXGBE_MDIO_POWER_UP_STALL; 25556a14ee0cSDon Skidmore 25566a14ee0cSDon Skidmore status = hw->phy.ops.write_reg(hw, 25576a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 25584dc4000bSEmil Tantilov MDIO_MMD_VEND1, 25596a14ee0cSDon Skidmore reg); 2560e2261bccSDon Skidmore if (status) 2561e2261bccSDon Skidmore return status; 2562e2261bccSDon Skidmore } 2563e2261bccSDon Skidmore 25646a14ee0cSDon Skidmore return status; 25656a14ee0cSDon Skidmore } 25666a14ee0cSDon Skidmore 2567e84db727SMark Rustad /** 2568e84db727SMark Rustad * ixgbe_set_mdio_speed - Set MDIO clock speed 2569e84db727SMark Rustad * @hw: pointer to hardware structure 2570e84db727SMark Rustad */ 2571e84db727SMark Rustad static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) 2572e84db727SMark Rustad { 2573e84db727SMark Rustad u32 hlreg0; 2574e84db727SMark Rustad 2575e84db727SMark Rustad switch (hw->device_id) { 2576e84db727SMark Rustad case IXGBE_DEV_ID_X550EM_X_10G_T: 2577a83c27e7SDon Skidmore case IXGBE_DEV_ID_X550EM_A_SGMII: 2578a83c27e7SDon Skidmore case IXGBE_DEV_ID_X550EM_A_SGMII_L: 257992ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 25802d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 2581e84db727SMark Rustad /* Config MDIO clock speed before the first MDIO PHY access */ 2582e84db727SMark Rustad hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 2583e84db727SMark Rustad hlreg0 &= ~IXGBE_HLREG0_MDCSPD; 2584e84db727SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 2585e84db727SMark Rustad break; 2586e84db727SMark Rustad default: 2587e84db727SMark Rustad break; 2588e84db727SMark Rustad } 2589e84db727SMark Rustad } 2590e84db727SMark Rustad 25916a14ee0cSDon Skidmore /** ixgbe_reset_hw_X550em - Perform hardware reset 25926a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 25936a14ee0cSDon Skidmore ** 25946a14ee0cSDon Skidmore ** Resets the hardware by resetting the transmit and receive units, masks 25956a14ee0cSDon Skidmore ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 25966a14ee0cSDon Skidmore ** reset. 25976a14ee0cSDon Skidmore **/ 25987ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 25996a14ee0cSDon Skidmore { 26006a14ee0cSDon Skidmore ixgbe_link_speed link_speed; 26016a14ee0cSDon Skidmore s32 status; 26026a14ee0cSDon Skidmore u32 ctrl = 0; 26036a14ee0cSDon Skidmore u32 i; 26046a14ee0cSDon Skidmore bool link_up = false; 26056a14ee0cSDon Skidmore 26066a14ee0cSDon Skidmore /* Call adapter stop to disable Tx/Rx and clear interrupts */ 26076a14ee0cSDon Skidmore status = hw->mac.ops.stop_adapter(hw); 26086a14ee0cSDon Skidmore if (status) 26096a14ee0cSDon Skidmore return status; 26106a14ee0cSDon Skidmore 26116a14ee0cSDon Skidmore /* flush pending Tx transactions */ 26126a14ee0cSDon Skidmore ixgbe_clear_tx_pending(hw); 26136a14ee0cSDon Skidmore 26146a14ee0cSDon Skidmore /* PHY ops must be identified and initialized prior to reset */ 26156a14ee0cSDon Skidmore 26166a14ee0cSDon Skidmore /* Identify PHY and related function pointers */ 26176a14ee0cSDon Skidmore status = hw->phy.ops.init(hw); 26186a14ee0cSDon Skidmore 26196a14ee0cSDon Skidmore /* start the external PHY */ 26206a14ee0cSDon Skidmore if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 26216a14ee0cSDon Skidmore status = ixgbe_init_ext_t_x550em(hw); 26226a14ee0cSDon Skidmore if (status) 26236a14ee0cSDon Skidmore return status; 26246a14ee0cSDon Skidmore } 26256a14ee0cSDon Skidmore 26266a14ee0cSDon Skidmore /* Setup SFP module if there is one present. */ 26276a14ee0cSDon Skidmore if (hw->phy.sfp_setup_needed) { 26286a14ee0cSDon Skidmore status = hw->mac.ops.setup_sfp(hw); 26296a14ee0cSDon Skidmore hw->phy.sfp_setup_needed = false; 26306a14ee0cSDon Skidmore } 26316a14ee0cSDon Skidmore 26326a14ee0cSDon Skidmore /* Reset PHY */ 26336a14ee0cSDon Skidmore if (!hw->phy.reset_disable && hw->phy.ops.reset) 26346a14ee0cSDon Skidmore hw->phy.ops.reset(hw); 26356a14ee0cSDon Skidmore 26366a14ee0cSDon Skidmore mac_reset_top: 26376a14ee0cSDon Skidmore /* Issue global reset to the MAC. Needs to be SW reset if link is up. 26386a14ee0cSDon Skidmore * If link reset is used when link is up, it might reset the PHY when 26396a14ee0cSDon Skidmore * mng is using it. If link is down or the flag to force full link 26406a14ee0cSDon Skidmore * reset is set, then perform link reset. 26416a14ee0cSDon Skidmore */ 26426a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_LNK_RST; 26436a14ee0cSDon Skidmore 26446a14ee0cSDon Skidmore if (!hw->force_full_reset) { 26456a14ee0cSDon Skidmore hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 26466a14ee0cSDon Skidmore if (link_up) 26476a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_RST; 26486a14ee0cSDon Skidmore } 26496a14ee0cSDon Skidmore 26506a14ee0cSDon Skidmore ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 26516a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 26526a14ee0cSDon Skidmore IXGBE_WRITE_FLUSH(hw); 2653efff2e02SMark Rustad usleep_range(1000, 1200); 26546a14ee0cSDon Skidmore 26556a14ee0cSDon Skidmore /* Poll for reset bit to self-clear meaning reset is complete */ 26566a14ee0cSDon Skidmore for (i = 0; i < 10; i++) { 26576a14ee0cSDon Skidmore ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 26586a14ee0cSDon Skidmore if (!(ctrl & IXGBE_CTRL_RST_MASK)) 26596a14ee0cSDon Skidmore break; 2660efff2e02SMark Rustad udelay(1); 26616a14ee0cSDon Skidmore } 26626a14ee0cSDon Skidmore 26636a14ee0cSDon Skidmore if (ctrl & IXGBE_CTRL_RST_MASK) { 26646a14ee0cSDon Skidmore status = IXGBE_ERR_RESET_FAILED; 26656a14ee0cSDon Skidmore hw_dbg(hw, "Reset polling failed to complete.\n"); 26666a14ee0cSDon Skidmore } 26676a14ee0cSDon Skidmore 26686a14ee0cSDon Skidmore msleep(50); 26696a14ee0cSDon Skidmore 26706a14ee0cSDon Skidmore /* Double resets are required for recovery from certain error 26716a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 26726a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 26736a14ee0cSDon Skidmore */ 26746a14ee0cSDon Skidmore if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 26756a14ee0cSDon Skidmore hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 26766a14ee0cSDon Skidmore goto mac_reset_top; 26776a14ee0cSDon Skidmore } 26786a14ee0cSDon Skidmore 26796a14ee0cSDon Skidmore /* Store the permanent mac address */ 26806a14ee0cSDon Skidmore hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 26816a14ee0cSDon Skidmore 26826a14ee0cSDon Skidmore /* Store MAC address from RAR0, clear receive address registers, and 26836a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 26846a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 26856a14ee0cSDon Skidmore */ 26866a14ee0cSDon Skidmore hw->mac.num_rar_entries = 128; 26876a14ee0cSDon Skidmore hw->mac.ops.init_rx_addrs(hw); 26886a14ee0cSDon Skidmore 2689e84db727SMark Rustad ixgbe_set_mdio_speed(hw); 2690deda562aSDon Skidmore 2691ab5fe0c5SDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 2692ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 2693ab5fe0c5SDon Skidmore 26946a14ee0cSDon Skidmore return status; 26956a14ee0cSDon Skidmore } 26966a14ee0cSDon Skidmore 26975b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 26985b7f000fSDon Skidmore * anti-spoofing 26995b7f000fSDon Skidmore * @hw: pointer to hardware structure 27005b7f000fSDon Skidmore * @enable: enable or disable switch for Ethertype anti-spoofing 27015b7f000fSDon Skidmore * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 27025b7f000fSDon Skidmore **/ 2703bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 2704bc035fc5SDon Skidmore bool enable, int vf) 27055b7f000fSDon Skidmore { 27065b7f000fSDon Skidmore int vf_target_reg = vf >> 3; 27075b7f000fSDon Skidmore int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 27085b7f000fSDon Skidmore u32 pfvfspoof; 27095b7f000fSDon Skidmore 27105b7f000fSDon Skidmore pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 27115b7f000fSDon Skidmore if (enable) 2712b4f47a48SJacob Keller pfvfspoof |= BIT(vf_target_shift); 27135b7f000fSDon Skidmore else 2714b4f47a48SJacob Keller pfvfspoof &= ~BIT(vf_target_shift); 27155b7f000fSDon Skidmore 27165b7f000fSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 27175b7f000fSDon Skidmore } 27185b7f000fSDon Skidmore 27196d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 27206d4c96adSDon Skidmore * @hw: pointer to hardware structure 27216d4c96adSDon Skidmore * @enable: enable or disable source address pruning 27226d4c96adSDon Skidmore * @pool: Rx pool to set source address pruning for 27236d4c96adSDon Skidmore **/ 27246d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 27256d4c96adSDon Skidmore bool enable, 27266d4c96adSDon Skidmore unsigned int pool) 27276d4c96adSDon Skidmore { 27286d4c96adSDon Skidmore u64 pfflp; 27296d4c96adSDon Skidmore 27306d4c96adSDon Skidmore /* max rx pool is 63 */ 27316d4c96adSDon Skidmore if (pool > 63) 27326d4c96adSDon Skidmore return; 27336d4c96adSDon Skidmore 27346d4c96adSDon Skidmore pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 27356d4c96adSDon Skidmore pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 27366d4c96adSDon Skidmore 27376d4c96adSDon Skidmore if (enable) 27386d4c96adSDon Skidmore pfflp |= (1ULL << pool); 27396d4c96adSDon Skidmore else 27406d4c96adSDon Skidmore pfflp &= ~(1ULL << pool); 27416d4c96adSDon Skidmore 27426d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 27436d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 27446d4c96adSDon Skidmore } 27456d4c96adSDon Skidmore 2746449e21a9SMark Rustad /** 2747449e21a9SMark Rustad * ixgbe_set_mux - Set mux for port 1 access with CS4227 2748449e21a9SMark Rustad * @hw: pointer to hardware structure 2749449e21a9SMark Rustad * @state: set mux if 1, clear if 0 2750449e21a9SMark Rustad */ 2751449e21a9SMark Rustad static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) 2752449e21a9SMark Rustad { 2753449e21a9SMark Rustad u32 esdp; 2754449e21a9SMark Rustad 2755449e21a9SMark Rustad if (!hw->bus.lan_id) 2756449e21a9SMark Rustad return; 2757449e21a9SMark Rustad esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 2758449e21a9SMark Rustad if (state) 2759449e21a9SMark Rustad esdp |= IXGBE_ESDP_SDP1; 2760449e21a9SMark Rustad else 2761449e21a9SMark Rustad esdp &= ~IXGBE_ESDP_SDP1; 2762449e21a9SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 2763449e21a9SMark Rustad IXGBE_WRITE_FLUSH(hw); 2764449e21a9SMark Rustad } 2765449e21a9SMark Rustad 2766449e21a9SMark Rustad /** 2767449e21a9SMark Rustad * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore 2768449e21a9SMark Rustad * @hw: pointer to hardware structure 2769449e21a9SMark Rustad * @mask: Mask to specify which semaphore to acquire 2770449e21a9SMark Rustad * 2771449e21a9SMark Rustad * Acquires the SWFW semaphore and sets the I2C MUX 2772449e21a9SMark Rustad */ 2773449e21a9SMark Rustad static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 2774449e21a9SMark Rustad { 2775449e21a9SMark Rustad s32 status; 2776449e21a9SMark Rustad 2777449e21a9SMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, mask); 2778449e21a9SMark Rustad if (status) 2779449e21a9SMark Rustad return status; 2780449e21a9SMark Rustad 2781449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 2782449e21a9SMark Rustad ixgbe_set_mux(hw, 1); 2783449e21a9SMark Rustad 2784449e21a9SMark Rustad return 0; 2785449e21a9SMark Rustad } 2786449e21a9SMark Rustad 2787449e21a9SMark Rustad /** 2788449e21a9SMark Rustad * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore 2789449e21a9SMark Rustad * @hw: pointer to hardware structure 2790449e21a9SMark Rustad * @mask: Mask to specify which semaphore to release 2791449e21a9SMark Rustad * 2792449e21a9SMark Rustad * Releases the SWFW semaphore and sets the I2C MUX 2793449e21a9SMark Rustad */ 2794449e21a9SMark Rustad static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 2795449e21a9SMark Rustad { 2796449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 2797449e21a9SMark Rustad ixgbe_set_mux(hw, 0); 2798449e21a9SMark Rustad 2799449e21a9SMark Rustad ixgbe_release_swfw_sync_X540(hw, mask); 2800449e21a9SMark Rustad } 2801449e21a9SMark Rustad 280249425dfcSMark Rustad /** 280349425dfcSMark Rustad * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore 280449425dfcSMark Rustad * @hw: pointer to hardware structure 280549425dfcSMark Rustad * @mask: Mask to specify which semaphore to acquire 280649425dfcSMark Rustad * 280749425dfcSMark Rustad * Acquires the SWFW semaphore and get the shared PHY token as needed 280849425dfcSMark Rustad */ 280949425dfcSMark Rustad static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 281049425dfcSMark Rustad { 281149425dfcSMark Rustad u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 281249425dfcSMark Rustad int retries = FW_PHY_TOKEN_RETRIES; 281349425dfcSMark Rustad s32 status; 281449425dfcSMark Rustad 281549425dfcSMark Rustad while (--retries) { 281649425dfcSMark Rustad status = 0; 281749425dfcSMark Rustad if (hmask) 281849425dfcSMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, hmask); 281949425dfcSMark Rustad if (status) 282049425dfcSMark Rustad return status; 282149425dfcSMark Rustad if (!(mask & IXGBE_GSSR_TOKEN_SM)) 282249425dfcSMark Rustad return 0; 282349425dfcSMark Rustad 282449425dfcSMark Rustad status = ixgbe_get_phy_token(hw); 282549425dfcSMark Rustad if (!status) 282649425dfcSMark Rustad return 0; 282749425dfcSMark Rustad if (hmask) 282849425dfcSMark Rustad ixgbe_release_swfw_sync_X540(hw, hmask); 282949425dfcSMark Rustad if (status != IXGBE_ERR_TOKEN_RETRY) 283049425dfcSMark Rustad return status; 2831d4f90d9dSArnd Bergmann msleep(FW_PHY_TOKEN_DELAY); 283249425dfcSMark Rustad } 283349425dfcSMark Rustad 283449425dfcSMark Rustad return status; 283549425dfcSMark Rustad } 283649425dfcSMark Rustad 283749425dfcSMark Rustad /** 283849425dfcSMark Rustad * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore 283949425dfcSMark Rustad * @hw: pointer to hardware structure 284049425dfcSMark Rustad * @mask: Mask to specify which semaphore to release 284149425dfcSMark Rustad * 284249425dfcSMark Rustad * Release the SWFW semaphore and puts the shared PHY token as needed 284349425dfcSMark Rustad */ 284449425dfcSMark Rustad static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 284549425dfcSMark Rustad { 284649425dfcSMark Rustad u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 284749425dfcSMark Rustad 284849425dfcSMark Rustad if (mask & IXGBE_GSSR_TOKEN_SM) 284949425dfcSMark Rustad ixgbe_put_phy_token(hw); 285049425dfcSMark Rustad 285149425dfcSMark Rustad if (hmask) 285249425dfcSMark Rustad ixgbe_release_swfw_sync_X540(hw, hmask); 285349425dfcSMark Rustad } 285449425dfcSMark Rustad 2855d31afc8fSMark Rustad /** 2856d31afc8fSMark Rustad * ixgbe_read_phy_reg_x550a - Reads specified PHY register 2857d31afc8fSMark Rustad * @hw: pointer to hardware structure 2858d31afc8fSMark Rustad * @reg_addr: 32 bit address of PHY register to read 2859d31afc8fSMark Rustad * @phy_data: Pointer to read data from PHY register 2860d31afc8fSMark Rustad * 2861d31afc8fSMark Rustad * Reads a value from a specified PHY register using the SWFW lock and PHY 2862d31afc8fSMark Rustad * Token. The PHY Token is needed since the MDIO is shared between to MAC 2863d31afc8fSMark Rustad * instances. 2864d31afc8fSMark Rustad */ 2865d31afc8fSMark Rustad static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 2866d31afc8fSMark Rustad u32 device_type, u16 *phy_data) 2867d31afc8fSMark Rustad { 2868d31afc8fSMark Rustad u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 2869d31afc8fSMark Rustad s32 status; 2870d31afc8fSMark Rustad 2871d31afc8fSMark Rustad if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 2872d31afc8fSMark Rustad return IXGBE_ERR_SWFW_SYNC; 2873d31afc8fSMark Rustad 2874d31afc8fSMark Rustad status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); 2875d31afc8fSMark Rustad 2876d31afc8fSMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 2877d31afc8fSMark Rustad 2878d31afc8fSMark Rustad return status; 2879d31afc8fSMark Rustad } 2880d31afc8fSMark Rustad 2881d31afc8fSMark Rustad /** 2882d31afc8fSMark Rustad * ixgbe_write_phy_reg_x550a - Writes specified PHY register 2883d31afc8fSMark Rustad * @hw: pointer to hardware structure 2884d31afc8fSMark Rustad * @reg_addr: 32 bit PHY register to write 2885d31afc8fSMark Rustad * @device_type: 5 bit device type 2886d31afc8fSMark Rustad * @phy_data: Data to write to the PHY register 2887d31afc8fSMark Rustad * 2888d31afc8fSMark Rustad * Writes a value to specified PHY register using the SWFW lock and PHY Token. 2889d31afc8fSMark Rustad * The PHY Token is needed since the MDIO is shared between to MAC instances. 2890d31afc8fSMark Rustad */ 2891d31afc8fSMark Rustad static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 2892d31afc8fSMark Rustad u32 device_type, u16 phy_data) 2893d31afc8fSMark Rustad { 2894d31afc8fSMark Rustad u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 2895d31afc8fSMark Rustad s32 status; 2896d31afc8fSMark Rustad 2897d31afc8fSMark Rustad if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 2898d31afc8fSMark Rustad return IXGBE_ERR_SWFW_SYNC; 2899d31afc8fSMark Rustad 2900d31afc8fSMark Rustad status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data); 2901d31afc8fSMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 2902d31afc8fSMark Rustad 2903d31afc8fSMark Rustad return status; 2904d31afc8fSMark Rustad } 2905d31afc8fSMark Rustad 29066a14ee0cSDon Skidmore #define X550_COMMON_MAC \ 29076a14ee0cSDon Skidmore .init_hw = &ixgbe_init_hw_generic, \ 29086a14ee0cSDon Skidmore .start_hw = &ixgbe_start_hw_X540, \ 29096a14ee0cSDon Skidmore .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 29106a14ee0cSDon Skidmore .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 29116a14ee0cSDon Skidmore .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 29126a14ee0cSDon Skidmore .get_device_caps = &ixgbe_get_device_caps_generic, \ 29136a14ee0cSDon Skidmore .stop_adapter = &ixgbe_stop_adapter_generic, \ 29146a14ee0cSDon Skidmore .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 29156a14ee0cSDon Skidmore .read_analog_reg8 = NULL, \ 29166a14ee0cSDon Skidmore .write_analog_reg8 = NULL, \ 29176a14ee0cSDon Skidmore .set_rxpba = &ixgbe_set_rxpba_generic, \ 29186a14ee0cSDon Skidmore .check_link = &ixgbe_check_mac_link_generic, \ 29196a14ee0cSDon Skidmore .blink_led_start = &ixgbe_blink_led_start_X540, \ 29206a14ee0cSDon Skidmore .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 29216a14ee0cSDon Skidmore .set_rar = &ixgbe_set_rar_generic, \ 29226a14ee0cSDon Skidmore .clear_rar = &ixgbe_clear_rar_generic, \ 29236a14ee0cSDon Skidmore .set_vmdq = &ixgbe_set_vmdq_generic, \ 29246a14ee0cSDon Skidmore .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 29256a14ee0cSDon Skidmore .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 29266a14ee0cSDon Skidmore .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 29276a14ee0cSDon Skidmore .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 29286a14ee0cSDon Skidmore .enable_mc = &ixgbe_enable_mc_generic, \ 29296a14ee0cSDon Skidmore .disable_mc = &ixgbe_disable_mc_generic, \ 29306a14ee0cSDon Skidmore .clear_vfta = &ixgbe_clear_vfta_generic, \ 29316a14ee0cSDon Skidmore .set_vfta = &ixgbe_set_vfta_generic, \ 29326a14ee0cSDon Skidmore .fc_enable = &ixgbe_fc_enable_generic, \ 29336a14ee0cSDon Skidmore .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, \ 29346a14ee0cSDon Skidmore .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 29356a14ee0cSDon Skidmore .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 29366a14ee0cSDon Skidmore .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 29376d4c96adSDon Skidmore .set_source_address_pruning = \ 29386d4c96adSDon Skidmore &ixgbe_set_source_address_pruning_X550, \ 29395b7f000fSDon Skidmore .set_ethertype_anti_spoofing = \ 29405b7f000fSDon Skidmore &ixgbe_set_ethertype_anti_spoofing_X550, \ 29416a14ee0cSDon Skidmore .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 29426a14ee0cSDon Skidmore .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 29436a14ee0cSDon Skidmore .get_thermal_sensor_data = NULL, \ 29446a14ee0cSDon Skidmore .init_thermal_sensor_thresh = NULL, \ 29451f9ac57cSDon Skidmore .enable_rx = &ixgbe_enable_rx_generic, \ 29461f9ac57cSDon Skidmore .disable_rx = &ixgbe_disable_rx_x550, \ 29476a14ee0cSDon Skidmore 294837689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550 = { 29496a14ee0cSDon Skidmore X550_COMMON_MAC 2950a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_generic, 2951a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_generic, 2952805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 29536a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X540, 29546a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X540, 29556a14ee0cSDon Skidmore .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 29566a14ee0cSDon Skidmore .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 29576a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_mac_link_X540, 29586a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 2959454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_generic, 29606a14ee0cSDon Skidmore .setup_sfp = NULL, 2961449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, 2962449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X540, 2963dbd15b8fSDon Skidmore .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 2964afdc71e4SMark Rustad .prot_autoc_read = prot_autoc_read_generic, 2965afdc71e4SMark Rustad .prot_autoc_write = prot_autoc_write_generic, 2966afdc71e4SMark Rustad .setup_fc = ixgbe_setup_fc_generic, 29676a14ee0cSDon Skidmore }; 29686a14ee0cSDon Skidmore 296937689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550EM_x = { 29706a14ee0cSDon Skidmore X550_COMMON_MAC 2971a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_t_x550em, 2972a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_t_x550em, 2973805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 29746a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X550em, 29756a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X550em, 29766a14ee0cSDon Skidmore .get_san_mac_addr = NULL, 29776a14ee0cSDon Skidmore .get_wwn_prefix = NULL, 29784695886cSEmil Tantilov .setup_link = &ixgbe_setup_mac_link_X540, 29796a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 2980454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_X550em, 29816a14ee0cSDon Skidmore .setup_sfp = ixgbe_setup_sfp_modules_X550em, 2982449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 2983449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 2984dbd15b8fSDon Skidmore .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 2985afdc71e4SMark Rustad .setup_fc = NULL, /* defined later */ 29869a5c27e6SMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, 29879a5c27e6SMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, 29886a14ee0cSDon Skidmore }; 29896a14ee0cSDon Skidmore 299049425dfcSMark Rustad static struct ixgbe_mac_operations mac_ops_x550em_a = { 299149425dfcSMark Rustad X550_COMMON_MAC 2992a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_t_x550em, 2993a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_t_x550em, 2994805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 299549425dfcSMark Rustad .reset_hw = ixgbe_reset_hw_X550em, 299649425dfcSMark Rustad .get_media_type = ixgbe_get_media_type_X550em, 299749425dfcSMark Rustad .get_san_mac_addr = NULL, 299849425dfcSMark Rustad .get_wwn_prefix = NULL, 2999a0254a70SMark Rustad .setup_link = NULL, /* defined later */ 300049425dfcSMark Rustad .get_link_capabilities = ixgbe_get_link_capabilities_X550em, 300149425dfcSMark Rustad .get_bus_info = ixgbe_get_bus_info_X550em, 300249425dfcSMark Rustad .setup_sfp = ixgbe_setup_sfp_modules_X550em, 300349425dfcSMark Rustad .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, 300449425dfcSMark Rustad .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, 3005a0254a70SMark Rustad .setup_fc = ixgbe_setup_fc_x550em, 300649425dfcSMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, 300749425dfcSMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, 300849425dfcSMark Rustad }; 300949425dfcSMark Rustad 30106a14ee0cSDon Skidmore #define X550_COMMON_EEP \ 30116a14ee0cSDon Skidmore .read = &ixgbe_read_ee_hostif_X550, \ 30126a14ee0cSDon Skidmore .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 30136a14ee0cSDon Skidmore .write = &ixgbe_write_ee_hostif_X550, \ 30146a14ee0cSDon Skidmore .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 30156a14ee0cSDon Skidmore .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 30166a14ee0cSDon Skidmore .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 30176a14ee0cSDon Skidmore .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 30186a14ee0cSDon Skidmore 301937689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550 = { 30206a14ee0cSDon Skidmore X550_COMMON_EEP 30216a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X550, 30226a14ee0cSDon Skidmore }; 30236a14ee0cSDon Skidmore 302437689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 30256a14ee0cSDon Skidmore X550_COMMON_EEP 30266a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X540, 30276a14ee0cSDon Skidmore }; 30286a14ee0cSDon Skidmore 30296a14ee0cSDon Skidmore #define X550_COMMON_PHY \ 30306a14ee0cSDon Skidmore .identify_sfp = &ixgbe_identify_module_generic, \ 30316a14ee0cSDon Skidmore .reset = NULL, \ 30326a14ee0cSDon Skidmore .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 30336a14ee0cSDon Skidmore .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 30346a14ee0cSDon Skidmore .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 30356a14ee0cSDon Skidmore .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 30366a14ee0cSDon Skidmore .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 30376a14ee0cSDon Skidmore .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 3038bef23de1SDon Skidmore .setup_link = &ixgbe_setup_phy_link_generic, \ 3039b5529ef5SDon Skidmore .set_phy_power = NULL, \ 30406a14ee0cSDon Skidmore .check_overtemp = &ixgbe_tn_check_overtemp, \ 30416a14ee0cSDon Skidmore .get_firmware_version = &ixgbe_get_phy_firmware_version_generic, 30426a14ee0cSDon Skidmore 304337689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550 = { 30446a14ee0cSDon Skidmore X550_COMMON_PHY 30456a14ee0cSDon Skidmore .init = NULL, 30466a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_generic, 3047d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_generic, 3048d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_generic, 30496a14ee0cSDon Skidmore }; 30506a14ee0cSDon Skidmore 305137689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550EM_x = { 30526a14ee0cSDon Skidmore X550_COMMON_PHY 30536a14ee0cSDon Skidmore .init = &ixgbe_init_phy_ops_X550em, 30546a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_x550em, 3055d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_generic, 3056d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_generic, 30574f9e3a3dSMark Rustad .read_i2c_combined = &ixgbe_read_i2c_combined_generic, 30584f9e3a3dSMark Rustad .write_i2c_combined = &ixgbe_write_i2c_combined_generic, 3059bb5ce9a5SMark Rustad .read_i2c_combined_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, 3060bb5ce9a5SMark Rustad .write_i2c_combined_unlocked = 3061bb5ce9a5SMark Rustad &ixgbe_write_i2c_combined_generic_unlocked, 30626a14ee0cSDon Skidmore }; 30636a14ee0cSDon Skidmore 3064d31afc8fSMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a = { 3065d31afc8fSMark Rustad X550_COMMON_PHY 3066d31afc8fSMark Rustad .init = &ixgbe_init_phy_ops_X550em, 3067d31afc8fSMark Rustad .identify = &ixgbe_identify_phy_x550em, 3068d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_x550a, 3069d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_x550a, 30708fe293aaSMark Rustad .read_reg_mdi = &ixgbe_read_phy_reg_mdi, 30718fe293aaSMark Rustad .write_reg_mdi = &ixgbe_write_phy_reg_mdi, 3072d31afc8fSMark Rustad }; 3073d31afc8fSMark Rustad 30749a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 30759a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550) 30769a900ecaSDon Skidmore }; 30779a900ecaSDon Skidmore 30789a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 30799a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550EM_x) 30809a900ecaSDon Skidmore }; 30819a900ecaSDon Skidmore 308249425dfcSMark Rustad static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = { 308349425dfcSMark Rustad IXGBE_MVALS_INIT(X550EM_a) 308449425dfcSMark Rustad }; 308549425dfcSMark Rustad 308637689010SMark Rustad const struct ixgbe_info ixgbe_X550_info = { 30876a14ee0cSDon Skidmore .mac = ixgbe_mac_X550, 30886a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 30896a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550, 30906a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550, 30916a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550, 30926a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 30939a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550, 30946a14ee0cSDon Skidmore }; 30956a14ee0cSDon Skidmore 309637689010SMark Rustad const struct ixgbe_info ixgbe_X550EM_x_info = { 30976a14ee0cSDon Skidmore .mac = ixgbe_mac_X550EM_x, 3098b5529ef5SDon Skidmore .get_invariants = &ixgbe_get_invariants_X550_x, 30996a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550EM_x, 31006a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550EM_x, 31016a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550EM_x, 31026a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 31039a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550EM_x, 31046a14ee0cSDon Skidmore }; 310549425dfcSMark Rustad 310649425dfcSMark Rustad const struct ixgbe_info ixgbe_x550em_a_info = { 310749425dfcSMark Rustad .mac = ixgbe_mac_x550em_a, 310849425dfcSMark Rustad .get_invariants = &ixgbe_get_invariants_X550_x, 310949425dfcSMark Rustad .mac_ops = &mac_ops_x550em_a, 311049425dfcSMark Rustad .eeprom_ops = &eeprom_ops_X550EM_x, 3111d31afc8fSMark Rustad .phy_ops = &phy_ops_x550em_a, 311249425dfcSMark Rustad .mbx_ops = &mbx_ops_generic, 311349425dfcSMark Rustad .mvals = ixgbe_mvals_x550em_a, 311449425dfcSMark Rustad }; 3115