16a14ee0cSDon Skidmore /******************************************************************************* 26a14ee0cSDon Skidmore * 36a14ee0cSDon Skidmore * Intel 10 Gigabit PCI Express Linux driver 4d5ec98a0SDon Skidmore * Copyright(c) 1999 - 2015 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); 30d91e3a7dSMark Rustad 31b5529ef5SDon Skidmore static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) 32b5529ef5SDon Skidmore { 33b5529ef5SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 34b5529ef5SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 35b5529ef5SDon Skidmore 36b5529ef5SDon Skidmore /* Start with X540 invariants, since so simular */ 37b5529ef5SDon Skidmore ixgbe_get_invariants_X540(hw); 38b5529ef5SDon Skidmore 39b5529ef5SDon Skidmore if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 40b5529ef5SDon Skidmore phy->ops.set_phy_power = NULL; 41b5529ef5SDon Skidmore 42b5529ef5SDon Skidmore return 0; 43b5529ef5SDon Skidmore } 44b5529ef5SDon Skidmore 45ab5fe0c5SDon Skidmore /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control 46ab5fe0c5SDon Skidmore * @hw: pointer to hardware structure 47ab5fe0c5SDon Skidmore **/ 48ab5fe0c5SDon Skidmore static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) 49ab5fe0c5SDon Skidmore { 50ab5fe0c5SDon Skidmore u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 51ab5fe0c5SDon Skidmore 52ab5fe0c5SDon Skidmore if (hw->bus.lan_id) { 53ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 54ab5fe0c5SDon Skidmore esdp |= IXGBE_ESDP_SDP1_DIR; 55ab5fe0c5SDon Skidmore } 56ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 57ab5fe0c5SDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 58ab5fe0c5SDon Skidmore IXGBE_WRITE_FLUSH(hw); 59ab5fe0c5SDon Skidmore } 60ab5fe0c5SDon Skidmore 61542b6eecSMark Rustad /** 62542b6eecSMark Rustad * ixgbe_read_cs4227 - Read CS4227 register 63542b6eecSMark Rustad * @hw: pointer to hardware structure 64542b6eecSMark Rustad * @reg: register number to write 65542b6eecSMark Rustad * @value: pointer to receive value read 66542b6eecSMark Rustad * 67542b6eecSMark Rustad * Returns status code 68542b6eecSMark Rustad */ 69542b6eecSMark Rustad static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) 70542b6eecSMark Rustad { 71542b6eecSMark Rustad return hw->phy.ops.read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, 72542b6eecSMark Rustad value); 73542b6eecSMark Rustad } 74542b6eecSMark Rustad 75542b6eecSMark Rustad /** 76542b6eecSMark Rustad * ixgbe_write_cs4227 - Write CS4227 register 77542b6eecSMark Rustad * @hw: pointer to hardware structure 78542b6eecSMark Rustad * @reg: register number to write 79542b6eecSMark Rustad * @value: value to write to register 80542b6eecSMark Rustad * 81542b6eecSMark Rustad * Returns status code 82542b6eecSMark Rustad */ 83542b6eecSMark Rustad static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) 84542b6eecSMark Rustad { 85542b6eecSMark Rustad return hw->phy.ops.write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, 86542b6eecSMark Rustad value); 87542b6eecSMark Rustad } 88542b6eecSMark Rustad 89542b6eecSMark Rustad /** 90542b6eecSMark Rustad * ixgbe_read_pe - Read register from port expander 91542b6eecSMark Rustad * @hw: pointer to hardware structure 92542b6eecSMark Rustad * @reg: register number to read 93542b6eecSMark Rustad * @value: pointer to receive read value 94542b6eecSMark Rustad * 95542b6eecSMark Rustad * Returns status code 96542b6eecSMark Rustad */ 97542b6eecSMark Rustad static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) 98542b6eecSMark Rustad { 99542b6eecSMark Rustad s32 status; 100542b6eecSMark Rustad 101542b6eecSMark Rustad status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, value); 102542b6eecSMark Rustad if (status) 103542b6eecSMark Rustad hw_err(hw, "port expander access failed with %d\n", status); 104542b6eecSMark Rustad return status; 105542b6eecSMark Rustad } 106542b6eecSMark Rustad 107542b6eecSMark Rustad /** 108542b6eecSMark Rustad * ixgbe_write_pe - Write register to port expander 109542b6eecSMark Rustad * @hw: pointer to hardware structure 110542b6eecSMark Rustad * @reg: register number to write 111542b6eecSMark Rustad * @value: value to write 112542b6eecSMark Rustad * 113542b6eecSMark Rustad * Returns status code 114542b6eecSMark Rustad */ 115542b6eecSMark Rustad static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) 116542b6eecSMark Rustad { 117542b6eecSMark Rustad s32 status; 118542b6eecSMark Rustad 119542b6eecSMark Rustad status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, 120542b6eecSMark Rustad value); 121542b6eecSMark Rustad if (status) 122542b6eecSMark Rustad hw_err(hw, "port expander access failed with %d\n", status); 123542b6eecSMark Rustad return status; 124542b6eecSMark Rustad } 125542b6eecSMark Rustad 126542b6eecSMark Rustad /** 127542b6eecSMark Rustad * ixgbe_reset_cs4227 - Reset CS4227 using port expander 128542b6eecSMark Rustad * @hw: pointer to hardware structure 129542b6eecSMark Rustad * 1308bf7a7b8SMark Rustad * This function assumes that the caller has acquired the proper semaphore. 131542b6eecSMark Rustad * Returns error code 132542b6eecSMark Rustad */ 133542b6eecSMark Rustad static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) 134542b6eecSMark Rustad { 135542b6eecSMark Rustad s32 status; 136542b6eecSMark Rustad u32 retry; 137542b6eecSMark Rustad u16 value; 138542b6eecSMark Rustad u8 reg; 139542b6eecSMark Rustad 140542b6eecSMark Rustad /* Trigger hard reset. */ 141542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 142542b6eecSMark Rustad if (status) 143542b6eecSMark Rustad return status; 144542b6eecSMark Rustad reg |= IXGBE_PE_BIT1; 145542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 146542b6eecSMark Rustad if (status) 147542b6eecSMark Rustad return status; 148542b6eecSMark Rustad 149542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); 150542b6eecSMark Rustad if (status) 151542b6eecSMark Rustad return status; 152542b6eecSMark Rustad reg &= ~IXGBE_PE_BIT1; 153542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); 154542b6eecSMark Rustad if (status) 155542b6eecSMark Rustad return status; 156542b6eecSMark Rustad 157542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 158542b6eecSMark Rustad if (status) 159542b6eecSMark Rustad return status; 160542b6eecSMark Rustad reg &= ~IXGBE_PE_BIT1; 161542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 162542b6eecSMark Rustad if (status) 163542b6eecSMark Rustad return status; 164542b6eecSMark Rustad 165542b6eecSMark Rustad usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100); 166542b6eecSMark Rustad 167542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 168542b6eecSMark Rustad if (status) 169542b6eecSMark Rustad return status; 170542b6eecSMark Rustad reg |= IXGBE_PE_BIT1; 171542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 172542b6eecSMark Rustad if (status) 173542b6eecSMark Rustad return status; 174542b6eecSMark Rustad 175542b6eecSMark Rustad /* Wait for the reset to complete. */ 176542b6eecSMark Rustad msleep(IXGBE_CS4227_RESET_DELAY); 177542b6eecSMark Rustad for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 178542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, 179542b6eecSMark Rustad &value); 180542b6eecSMark Rustad if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK) 181542b6eecSMark Rustad break; 182542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 183542b6eecSMark Rustad } 184542b6eecSMark Rustad if (retry == IXGBE_CS4227_RETRIES) { 185542b6eecSMark Rustad hw_err(hw, "CS4227 reset did not complete\n"); 186542b6eecSMark Rustad return IXGBE_ERR_PHY; 187542b6eecSMark Rustad } 188542b6eecSMark Rustad 189542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value); 190542b6eecSMark Rustad if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { 191542b6eecSMark Rustad hw_err(hw, "CS4227 EEPROM did not load successfully\n"); 192542b6eecSMark Rustad return IXGBE_ERR_PHY; 193542b6eecSMark Rustad } 194542b6eecSMark Rustad 195542b6eecSMark Rustad return 0; 196542b6eecSMark Rustad } 197542b6eecSMark Rustad 198542b6eecSMark Rustad /** 199542b6eecSMark Rustad * ixgbe_check_cs4227 - Check CS4227 and reset as needed 200542b6eecSMark Rustad * @hw: pointer to hardware structure 201542b6eecSMark Rustad */ 202542b6eecSMark Rustad static void ixgbe_check_cs4227(struct ixgbe_hw *hw) 203542b6eecSMark Rustad { 204542b6eecSMark Rustad u32 swfw_mask = hw->phy.phy_semaphore_mask; 205542b6eecSMark Rustad s32 status; 206542b6eecSMark Rustad u16 value; 207542b6eecSMark Rustad u8 retry; 208542b6eecSMark Rustad 209542b6eecSMark Rustad for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 210542b6eecSMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 211542b6eecSMark Rustad if (status) { 212542b6eecSMark Rustad hw_err(hw, "semaphore failed with %d\n", status); 213542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 214542b6eecSMark Rustad continue; 215542b6eecSMark Rustad } 216542b6eecSMark Rustad 217542b6eecSMark Rustad /* Get status of reset flow. */ 218542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); 219542b6eecSMark Rustad if (!status && value == IXGBE_CS4227_RESET_COMPLETE) 220542b6eecSMark Rustad goto out; 221542b6eecSMark Rustad 222542b6eecSMark Rustad if (status || value != IXGBE_CS4227_RESET_PENDING) 223542b6eecSMark Rustad break; 224542b6eecSMark Rustad 225542b6eecSMark Rustad /* Reset is pending. Wait and check again. */ 226542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 227542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 228542b6eecSMark Rustad } 2298bf7a7b8SMark Rustad /* If still pending, assume other instance failed. */ 2308bf7a7b8SMark Rustad if (retry == IXGBE_CS4227_RETRIES) { 2318bf7a7b8SMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 2328bf7a7b8SMark Rustad if (status) { 2338bf7a7b8SMark Rustad hw_err(hw, "semaphore failed with %d\n", status); 2348bf7a7b8SMark Rustad return; 2358bf7a7b8SMark Rustad } 2368bf7a7b8SMark Rustad } 237542b6eecSMark Rustad 238542b6eecSMark Rustad /* Reset the CS4227. */ 239542b6eecSMark Rustad status = ixgbe_reset_cs4227(hw); 240542b6eecSMark Rustad if (status) { 241542b6eecSMark Rustad hw_err(hw, "CS4227 reset failed: %d", status); 242542b6eecSMark Rustad goto out; 243542b6eecSMark Rustad } 244542b6eecSMark Rustad 245542b6eecSMark Rustad /* Reset takes so long, temporarily release semaphore in case the 246542b6eecSMark Rustad * other driver instance is waiting for the reset indication. 247542b6eecSMark Rustad */ 248542b6eecSMark Rustad ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 249542b6eecSMark Rustad IXGBE_CS4227_RESET_PENDING); 250542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 251542b6eecSMark Rustad usleep_range(10000, 12000); 252542b6eecSMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 253542b6eecSMark Rustad if (status) { 254542b6eecSMark Rustad hw_err(hw, "semaphore failed with %d", status); 255542b6eecSMark Rustad return; 256542b6eecSMark Rustad } 257542b6eecSMark Rustad 258542b6eecSMark Rustad /* Record completion for next time. */ 259542b6eecSMark Rustad status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 260542b6eecSMark Rustad IXGBE_CS4227_RESET_COMPLETE); 261542b6eecSMark Rustad 262542b6eecSMark Rustad out: 263542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 264542b6eecSMark Rustad msleep(hw->eeprom.semaphore_delay); 265542b6eecSMark Rustad } 266542b6eecSMark Rustad 2676a14ee0cSDon Skidmore /** ixgbe_identify_phy_x550em - Get PHY type based on device id 2686a14ee0cSDon Skidmore * @hw: pointer to hardware structure 2696a14ee0cSDon Skidmore * 2706a14ee0cSDon Skidmore * Returns error code 2716a14ee0cSDon Skidmore */ 2726a14ee0cSDon Skidmore static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) 2736a14ee0cSDon Skidmore { 2746a14ee0cSDon Skidmore switch (hw->device_id) { 2756a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 2766a14ee0cSDon Skidmore /* set up for CS4227 usage */ 2776a14ee0cSDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 278ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 279542b6eecSMark Rustad ixgbe_check_cs4227(hw); 2806a14ee0cSDon Skidmore return ixgbe_identify_module_generic(hw); 2816a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 2826a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kx4; 2836a14ee0cSDon Skidmore break; 2846a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 2856a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kr; 2866a14ee0cSDon Skidmore break; 2876a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 2886a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 2896a14ee0cSDon Skidmore return ixgbe_identify_phy_generic(hw); 2906a14ee0cSDon Skidmore default: 2916a14ee0cSDon Skidmore break; 2926a14ee0cSDon Skidmore } 2936a14ee0cSDon Skidmore return 0; 2946a14ee0cSDon Skidmore } 2956a14ee0cSDon Skidmore 2966a14ee0cSDon Skidmore static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 2976a14ee0cSDon Skidmore u32 device_type, u16 *phy_data) 2986a14ee0cSDon Skidmore { 2996a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 3006a14ee0cSDon Skidmore } 3016a14ee0cSDon Skidmore 3026a14ee0cSDon Skidmore static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 3036a14ee0cSDon Skidmore u32 device_type, u16 phy_data) 3046a14ee0cSDon Skidmore { 3056a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 3066a14ee0cSDon Skidmore } 3076a14ee0cSDon Skidmore 3086a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 3096a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3106a14ee0cSDon Skidmore * 3116a14ee0cSDon Skidmore * Initializes the EEPROM parameters ixgbe_eeprom_info within the 3126a14ee0cSDon Skidmore * ixgbe_hw struct in order to set up EEPROM access. 3136a14ee0cSDon Skidmore **/ 3147ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 3156a14ee0cSDon Skidmore { 3166a14ee0cSDon Skidmore struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 3176a14ee0cSDon Skidmore u32 eec; 3186a14ee0cSDon Skidmore u16 eeprom_size; 3196a14ee0cSDon Skidmore 3206a14ee0cSDon Skidmore if (eeprom->type == ixgbe_eeprom_uninitialized) { 3216a14ee0cSDon Skidmore eeprom->semaphore_delay = 10; 3226a14ee0cSDon Skidmore eeprom->type = ixgbe_flash; 3236a14ee0cSDon Skidmore 3249a900ecaSDon Skidmore eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 3256a14ee0cSDon Skidmore eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 3266a14ee0cSDon Skidmore IXGBE_EEC_SIZE_SHIFT); 3276a14ee0cSDon Skidmore eeprom->word_size = 1 << (eeprom_size + 3286a14ee0cSDon Skidmore IXGBE_EEPROM_WORD_SIZE_SHIFT); 3296a14ee0cSDon Skidmore 3306a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 3316a14ee0cSDon Skidmore eeprom->type, eeprom->word_size); 3326a14ee0cSDon Skidmore } 3336a14ee0cSDon Skidmore 3346a14ee0cSDon Skidmore return 0; 3356a14ee0cSDon Skidmore } 3366a14ee0cSDon Skidmore 337ae14a1d8SMark Rustad /** 338ae14a1d8SMark Rustad * ixgbe_iosf_wait - Wait for IOSF command completion 339ae14a1d8SMark Rustad * @hw: pointer to hardware structure 340ae14a1d8SMark Rustad * @ctrl: pointer to location to receive final IOSF control value 341ae14a1d8SMark Rustad * 342ae14a1d8SMark Rustad * Return: failing status on timeout 343ae14a1d8SMark Rustad * 344ae14a1d8SMark Rustad * Note: ctrl can be NULL if the IOSF control register value is not needed 345ae14a1d8SMark Rustad */ 346ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 347ae14a1d8SMark Rustad { 348ae14a1d8SMark Rustad u32 i, command; 349ae14a1d8SMark Rustad 350ae14a1d8SMark Rustad /* Check every 10 usec to see if the address cycle completed. 351ae14a1d8SMark Rustad * The SB IOSF BUSY bit will clear when the operation is 352ae14a1d8SMark Rustad * complete. 353ae14a1d8SMark Rustad */ 354ae14a1d8SMark Rustad for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 355ae14a1d8SMark Rustad command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 356ae14a1d8SMark Rustad if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 357ae14a1d8SMark Rustad break; 358ae14a1d8SMark Rustad usleep_range(10, 20); 359ae14a1d8SMark Rustad } 360ae14a1d8SMark Rustad if (ctrl) 361ae14a1d8SMark Rustad *ctrl = command; 362ae14a1d8SMark Rustad if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 363ae14a1d8SMark Rustad hw_dbg(hw, "IOSF wait timed out\n"); 364ae14a1d8SMark Rustad return IXGBE_ERR_PHY; 365ae14a1d8SMark Rustad } 366ae14a1d8SMark Rustad 367ae14a1d8SMark Rustad return 0; 368ae14a1d8SMark Rustad } 369ae14a1d8SMark Rustad 3706a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 3716a14ee0cSDon Skidmore * IOSF device 3726a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3736a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 3746a14ee0cSDon Skidmore * @device_type: 3 bit device type 3756a14ee0cSDon Skidmore * @phy_data: Pointer to read data from the register 3766a14ee0cSDon Skidmore **/ 3777ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 3786a14ee0cSDon Skidmore u32 device_type, u32 *data) 3796a14ee0cSDon Skidmore { 380ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 381ae14a1d8SMark Rustad u32 command, error; 382ae14a1d8SMark Rustad s32 ret; 383ae14a1d8SMark Rustad 384ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 385ae14a1d8SMark Rustad if (ret) 386ae14a1d8SMark Rustad return ret; 387ae14a1d8SMark Rustad 388ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 389ae14a1d8SMark Rustad if (ret) 390ae14a1d8SMark Rustad goto out; 3916a14ee0cSDon Skidmore 3926a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 3936a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 3946a14ee0cSDon Skidmore 3956a14ee0cSDon Skidmore /* Write IOSF control register */ 3966a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 3976a14ee0cSDon Skidmore 398ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 3996a14ee0cSDon Skidmore 4006a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 4016a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 4026a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 4036a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read, error %x\n", error); 4046a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 4056a14ee0cSDon Skidmore } 4066a14ee0cSDon Skidmore 407ae14a1d8SMark Rustad if (!ret) 4086a14ee0cSDon Skidmore *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 4096a14ee0cSDon Skidmore 410ae14a1d8SMark Rustad out: 411ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 412ae14a1d8SMark Rustad return ret; 4136a14ee0cSDon Skidmore } 4146a14ee0cSDon Skidmore 4156a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface 4166a14ee0cSDon Skidmore * command assuming that the semaphore is already obtained. 4176a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4186a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 4196a14ee0cSDon Skidmore * @data: word read from the EEPROM 4206a14ee0cSDon Skidmore * 4216a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 4226a14ee0cSDon Skidmore **/ 4237ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 4247ddbde3fSDon Skidmore u16 *data) 4256a14ee0cSDon Skidmore { 4266a14ee0cSDon Skidmore s32 status; 4276a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 4286a14ee0cSDon Skidmore 4296a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 4306a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 4316a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 4326a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 4336a14ee0cSDon Skidmore 4346a14ee0cSDon Skidmore /* convert offset from words to bytes */ 4356a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 4366a14ee0cSDon Skidmore /* one word */ 4376a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 4386a14ee0cSDon Skidmore 4396a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 4406a14ee0cSDon Skidmore sizeof(buffer), 4416a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 4426a14ee0cSDon Skidmore if (status) 4436a14ee0cSDon Skidmore return status; 4446a14ee0cSDon Skidmore 4456a14ee0cSDon Skidmore *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 4466a14ee0cSDon Skidmore FW_NVM_DATA_OFFSET); 4476a14ee0cSDon Skidmore 4486a14ee0cSDon Skidmore return 0; 4496a14ee0cSDon Skidmore } 4506a14ee0cSDon Skidmore 4516a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 4526a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4536a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 4546a14ee0cSDon Skidmore * @words: number of words 4556a14ee0cSDon Skidmore * @data: word(s) read from the EEPROM 4566a14ee0cSDon Skidmore * 4576a14ee0cSDon Skidmore * Reads a 16 bit word(s) from the EEPROM using the hostif. 4586a14ee0cSDon Skidmore **/ 4597ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 4606a14ee0cSDon Skidmore u16 offset, u16 words, u16 *data) 4616a14ee0cSDon Skidmore { 4626a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 4636a14ee0cSDon Skidmore u32 current_word = 0; 4646a14ee0cSDon Skidmore u16 words_to_read; 4656a14ee0cSDon Skidmore s32 status; 4666a14ee0cSDon Skidmore u32 i; 4676a14ee0cSDon Skidmore 4686a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 4696a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 4706a14ee0cSDon Skidmore if (status) { 4716a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 4726a14ee0cSDon Skidmore return status; 4736a14ee0cSDon Skidmore } 4746a14ee0cSDon Skidmore 4756a14ee0cSDon Skidmore while (words) { 4766a14ee0cSDon Skidmore if (words > FW_MAX_READ_BUFFER_SIZE / 2) 4776a14ee0cSDon Skidmore words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 4786a14ee0cSDon Skidmore else 4796a14ee0cSDon Skidmore words_to_read = words; 4806a14ee0cSDon Skidmore 4816a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 4826a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 4836a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 4846a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 4856a14ee0cSDon Skidmore 4866a14ee0cSDon Skidmore /* convert offset from words to bytes */ 4876a14ee0cSDon Skidmore buffer.address = cpu_to_be32((offset + current_word) * 2); 4886a14ee0cSDon Skidmore buffer.length = cpu_to_be16(words_to_read * 2); 4896a14ee0cSDon Skidmore 4906a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 4916a14ee0cSDon Skidmore sizeof(buffer), 4926a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, 4936a14ee0cSDon Skidmore false); 4946a14ee0cSDon Skidmore if (status) { 4956a14ee0cSDon Skidmore hw_dbg(hw, "Host interface command failed\n"); 4966a14ee0cSDon Skidmore goto out; 4976a14ee0cSDon Skidmore } 4986a14ee0cSDon Skidmore 4996a14ee0cSDon Skidmore for (i = 0; i < words_to_read; i++) { 5006a14ee0cSDon Skidmore u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 5016a14ee0cSDon Skidmore 2 * i; 5026a14ee0cSDon Skidmore u32 value = IXGBE_READ_REG(hw, reg); 5036a14ee0cSDon Skidmore 5046a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 5056a14ee0cSDon Skidmore current_word++; 5066a14ee0cSDon Skidmore i++; 5076a14ee0cSDon Skidmore if (i < words_to_read) { 5086a14ee0cSDon Skidmore value >>= 16; 5096a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 5106a14ee0cSDon Skidmore current_word++; 5116a14ee0cSDon Skidmore } 5126a14ee0cSDon Skidmore } 5136a14ee0cSDon Skidmore words -= words_to_read; 5146a14ee0cSDon Skidmore } 5156a14ee0cSDon Skidmore 5166a14ee0cSDon Skidmore out: 5176a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 5186a14ee0cSDon Skidmore return status; 5196a14ee0cSDon Skidmore } 5206a14ee0cSDon Skidmore 5216a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region 5226a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5236a14ee0cSDon Skidmore * @ptr: pointer offset in eeprom 5246a14ee0cSDon Skidmore * @size: size of section pointed by ptr, if 0 first word will be used as size 5256a14ee0cSDon Skidmore * @csum: address of checksum to update 5266a14ee0cSDon Skidmore * 5276a14ee0cSDon Skidmore * Returns error status for any failure 5286a14ee0cSDon Skidmore **/ 5296a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 5306a14ee0cSDon Skidmore u16 size, u16 *csum, u16 *buffer, 5316a14ee0cSDon Skidmore u32 buffer_size) 5326a14ee0cSDon Skidmore { 5336a14ee0cSDon Skidmore u16 buf[256]; 5346a14ee0cSDon Skidmore s32 status; 5356a14ee0cSDon Skidmore u16 length, bufsz, i, start; 5366a14ee0cSDon Skidmore u16 *local_buffer; 5376a14ee0cSDon Skidmore 5386a14ee0cSDon Skidmore bufsz = sizeof(buf) / sizeof(buf[0]); 5396a14ee0cSDon Skidmore 5406a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 5416a14ee0cSDon Skidmore if (!buffer) { 5426a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 5436a14ee0cSDon Skidmore if (status) { 5446a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 5456a14ee0cSDon Skidmore return status; 5466a14ee0cSDon Skidmore } 5476a14ee0cSDon Skidmore local_buffer = buf; 5486a14ee0cSDon Skidmore } else { 5496a14ee0cSDon Skidmore if (buffer_size < ptr) 5506a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 5516a14ee0cSDon Skidmore local_buffer = &buffer[ptr]; 5526a14ee0cSDon Skidmore } 5536a14ee0cSDon Skidmore 5546a14ee0cSDon Skidmore if (size) { 5556a14ee0cSDon Skidmore start = 0; 5566a14ee0cSDon Skidmore length = size; 5576a14ee0cSDon Skidmore } else { 5586a14ee0cSDon Skidmore start = 1; 5596a14ee0cSDon Skidmore length = local_buffer[0]; 5606a14ee0cSDon Skidmore 5616a14ee0cSDon Skidmore /* Skip pointer section if length is invalid. */ 5626a14ee0cSDon Skidmore if (length == 0xFFFF || length == 0 || 5636a14ee0cSDon Skidmore (ptr + length) >= hw->eeprom.word_size) 5646a14ee0cSDon Skidmore return 0; 5656a14ee0cSDon Skidmore } 5666a14ee0cSDon Skidmore 5676a14ee0cSDon Skidmore if (buffer && ((u32)start + (u32)length > buffer_size)) 5686a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 5696a14ee0cSDon Skidmore 5706a14ee0cSDon Skidmore for (i = start; length; i++, length--) { 5716a14ee0cSDon Skidmore if (i == bufsz && !buffer) { 5726a14ee0cSDon Skidmore ptr += bufsz; 5736a14ee0cSDon Skidmore i = 0; 5746a14ee0cSDon Skidmore if (length < bufsz) 5756a14ee0cSDon Skidmore bufsz = length; 5766a14ee0cSDon Skidmore 5776a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 5786a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 5796a14ee0cSDon Skidmore bufsz, buf); 5806a14ee0cSDon Skidmore if (status) { 5816a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 5826a14ee0cSDon Skidmore return status; 5836a14ee0cSDon Skidmore } 5846a14ee0cSDon Skidmore } 5856a14ee0cSDon Skidmore *csum += local_buffer[i]; 5866a14ee0cSDon Skidmore } 5876a14ee0cSDon Skidmore return 0; 5886a14ee0cSDon Skidmore } 5896a14ee0cSDon Skidmore 5906a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 5916a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5926a14ee0cSDon Skidmore * @buffer: pointer to buffer containing calculated checksum 5936a14ee0cSDon Skidmore * @buffer_size: size of buffer 5946a14ee0cSDon Skidmore * 5956a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 5966a14ee0cSDon Skidmore **/ 5977ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 5987ddbde3fSDon Skidmore u32 buffer_size) 5996a14ee0cSDon Skidmore { 6006a14ee0cSDon Skidmore u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 6016a14ee0cSDon Skidmore u16 *local_buffer; 6026a14ee0cSDon Skidmore s32 status; 6036a14ee0cSDon Skidmore u16 checksum = 0; 6046a14ee0cSDon Skidmore u16 pointer, i, size; 6056a14ee0cSDon Skidmore 6066a14ee0cSDon Skidmore hw->eeprom.ops.init_params(hw); 6076a14ee0cSDon Skidmore 6086a14ee0cSDon Skidmore if (!buffer) { 6096a14ee0cSDon Skidmore /* Read pointer area */ 6106a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 6116a14ee0cSDon Skidmore IXGBE_EEPROM_LAST_WORD + 1, 6126a14ee0cSDon Skidmore eeprom_ptrs); 6136a14ee0cSDon Skidmore if (status) { 6146a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 6156a14ee0cSDon Skidmore return status; 6166a14ee0cSDon Skidmore } 6176a14ee0cSDon Skidmore local_buffer = eeprom_ptrs; 6186a14ee0cSDon Skidmore } else { 6196a14ee0cSDon Skidmore if (buffer_size < IXGBE_EEPROM_LAST_WORD) 6206a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 6216a14ee0cSDon Skidmore local_buffer = buffer; 6226a14ee0cSDon Skidmore } 6236a14ee0cSDon Skidmore 6246a14ee0cSDon Skidmore /* For X550 hardware include 0x0-0x41 in the checksum, skip the 6256a14ee0cSDon Skidmore * checksum word itself 6266a14ee0cSDon Skidmore */ 6276a14ee0cSDon Skidmore for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 6286a14ee0cSDon Skidmore if (i != IXGBE_EEPROM_CHECKSUM) 6296a14ee0cSDon Skidmore checksum += local_buffer[i]; 6306a14ee0cSDon Skidmore 6316a14ee0cSDon Skidmore /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 6326a14ee0cSDon Skidmore * FW, PHY module, and PCIe Expansion/Option ROM pointers. 6336a14ee0cSDon Skidmore */ 6346a14ee0cSDon Skidmore for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 6356a14ee0cSDon Skidmore if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 6366a14ee0cSDon Skidmore continue; 6376a14ee0cSDon Skidmore 6386a14ee0cSDon Skidmore pointer = local_buffer[i]; 6396a14ee0cSDon Skidmore 6406a14ee0cSDon Skidmore /* Skip pointer section if the pointer is invalid. */ 6416a14ee0cSDon Skidmore if (pointer == 0xFFFF || pointer == 0 || 6426a14ee0cSDon Skidmore pointer >= hw->eeprom.word_size) 6436a14ee0cSDon Skidmore continue; 6446a14ee0cSDon Skidmore 6456a14ee0cSDon Skidmore switch (i) { 6466a14ee0cSDon Skidmore case IXGBE_PCIE_GENERAL_PTR: 6476a14ee0cSDon Skidmore size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 6486a14ee0cSDon Skidmore break; 6496a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG0_PTR: 6506a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG1_PTR: 6516a14ee0cSDon Skidmore size = IXGBE_PCIE_CONFIG_SIZE; 6526a14ee0cSDon Skidmore break; 6536a14ee0cSDon Skidmore default: 6546a14ee0cSDon Skidmore size = 0; 6556a14ee0cSDon Skidmore break; 6566a14ee0cSDon Skidmore } 6576a14ee0cSDon Skidmore 6586a14ee0cSDon Skidmore status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 6596a14ee0cSDon Skidmore buffer, buffer_size); 6606a14ee0cSDon Skidmore if (status) 6616a14ee0cSDon Skidmore return status; 6626a14ee0cSDon Skidmore } 6636a14ee0cSDon Skidmore 6646a14ee0cSDon Skidmore checksum = (u16)IXGBE_EEPROM_SUM - checksum; 6656a14ee0cSDon Skidmore 6666a14ee0cSDon Skidmore return (s32)checksum; 6676a14ee0cSDon Skidmore } 6686a14ee0cSDon Skidmore 6696a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 6706a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6716a14ee0cSDon Skidmore * 6726a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 6736a14ee0cSDon Skidmore **/ 6747ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 6756a14ee0cSDon Skidmore { 6766a14ee0cSDon Skidmore return ixgbe_calc_checksum_X550(hw, NULL, 0); 6776a14ee0cSDon Skidmore } 6786a14ee0cSDon Skidmore 6796a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 6806a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6816a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 6826a14ee0cSDon Skidmore * @data: word read from the EEPROM 6836a14ee0cSDon Skidmore * 6846a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 6856a14ee0cSDon Skidmore **/ 6867ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 6876a14ee0cSDon Skidmore { 6886a14ee0cSDon Skidmore s32 status = 0; 6896a14ee0cSDon Skidmore 6906a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 6916a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_data_X550(hw, offset, data); 6926a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 6936a14ee0cSDon Skidmore } else { 6946a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 6956a14ee0cSDon Skidmore } 6966a14ee0cSDon Skidmore 6976a14ee0cSDon Skidmore return status; 6986a14ee0cSDon Skidmore } 6996a14ee0cSDon Skidmore 7006a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 7016a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7026a14ee0cSDon Skidmore * @checksum_val: calculated checksum 7036a14ee0cSDon Skidmore * 7046a14ee0cSDon Skidmore * Performs checksum calculation and validates the EEPROM checksum. If the 7056a14ee0cSDon Skidmore * caller does not need checksum_val, the value can be NULL. 7066a14ee0cSDon Skidmore **/ 7077ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 7087ddbde3fSDon Skidmore u16 *checksum_val) 7096a14ee0cSDon Skidmore { 7106a14ee0cSDon Skidmore s32 status; 7116a14ee0cSDon Skidmore u16 checksum; 7126a14ee0cSDon Skidmore u16 read_checksum = 0; 7136a14ee0cSDon Skidmore 7146a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 7156a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 7166a14ee0cSDon Skidmore * EEPROM read fails 7176a14ee0cSDon Skidmore */ 7186a14ee0cSDon Skidmore status = hw->eeprom.ops.read(hw, 0, &checksum); 7196a14ee0cSDon Skidmore if (status) { 7206a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 7216a14ee0cSDon Skidmore return status; 7226a14ee0cSDon Skidmore } 7236a14ee0cSDon Skidmore 7246a14ee0cSDon Skidmore status = hw->eeprom.ops.calc_checksum(hw); 7256a14ee0cSDon Skidmore if (status < 0) 7266a14ee0cSDon Skidmore return status; 7276a14ee0cSDon Skidmore 7286a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 7296a14ee0cSDon Skidmore 7306a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 7316a14ee0cSDon Skidmore &read_checksum); 7326a14ee0cSDon Skidmore if (status) 7336a14ee0cSDon Skidmore return status; 7346a14ee0cSDon Skidmore 7356a14ee0cSDon Skidmore /* Verify read checksum from EEPROM is the same as 7366a14ee0cSDon Skidmore * calculated checksum 7376a14ee0cSDon Skidmore */ 7386a14ee0cSDon Skidmore if (read_checksum != checksum) { 7396a14ee0cSDon Skidmore status = IXGBE_ERR_EEPROM_CHECKSUM; 7406a14ee0cSDon Skidmore hw_dbg(hw, "Invalid EEPROM checksum"); 7416a14ee0cSDon Skidmore } 7426a14ee0cSDon Skidmore 7436a14ee0cSDon Skidmore /* If the user cares, return the calculated checksum */ 7446a14ee0cSDon Skidmore if (checksum_val) 7456a14ee0cSDon Skidmore *checksum_val = checksum; 7466a14ee0cSDon Skidmore 7476a14ee0cSDon Skidmore return status; 7486a14ee0cSDon Skidmore } 7496a14ee0cSDon Skidmore 7506a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 7516a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7526a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 7536a14ee0cSDon Skidmore * @data: word write to the EEPROM 7546a14ee0cSDon Skidmore * 7556a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 7566a14ee0cSDon Skidmore **/ 7577ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 7587ddbde3fSDon Skidmore u16 data) 7596a14ee0cSDon Skidmore { 7606a14ee0cSDon Skidmore s32 status; 7616a14ee0cSDon Skidmore struct ixgbe_hic_write_shadow_ram buffer; 7626a14ee0cSDon Skidmore 7636a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 7646a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 7656a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 7666a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 7676a14ee0cSDon Skidmore 7686a14ee0cSDon Skidmore /* one word */ 7696a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 7706a14ee0cSDon Skidmore buffer.data = data; 7716a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 7726a14ee0cSDon Skidmore 7736a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 7746a14ee0cSDon Skidmore sizeof(buffer), 7756a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 7766a14ee0cSDon Skidmore return status; 7776a14ee0cSDon Skidmore } 7786a14ee0cSDon Skidmore 7796a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 7806a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7816a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 7826a14ee0cSDon Skidmore * @data: word write to the EEPROM 7836a14ee0cSDon Skidmore * 7846a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 7856a14ee0cSDon Skidmore **/ 7867ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 7876a14ee0cSDon Skidmore { 7886a14ee0cSDon Skidmore s32 status = 0; 7896a14ee0cSDon Skidmore 7906a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 7916a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 7926a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 7936a14ee0cSDon Skidmore } else { 7946a14ee0cSDon Skidmore hw_dbg(hw, "write ee hostif failed to get semaphore"); 7956a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 7966a14ee0cSDon Skidmore } 7976a14ee0cSDon Skidmore 7986a14ee0cSDon Skidmore return status; 7996a14ee0cSDon Skidmore } 8006a14ee0cSDon Skidmore 8016a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 8026a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8036a14ee0cSDon Skidmore * 8046a14ee0cSDon Skidmore * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 8056a14ee0cSDon Skidmore **/ 8067ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 8076a14ee0cSDon Skidmore { 8086a14ee0cSDon Skidmore s32 status = 0; 8096a14ee0cSDon Skidmore union ixgbe_hic_hdr2 buffer; 8106a14ee0cSDon Skidmore 8116a14ee0cSDon Skidmore buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 8126a14ee0cSDon Skidmore buffer.req.buf_lenh = 0; 8136a14ee0cSDon Skidmore buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 8146a14ee0cSDon Skidmore buffer.req.checksum = FW_DEFAULT_CHECKSUM; 8156a14ee0cSDon Skidmore 8166a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 8176a14ee0cSDon Skidmore sizeof(buffer), 8186a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 8196a14ee0cSDon Skidmore return status; 8206a14ee0cSDon Skidmore } 8216a14ee0cSDon Skidmore 822454c65ddSDon Skidmore /** 823454c65ddSDon Skidmore * ixgbe_get_bus_info_X550em - Set PCI bus info 824454c65ddSDon Skidmore * @hw: pointer to hardware structure 825454c65ddSDon Skidmore * 826454c65ddSDon Skidmore * Sets bus link width and speed to unknown because X550em is 827454c65ddSDon Skidmore * not a PCI device. 828454c65ddSDon Skidmore **/ 829454c65ddSDon Skidmore static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) 830454c65ddSDon Skidmore { 831f9328bc6SDon Skidmore hw->bus.type = ixgbe_bus_type_internal; 832454c65ddSDon Skidmore hw->bus.width = ixgbe_bus_width_unknown; 833454c65ddSDon Skidmore hw->bus.speed = ixgbe_bus_speed_unknown; 834454c65ddSDon Skidmore 835454c65ddSDon Skidmore hw->mac.ops.set_lan_id(hw); 836454c65ddSDon Skidmore 837454c65ddSDon Skidmore return 0; 838454c65ddSDon Skidmore } 839454c65ddSDon Skidmore 8401f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit 8411f9ac57cSDon Skidmore * 8421f9ac57cSDon Skidmore * Enables the Rx DMA unit for x550 8431f9ac57cSDon Skidmore **/ 8441f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 8451f9ac57cSDon Skidmore { 8461f9ac57cSDon Skidmore u32 rxctrl, pfdtxgswc; 8471f9ac57cSDon Skidmore s32 status; 8481f9ac57cSDon Skidmore struct ixgbe_hic_disable_rxen fw_cmd; 8491f9ac57cSDon Skidmore 8501f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 8511f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 8521f9ac57cSDon Skidmore pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 8531f9ac57cSDon Skidmore if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 8541f9ac57cSDon Skidmore pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 8551f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 8561f9ac57cSDon Skidmore hw->mac.set_lben = true; 8571f9ac57cSDon Skidmore } else { 8581f9ac57cSDon Skidmore hw->mac.set_lben = false; 8591f9ac57cSDon Skidmore } 8601f9ac57cSDon Skidmore 8611f9ac57cSDon Skidmore fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 8621f9ac57cSDon Skidmore fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 8631f9ac57cSDon Skidmore fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 8641f9ac57cSDon Skidmore fw_cmd.port_number = (u8)hw->bus.lan_id; 8651f9ac57cSDon Skidmore 8661f9ac57cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 8671f9ac57cSDon Skidmore sizeof(struct ixgbe_hic_disable_rxen), 8681f9ac57cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, true); 8691f9ac57cSDon Skidmore 8701f9ac57cSDon Skidmore /* If we fail - disable RX using register write */ 8711f9ac57cSDon Skidmore if (status) { 8721f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 8731f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 8741f9ac57cSDon Skidmore rxctrl &= ~IXGBE_RXCTRL_RXEN; 8751f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 8761f9ac57cSDon Skidmore } 8771f9ac57cSDon Skidmore } 8781f9ac57cSDon Skidmore } 8791f9ac57cSDon Skidmore } 8801f9ac57cSDon Skidmore 8816a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 8826a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8836a14ee0cSDon Skidmore * 8846a14ee0cSDon Skidmore * After writing EEPROM to shadow RAM using EEWR register, software calculates 8856a14ee0cSDon Skidmore * checksum and updates the EEPROM and instructs the hardware to update 8866a14ee0cSDon Skidmore * the flash. 8876a14ee0cSDon Skidmore **/ 8887ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 8896a14ee0cSDon Skidmore { 8906a14ee0cSDon Skidmore s32 status; 8916a14ee0cSDon Skidmore u16 checksum = 0; 8926a14ee0cSDon Skidmore 8936a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 8946a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 8956a14ee0cSDon Skidmore * EEPROM read fails 8966a14ee0cSDon Skidmore */ 8976a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 8986a14ee0cSDon Skidmore if (status) { 8996a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 9006a14ee0cSDon Skidmore return status; 9016a14ee0cSDon Skidmore } 9026a14ee0cSDon Skidmore 9036a14ee0cSDon Skidmore status = ixgbe_calc_eeprom_checksum_X550(hw); 9046a14ee0cSDon Skidmore if (status < 0) 9056a14ee0cSDon Skidmore return status; 9066a14ee0cSDon Skidmore 9076a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 9086a14ee0cSDon Skidmore 9096a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 9106a14ee0cSDon Skidmore checksum); 9116a14ee0cSDon Skidmore if (status) 9126a14ee0cSDon Skidmore return status; 9136a14ee0cSDon Skidmore 9146a14ee0cSDon Skidmore status = ixgbe_update_flash_X550(hw); 9156a14ee0cSDon Skidmore 9166a14ee0cSDon Skidmore return status; 9176a14ee0cSDon Skidmore } 9186a14ee0cSDon Skidmore 9196a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 9206a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9216a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 9226a14ee0cSDon Skidmore * @words: number of words 9236a14ee0cSDon Skidmore * @data: word(s) write to the EEPROM 9246a14ee0cSDon Skidmore * 9256a14ee0cSDon Skidmore * 9266a14ee0cSDon Skidmore * Write a 16 bit word(s) to the EEPROM using the hostif. 9276a14ee0cSDon Skidmore **/ 9287ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 9297ddbde3fSDon Skidmore u16 offset, u16 words, 9307ddbde3fSDon Skidmore u16 *data) 9316a14ee0cSDon Skidmore { 9326a14ee0cSDon Skidmore s32 status = 0; 9336a14ee0cSDon Skidmore u32 i = 0; 9346a14ee0cSDon Skidmore 9356a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 9366a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 9376a14ee0cSDon Skidmore if (status) { 9386a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 9396a14ee0cSDon Skidmore return status; 9406a14ee0cSDon Skidmore } 9416a14ee0cSDon Skidmore 9426a14ee0cSDon Skidmore for (i = 0; i < words; i++) { 9436a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 9446a14ee0cSDon Skidmore data[i]); 9456a14ee0cSDon Skidmore if (status) { 9466a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom buffered write failed\n"); 9476a14ee0cSDon Skidmore break; 9486a14ee0cSDon Skidmore } 9496a14ee0cSDon Skidmore } 9506a14ee0cSDon Skidmore 9516a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 9526a14ee0cSDon Skidmore 9536a14ee0cSDon Skidmore return status; 9546a14ee0cSDon Skidmore } 9556a14ee0cSDon Skidmore 9566a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 9576a14ee0cSDon Skidmore * IOSF device 9586a14ee0cSDon Skidmore * 9596a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9606a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 9616a14ee0cSDon Skidmore * @device_type: 3 bit device type 9626a14ee0cSDon Skidmore * @data: Data to write to the register 9636a14ee0cSDon Skidmore **/ 9647ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 9656a14ee0cSDon Skidmore u32 device_type, u32 data) 9666a14ee0cSDon Skidmore { 967ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 968ae14a1d8SMark Rustad u32 command, error; 969ae14a1d8SMark Rustad s32 ret; 970ae14a1d8SMark Rustad 971ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 972ae14a1d8SMark Rustad if (ret) 973ae14a1d8SMark Rustad return ret; 974ae14a1d8SMark Rustad 975ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 976ae14a1d8SMark Rustad if (ret) 977ae14a1d8SMark Rustad goto out; 9786a14ee0cSDon Skidmore 9796a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 9806a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 9816a14ee0cSDon Skidmore 9826a14ee0cSDon Skidmore /* Write IOSF control register */ 9836a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 9846a14ee0cSDon Skidmore 9856a14ee0cSDon Skidmore /* Write IOSF data register */ 9866a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 9876a14ee0cSDon Skidmore 988ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 9896a14ee0cSDon Skidmore 9906a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 9916a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 9926a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 9936a14ee0cSDon Skidmore hw_dbg(hw, "Failed to write, error %x\n", error); 9946a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 9956a14ee0cSDon Skidmore } 9966a14ee0cSDon Skidmore 997ae14a1d8SMark Rustad out: 998ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 999ae14a1d8SMark Rustad return ret; 10006a14ee0cSDon Skidmore } 10016a14ee0cSDon Skidmore 10026a14ee0cSDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 10036a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10046a14ee0cSDon Skidmore * @speed: the link speed to force 10056a14ee0cSDon Skidmore * 10066a14ee0cSDon Skidmore * Configures the integrated KR PHY to use iXFI mode. Used to connect an 10076a14ee0cSDon Skidmore * internal and external PHY at a specific speed, without autonegotiation. 10086a14ee0cSDon Skidmore **/ 10096a14ee0cSDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 10106a14ee0cSDon Skidmore { 10116a14ee0cSDon Skidmore s32 status; 10126a14ee0cSDon Skidmore u32 reg_val; 10136a14ee0cSDon Skidmore 10146a14ee0cSDon Skidmore /* Disable AN and force speed to 10G Serial. */ 10156a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 10166a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 10176a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 10186a14ee0cSDon Skidmore if (status) 10196a14ee0cSDon Skidmore return status; 10206a14ee0cSDon Skidmore 10216a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 10226a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 10236a14ee0cSDon Skidmore 10246a14ee0cSDon Skidmore /* Select forced link speed for internal PHY. */ 10256a14ee0cSDon Skidmore switch (*speed) { 10266a14ee0cSDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 10276a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 10286a14ee0cSDon Skidmore break; 10296a14ee0cSDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 10306a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 10316a14ee0cSDon Skidmore break; 10326a14ee0cSDon Skidmore default: 10336a14ee0cSDon Skidmore /* Other link speeds are not supported by internal KR PHY. */ 10346a14ee0cSDon Skidmore return IXGBE_ERR_LINK_SETUP; 10356a14ee0cSDon Skidmore } 10366a14ee0cSDon Skidmore 10376a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 1038bec4e68eSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 10396a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 10406a14ee0cSDon Skidmore if (status) 10416a14ee0cSDon Skidmore return status; 10426a14ee0cSDon Skidmore 10436a14ee0cSDon Skidmore /* Disable training protocol FSM. */ 10446a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 10456a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 10466a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 10476a14ee0cSDon Skidmore if (status) 10486a14ee0cSDon Skidmore return status; 10496a14ee0cSDon Skidmore 10506a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 10516a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 10526a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 10536a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 10546a14ee0cSDon Skidmore if (status) 10556a14ee0cSDon Skidmore return status; 10566a14ee0cSDon Skidmore 10576a14ee0cSDon Skidmore /* Disable Flex from training TXFFE. */ 10586a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 10596a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 10606a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 10616a14ee0cSDon Skidmore if (status) 10626a14ee0cSDon Skidmore return status; 10636a14ee0cSDon Skidmore 10646a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 10656a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 10666a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 10676a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 10686a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 10696a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 10706a14ee0cSDon Skidmore if (status) 10716a14ee0cSDon Skidmore return status; 10726a14ee0cSDon Skidmore 10736a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 10746a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 10756a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 10766a14ee0cSDon Skidmore if (status) 10776a14ee0cSDon Skidmore return status; 10786a14ee0cSDon Skidmore 10796a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 10806a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 10816a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 10826a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 10836a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 10846a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 10856a14ee0cSDon Skidmore if (status) 10866a14ee0cSDon Skidmore return status; 10876a14ee0cSDon Skidmore 10886a14ee0cSDon Skidmore /* Enable override for coefficients. */ 10896a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 10906a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 10916a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 10926a14ee0cSDon Skidmore if (status) 10936a14ee0cSDon Skidmore return status; 10946a14ee0cSDon Skidmore 10956a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 10966a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 10976a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 10986a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 10996a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 11006a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 11016a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 11026a14ee0cSDon Skidmore if (status) 11036a14ee0cSDon Skidmore return status; 11046a14ee0cSDon Skidmore 11056a14ee0cSDon Skidmore /* Toggle port SW reset by AN reset. */ 11066a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 11076a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 11086a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 11096a14ee0cSDon Skidmore if (status) 11106a14ee0cSDon Skidmore return status; 11116a14ee0cSDon Skidmore 11126a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 11136a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 11146a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 11156a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 11166a14ee0cSDon Skidmore 11176a14ee0cSDon Skidmore return status; 11186a14ee0cSDon Skidmore } 11196a14ee0cSDon Skidmore 1120c3dc4c09SDon Skidmore /** 1121e23f3336SMark Rustad * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported 1122e23f3336SMark Rustad * @hw: pointer to hardware structure 1123e23f3336SMark Rustad * @linear: true if SFP module is linear 1124e23f3336SMark Rustad */ 1125e23f3336SMark Rustad static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) 1126e23f3336SMark Rustad { 1127e23f3336SMark Rustad switch (hw->phy.sfp_type) { 1128e23f3336SMark Rustad case ixgbe_sfp_type_not_present: 1129e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_PRESENT; 1130e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core0: 1131e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core1: 1132e23f3336SMark Rustad *linear = true; 1133e23f3336SMark Rustad break; 1134e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core0: 1135e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core1: 1136e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core0: 1137e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core1: 1138e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core0: 1139e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core1: 1140e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core0: 1141e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core1: 1142e23f3336SMark Rustad *linear = false; 1143e23f3336SMark Rustad break; 1144e23f3336SMark Rustad case ixgbe_sfp_type_unknown: 1145e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core0: 1146e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core1: 1147e23f3336SMark Rustad default: 1148e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_SUPPORTED; 1149e23f3336SMark Rustad } 1150e23f3336SMark Rustad 1151e23f3336SMark Rustad return 0; 1152e23f3336SMark Rustad } 1153e23f3336SMark Rustad 1154e23f3336SMark Rustad /** 11556d373a1bSMark Rustad * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. 11566d373a1bSMark Rustad * @hw: pointer to hardware structure 11576d373a1bSMark Rustad * 11586d373a1bSMark Rustad * Configures the extern PHY and the integrated KR PHY for SFP support. 11596d373a1bSMark Rustad */ 11606d373a1bSMark Rustad static s32 11616d373a1bSMark Rustad ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, 11626d373a1bSMark Rustad ixgbe_link_speed speed, 11636d373a1bSMark Rustad __always_unused bool autoneg_wait_to_complete) 11646d373a1bSMark Rustad { 1165e23f3336SMark Rustad s32 status; 1166e23f3336SMark Rustad u16 slice, value; 1167e23f3336SMark Rustad bool setup_linear = false; 1168e23f3336SMark Rustad 1169e23f3336SMark Rustad /* Check if SFP module is supported and linear */ 1170e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 1171e23f3336SMark Rustad 1172e23f3336SMark Rustad /* If no SFP module present, then return success. Return success since 1173e23f3336SMark Rustad * there is no reason to configure CS4227 and SFP not present error is 1174e23f3336SMark Rustad * not accepted in the setup MAC link flow. 1175e23f3336SMark Rustad */ 1176e23f3336SMark Rustad if (status == IXGBE_ERR_SFP_NOT_PRESENT) 1177e23f3336SMark Rustad return 0; 1178e23f3336SMark Rustad 1179e23f3336SMark Rustad if (status) 1180e23f3336SMark Rustad return status; 1181e23f3336SMark Rustad 1182d91e3a7dSMark Rustad if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1183e23f3336SMark Rustad /* Configure CS4227 LINE side to 10G SR. */ 1184e23f3336SMark Rustad slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12); 1185e23f3336SMark Rustad value = IXGBE_CS4227_SPEED_10G; 1186d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1187d91e3a7dSMark Rustad slice, value); 1188d91e3a7dSMark Rustad if (status) 1189d91e3a7dSMark Rustad goto i2c_err; 1190d91e3a7dSMark Rustad 1191d91e3a7dSMark Rustad slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 1192d91e3a7dSMark Rustad value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 1193d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1194d91e3a7dSMark Rustad slice, value); 1195d91e3a7dSMark Rustad if (status) 1196d91e3a7dSMark Rustad goto i2c_err; 1197e23f3336SMark Rustad 1198e23f3336SMark Rustad /* Configure CS4227 for HOST connection rate then type. */ 1199e23f3336SMark Rustad slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12); 1200e23f3336SMark Rustad value = speed & IXGBE_LINK_SPEED_10GB_FULL ? 1201e23f3336SMark Rustad IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; 1202d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1203d91e3a7dSMark Rustad slice, value); 1204d91e3a7dSMark Rustad if (status) 1205d91e3a7dSMark Rustad goto i2c_err; 1206e23f3336SMark Rustad 1207e23f3336SMark Rustad slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12); 1208e23f3336SMark Rustad if (setup_linear) 1209e23f3336SMark Rustad value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 1210e23f3336SMark Rustad else 1211e23f3336SMark Rustad value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 1212d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1213d91e3a7dSMark Rustad slice, value); 1214d91e3a7dSMark Rustad if (status) 1215d91e3a7dSMark Rustad goto i2c_err; 1216e23f3336SMark Rustad 1217d91e3a7dSMark Rustad /* Setup XFI internal link. */ 1218e23f3336SMark Rustad status = ixgbe_setup_ixfi_x550em(hw, &speed); 1219d91e3a7dSMark Rustad if (status) { 1220d91e3a7dSMark Rustad hw_dbg(hw, "setup_ixfi failed with %d\n", status); 1221d91e3a7dSMark Rustad return status; 1222d91e3a7dSMark Rustad } 1223d91e3a7dSMark Rustad } else { 1224d91e3a7dSMark Rustad /* Configure internal PHY for KR/KX. */ 1225d91e3a7dSMark Rustad status = ixgbe_setup_kr_speed_x550em(hw, speed); 1226d91e3a7dSMark Rustad if (status) { 1227d91e3a7dSMark Rustad hw_dbg(hw, "setup_kr_speed failed with %d\n", status); 1228d91e3a7dSMark Rustad return status; 1229d91e3a7dSMark Rustad } 1230e23f3336SMark Rustad 1231d91e3a7dSMark Rustad /* Configure CS4227 LINE side to proper mode. */ 1232d91e3a7dSMark Rustad slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 1233d91e3a7dSMark Rustad if (setup_linear) 1234d91e3a7dSMark Rustad value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 1235d91e3a7dSMark Rustad else 1236d91e3a7dSMark Rustad value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 1237d91e3a7dSMark Rustad status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, 1238d91e3a7dSMark Rustad slice, value); 1239d91e3a7dSMark Rustad if (status) 1240d91e3a7dSMark Rustad goto i2c_err; 1241d91e3a7dSMark Rustad } 1242d91e3a7dSMark Rustad 1243d91e3a7dSMark Rustad return 0; 1244d91e3a7dSMark Rustad 1245d91e3a7dSMark Rustad i2c_err: 1246d91e3a7dSMark Rustad hw_dbg(hw, "combined i2c access failed with %d\n", status); 1247e23f3336SMark Rustad return status; 12486d373a1bSMark Rustad } 12496d373a1bSMark Rustad 12506d373a1bSMark Rustad /** 1251c3dc4c09SDon Skidmore * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 1252c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1253c3dc4c09SDon Skidmore * @speed: new link speed 1254c3dc4c09SDon Skidmore * @autoneg_wait_to_complete: true when waiting for completion is needed 1255c3dc4c09SDon Skidmore * 1256c3dc4c09SDon Skidmore * Setup internal/external PHY link speed based on link speed, then set 1257c3dc4c09SDon Skidmore * external PHY auto advertised link speed. 1258c3dc4c09SDon Skidmore * 1259c3dc4c09SDon Skidmore * Returns error status for any failure 1260c3dc4c09SDon Skidmore **/ 1261c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 1262c3dc4c09SDon Skidmore ixgbe_link_speed speed, 1263c3dc4c09SDon Skidmore bool autoneg_wait) 1264c3dc4c09SDon Skidmore { 1265c3dc4c09SDon Skidmore s32 status; 1266c3dc4c09SDon Skidmore ixgbe_link_speed force_speed; 1267c3dc4c09SDon Skidmore 1268c3dc4c09SDon Skidmore /* Setup internal/external PHY link speed to iXFI (10G), unless 1269c3dc4c09SDon Skidmore * only 1G is auto advertised then setup KX link. 1270c3dc4c09SDon Skidmore */ 1271c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1272c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 1273c3dc4c09SDon Skidmore else 1274c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 1275c3dc4c09SDon Skidmore 1276c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup XFI internal link. */ 1277c3dc4c09SDon Skidmore if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1278c3dc4c09SDon Skidmore status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 1279c3dc4c09SDon Skidmore 1280c3dc4c09SDon Skidmore if (status) 1281c3dc4c09SDon Skidmore return status; 1282c3dc4c09SDon Skidmore } 1283c3dc4c09SDon Skidmore 1284c3dc4c09SDon Skidmore return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 1285c3dc4c09SDon Skidmore } 1286c3dc4c09SDon Skidmore 1287a4e293a5SDon Skidmore /** ixgbe_check_link_t_X550em - Determine link and speed status 1288a4e293a5SDon Skidmore * @hw: pointer to hardware structure 1289a4e293a5SDon Skidmore * @speed: pointer to link speed 1290a4e293a5SDon Skidmore * @link_up: true when link is up 1291a4e293a5SDon Skidmore * @link_up_wait_to_complete: bool used to wait for link up or not 1292a4e293a5SDon Skidmore * 1293a4e293a5SDon Skidmore * Check that both the MAC and X557 external PHY have link. 1294a4e293a5SDon Skidmore **/ 1295a4e293a5SDon Skidmore static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, 1296a4e293a5SDon Skidmore ixgbe_link_speed *speed, 1297a4e293a5SDon Skidmore bool *link_up, 1298a4e293a5SDon Skidmore bool link_up_wait_to_complete) 1299a4e293a5SDon Skidmore { 1300a4e293a5SDon Skidmore u32 status; 1301a4e293a5SDon Skidmore u16 autoneg_status; 1302a4e293a5SDon Skidmore 1303a4e293a5SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 1304a4e293a5SDon Skidmore return IXGBE_ERR_CONFIG; 1305a4e293a5SDon Skidmore 1306a4e293a5SDon Skidmore status = ixgbe_check_mac_link_generic(hw, speed, link_up, 1307a4e293a5SDon Skidmore link_up_wait_to_complete); 1308a4e293a5SDon Skidmore 1309a4e293a5SDon Skidmore /* If check link fails or MAC link is not up, then return */ 1310a4e293a5SDon Skidmore if (status || !(*link_up)) 1311a4e293a5SDon Skidmore return status; 1312a4e293a5SDon Skidmore 1313a4e293a5SDon Skidmore /* MAC link is up, so check external PHY link. 1314a4e293a5SDon Skidmore * Read this twice back to back to indicate current status. 1315a4e293a5SDon Skidmore */ 1316a4e293a5SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 1317a4e293a5SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 1318a4e293a5SDon Skidmore &autoneg_status); 1319a4e293a5SDon Skidmore if (status) 1320a4e293a5SDon Skidmore return status; 1321a4e293a5SDon Skidmore 1322a4e293a5SDon Skidmore /* If external PHY link is not up, then indicate link not up */ 1323a4e293a5SDon Skidmore if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 1324a4e293a5SDon Skidmore *link_up = false; 1325a4e293a5SDon Skidmore 1326a4e293a5SDon Skidmore return 0; 1327a4e293a5SDon Skidmore } 1328a4e293a5SDon Skidmore 1329c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 1330c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1331c3dc4c09SDon Skidmore **/ 1332c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 1333c3dc4c09SDon Skidmore { 1334c3dc4c09SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 1335c3dc4c09SDon Skidmore 1336c3dc4c09SDon Skidmore switch (mac->ops.get_media_type(hw)) { 1337c3dc4c09SDon Skidmore case ixgbe_media_type_fiber: 1338c3dc4c09SDon Skidmore /* CS4227 does not support autoneg, so disable the laser control 1339c3dc4c09SDon Skidmore * functions for SFP+ fiber 1340c3dc4c09SDon Skidmore */ 1341c3dc4c09SDon Skidmore mac->ops.disable_tx_laser = NULL; 1342c3dc4c09SDon Skidmore mac->ops.enable_tx_laser = NULL; 1343c3dc4c09SDon Skidmore mac->ops.flap_tx_laser = NULL; 13446d373a1bSMark Rustad mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; 13456d373a1bSMark Rustad mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em; 13466d373a1bSMark Rustad mac->ops.set_rate_select_speed = 13476d373a1bSMark Rustad ixgbe_set_soft_rate_select_speed; 1348c3dc4c09SDon Skidmore break; 1349c3dc4c09SDon Skidmore case ixgbe_media_type_copper: 1350c3dc4c09SDon Skidmore mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 1351a4e293a5SDon Skidmore mac->ops.check_link = ixgbe_check_link_t_X550em; 1352c3dc4c09SDon Skidmore break; 1353c3dc4c09SDon Skidmore default: 1354c3dc4c09SDon Skidmore break; 1355c3dc4c09SDon Skidmore } 1356c3dc4c09SDon Skidmore } 1357c3dc4c09SDon Skidmore 1358c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module 1359c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1360c3dc4c09SDon Skidmore */ 1361c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 1362c3dc4c09SDon Skidmore { 1363e23f3336SMark Rustad s32 status; 1364e23f3336SMark Rustad bool linear; 1365c3dc4c09SDon Skidmore 1366e23f3336SMark Rustad /* Check if SFP module is supported */ 1367e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &linear); 1368e23f3336SMark Rustad if (status) 1369e23f3336SMark Rustad return status; 1370c3dc4c09SDon Skidmore 1371c3dc4c09SDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 1372c3dc4c09SDon Skidmore hw->phy.ops.reset = NULL; 1373c3dc4c09SDon Skidmore 1374e23f3336SMark Rustad return 0; 1375c3dc4c09SDon Skidmore } 1376c3dc4c09SDon Skidmore 1377c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities 1378c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1379c3dc4c09SDon Skidmore * @speed: pointer to link speed 1380c3dc4c09SDon Skidmore * @autoneg: true when autoneg or autotry is enabled 1381c3dc4c09SDon Skidmore **/ 1382c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 1383c3dc4c09SDon Skidmore ixgbe_link_speed *speed, 1384c3dc4c09SDon Skidmore bool *autoneg) 1385c3dc4c09SDon Skidmore { 1386c3dc4c09SDon Skidmore /* SFP */ 1387c3dc4c09SDon Skidmore if (hw->phy.media_type == ixgbe_media_type_fiber) { 1388c3dc4c09SDon Skidmore /* CS4227 SFP must not enable auto-negotiation */ 1389c3dc4c09SDon Skidmore *autoneg = false; 1390c3dc4c09SDon Skidmore 1391c3dc4c09SDon Skidmore if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 1392c3dc4c09SDon Skidmore hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { 1393c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 1394c3dc4c09SDon Skidmore return 0; 1395c3dc4c09SDon Skidmore } 1396c3dc4c09SDon Skidmore 1397c3dc4c09SDon Skidmore /* Link capabilities are based on SFP */ 1398c3dc4c09SDon Skidmore if (hw->phy.multispeed_fiber) 1399c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1400c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1401c3dc4c09SDon Skidmore else 1402c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL; 1403c3dc4c09SDon Skidmore } else { 1404c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1405c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1406c3dc4c09SDon Skidmore *autoneg = true; 1407c3dc4c09SDon Skidmore } 1408c3dc4c09SDon Skidmore return 0; 1409c3dc4c09SDon Skidmore } 1410c3dc4c09SDon Skidmore 1411c3dc4c09SDon Skidmore /** 1412c3dc4c09SDon Skidmore * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause 1413c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1414c3dc4c09SDon Skidmore * @lsc: pointer to boolean flag which indicates whether external Base T 1415c3dc4c09SDon Skidmore * PHY interrupt is lsc 1416c3dc4c09SDon Skidmore * 1417c3dc4c09SDon Skidmore * Determime if external Base T PHY interrupt cause is high temperature 1418c3dc4c09SDon Skidmore * failure alarm or link status change. 1419c3dc4c09SDon Skidmore * 1420c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1421c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1422c3dc4c09SDon Skidmore **/ 1423c3dc4c09SDon Skidmore static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) 1424c3dc4c09SDon Skidmore { 1425c3dc4c09SDon Skidmore u32 status; 1426c3dc4c09SDon Skidmore u16 reg; 1427c3dc4c09SDon Skidmore 1428c3dc4c09SDon Skidmore *lsc = false; 1429c3dc4c09SDon Skidmore 1430c3dc4c09SDon Skidmore /* Vendor alarm triggered */ 1431c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 1432c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1433c3dc4c09SDon Skidmore ®); 1434c3dc4c09SDon Skidmore 1435c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 1436c3dc4c09SDon Skidmore return status; 1437c3dc4c09SDon Skidmore 1438c3dc4c09SDon Skidmore /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 1439c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 1440c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1441c3dc4c09SDon Skidmore ®); 1442c3dc4c09SDon Skidmore 1443c3dc4c09SDon Skidmore if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1444c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 1445c3dc4c09SDon Skidmore return status; 1446c3dc4c09SDon Skidmore 1447c3dc4c09SDon Skidmore /* High temperature failure alarm triggered */ 1448c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 1449c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1450c3dc4c09SDon Skidmore ®); 1451c3dc4c09SDon Skidmore 1452c3dc4c09SDon Skidmore if (status) 1453c3dc4c09SDon Skidmore return status; 1454c3dc4c09SDon Skidmore 1455c3dc4c09SDon Skidmore /* If high temperature failure, then return over temp error and exit */ 1456c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 1457c3dc4c09SDon Skidmore /* power down the PHY in case the PHY FW didn't already */ 1458c3dc4c09SDon Skidmore ixgbe_set_copper_phy_power(hw, false); 1459c3dc4c09SDon Skidmore return IXGBE_ERR_OVERTEMP; 1460c3dc4c09SDon Skidmore } 1461c3dc4c09SDon Skidmore 1462c3dc4c09SDon Skidmore /* Vendor alarm 2 triggered */ 1463c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 1464c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1465c3dc4c09SDon Skidmore 1466c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 1467c3dc4c09SDon Skidmore return status; 1468c3dc4c09SDon Skidmore 1469c3dc4c09SDon Skidmore /* link connect/disconnect event occurred */ 1470c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 1471c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1472c3dc4c09SDon Skidmore 1473c3dc4c09SDon Skidmore if (status) 1474c3dc4c09SDon Skidmore return status; 1475c3dc4c09SDon Skidmore 1476c3dc4c09SDon Skidmore /* Indicate LSC */ 1477c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 1478c3dc4c09SDon Skidmore *lsc = true; 1479c3dc4c09SDon Skidmore 1480c3dc4c09SDon Skidmore return 0; 1481c3dc4c09SDon Skidmore } 1482c3dc4c09SDon Skidmore 1483c3dc4c09SDon Skidmore /** 1484c3dc4c09SDon Skidmore * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 1485c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1486c3dc4c09SDon Skidmore * 1487c3dc4c09SDon Skidmore * Enable link status change and temperature failure alarm for the external 1488c3dc4c09SDon Skidmore * Base T PHY 1489c3dc4c09SDon Skidmore * 1490c3dc4c09SDon Skidmore * Returns PHY access status 1491c3dc4c09SDon Skidmore **/ 1492c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1493c3dc4c09SDon Skidmore { 1494c3dc4c09SDon Skidmore u32 status; 1495c3dc4c09SDon Skidmore u16 reg; 1496c3dc4c09SDon Skidmore bool lsc; 1497c3dc4c09SDon Skidmore 1498c3dc4c09SDon Skidmore /* Clear interrupt flags */ 1499c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1500c3dc4c09SDon Skidmore 1501c3dc4c09SDon Skidmore /* Enable link status change alarm */ 1502c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 1503c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1504c3dc4c09SDon Skidmore if (status) 1505c3dc4c09SDon Skidmore return status; 1506c3dc4c09SDon Skidmore 1507c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 1508c3dc4c09SDon Skidmore 1509c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 1510c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); 1511c3dc4c09SDon Skidmore if (status) 1512c3dc4c09SDon Skidmore return status; 1513c3dc4c09SDon Skidmore 1514c3dc4c09SDon Skidmore /* Enables high temperature failure alarm */ 1515c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 1516c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1517c3dc4c09SDon Skidmore ®); 1518c3dc4c09SDon Skidmore if (status) 1519c3dc4c09SDon Skidmore return status; 1520c3dc4c09SDon Skidmore 1521c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN; 1522c3dc4c09SDon Skidmore 1523c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 1524c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1525c3dc4c09SDon Skidmore reg); 1526c3dc4c09SDon Skidmore if (status) 1527c3dc4c09SDon Skidmore return status; 1528c3dc4c09SDon Skidmore 1529c3dc4c09SDon Skidmore /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 1530c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 1531c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1532c3dc4c09SDon Skidmore ®); 1533c3dc4c09SDon Skidmore if (status) 1534c3dc4c09SDon Skidmore return status; 1535c3dc4c09SDon Skidmore 1536c3dc4c09SDon Skidmore reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1537c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT); 1538c3dc4c09SDon Skidmore 1539c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 1540c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1541c3dc4c09SDon Skidmore reg); 1542c3dc4c09SDon Skidmore if (status) 1543c3dc4c09SDon Skidmore return status; 1544c3dc4c09SDon Skidmore 1545c3dc4c09SDon Skidmore /* Enable chip-wide vendor alarm */ 1546c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 1547c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1548c3dc4c09SDon Skidmore ®); 1549c3dc4c09SDon Skidmore if (status) 1550c3dc4c09SDon Skidmore return status; 1551c3dc4c09SDon Skidmore 1552c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 1553c3dc4c09SDon Skidmore 1554c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 1555c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1556c3dc4c09SDon Skidmore reg); 1557c3dc4c09SDon Skidmore 1558c3dc4c09SDon Skidmore return status; 1559c3dc4c09SDon Skidmore } 1560c3dc4c09SDon Skidmore 1561c3dc4c09SDon Skidmore /** 1562c3dc4c09SDon Skidmore * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 1563c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1564c3dc4c09SDon Skidmore * 1565c3dc4c09SDon Skidmore * Handle external Base T PHY interrupt. If high temperature 1566c3dc4c09SDon Skidmore * failure alarm then return error, else if link status change 1567c3dc4c09SDon Skidmore * then setup internal/external PHY link 1568c3dc4c09SDon Skidmore * 1569c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1570c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1571c3dc4c09SDon Skidmore **/ 1572c3dc4c09SDon Skidmore static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1573c3dc4c09SDon Skidmore { 1574c3dc4c09SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 1575c3dc4c09SDon Skidmore bool lsc; 1576c3dc4c09SDon Skidmore u32 status; 1577c3dc4c09SDon Skidmore 1578c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1579c3dc4c09SDon Skidmore if (status) 1580c3dc4c09SDon Skidmore return status; 1581c3dc4c09SDon Skidmore 1582a85ce532SMark Rustad if (lsc && phy->ops.setup_internal_link) 1583c3dc4c09SDon Skidmore return phy->ops.setup_internal_link(hw); 1584c3dc4c09SDon Skidmore 1585c3dc4c09SDon Skidmore return 0; 1586c3dc4c09SDon Skidmore } 1587c3dc4c09SDon Skidmore 1588c3dc4c09SDon Skidmore /** 1589c3dc4c09SDon Skidmore * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 1590c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1591c3dc4c09SDon Skidmore * @speed: link speed 1592c3dc4c09SDon Skidmore * 1593c3dc4c09SDon Skidmore * Configures the integrated KR PHY. 1594c3dc4c09SDon Skidmore **/ 1595c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 1596c3dc4c09SDon Skidmore ixgbe_link_speed speed) 1597c3dc4c09SDon Skidmore { 1598c3dc4c09SDon Skidmore s32 status; 1599c3dc4c09SDon Skidmore u32 reg_val; 1600c3dc4c09SDon Skidmore 1601c3dc4c09SDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 1602c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1603c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 1604c3dc4c09SDon Skidmore if (status) 1605c3dc4c09SDon Skidmore return status; 1606c3dc4c09SDon Skidmore 1607c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1608c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ | 1609c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC); 1610c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 1611c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 1612c3dc4c09SDon Skidmore 1613c3dc4c09SDon Skidmore /* Advertise 10G support. */ 1614c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1615c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 1616c3dc4c09SDon Skidmore 1617c3dc4c09SDon Skidmore /* Advertise 1G support. */ 1618c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_1GB_FULL) 1619c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 1620c3dc4c09SDon Skidmore 1621c3dc4c09SDon Skidmore /* Restart auto-negotiation. */ 1622c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 1623c3dc4c09SDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 1624c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1625c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 1626c3dc4c09SDon Skidmore 1627c3dc4c09SDon Skidmore return status; 1628c3dc4c09SDon Skidmore } 1629c3dc4c09SDon Skidmore 16306a14ee0cSDon Skidmore /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. 16316a14ee0cSDon Skidmore * @hw: pointer to hardware structure 16326a14ee0cSDon Skidmore * 16336a14ee0cSDon Skidmore * Configures the integrated KX4 PHY. 16346a14ee0cSDon Skidmore **/ 16357ddbde3fSDon Skidmore static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) 16366a14ee0cSDon Skidmore { 16376a14ee0cSDon Skidmore s32 status; 16386a14ee0cSDon Skidmore u32 reg_val; 16396a14ee0cSDon Skidmore 16406a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, 16416a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 16426a14ee0cSDon Skidmore hw->bus.lan_id, ®_val); 16436a14ee0cSDon Skidmore if (status) 16446a14ee0cSDon Skidmore return status; 16456a14ee0cSDon Skidmore 16466a14ee0cSDon Skidmore reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | 16476a14ee0cSDon Skidmore IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); 16486a14ee0cSDon Skidmore 16496a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; 16506a14ee0cSDon Skidmore 16516a14ee0cSDon Skidmore /* Advertise 10G support. */ 16526a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) 16536a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; 16546a14ee0cSDon Skidmore 16556a14ee0cSDon Skidmore /* Advertise 1G support. */ 16566a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) 16576a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; 16586a14ee0cSDon Skidmore 16596a14ee0cSDon Skidmore /* Restart auto-negotiation. */ 16606a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; 16616a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, 16626a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 16636a14ee0cSDon Skidmore hw->bus.lan_id, reg_val); 16646a14ee0cSDon Skidmore 16656a14ee0cSDon Skidmore return status; 16666a14ee0cSDon Skidmore } 16676a14ee0cSDon Skidmore 16686a14ee0cSDon Skidmore /** ixgbe_setup_kr_x550em - Configure the KR PHY. 16696a14ee0cSDon Skidmore * @hw: pointer to hardware structure 16706a14ee0cSDon Skidmore * 16716a14ee0cSDon Skidmore * Configures the integrated KR PHY. 16726a14ee0cSDon Skidmore **/ 16737ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 16746a14ee0cSDon Skidmore { 1675c3dc4c09SDon Skidmore return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 16766a14ee0cSDon Skidmore } 16776a14ee0cSDon Skidmore 1678c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 1679c3dc4c09SDon Skidmore * @hw: address of hardware structure 1680c3dc4c09SDon Skidmore * @link_up: address of boolean to indicate link status 1681c3dc4c09SDon Skidmore * 1682c3dc4c09SDon Skidmore * Returns error code if unable to get link status. 1683c3dc4c09SDon Skidmore **/ 1684c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 1685c3dc4c09SDon Skidmore { 1686c3dc4c09SDon Skidmore u32 ret; 1687c3dc4c09SDon Skidmore u16 autoneg_status; 1688c3dc4c09SDon Skidmore 1689c3dc4c09SDon Skidmore *link_up = false; 1690c3dc4c09SDon Skidmore 1691c3dc4c09SDon Skidmore /* read this twice back to back to indicate current status */ 1692c3dc4c09SDon Skidmore ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 1693c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 1694c3dc4c09SDon Skidmore &autoneg_status); 1695c3dc4c09SDon Skidmore if (ret) 1696c3dc4c09SDon Skidmore return ret; 1697c3dc4c09SDon Skidmore 1698c3dc4c09SDon Skidmore ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 1699c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 1700c3dc4c09SDon Skidmore &autoneg_status); 1701c3dc4c09SDon Skidmore if (ret) 1702c3dc4c09SDon Skidmore return ret; 1703c3dc4c09SDon Skidmore 1704c3dc4c09SDon Skidmore *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 1705c3dc4c09SDon Skidmore 1706c3dc4c09SDon Skidmore return 0; 1707c3dc4c09SDon Skidmore } 1708c3dc4c09SDon Skidmore 1709c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 17106a14ee0cSDon Skidmore * @hw: point to hardware structure 17116a14ee0cSDon Skidmore * 1712c3dc4c09SDon Skidmore * Configures the link between the integrated KR PHY and the external X557 PHY 1713c3dc4c09SDon Skidmore * The driver will call this function when it gets a link status change 1714c3dc4c09SDon Skidmore * interrupt from the X557 PHY. This function configures the link speed 1715c3dc4c09SDon Skidmore * between the PHYs to match the link speed of the BASE-T link. 17166a14ee0cSDon Skidmore * 17176a14ee0cSDon Skidmore * A return of a non-zero value indicates an error, and the base driver should 17186a14ee0cSDon Skidmore * not report link up. 17196a14ee0cSDon Skidmore **/ 1720c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 17216a14ee0cSDon Skidmore { 17226a14ee0cSDon Skidmore ixgbe_link_speed force_speed; 1723c3dc4c09SDon Skidmore bool link_up; 1724c3dc4c09SDon Skidmore u32 status; 1725c3dc4c09SDon Skidmore u16 speed; 17266a14ee0cSDon Skidmore 1727c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 1728c3dc4c09SDon Skidmore return IXGBE_ERR_CONFIG; 1729c3dc4c09SDon Skidmore 1730f164b845SMark Rustad if (hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { 1731f164b845SMark Rustad speed = IXGBE_LINK_SPEED_10GB_FULL | 1732f164b845SMark Rustad IXGBE_LINK_SPEED_1GB_FULL; 1733f164b845SMark Rustad return ixgbe_setup_kr_speed_x550em(hw, speed); 1734f164b845SMark Rustad } 1735f164b845SMark Rustad 1736c3dc4c09SDon Skidmore /* If link is not up, then there is no setup necessary so return */ 1737c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 17386a14ee0cSDon Skidmore if (status) 17396a14ee0cSDon Skidmore return status; 17406a14ee0cSDon Skidmore 1741c3dc4c09SDon Skidmore if (!link_up) 17426a14ee0cSDon Skidmore return 0; 17436a14ee0cSDon Skidmore 17446a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 17456a14ee0cSDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 17466a14ee0cSDon Skidmore &speed); 1747c3dc4c09SDon Skidmore if (status) 1748c3dc4c09SDon Skidmore return status; 1749c3dc4c09SDon Skidmore 1750c3dc4c09SDon Skidmore /* If link is not still up, then no setup is necessary so return */ 1751c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 1752c3dc4c09SDon Skidmore if (status) 1753c3dc4c09SDon Skidmore return status; 1754c3dc4c09SDon Skidmore 1755c3dc4c09SDon Skidmore if (!link_up) 1756c3dc4c09SDon Skidmore return 0; 17576a14ee0cSDon Skidmore 17586a14ee0cSDon Skidmore /* clear everything but the speed and duplex bits */ 17596a14ee0cSDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 17606a14ee0cSDon Skidmore 17616a14ee0cSDon Skidmore switch (speed) { 17626a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 17636a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 17646a14ee0cSDon Skidmore break; 17656a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 17666a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 17676a14ee0cSDon Skidmore break; 17686a14ee0cSDon Skidmore default: 17696a14ee0cSDon Skidmore /* Internal PHY does not support anything else */ 17706a14ee0cSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 17716a14ee0cSDon Skidmore } 17726a14ee0cSDon Skidmore 17736a14ee0cSDon Skidmore return ixgbe_setup_ixfi_x550em(hw, &force_speed); 17746a14ee0cSDon Skidmore } 17756a14ee0cSDon Skidmore 1776f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 1777f4410d2cSDon Skidmore * @hw: pointer to hardware structure 1778f4410d2cSDon Skidmore **/ 1779f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 1780f4410d2cSDon Skidmore { 1781f4410d2cSDon Skidmore s32 status; 1782f4410d2cSDon Skidmore 1783f4410d2cSDon Skidmore status = ixgbe_reset_phy_generic(hw); 1784f4410d2cSDon Skidmore 1785f4410d2cSDon Skidmore if (status) 1786f4410d2cSDon Skidmore return status; 1787f4410d2cSDon Skidmore 1788f4410d2cSDon Skidmore /* Configure Link Status Alarm and Temperature Threshold interrupts */ 1789f4410d2cSDon Skidmore return ixgbe_enable_lasi_ext_t_x550em(hw); 1790f4410d2cSDon Skidmore } 1791f4410d2cSDon Skidmore 17926ac74394SDon Skidmore /** ixgbe_get_lcd_x550em - Determine lowest common denominator 17936ac74394SDon Skidmore * @hw: pointer to hardware structure 17946ac74394SDon Skidmore * @lcd_speed: pointer to lowest common link speed 17956ac74394SDon Skidmore * 17966ac74394SDon Skidmore * Determine lowest common link speed with link partner. 17976ac74394SDon Skidmore **/ 17986ac74394SDon Skidmore static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, 17996ac74394SDon Skidmore ixgbe_link_speed *lcd_speed) 18006ac74394SDon Skidmore { 18016ac74394SDon Skidmore u16 an_lp_status; 18026ac74394SDon Skidmore s32 status; 18036ac74394SDon Skidmore u16 word = hw->eeprom.ctrl_word_3; 18046ac74394SDon Skidmore 18056ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; 18066ac74394SDon Skidmore 18076ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, 18086ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 18096ac74394SDon Skidmore &an_lp_status); 18106ac74394SDon Skidmore if (status) 18116ac74394SDon Skidmore return status; 18126ac74394SDon Skidmore 18136ac74394SDon Skidmore /* If link partner advertised 1G, return 1G */ 18146ac74394SDon Skidmore if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { 18156ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; 18166ac74394SDon Skidmore return status; 18176ac74394SDon Skidmore } 18186ac74394SDon Skidmore 18196ac74394SDon Skidmore /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ 18206ac74394SDon Skidmore if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || 18216ac74394SDon Skidmore (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) 18226ac74394SDon Skidmore return status; 18236ac74394SDon Skidmore 18246ac74394SDon Skidmore /* Link partner not capable of lower speeds, return 10G */ 18256ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; 18266ac74394SDon Skidmore return status; 18276ac74394SDon Skidmore } 18286ac74394SDon Skidmore 18296ac74394SDon Skidmore /** ixgbe_enter_lplu_x550em - Transition to low power states 18306ac74394SDon Skidmore * @hw: pointer to hardware structure 18316ac74394SDon Skidmore * 18326ac74394SDon Skidmore * Configures Low Power Link Up on transition to low power states 18336ac74394SDon Skidmore * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting 18346ac74394SDon Skidmore * the X557 PHY immediately prior to entering LPLU. 18356ac74394SDon Skidmore **/ 18366ac74394SDon Skidmore static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) 18376ac74394SDon Skidmore { 18386ac74394SDon Skidmore u16 an_10g_cntl_reg, autoneg_reg, speed; 18396ac74394SDon Skidmore s32 status; 18406ac74394SDon Skidmore ixgbe_link_speed lcd_speed; 18416ac74394SDon Skidmore u32 save_autoneg; 18426ac74394SDon Skidmore bool link_up; 18436ac74394SDon Skidmore 18446ac74394SDon Skidmore /* SW LPLU not required on later HW revisions. */ 18456ac74394SDon Skidmore if (IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))) 18466ac74394SDon Skidmore return 0; 18476ac74394SDon Skidmore 18486ac74394SDon Skidmore /* If blocked by MNG FW, then don't restart AN */ 18496ac74394SDon Skidmore if (ixgbe_check_reset_blocked(hw)) 18506ac74394SDon Skidmore return 0; 18516ac74394SDon Skidmore 18526ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 18536ac74394SDon Skidmore if (status) 18546ac74394SDon Skidmore return status; 18556ac74394SDon Skidmore 18566ac74394SDon Skidmore status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, 18576ac74394SDon Skidmore &hw->eeprom.ctrl_word_3); 18586ac74394SDon Skidmore if (status) 18596ac74394SDon Skidmore return status; 18606ac74394SDon Skidmore 18616ac74394SDon Skidmore /* If link is down, LPLU disabled in NVM, WoL disabled, or 18626ac74394SDon Skidmore * manageability disabled, then force link down by entering 18636ac74394SDon Skidmore * low power mode. 18646ac74394SDon Skidmore */ 18656ac74394SDon Skidmore if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || 18666ac74394SDon Skidmore !(hw->wol_enabled || ixgbe_mng_present(hw))) 18676ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 18686ac74394SDon Skidmore 18696ac74394SDon Skidmore /* Determine LCD */ 18706ac74394SDon Skidmore status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); 18716ac74394SDon Skidmore if (status) 18726ac74394SDon Skidmore return status; 18736ac74394SDon Skidmore 18746ac74394SDon Skidmore /* If no valid LCD link speed, then force link down and exit. */ 18756ac74394SDon Skidmore if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) 18766ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 18776ac74394SDon Skidmore 18786ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 18796ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 18806ac74394SDon Skidmore &speed); 18816ac74394SDon Skidmore if (status) 18826ac74394SDon Skidmore return status; 18836ac74394SDon Skidmore 18846ac74394SDon Skidmore /* If no link now, speed is invalid so take link down */ 18856ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 18866ac74394SDon Skidmore if (status) 18876ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 18886ac74394SDon Skidmore 18896ac74394SDon Skidmore /* clear everything but the speed bits */ 18906ac74394SDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; 18916ac74394SDon Skidmore 18926ac74394SDon Skidmore /* If current speed is already LCD, then exit. */ 18936ac74394SDon Skidmore if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && 18946ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || 18956ac74394SDon Skidmore ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && 18966ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) 18976ac74394SDon Skidmore return status; 18986ac74394SDon Skidmore 18996ac74394SDon Skidmore /* Clear AN completed indication */ 19006ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, 19016ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 19026ac74394SDon Skidmore &autoneg_reg); 19036ac74394SDon Skidmore if (status) 19046ac74394SDon Skidmore return status; 19056ac74394SDon Skidmore 19066ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, 19076ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 19086ac74394SDon Skidmore &an_10g_cntl_reg); 19096ac74394SDon Skidmore if (status) 19106ac74394SDon Skidmore return status; 19116ac74394SDon Skidmore 19126ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, 19136ac74394SDon Skidmore IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, 19146ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 19156ac74394SDon Skidmore &autoneg_reg); 19166ac74394SDon Skidmore if (status) 19176ac74394SDon Skidmore return status; 19186ac74394SDon Skidmore 19196ac74394SDon Skidmore save_autoneg = hw->phy.autoneg_advertised; 19206ac74394SDon Skidmore 19216ac74394SDon Skidmore /* Setup link at least common link speed */ 19226ac74394SDon Skidmore status = hw->mac.ops.setup_link(hw, lcd_speed, false); 19236ac74394SDon Skidmore 19246ac74394SDon Skidmore /* restore autoneg from before setting lplu speed */ 19256ac74394SDon Skidmore hw->phy.autoneg_advertised = save_autoneg; 19266ac74394SDon Skidmore 19276ac74394SDon Skidmore return status; 19286ac74394SDon Skidmore } 19296ac74394SDon Skidmore 19306a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 19316a14ee0cSDon Skidmore * @hw: pointer to hardware structure 19326a14ee0cSDon Skidmore * 19336a14ee0cSDon Skidmore * Initialize any function pointers that were not able to be 19346a14ee0cSDon Skidmore * set during init_shared_code because the PHY/SFP type was 19356a14ee0cSDon Skidmore * not known. Perform the SFP init if necessary. 19366a14ee0cSDon Skidmore **/ 19377ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 19386a14ee0cSDon Skidmore { 19396a14ee0cSDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 19406a14ee0cSDon Skidmore s32 ret_val; 19416a14ee0cSDon Skidmore 19427e49d616SDon Skidmore hw->mac.ops.set_lan_id(hw); 19437e49d616SDon Skidmore 1944c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 19456a14ee0cSDon Skidmore phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 1946ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 1947c3dc4c09SDon Skidmore 1948c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 1949c3dc4c09SDon Skidmore * to determine internal PHY mode. 1950c3dc4c09SDon Skidmore */ 1951c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 19526a14ee0cSDon Skidmore } 19536a14ee0cSDon Skidmore 19546a14ee0cSDon Skidmore /* Identify the PHY or SFP module */ 19556a14ee0cSDon Skidmore ret_val = phy->ops.identify(hw); 19566a14ee0cSDon Skidmore 1957c3dc4c09SDon Skidmore /* Setup function pointers based on detected hardware */ 19586a14ee0cSDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 19596a14ee0cSDon Skidmore if (phy->sfp_type != ixgbe_sfp_type_unknown) 19606a14ee0cSDon Skidmore phy->ops.reset = NULL; 19616a14ee0cSDon Skidmore 19626a14ee0cSDon Skidmore /* Set functions pointers based on phy type */ 19636a14ee0cSDon Skidmore switch (hw->phy.type) { 19646a14ee0cSDon Skidmore case ixgbe_phy_x550em_kx4: 19656a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kx4_x550em; 19666a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 19676a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 19686a14ee0cSDon Skidmore break; 19696a14ee0cSDon Skidmore case ixgbe_phy_x550em_kr: 19706a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kr_x550em; 19716a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 19726a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 19736a14ee0cSDon Skidmore break; 19746a14ee0cSDon Skidmore case ixgbe_phy_x550em_ext_t: 1975c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 1976c3dc4c09SDon Skidmore * to determine internal PHY mode 1977c3dc4c09SDon Skidmore */ 1978c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 1979c3dc4c09SDon Skidmore 1980c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup iXFI internal link, 1981c3dc4c09SDon Skidmore * else setup KR now. 1982c3dc4c09SDon Skidmore */ 1983c3dc4c09SDon Skidmore phy->ops.setup_internal_link = 1984c3dc4c09SDon Skidmore ixgbe_setup_internal_phy_t_x550em; 1985c3dc4c09SDon Skidmore 19866ac74394SDon Skidmore /* setup SW LPLU only for first revision */ 19876ac74394SDon Skidmore if (!(IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, 19886ac74394SDon Skidmore IXGBE_FUSES0_GROUP(0)))) 19896ac74394SDon Skidmore phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; 19906ac74394SDon Skidmore 1991c3dc4c09SDon Skidmore phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 1992f4410d2cSDon Skidmore phy->ops.reset = ixgbe_reset_phy_t_X550em; 19936a14ee0cSDon Skidmore break; 19946a14ee0cSDon Skidmore default: 19956a14ee0cSDon Skidmore break; 19966a14ee0cSDon Skidmore } 1997c3dc4c09SDon Skidmore 19986a14ee0cSDon Skidmore return ret_val; 19996a14ee0cSDon Skidmore } 20006a14ee0cSDon Skidmore 20016a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type 20026a14ee0cSDon Skidmore * @hw: pointer to hardware structure 20036a14ee0cSDon Skidmore * 20046a14ee0cSDon Skidmore * Returns the media type (fiber, copper, backplane) 20056a14ee0cSDon Skidmore * 20066a14ee0cSDon Skidmore */ 20077ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 20086a14ee0cSDon Skidmore { 20096a14ee0cSDon Skidmore enum ixgbe_media_type media_type; 20106a14ee0cSDon Skidmore 20116a14ee0cSDon Skidmore /* Detect if there is a copper PHY attached. */ 20126a14ee0cSDon Skidmore switch (hw->device_id) { 20136a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 20146a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 20156a14ee0cSDon Skidmore media_type = ixgbe_media_type_backplane; 20166a14ee0cSDon Skidmore break; 20176a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 20186a14ee0cSDon Skidmore media_type = ixgbe_media_type_fiber; 20196a14ee0cSDon Skidmore break; 20206a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 20216a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 20226a14ee0cSDon Skidmore media_type = ixgbe_media_type_copper; 20236a14ee0cSDon Skidmore break; 20246a14ee0cSDon Skidmore default: 20256a14ee0cSDon Skidmore media_type = ixgbe_media_type_unknown; 20266a14ee0cSDon Skidmore break; 20276a14ee0cSDon Skidmore } 20286a14ee0cSDon Skidmore return media_type; 20296a14ee0cSDon Skidmore } 20306a14ee0cSDon Skidmore 20316a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 20326a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 20336a14ee0cSDon Skidmore **/ 20347ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 20356a14ee0cSDon Skidmore { 2036a1e869deSMark Rustad s32 status; 20376a14ee0cSDon Skidmore u16 reg; 20386a14ee0cSDon Skidmore 20396a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 20406a14ee0cSDon Skidmore IXGBE_MDIO_TX_VENDOR_ALARMS_3, 20416a14ee0cSDon Skidmore IXGBE_MDIO_PMA_PMD_DEV_TYPE, 20426a14ee0cSDon Skidmore ®); 20436a14ee0cSDon Skidmore if (status) 20446a14ee0cSDon Skidmore return status; 20456a14ee0cSDon Skidmore 2046e2261bccSDon Skidmore /* If PHY FW reset completed bit is set then this is the first 2047e2261bccSDon Skidmore * SW instance after a power on so the PHY FW must be un-stalled. 2048e2261bccSDon Skidmore */ 2049e2261bccSDon Skidmore if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 20506a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 20516a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 20526a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 20536a14ee0cSDon Skidmore ®); 20546a14ee0cSDon Skidmore if (status) 20556a14ee0cSDon Skidmore return status; 20566a14ee0cSDon Skidmore 20576a14ee0cSDon Skidmore reg &= ~IXGBE_MDIO_POWER_UP_STALL; 20586a14ee0cSDon Skidmore 20596a14ee0cSDon Skidmore status = hw->phy.ops.write_reg(hw, 20606a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 20616a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 20626a14ee0cSDon Skidmore reg); 2063e2261bccSDon Skidmore if (status) 2064e2261bccSDon Skidmore return status; 2065e2261bccSDon Skidmore } 2066e2261bccSDon Skidmore 20676a14ee0cSDon Skidmore return status; 20686a14ee0cSDon Skidmore } 20696a14ee0cSDon Skidmore 20706a14ee0cSDon Skidmore /** ixgbe_reset_hw_X550em - Perform hardware reset 20716a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 20726a14ee0cSDon Skidmore ** 20736a14ee0cSDon Skidmore ** Resets the hardware by resetting the transmit and receive units, masks 20746a14ee0cSDon Skidmore ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 20756a14ee0cSDon Skidmore ** reset. 20766a14ee0cSDon Skidmore **/ 20777ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 20786a14ee0cSDon Skidmore { 20796a14ee0cSDon Skidmore ixgbe_link_speed link_speed; 20806a14ee0cSDon Skidmore s32 status; 20816a14ee0cSDon Skidmore u32 ctrl = 0; 20826a14ee0cSDon Skidmore u32 i; 2083deda562aSDon Skidmore u32 hlreg0; 20846a14ee0cSDon Skidmore bool link_up = false; 20856a14ee0cSDon Skidmore 20866a14ee0cSDon Skidmore /* Call adapter stop to disable Tx/Rx and clear interrupts */ 20876a14ee0cSDon Skidmore status = hw->mac.ops.stop_adapter(hw); 20886a14ee0cSDon Skidmore if (status) 20896a14ee0cSDon Skidmore return status; 20906a14ee0cSDon Skidmore 20916a14ee0cSDon Skidmore /* flush pending Tx transactions */ 20926a14ee0cSDon Skidmore ixgbe_clear_tx_pending(hw); 20936a14ee0cSDon Skidmore 20946a14ee0cSDon Skidmore /* PHY ops must be identified and initialized prior to reset */ 20956a14ee0cSDon Skidmore 20966a14ee0cSDon Skidmore /* Identify PHY and related function pointers */ 20976a14ee0cSDon Skidmore status = hw->phy.ops.init(hw); 20986a14ee0cSDon Skidmore 20996a14ee0cSDon Skidmore /* start the external PHY */ 21006a14ee0cSDon Skidmore if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 21016a14ee0cSDon Skidmore status = ixgbe_init_ext_t_x550em(hw); 21026a14ee0cSDon Skidmore if (status) 21036a14ee0cSDon Skidmore return status; 21046a14ee0cSDon Skidmore } 21056a14ee0cSDon Skidmore 21066a14ee0cSDon Skidmore /* Setup SFP module if there is one present. */ 21076a14ee0cSDon Skidmore if (hw->phy.sfp_setup_needed) { 21086a14ee0cSDon Skidmore status = hw->mac.ops.setup_sfp(hw); 21096a14ee0cSDon Skidmore hw->phy.sfp_setup_needed = false; 21106a14ee0cSDon Skidmore } 21116a14ee0cSDon Skidmore 21126a14ee0cSDon Skidmore /* Reset PHY */ 21136a14ee0cSDon Skidmore if (!hw->phy.reset_disable && hw->phy.ops.reset) 21146a14ee0cSDon Skidmore hw->phy.ops.reset(hw); 21156a14ee0cSDon Skidmore 21166a14ee0cSDon Skidmore mac_reset_top: 21176a14ee0cSDon Skidmore /* Issue global reset to the MAC. Needs to be SW reset if link is up. 21186a14ee0cSDon Skidmore * If link reset is used when link is up, it might reset the PHY when 21196a14ee0cSDon Skidmore * mng is using it. If link is down or the flag to force full link 21206a14ee0cSDon Skidmore * reset is set, then perform link reset. 21216a14ee0cSDon Skidmore */ 21226a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_LNK_RST; 21236a14ee0cSDon Skidmore 21246a14ee0cSDon Skidmore if (!hw->force_full_reset) { 21256a14ee0cSDon Skidmore hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 21266a14ee0cSDon Skidmore if (link_up) 21276a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_RST; 21286a14ee0cSDon Skidmore } 21296a14ee0cSDon Skidmore 21306a14ee0cSDon Skidmore ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 21316a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 21326a14ee0cSDon Skidmore IXGBE_WRITE_FLUSH(hw); 21336a14ee0cSDon Skidmore 21346a14ee0cSDon Skidmore /* Poll for reset bit to self-clear meaning reset is complete */ 21356a14ee0cSDon Skidmore for (i = 0; i < 10; i++) { 21366a14ee0cSDon Skidmore udelay(1); 21376a14ee0cSDon Skidmore ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 21386a14ee0cSDon Skidmore if (!(ctrl & IXGBE_CTRL_RST_MASK)) 21396a14ee0cSDon Skidmore break; 21406a14ee0cSDon Skidmore } 21416a14ee0cSDon Skidmore 21426a14ee0cSDon Skidmore if (ctrl & IXGBE_CTRL_RST_MASK) { 21436a14ee0cSDon Skidmore status = IXGBE_ERR_RESET_FAILED; 21446a14ee0cSDon Skidmore hw_dbg(hw, "Reset polling failed to complete.\n"); 21456a14ee0cSDon Skidmore } 21466a14ee0cSDon Skidmore 21476a14ee0cSDon Skidmore msleep(50); 21486a14ee0cSDon Skidmore 21496a14ee0cSDon Skidmore /* Double resets are required for recovery from certain error 21506a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 21516a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 21526a14ee0cSDon Skidmore */ 21536a14ee0cSDon Skidmore if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 21546a14ee0cSDon Skidmore hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 21556a14ee0cSDon Skidmore goto mac_reset_top; 21566a14ee0cSDon Skidmore } 21576a14ee0cSDon Skidmore 21586a14ee0cSDon Skidmore /* Store the permanent mac address */ 21596a14ee0cSDon Skidmore hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 21606a14ee0cSDon Skidmore 21616a14ee0cSDon Skidmore /* Store MAC address from RAR0, clear receive address registers, and 21626a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 21636a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 21646a14ee0cSDon Skidmore */ 21656a14ee0cSDon Skidmore hw->mac.num_rar_entries = 128; 21666a14ee0cSDon Skidmore hw->mac.ops.init_rx_addrs(hw); 21676a14ee0cSDon Skidmore 2168deda562aSDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 2169deda562aSDon Skidmore hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 2170deda562aSDon Skidmore hlreg0 &= ~IXGBE_HLREG0_MDCSPD; 2171deda562aSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 2172deda562aSDon Skidmore } 2173deda562aSDon Skidmore 2174ab5fe0c5SDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 2175ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 2176ab5fe0c5SDon Skidmore 21776a14ee0cSDon Skidmore return status; 21786a14ee0cSDon Skidmore } 21796a14ee0cSDon Skidmore 21805b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 21815b7f000fSDon Skidmore * anti-spoofing 21825b7f000fSDon Skidmore * @hw: pointer to hardware structure 21835b7f000fSDon Skidmore * @enable: enable or disable switch for Ethertype anti-spoofing 21845b7f000fSDon Skidmore * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 21855b7f000fSDon Skidmore **/ 2186bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 2187bc035fc5SDon Skidmore bool enable, int vf) 21885b7f000fSDon Skidmore { 21895b7f000fSDon Skidmore int vf_target_reg = vf >> 3; 21905b7f000fSDon Skidmore int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 21915b7f000fSDon Skidmore u32 pfvfspoof; 21925b7f000fSDon Skidmore 21935b7f000fSDon Skidmore pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 21945b7f000fSDon Skidmore if (enable) 21955b7f000fSDon Skidmore pfvfspoof |= (1 << vf_target_shift); 21965b7f000fSDon Skidmore else 21975b7f000fSDon Skidmore pfvfspoof &= ~(1 << vf_target_shift); 21985b7f000fSDon Skidmore 21995b7f000fSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 22005b7f000fSDon Skidmore } 22015b7f000fSDon Skidmore 22026d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 22036d4c96adSDon Skidmore * @hw: pointer to hardware structure 22046d4c96adSDon Skidmore * @enable: enable or disable source address pruning 22056d4c96adSDon Skidmore * @pool: Rx pool to set source address pruning for 22066d4c96adSDon Skidmore **/ 22076d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 22086d4c96adSDon Skidmore bool enable, 22096d4c96adSDon Skidmore unsigned int pool) 22106d4c96adSDon Skidmore { 22116d4c96adSDon Skidmore u64 pfflp; 22126d4c96adSDon Skidmore 22136d4c96adSDon Skidmore /* max rx pool is 63 */ 22146d4c96adSDon Skidmore if (pool > 63) 22156d4c96adSDon Skidmore return; 22166d4c96adSDon Skidmore 22176d4c96adSDon Skidmore pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 22186d4c96adSDon Skidmore pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 22196d4c96adSDon Skidmore 22206d4c96adSDon Skidmore if (enable) 22216d4c96adSDon Skidmore pfflp |= (1ULL << pool); 22226d4c96adSDon Skidmore else 22236d4c96adSDon Skidmore pfflp &= ~(1ULL << pool); 22246d4c96adSDon Skidmore 22256d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 22266d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 22276d4c96adSDon Skidmore } 22286d4c96adSDon Skidmore 2229449e21a9SMark Rustad /** 2230449e21a9SMark Rustad * ixgbe_set_mux - Set mux for port 1 access with CS4227 2231449e21a9SMark Rustad * @hw: pointer to hardware structure 2232449e21a9SMark Rustad * @state: set mux if 1, clear if 0 2233449e21a9SMark Rustad */ 2234449e21a9SMark Rustad static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) 2235449e21a9SMark Rustad { 2236449e21a9SMark Rustad u32 esdp; 2237449e21a9SMark Rustad 2238449e21a9SMark Rustad if (!hw->bus.lan_id) 2239449e21a9SMark Rustad return; 2240449e21a9SMark Rustad esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 2241449e21a9SMark Rustad if (state) 2242449e21a9SMark Rustad esdp |= IXGBE_ESDP_SDP1; 2243449e21a9SMark Rustad else 2244449e21a9SMark Rustad esdp &= ~IXGBE_ESDP_SDP1; 2245449e21a9SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 2246449e21a9SMark Rustad IXGBE_WRITE_FLUSH(hw); 2247449e21a9SMark Rustad } 2248449e21a9SMark Rustad 2249449e21a9SMark Rustad /** 2250449e21a9SMark Rustad * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore 2251449e21a9SMark Rustad * @hw: pointer to hardware structure 2252449e21a9SMark Rustad * @mask: Mask to specify which semaphore to acquire 2253449e21a9SMark Rustad * 2254449e21a9SMark Rustad * Acquires the SWFW semaphore and sets the I2C MUX 2255449e21a9SMark Rustad */ 2256449e21a9SMark Rustad static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 2257449e21a9SMark Rustad { 2258449e21a9SMark Rustad s32 status; 2259449e21a9SMark Rustad 2260449e21a9SMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, mask); 2261449e21a9SMark Rustad if (status) 2262449e21a9SMark Rustad return status; 2263449e21a9SMark Rustad 2264449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 2265449e21a9SMark Rustad ixgbe_set_mux(hw, 1); 2266449e21a9SMark Rustad 2267449e21a9SMark Rustad return 0; 2268449e21a9SMark Rustad } 2269449e21a9SMark Rustad 2270449e21a9SMark Rustad /** 2271449e21a9SMark Rustad * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore 2272449e21a9SMark Rustad * @hw: pointer to hardware structure 2273449e21a9SMark Rustad * @mask: Mask to specify which semaphore to release 2274449e21a9SMark Rustad * 2275449e21a9SMark Rustad * Releases the SWFW semaphore and sets the I2C MUX 2276449e21a9SMark Rustad */ 2277449e21a9SMark Rustad static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 2278449e21a9SMark Rustad { 2279449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 2280449e21a9SMark Rustad ixgbe_set_mux(hw, 0); 2281449e21a9SMark Rustad 2282449e21a9SMark Rustad ixgbe_release_swfw_sync_X540(hw, mask); 2283449e21a9SMark Rustad } 2284449e21a9SMark Rustad 22856a14ee0cSDon Skidmore #define X550_COMMON_MAC \ 22866a14ee0cSDon Skidmore .init_hw = &ixgbe_init_hw_generic, \ 22876a14ee0cSDon Skidmore .start_hw = &ixgbe_start_hw_X540, \ 22886a14ee0cSDon Skidmore .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 22896a14ee0cSDon Skidmore .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 22906a14ee0cSDon Skidmore .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 22916a14ee0cSDon Skidmore .get_device_caps = &ixgbe_get_device_caps_generic, \ 22926a14ee0cSDon Skidmore .stop_adapter = &ixgbe_stop_adapter_generic, \ 22936a14ee0cSDon Skidmore .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 22946a14ee0cSDon Skidmore .read_analog_reg8 = NULL, \ 22956a14ee0cSDon Skidmore .write_analog_reg8 = NULL, \ 22966a14ee0cSDon Skidmore .set_rxpba = &ixgbe_set_rxpba_generic, \ 22976a14ee0cSDon Skidmore .check_link = &ixgbe_check_mac_link_generic, \ 22986a14ee0cSDon Skidmore .led_on = &ixgbe_led_on_generic, \ 22996a14ee0cSDon Skidmore .led_off = &ixgbe_led_off_generic, \ 23006a14ee0cSDon Skidmore .blink_led_start = &ixgbe_blink_led_start_X540, \ 23016a14ee0cSDon Skidmore .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 23026a14ee0cSDon Skidmore .set_rar = &ixgbe_set_rar_generic, \ 23036a14ee0cSDon Skidmore .clear_rar = &ixgbe_clear_rar_generic, \ 23046a14ee0cSDon Skidmore .set_vmdq = &ixgbe_set_vmdq_generic, \ 23056a14ee0cSDon Skidmore .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 23066a14ee0cSDon Skidmore .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 23076a14ee0cSDon Skidmore .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 23086a14ee0cSDon Skidmore .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 23096a14ee0cSDon Skidmore .enable_mc = &ixgbe_enable_mc_generic, \ 23106a14ee0cSDon Skidmore .disable_mc = &ixgbe_disable_mc_generic, \ 23116a14ee0cSDon Skidmore .clear_vfta = &ixgbe_clear_vfta_generic, \ 23126a14ee0cSDon Skidmore .set_vfta = &ixgbe_set_vfta_generic, \ 23136a14ee0cSDon Skidmore .fc_enable = &ixgbe_fc_enable_generic, \ 23146a14ee0cSDon Skidmore .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, \ 23156a14ee0cSDon Skidmore .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 23166a14ee0cSDon Skidmore .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 23176a14ee0cSDon Skidmore .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 23186d4c96adSDon Skidmore .set_source_address_pruning = \ 23196d4c96adSDon Skidmore &ixgbe_set_source_address_pruning_X550, \ 23205b7f000fSDon Skidmore .set_ethertype_anti_spoofing = \ 23215b7f000fSDon Skidmore &ixgbe_set_ethertype_anti_spoofing_X550, \ 23226a14ee0cSDon Skidmore .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 23236a14ee0cSDon Skidmore .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 23246a14ee0cSDon Skidmore .get_thermal_sensor_data = NULL, \ 23256a14ee0cSDon Skidmore .init_thermal_sensor_thresh = NULL, \ 23266a14ee0cSDon Skidmore .prot_autoc_read = &prot_autoc_read_generic, \ 23276a14ee0cSDon Skidmore .prot_autoc_write = &prot_autoc_write_generic, \ 23281f9ac57cSDon Skidmore .enable_rx = &ixgbe_enable_rx_generic, \ 23291f9ac57cSDon Skidmore .disable_rx = &ixgbe_disable_rx_x550, \ 23306a14ee0cSDon Skidmore 23316a14ee0cSDon Skidmore static struct ixgbe_mac_operations mac_ops_X550 = { 23326a14ee0cSDon Skidmore X550_COMMON_MAC 23336a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X540, 23346a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X540, 23356a14ee0cSDon Skidmore .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 23366a14ee0cSDon Skidmore .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 23376a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_mac_link_X540, 23386a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 2339454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_generic, 23406a14ee0cSDon Skidmore .setup_sfp = NULL, 2341449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, 2342449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X540, 23436a14ee0cSDon Skidmore }; 23446a14ee0cSDon Skidmore 23456a14ee0cSDon Skidmore static struct ixgbe_mac_operations mac_ops_X550EM_x = { 23466a14ee0cSDon Skidmore X550_COMMON_MAC 23476a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X550em, 23486a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X550em, 23496a14ee0cSDon Skidmore .get_san_mac_addr = NULL, 23506a14ee0cSDon Skidmore .get_wwn_prefix = NULL, 23516a14ee0cSDon Skidmore .setup_link = NULL, /* defined later */ 23526a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 2353454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_X550em, 23546a14ee0cSDon Skidmore .setup_sfp = ixgbe_setup_sfp_modules_X550em, 2355449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 2356449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 23576a14ee0cSDon Skidmore }; 23586a14ee0cSDon Skidmore 23596a14ee0cSDon Skidmore #define X550_COMMON_EEP \ 23606a14ee0cSDon Skidmore .read = &ixgbe_read_ee_hostif_X550, \ 23616a14ee0cSDon Skidmore .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 23626a14ee0cSDon Skidmore .write = &ixgbe_write_ee_hostif_X550, \ 23636a14ee0cSDon Skidmore .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 23646a14ee0cSDon Skidmore .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 23656a14ee0cSDon Skidmore .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 23666a14ee0cSDon Skidmore .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 23676a14ee0cSDon Skidmore 23686a14ee0cSDon Skidmore static struct ixgbe_eeprom_operations eeprom_ops_X550 = { 23696a14ee0cSDon Skidmore X550_COMMON_EEP 23706a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X550, 23716a14ee0cSDon Skidmore }; 23726a14ee0cSDon Skidmore 23736a14ee0cSDon Skidmore static struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 23746a14ee0cSDon Skidmore X550_COMMON_EEP 23756a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X540, 23766a14ee0cSDon Skidmore }; 23776a14ee0cSDon Skidmore 23786a14ee0cSDon Skidmore #define X550_COMMON_PHY \ 23796a14ee0cSDon Skidmore .identify_sfp = &ixgbe_identify_module_generic, \ 23806a14ee0cSDon Skidmore .reset = NULL, \ 23816a14ee0cSDon Skidmore .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 23826a14ee0cSDon Skidmore .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 23836a14ee0cSDon Skidmore .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 23846a14ee0cSDon Skidmore .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 23856a14ee0cSDon Skidmore .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 23866a14ee0cSDon Skidmore .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 2387bef23de1SDon Skidmore .read_reg = &ixgbe_read_phy_reg_generic, \ 2388bef23de1SDon Skidmore .write_reg = &ixgbe_write_phy_reg_generic, \ 2389bef23de1SDon Skidmore .setup_link = &ixgbe_setup_phy_link_generic, \ 2390b5529ef5SDon Skidmore .set_phy_power = NULL, \ 23916a14ee0cSDon Skidmore .check_overtemp = &ixgbe_tn_check_overtemp, \ 23926a14ee0cSDon Skidmore .get_firmware_version = &ixgbe_get_phy_firmware_version_generic, 23936a14ee0cSDon Skidmore 23946a14ee0cSDon Skidmore static struct ixgbe_phy_operations phy_ops_X550 = { 23956a14ee0cSDon Skidmore X550_COMMON_PHY 23966a14ee0cSDon Skidmore .init = NULL, 23976a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_generic, 23986a14ee0cSDon Skidmore }; 23996a14ee0cSDon Skidmore 24006a14ee0cSDon Skidmore static struct ixgbe_phy_operations phy_ops_X550EM_x = { 24016a14ee0cSDon Skidmore X550_COMMON_PHY 24026a14ee0cSDon Skidmore .init = &ixgbe_init_phy_ops_X550em, 24036a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_x550em, 24044f9e3a3dSMark Rustad .read_i2c_combined = &ixgbe_read_i2c_combined_generic, 24054f9e3a3dSMark Rustad .write_i2c_combined = &ixgbe_write_i2c_combined_generic, 2406bb5ce9a5SMark Rustad .read_i2c_combined_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, 2407bb5ce9a5SMark Rustad .write_i2c_combined_unlocked = 2408bb5ce9a5SMark Rustad &ixgbe_write_i2c_combined_generic_unlocked, 24096a14ee0cSDon Skidmore }; 24106a14ee0cSDon Skidmore 24119a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 24129a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550) 24139a900ecaSDon Skidmore }; 24149a900ecaSDon Skidmore 24159a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 24169a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550EM_x) 24179a900ecaSDon Skidmore }; 24189a900ecaSDon Skidmore 24196a14ee0cSDon Skidmore struct ixgbe_info ixgbe_X550_info = { 24206a14ee0cSDon Skidmore .mac = ixgbe_mac_X550, 24216a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 24226a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550, 24236a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550, 24246a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550, 24256a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 24269a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550, 24276a14ee0cSDon Skidmore }; 24286a14ee0cSDon Skidmore 24296a14ee0cSDon Skidmore struct ixgbe_info ixgbe_X550EM_x_info = { 24306a14ee0cSDon Skidmore .mac = ixgbe_mac_X550EM_x, 2431b5529ef5SDon Skidmore .get_invariants = &ixgbe_get_invariants_X550_x, 24326a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550EM_x, 24336a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550EM_x, 24346a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550EM_x, 24356a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 24369a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550EM_x, 24376a14ee0cSDon Skidmore }; 2438