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; 2986a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 2996a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 3006a14ee0cSDon Skidmore return ixgbe_identify_phy_generic(hw); 3016a14ee0cSDon Skidmore default: 3026a14ee0cSDon Skidmore break; 3036a14ee0cSDon Skidmore } 3046a14ee0cSDon Skidmore return 0; 3056a14ee0cSDon Skidmore } 3066a14ee0cSDon Skidmore 3076a14ee0cSDon Skidmore static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 3086a14ee0cSDon Skidmore u32 device_type, u16 *phy_data) 3096a14ee0cSDon Skidmore { 3106a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 3116a14ee0cSDon Skidmore } 3126a14ee0cSDon Skidmore 3136a14ee0cSDon Skidmore static s32 ixgbe_write_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 /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 3206a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3216a14ee0cSDon Skidmore * 3226a14ee0cSDon Skidmore * Initializes the EEPROM parameters ixgbe_eeprom_info within the 3236a14ee0cSDon Skidmore * ixgbe_hw struct in order to set up EEPROM access. 3246a14ee0cSDon Skidmore **/ 3257ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 3266a14ee0cSDon Skidmore { 3276a14ee0cSDon Skidmore struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 3286a14ee0cSDon Skidmore u32 eec; 3296a14ee0cSDon Skidmore u16 eeprom_size; 3306a14ee0cSDon Skidmore 3316a14ee0cSDon Skidmore if (eeprom->type == ixgbe_eeprom_uninitialized) { 3326a14ee0cSDon Skidmore eeprom->semaphore_delay = 10; 3336a14ee0cSDon Skidmore eeprom->type = ixgbe_flash; 3346a14ee0cSDon Skidmore 3359a900ecaSDon Skidmore eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 3366a14ee0cSDon Skidmore eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 3376a14ee0cSDon Skidmore IXGBE_EEC_SIZE_SHIFT); 338b4f47a48SJacob Keller eeprom->word_size = BIT(eeprom_size + 3396a14ee0cSDon Skidmore IXGBE_EEPROM_WORD_SIZE_SHIFT); 3406a14ee0cSDon Skidmore 3416a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 3426a14ee0cSDon Skidmore eeprom->type, eeprom->word_size); 3436a14ee0cSDon Skidmore } 3446a14ee0cSDon Skidmore 3456a14ee0cSDon Skidmore return 0; 3466a14ee0cSDon Skidmore } 3476a14ee0cSDon Skidmore 348ae14a1d8SMark Rustad /** 349ae14a1d8SMark Rustad * ixgbe_iosf_wait - Wait for IOSF command completion 350ae14a1d8SMark Rustad * @hw: pointer to hardware structure 351ae14a1d8SMark Rustad * @ctrl: pointer to location to receive final IOSF control value 352ae14a1d8SMark Rustad * 353ae14a1d8SMark Rustad * Return: failing status on timeout 354ae14a1d8SMark Rustad * 355ae14a1d8SMark Rustad * Note: ctrl can be NULL if the IOSF control register value is not needed 356ae14a1d8SMark Rustad */ 357ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 358ae14a1d8SMark Rustad { 359ae14a1d8SMark Rustad u32 i, command; 360ae14a1d8SMark Rustad 361ae14a1d8SMark Rustad /* Check every 10 usec to see if the address cycle completed. 362ae14a1d8SMark Rustad * The SB IOSF BUSY bit will clear when the operation is 363ae14a1d8SMark Rustad * complete. 364ae14a1d8SMark Rustad */ 365ae14a1d8SMark Rustad for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 366ae14a1d8SMark Rustad command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 367ae14a1d8SMark Rustad if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 368ae14a1d8SMark Rustad break; 369d90b5b0eSMark Rustad udelay(10); 370ae14a1d8SMark Rustad } 371ae14a1d8SMark Rustad if (ctrl) 372ae14a1d8SMark Rustad *ctrl = command; 373ae14a1d8SMark Rustad if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 374ae14a1d8SMark Rustad hw_dbg(hw, "IOSF wait timed out\n"); 375ae14a1d8SMark Rustad return IXGBE_ERR_PHY; 376ae14a1d8SMark Rustad } 377ae14a1d8SMark Rustad 378ae14a1d8SMark Rustad return 0; 379ae14a1d8SMark Rustad } 380ae14a1d8SMark Rustad 3816a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 3826a14ee0cSDon Skidmore * IOSF device 3836a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3846a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 3856a14ee0cSDon Skidmore * @device_type: 3 bit device type 3866a14ee0cSDon Skidmore * @phy_data: Pointer to read data from the register 3876a14ee0cSDon Skidmore **/ 3887ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 3896a14ee0cSDon Skidmore u32 device_type, u32 *data) 3906a14ee0cSDon Skidmore { 391ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 392ae14a1d8SMark Rustad u32 command, error; 393ae14a1d8SMark Rustad s32 ret; 394ae14a1d8SMark Rustad 395ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 396ae14a1d8SMark Rustad if (ret) 397ae14a1d8SMark Rustad return ret; 398ae14a1d8SMark Rustad 399ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 400ae14a1d8SMark Rustad if (ret) 401ae14a1d8SMark Rustad goto out; 4026a14ee0cSDon Skidmore 4036a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 4046a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 4056a14ee0cSDon Skidmore 4066a14ee0cSDon Skidmore /* Write IOSF control register */ 4076a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 4086a14ee0cSDon Skidmore 409ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 4106a14ee0cSDon Skidmore 4116a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 4126a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 4136a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 4146a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read, error %x\n", error); 4156a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 4166a14ee0cSDon Skidmore } 4176a14ee0cSDon Skidmore 418ae14a1d8SMark Rustad if (!ret) 4196a14ee0cSDon Skidmore *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 4206a14ee0cSDon Skidmore 421ae14a1d8SMark Rustad out: 422ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 423ae14a1d8SMark Rustad return ret; 4246a14ee0cSDon Skidmore } 4256a14ee0cSDon Skidmore 42649425dfcSMark Rustad /** 42749425dfcSMark Rustad * ixgbe_get_phy_token - Get the token for shared PHY access 42849425dfcSMark Rustad * @hw: Pointer to hardware structure 42949425dfcSMark Rustad */ 43049425dfcSMark Rustad static s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) 43149425dfcSMark Rustad { 43249425dfcSMark Rustad struct ixgbe_hic_phy_token_req token_cmd; 43349425dfcSMark Rustad s32 status; 43449425dfcSMark Rustad 43549425dfcSMark Rustad token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 43649425dfcSMark Rustad token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 43749425dfcSMark Rustad token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 43849425dfcSMark Rustad token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 43949425dfcSMark Rustad token_cmd.port_number = hw->bus.lan_id; 44049425dfcSMark Rustad token_cmd.command_type = FW_PHY_TOKEN_REQ; 44149425dfcSMark Rustad token_cmd.pad = 0; 44249425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 44349425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 44449425dfcSMark Rustad true); 44549425dfcSMark Rustad if (status) 44649425dfcSMark Rustad return status; 44749425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 44849425dfcSMark Rustad return 0; 44949425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) 45049425dfcSMark Rustad return IXGBE_ERR_FW_RESP_INVALID; 45149425dfcSMark Rustad 45249425dfcSMark Rustad return IXGBE_ERR_TOKEN_RETRY; 45349425dfcSMark Rustad } 45449425dfcSMark Rustad 45549425dfcSMark Rustad /** 45649425dfcSMark Rustad * ixgbe_put_phy_token - Put the token for shared PHY access 45749425dfcSMark Rustad * @hw: Pointer to hardware structure 45849425dfcSMark Rustad */ 45949425dfcSMark Rustad static s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) 46049425dfcSMark Rustad { 46149425dfcSMark Rustad struct ixgbe_hic_phy_token_req token_cmd; 46249425dfcSMark Rustad s32 status; 46349425dfcSMark Rustad 46449425dfcSMark Rustad token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 46549425dfcSMark Rustad token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 46649425dfcSMark Rustad token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 46749425dfcSMark Rustad token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 46849425dfcSMark Rustad token_cmd.port_number = hw->bus.lan_id; 46949425dfcSMark Rustad token_cmd.command_type = FW_PHY_TOKEN_REL; 47049425dfcSMark Rustad token_cmd.pad = 0; 47149425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 47249425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 47349425dfcSMark Rustad true); 47449425dfcSMark Rustad if (status) 47549425dfcSMark Rustad return status; 47649425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 47749425dfcSMark Rustad return 0; 47849425dfcSMark Rustad return IXGBE_ERR_FW_RESP_INVALID; 47949425dfcSMark Rustad } 48049425dfcSMark Rustad 48149425dfcSMark Rustad /** 48249425dfcSMark Rustad * ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register 48349425dfcSMark Rustad * @hw: pointer to hardware structure 48449425dfcSMark Rustad * @reg_addr: 32 bit PHY register to write 48549425dfcSMark Rustad * @device_type: 3 bit device type 48649425dfcSMark Rustad * @data: Data to write to the register 48749425dfcSMark Rustad **/ 48849425dfcSMark Rustad static s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 48949425dfcSMark Rustad __always_unused u32 device_type, 49049425dfcSMark Rustad u32 data) 49149425dfcSMark Rustad { 49249425dfcSMark Rustad struct ixgbe_hic_internal_phy_req write_cmd; 49349425dfcSMark Rustad 49449425dfcSMark Rustad memset(&write_cmd, 0, sizeof(write_cmd)); 49549425dfcSMark Rustad write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 49649425dfcSMark Rustad write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 49749425dfcSMark Rustad write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 49849425dfcSMark Rustad write_cmd.port_number = hw->bus.lan_id; 49949425dfcSMark Rustad write_cmd.command_type = FW_INT_PHY_REQ_WRITE; 50049425dfcSMark Rustad write_cmd.address = cpu_to_be16(reg_addr); 50149425dfcSMark Rustad write_cmd.write_data = cpu_to_be32(data); 50249425dfcSMark Rustad 50349425dfcSMark Rustad return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd), 50449425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, false); 50549425dfcSMark Rustad } 50649425dfcSMark Rustad 50749425dfcSMark Rustad /** 50849425dfcSMark Rustad * ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register 50949425dfcSMark Rustad * @hw: pointer to hardware structure 51049425dfcSMark Rustad * @reg_addr: 32 bit PHY register to write 51149425dfcSMark Rustad * @device_type: 3 bit device type 51249425dfcSMark Rustad * @data: Pointer to read data from the register 51349425dfcSMark Rustad **/ 51449425dfcSMark Rustad static s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 51549425dfcSMark Rustad __always_unused u32 device_type, 51649425dfcSMark Rustad u32 *data) 51749425dfcSMark Rustad { 51849425dfcSMark Rustad union { 51949425dfcSMark Rustad struct ixgbe_hic_internal_phy_req cmd; 52049425dfcSMark Rustad struct ixgbe_hic_internal_phy_resp rsp; 52149425dfcSMark Rustad } hic; 52249425dfcSMark Rustad s32 status; 52349425dfcSMark Rustad 52449425dfcSMark Rustad memset(&hic, 0, sizeof(hic)); 52549425dfcSMark Rustad hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 52649425dfcSMark Rustad hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 52749425dfcSMark Rustad hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 52849425dfcSMark Rustad hic.cmd.port_number = hw->bus.lan_id; 52949425dfcSMark Rustad hic.cmd.command_type = FW_INT_PHY_REQ_READ; 53049425dfcSMark Rustad hic.cmd.address = cpu_to_be16(reg_addr); 53149425dfcSMark Rustad 53249425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 53349425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, true); 53449425dfcSMark Rustad 53549425dfcSMark Rustad /* Extract the register value from the response. */ 53649425dfcSMark Rustad *data = be32_to_cpu(hic.rsp.read_data); 53749425dfcSMark Rustad 53849425dfcSMark Rustad return status; 53949425dfcSMark Rustad } 54049425dfcSMark Rustad 5416a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface 5426a14ee0cSDon Skidmore * command assuming that the semaphore is already obtained. 5436a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5446a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 5456a14ee0cSDon Skidmore * @data: word read from the EEPROM 5466a14ee0cSDon Skidmore * 5476a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 5486a14ee0cSDon Skidmore **/ 5497ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 5507ddbde3fSDon Skidmore u16 *data) 5516a14ee0cSDon Skidmore { 5526a14ee0cSDon Skidmore s32 status; 5536a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 5546a14ee0cSDon Skidmore 5556a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 5566a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 5576a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 5586a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 5596a14ee0cSDon Skidmore 5606a14ee0cSDon Skidmore /* convert offset from words to bytes */ 5616a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 5626a14ee0cSDon Skidmore /* one word */ 5636a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 5646a14ee0cSDon Skidmore 5655cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 5666a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 5676a14ee0cSDon Skidmore if (status) 5686a14ee0cSDon Skidmore return status; 5696a14ee0cSDon Skidmore 5706a14ee0cSDon Skidmore *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 5716a14ee0cSDon Skidmore FW_NVM_DATA_OFFSET); 5726a14ee0cSDon Skidmore 5736a14ee0cSDon Skidmore return 0; 5746a14ee0cSDon Skidmore } 5756a14ee0cSDon Skidmore 5766a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 5776a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5786a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 5796a14ee0cSDon Skidmore * @words: number of words 5806a14ee0cSDon Skidmore * @data: word(s) read from the EEPROM 5816a14ee0cSDon Skidmore * 5826a14ee0cSDon Skidmore * Reads a 16 bit word(s) from the EEPROM using the hostif. 5836a14ee0cSDon Skidmore **/ 5847ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 5856a14ee0cSDon Skidmore u16 offset, u16 words, u16 *data) 5866a14ee0cSDon Skidmore { 5876a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 5886a14ee0cSDon Skidmore u32 current_word = 0; 5896a14ee0cSDon Skidmore u16 words_to_read; 5906a14ee0cSDon Skidmore s32 status; 5916a14ee0cSDon Skidmore u32 i; 5926a14ee0cSDon Skidmore 5936a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 5946a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 5956a14ee0cSDon Skidmore if (status) { 5966a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 5976a14ee0cSDon Skidmore return status; 5986a14ee0cSDon Skidmore } 5996a14ee0cSDon Skidmore 6006a14ee0cSDon Skidmore while (words) { 6016a14ee0cSDon Skidmore if (words > FW_MAX_READ_BUFFER_SIZE / 2) 6026a14ee0cSDon Skidmore words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 6036a14ee0cSDon Skidmore else 6046a14ee0cSDon Skidmore words_to_read = words; 6056a14ee0cSDon Skidmore 6066a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 6076a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 6086a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 6096a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 6106a14ee0cSDon Skidmore 6116a14ee0cSDon Skidmore /* convert offset from words to bytes */ 6126a14ee0cSDon Skidmore buffer.address = cpu_to_be32((offset + current_word) * 2); 6136a14ee0cSDon Skidmore buffer.length = cpu_to_be16(words_to_read * 2); 6146a14ee0cSDon Skidmore 6155cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, 6166a14ee0cSDon Skidmore sizeof(buffer), 6176a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, 6186a14ee0cSDon Skidmore false); 6196a14ee0cSDon Skidmore if (status) { 6206a14ee0cSDon Skidmore hw_dbg(hw, "Host interface command failed\n"); 6216a14ee0cSDon Skidmore goto out; 6226a14ee0cSDon Skidmore } 6236a14ee0cSDon Skidmore 6246a14ee0cSDon Skidmore for (i = 0; i < words_to_read; i++) { 6256a14ee0cSDon Skidmore u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 6266a14ee0cSDon Skidmore 2 * i; 6276a14ee0cSDon Skidmore u32 value = IXGBE_READ_REG(hw, reg); 6286a14ee0cSDon Skidmore 6296a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 6306a14ee0cSDon Skidmore current_word++; 6316a14ee0cSDon Skidmore i++; 6326a14ee0cSDon Skidmore if (i < words_to_read) { 6336a14ee0cSDon Skidmore value >>= 16; 6346a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 6356a14ee0cSDon Skidmore current_word++; 6366a14ee0cSDon Skidmore } 6376a14ee0cSDon Skidmore } 6386a14ee0cSDon Skidmore words -= words_to_read; 6396a14ee0cSDon Skidmore } 6406a14ee0cSDon Skidmore 6416a14ee0cSDon Skidmore out: 6426a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 6436a14ee0cSDon Skidmore return status; 6446a14ee0cSDon Skidmore } 6456a14ee0cSDon Skidmore 6466a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region 6476a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6486a14ee0cSDon Skidmore * @ptr: pointer offset in eeprom 6496a14ee0cSDon Skidmore * @size: size of section pointed by ptr, if 0 first word will be used as size 6506a14ee0cSDon Skidmore * @csum: address of checksum to update 6516a14ee0cSDon Skidmore * 6526a14ee0cSDon Skidmore * Returns error status for any failure 6536a14ee0cSDon Skidmore **/ 6546a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 6556a14ee0cSDon Skidmore u16 size, u16 *csum, u16 *buffer, 6566a14ee0cSDon Skidmore u32 buffer_size) 6576a14ee0cSDon Skidmore { 6586a14ee0cSDon Skidmore u16 buf[256]; 6596a14ee0cSDon Skidmore s32 status; 6606a14ee0cSDon Skidmore u16 length, bufsz, i, start; 6616a14ee0cSDon Skidmore u16 *local_buffer; 6626a14ee0cSDon Skidmore 6636a14ee0cSDon Skidmore bufsz = sizeof(buf) / sizeof(buf[0]); 6646a14ee0cSDon Skidmore 6656a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 6666a14ee0cSDon Skidmore if (!buffer) { 6676a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 6686a14ee0cSDon Skidmore if (status) { 6696a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 6706a14ee0cSDon Skidmore return status; 6716a14ee0cSDon Skidmore } 6726a14ee0cSDon Skidmore local_buffer = buf; 6736a14ee0cSDon Skidmore } else { 6746a14ee0cSDon Skidmore if (buffer_size < ptr) 6756a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 6766a14ee0cSDon Skidmore local_buffer = &buffer[ptr]; 6776a14ee0cSDon Skidmore } 6786a14ee0cSDon Skidmore 6796a14ee0cSDon Skidmore if (size) { 6806a14ee0cSDon Skidmore start = 0; 6816a14ee0cSDon Skidmore length = size; 6826a14ee0cSDon Skidmore } else { 6836a14ee0cSDon Skidmore start = 1; 6846a14ee0cSDon Skidmore length = local_buffer[0]; 6856a14ee0cSDon Skidmore 6866a14ee0cSDon Skidmore /* Skip pointer section if length is invalid. */ 6876a14ee0cSDon Skidmore if (length == 0xFFFF || length == 0 || 6886a14ee0cSDon Skidmore (ptr + length) >= hw->eeprom.word_size) 6896a14ee0cSDon Skidmore return 0; 6906a14ee0cSDon Skidmore } 6916a14ee0cSDon Skidmore 6926a14ee0cSDon Skidmore if (buffer && ((u32)start + (u32)length > buffer_size)) 6936a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 6946a14ee0cSDon Skidmore 6956a14ee0cSDon Skidmore for (i = start; length; i++, length--) { 6966a14ee0cSDon Skidmore if (i == bufsz && !buffer) { 6976a14ee0cSDon Skidmore ptr += bufsz; 6986a14ee0cSDon Skidmore i = 0; 6996a14ee0cSDon Skidmore if (length < bufsz) 7006a14ee0cSDon Skidmore bufsz = length; 7016a14ee0cSDon Skidmore 7026a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 7036a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 7046a14ee0cSDon Skidmore bufsz, buf); 7056a14ee0cSDon Skidmore if (status) { 7066a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 7076a14ee0cSDon Skidmore return status; 7086a14ee0cSDon Skidmore } 7096a14ee0cSDon Skidmore } 7106a14ee0cSDon Skidmore *csum += local_buffer[i]; 7116a14ee0cSDon Skidmore } 7126a14ee0cSDon Skidmore return 0; 7136a14ee0cSDon Skidmore } 7146a14ee0cSDon Skidmore 7156a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 7166a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7176a14ee0cSDon Skidmore * @buffer: pointer to buffer containing calculated checksum 7186a14ee0cSDon Skidmore * @buffer_size: size of buffer 7196a14ee0cSDon Skidmore * 7206a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 7216a14ee0cSDon Skidmore **/ 7227ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 7237ddbde3fSDon Skidmore u32 buffer_size) 7246a14ee0cSDon Skidmore { 7256a14ee0cSDon Skidmore u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 7266a14ee0cSDon Skidmore u16 *local_buffer; 7276a14ee0cSDon Skidmore s32 status; 7286a14ee0cSDon Skidmore u16 checksum = 0; 7296a14ee0cSDon Skidmore u16 pointer, i, size; 7306a14ee0cSDon Skidmore 7316a14ee0cSDon Skidmore hw->eeprom.ops.init_params(hw); 7326a14ee0cSDon Skidmore 7336a14ee0cSDon Skidmore if (!buffer) { 7346a14ee0cSDon Skidmore /* Read pointer area */ 7356a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 7366a14ee0cSDon Skidmore IXGBE_EEPROM_LAST_WORD + 1, 7376a14ee0cSDon Skidmore eeprom_ptrs); 7386a14ee0cSDon Skidmore if (status) { 7396a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 7406a14ee0cSDon Skidmore return status; 7416a14ee0cSDon Skidmore } 7426a14ee0cSDon Skidmore local_buffer = eeprom_ptrs; 7436a14ee0cSDon Skidmore } else { 7446a14ee0cSDon Skidmore if (buffer_size < IXGBE_EEPROM_LAST_WORD) 7456a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 7466a14ee0cSDon Skidmore local_buffer = buffer; 7476a14ee0cSDon Skidmore } 7486a14ee0cSDon Skidmore 7496a14ee0cSDon Skidmore /* For X550 hardware include 0x0-0x41 in the checksum, skip the 7506a14ee0cSDon Skidmore * checksum word itself 7516a14ee0cSDon Skidmore */ 7526a14ee0cSDon Skidmore for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 7536a14ee0cSDon Skidmore if (i != IXGBE_EEPROM_CHECKSUM) 7546a14ee0cSDon Skidmore checksum += local_buffer[i]; 7556a14ee0cSDon Skidmore 7566a14ee0cSDon Skidmore /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 7576a14ee0cSDon Skidmore * FW, PHY module, and PCIe Expansion/Option ROM pointers. 7586a14ee0cSDon Skidmore */ 7596a14ee0cSDon Skidmore for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 7606a14ee0cSDon Skidmore if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 7616a14ee0cSDon Skidmore continue; 7626a14ee0cSDon Skidmore 7636a14ee0cSDon Skidmore pointer = local_buffer[i]; 7646a14ee0cSDon Skidmore 7656a14ee0cSDon Skidmore /* Skip pointer section if the pointer is invalid. */ 7666a14ee0cSDon Skidmore if (pointer == 0xFFFF || pointer == 0 || 7676a14ee0cSDon Skidmore pointer >= hw->eeprom.word_size) 7686a14ee0cSDon Skidmore continue; 7696a14ee0cSDon Skidmore 7706a14ee0cSDon Skidmore switch (i) { 7716a14ee0cSDon Skidmore case IXGBE_PCIE_GENERAL_PTR: 7726a14ee0cSDon Skidmore size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 7736a14ee0cSDon Skidmore break; 7746a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG0_PTR: 7756a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG1_PTR: 7766a14ee0cSDon Skidmore size = IXGBE_PCIE_CONFIG_SIZE; 7776a14ee0cSDon Skidmore break; 7786a14ee0cSDon Skidmore default: 7796a14ee0cSDon Skidmore size = 0; 7806a14ee0cSDon Skidmore break; 7816a14ee0cSDon Skidmore } 7826a14ee0cSDon Skidmore 7836a14ee0cSDon Skidmore status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 7846a14ee0cSDon Skidmore buffer, buffer_size); 7856a14ee0cSDon Skidmore if (status) 7866a14ee0cSDon Skidmore return status; 7876a14ee0cSDon Skidmore } 7886a14ee0cSDon Skidmore 7896a14ee0cSDon Skidmore checksum = (u16)IXGBE_EEPROM_SUM - checksum; 7906a14ee0cSDon Skidmore 7916a14ee0cSDon Skidmore return (s32)checksum; 7926a14ee0cSDon Skidmore } 7936a14ee0cSDon Skidmore 7946a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 7956a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7966a14ee0cSDon Skidmore * 7976a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 7986a14ee0cSDon Skidmore **/ 7997ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 8006a14ee0cSDon Skidmore { 8016a14ee0cSDon Skidmore return ixgbe_calc_checksum_X550(hw, NULL, 0); 8026a14ee0cSDon Skidmore } 8036a14ee0cSDon Skidmore 8046a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 8056a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8066a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 8076a14ee0cSDon Skidmore * @data: word read from the EEPROM 8086a14ee0cSDon Skidmore * 8096a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 8106a14ee0cSDon Skidmore **/ 8117ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 8126a14ee0cSDon Skidmore { 8136a14ee0cSDon Skidmore s32 status = 0; 8146a14ee0cSDon Skidmore 8156a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 8166a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_data_X550(hw, offset, data); 8176a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 8186a14ee0cSDon Skidmore } else { 8196a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 8206a14ee0cSDon Skidmore } 8216a14ee0cSDon Skidmore 8226a14ee0cSDon Skidmore return status; 8236a14ee0cSDon Skidmore } 8246a14ee0cSDon Skidmore 8256a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 8266a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8276a14ee0cSDon Skidmore * @checksum_val: calculated checksum 8286a14ee0cSDon Skidmore * 8296a14ee0cSDon Skidmore * Performs checksum calculation and validates the EEPROM checksum. If the 8306a14ee0cSDon Skidmore * caller does not need checksum_val, the value can be NULL. 8316a14ee0cSDon Skidmore **/ 8327ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 8337ddbde3fSDon Skidmore u16 *checksum_val) 8346a14ee0cSDon Skidmore { 8356a14ee0cSDon Skidmore s32 status; 8366a14ee0cSDon Skidmore u16 checksum; 8376a14ee0cSDon Skidmore u16 read_checksum = 0; 8386a14ee0cSDon Skidmore 8396a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 8406a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 8416a14ee0cSDon Skidmore * EEPROM read fails 8426a14ee0cSDon Skidmore */ 8436a14ee0cSDon Skidmore status = hw->eeprom.ops.read(hw, 0, &checksum); 8446a14ee0cSDon Skidmore if (status) { 8456a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 8466a14ee0cSDon Skidmore return status; 8476a14ee0cSDon Skidmore } 8486a14ee0cSDon Skidmore 8496a14ee0cSDon Skidmore status = hw->eeprom.ops.calc_checksum(hw); 8506a14ee0cSDon Skidmore if (status < 0) 8516a14ee0cSDon Skidmore return status; 8526a14ee0cSDon Skidmore 8536a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 8546a14ee0cSDon Skidmore 8556a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 8566a14ee0cSDon Skidmore &read_checksum); 8576a14ee0cSDon Skidmore if (status) 8586a14ee0cSDon Skidmore return status; 8596a14ee0cSDon Skidmore 8606a14ee0cSDon Skidmore /* Verify read checksum from EEPROM is the same as 8616a14ee0cSDon Skidmore * calculated checksum 8626a14ee0cSDon Skidmore */ 8636a14ee0cSDon Skidmore if (read_checksum != checksum) { 8646a14ee0cSDon Skidmore status = IXGBE_ERR_EEPROM_CHECKSUM; 8656a14ee0cSDon Skidmore hw_dbg(hw, "Invalid EEPROM checksum"); 8666a14ee0cSDon Skidmore } 8676a14ee0cSDon Skidmore 8686a14ee0cSDon Skidmore /* If the user cares, return the calculated checksum */ 8696a14ee0cSDon Skidmore if (checksum_val) 8706a14ee0cSDon Skidmore *checksum_val = checksum; 8716a14ee0cSDon Skidmore 8726a14ee0cSDon Skidmore return status; 8736a14ee0cSDon Skidmore } 8746a14ee0cSDon Skidmore 8756a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 8766a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8776a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 8786a14ee0cSDon Skidmore * @data: word write to the EEPROM 8796a14ee0cSDon Skidmore * 8806a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 8816a14ee0cSDon Skidmore **/ 8827ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 8837ddbde3fSDon Skidmore u16 data) 8846a14ee0cSDon Skidmore { 8856a14ee0cSDon Skidmore s32 status; 8866a14ee0cSDon Skidmore struct ixgbe_hic_write_shadow_ram buffer; 8876a14ee0cSDon Skidmore 8886a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 8896a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 8906a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 8916a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 8926a14ee0cSDon Skidmore 8936a14ee0cSDon Skidmore /* one word */ 8946a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 8956a14ee0cSDon Skidmore buffer.data = data; 8966a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 8976a14ee0cSDon Skidmore 8985cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 8996a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 9006a14ee0cSDon Skidmore return status; 9016a14ee0cSDon Skidmore } 9026a14ee0cSDon Skidmore 9036a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 9046a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9056a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 9066a14ee0cSDon Skidmore * @data: word write to the EEPROM 9076a14ee0cSDon Skidmore * 9086a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 9096a14ee0cSDon Skidmore **/ 9107ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 9116a14ee0cSDon Skidmore { 9126a14ee0cSDon Skidmore s32 status = 0; 9136a14ee0cSDon Skidmore 9146a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 9156a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 9166a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 9176a14ee0cSDon Skidmore } else { 9186a14ee0cSDon Skidmore hw_dbg(hw, "write ee hostif failed to get semaphore"); 9196a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 9206a14ee0cSDon Skidmore } 9216a14ee0cSDon Skidmore 9226a14ee0cSDon Skidmore return status; 9236a14ee0cSDon Skidmore } 9246a14ee0cSDon Skidmore 9256a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 9266a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9276a14ee0cSDon Skidmore * 9286a14ee0cSDon Skidmore * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 9296a14ee0cSDon Skidmore **/ 9307ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 9316a14ee0cSDon Skidmore { 9326a14ee0cSDon Skidmore s32 status = 0; 9336a14ee0cSDon Skidmore union ixgbe_hic_hdr2 buffer; 9346a14ee0cSDon Skidmore 9356a14ee0cSDon Skidmore buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 9366a14ee0cSDon Skidmore buffer.req.buf_lenh = 0; 9376a14ee0cSDon Skidmore buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 9386a14ee0cSDon Skidmore buffer.req.checksum = FW_DEFAULT_CHECKSUM; 9396a14ee0cSDon Skidmore 9405cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 9416a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 9426a14ee0cSDon Skidmore return status; 9436a14ee0cSDon Skidmore } 9446a14ee0cSDon Skidmore 945454c65ddSDon Skidmore /** 946454c65ddSDon Skidmore * ixgbe_get_bus_info_X550em - Set PCI bus info 947454c65ddSDon Skidmore * @hw: pointer to hardware structure 948454c65ddSDon Skidmore * 949454c65ddSDon Skidmore * Sets bus link width and speed to unknown because X550em is 950454c65ddSDon Skidmore * not a PCI device. 951454c65ddSDon Skidmore **/ 952454c65ddSDon Skidmore static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) 953454c65ddSDon Skidmore { 954f9328bc6SDon Skidmore hw->bus.type = ixgbe_bus_type_internal; 955454c65ddSDon Skidmore hw->bus.width = ixgbe_bus_width_unknown; 956454c65ddSDon Skidmore hw->bus.speed = ixgbe_bus_speed_unknown; 957454c65ddSDon Skidmore 958454c65ddSDon Skidmore hw->mac.ops.set_lan_id(hw); 959454c65ddSDon Skidmore 960454c65ddSDon Skidmore return 0; 961454c65ddSDon Skidmore } 962454c65ddSDon Skidmore 9631f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit 9641f9ac57cSDon Skidmore * 9651f9ac57cSDon Skidmore * Enables the Rx DMA unit for x550 9661f9ac57cSDon Skidmore **/ 9671f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 9681f9ac57cSDon Skidmore { 9691f9ac57cSDon Skidmore u32 rxctrl, pfdtxgswc; 9701f9ac57cSDon Skidmore s32 status; 9711f9ac57cSDon Skidmore struct ixgbe_hic_disable_rxen fw_cmd; 9721f9ac57cSDon Skidmore 9731f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 9741f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 9751f9ac57cSDon Skidmore pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 9761f9ac57cSDon Skidmore if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 9771f9ac57cSDon Skidmore pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 9781f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 9791f9ac57cSDon Skidmore hw->mac.set_lben = true; 9801f9ac57cSDon Skidmore } else { 9811f9ac57cSDon Skidmore hw->mac.set_lben = false; 9821f9ac57cSDon Skidmore } 9831f9ac57cSDon Skidmore 9841f9ac57cSDon Skidmore fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 9851f9ac57cSDon Skidmore fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 9861f9ac57cSDon Skidmore fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 9873775b814SMark Rustad fw_cmd.port_number = hw->bus.lan_id; 9881f9ac57cSDon Skidmore 9895cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &fw_cmd, 9901f9ac57cSDon Skidmore sizeof(struct ixgbe_hic_disable_rxen), 9911f9ac57cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, true); 9921f9ac57cSDon Skidmore 9931f9ac57cSDon Skidmore /* If we fail - disable RX using register write */ 9941f9ac57cSDon Skidmore if (status) { 9951f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 9961f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 9971f9ac57cSDon Skidmore rxctrl &= ~IXGBE_RXCTRL_RXEN; 9981f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 9991f9ac57cSDon Skidmore } 10001f9ac57cSDon Skidmore } 10011f9ac57cSDon Skidmore } 10021f9ac57cSDon Skidmore } 10031f9ac57cSDon Skidmore 10046a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 10056a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10066a14ee0cSDon Skidmore * 10076a14ee0cSDon Skidmore * After writing EEPROM to shadow RAM using EEWR register, software calculates 10086a14ee0cSDon Skidmore * checksum and updates the EEPROM and instructs the hardware to update 10096a14ee0cSDon Skidmore * the flash. 10106a14ee0cSDon Skidmore **/ 10117ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 10126a14ee0cSDon Skidmore { 10136a14ee0cSDon Skidmore s32 status; 10146a14ee0cSDon Skidmore u16 checksum = 0; 10156a14ee0cSDon Skidmore 10166a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 10176a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 10186a14ee0cSDon Skidmore * EEPROM read fails 10196a14ee0cSDon Skidmore */ 10206a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 10216a14ee0cSDon Skidmore if (status) { 10226a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 10236a14ee0cSDon Skidmore return status; 10246a14ee0cSDon Skidmore } 10256a14ee0cSDon Skidmore 10266a14ee0cSDon Skidmore status = ixgbe_calc_eeprom_checksum_X550(hw); 10276a14ee0cSDon Skidmore if (status < 0) 10286a14ee0cSDon Skidmore return status; 10296a14ee0cSDon Skidmore 10306a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 10316a14ee0cSDon Skidmore 10326a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 10336a14ee0cSDon Skidmore checksum); 10346a14ee0cSDon Skidmore if (status) 10356a14ee0cSDon Skidmore return status; 10366a14ee0cSDon Skidmore 10376a14ee0cSDon Skidmore status = ixgbe_update_flash_X550(hw); 10386a14ee0cSDon Skidmore 10396a14ee0cSDon Skidmore return status; 10406a14ee0cSDon Skidmore } 10416a14ee0cSDon Skidmore 10426a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 10436a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10446a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 10456a14ee0cSDon Skidmore * @words: number of words 10466a14ee0cSDon Skidmore * @data: word(s) write to the EEPROM 10476a14ee0cSDon Skidmore * 10486a14ee0cSDon Skidmore * 10496a14ee0cSDon Skidmore * Write a 16 bit word(s) to the EEPROM using the hostif. 10506a14ee0cSDon Skidmore **/ 10517ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 10527ddbde3fSDon Skidmore u16 offset, u16 words, 10537ddbde3fSDon Skidmore u16 *data) 10546a14ee0cSDon Skidmore { 10556a14ee0cSDon Skidmore s32 status = 0; 10566a14ee0cSDon Skidmore u32 i = 0; 10576a14ee0cSDon Skidmore 10586a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 10596a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 10606a14ee0cSDon Skidmore if (status) { 10616a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 10626a14ee0cSDon Skidmore return status; 10636a14ee0cSDon Skidmore } 10646a14ee0cSDon Skidmore 10656a14ee0cSDon Skidmore for (i = 0; i < words; i++) { 10666a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 10676a14ee0cSDon Skidmore data[i]); 10686a14ee0cSDon Skidmore if (status) { 10696a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom buffered write failed\n"); 10706a14ee0cSDon Skidmore break; 10716a14ee0cSDon Skidmore } 10726a14ee0cSDon Skidmore } 10736a14ee0cSDon Skidmore 10746a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 10756a14ee0cSDon Skidmore 10766a14ee0cSDon Skidmore return status; 10776a14ee0cSDon Skidmore } 10786a14ee0cSDon Skidmore 10796a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 10806a14ee0cSDon Skidmore * IOSF device 10816a14ee0cSDon Skidmore * 10826a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10836a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 10846a14ee0cSDon Skidmore * @device_type: 3 bit device type 10856a14ee0cSDon Skidmore * @data: Data to write to the register 10866a14ee0cSDon Skidmore **/ 10877ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 10886a14ee0cSDon Skidmore u32 device_type, u32 data) 10896a14ee0cSDon Skidmore { 1090ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 1091ae14a1d8SMark Rustad u32 command, error; 1092ae14a1d8SMark Rustad s32 ret; 1093ae14a1d8SMark Rustad 1094ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 1095ae14a1d8SMark Rustad if (ret) 1096ae14a1d8SMark Rustad return ret; 1097ae14a1d8SMark Rustad 1098ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 1099ae14a1d8SMark Rustad if (ret) 1100ae14a1d8SMark Rustad goto out; 11016a14ee0cSDon Skidmore 11026a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 11036a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 11046a14ee0cSDon Skidmore 11056a14ee0cSDon Skidmore /* Write IOSF control register */ 11066a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 11076a14ee0cSDon Skidmore 11086a14ee0cSDon Skidmore /* Write IOSF data register */ 11096a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 11106a14ee0cSDon Skidmore 1111ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 11126a14ee0cSDon Skidmore 11136a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 11146a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 11156a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 11166a14ee0cSDon Skidmore hw_dbg(hw, "Failed to write, error %x\n", error); 11176a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 11186a14ee0cSDon Skidmore } 11196a14ee0cSDon Skidmore 1120ae14a1d8SMark Rustad out: 1121ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 1122ae14a1d8SMark Rustad return ret; 11236a14ee0cSDon Skidmore } 11246a14ee0cSDon Skidmore 11256a14ee0cSDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 11266a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11276a14ee0cSDon Skidmore * @speed: the link speed to force 11286a14ee0cSDon Skidmore * 11296a14ee0cSDon Skidmore * Configures the integrated KR PHY to use iXFI mode. Used to connect an 11306a14ee0cSDon Skidmore * internal and external PHY at a specific speed, without autonegotiation. 11316a14ee0cSDon Skidmore **/ 11326a14ee0cSDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 11336a14ee0cSDon Skidmore { 11346a14ee0cSDon Skidmore s32 status; 11356a14ee0cSDon Skidmore u32 reg_val; 11366a14ee0cSDon Skidmore 11376a14ee0cSDon Skidmore /* Disable AN and force speed to 10G Serial. */ 11386a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 11396a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 11406a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 11416a14ee0cSDon Skidmore if (status) 11426a14ee0cSDon Skidmore return status; 11436a14ee0cSDon Skidmore 11446a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 11456a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 11466a14ee0cSDon Skidmore 11476a14ee0cSDon Skidmore /* Select forced link speed for internal PHY. */ 11486a14ee0cSDon Skidmore switch (*speed) { 11496a14ee0cSDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 11506a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 11516a14ee0cSDon Skidmore break; 11526a14ee0cSDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 11536a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 11546a14ee0cSDon Skidmore break; 11556a14ee0cSDon Skidmore default: 11566a14ee0cSDon Skidmore /* Other link speeds are not supported by internal KR PHY. */ 11576a14ee0cSDon Skidmore return IXGBE_ERR_LINK_SETUP; 11586a14ee0cSDon Skidmore } 11596a14ee0cSDon Skidmore 11606a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 1161bec4e68eSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 11626a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 11636a14ee0cSDon Skidmore if (status) 11646a14ee0cSDon Skidmore return status; 11656a14ee0cSDon Skidmore 11666a14ee0cSDon Skidmore /* Disable training protocol FSM. */ 11676a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 11686a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 11696a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 11706a14ee0cSDon Skidmore if (status) 11716a14ee0cSDon Skidmore return status; 11726a14ee0cSDon Skidmore 11736a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 11746a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 11756a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 11766a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 11776a14ee0cSDon Skidmore if (status) 11786a14ee0cSDon Skidmore return status; 11796a14ee0cSDon Skidmore 11806a14ee0cSDon Skidmore /* Disable Flex from training TXFFE. */ 11816a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 11826a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 11836a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 11846a14ee0cSDon Skidmore if (status) 11856a14ee0cSDon Skidmore return status; 11866a14ee0cSDon Skidmore 11876a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 11886a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 11896a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 11906a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 11916a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 11926a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 11936a14ee0cSDon Skidmore if (status) 11946a14ee0cSDon Skidmore return status; 11956a14ee0cSDon Skidmore 11966a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 11976a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 11986a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 11996a14ee0cSDon Skidmore if (status) 12006a14ee0cSDon Skidmore return status; 12016a14ee0cSDon Skidmore 12026a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 12036a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 12046a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 12056a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12066a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 12076a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12086a14ee0cSDon Skidmore if (status) 12096a14ee0cSDon Skidmore return status; 12106a14ee0cSDon Skidmore 12116a14ee0cSDon Skidmore /* Enable override for coefficients. */ 12126a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12136a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 12146a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12156a14ee0cSDon Skidmore if (status) 12166a14ee0cSDon Skidmore return status; 12176a14ee0cSDon Skidmore 12186a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 12196a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 12206a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 12216a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 12226a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12236a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 12246a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12256a14ee0cSDon Skidmore if (status) 12266a14ee0cSDon Skidmore return status; 12276a14ee0cSDon Skidmore 12286a14ee0cSDon Skidmore /* Toggle port SW reset by AN reset. */ 12296a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12306a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 12316a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12326a14ee0cSDon Skidmore if (status) 12336a14ee0cSDon Skidmore return status; 12346a14ee0cSDon Skidmore 12356a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 12366a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12376a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 12386a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12396a14ee0cSDon Skidmore 12406a14ee0cSDon Skidmore return status; 12416a14ee0cSDon Skidmore } 12426a14ee0cSDon Skidmore 1243c3dc4c09SDon Skidmore /** 1244e23f3336SMark Rustad * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported 1245e23f3336SMark Rustad * @hw: pointer to hardware structure 1246e23f3336SMark Rustad * @linear: true if SFP module is linear 1247e23f3336SMark Rustad */ 1248e23f3336SMark Rustad static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) 1249e23f3336SMark Rustad { 1250e23f3336SMark Rustad switch (hw->phy.sfp_type) { 1251e23f3336SMark Rustad case ixgbe_sfp_type_not_present: 1252e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_PRESENT; 1253e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core0: 1254e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core1: 1255e23f3336SMark Rustad *linear = true; 1256e23f3336SMark Rustad break; 1257e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core0: 1258e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core1: 1259e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core0: 1260e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core1: 1261e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core0: 1262e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core1: 1263e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core0: 1264e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core1: 1265e23f3336SMark Rustad *linear = false; 1266e23f3336SMark Rustad break; 1267e23f3336SMark Rustad case ixgbe_sfp_type_unknown: 1268e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core0: 1269e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core1: 1270e23f3336SMark Rustad default: 1271e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_SUPPORTED; 1272e23f3336SMark Rustad } 1273e23f3336SMark Rustad 1274e23f3336SMark Rustad return 0; 1275e23f3336SMark Rustad } 1276e23f3336SMark Rustad 1277e23f3336SMark Rustad /** 12786d373a1bSMark Rustad * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. 12796d373a1bSMark Rustad * @hw: pointer to hardware structure 12806d373a1bSMark Rustad * 12816d373a1bSMark Rustad * Configures the extern PHY and the integrated KR PHY for SFP support. 12826d373a1bSMark Rustad */ 12836d373a1bSMark Rustad static s32 12846d373a1bSMark Rustad ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, 12856d373a1bSMark Rustad ixgbe_link_speed speed, 12866d373a1bSMark Rustad __always_unused bool autoneg_wait_to_complete) 12876d373a1bSMark Rustad { 1288e23f3336SMark Rustad s32 status; 1289e23f3336SMark Rustad u16 slice, value; 1290e23f3336SMark Rustad bool setup_linear = false; 1291e23f3336SMark Rustad 1292e23f3336SMark Rustad /* Check if SFP module is supported and linear */ 1293e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 1294e23f3336SMark Rustad 1295e23f3336SMark Rustad /* If no SFP module present, then return success. Return success since 1296e23f3336SMark Rustad * there is no reason to configure CS4227 and SFP not present error is 1297e23f3336SMark Rustad * not accepted in the setup MAC link flow. 1298e23f3336SMark Rustad */ 1299e23f3336SMark Rustad if (status == IXGBE_ERR_SFP_NOT_PRESENT) 1300e23f3336SMark Rustad return 0; 1301e23f3336SMark Rustad 1302e23f3336SMark Rustad if (status) 1303e23f3336SMark Rustad return status; 1304e23f3336SMark Rustad 1305d91e3a7dSMark Rustad if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1306e23f3336SMark Rustad /* Configure CS4227 LINE side to 10G SR. */ 1307e23f3336SMark Rustad slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12); 1308e23f3336SMark Rustad value = IXGBE_CS4227_SPEED_10G; 1309d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1310d91e3a7dSMark Rustad slice, value); 1311d91e3a7dSMark Rustad if (status) 1312d91e3a7dSMark Rustad goto i2c_err; 1313d91e3a7dSMark Rustad 1314d91e3a7dSMark Rustad slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 1315d91e3a7dSMark Rustad value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 1316d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1317d91e3a7dSMark Rustad slice, value); 1318d91e3a7dSMark Rustad if (status) 1319d91e3a7dSMark Rustad goto i2c_err; 1320e23f3336SMark Rustad 1321e23f3336SMark Rustad /* Configure CS4227 for HOST connection rate then type. */ 1322e23f3336SMark Rustad slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12); 1323e23f3336SMark Rustad value = speed & IXGBE_LINK_SPEED_10GB_FULL ? 1324e23f3336SMark Rustad IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; 1325d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1326d91e3a7dSMark Rustad slice, value); 1327d91e3a7dSMark Rustad if (status) 1328d91e3a7dSMark Rustad goto i2c_err; 1329e23f3336SMark Rustad 1330e23f3336SMark Rustad slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12); 1331e23f3336SMark Rustad if (setup_linear) 1332e23f3336SMark Rustad value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 1333e23f3336SMark Rustad else 1334e23f3336SMark Rustad value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 1335d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1336d91e3a7dSMark Rustad slice, value); 1337d91e3a7dSMark Rustad if (status) 1338d91e3a7dSMark Rustad goto i2c_err; 1339e23f3336SMark Rustad 1340d91e3a7dSMark Rustad /* Setup XFI internal link. */ 1341e23f3336SMark Rustad status = ixgbe_setup_ixfi_x550em(hw, &speed); 1342d91e3a7dSMark Rustad if (status) { 1343d91e3a7dSMark Rustad hw_dbg(hw, "setup_ixfi failed with %d\n", status); 1344d91e3a7dSMark Rustad return status; 1345d91e3a7dSMark Rustad } 1346d91e3a7dSMark Rustad } else { 1347d91e3a7dSMark Rustad /* Configure internal PHY for KR/KX. */ 1348d91e3a7dSMark Rustad status = ixgbe_setup_kr_speed_x550em(hw, speed); 1349d91e3a7dSMark Rustad if (status) { 1350d91e3a7dSMark Rustad hw_dbg(hw, "setup_kr_speed failed with %d\n", status); 1351d91e3a7dSMark Rustad return status; 1352d91e3a7dSMark Rustad } 1353e23f3336SMark Rustad 1354d91e3a7dSMark Rustad /* Configure CS4227 LINE side to proper mode. */ 1355d91e3a7dSMark Rustad slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 1356d91e3a7dSMark Rustad if (setup_linear) 1357d91e3a7dSMark Rustad value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 1358d91e3a7dSMark Rustad else 1359d91e3a7dSMark Rustad value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 1360d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1361d91e3a7dSMark Rustad slice, value); 1362d91e3a7dSMark Rustad if (status) 1363d91e3a7dSMark Rustad goto i2c_err; 1364d91e3a7dSMark Rustad } 1365d91e3a7dSMark Rustad 1366d91e3a7dSMark Rustad return 0; 1367d91e3a7dSMark Rustad 1368d91e3a7dSMark Rustad i2c_err: 1369d91e3a7dSMark Rustad hw_dbg(hw, "combined i2c access failed with %d\n", status); 1370e23f3336SMark Rustad return status; 13716d373a1bSMark Rustad } 13726d373a1bSMark Rustad 13736d373a1bSMark Rustad /** 13742d40cd17SMark Rustad * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP 13752d40cd17SMark Rustad * @hw: pointer to hardware structure 13762d40cd17SMark Rustad * 13772d40cd17SMark Rustad * Configure the the integrated PHY for native SFP support. 13782d40cd17SMark Rustad */ 13792d40cd17SMark Rustad static s32 13802d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, 13812d40cd17SMark Rustad __always_unused bool autoneg_wait_to_complete) 13822d40cd17SMark Rustad { 13832d40cd17SMark Rustad bool setup_linear = false; 13842d40cd17SMark Rustad u32 reg_phy_int; 13852d40cd17SMark Rustad s32 rc; 13862d40cd17SMark Rustad 13872d40cd17SMark Rustad /* Check if SFP module is supported and linear */ 13882d40cd17SMark Rustad rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 13892d40cd17SMark Rustad 13902d40cd17SMark Rustad /* If no SFP module present, then return success. Return success since 13912d40cd17SMark Rustad * SFP not present error is not excepted in the setup MAC link flow. 13922d40cd17SMark Rustad */ 13932d40cd17SMark Rustad if (rc == IXGBE_ERR_SFP_NOT_PRESENT) 13942d40cd17SMark Rustad return 0; 13952d40cd17SMark Rustad 13962d40cd17SMark Rustad if (!rc) 13972d40cd17SMark Rustad return rc; 13982d40cd17SMark Rustad 13992d40cd17SMark Rustad /* Configure internal PHY for native SFI */ 14002d40cd17SMark Rustad rc = hw->mac.ops.read_iosf_sb_reg(hw, 14012d40cd17SMark Rustad IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), 14022d40cd17SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 14032d40cd17SMark Rustad ®_phy_int); 14042d40cd17SMark Rustad if (rc) 14052d40cd17SMark Rustad return rc; 14062d40cd17SMark Rustad 14072d40cd17SMark Rustad if (setup_linear) { 14082d40cd17SMark Rustad reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING; 14092d40cd17SMark Rustad reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR; 14102d40cd17SMark Rustad } else { 14112d40cd17SMark Rustad reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING; 14122d40cd17SMark Rustad reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR; 14132d40cd17SMark Rustad } 14142d40cd17SMark Rustad 14152d40cd17SMark Rustad rc = hw->mac.ops.write_iosf_sb_reg(hw, 14162d40cd17SMark Rustad IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), 14172d40cd17SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 14182d40cd17SMark Rustad reg_phy_int); 14192d40cd17SMark Rustad if (rc) 14202d40cd17SMark Rustad return rc; 14212d40cd17SMark Rustad 14222d40cd17SMark Rustad /* Setup XFI/SFI internal link */ 14232d40cd17SMark Rustad return ixgbe_setup_ixfi_x550em(hw, &speed); 14242d40cd17SMark Rustad } 14252d40cd17SMark Rustad 14262d40cd17SMark Rustad /** 14272d40cd17SMark Rustad * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP 14282d40cd17SMark Rustad * @hw: pointer to hardware structure 14292d40cd17SMark Rustad * 14302d40cd17SMark Rustad * Configure the the integrated PHY for SFP support. 14312d40cd17SMark Rustad */ 14322d40cd17SMark Rustad static s32 14332d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, 14342d40cd17SMark Rustad __always_unused bool autoneg_wait_to_complete) 14352d40cd17SMark Rustad { 14362d40cd17SMark Rustad u32 reg_slice, slice_offset; 14372d40cd17SMark Rustad bool setup_linear = false; 14382d40cd17SMark Rustad u16 reg_phy_ext; 14392d40cd17SMark Rustad s32 rc; 14402d40cd17SMark Rustad 14412d40cd17SMark Rustad /* Check if SFP module is supported and linear */ 14422d40cd17SMark Rustad rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 14432d40cd17SMark Rustad 14442d40cd17SMark Rustad /* If no SFP module present, then return success. Return success since 14452d40cd17SMark Rustad * SFP not present error is not excepted in the setup MAC link flow. 14462d40cd17SMark Rustad */ 14472d40cd17SMark Rustad if (rc == IXGBE_ERR_SFP_NOT_PRESENT) 14482d40cd17SMark Rustad return 0; 14492d40cd17SMark Rustad 14502d40cd17SMark Rustad if (!rc) 14512d40cd17SMark Rustad return rc; 14522d40cd17SMark Rustad 14532d40cd17SMark Rustad /* Configure internal PHY for KR/KX. */ 14542d40cd17SMark Rustad ixgbe_setup_kr_speed_x550em(hw, speed); 14552d40cd17SMark Rustad 14562d40cd17SMark Rustad if (!hw->phy.mdio.prtad || hw->phy.mdio.prtad == 0xFFFF) 14572d40cd17SMark Rustad return IXGBE_ERR_PHY_ADDR_INVALID; 14582d40cd17SMark Rustad 14592d40cd17SMark Rustad /* Get external PHY device id */ 14602d40cd17SMark Rustad rc = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, 14612d40cd17SMark Rustad IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 14622d40cd17SMark Rustad if (rc) 14632d40cd17SMark Rustad return rc; 14642d40cd17SMark Rustad 14652d40cd17SMark Rustad /* When configuring quad port CS4223, the MAC instance is part 14662d40cd17SMark Rustad * of the slice offset. 14672d40cd17SMark Rustad */ 14682d40cd17SMark Rustad if (reg_phy_ext == IXGBE_CS4223_PHY_ID) 14692d40cd17SMark Rustad slice_offset = (hw->bus.lan_id + 14702d40cd17SMark Rustad (hw->bus.instance_id << 1)) << 12; 14712d40cd17SMark Rustad else 14722d40cd17SMark Rustad slice_offset = hw->bus.lan_id << 12; 14732d40cd17SMark Rustad 14742d40cd17SMark Rustad /* Configure CS4227/CS4223 LINE side to proper mode. */ 14752d40cd17SMark Rustad reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; 14762d40cd17SMark Rustad if (setup_linear) 14772d40cd17SMark Rustad reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 14782d40cd17SMark Rustad else 14792d40cd17SMark Rustad reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 14802d40cd17SMark Rustad return hw->phy.ops.write_reg(hw, reg_slice, IXGBE_MDIO_ZERO_DEV_TYPE, 14812d40cd17SMark Rustad reg_phy_ext); 14822d40cd17SMark Rustad } 14832d40cd17SMark Rustad 14842d40cd17SMark Rustad /** 1485c3dc4c09SDon Skidmore * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 1486c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1487c3dc4c09SDon Skidmore * @speed: new link speed 1488c3dc4c09SDon Skidmore * @autoneg_wait_to_complete: true when waiting for completion is needed 1489c3dc4c09SDon Skidmore * 1490c3dc4c09SDon Skidmore * Setup internal/external PHY link speed based on link speed, then set 1491c3dc4c09SDon Skidmore * external PHY auto advertised link speed. 1492c3dc4c09SDon Skidmore * 1493c3dc4c09SDon Skidmore * Returns error status for any failure 1494c3dc4c09SDon Skidmore **/ 1495c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 1496c3dc4c09SDon Skidmore ixgbe_link_speed speed, 1497c3dc4c09SDon Skidmore bool autoneg_wait) 1498c3dc4c09SDon Skidmore { 1499c3dc4c09SDon Skidmore s32 status; 1500c3dc4c09SDon Skidmore ixgbe_link_speed force_speed; 1501c3dc4c09SDon Skidmore 1502c3dc4c09SDon Skidmore /* Setup internal/external PHY link speed to iXFI (10G), unless 1503c3dc4c09SDon Skidmore * only 1G is auto advertised then setup KX link. 1504c3dc4c09SDon Skidmore */ 1505c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1506c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 1507c3dc4c09SDon Skidmore else 1508c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 1509c3dc4c09SDon Skidmore 1510c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup XFI internal link. */ 1511c3dc4c09SDon Skidmore if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1512c3dc4c09SDon Skidmore status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 1513c3dc4c09SDon Skidmore 1514c3dc4c09SDon Skidmore if (status) 1515c3dc4c09SDon Skidmore return status; 1516c3dc4c09SDon Skidmore } 1517c3dc4c09SDon Skidmore 1518c3dc4c09SDon Skidmore return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 1519c3dc4c09SDon Skidmore } 1520c3dc4c09SDon Skidmore 1521a4e293a5SDon Skidmore /** ixgbe_check_link_t_X550em - Determine link and speed status 1522a4e293a5SDon Skidmore * @hw: pointer to hardware structure 1523a4e293a5SDon Skidmore * @speed: pointer to link speed 1524a4e293a5SDon Skidmore * @link_up: true when link is up 1525a4e293a5SDon Skidmore * @link_up_wait_to_complete: bool used to wait for link up or not 1526a4e293a5SDon Skidmore * 1527a4e293a5SDon Skidmore * Check that both the MAC and X557 external PHY have link. 1528a4e293a5SDon Skidmore **/ 1529a4e293a5SDon Skidmore static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, 1530a4e293a5SDon Skidmore ixgbe_link_speed *speed, 1531a4e293a5SDon Skidmore bool *link_up, 1532a4e293a5SDon Skidmore bool link_up_wait_to_complete) 1533a4e293a5SDon Skidmore { 1534a4e293a5SDon Skidmore u32 status; 1535a4e293a5SDon Skidmore u16 autoneg_status; 1536a4e293a5SDon Skidmore 1537a4e293a5SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 1538a4e293a5SDon Skidmore return IXGBE_ERR_CONFIG; 1539a4e293a5SDon Skidmore 1540a4e293a5SDon Skidmore status = ixgbe_check_mac_link_generic(hw, speed, link_up, 1541a4e293a5SDon Skidmore link_up_wait_to_complete); 1542a4e293a5SDon Skidmore 1543a4e293a5SDon Skidmore /* If check link fails or MAC link is not up, then return */ 1544a4e293a5SDon Skidmore if (status || !(*link_up)) 1545a4e293a5SDon Skidmore return status; 1546a4e293a5SDon Skidmore 1547a4e293a5SDon Skidmore /* MAC link is up, so check external PHY link. 1548a4e293a5SDon Skidmore * Read this twice back to back to indicate current status. 1549a4e293a5SDon Skidmore */ 1550a4e293a5SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 1551a4e293a5SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 1552a4e293a5SDon Skidmore &autoneg_status); 1553a4e293a5SDon Skidmore if (status) 1554a4e293a5SDon Skidmore return status; 1555a4e293a5SDon Skidmore 1556a4e293a5SDon Skidmore /* If external PHY link is not up, then indicate link not up */ 1557a4e293a5SDon Skidmore if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 1558a4e293a5SDon Skidmore *link_up = false; 1559a4e293a5SDon Skidmore 1560a4e293a5SDon Skidmore return 0; 1561a4e293a5SDon Skidmore } 1562a4e293a5SDon Skidmore 1563200157c2SMark Rustad /** 1564200157c2SMark Rustad * ixgbe_setup_sgmii - Set up link for sgmii 1565200157c2SMark Rustad * @hw: pointer to hardware structure 1566200157c2SMark Rustad */ 1567200157c2SMark Rustad static s32 1568200157c2SMark Rustad ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, 1569200157c2SMark Rustad __always_unused bool autoneg_wait_to_complete) 1570200157c2SMark Rustad { 1571200157c2SMark Rustad struct ixgbe_mac_info *mac = &hw->mac; 1572200157c2SMark Rustad u32 lval, sval; 1573200157c2SMark Rustad s32 rc; 1574200157c2SMark Rustad 1575200157c2SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 1576200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1577200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 1578200157c2SMark Rustad if (rc) 1579200157c2SMark Rustad return rc; 1580200157c2SMark Rustad 1581200157c2SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1582200157c2SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 1583200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 1584200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 1585200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 1586200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1587200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1588200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1589200157c2SMark Rustad if (rc) 1590200157c2SMark Rustad return rc; 1591200157c2SMark Rustad 1592200157c2SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 1593200157c2SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1594200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 1595200157c2SMark Rustad if (rc) 1596200157c2SMark Rustad return rc; 1597200157c2SMark Rustad 1598200157c2SMark Rustad sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 1599200157c2SMark Rustad sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 1600200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1601200157c2SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1602200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 1603200157c2SMark Rustad if (rc) 1604200157c2SMark Rustad return rc; 1605200157c2SMark Rustad 1606200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 1607200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1608200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1609200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1610200157c2SMark Rustad 1611200157c2SMark Rustad return rc; 1612200157c2SMark Rustad } 1613200157c2SMark Rustad 1614c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 1615c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1616c3dc4c09SDon Skidmore **/ 1617c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 1618c3dc4c09SDon Skidmore { 1619c3dc4c09SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 1620c3dc4c09SDon Skidmore 1621c3dc4c09SDon Skidmore switch (mac->ops.get_media_type(hw)) { 1622c3dc4c09SDon Skidmore case ixgbe_media_type_fiber: 1623c3dc4c09SDon Skidmore /* CS4227 does not support autoneg, so disable the laser control 1624c3dc4c09SDon Skidmore * functions for SFP+ fiber 1625c3dc4c09SDon Skidmore */ 1626c3dc4c09SDon Skidmore mac->ops.disable_tx_laser = NULL; 1627c3dc4c09SDon Skidmore mac->ops.enable_tx_laser = NULL; 1628c3dc4c09SDon Skidmore mac->ops.flap_tx_laser = NULL; 16296d373a1bSMark Rustad mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; 1630afdc71e4SMark Rustad mac->ops.setup_fc = ixgbe_setup_fc_x550em; 16312d40cd17SMark Rustad switch (hw->device_id) { 16322d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 16332d40cd17SMark Rustad mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; 16342d40cd17SMark Rustad break; 16352d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 16362d40cd17SMark Rustad mac->ops.setup_mac_link = 16372d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a; 16382d40cd17SMark Rustad break; 16392d40cd17SMark Rustad default: 16402d40cd17SMark Rustad mac->ops.setup_mac_link = 16412d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550em; 16422d40cd17SMark Rustad break; 16432d40cd17SMark Rustad } 16446d373a1bSMark Rustad mac->ops.set_rate_select_speed = 16456d373a1bSMark Rustad ixgbe_set_soft_rate_select_speed; 1646c3dc4c09SDon Skidmore break; 1647c3dc4c09SDon Skidmore case ixgbe_media_type_copper: 1648c3dc4c09SDon Skidmore mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 1649afdc71e4SMark Rustad mac->ops.setup_fc = ixgbe_setup_fc_generic; 1650a4e293a5SDon Skidmore mac->ops.check_link = ixgbe_check_link_t_X550em; 165149425dfcSMark Rustad return; 165249425dfcSMark Rustad case ixgbe_media_type_backplane: 1653200157c2SMark Rustad if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || 1654200157c2SMark Rustad hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) 1655200157c2SMark Rustad mac->ops.setup_link = ixgbe_setup_sgmii; 1656c3dc4c09SDon Skidmore break; 1657c3dc4c09SDon Skidmore default: 1658afdc71e4SMark Rustad mac->ops.setup_fc = ixgbe_setup_fc_x550em; 1659c3dc4c09SDon Skidmore break; 1660c3dc4c09SDon Skidmore } 1661c3dc4c09SDon Skidmore } 1662c3dc4c09SDon Skidmore 1663c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module 1664c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1665c3dc4c09SDon Skidmore */ 1666c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 1667c3dc4c09SDon Skidmore { 1668e23f3336SMark Rustad s32 status; 1669e23f3336SMark Rustad bool linear; 1670c3dc4c09SDon Skidmore 1671e23f3336SMark Rustad /* Check if SFP module is supported */ 1672e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &linear); 1673e23f3336SMark Rustad if (status) 1674e23f3336SMark Rustad return status; 1675c3dc4c09SDon Skidmore 1676c3dc4c09SDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 1677c3dc4c09SDon Skidmore hw->phy.ops.reset = NULL; 1678c3dc4c09SDon Skidmore 1679e23f3336SMark Rustad return 0; 1680c3dc4c09SDon Skidmore } 1681c3dc4c09SDon Skidmore 1682c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities 1683c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1684c3dc4c09SDon Skidmore * @speed: pointer to link speed 1685c3dc4c09SDon Skidmore * @autoneg: true when autoneg or autotry is enabled 1686c3dc4c09SDon Skidmore **/ 1687c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 1688c3dc4c09SDon Skidmore ixgbe_link_speed *speed, 1689c3dc4c09SDon Skidmore bool *autoneg) 1690c3dc4c09SDon Skidmore { 1691c3dc4c09SDon Skidmore /* SFP */ 1692c3dc4c09SDon Skidmore if (hw->phy.media_type == ixgbe_media_type_fiber) { 1693c3dc4c09SDon Skidmore /* CS4227 SFP must not enable auto-negotiation */ 1694c3dc4c09SDon Skidmore *autoneg = false; 1695c3dc4c09SDon Skidmore 1696c3dc4c09SDon Skidmore if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 1697c3dc4c09SDon Skidmore hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { 1698c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 1699c3dc4c09SDon Skidmore return 0; 1700c3dc4c09SDon Skidmore } 1701c3dc4c09SDon Skidmore 1702c3dc4c09SDon Skidmore /* Link capabilities are based on SFP */ 1703c3dc4c09SDon Skidmore if (hw->phy.multispeed_fiber) 1704c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1705c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1706c3dc4c09SDon Skidmore else 1707c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL; 1708c3dc4c09SDon Skidmore } else { 1709c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1710c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1711c3dc4c09SDon Skidmore *autoneg = true; 1712c3dc4c09SDon Skidmore } 1713c3dc4c09SDon Skidmore return 0; 1714c3dc4c09SDon Skidmore } 1715c3dc4c09SDon Skidmore 1716c3dc4c09SDon Skidmore /** 1717c3dc4c09SDon Skidmore * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause 1718c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1719c3dc4c09SDon Skidmore * @lsc: pointer to boolean flag which indicates whether external Base T 1720c3dc4c09SDon Skidmore * PHY interrupt is lsc 1721c3dc4c09SDon Skidmore * 1722c3dc4c09SDon Skidmore * Determime if external Base T PHY interrupt cause is high temperature 1723c3dc4c09SDon Skidmore * failure alarm or link status change. 1724c3dc4c09SDon Skidmore * 1725c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1726c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1727c3dc4c09SDon Skidmore **/ 1728c3dc4c09SDon Skidmore static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) 1729c3dc4c09SDon Skidmore { 1730c3dc4c09SDon Skidmore u32 status; 1731c3dc4c09SDon Skidmore u16 reg; 1732c3dc4c09SDon Skidmore 1733c3dc4c09SDon Skidmore *lsc = false; 1734c3dc4c09SDon Skidmore 1735c3dc4c09SDon Skidmore /* Vendor alarm triggered */ 1736c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 1737c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1738c3dc4c09SDon Skidmore ®); 1739c3dc4c09SDon Skidmore 1740c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 1741c3dc4c09SDon Skidmore return status; 1742c3dc4c09SDon Skidmore 1743c3dc4c09SDon Skidmore /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 1744c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 1745c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1746c3dc4c09SDon Skidmore ®); 1747c3dc4c09SDon Skidmore 1748c3dc4c09SDon Skidmore if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1749c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 1750c3dc4c09SDon Skidmore return status; 1751c3dc4c09SDon Skidmore 175283a9fb20SMark Rustad /* Global alarm triggered */ 1753c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 1754c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1755c3dc4c09SDon Skidmore ®); 1756c3dc4c09SDon Skidmore 1757c3dc4c09SDon Skidmore if (status) 1758c3dc4c09SDon Skidmore return status; 1759c3dc4c09SDon Skidmore 1760c3dc4c09SDon Skidmore /* If high temperature failure, then return over temp error and exit */ 1761c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 1762c3dc4c09SDon Skidmore /* power down the PHY in case the PHY FW didn't already */ 1763c3dc4c09SDon Skidmore ixgbe_set_copper_phy_power(hw, false); 1764c3dc4c09SDon Skidmore return IXGBE_ERR_OVERTEMP; 1765c3dc4c09SDon Skidmore } 176683a9fb20SMark Rustad if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { 176783a9fb20SMark Rustad /* device fault alarm triggered */ 176883a9fb20SMark Rustad status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, 176983a9fb20SMark Rustad IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 177083a9fb20SMark Rustad ®); 177183a9fb20SMark Rustad if (status) 177283a9fb20SMark Rustad return status; 177383a9fb20SMark Rustad 177483a9fb20SMark Rustad /* if device fault was due to high temp alarm handle and exit */ 177583a9fb20SMark Rustad if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { 177683a9fb20SMark Rustad /* power down the PHY in case the PHY FW didn't */ 177783a9fb20SMark Rustad ixgbe_set_copper_phy_power(hw, false); 177883a9fb20SMark Rustad return IXGBE_ERR_OVERTEMP; 177983a9fb20SMark Rustad } 178083a9fb20SMark Rustad } 1781c3dc4c09SDon Skidmore 1782c3dc4c09SDon Skidmore /* Vendor alarm 2 triggered */ 1783c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 1784c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1785c3dc4c09SDon Skidmore 1786c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 1787c3dc4c09SDon Skidmore return status; 1788c3dc4c09SDon Skidmore 1789c3dc4c09SDon Skidmore /* link connect/disconnect event occurred */ 1790c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 1791c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1792c3dc4c09SDon Skidmore 1793c3dc4c09SDon Skidmore if (status) 1794c3dc4c09SDon Skidmore return status; 1795c3dc4c09SDon Skidmore 1796c3dc4c09SDon Skidmore /* Indicate LSC */ 1797c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 1798c3dc4c09SDon Skidmore *lsc = true; 1799c3dc4c09SDon Skidmore 1800c3dc4c09SDon Skidmore return 0; 1801c3dc4c09SDon Skidmore } 1802c3dc4c09SDon Skidmore 1803c3dc4c09SDon Skidmore /** 1804c3dc4c09SDon Skidmore * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 1805c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1806c3dc4c09SDon Skidmore * 1807c3dc4c09SDon Skidmore * Enable link status change and temperature failure alarm for the external 1808c3dc4c09SDon Skidmore * Base T PHY 1809c3dc4c09SDon Skidmore * 1810c3dc4c09SDon Skidmore * Returns PHY access status 1811c3dc4c09SDon Skidmore **/ 1812c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1813c3dc4c09SDon Skidmore { 1814c3dc4c09SDon Skidmore u32 status; 1815c3dc4c09SDon Skidmore u16 reg; 1816c3dc4c09SDon Skidmore bool lsc; 1817c3dc4c09SDon Skidmore 1818c3dc4c09SDon Skidmore /* Clear interrupt flags */ 1819c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1820c3dc4c09SDon Skidmore 1821c3dc4c09SDon Skidmore /* Enable link status change alarm */ 1822c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 1823c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1824c3dc4c09SDon Skidmore if (status) 1825c3dc4c09SDon Skidmore return status; 1826c3dc4c09SDon Skidmore 1827c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 1828c3dc4c09SDon Skidmore 1829c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 1830c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); 1831c3dc4c09SDon Skidmore if (status) 1832c3dc4c09SDon Skidmore return status; 1833c3dc4c09SDon Skidmore 183483a9fb20SMark Rustad /* Enable high temperature failure and global fault alarms */ 1835c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 1836c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1837c3dc4c09SDon Skidmore ®); 1838c3dc4c09SDon Skidmore if (status) 1839c3dc4c09SDon Skidmore return status; 1840c3dc4c09SDon Skidmore 184183a9fb20SMark Rustad reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | 184283a9fb20SMark Rustad IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); 1843c3dc4c09SDon Skidmore 1844c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 1845c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1846c3dc4c09SDon Skidmore reg); 1847c3dc4c09SDon Skidmore if (status) 1848c3dc4c09SDon Skidmore return status; 1849c3dc4c09SDon Skidmore 1850c3dc4c09SDon Skidmore /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 1851c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 1852c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1853c3dc4c09SDon Skidmore ®); 1854c3dc4c09SDon Skidmore if (status) 1855c3dc4c09SDon Skidmore return status; 1856c3dc4c09SDon Skidmore 1857c3dc4c09SDon Skidmore reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1858c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT); 1859c3dc4c09SDon Skidmore 1860c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 1861c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1862c3dc4c09SDon Skidmore reg); 1863c3dc4c09SDon Skidmore if (status) 1864c3dc4c09SDon Skidmore return status; 1865c3dc4c09SDon Skidmore 1866c3dc4c09SDon Skidmore /* Enable chip-wide vendor alarm */ 1867c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 1868c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1869c3dc4c09SDon Skidmore ®); 1870c3dc4c09SDon Skidmore if (status) 1871c3dc4c09SDon Skidmore return status; 1872c3dc4c09SDon Skidmore 1873c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 1874c3dc4c09SDon Skidmore 1875c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 1876c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1877c3dc4c09SDon Skidmore reg); 1878c3dc4c09SDon Skidmore 1879c3dc4c09SDon Skidmore return status; 1880c3dc4c09SDon Skidmore } 1881c3dc4c09SDon Skidmore 1882c3dc4c09SDon Skidmore /** 1883c3dc4c09SDon Skidmore * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 1884c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1885c3dc4c09SDon Skidmore * 1886c3dc4c09SDon Skidmore * Handle external Base T PHY interrupt. If high temperature 1887c3dc4c09SDon Skidmore * failure alarm then return error, else if link status change 1888c3dc4c09SDon Skidmore * then setup internal/external PHY link 1889c3dc4c09SDon Skidmore * 1890c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1891c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1892c3dc4c09SDon Skidmore **/ 1893c3dc4c09SDon Skidmore static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1894c3dc4c09SDon Skidmore { 1895c3dc4c09SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 1896c3dc4c09SDon Skidmore bool lsc; 1897c3dc4c09SDon Skidmore u32 status; 1898c3dc4c09SDon Skidmore 1899c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1900c3dc4c09SDon Skidmore if (status) 1901c3dc4c09SDon Skidmore return status; 1902c3dc4c09SDon Skidmore 1903a85ce532SMark Rustad if (lsc && phy->ops.setup_internal_link) 1904c3dc4c09SDon Skidmore return phy->ops.setup_internal_link(hw); 1905c3dc4c09SDon Skidmore 1906c3dc4c09SDon Skidmore return 0; 1907c3dc4c09SDon Skidmore } 1908c3dc4c09SDon Skidmore 1909c3dc4c09SDon Skidmore /** 1910c3dc4c09SDon Skidmore * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 1911c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1912c3dc4c09SDon Skidmore * @speed: link speed 1913c3dc4c09SDon Skidmore * 1914c3dc4c09SDon Skidmore * Configures the integrated KR PHY. 1915c3dc4c09SDon Skidmore **/ 1916c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 1917c3dc4c09SDon Skidmore ixgbe_link_speed speed) 1918c3dc4c09SDon Skidmore { 1919c3dc4c09SDon Skidmore s32 status; 1920c3dc4c09SDon Skidmore u32 reg_val; 1921c3dc4c09SDon Skidmore 19229a5c27e6SMark Rustad status = hw->mac.ops.read_iosf_sb_reg(hw, 1923c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1924c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 1925c3dc4c09SDon Skidmore if (status) 1926c3dc4c09SDon Skidmore return status; 1927c3dc4c09SDon Skidmore 1928c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1929c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ | 1930c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC); 1931c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 1932c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 1933c3dc4c09SDon Skidmore 1934c3dc4c09SDon Skidmore /* Advertise 10G support. */ 1935c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1936c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 1937c3dc4c09SDon Skidmore 1938c3dc4c09SDon Skidmore /* Advertise 1G support. */ 1939c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_1GB_FULL) 1940c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 1941c3dc4c09SDon Skidmore 1942c3dc4c09SDon Skidmore /* Restart auto-negotiation. */ 1943c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 19449a5c27e6SMark Rustad status = hw->mac.ops.write_iosf_sb_reg(hw, 1945c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1946c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 1947c3dc4c09SDon Skidmore 1948c3dc4c09SDon Skidmore return status; 1949c3dc4c09SDon Skidmore } 1950c3dc4c09SDon Skidmore 19516a14ee0cSDon Skidmore /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. 19526a14ee0cSDon Skidmore * @hw: pointer to hardware structure 19536a14ee0cSDon Skidmore * 19546a14ee0cSDon Skidmore * Configures the integrated KX4 PHY. 19556a14ee0cSDon Skidmore **/ 19567ddbde3fSDon Skidmore static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) 19576a14ee0cSDon Skidmore { 19586a14ee0cSDon Skidmore s32 status; 19596a14ee0cSDon Skidmore u32 reg_val; 19606a14ee0cSDon Skidmore 19619a5c27e6SMark Rustad status = hw->mac.ops.read_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, 19626a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 19636a14ee0cSDon Skidmore hw->bus.lan_id, ®_val); 19646a14ee0cSDon Skidmore if (status) 19656a14ee0cSDon Skidmore return status; 19666a14ee0cSDon Skidmore 19676a14ee0cSDon Skidmore reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | 19686a14ee0cSDon Skidmore IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); 19696a14ee0cSDon Skidmore 19706a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; 19716a14ee0cSDon Skidmore 19726a14ee0cSDon Skidmore /* Advertise 10G support. */ 19736a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) 19746a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; 19756a14ee0cSDon Skidmore 19766a14ee0cSDon Skidmore /* Advertise 1G support. */ 19776a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) 19786a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; 19796a14ee0cSDon Skidmore 19806a14ee0cSDon Skidmore /* Restart auto-negotiation. */ 19816a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; 19829a5c27e6SMark Rustad status = hw->mac.ops.write_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, 19836a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 19846a14ee0cSDon Skidmore hw->bus.lan_id, reg_val); 19856a14ee0cSDon Skidmore 19866a14ee0cSDon Skidmore return status; 19876a14ee0cSDon Skidmore } 19886a14ee0cSDon Skidmore 1989f572b2c4SMark Rustad /** 1990f572b2c4SMark Rustad * ixgbe_setup_kr_x550em - Configure the KR PHY 19916a14ee0cSDon Skidmore * @hw: pointer to hardware structure 19926a14ee0cSDon Skidmore * 1993f572b2c4SMark Rustad * Configures the integrated KR PHY for X550EM_x. 19946a14ee0cSDon Skidmore **/ 19957ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 19966a14ee0cSDon Skidmore { 1997f572b2c4SMark Rustad if (hw->mac.type != ixgbe_mac_X550EM_x) 1998f572b2c4SMark Rustad return 0; 1999f572b2c4SMark Rustad 2000c3dc4c09SDon Skidmore return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 20016a14ee0cSDon Skidmore } 20026a14ee0cSDon Skidmore 2003c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 2004c3dc4c09SDon Skidmore * @hw: address of hardware structure 2005c3dc4c09SDon Skidmore * @link_up: address of boolean to indicate link status 2006c3dc4c09SDon Skidmore * 2007c3dc4c09SDon Skidmore * Returns error code if unable to get link status. 2008c3dc4c09SDon Skidmore **/ 2009c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 2010c3dc4c09SDon Skidmore { 2011c3dc4c09SDon Skidmore u32 ret; 2012c3dc4c09SDon Skidmore u16 autoneg_status; 2013c3dc4c09SDon Skidmore 2014c3dc4c09SDon Skidmore *link_up = false; 2015c3dc4c09SDon Skidmore 2016c3dc4c09SDon Skidmore /* read this twice back to back to indicate current status */ 2017c3dc4c09SDon Skidmore ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 2018c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 2019c3dc4c09SDon Skidmore &autoneg_status); 2020c3dc4c09SDon Skidmore if (ret) 2021c3dc4c09SDon Skidmore return ret; 2022c3dc4c09SDon Skidmore 2023c3dc4c09SDon Skidmore ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 2024c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 2025c3dc4c09SDon Skidmore &autoneg_status); 2026c3dc4c09SDon Skidmore if (ret) 2027c3dc4c09SDon Skidmore return ret; 2028c3dc4c09SDon Skidmore 2029c3dc4c09SDon Skidmore *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 2030c3dc4c09SDon Skidmore 2031c3dc4c09SDon Skidmore return 0; 2032c3dc4c09SDon Skidmore } 2033c3dc4c09SDon Skidmore 2034c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 20356a14ee0cSDon Skidmore * @hw: point to hardware structure 20366a14ee0cSDon Skidmore * 2037c3dc4c09SDon Skidmore * Configures the link between the integrated KR PHY and the external X557 PHY 2038c3dc4c09SDon Skidmore * The driver will call this function when it gets a link status change 2039c3dc4c09SDon Skidmore * interrupt from the X557 PHY. This function configures the link speed 2040c3dc4c09SDon Skidmore * between the PHYs to match the link speed of the BASE-T link. 20416a14ee0cSDon Skidmore * 20426a14ee0cSDon Skidmore * A return of a non-zero value indicates an error, and the base driver should 20436a14ee0cSDon Skidmore * not report link up. 20446a14ee0cSDon Skidmore **/ 2045c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 20466a14ee0cSDon Skidmore { 20476a14ee0cSDon Skidmore ixgbe_link_speed force_speed; 2048c3dc4c09SDon Skidmore bool link_up; 2049c3dc4c09SDon Skidmore u32 status; 2050c3dc4c09SDon Skidmore u16 speed; 20516a14ee0cSDon Skidmore 2052c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 2053c3dc4c09SDon Skidmore return IXGBE_ERR_CONFIG; 2054c3dc4c09SDon Skidmore 2055f164b845SMark Rustad if (hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { 2056f164b845SMark Rustad speed = IXGBE_LINK_SPEED_10GB_FULL | 2057f164b845SMark Rustad IXGBE_LINK_SPEED_1GB_FULL; 2058f164b845SMark Rustad return ixgbe_setup_kr_speed_x550em(hw, speed); 2059f164b845SMark Rustad } 2060f164b845SMark Rustad 2061c3dc4c09SDon Skidmore /* If link is not up, then there is no setup necessary so return */ 2062c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 20636a14ee0cSDon Skidmore if (status) 20646a14ee0cSDon Skidmore return status; 20656a14ee0cSDon Skidmore 2066c3dc4c09SDon Skidmore if (!link_up) 20676a14ee0cSDon Skidmore return 0; 20686a14ee0cSDon Skidmore 20696a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 20706a14ee0cSDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 20716a14ee0cSDon Skidmore &speed); 2072c3dc4c09SDon Skidmore if (status) 2073c3dc4c09SDon Skidmore return status; 2074c3dc4c09SDon Skidmore 2075c3dc4c09SDon Skidmore /* If link is not still up, then no setup is necessary so return */ 2076c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 2077c3dc4c09SDon Skidmore if (status) 2078c3dc4c09SDon Skidmore return status; 2079c3dc4c09SDon Skidmore 2080c3dc4c09SDon Skidmore if (!link_up) 2081c3dc4c09SDon Skidmore return 0; 20826a14ee0cSDon Skidmore 20836a14ee0cSDon Skidmore /* clear everything but the speed and duplex bits */ 20846a14ee0cSDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 20856a14ee0cSDon Skidmore 20866a14ee0cSDon Skidmore switch (speed) { 20876a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 20886a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 20896a14ee0cSDon Skidmore break; 20906a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 20916a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 20926a14ee0cSDon Skidmore break; 20936a14ee0cSDon Skidmore default: 20946a14ee0cSDon Skidmore /* Internal PHY does not support anything else */ 20956a14ee0cSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 20966a14ee0cSDon Skidmore } 20976a14ee0cSDon Skidmore 20986a14ee0cSDon Skidmore return ixgbe_setup_ixfi_x550em(hw, &force_speed); 20996a14ee0cSDon Skidmore } 21006a14ee0cSDon Skidmore 2101f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 2102f4410d2cSDon Skidmore * @hw: pointer to hardware structure 2103f4410d2cSDon Skidmore **/ 2104f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 2105f4410d2cSDon Skidmore { 2106f4410d2cSDon Skidmore s32 status; 2107f4410d2cSDon Skidmore 2108f4410d2cSDon Skidmore status = ixgbe_reset_phy_generic(hw); 2109f4410d2cSDon Skidmore 2110f4410d2cSDon Skidmore if (status) 2111f4410d2cSDon Skidmore return status; 2112f4410d2cSDon Skidmore 2113f4410d2cSDon Skidmore /* Configure Link Status Alarm and Temperature Threshold interrupts */ 2114f4410d2cSDon Skidmore return ixgbe_enable_lasi_ext_t_x550em(hw); 2115f4410d2cSDon Skidmore } 2116f4410d2cSDon Skidmore 21176ac74394SDon Skidmore /** ixgbe_get_lcd_x550em - Determine lowest common denominator 21186ac74394SDon Skidmore * @hw: pointer to hardware structure 21196ac74394SDon Skidmore * @lcd_speed: pointer to lowest common link speed 21206ac74394SDon Skidmore * 21216ac74394SDon Skidmore * Determine lowest common link speed with link partner. 21226ac74394SDon Skidmore **/ 21236ac74394SDon Skidmore static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, 21246ac74394SDon Skidmore ixgbe_link_speed *lcd_speed) 21256ac74394SDon Skidmore { 21266ac74394SDon Skidmore u16 an_lp_status; 21276ac74394SDon Skidmore s32 status; 21286ac74394SDon Skidmore u16 word = hw->eeprom.ctrl_word_3; 21296ac74394SDon Skidmore 21306ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; 21316ac74394SDon Skidmore 21326ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, 21336ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 21346ac74394SDon Skidmore &an_lp_status); 21356ac74394SDon Skidmore if (status) 21366ac74394SDon Skidmore return status; 21376ac74394SDon Skidmore 21386ac74394SDon Skidmore /* If link partner advertised 1G, return 1G */ 21396ac74394SDon Skidmore if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { 21406ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; 21416ac74394SDon Skidmore return status; 21426ac74394SDon Skidmore } 21436ac74394SDon Skidmore 21446ac74394SDon Skidmore /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ 21456ac74394SDon Skidmore if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || 21466ac74394SDon Skidmore (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) 21476ac74394SDon Skidmore return status; 21486ac74394SDon Skidmore 21496ac74394SDon Skidmore /* Link partner not capable of lower speeds, return 10G */ 21506ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; 21516ac74394SDon Skidmore return status; 21526ac74394SDon Skidmore } 21536ac74394SDon Skidmore 2154afdc71e4SMark Rustad /** 2155afdc71e4SMark Rustad * ixgbe_setup_fc_x550em - Set up flow control 2156afdc71e4SMark Rustad * @hw: pointer to hardware structure 2157afdc71e4SMark Rustad */ 2158afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) 2159afdc71e4SMark Rustad { 2160afdc71e4SMark Rustad bool pause, asm_dir; 2161afdc71e4SMark Rustad u32 reg_val; 2162afdc71e4SMark Rustad s32 rc; 2163afdc71e4SMark Rustad 2164afdc71e4SMark Rustad /* Validate the requested mode */ 2165afdc71e4SMark Rustad if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 2166afdc71e4SMark Rustad hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 2167afdc71e4SMark Rustad return IXGBE_ERR_INVALID_LINK_SETTINGS; 2168afdc71e4SMark Rustad } 2169afdc71e4SMark Rustad 2170afdc71e4SMark Rustad /* 10gig parts do not have a word in the EEPROM to determine the 2171afdc71e4SMark Rustad * default flow control setting, so we explicitly set it to full. 2172afdc71e4SMark Rustad */ 2173afdc71e4SMark Rustad if (hw->fc.requested_mode == ixgbe_fc_default) 2174afdc71e4SMark Rustad hw->fc.requested_mode = ixgbe_fc_full; 2175afdc71e4SMark Rustad 2176afdc71e4SMark Rustad /* Determine PAUSE and ASM_DIR bits. */ 2177afdc71e4SMark Rustad switch (hw->fc.requested_mode) { 2178afdc71e4SMark Rustad case ixgbe_fc_none: 2179afdc71e4SMark Rustad pause = false; 2180afdc71e4SMark Rustad asm_dir = false; 2181afdc71e4SMark Rustad break; 2182afdc71e4SMark Rustad case ixgbe_fc_tx_pause: 2183afdc71e4SMark Rustad pause = false; 2184afdc71e4SMark Rustad asm_dir = true; 2185afdc71e4SMark Rustad break; 2186afdc71e4SMark Rustad case ixgbe_fc_rx_pause: 2187afdc71e4SMark Rustad /* Rx Flow control is enabled and Tx Flow control is 2188afdc71e4SMark Rustad * disabled by software override. Since there really 2189afdc71e4SMark Rustad * isn't a way to advertise that we are capable of RX 2190afdc71e4SMark Rustad * Pause ONLY, we will advertise that we support both 2191afdc71e4SMark Rustad * symmetric and asymmetric Rx PAUSE, as such we fall 2192afdc71e4SMark Rustad * through to the fc_full statement. Later, we will 2193afdc71e4SMark Rustad * disable the adapter's ability to send PAUSE frames. 2194afdc71e4SMark Rustad */ 2195afdc71e4SMark Rustad /* Fallthrough */ 2196afdc71e4SMark Rustad case ixgbe_fc_full: 2197afdc71e4SMark Rustad pause = true; 2198afdc71e4SMark Rustad asm_dir = true; 2199afdc71e4SMark Rustad break; 2200afdc71e4SMark Rustad default: 2201afdc71e4SMark Rustad hw_err(hw, "Flow control param set incorrectly\n"); 2202afdc71e4SMark Rustad return IXGBE_ERR_CONFIG; 2203afdc71e4SMark Rustad } 2204afdc71e4SMark Rustad 2205f572b2c4SMark Rustad if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR && 2206f572b2c4SMark Rustad hw->device_id != IXGBE_DEV_ID_X550EM_A_KR && 2207f572b2c4SMark Rustad hw->device_id != IXGBE_DEV_ID_X550EM_A_KR_L) 2208afdc71e4SMark Rustad return 0; 2209afdc71e4SMark Rustad 22109a5c27e6SMark Rustad rc = hw->mac.ops.read_iosf_sb_reg(hw, 2211afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 22129a5c27e6SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 22139a5c27e6SMark Rustad ®_val); 2214afdc71e4SMark Rustad if (rc) 2215afdc71e4SMark Rustad return rc; 2216afdc71e4SMark Rustad 2217afdc71e4SMark Rustad reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 2218afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 2219afdc71e4SMark Rustad if (pause) 2220afdc71e4SMark Rustad reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 2221afdc71e4SMark Rustad if (asm_dir) 2222afdc71e4SMark Rustad reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 22239a5c27e6SMark Rustad rc = hw->mac.ops.write_iosf_sb_reg(hw, 2224afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 22259a5c27e6SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 22269a5c27e6SMark Rustad reg_val); 2227afdc71e4SMark Rustad 2228afdc71e4SMark Rustad /* This device does not fully support AN. */ 2229afdc71e4SMark Rustad hw->fc.disable_fc_autoneg = true; 2230afdc71e4SMark Rustad 2231afdc71e4SMark Rustad return rc; 2232afdc71e4SMark Rustad } 2233afdc71e4SMark Rustad 22346ac74394SDon Skidmore /** ixgbe_enter_lplu_x550em - Transition to low power states 22356ac74394SDon Skidmore * @hw: pointer to hardware structure 22366ac74394SDon Skidmore * 22376ac74394SDon Skidmore * Configures Low Power Link Up on transition to low power states 22386ac74394SDon Skidmore * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting 22396ac74394SDon Skidmore * the X557 PHY immediately prior to entering LPLU. 22406ac74394SDon Skidmore **/ 22416ac74394SDon Skidmore static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) 22426ac74394SDon Skidmore { 22436ac74394SDon Skidmore u16 an_10g_cntl_reg, autoneg_reg, speed; 22446ac74394SDon Skidmore s32 status; 22456ac74394SDon Skidmore ixgbe_link_speed lcd_speed; 22466ac74394SDon Skidmore u32 save_autoneg; 22476ac74394SDon Skidmore bool link_up; 22486ac74394SDon Skidmore 22496ac74394SDon Skidmore /* If blocked by MNG FW, then don't restart AN */ 22506ac74394SDon Skidmore if (ixgbe_check_reset_blocked(hw)) 22516ac74394SDon Skidmore return 0; 22526ac74394SDon Skidmore 22536ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 22546ac74394SDon Skidmore if (status) 22556ac74394SDon Skidmore return status; 22566ac74394SDon Skidmore 22576ac74394SDon Skidmore status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, 22586ac74394SDon Skidmore &hw->eeprom.ctrl_word_3); 22596ac74394SDon Skidmore if (status) 22606ac74394SDon Skidmore return status; 22616ac74394SDon Skidmore 22626ac74394SDon Skidmore /* If link is down, LPLU disabled in NVM, WoL disabled, or 22636ac74394SDon Skidmore * manageability disabled, then force link down by entering 22646ac74394SDon Skidmore * low power mode. 22656ac74394SDon Skidmore */ 22666ac74394SDon Skidmore if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || 22676ac74394SDon Skidmore !(hw->wol_enabled || ixgbe_mng_present(hw))) 22686ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 22696ac74394SDon Skidmore 22706ac74394SDon Skidmore /* Determine LCD */ 22716ac74394SDon Skidmore status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); 22726ac74394SDon Skidmore if (status) 22736ac74394SDon Skidmore return status; 22746ac74394SDon Skidmore 22756ac74394SDon Skidmore /* If no valid LCD link speed, then force link down and exit. */ 22766ac74394SDon Skidmore if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) 22776ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 22786ac74394SDon Skidmore 22796ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 22806ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 22816ac74394SDon Skidmore &speed); 22826ac74394SDon Skidmore if (status) 22836ac74394SDon Skidmore return status; 22846ac74394SDon Skidmore 22856ac74394SDon Skidmore /* If no link now, speed is invalid so take link down */ 22866ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 22876ac74394SDon Skidmore if (status) 22886ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 22896ac74394SDon Skidmore 22906ac74394SDon Skidmore /* clear everything but the speed bits */ 22916ac74394SDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; 22926ac74394SDon Skidmore 22936ac74394SDon Skidmore /* If current speed is already LCD, then exit. */ 22946ac74394SDon Skidmore if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && 22956ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || 22966ac74394SDon Skidmore ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && 22976ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) 22986ac74394SDon Skidmore return status; 22996ac74394SDon Skidmore 23006ac74394SDon Skidmore /* Clear AN completed indication */ 23016ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, 23026ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 23036ac74394SDon Skidmore &autoneg_reg); 23046ac74394SDon Skidmore if (status) 23056ac74394SDon Skidmore return status; 23066ac74394SDon Skidmore 23076ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, 23086ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 23096ac74394SDon Skidmore &an_10g_cntl_reg); 23106ac74394SDon Skidmore if (status) 23116ac74394SDon Skidmore return status; 23126ac74394SDon Skidmore 23136ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, 23146ac74394SDon Skidmore IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, 23156ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 23166ac74394SDon Skidmore &autoneg_reg); 23176ac74394SDon Skidmore if (status) 23186ac74394SDon Skidmore return status; 23196ac74394SDon Skidmore 23206ac74394SDon Skidmore save_autoneg = hw->phy.autoneg_advertised; 23216ac74394SDon Skidmore 23226ac74394SDon Skidmore /* Setup link at least common link speed */ 23236ac74394SDon Skidmore status = hw->mac.ops.setup_link(hw, lcd_speed, false); 23246ac74394SDon Skidmore 23256ac74394SDon Skidmore /* restore autoneg from before setting lplu speed */ 23266ac74394SDon Skidmore hw->phy.autoneg_advertised = save_autoneg; 23276ac74394SDon Skidmore 23286ac74394SDon Skidmore return status; 23296ac74394SDon Skidmore } 23306ac74394SDon Skidmore 2331537cc5dfSMark Rustad /** 2332537cc5dfSMark Rustad * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register 2333537cc5dfSMark Rustad * @hw: pointer to hardware structure 2334537cc5dfSMark Rustad * 2335537cc5dfSMark Rustad * Read NW_MNG_IF_SEL register and save field values. 2336537cc5dfSMark Rustad */ 2337537cc5dfSMark Rustad static void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) 2338537cc5dfSMark Rustad { 2339537cc5dfSMark Rustad /* Save NW management interface connected on board. This is used 2340537cc5dfSMark Rustad * to determine internal PHY mode. 2341537cc5dfSMark Rustad */ 2342537cc5dfSMark Rustad hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 2343537cc5dfSMark Rustad 2344537cc5dfSMark Rustad /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set 2345537cc5dfSMark Rustad * PHY address. This register field was has only been used for X552. 2346537cc5dfSMark Rustad */ 2347537cc5dfSMark Rustad if (!hw->phy.nw_mng_if_sel) { 2348537cc5dfSMark Rustad if (hw->mac.type == ixgbe_mac_x550em_a) { 2349537cc5dfSMark Rustad struct ixgbe_adapter *adapter = hw->back; 2350537cc5dfSMark Rustad 2351537cc5dfSMark Rustad e_warn(drv, "nw_mng_if_sel not set\n"); 2352537cc5dfSMark Rustad } 2353537cc5dfSMark Rustad return; 2354537cc5dfSMark Rustad } 2355537cc5dfSMark Rustad 2356537cc5dfSMark Rustad hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel & 2357537cc5dfSMark Rustad IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> 2358537cc5dfSMark Rustad IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; 2359537cc5dfSMark Rustad } 2360537cc5dfSMark Rustad 23616a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 23626a14ee0cSDon Skidmore * @hw: pointer to hardware structure 23636a14ee0cSDon Skidmore * 23646a14ee0cSDon Skidmore * Initialize any function pointers that were not able to be 23656a14ee0cSDon Skidmore * set during init_shared_code because the PHY/SFP type was 23666a14ee0cSDon Skidmore * not known. Perform the SFP init if necessary. 23676a14ee0cSDon Skidmore **/ 23687ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 23696a14ee0cSDon Skidmore { 23706a14ee0cSDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 23716a14ee0cSDon Skidmore s32 ret_val; 23726a14ee0cSDon Skidmore 23737e49d616SDon Skidmore hw->mac.ops.set_lan_id(hw); 23747e49d616SDon Skidmore 2375537cc5dfSMark Rustad ixgbe_read_mng_if_sel_x550em(hw); 2376537cc5dfSMark Rustad 2377c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 23786a14ee0cSDon Skidmore phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 2379ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 23806a14ee0cSDon Skidmore } 23816a14ee0cSDon Skidmore 23826a14ee0cSDon Skidmore /* Identify the PHY or SFP module */ 23836a14ee0cSDon Skidmore ret_val = phy->ops.identify(hw); 23846a14ee0cSDon Skidmore 2385c3dc4c09SDon Skidmore /* Setup function pointers based on detected hardware */ 23866a14ee0cSDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 23876a14ee0cSDon Skidmore if (phy->sfp_type != ixgbe_sfp_type_unknown) 23886a14ee0cSDon Skidmore phy->ops.reset = NULL; 23896a14ee0cSDon Skidmore 23906a14ee0cSDon Skidmore /* Set functions pointers based on phy type */ 23916a14ee0cSDon Skidmore switch (hw->phy.type) { 23926a14ee0cSDon Skidmore case ixgbe_phy_x550em_kx4: 23936a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kx4_x550em; 23946a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 23956a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 23966a14ee0cSDon Skidmore break; 23976a14ee0cSDon Skidmore case ixgbe_phy_x550em_kr: 23986a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kr_x550em; 23996a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 24006a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 24016a14ee0cSDon Skidmore break; 24026a14ee0cSDon Skidmore case ixgbe_phy_x550em_ext_t: 2403c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 2404c3dc4c09SDon Skidmore * to determine internal PHY mode 2405c3dc4c09SDon Skidmore */ 2406c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 2407c3dc4c09SDon Skidmore 2408c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup iXFI internal link, 2409c3dc4c09SDon Skidmore * else setup KR now. 2410c3dc4c09SDon Skidmore */ 2411c3dc4c09SDon Skidmore phy->ops.setup_internal_link = 2412c3dc4c09SDon Skidmore ixgbe_setup_internal_phy_t_x550em; 2413c3dc4c09SDon Skidmore 24146ac74394SDon Skidmore /* setup SW LPLU only for first revision */ 24153ca2b250SMark Rustad if (hw->mac.type == ixgbe_mac_X550EM_x && 24163ca2b250SMark Rustad !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) & 24173ca2b250SMark Rustad IXGBE_FUSES0_REV_MASK)) 24186ac74394SDon Skidmore phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; 24196ac74394SDon Skidmore 2420c3dc4c09SDon Skidmore phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 2421f4410d2cSDon Skidmore phy->ops.reset = ixgbe_reset_phy_t_X550em; 24226a14ee0cSDon Skidmore break; 24236a14ee0cSDon Skidmore default: 24246a14ee0cSDon Skidmore break; 24256a14ee0cSDon Skidmore } 2426c3dc4c09SDon Skidmore 24276a14ee0cSDon Skidmore return ret_val; 24286a14ee0cSDon Skidmore } 24296a14ee0cSDon Skidmore 24306a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type 24316a14ee0cSDon Skidmore * @hw: pointer to hardware structure 24326a14ee0cSDon Skidmore * 24336a14ee0cSDon Skidmore * Returns the media type (fiber, copper, backplane) 24346a14ee0cSDon Skidmore * 24356a14ee0cSDon Skidmore */ 24367ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 24376a14ee0cSDon Skidmore { 24386a14ee0cSDon Skidmore enum ixgbe_media_type media_type; 24396a14ee0cSDon Skidmore 24406a14ee0cSDon Skidmore /* Detect if there is a copper PHY attached. */ 24416a14ee0cSDon Skidmore switch (hw->device_id) { 2442200157c2SMark Rustad case IXGBE_DEV_ID_X550EM_A_SGMII: 2443200157c2SMark Rustad case IXGBE_DEV_ID_X550EM_A_SGMII_L: 2444200157c2SMark Rustad hw->phy.type = ixgbe_phy_sgmii; 2445200157c2SMark Rustad /* Fallthrough */ 24466a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 24476a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 2448f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR: 2449f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR_L: 24506a14ee0cSDon Skidmore media_type = ixgbe_media_type_backplane; 24516a14ee0cSDon Skidmore break; 24526a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 24532d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 245449425dfcSMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 24556a14ee0cSDon Skidmore media_type = ixgbe_media_type_fiber; 24566a14ee0cSDon Skidmore break; 24576a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 24586a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 24596a14ee0cSDon Skidmore media_type = ixgbe_media_type_copper; 24606a14ee0cSDon Skidmore break; 24616a14ee0cSDon Skidmore default: 24626a14ee0cSDon Skidmore media_type = ixgbe_media_type_unknown; 24636a14ee0cSDon Skidmore break; 24646a14ee0cSDon Skidmore } 24656a14ee0cSDon Skidmore return media_type; 24666a14ee0cSDon Skidmore } 24676a14ee0cSDon Skidmore 24686a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 24696a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 24706a14ee0cSDon Skidmore **/ 24717ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 24726a14ee0cSDon Skidmore { 2473a1e869deSMark Rustad s32 status; 24746a14ee0cSDon Skidmore u16 reg; 24756a14ee0cSDon Skidmore 24766a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 24776a14ee0cSDon Skidmore IXGBE_MDIO_TX_VENDOR_ALARMS_3, 24786a14ee0cSDon Skidmore IXGBE_MDIO_PMA_PMD_DEV_TYPE, 24796a14ee0cSDon Skidmore ®); 24806a14ee0cSDon Skidmore if (status) 24816a14ee0cSDon Skidmore return status; 24826a14ee0cSDon Skidmore 2483e2261bccSDon Skidmore /* If PHY FW reset completed bit is set then this is the first 2484e2261bccSDon Skidmore * SW instance after a power on so the PHY FW must be un-stalled. 2485e2261bccSDon Skidmore */ 2486e2261bccSDon Skidmore if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 24876a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 24886a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 24896a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 24906a14ee0cSDon Skidmore ®); 24916a14ee0cSDon Skidmore if (status) 24926a14ee0cSDon Skidmore return status; 24936a14ee0cSDon Skidmore 24946a14ee0cSDon Skidmore reg &= ~IXGBE_MDIO_POWER_UP_STALL; 24956a14ee0cSDon Skidmore 24966a14ee0cSDon Skidmore status = hw->phy.ops.write_reg(hw, 24976a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 24986a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 24996a14ee0cSDon Skidmore reg); 2500e2261bccSDon Skidmore if (status) 2501e2261bccSDon Skidmore return status; 2502e2261bccSDon Skidmore } 2503e2261bccSDon Skidmore 25046a14ee0cSDon Skidmore return status; 25056a14ee0cSDon Skidmore } 25066a14ee0cSDon Skidmore 2507e84db727SMark Rustad /** 2508e84db727SMark Rustad * ixgbe_set_mdio_speed - Set MDIO clock speed 2509e84db727SMark Rustad * @hw: pointer to hardware structure 2510e84db727SMark Rustad */ 2511e84db727SMark Rustad static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) 2512e84db727SMark Rustad { 2513e84db727SMark Rustad u32 hlreg0; 2514e84db727SMark Rustad 2515e84db727SMark Rustad switch (hw->device_id) { 2516e84db727SMark Rustad case IXGBE_DEV_ID_X550EM_X_10G_T: 25172d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 2518e84db727SMark Rustad /* Config MDIO clock speed before the first MDIO PHY access */ 2519e84db727SMark Rustad hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 2520e84db727SMark Rustad hlreg0 &= ~IXGBE_HLREG0_MDCSPD; 2521e84db727SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 2522e84db727SMark Rustad break; 2523e84db727SMark Rustad default: 2524e84db727SMark Rustad break; 2525e84db727SMark Rustad } 2526e84db727SMark Rustad } 2527e84db727SMark Rustad 25286a14ee0cSDon Skidmore /** ixgbe_reset_hw_X550em - Perform hardware reset 25296a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 25306a14ee0cSDon Skidmore ** 25316a14ee0cSDon Skidmore ** Resets the hardware by resetting the transmit and receive units, masks 25326a14ee0cSDon Skidmore ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 25336a14ee0cSDon Skidmore ** reset. 25346a14ee0cSDon Skidmore **/ 25357ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 25366a14ee0cSDon Skidmore { 25376a14ee0cSDon Skidmore ixgbe_link_speed link_speed; 25386a14ee0cSDon Skidmore s32 status; 25396a14ee0cSDon Skidmore u32 ctrl = 0; 25406a14ee0cSDon Skidmore u32 i; 25416a14ee0cSDon Skidmore bool link_up = false; 25426a14ee0cSDon Skidmore 25436a14ee0cSDon Skidmore /* Call adapter stop to disable Tx/Rx and clear interrupts */ 25446a14ee0cSDon Skidmore status = hw->mac.ops.stop_adapter(hw); 25456a14ee0cSDon Skidmore if (status) 25466a14ee0cSDon Skidmore return status; 25476a14ee0cSDon Skidmore 25486a14ee0cSDon Skidmore /* flush pending Tx transactions */ 25496a14ee0cSDon Skidmore ixgbe_clear_tx_pending(hw); 25506a14ee0cSDon Skidmore 25516a14ee0cSDon Skidmore /* PHY ops must be identified and initialized prior to reset */ 25526a14ee0cSDon Skidmore 25536a14ee0cSDon Skidmore /* Identify PHY and related function pointers */ 25546a14ee0cSDon Skidmore status = hw->phy.ops.init(hw); 25556a14ee0cSDon Skidmore 25566a14ee0cSDon Skidmore /* start the external PHY */ 25576a14ee0cSDon Skidmore if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 25586a14ee0cSDon Skidmore status = ixgbe_init_ext_t_x550em(hw); 25596a14ee0cSDon Skidmore if (status) 25606a14ee0cSDon Skidmore return status; 25616a14ee0cSDon Skidmore } 25626a14ee0cSDon Skidmore 25636a14ee0cSDon Skidmore /* Setup SFP module if there is one present. */ 25646a14ee0cSDon Skidmore if (hw->phy.sfp_setup_needed) { 25656a14ee0cSDon Skidmore status = hw->mac.ops.setup_sfp(hw); 25666a14ee0cSDon Skidmore hw->phy.sfp_setup_needed = false; 25676a14ee0cSDon Skidmore } 25686a14ee0cSDon Skidmore 25696a14ee0cSDon Skidmore /* Reset PHY */ 25706a14ee0cSDon Skidmore if (!hw->phy.reset_disable && hw->phy.ops.reset) 25716a14ee0cSDon Skidmore hw->phy.ops.reset(hw); 25726a14ee0cSDon Skidmore 25736a14ee0cSDon Skidmore mac_reset_top: 25746a14ee0cSDon Skidmore /* Issue global reset to the MAC. Needs to be SW reset if link is up. 25756a14ee0cSDon Skidmore * If link reset is used when link is up, it might reset the PHY when 25766a14ee0cSDon Skidmore * mng is using it. If link is down or the flag to force full link 25776a14ee0cSDon Skidmore * reset is set, then perform link reset. 25786a14ee0cSDon Skidmore */ 25796a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_LNK_RST; 25806a14ee0cSDon Skidmore 25816a14ee0cSDon Skidmore if (!hw->force_full_reset) { 25826a14ee0cSDon Skidmore hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 25836a14ee0cSDon Skidmore if (link_up) 25846a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_RST; 25856a14ee0cSDon Skidmore } 25866a14ee0cSDon Skidmore 25876a14ee0cSDon Skidmore ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 25886a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 25896a14ee0cSDon Skidmore IXGBE_WRITE_FLUSH(hw); 2590efff2e02SMark Rustad usleep_range(1000, 1200); 25916a14ee0cSDon Skidmore 25926a14ee0cSDon Skidmore /* Poll for reset bit to self-clear meaning reset is complete */ 25936a14ee0cSDon Skidmore for (i = 0; i < 10; i++) { 25946a14ee0cSDon Skidmore ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 25956a14ee0cSDon Skidmore if (!(ctrl & IXGBE_CTRL_RST_MASK)) 25966a14ee0cSDon Skidmore break; 2597efff2e02SMark Rustad udelay(1); 25986a14ee0cSDon Skidmore } 25996a14ee0cSDon Skidmore 26006a14ee0cSDon Skidmore if (ctrl & IXGBE_CTRL_RST_MASK) { 26016a14ee0cSDon Skidmore status = IXGBE_ERR_RESET_FAILED; 26026a14ee0cSDon Skidmore hw_dbg(hw, "Reset polling failed to complete.\n"); 26036a14ee0cSDon Skidmore } 26046a14ee0cSDon Skidmore 26056a14ee0cSDon Skidmore msleep(50); 26066a14ee0cSDon Skidmore 26076a14ee0cSDon Skidmore /* Double resets are required for recovery from certain error 26086a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 26096a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 26106a14ee0cSDon Skidmore */ 26116a14ee0cSDon Skidmore if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 26126a14ee0cSDon Skidmore hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 26136a14ee0cSDon Skidmore goto mac_reset_top; 26146a14ee0cSDon Skidmore } 26156a14ee0cSDon Skidmore 26166a14ee0cSDon Skidmore /* Store the permanent mac address */ 26176a14ee0cSDon Skidmore hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 26186a14ee0cSDon Skidmore 26196a14ee0cSDon Skidmore /* Store MAC address from RAR0, clear receive address registers, and 26206a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 26216a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 26226a14ee0cSDon Skidmore */ 26236a14ee0cSDon Skidmore hw->mac.num_rar_entries = 128; 26246a14ee0cSDon Skidmore hw->mac.ops.init_rx_addrs(hw); 26256a14ee0cSDon Skidmore 2626e84db727SMark Rustad ixgbe_set_mdio_speed(hw); 2627deda562aSDon Skidmore 2628ab5fe0c5SDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 2629ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 2630ab5fe0c5SDon Skidmore 26316a14ee0cSDon Skidmore return status; 26326a14ee0cSDon Skidmore } 26336a14ee0cSDon Skidmore 26345b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 26355b7f000fSDon Skidmore * anti-spoofing 26365b7f000fSDon Skidmore * @hw: pointer to hardware structure 26375b7f000fSDon Skidmore * @enable: enable or disable switch for Ethertype anti-spoofing 26385b7f000fSDon Skidmore * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 26395b7f000fSDon Skidmore **/ 2640bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 2641bc035fc5SDon Skidmore bool enable, int vf) 26425b7f000fSDon Skidmore { 26435b7f000fSDon Skidmore int vf_target_reg = vf >> 3; 26445b7f000fSDon Skidmore int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 26455b7f000fSDon Skidmore u32 pfvfspoof; 26465b7f000fSDon Skidmore 26475b7f000fSDon Skidmore pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 26485b7f000fSDon Skidmore if (enable) 2649b4f47a48SJacob Keller pfvfspoof |= BIT(vf_target_shift); 26505b7f000fSDon Skidmore else 2651b4f47a48SJacob Keller pfvfspoof &= ~BIT(vf_target_shift); 26525b7f000fSDon Skidmore 26535b7f000fSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 26545b7f000fSDon Skidmore } 26555b7f000fSDon Skidmore 26566d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 26576d4c96adSDon Skidmore * @hw: pointer to hardware structure 26586d4c96adSDon Skidmore * @enable: enable or disable source address pruning 26596d4c96adSDon Skidmore * @pool: Rx pool to set source address pruning for 26606d4c96adSDon Skidmore **/ 26616d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 26626d4c96adSDon Skidmore bool enable, 26636d4c96adSDon Skidmore unsigned int pool) 26646d4c96adSDon Skidmore { 26656d4c96adSDon Skidmore u64 pfflp; 26666d4c96adSDon Skidmore 26676d4c96adSDon Skidmore /* max rx pool is 63 */ 26686d4c96adSDon Skidmore if (pool > 63) 26696d4c96adSDon Skidmore return; 26706d4c96adSDon Skidmore 26716d4c96adSDon Skidmore pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 26726d4c96adSDon Skidmore pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 26736d4c96adSDon Skidmore 26746d4c96adSDon Skidmore if (enable) 26756d4c96adSDon Skidmore pfflp |= (1ULL << pool); 26766d4c96adSDon Skidmore else 26776d4c96adSDon Skidmore pfflp &= ~(1ULL << pool); 26786d4c96adSDon Skidmore 26796d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 26806d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 26816d4c96adSDon Skidmore } 26826d4c96adSDon Skidmore 2683449e21a9SMark Rustad /** 2684449e21a9SMark Rustad * ixgbe_set_mux - Set mux for port 1 access with CS4227 2685449e21a9SMark Rustad * @hw: pointer to hardware structure 2686449e21a9SMark Rustad * @state: set mux if 1, clear if 0 2687449e21a9SMark Rustad */ 2688449e21a9SMark Rustad static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) 2689449e21a9SMark Rustad { 2690449e21a9SMark Rustad u32 esdp; 2691449e21a9SMark Rustad 2692449e21a9SMark Rustad if (!hw->bus.lan_id) 2693449e21a9SMark Rustad return; 2694449e21a9SMark Rustad esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 2695449e21a9SMark Rustad if (state) 2696449e21a9SMark Rustad esdp |= IXGBE_ESDP_SDP1; 2697449e21a9SMark Rustad else 2698449e21a9SMark Rustad esdp &= ~IXGBE_ESDP_SDP1; 2699449e21a9SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 2700449e21a9SMark Rustad IXGBE_WRITE_FLUSH(hw); 2701449e21a9SMark Rustad } 2702449e21a9SMark Rustad 2703449e21a9SMark Rustad /** 2704449e21a9SMark Rustad * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore 2705449e21a9SMark Rustad * @hw: pointer to hardware structure 2706449e21a9SMark Rustad * @mask: Mask to specify which semaphore to acquire 2707449e21a9SMark Rustad * 2708449e21a9SMark Rustad * Acquires the SWFW semaphore and sets the I2C MUX 2709449e21a9SMark Rustad */ 2710449e21a9SMark Rustad static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 2711449e21a9SMark Rustad { 2712449e21a9SMark Rustad s32 status; 2713449e21a9SMark Rustad 2714449e21a9SMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, mask); 2715449e21a9SMark Rustad if (status) 2716449e21a9SMark Rustad return status; 2717449e21a9SMark Rustad 2718449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 2719449e21a9SMark Rustad ixgbe_set_mux(hw, 1); 2720449e21a9SMark Rustad 2721449e21a9SMark Rustad return 0; 2722449e21a9SMark Rustad } 2723449e21a9SMark Rustad 2724449e21a9SMark Rustad /** 2725449e21a9SMark Rustad * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore 2726449e21a9SMark Rustad * @hw: pointer to hardware structure 2727449e21a9SMark Rustad * @mask: Mask to specify which semaphore to release 2728449e21a9SMark Rustad * 2729449e21a9SMark Rustad * Releases the SWFW semaphore and sets the I2C MUX 2730449e21a9SMark Rustad */ 2731449e21a9SMark Rustad static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 2732449e21a9SMark Rustad { 2733449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 2734449e21a9SMark Rustad ixgbe_set_mux(hw, 0); 2735449e21a9SMark Rustad 2736449e21a9SMark Rustad ixgbe_release_swfw_sync_X540(hw, mask); 2737449e21a9SMark Rustad } 2738449e21a9SMark Rustad 273949425dfcSMark Rustad /** 274049425dfcSMark Rustad * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore 274149425dfcSMark Rustad * @hw: pointer to hardware structure 274249425dfcSMark Rustad * @mask: Mask to specify which semaphore to acquire 274349425dfcSMark Rustad * 274449425dfcSMark Rustad * Acquires the SWFW semaphore and get the shared PHY token as needed 274549425dfcSMark Rustad */ 274649425dfcSMark Rustad static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 274749425dfcSMark Rustad { 274849425dfcSMark Rustad u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 274949425dfcSMark Rustad int retries = FW_PHY_TOKEN_RETRIES; 275049425dfcSMark Rustad s32 status; 275149425dfcSMark Rustad 275249425dfcSMark Rustad while (--retries) { 275349425dfcSMark Rustad status = 0; 275449425dfcSMark Rustad if (hmask) 275549425dfcSMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, hmask); 275649425dfcSMark Rustad if (status) 275749425dfcSMark Rustad return status; 275849425dfcSMark Rustad if (!(mask & IXGBE_GSSR_TOKEN_SM)) 275949425dfcSMark Rustad return 0; 276049425dfcSMark Rustad 276149425dfcSMark Rustad status = ixgbe_get_phy_token(hw); 276249425dfcSMark Rustad if (!status) 276349425dfcSMark Rustad return 0; 276449425dfcSMark Rustad if (hmask) 276549425dfcSMark Rustad ixgbe_release_swfw_sync_X540(hw, hmask); 276649425dfcSMark Rustad if (status != IXGBE_ERR_TOKEN_RETRY) 276749425dfcSMark Rustad return status; 2768d4f90d9dSArnd Bergmann msleep(FW_PHY_TOKEN_DELAY); 276949425dfcSMark Rustad } 277049425dfcSMark Rustad 277149425dfcSMark Rustad return status; 277249425dfcSMark Rustad } 277349425dfcSMark Rustad 277449425dfcSMark Rustad /** 277549425dfcSMark Rustad * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore 277649425dfcSMark Rustad * @hw: pointer to hardware structure 277749425dfcSMark Rustad * @mask: Mask to specify which semaphore to release 277849425dfcSMark Rustad * 277949425dfcSMark Rustad * Release the SWFW semaphore and puts the shared PHY token as needed 278049425dfcSMark Rustad */ 278149425dfcSMark Rustad static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 278249425dfcSMark Rustad { 278349425dfcSMark Rustad u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 278449425dfcSMark Rustad 278549425dfcSMark Rustad if (mask & IXGBE_GSSR_TOKEN_SM) 278649425dfcSMark Rustad ixgbe_put_phy_token(hw); 278749425dfcSMark Rustad 278849425dfcSMark Rustad if (hmask) 278949425dfcSMark Rustad ixgbe_release_swfw_sync_X540(hw, hmask); 279049425dfcSMark Rustad } 279149425dfcSMark Rustad 2792d31afc8fSMark Rustad /** 2793d31afc8fSMark Rustad * ixgbe_read_phy_reg_x550a - Reads specified PHY register 2794d31afc8fSMark Rustad * @hw: pointer to hardware structure 2795d31afc8fSMark Rustad * @reg_addr: 32 bit address of PHY register to read 2796d31afc8fSMark Rustad * @phy_data: Pointer to read data from PHY register 2797d31afc8fSMark Rustad * 2798d31afc8fSMark Rustad * Reads a value from a specified PHY register using the SWFW lock and PHY 2799d31afc8fSMark Rustad * Token. The PHY Token is needed since the MDIO is shared between to MAC 2800d31afc8fSMark Rustad * instances. 2801d31afc8fSMark Rustad */ 2802d31afc8fSMark Rustad static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 2803d31afc8fSMark Rustad u32 device_type, u16 *phy_data) 2804d31afc8fSMark Rustad { 2805d31afc8fSMark Rustad u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 2806d31afc8fSMark Rustad s32 status; 2807d31afc8fSMark Rustad 2808d31afc8fSMark Rustad if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 2809d31afc8fSMark Rustad return IXGBE_ERR_SWFW_SYNC; 2810d31afc8fSMark Rustad 2811d31afc8fSMark Rustad status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); 2812d31afc8fSMark Rustad 2813d31afc8fSMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 2814d31afc8fSMark Rustad 2815d31afc8fSMark Rustad return status; 2816d31afc8fSMark Rustad } 2817d31afc8fSMark Rustad 2818d31afc8fSMark Rustad /** 2819d31afc8fSMark Rustad * ixgbe_write_phy_reg_x550a - Writes specified PHY register 2820d31afc8fSMark Rustad * @hw: pointer to hardware structure 2821d31afc8fSMark Rustad * @reg_addr: 32 bit PHY register to write 2822d31afc8fSMark Rustad * @device_type: 5 bit device type 2823d31afc8fSMark Rustad * @phy_data: Data to write to the PHY register 2824d31afc8fSMark Rustad * 2825d31afc8fSMark Rustad * Writes a value to specified PHY register using the SWFW lock and PHY Token. 2826d31afc8fSMark Rustad * The PHY Token is needed since the MDIO is shared between to MAC instances. 2827d31afc8fSMark Rustad */ 2828d31afc8fSMark Rustad static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 2829d31afc8fSMark Rustad u32 device_type, u16 phy_data) 2830d31afc8fSMark Rustad { 2831d31afc8fSMark Rustad u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 2832d31afc8fSMark Rustad s32 status; 2833d31afc8fSMark Rustad 2834d31afc8fSMark Rustad if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 2835d31afc8fSMark Rustad return IXGBE_ERR_SWFW_SYNC; 2836d31afc8fSMark Rustad 2837d31afc8fSMark Rustad status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data); 2838d31afc8fSMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 2839d31afc8fSMark Rustad 2840d31afc8fSMark Rustad return status; 2841d31afc8fSMark Rustad } 2842d31afc8fSMark Rustad 28436a14ee0cSDon Skidmore #define X550_COMMON_MAC \ 28446a14ee0cSDon Skidmore .init_hw = &ixgbe_init_hw_generic, \ 28456a14ee0cSDon Skidmore .start_hw = &ixgbe_start_hw_X540, \ 28466a14ee0cSDon Skidmore .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 28476a14ee0cSDon Skidmore .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 28486a14ee0cSDon Skidmore .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 28496a14ee0cSDon Skidmore .get_device_caps = &ixgbe_get_device_caps_generic, \ 28506a14ee0cSDon Skidmore .stop_adapter = &ixgbe_stop_adapter_generic, \ 28516a14ee0cSDon Skidmore .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 28526a14ee0cSDon Skidmore .read_analog_reg8 = NULL, \ 28536a14ee0cSDon Skidmore .write_analog_reg8 = NULL, \ 28546a14ee0cSDon Skidmore .set_rxpba = &ixgbe_set_rxpba_generic, \ 28556a14ee0cSDon Skidmore .check_link = &ixgbe_check_mac_link_generic, \ 28566a14ee0cSDon Skidmore .led_on = &ixgbe_led_on_generic, \ 28576a14ee0cSDon Skidmore .led_off = &ixgbe_led_off_generic, \ 28586a14ee0cSDon Skidmore .blink_led_start = &ixgbe_blink_led_start_X540, \ 28596a14ee0cSDon Skidmore .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 28606a14ee0cSDon Skidmore .set_rar = &ixgbe_set_rar_generic, \ 28616a14ee0cSDon Skidmore .clear_rar = &ixgbe_clear_rar_generic, \ 28626a14ee0cSDon Skidmore .set_vmdq = &ixgbe_set_vmdq_generic, \ 28636a14ee0cSDon Skidmore .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 28646a14ee0cSDon Skidmore .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 28656a14ee0cSDon Skidmore .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 28666a14ee0cSDon Skidmore .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 28676a14ee0cSDon Skidmore .enable_mc = &ixgbe_enable_mc_generic, \ 28686a14ee0cSDon Skidmore .disable_mc = &ixgbe_disable_mc_generic, \ 28696a14ee0cSDon Skidmore .clear_vfta = &ixgbe_clear_vfta_generic, \ 28706a14ee0cSDon Skidmore .set_vfta = &ixgbe_set_vfta_generic, \ 28716a14ee0cSDon Skidmore .fc_enable = &ixgbe_fc_enable_generic, \ 28726a14ee0cSDon Skidmore .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, \ 28736a14ee0cSDon Skidmore .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 28746a14ee0cSDon Skidmore .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 28756a14ee0cSDon Skidmore .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 28766d4c96adSDon Skidmore .set_source_address_pruning = \ 28776d4c96adSDon Skidmore &ixgbe_set_source_address_pruning_X550, \ 28785b7f000fSDon Skidmore .set_ethertype_anti_spoofing = \ 28795b7f000fSDon Skidmore &ixgbe_set_ethertype_anti_spoofing_X550, \ 28806a14ee0cSDon Skidmore .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 28816a14ee0cSDon Skidmore .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 28826a14ee0cSDon Skidmore .get_thermal_sensor_data = NULL, \ 28836a14ee0cSDon Skidmore .init_thermal_sensor_thresh = NULL, \ 28841f9ac57cSDon Skidmore .enable_rx = &ixgbe_enable_rx_generic, \ 28851f9ac57cSDon Skidmore .disable_rx = &ixgbe_disable_rx_x550, \ 28866a14ee0cSDon Skidmore 288737689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550 = { 28886a14ee0cSDon Skidmore X550_COMMON_MAC 28896a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X540, 28906a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X540, 28916a14ee0cSDon Skidmore .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 28926a14ee0cSDon Skidmore .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 28936a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_mac_link_X540, 28946a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 2895454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_generic, 28966a14ee0cSDon Skidmore .setup_sfp = NULL, 2897449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, 2898449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X540, 2899dbd15b8fSDon Skidmore .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 2900afdc71e4SMark Rustad .prot_autoc_read = prot_autoc_read_generic, 2901afdc71e4SMark Rustad .prot_autoc_write = prot_autoc_write_generic, 2902afdc71e4SMark Rustad .setup_fc = ixgbe_setup_fc_generic, 29036a14ee0cSDon Skidmore }; 29046a14ee0cSDon Skidmore 290537689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550EM_x = { 29066a14ee0cSDon Skidmore X550_COMMON_MAC 29076a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X550em, 29086a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X550em, 29096a14ee0cSDon Skidmore .get_san_mac_addr = NULL, 29106a14ee0cSDon Skidmore .get_wwn_prefix = NULL, 29114695886cSEmil Tantilov .setup_link = &ixgbe_setup_mac_link_X540, 29126a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 2913454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_X550em, 29146a14ee0cSDon Skidmore .setup_sfp = ixgbe_setup_sfp_modules_X550em, 2915449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 2916449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 2917dbd15b8fSDon Skidmore .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 2918afdc71e4SMark Rustad .setup_fc = NULL, /* defined later */ 29199a5c27e6SMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, 29209a5c27e6SMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, 29216a14ee0cSDon Skidmore }; 29226a14ee0cSDon Skidmore 292349425dfcSMark Rustad static struct ixgbe_mac_operations mac_ops_x550em_a = { 292449425dfcSMark Rustad X550_COMMON_MAC 292549425dfcSMark Rustad .reset_hw = ixgbe_reset_hw_X550em, 292649425dfcSMark Rustad .get_media_type = ixgbe_get_media_type_X550em, 292749425dfcSMark Rustad .get_san_mac_addr = NULL, 292849425dfcSMark Rustad .get_wwn_prefix = NULL, 2929a0254a70SMark Rustad .setup_link = NULL, /* defined later */ 293049425dfcSMark Rustad .get_link_capabilities = ixgbe_get_link_capabilities_X550em, 293149425dfcSMark Rustad .get_bus_info = ixgbe_get_bus_info_X550em, 293249425dfcSMark Rustad .setup_sfp = ixgbe_setup_sfp_modules_X550em, 293349425dfcSMark Rustad .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, 293449425dfcSMark Rustad .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, 2935a0254a70SMark Rustad .setup_fc = ixgbe_setup_fc_x550em, 293649425dfcSMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, 293749425dfcSMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, 293849425dfcSMark Rustad }; 293949425dfcSMark Rustad 29406a14ee0cSDon Skidmore #define X550_COMMON_EEP \ 29416a14ee0cSDon Skidmore .read = &ixgbe_read_ee_hostif_X550, \ 29426a14ee0cSDon Skidmore .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 29436a14ee0cSDon Skidmore .write = &ixgbe_write_ee_hostif_X550, \ 29446a14ee0cSDon Skidmore .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 29456a14ee0cSDon Skidmore .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 29466a14ee0cSDon Skidmore .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 29476a14ee0cSDon Skidmore .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 29486a14ee0cSDon Skidmore 294937689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550 = { 29506a14ee0cSDon Skidmore X550_COMMON_EEP 29516a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X550, 29526a14ee0cSDon Skidmore }; 29536a14ee0cSDon Skidmore 295437689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 29556a14ee0cSDon Skidmore X550_COMMON_EEP 29566a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X540, 29576a14ee0cSDon Skidmore }; 29586a14ee0cSDon Skidmore 29596a14ee0cSDon Skidmore #define X550_COMMON_PHY \ 29606a14ee0cSDon Skidmore .identify_sfp = &ixgbe_identify_module_generic, \ 29616a14ee0cSDon Skidmore .reset = NULL, \ 29626a14ee0cSDon Skidmore .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 29636a14ee0cSDon Skidmore .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 29646a14ee0cSDon Skidmore .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 29656a14ee0cSDon Skidmore .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 29666a14ee0cSDon Skidmore .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 29676a14ee0cSDon Skidmore .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 2968bef23de1SDon Skidmore .setup_link = &ixgbe_setup_phy_link_generic, \ 2969b5529ef5SDon Skidmore .set_phy_power = NULL, \ 29706a14ee0cSDon Skidmore .check_overtemp = &ixgbe_tn_check_overtemp, \ 29716a14ee0cSDon Skidmore .get_firmware_version = &ixgbe_get_phy_firmware_version_generic, 29726a14ee0cSDon Skidmore 297337689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550 = { 29746a14ee0cSDon Skidmore X550_COMMON_PHY 29756a14ee0cSDon Skidmore .init = NULL, 29766a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_generic, 2977d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_generic, 2978d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_generic, 29796a14ee0cSDon Skidmore }; 29806a14ee0cSDon Skidmore 298137689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550EM_x = { 29826a14ee0cSDon Skidmore X550_COMMON_PHY 29836a14ee0cSDon Skidmore .init = &ixgbe_init_phy_ops_X550em, 29846a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_x550em, 2985d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_generic, 2986d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_generic, 29874f9e3a3dSMark Rustad .read_i2c_combined = &ixgbe_read_i2c_combined_generic, 29884f9e3a3dSMark Rustad .write_i2c_combined = &ixgbe_write_i2c_combined_generic, 2989bb5ce9a5SMark Rustad .read_i2c_combined_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, 2990bb5ce9a5SMark Rustad .write_i2c_combined_unlocked = 2991bb5ce9a5SMark Rustad &ixgbe_write_i2c_combined_generic_unlocked, 29926a14ee0cSDon Skidmore }; 29936a14ee0cSDon Skidmore 2994d31afc8fSMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a = { 2995d31afc8fSMark Rustad X550_COMMON_PHY 2996d31afc8fSMark Rustad .init = &ixgbe_init_phy_ops_X550em, 2997d31afc8fSMark Rustad .identify = &ixgbe_identify_phy_x550em, 2998d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_x550a, 2999d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_x550a, 3000d31afc8fSMark Rustad }; 3001d31afc8fSMark Rustad 30029a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 30039a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550) 30049a900ecaSDon Skidmore }; 30059a900ecaSDon Skidmore 30069a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 30079a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550EM_x) 30089a900ecaSDon Skidmore }; 30099a900ecaSDon Skidmore 301049425dfcSMark Rustad static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = { 301149425dfcSMark Rustad IXGBE_MVALS_INIT(X550EM_a) 301249425dfcSMark Rustad }; 301349425dfcSMark Rustad 301437689010SMark Rustad const struct ixgbe_info ixgbe_X550_info = { 30156a14ee0cSDon Skidmore .mac = ixgbe_mac_X550, 30166a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 30176a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550, 30186a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550, 30196a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550, 30206a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 30219a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550, 30226a14ee0cSDon Skidmore }; 30236a14ee0cSDon Skidmore 302437689010SMark Rustad const struct ixgbe_info ixgbe_X550EM_x_info = { 30256a14ee0cSDon Skidmore .mac = ixgbe_mac_X550EM_x, 3026b5529ef5SDon Skidmore .get_invariants = &ixgbe_get_invariants_X550_x, 30276a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550EM_x, 30286a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550EM_x, 30296a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550EM_x, 30306a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 30319a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550EM_x, 30326a14ee0cSDon Skidmore }; 303349425dfcSMark Rustad 303449425dfcSMark Rustad const struct ixgbe_info ixgbe_x550em_a_info = { 303549425dfcSMark Rustad .mac = ixgbe_mac_x550em_a, 303649425dfcSMark Rustad .get_invariants = &ixgbe_get_invariants_X550_x, 303749425dfcSMark Rustad .mac_ops = &mac_ops_x550em_a, 303849425dfcSMark Rustad .eeprom_ops = &eeprom_ops_X550EM_x, 3039d31afc8fSMark Rustad .phy_ops = &phy_ops_x550em_a, 304049425dfcSMark Rustad .mbx_ops = &mbx_ops_generic, 304149425dfcSMark Rustad .mvals = ixgbe_mvals_x550em_a, 304249425dfcSMark Rustad }; 3043