16a14ee0cSDon Skidmore /******************************************************************************* 26a14ee0cSDon Skidmore * 36a14ee0cSDon Skidmore * Intel 10 Gigabit PCI Express Linux driver 437689010SMark Rustad * Copyright(c) 1999 - 2016 Intel Corporation. 56a14ee0cSDon Skidmore * 66a14ee0cSDon Skidmore * This program is free software; you can redistribute it and/or modify it 76a14ee0cSDon Skidmore * under the terms and conditions of the GNU General Public License, 86a14ee0cSDon Skidmore * version 2, as published by the Free Software Foundation. 96a14ee0cSDon Skidmore * 106a14ee0cSDon Skidmore * This program is distributed in the hope it will be useful, but WITHOUT 116a14ee0cSDon Skidmore * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 126a14ee0cSDon Skidmore * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 136a14ee0cSDon Skidmore * more details. 146a14ee0cSDon Skidmore * 156a14ee0cSDon Skidmore * The full GNU General Public License is included in this distribution in 166a14ee0cSDon Skidmore * the file called "COPYING". 176a14ee0cSDon Skidmore * 186a14ee0cSDon Skidmore * Contact Information: 196a14ee0cSDon Skidmore * Linux NICS <linux.nics@intel.com> 206a14ee0cSDon Skidmore * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 216a14ee0cSDon Skidmore * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 226a14ee0cSDon Skidmore * 236a14ee0cSDon Skidmore ******************************************************************************/ 246a14ee0cSDon Skidmore #include "ixgbe_x540.h" 256a14ee0cSDon Skidmore #include "ixgbe_type.h" 266a14ee0cSDon Skidmore #include "ixgbe_common.h" 276a14ee0cSDon Skidmore #include "ixgbe_phy.h" 286a14ee0cSDon Skidmore 29d91e3a7dSMark Rustad static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed); 30afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *); 312916500dSDon Skidmore static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *); 322916500dSDon Skidmore static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *); 332916500dSDon Skidmore static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *); 34d91e3a7dSMark Rustad 35b5529ef5SDon Skidmore static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) 36b5529ef5SDon Skidmore { 37b5529ef5SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 38b5529ef5SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 39b71f6c40SEmil Tantilov struct ixgbe_link_info *link = &hw->link; 40b71f6c40SEmil Tantilov 41b71f6c40SEmil Tantilov /* Start with X540 invariants, since so simular */ 42b71f6c40SEmil Tantilov ixgbe_get_invariants_X540(hw); 43b71f6c40SEmil Tantilov 44b71f6c40SEmil Tantilov if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 45b71f6c40SEmil Tantilov phy->ops.set_phy_power = NULL; 46b71f6c40SEmil Tantilov 47b71f6c40SEmil Tantilov link->addr = IXGBE_CS4227; 48b71f6c40SEmil Tantilov 49b71f6c40SEmil Tantilov return 0; 50b71f6c40SEmil Tantilov } 51b71f6c40SEmil Tantilov 52b71f6c40SEmil Tantilov static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw) 53b71f6c40SEmil Tantilov { 54b71f6c40SEmil Tantilov struct ixgbe_mac_info *mac = &hw->mac; 55b71f6c40SEmil Tantilov struct ixgbe_phy_info *phy = &hw->phy; 56b5529ef5SDon Skidmore 57b5529ef5SDon Skidmore /* Start with X540 invariants, since so simular */ 58b5529ef5SDon Skidmore ixgbe_get_invariants_X540(hw); 59b5529ef5SDon Skidmore 60b5529ef5SDon Skidmore if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 61b5529ef5SDon Skidmore phy->ops.set_phy_power = NULL; 62b5529ef5SDon Skidmore 63b5529ef5SDon Skidmore return 0; 64b5529ef5SDon Skidmore } 65b5529ef5SDon Skidmore 66ab5fe0c5SDon Skidmore /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control 67ab5fe0c5SDon Skidmore * @hw: pointer to hardware structure 68ab5fe0c5SDon Skidmore **/ 69ab5fe0c5SDon Skidmore static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) 70ab5fe0c5SDon Skidmore { 71ab5fe0c5SDon Skidmore u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 72ab5fe0c5SDon Skidmore 73ab5fe0c5SDon Skidmore if (hw->bus.lan_id) { 74ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 75ab5fe0c5SDon Skidmore esdp |= IXGBE_ESDP_SDP1_DIR; 76ab5fe0c5SDon Skidmore } 77ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 78ab5fe0c5SDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 79ab5fe0c5SDon Skidmore IXGBE_WRITE_FLUSH(hw); 80ab5fe0c5SDon Skidmore } 81ab5fe0c5SDon Skidmore 82542b6eecSMark Rustad /** 83542b6eecSMark Rustad * ixgbe_read_cs4227 - Read CS4227 register 84542b6eecSMark Rustad * @hw: pointer to hardware structure 85542b6eecSMark Rustad * @reg: register number to write 86542b6eecSMark Rustad * @value: pointer to receive value read 87542b6eecSMark Rustad * 88542b6eecSMark Rustad * Returns status code 89542b6eecSMark Rustad */ 90542b6eecSMark Rustad static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) 91542b6eecSMark Rustad { 92b71f6c40SEmil Tantilov return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value); 93542b6eecSMark Rustad } 94542b6eecSMark Rustad 95542b6eecSMark Rustad /** 96542b6eecSMark Rustad * ixgbe_write_cs4227 - Write CS4227 register 97542b6eecSMark Rustad * @hw: pointer to hardware structure 98542b6eecSMark Rustad * @reg: register number to write 99542b6eecSMark Rustad * @value: value to write to register 100542b6eecSMark Rustad * 101542b6eecSMark Rustad * Returns status code 102542b6eecSMark Rustad */ 103542b6eecSMark Rustad static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) 104542b6eecSMark Rustad { 105b71f6c40SEmil Tantilov return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value); 106542b6eecSMark Rustad } 107542b6eecSMark Rustad 108542b6eecSMark Rustad /** 109542b6eecSMark Rustad * ixgbe_read_pe - Read register from port expander 110542b6eecSMark Rustad * @hw: pointer to hardware structure 111542b6eecSMark Rustad * @reg: register number to read 112542b6eecSMark Rustad * @value: pointer to receive read value 113542b6eecSMark Rustad * 114542b6eecSMark Rustad * Returns status code 115542b6eecSMark Rustad */ 116542b6eecSMark Rustad static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) 117542b6eecSMark Rustad { 118542b6eecSMark Rustad s32 status; 119542b6eecSMark Rustad 120542b6eecSMark Rustad status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, 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_write_pe - Write register to port expander 128542b6eecSMark Rustad * @hw: pointer to hardware structure 129542b6eecSMark Rustad * @reg: register number to write 130542b6eecSMark Rustad * @value: value to write 131542b6eecSMark Rustad * 132542b6eecSMark Rustad * Returns status code 133542b6eecSMark Rustad */ 134542b6eecSMark Rustad static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) 135542b6eecSMark Rustad { 136542b6eecSMark Rustad s32 status; 137542b6eecSMark Rustad 138542b6eecSMark Rustad status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, 139542b6eecSMark Rustad value); 140542b6eecSMark Rustad if (status) 141542b6eecSMark Rustad hw_err(hw, "port expander access failed with %d\n", status); 142542b6eecSMark Rustad return status; 143542b6eecSMark Rustad } 144542b6eecSMark Rustad 145542b6eecSMark Rustad /** 146542b6eecSMark Rustad * ixgbe_reset_cs4227 - Reset CS4227 using port expander 147542b6eecSMark Rustad * @hw: pointer to hardware structure 148542b6eecSMark Rustad * 1498bf7a7b8SMark Rustad * This function assumes that the caller has acquired the proper semaphore. 150542b6eecSMark Rustad * Returns error code 151542b6eecSMark Rustad */ 152542b6eecSMark Rustad static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) 153542b6eecSMark Rustad { 154542b6eecSMark Rustad s32 status; 155542b6eecSMark Rustad u32 retry; 156542b6eecSMark Rustad u16 value; 157542b6eecSMark Rustad u8 reg; 158542b6eecSMark Rustad 159542b6eecSMark Rustad /* Trigger hard reset. */ 160542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 161542b6eecSMark Rustad if (status) 162542b6eecSMark Rustad return status; 163542b6eecSMark Rustad reg |= IXGBE_PE_BIT1; 164542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 165542b6eecSMark Rustad if (status) 166542b6eecSMark Rustad return status; 167542b6eecSMark Rustad 168542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); 169542b6eecSMark Rustad if (status) 170542b6eecSMark Rustad return status; 171542b6eecSMark Rustad reg &= ~IXGBE_PE_BIT1; 172542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); 173542b6eecSMark Rustad if (status) 174542b6eecSMark Rustad return status; 175542b6eecSMark Rustad 176542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 177542b6eecSMark Rustad if (status) 178542b6eecSMark Rustad return status; 179542b6eecSMark Rustad reg &= ~IXGBE_PE_BIT1; 180542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 181542b6eecSMark Rustad if (status) 182542b6eecSMark Rustad return status; 183542b6eecSMark Rustad 184542b6eecSMark Rustad usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100); 185542b6eecSMark Rustad 186542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 187542b6eecSMark Rustad if (status) 188542b6eecSMark Rustad return status; 189542b6eecSMark Rustad reg |= IXGBE_PE_BIT1; 190542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 191542b6eecSMark Rustad if (status) 192542b6eecSMark Rustad return status; 193542b6eecSMark Rustad 194542b6eecSMark Rustad /* Wait for the reset to complete. */ 195542b6eecSMark Rustad msleep(IXGBE_CS4227_RESET_DELAY); 196542b6eecSMark Rustad for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 197542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, 198542b6eecSMark Rustad &value); 199542b6eecSMark Rustad if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK) 200542b6eecSMark Rustad break; 201542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 202542b6eecSMark Rustad } 203542b6eecSMark Rustad if (retry == IXGBE_CS4227_RETRIES) { 204542b6eecSMark Rustad hw_err(hw, "CS4227 reset did not complete\n"); 205542b6eecSMark Rustad return IXGBE_ERR_PHY; 206542b6eecSMark Rustad } 207542b6eecSMark Rustad 208542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value); 209542b6eecSMark Rustad if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { 210542b6eecSMark Rustad hw_err(hw, "CS4227 EEPROM did not load successfully\n"); 211542b6eecSMark Rustad return IXGBE_ERR_PHY; 212542b6eecSMark Rustad } 213542b6eecSMark Rustad 214542b6eecSMark Rustad return 0; 215542b6eecSMark Rustad } 216542b6eecSMark Rustad 217542b6eecSMark Rustad /** 218542b6eecSMark Rustad * ixgbe_check_cs4227 - Check CS4227 and reset as needed 219542b6eecSMark Rustad * @hw: pointer to hardware structure 220542b6eecSMark Rustad */ 221542b6eecSMark Rustad static void ixgbe_check_cs4227(struct ixgbe_hw *hw) 222542b6eecSMark Rustad { 223542b6eecSMark Rustad u32 swfw_mask = hw->phy.phy_semaphore_mask; 224542b6eecSMark Rustad s32 status; 225542b6eecSMark Rustad u16 value; 226542b6eecSMark Rustad u8 retry; 227542b6eecSMark Rustad 228542b6eecSMark Rustad for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 229542b6eecSMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 230542b6eecSMark Rustad if (status) { 231542b6eecSMark Rustad hw_err(hw, "semaphore failed with %d\n", status); 232542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 233542b6eecSMark Rustad continue; 234542b6eecSMark Rustad } 235542b6eecSMark Rustad 236542b6eecSMark Rustad /* Get status of reset flow. */ 237542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); 238542b6eecSMark Rustad if (!status && value == IXGBE_CS4227_RESET_COMPLETE) 239542b6eecSMark Rustad goto out; 240542b6eecSMark Rustad 241542b6eecSMark Rustad if (status || value != IXGBE_CS4227_RESET_PENDING) 242542b6eecSMark Rustad break; 243542b6eecSMark Rustad 244542b6eecSMark Rustad /* Reset is pending. Wait and check again. */ 245542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 246542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 247542b6eecSMark Rustad } 2488bf7a7b8SMark Rustad /* If still pending, assume other instance failed. */ 2498bf7a7b8SMark Rustad if (retry == IXGBE_CS4227_RETRIES) { 2508bf7a7b8SMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 2518bf7a7b8SMark Rustad if (status) { 2528bf7a7b8SMark Rustad hw_err(hw, "semaphore failed with %d\n", status); 2538bf7a7b8SMark Rustad return; 2548bf7a7b8SMark Rustad } 2558bf7a7b8SMark Rustad } 256542b6eecSMark Rustad 257542b6eecSMark Rustad /* Reset the CS4227. */ 258542b6eecSMark Rustad status = ixgbe_reset_cs4227(hw); 259542b6eecSMark Rustad if (status) { 260542b6eecSMark Rustad hw_err(hw, "CS4227 reset failed: %d", status); 261542b6eecSMark Rustad goto out; 262542b6eecSMark Rustad } 263542b6eecSMark Rustad 264542b6eecSMark Rustad /* Reset takes so long, temporarily release semaphore in case the 265542b6eecSMark Rustad * other driver instance is waiting for the reset indication. 266542b6eecSMark Rustad */ 267542b6eecSMark Rustad ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 268542b6eecSMark Rustad IXGBE_CS4227_RESET_PENDING); 269542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 270542b6eecSMark Rustad usleep_range(10000, 12000); 271542b6eecSMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 272542b6eecSMark Rustad if (status) { 273542b6eecSMark Rustad hw_err(hw, "semaphore failed with %d", status); 274542b6eecSMark Rustad return; 275542b6eecSMark Rustad } 276542b6eecSMark Rustad 277542b6eecSMark Rustad /* Record completion for next time. */ 278542b6eecSMark Rustad status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 279542b6eecSMark Rustad IXGBE_CS4227_RESET_COMPLETE); 280542b6eecSMark Rustad 281542b6eecSMark Rustad out: 282542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 283542b6eecSMark Rustad msleep(hw->eeprom.semaphore_delay); 284542b6eecSMark Rustad } 285542b6eecSMark Rustad 2866a14ee0cSDon Skidmore /** ixgbe_identify_phy_x550em - Get PHY type based on device id 2876a14ee0cSDon Skidmore * @hw: pointer to hardware structure 2886a14ee0cSDon Skidmore * 2896a14ee0cSDon Skidmore * Returns error code 2906a14ee0cSDon Skidmore */ 2916a14ee0cSDon Skidmore static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) 2926a14ee0cSDon Skidmore { 2936a14ee0cSDon Skidmore switch (hw->device_id) { 2942d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 2952d40cd17SMark Rustad if (hw->bus.lan_id) 2962d40cd17SMark Rustad hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 2972d40cd17SMark Rustad else 2982d40cd17SMark Rustad hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 2992d40cd17SMark Rustad return ixgbe_identify_module_generic(hw); 3006a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 3016a14ee0cSDon Skidmore /* set up for CS4227 usage */ 3026a14ee0cSDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 303ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 304542b6eecSMark Rustad ixgbe_check_cs4227(hw); 30549425dfcSMark Rustad /* Fallthrough */ 30649425dfcSMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 3076a14ee0cSDon Skidmore return ixgbe_identify_module_generic(hw); 3086a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 3096a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kx4; 3106a14ee0cSDon Skidmore break; 3116a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 312f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR: 313f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR_L: 3146a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kr; 3156a14ee0cSDon Skidmore break; 31692ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 31792ed8430SDon Skidmore if (hw->bus.lan_id) 31892ed8430SDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 31992ed8430SDon Skidmore else 32092ed8430SDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 32192ed8430SDon Skidmore /* Fallthrough */ 3226a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 3236a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 3246a14ee0cSDon Skidmore return ixgbe_identify_phy_generic(hw); 3256a14ee0cSDon Skidmore default: 3266a14ee0cSDon Skidmore break; 3276a14ee0cSDon Skidmore } 3286a14ee0cSDon Skidmore return 0; 3296a14ee0cSDon Skidmore } 3306a14ee0cSDon Skidmore 3316a14ee0cSDon Skidmore static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 3326a14ee0cSDon Skidmore u32 device_type, u16 *phy_data) 3336a14ee0cSDon Skidmore { 3346a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 3356a14ee0cSDon Skidmore } 3366a14ee0cSDon Skidmore 3376a14ee0cSDon Skidmore static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 3386a14ee0cSDon Skidmore u32 device_type, u16 phy_data) 3396a14ee0cSDon Skidmore { 3406a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 3416a14ee0cSDon Skidmore } 3426a14ee0cSDon Skidmore 343b71f6c40SEmil Tantilov /** 344b71f6c40SEmil Tantilov * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation 345b71f6c40SEmil Tantilov * @hw: pointer to the hardware structure 346b71f6c40SEmil Tantilov * @addr: I2C bus address to read from 347b71f6c40SEmil Tantilov * @reg: I2C device register to read from 348b71f6c40SEmil Tantilov * @val: pointer to location to receive read value 349b71f6c40SEmil Tantilov * 350b71f6c40SEmil Tantilov * Returns an error code on error. 351b71f6c40SEmil Tantilov **/ 352b71f6c40SEmil Tantilov static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, 353b71f6c40SEmil Tantilov u16 reg, u16 *val) 354b71f6c40SEmil Tantilov { 355b71f6c40SEmil Tantilov return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); 356b71f6c40SEmil Tantilov } 357b71f6c40SEmil Tantilov 358b71f6c40SEmil Tantilov /** 359b71f6c40SEmil Tantilov * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation 360b71f6c40SEmil Tantilov * @hw: pointer to the hardware structure 361b71f6c40SEmil Tantilov * @addr: I2C bus address to read from 362b71f6c40SEmil Tantilov * @reg: I2C device register to read from 363b71f6c40SEmil Tantilov * @val: pointer to location to receive read value 364b71f6c40SEmil Tantilov * 365b71f6c40SEmil Tantilov * Returns an error code on error. 366b71f6c40SEmil Tantilov **/ 367b71f6c40SEmil Tantilov static s32 368b71f6c40SEmil Tantilov ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, 369b71f6c40SEmil Tantilov u16 reg, u16 *val) 370b71f6c40SEmil Tantilov { 371b71f6c40SEmil Tantilov return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); 372b71f6c40SEmil Tantilov } 373b71f6c40SEmil Tantilov 374b71f6c40SEmil Tantilov /** 375b71f6c40SEmil Tantilov * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation 376b71f6c40SEmil Tantilov * @hw: pointer to the hardware structure 377b71f6c40SEmil Tantilov * @addr: I2C bus address to write to 378b71f6c40SEmil Tantilov * @reg: I2C device register to write to 379b71f6c40SEmil Tantilov * @val: value to write 380b71f6c40SEmil Tantilov * 381b71f6c40SEmil Tantilov * Returns an error code on error. 382b71f6c40SEmil Tantilov **/ 383b71f6c40SEmil Tantilov static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, 384b71f6c40SEmil Tantilov u8 addr, u16 reg, u16 val) 385b71f6c40SEmil Tantilov { 386b71f6c40SEmil Tantilov return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); 387b71f6c40SEmil Tantilov } 388b71f6c40SEmil Tantilov 389b71f6c40SEmil Tantilov /** 390b71f6c40SEmil Tantilov * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation 391b71f6c40SEmil Tantilov * @hw: pointer to the hardware structure 392b71f6c40SEmil Tantilov * @addr: I2C bus address to write to 393b71f6c40SEmil Tantilov * @reg: I2C device register to write to 394b71f6c40SEmil Tantilov * @val: value to write 395b71f6c40SEmil Tantilov * 396b71f6c40SEmil Tantilov * Returns an error code on error. 397b71f6c40SEmil Tantilov **/ 398b71f6c40SEmil Tantilov static s32 399b71f6c40SEmil Tantilov ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, 400b71f6c40SEmil Tantilov u8 addr, u16 reg, u16 val) 401b71f6c40SEmil Tantilov { 402b71f6c40SEmil Tantilov return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); 403b71f6c40SEmil Tantilov } 404b71f6c40SEmil Tantilov 4056a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 4066a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4076a14ee0cSDon Skidmore * 4086a14ee0cSDon Skidmore * Initializes the EEPROM parameters ixgbe_eeprom_info within the 4096a14ee0cSDon Skidmore * ixgbe_hw struct in order to set up EEPROM access. 4106a14ee0cSDon Skidmore **/ 4117ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 4126a14ee0cSDon Skidmore { 4136a14ee0cSDon Skidmore struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 4146a14ee0cSDon Skidmore u32 eec; 4156a14ee0cSDon Skidmore u16 eeprom_size; 4166a14ee0cSDon Skidmore 4176a14ee0cSDon Skidmore if (eeprom->type == ixgbe_eeprom_uninitialized) { 4186a14ee0cSDon Skidmore eeprom->semaphore_delay = 10; 4196a14ee0cSDon Skidmore eeprom->type = ixgbe_flash; 4206a14ee0cSDon Skidmore 4219a900ecaSDon Skidmore eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 4226a14ee0cSDon Skidmore eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 4236a14ee0cSDon Skidmore IXGBE_EEC_SIZE_SHIFT); 424b4f47a48SJacob Keller eeprom->word_size = BIT(eeprom_size + 4256a14ee0cSDon Skidmore IXGBE_EEPROM_WORD_SIZE_SHIFT); 4266a14ee0cSDon Skidmore 4276a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 4286a14ee0cSDon Skidmore eeprom->type, eeprom->word_size); 4296a14ee0cSDon Skidmore } 4306a14ee0cSDon Skidmore 4316a14ee0cSDon Skidmore return 0; 4326a14ee0cSDon Skidmore } 4336a14ee0cSDon Skidmore 434ae14a1d8SMark Rustad /** 435ae14a1d8SMark Rustad * ixgbe_iosf_wait - Wait for IOSF command completion 436ae14a1d8SMark Rustad * @hw: pointer to hardware structure 437ae14a1d8SMark Rustad * @ctrl: pointer to location to receive final IOSF control value 438ae14a1d8SMark Rustad * 439ae14a1d8SMark Rustad * Return: failing status on timeout 440ae14a1d8SMark Rustad * 441ae14a1d8SMark Rustad * Note: ctrl can be NULL if the IOSF control register value is not needed 442ae14a1d8SMark Rustad */ 443ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 444ae14a1d8SMark Rustad { 445ae14a1d8SMark Rustad u32 i, command; 446ae14a1d8SMark Rustad 447ae14a1d8SMark Rustad /* Check every 10 usec to see if the address cycle completed. 448ae14a1d8SMark Rustad * The SB IOSF BUSY bit will clear when the operation is 449ae14a1d8SMark Rustad * complete. 450ae14a1d8SMark Rustad */ 451ae14a1d8SMark Rustad for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 452ae14a1d8SMark Rustad command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 453ae14a1d8SMark Rustad if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 454ae14a1d8SMark Rustad break; 455d90b5b0eSMark Rustad udelay(10); 456ae14a1d8SMark Rustad } 457ae14a1d8SMark Rustad if (ctrl) 458ae14a1d8SMark Rustad *ctrl = command; 459ae14a1d8SMark Rustad if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 460ae14a1d8SMark Rustad hw_dbg(hw, "IOSF wait timed out\n"); 461ae14a1d8SMark Rustad return IXGBE_ERR_PHY; 462ae14a1d8SMark Rustad } 463ae14a1d8SMark Rustad 464ae14a1d8SMark Rustad return 0; 465ae14a1d8SMark Rustad } 466ae14a1d8SMark Rustad 4676a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 4686a14ee0cSDon Skidmore * IOSF device 4696a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4706a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 4716a14ee0cSDon Skidmore * @device_type: 3 bit device type 4726a14ee0cSDon Skidmore * @phy_data: Pointer to read data from the register 4736a14ee0cSDon Skidmore **/ 4747ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 4756a14ee0cSDon Skidmore u32 device_type, u32 *data) 4766a14ee0cSDon Skidmore { 477ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 478ae14a1d8SMark Rustad u32 command, error; 479ae14a1d8SMark Rustad s32 ret; 480ae14a1d8SMark Rustad 481ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 482ae14a1d8SMark Rustad if (ret) 483ae14a1d8SMark Rustad return ret; 484ae14a1d8SMark Rustad 485ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 486ae14a1d8SMark Rustad if (ret) 487ae14a1d8SMark Rustad goto out; 4886a14ee0cSDon Skidmore 4896a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 4906a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 4916a14ee0cSDon Skidmore 4926a14ee0cSDon Skidmore /* Write IOSF control register */ 4936a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 4946a14ee0cSDon Skidmore 495ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 4966a14ee0cSDon Skidmore 4976a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 4986a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 4996a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 5006a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read, error %x\n", error); 5016a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 5026a14ee0cSDon Skidmore } 5036a14ee0cSDon Skidmore 504ae14a1d8SMark Rustad if (!ret) 5056a14ee0cSDon Skidmore *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 5066a14ee0cSDon Skidmore 507ae14a1d8SMark Rustad out: 508ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 509ae14a1d8SMark Rustad return ret; 5106a14ee0cSDon Skidmore } 5116a14ee0cSDon Skidmore 51249425dfcSMark Rustad /** 51349425dfcSMark Rustad * ixgbe_get_phy_token - Get the token for shared PHY access 51449425dfcSMark Rustad * @hw: Pointer to hardware structure 51549425dfcSMark Rustad */ 51649425dfcSMark Rustad static s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) 51749425dfcSMark Rustad { 51849425dfcSMark Rustad struct ixgbe_hic_phy_token_req token_cmd; 51949425dfcSMark Rustad s32 status; 52049425dfcSMark Rustad 52149425dfcSMark Rustad token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 52249425dfcSMark Rustad token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 52349425dfcSMark Rustad token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 52449425dfcSMark Rustad token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 52549425dfcSMark Rustad token_cmd.port_number = hw->bus.lan_id; 52649425dfcSMark Rustad token_cmd.command_type = FW_PHY_TOKEN_REQ; 52749425dfcSMark Rustad token_cmd.pad = 0; 52849425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 52949425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 53049425dfcSMark Rustad true); 53149425dfcSMark Rustad if (status) 53249425dfcSMark Rustad return status; 53349425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 53449425dfcSMark Rustad return 0; 53549425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) 53649425dfcSMark Rustad return IXGBE_ERR_FW_RESP_INVALID; 53749425dfcSMark Rustad 53849425dfcSMark Rustad return IXGBE_ERR_TOKEN_RETRY; 53949425dfcSMark Rustad } 54049425dfcSMark Rustad 54149425dfcSMark Rustad /** 54249425dfcSMark Rustad * ixgbe_put_phy_token - Put the token for shared PHY access 54349425dfcSMark Rustad * @hw: Pointer to hardware structure 54449425dfcSMark Rustad */ 54549425dfcSMark Rustad static s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) 54649425dfcSMark Rustad { 54749425dfcSMark Rustad struct ixgbe_hic_phy_token_req token_cmd; 54849425dfcSMark Rustad s32 status; 54949425dfcSMark Rustad 55049425dfcSMark Rustad token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 55149425dfcSMark Rustad token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 55249425dfcSMark Rustad token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 55349425dfcSMark Rustad token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 55449425dfcSMark Rustad token_cmd.port_number = hw->bus.lan_id; 55549425dfcSMark Rustad token_cmd.command_type = FW_PHY_TOKEN_REL; 55649425dfcSMark Rustad token_cmd.pad = 0; 55749425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 55849425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 55949425dfcSMark Rustad true); 56049425dfcSMark Rustad if (status) 56149425dfcSMark Rustad return status; 56249425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 56349425dfcSMark Rustad return 0; 56449425dfcSMark Rustad return IXGBE_ERR_FW_RESP_INVALID; 56549425dfcSMark Rustad } 56649425dfcSMark Rustad 56749425dfcSMark Rustad /** 56849425dfcSMark Rustad * ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register 56949425dfcSMark Rustad * @hw: pointer to hardware structure 57049425dfcSMark Rustad * @reg_addr: 32 bit PHY register to write 57149425dfcSMark Rustad * @device_type: 3 bit device type 57249425dfcSMark Rustad * @data: Data to write to the register 57349425dfcSMark Rustad **/ 57449425dfcSMark Rustad static s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 57549425dfcSMark Rustad __always_unused u32 device_type, 57649425dfcSMark Rustad u32 data) 57749425dfcSMark Rustad { 57849425dfcSMark Rustad struct ixgbe_hic_internal_phy_req write_cmd; 57949425dfcSMark Rustad 58049425dfcSMark Rustad memset(&write_cmd, 0, sizeof(write_cmd)); 58149425dfcSMark Rustad write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 58249425dfcSMark Rustad write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 58349425dfcSMark Rustad write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 58449425dfcSMark Rustad write_cmd.port_number = hw->bus.lan_id; 58549425dfcSMark Rustad write_cmd.command_type = FW_INT_PHY_REQ_WRITE; 58649425dfcSMark Rustad write_cmd.address = cpu_to_be16(reg_addr); 58749425dfcSMark Rustad write_cmd.write_data = cpu_to_be32(data); 58849425dfcSMark Rustad 58949425dfcSMark Rustad return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd), 59049425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, false); 59149425dfcSMark Rustad } 59249425dfcSMark Rustad 59349425dfcSMark Rustad /** 59449425dfcSMark Rustad * ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register 59549425dfcSMark Rustad * @hw: pointer to hardware structure 59649425dfcSMark Rustad * @reg_addr: 32 bit PHY register to write 59749425dfcSMark Rustad * @device_type: 3 bit device type 59849425dfcSMark Rustad * @data: Pointer to read data from the register 59949425dfcSMark Rustad **/ 60049425dfcSMark Rustad static s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 60149425dfcSMark Rustad __always_unused u32 device_type, 60249425dfcSMark Rustad u32 *data) 60349425dfcSMark Rustad { 60449425dfcSMark Rustad union { 60549425dfcSMark Rustad struct ixgbe_hic_internal_phy_req cmd; 60649425dfcSMark Rustad struct ixgbe_hic_internal_phy_resp rsp; 60749425dfcSMark Rustad } hic; 60849425dfcSMark Rustad s32 status; 60949425dfcSMark Rustad 61049425dfcSMark Rustad memset(&hic, 0, sizeof(hic)); 61149425dfcSMark Rustad hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 61249425dfcSMark Rustad hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 61349425dfcSMark Rustad hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 61449425dfcSMark Rustad hic.cmd.port_number = hw->bus.lan_id; 61549425dfcSMark Rustad hic.cmd.command_type = FW_INT_PHY_REQ_READ; 61649425dfcSMark Rustad hic.cmd.address = cpu_to_be16(reg_addr); 61749425dfcSMark Rustad 61849425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 61949425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, true); 62049425dfcSMark Rustad 62149425dfcSMark Rustad /* Extract the register value from the response. */ 62249425dfcSMark Rustad *data = be32_to_cpu(hic.rsp.read_data); 62349425dfcSMark Rustad 62449425dfcSMark Rustad return status; 62549425dfcSMark Rustad } 62649425dfcSMark Rustad 6276a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface 6286a14ee0cSDon Skidmore * command assuming that the semaphore is already obtained. 6296a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6306a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 6316a14ee0cSDon Skidmore * @data: word read from the EEPROM 6326a14ee0cSDon Skidmore * 6336a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 6346a14ee0cSDon Skidmore **/ 6357ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 6367ddbde3fSDon Skidmore u16 *data) 6376a14ee0cSDon Skidmore { 6386a14ee0cSDon Skidmore s32 status; 6396a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 6406a14ee0cSDon Skidmore 6416a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 6426a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 6436a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 6446a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 6456a14ee0cSDon Skidmore 6466a14ee0cSDon Skidmore /* convert offset from words to bytes */ 6476a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 6486a14ee0cSDon Skidmore /* one word */ 6496a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 6506a14ee0cSDon Skidmore 6515cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 6526a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 6536a14ee0cSDon Skidmore if (status) 6546a14ee0cSDon Skidmore return status; 6556a14ee0cSDon Skidmore 6566a14ee0cSDon Skidmore *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 6576a14ee0cSDon Skidmore FW_NVM_DATA_OFFSET); 6586a14ee0cSDon Skidmore 6596a14ee0cSDon Skidmore return 0; 6606a14ee0cSDon Skidmore } 6616a14ee0cSDon Skidmore 6626a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 6636a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6646a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 6656a14ee0cSDon Skidmore * @words: number of words 6666a14ee0cSDon Skidmore * @data: word(s) read from the EEPROM 6676a14ee0cSDon Skidmore * 6686a14ee0cSDon Skidmore * Reads a 16 bit word(s) from the EEPROM using the hostif. 6696a14ee0cSDon Skidmore **/ 6707ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 6716a14ee0cSDon Skidmore u16 offset, u16 words, u16 *data) 6726a14ee0cSDon Skidmore { 6736a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 6746a14ee0cSDon Skidmore u32 current_word = 0; 6756a14ee0cSDon Skidmore u16 words_to_read; 6766a14ee0cSDon Skidmore s32 status; 6776a14ee0cSDon Skidmore u32 i; 6786a14ee0cSDon Skidmore 6796a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 6806a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 6816a14ee0cSDon Skidmore if (status) { 6826a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 6836a14ee0cSDon Skidmore return status; 6846a14ee0cSDon Skidmore } 6856a14ee0cSDon Skidmore 6866a14ee0cSDon Skidmore while (words) { 6876a14ee0cSDon Skidmore if (words > FW_MAX_READ_BUFFER_SIZE / 2) 6886a14ee0cSDon Skidmore words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 6896a14ee0cSDon Skidmore else 6906a14ee0cSDon Skidmore words_to_read = words; 6916a14ee0cSDon Skidmore 6926a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 6936a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 6946a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 6956a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 6966a14ee0cSDon Skidmore 6976a14ee0cSDon Skidmore /* convert offset from words to bytes */ 6986a14ee0cSDon Skidmore buffer.address = cpu_to_be32((offset + current_word) * 2); 6996a14ee0cSDon Skidmore buffer.length = cpu_to_be16(words_to_read * 2); 7006a14ee0cSDon Skidmore 7015cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, 7026a14ee0cSDon Skidmore sizeof(buffer), 7036a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, 7046a14ee0cSDon Skidmore false); 7056a14ee0cSDon Skidmore if (status) { 7066a14ee0cSDon Skidmore hw_dbg(hw, "Host interface command failed\n"); 7076a14ee0cSDon Skidmore goto out; 7086a14ee0cSDon Skidmore } 7096a14ee0cSDon Skidmore 7106a14ee0cSDon Skidmore for (i = 0; i < words_to_read; i++) { 7116a14ee0cSDon Skidmore u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 7126a14ee0cSDon Skidmore 2 * i; 7136a14ee0cSDon Skidmore u32 value = IXGBE_READ_REG(hw, reg); 7146a14ee0cSDon Skidmore 7156a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 7166a14ee0cSDon Skidmore current_word++; 7176a14ee0cSDon Skidmore i++; 7186a14ee0cSDon Skidmore if (i < words_to_read) { 7196a14ee0cSDon Skidmore value >>= 16; 7206a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 7216a14ee0cSDon Skidmore current_word++; 7226a14ee0cSDon Skidmore } 7236a14ee0cSDon Skidmore } 7246a14ee0cSDon Skidmore words -= words_to_read; 7256a14ee0cSDon Skidmore } 7266a14ee0cSDon Skidmore 7276a14ee0cSDon Skidmore out: 7286a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 7296a14ee0cSDon Skidmore return status; 7306a14ee0cSDon Skidmore } 7316a14ee0cSDon Skidmore 7326a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region 7336a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7346a14ee0cSDon Skidmore * @ptr: pointer offset in eeprom 7356a14ee0cSDon Skidmore * @size: size of section pointed by ptr, if 0 first word will be used as size 7366a14ee0cSDon Skidmore * @csum: address of checksum to update 7376a14ee0cSDon Skidmore * 7386a14ee0cSDon Skidmore * Returns error status for any failure 7396a14ee0cSDon Skidmore **/ 7406a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 7416a14ee0cSDon Skidmore u16 size, u16 *csum, u16 *buffer, 7426a14ee0cSDon Skidmore u32 buffer_size) 7436a14ee0cSDon Skidmore { 7446a14ee0cSDon Skidmore u16 buf[256]; 7456a14ee0cSDon Skidmore s32 status; 7466a14ee0cSDon Skidmore u16 length, bufsz, i, start; 7476a14ee0cSDon Skidmore u16 *local_buffer; 7486a14ee0cSDon Skidmore 7496a14ee0cSDon Skidmore bufsz = sizeof(buf) / sizeof(buf[0]); 7506a14ee0cSDon Skidmore 7516a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 7526a14ee0cSDon Skidmore if (!buffer) { 7536a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 7546a14ee0cSDon Skidmore if (status) { 7556a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 7566a14ee0cSDon Skidmore return status; 7576a14ee0cSDon Skidmore } 7586a14ee0cSDon Skidmore local_buffer = buf; 7596a14ee0cSDon Skidmore } else { 7606a14ee0cSDon Skidmore if (buffer_size < ptr) 7616a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 7626a14ee0cSDon Skidmore local_buffer = &buffer[ptr]; 7636a14ee0cSDon Skidmore } 7646a14ee0cSDon Skidmore 7656a14ee0cSDon Skidmore if (size) { 7666a14ee0cSDon Skidmore start = 0; 7676a14ee0cSDon Skidmore length = size; 7686a14ee0cSDon Skidmore } else { 7696a14ee0cSDon Skidmore start = 1; 7706a14ee0cSDon Skidmore length = local_buffer[0]; 7716a14ee0cSDon Skidmore 7726a14ee0cSDon Skidmore /* Skip pointer section if length is invalid. */ 7736a14ee0cSDon Skidmore if (length == 0xFFFF || length == 0 || 7746a14ee0cSDon Skidmore (ptr + length) >= hw->eeprom.word_size) 7756a14ee0cSDon Skidmore return 0; 7766a14ee0cSDon Skidmore } 7776a14ee0cSDon Skidmore 7786a14ee0cSDon Skidmore if (buffer && ((u32)start + (u32)length > buffer_size)) 7796a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 7806a14ee0cSDon Skidmore 7816a14ee0cSDon Skidmore for (i = start; length; i++, length--) { 7826a14ee0cSDon Skidmore if (i == bufsz && !buffer) { 7836a14ee0cSDon Skidmore ptr += bufsz; 7846a14ee0cSDon Skidmore i = 0; 7856a14ee0cSDon Skidmore if (length < bufsz) 7866a14ee0cSDon Skidmore bufsz = length; 7876a14ee0cSDon Skidmore 7886a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 7896a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 7906a14ee0cSDon Skidmore bufsz, buf); 7916a14ee0cSDon Skidmore if (status) { 7926a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 7936a14ee0cSDon Skidmore return status; 7946a14ee0cSDon Skidmore } 7956a14ee0cSDon Skidmore } 7966a14ee0cSDon Skidmore *csum += local_buffer[i]; 7976a14ee0cSDon Skidmore } 7986a14ee0cSDon Skidmore return 0; 7996a14ee0cSDon Skidmore } 8006a14ee0cSDon Skidmore 8016a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 8026a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8036a14ee0cSDon Skidmore * @buffer: pointer to buffer containing calculated checksum 8046a14ee0cSDon Skidmore * @buffer_size: size of buffer 8056a14ee0cSDon Skidmore * 8066a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 8076a14ee0cSDon Skidmore **/ 8087ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 8097ddbde3fSDon Skidmore u32 buffer_size) 8106a14ee0cSDon Skidmore { 8116a14ee0cSDon Skidmore u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 8126a14ee0cSDon Skidmore u16 *local_buffer; 8136a14ee0cSDon Skidmore s32 status; 8146a14ee0cSDon Skidmore u16 checksum = 0; 8156a14ee0cSDon Skidmore u16 pointer, i, size; 8166a14ee0cSDon Skidmore 8176a14ee0cSDon Skidmore hw->eeprom.ops.init_params(hw); 8186a14ee0cSDon Skidmore 8196a14ee0cSDon Skidmore if (!buffer) { 8206a14ee0cSDon Skidmore /* Read pointer area */ 8216a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 8226a14ee0cSDon Skidmore IXGBE_EEPROM_LAST_WORD + 1, 8236a14ee0cSDon Skidmore eeprom_ptrs); 8246a14ee0cSDon Skidmore if (status) { 8256a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 8266a14ee0cSDon Skidmore return status; 8276a14ee0cSDon Skidmore } 8286a14ee0cSDon Skidmore local_buffer = eeprom_ptrs; 8296a14ee0cSDon Skidmore } else { 8306a14ee0cSDon Skidmore if (buffer_size < IXGBE_EEPROM_LAST_WORD) 8316a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 8326a14ee0cSDon Skidmore local_buffer = buffer; 8336a14ee0cSDon Skidmore } 8346a14ee0cSDon Skidmore 8356a14ee0cSDon Skidmore /* For X550 hardware include 0x0-0x41 in the checksum, skip the 8366a14ee0cSDon Skidmore * checksum word itself 8376a14ee0cSDon Skidmore */ 8386a14ee0cSDon Skidmore for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 8396a14ee0cSDon Skidmore if (i != IXGBE_EEPROM_CHECKSUM) 8406a14ee0cSDon Skidmore checksum += local_buffer[i]; 8416a14ee0cSDon Skidmore 8426a14ee0cSDon Skidmore /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 8436a14ee0cSDon Skidmore * FW, PHY module, and PCIe Expansion/Option ROM pointers. 8446a14ee0cSDon Skidmore */ 8456a14ee0cSDon Skidmore for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 8466a14ee0cSDon Skidmore if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 8476a14ee0cSDon Skidmore continue; 8486a14ee0cSDon Skidmore 8496a14ee0cSDon Skidmore pointer = local_buffer[i]; 8506a14ee0cSDon Skidmore 8516a14ee0cSDon Skidmore /* Skip pointer section if the pointer is invalid. */ 8526a14ee0cSDon Skidmore if (pointer == 0xFFFF || pointer == 0 || 8536a14ee0cSDon Skidmore pointer >= hw->eeprom.word_size) 8546a14ee0cSDon Skidmore continue; 8556a14ee0cSDon Skidmore 8566a14ee0cSDon Skidmore switch (i) { 8576a14ee0cSDon Skidmore case IXGBE_PCIE_GENERAL_PTR: 8586a14ee0cSDon Skidmore size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 8596a14ee0cSDon Skidmore break; 8606a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG0_PTR: 8616a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG1_PTR: 8626a14ee0cSDon Skidmore size = IXGBE_PCIE_CONFIG_SIZE; 8636a14ee0cSDon Skidmore break; 8646a14ee0cSDon Skidmore default: 8656a14ee0cSDon Skidmore size = 0; 8666a14ee0cSDon Skidmore break; 8676a14ee0cSDon Skidmore } 8686a14ee0cSDon Skidmore 8696a14ee0cSDon Skidmore status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 8706a14ee0cSDon Skidmore buffer, buffer_size); 8716a14ee0cSDon Skidmore if (status) 8726a14ee0cSDon Skidmore return status; 8736a14ee0cSDon Skidmore } 8746a14ee0cSDon Skidmore 8756a14ee0cSDon Skidmore checksum = (u16)IXGBE_EEPROM_SUM - checksum; 8766a14ee0cSDon Skidmore 8776a14ee0cSDon Skidmore return (s32)checksum; 8786a14ee0cSDon Skidmore } 8796a14ee0cSDon Skidmore 8806a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 8816a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8826a14ee0cSDon Skidmore * 8836a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 8846a14ee0cSDon Skidmore **/ 8857ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 8866a14ee0cSDon Skidmore { 8876a14ee0cSDon Skidmore return ixgbe_calc_checksum_X550(hw, NULL, 0); 8886a14ee0cSDon Skidmore } 8896a14ee0cSDon Skidmore 8906a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 8916a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8926a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 8936a14ee0cSDon Skidmore * @data: word read from the EEPROM 8946a14ee0cSDon Skidmore * 8956a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 8966a14ee0cSDon Skidmore **/ 8977ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 8986a14ee0cSDon Skidmore { 8996a14ee0cSDon Skidmore s32 status = 0; 9006a14ee0cSDon Skidmore 9016a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 9026a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_data_X550(hw, offset, data); 9036a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 9046a14ee0cSDon Skidmore } else { 9056a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 9066a14ee0cSDon Skidmore } 9076a14ee0cSDon Skidmore 9086a14ee0cSDon Skidmore return status; 9096a14ee0cSDon Skidmore } 9106a14ee0cSDon Skidmore 9116a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 9126a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9136a14ee0cSDon Skidmore * @checksum_val: calculated checksum 9146a14ee0cSDon Skidmore * 9156a14ee0cSDon Skidmore * Performs checksum calculation and validates the EEPROM checksum. If the 9166a14ee0cSDon Skidmore * caller does not need checksum_val, the value can be NULL. 9176a14ee0cSDon Skidmore **/ 9187ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 9197ddbde3fSDon Skidmore u16 *checksum_val) 9206a14ee0cSDon Skidmore { 9216a14ee0cSDon Skidmore s32 status; 9226a14ee0cSDon Skidmore u16 checksum; 9236a14ee0cSDon Skidmore u16 read_checksum = 0; 9246a14ee0cSDon Skidmore 9256a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 9266a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 9276a14ee0cSDon Skidmore * EEPROM read fails 9286a14ee0cSDon Skidmore */ 9296a14ee0cSDon Skidmore status = hw->eeprom.ops.read(hw, 0, &checksum); 9306a14ee0cSDon Skidmore if (status) { 9316a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 9326a14ee0cSDon Skidmore return status; 9336a14ee0cSDon Skidmore } 9346a14ee0cSDon Skidmore 9356a14ee0cSDon Skidmore status = hw->eeprom.ops.calc_checksum(hw); 9366a14ee0cSDon Skidmore if (status < 0) 9376a14ee0cSDon Skidmore return status; 9386a14ee0cSDon Skidmore 9396a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 9406a14ee0cSDon Skidmore 9416a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 9426a14ee0cSDon Skidmore &read_checksum); 9436a14ee0cSDon Skidmore if (status) 9446a14ee0cSDon Skidmore return status; 9456a14ee0cSDon Skidmore 9466a14ee0cSDon Skidmore /* Verify read checksum from EEPROM is the same as 9476a14ee0cSDon Skidmore * calculated checksum 9486a14ee0cSDon Skidmore */ 9496a14ee0cSDon Skidmore if (read_checksum != checksum) { 9506a14ee0cSDon Skidmore status = IXGBE_ERR_EEPROM_CHECKSUM; 9516a14ee0cSDon Skidmore hw_dbg(hw, "Invalid EEPROM checksum"); 9526a14ee0cSDon Skidmore } 9536a14ee0cSDon Skidmore 9546a14ee0cSDon Skidmore /* If the user cares, return the calculated checksum */ 9556a14ee0cSDon Skidmore if (checksum_val) 9566a14ee0cSDon Skidmore *checksum_val = checksum; 9576a14ee0cSDon Skidmore 9586a14ee0cSDon Skidmore return status; 9596a14ee0cSDon Skidmore } 9606a14ee0cSDon Skidmore 9616a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 9626a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9636a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 9646a14ee0cSDon Skidmore * @data: word write to the EEPROM 9656a14ee0cSDon Skidmore * 9666a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 9676a14ee0cSDon Skidmore **/ 9687ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 9697ddbde3fSDon Skidmore u16 data) 9706a14ee0cSDon Skidmore { 9716a14ee0cSDon Skidmore s32 status; 9726a14ee0cSDon Skidmore struct ixgbe_hic_write_shadow_ram buffer; 9736a14ee0cSDon Skidmore 9746a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 9756a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 9766a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 9776a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 9786a14ee0cSDon Skidmore 9796a14ee0cSDon Skidmore /* one word */ 9806a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 9816a14ee0cSDon Skidmore buffer.data = data; 9826a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 9836a14ee0cSDon Skidmore 9845cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 9856a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 9866a14ee0cSDon Skidmore return status; 9876a14ee0cSDon Skidmore } 9886a14ee0cSDon Skidmore 9896a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 9906a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9916a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 9926a14ee0cSDon Skidmore * @data: word write to the EEPROM 9936a14ee0cSDon Skidmore * 9946a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 9956a14ee0cSDon Skidmore **/ 9967ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 9976a14ee0cSDon Skidmore { 9986a14ee0cSDon Skidmore s32 status = 0; 9996a14ee0cSDon Skidmore 10006a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 10016a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 10026a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 10036a14ee0cSDon Skidmore } else { 10046a14ee0cSDon Skidmore hw_dbg(hw, "write ee hostif failed to get semaphore"); 10056a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 10066a14ee0cSDon Skidmore } 10076a14ee0cSDon Skidmore 10086a14ee0cSDon Skidmore return status; 10096a14ee0cSDon Skidmore } 10106a14ee0cSDon Skidmore 10116a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 10126a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10136a14ee0cSDon Skidmore * 10146a14ee0cSDon Skidmore * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 10156a14ee0cSDon Skidmore **/ 10167ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 10176a14ee0cSDon Skidmore { 10186a14ee0cSDon Skidmore s32 status = 0; 10196a14ee0cSDon Skidmore union ixgbe_hic_hdr2 buffer; 10206a14ee0cSDon Skidmore 10216a14ee0cSDon Skidmore buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 10226a14ee0cSDon Skidmore buffer.req.buf_lenh = 0; 10236a14ee0cSDon Skidmore buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 10246a14ee0cSDon Skidmore buffer.req.checksum = FW_DEFAULT_CHECKSUM; 10256a14ee0cSDon Skidmore 10265cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 10276a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 10286a14ee0cSDon Skidmore return status; 10296a14ee0cSDon Skidmore } 10306a14ee0cSDon Skidmore 1031454c65ddSDon Skidmore /** 1032454c65ddSDon Skidmore * ixgbe_get_bus_info_X550em - Set PCI bus info 1033454c65ddSDon Skidmore * @hw: pointer to hardware structure 1034454c65ddSDon Skidmore * 1035454c65ddSDon Skidmore * Sets bus link width and speed to unknown because X550em is 1036454c65ddSDon Skidmore * not a PCI device. 1037454c65ddSDon Skidmore **/ 1038454c65ddSDon Skidmore static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) 1039454c65ddSDon Skidmore { 1040f9328bc6SDon Skidmore hw->bus.type = ixgbe_bus_type_internal; 1041454c65ddSDon Skidmore hw->bus.width = ixgbe_bus_width_unknown; 1042454c65ddSDon Skidmore hw->bus.speed = ixgbe_bus_speed_unknown; 1043454c65ddSDon Skidmore 1044454c65ddSDon Skidmore hw->mac.ops.set_lan_id(hw); 1045454c65ddSDon Skidmore 1046454c65ddSDon Skidmore return 0; 1047454c65ddSDon Skidmore } 1048454c65ddSDon Skidmore 10491f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit 10501f9ac57cSDon Skidmore * 10511f9ac57cSDon Skidmore * Enables the Rx DMA unit for x550 10521f9ac57cSDon Skidmore **/ 10531f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 10541f9ac57cSDon Skidmore { 10551f9ac57cSDon Skidmore u32 rxctrl, pfdtxgswc; 10561f9ac57cSDon Skidmore s32 status; 10571f9ac57cSDon Skidmore struct ixgbe_hic_disable_rxen fw_cmd; 10581f9ac57cSDon Skidmore 10591f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 10601f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 10611f9ac57cSDon Skidmore pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 10621f9ac57cSDon Skidmore if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 10631f9ac57cSDon Skidmore pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 10641f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 10651f9ac57cSDon Skidmore hw->mac.set_lben = true; 10661f9ac57cSDon Skidmore } else { 10671f9ac57cSDon Skidmore hw->mac.set_lben = false; 10681f9ac57cSDon Skidmore } 10691f9ac57cSDon Skidmore 10701f9ac57cSDon Skidmore fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 10711f9ac57cSDon Skidmore fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 10721f9ac57cSDon Skidmore fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 10733775b814SMark Rustad fw_cmd.port_number = hw->bus.lan_id; 10741f9ac57cSDon Skidmore 10755cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &fw_cmd, 10761f9ac57cSDon Skidmore sizeof(struct ixgbe_hic_disable_rxen), 10771f9ac57cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, true); 10781f9ac57cSDon Skidmore 10791f9ac57cSDon Skidmore /* If we fail - disable RX using register write */ 10801f9ac57cSDon Skidmore if (status) { 10811f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 10821f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 10831f9ac57cSDon Skidmore rxctrl &= ~IXGBE_RXCTRL_RXEN; 10841f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 10851f9ac57cSDon Skidmore } 10861f9ac57cSDon Skidmore } 10871f9ac57cSDon Skidmore } 10881f9ac57cSDon Skidmore } 10891f9ac57cSDon Skidmore 10906a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 10916a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10926a14ee0cSDon Skidmore * 10936a14ee0cSDon Skidmore * After writing EEPROM to shadow RAM using EEWR register, software calculates 10946a14ee0cSDon Skidmore * checksum and updates the EEPROM and instructs the hardware to update 10956a14ee0cSDon Skidmore * the flash. 10966a14ee0cSDon Skidmore **/ 10977ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 10986a14ee0cSDon Skidmore { 10996a14ee0cSDon Skidmore s32 status; 11006a14ee0cSDon Skidmore u16 checksum = 0; 11016a14ee0cSDon Skidmore 11026a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 11036a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 11046a14ee0cSDon Skidmore * EEPROM read fails 11056a14ee0cSDon Skidmore */ 11066a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 11076a14ee0cSDon Skidmore if (status) { 11086a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 11096a14ee0cSDon Skidmore return status; 11106a14ee0cSDon Skidmore } 11116a14ee0cSDon Skidmore 11126a14ee0cSDon Skidmore status = ixgbe_calc_eeprom_checksum_X550(hw); 11136a14ee0cSDon Skidmore if (status < 0) 11146a14ee0cSDon Skidmore return status; 11156a14ee0cSDon Skidmore 11166a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 11176a14ee0cSDon Skidmore 11186a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 11196a14ee0cSDon Skidmore checksum); 11206a14ee0cSDon Skidmore if (status) 11216a14ee0cSDon Skidmore return status; 11226a14ee0cSDon Skidmore 11236a14ee0cSDon Skidmore status = ixgbe_update_flash_X550(hw); 11246a14ee0cSDon Skidmore 11256a14ee0cSDon Skidmore return status; 11266a14ee0cSDon Skidmore } 11276a14ee0cSDon Skidmore 11286a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 11296a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11306a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 11316a14ee0cSDon Skidmore * @words: number of words 11326a14ee0cSDon Skidmore * @data: word(s) write to the EEPROM 11336a14ee0cSDon Skidmore * 11346a14ee0cSDon Skidmore * 11356a14ee0cSDon Skidmore * Write a 16 bit word(s) to the EEPROM using the hostif. 11366a14ee0cSDon Skidmore **/ 11377ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 11387ddbde3fSDon Skidmore u16 offset, u16 words, 11397ddbde3fSDon Skidmore u16 *data) 11406a14ee0cSDon Skidmore { 11416a14ee0cSDon Skidmore s32 status = 0; 11426a14ee0cSDon Skidmore u32 i = 0; 11436a14ee0cSDon Skidmore 11446a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 11456a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 11466a14ee0cSDon Skidmore if (status) { 11476a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 11486a14ee0cSDon Skidmore return status; 11496a14ee0cSDon Skidmore } 11506a14ee0cSDon Skidmore 11516a14ee0cSDon Skidmore for (i = 0; i < words; i++) { 11526a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 11536a14ee0cSDon Skidmore data[i]); 11546a14ee0cSDon Skidmore if (status) { 11556a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom buffered write failed\n"); 11566a14ee0cSDon Skidmore break; 11576a14ee0cSDon Skidmore } 11586a14ee0cSDon Skidmore } 11596a14ee0cSDon Skidmore 11606a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 11616a14ee0cSDon Skidmore 11626a14ee0cSDon Skidmore return status; 11636a14ee0cSDon Skidmore } 11646a14ee0cSDon Skidmore 11656a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 11666a14ee0cSDon Skidmore * IOSF device 11676a14ee0cSDon Skidmore * 11686a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11696a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 11706a14ee0cSDon Skidmore * @device_type: 3 bit device type 11716a14ee0cSDon Skidmore * @data: Data to write to the register 11726a14ee0cSDon Skidmore **/ 11737ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 11746a14ee0cSDon Skidmore u32 device_type, u32 data) 11756a14ee0cSDon Skidmore { 1176ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 1177ae14a1d8SMark Rustad u32 command, error; 1178ae14a1d8SMark Rustad s32 ret; 1179ae14a1d8SMark Rustad 1180ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 1181ae14a1d8SMark Rustad if (ret) 1182ae14a1d8SMark Rustad return ret; 1183ae14a1d8SMark Rustad 1184ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 1185ae14a1d8SMark Rustad if (ret) 1186ae14a1d8SMark Rustad goto out; 11876a14ee0cSDon Skidmore 11886a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 11896a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 11906a14ee0cSDon Skidmore 11916a14ee0cSDon Skidmore /* Write IOSF control register */ 11926a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 11936a14ee0cSDon Skidmore 11946a14ee0cSDon Skidmore /* Write IOSF data register */ 11956a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 11966a14ee0cSDon Skidmore 1197ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 11986a14ee0cSDon Skidmore 11996a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 12006a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 12016a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 12026a14ee0cSDon Skidmore hw_dbg(hw, "Failed to write, error %x\n", error); 12036a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 12046a14ee0cSDon Skidmore } 12056a14ee0cSDon Skidmore 1206ae14a1d8SMark Rustad out: 1207ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 1208ae14a1d8SMark Rustad return ret; 12096a14ee0cSDon Skidmore } 12106a14ee0cSDon Skidmore 12110c1b7de4SDon Skidmore /** 12120c1b7de4SDon Skidmore * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration 12136a14ee0cSDon Skidmore * @hw: pointer to hardware structure 12146a14ee0cSDon Skidmore * 12150c1b7de4SDon Skidmore * iXfI configuration needed for ixgbe_mac_X550EM_x devices. 12166a14ee0cSDon Skidmore **/ 12170c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) 12186a14ee0cSDon Skidmore { 12196a14ee0cSDon Skidmore s32 status; 12206a14ee0cSDon Skidmore u32 reg_val; 12216a14ee0cSDon Skidmore 12226a14ee0cSDon Skidmore /* Disable training protocol FSM. */ 12236a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12246a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 12256a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12266a14ee0cSDon Skidmore if (status) 12276a14ee0cSDon Skidmore return status; 12286a14ee0cSDon Skidmore 12296a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 12306a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12316a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 12326a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12336a14ee0cSDon Skidmore if (status) 12346a14ee0cSDon Skidmore return status; 12356a14ee0cSDon Skidmore 12366a14ee0cSDon Skidmore /* Disable Flex from training TXFFE. */ 12376a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12386a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 12396a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12406a14ee0cSDon Skidmore if (status) 12416a14ee0cSDon Skidmore return status; 12426a14ee0cSDon Skidmore 12436a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 12446a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 12456a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 12466a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12476a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 12486a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12496a14ee0cSDon Skidmore if (status) 12506a14ee0cSDon Skidmore return status; 12516a14ee0cSDon Skidmore 12526a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12536a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 12546a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12556a14ee0cSDon Skidmore if (status) 12566a14ee0cSDon Skidmore return status; 12576a14ee0cSDon Skidmore 12586a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 12596a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 12606a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 12616a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12626a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 12636a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12646a14ee0cSDon Skidmore if (status) 12656a14ee0cSDon Skidmore return status; 12666a14ee0cSDon Skidmore 12676a14ee0cSDon Skidmore /* Enable override for coefficients. */ 12686a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12696a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 12706a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12716a14ee0cSDon Skidmore if (status) 12726a14ee0cSDon Skidmore return status; 12736a14ee0cSDon Skidmore 12746a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 12756a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 12766a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 12776a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 12786a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12796a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 12806a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12810c1b7de4SDon Skidmore return status; 12820c1b7de4SDon Skidmore } 12830c1b7de4SDon Skidmore 12840c1b7de4SDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 12850c1b7de4SDon Skidmore * @hw: pointer to hardware structure 12860c1b7de4SDon Skidmore * @speed: the link speed to force 12870c1b7de4SDon Skidmore * 12880c1b7de4SDon Skidmore * Configures the integrated KR PHY to use iXFI mode. Used to connect an 12890c1b7de4SDon Skidmore * internal and external PHY at a specific speed, without autonegotiation. 12900c1b7de4SDon Skidmore **/ 12910c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 12920c1b7de4SDon Skidmore { 12930c1b7de4SDon Skidmore s32 status; 12940c1b7de4SDon Skidmore u32 reg_val; 12950c1b7de4SDon Skidmore 12960c1b7de4SDon Skidmore /* Disable AN and force speed to 10G Serial. */ 12970c1b7de4SDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12980c1b7de4SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 12990c1b7de4SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 13006a14ee0cSDon Skidmore if (status) 13016a14ee0cSDon Skidmore return status; 13026a14ee0cSDon Skidmore 13030c1b7de4SDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 13040c1b7de4SDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 13050c1b7de4SDon Skidmore 13060c1b7de4SDon Skidmore /* Select forced link speed for internal PHY. */ 13070c1b7de4SDon Skidmore switch (*speed) { 13080c1b7de4SDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 13090c1b7de4SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 13100c1b7de4SDon Skidmore break; 13110c1b7de4SDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 13120c1b7de4SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 13130c1b7de4SDon Skidmore break; 13140c1b7de4SDon Skidmore default: 13150c1b7de4SDon Skidmore /* Other link speeds are not supported by internal KR PHY. */ 13160c1b7de4SDon Skidmore return IXGBE_ERR_LINK_SETUP; 13170c1b7de4SDon Skidmore } 13180c1b7de4SDon Skidmore 13190c1b7de4SDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 13200c1b7de4SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 13210c1b7de4SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 13220c1b7de4SDon Skidmore if (status) 13230c1b7de4SDon Skidmore return status; 13240c1b7de4SDon Skidmore 13250c1b7de4SDon Skidmore /* Additional configuration needed for x550em_x */ 13260c1b7de4SDon Skidmore if (hw->mac.type == ixgbe_mac_X550EM_x) { 13270c1b7de4SDon Skidmore status = ixgbe_setup_ixfi_x550em_x(hw); 13280c1b7de4SDon Skidmore if (status) 13290c1b7de4SDon Skidmore return status; 13300c1b7de4SDon Skidmore } 13310c1b7de4SDon Skidmore 13326a14ee0cSDon Skidmore /* Toggle port SW reset by AN reset. */ 13336a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 13346a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 13356a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 13366a14ee0cSDon Skidmore if (status) 13376a14ee0cSDon Skidmore return status; 13386a14ee0cSDon Skidmore 13396a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 13406a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 13416a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 13426a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 13436a14ee0cSDon Skidmore 13446a14ee0cSDon Skidmore return status; 13456a14ee0cSDon Skidmore } 13466a14ee0cSDon Skidmore 1347c3dc4c09SDon Skidmore /** 1348e23f3336SMark Rustad * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported 1349e23f3336SMark Rustad * @hw: pointer to hardware structure 1350e23f3336SMark Rustad * @linear: true if SFP module is linear 1351e23f3336SMark Rustad */ 1352e23f3336SMark Rustad static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) 1353e23f3336SMark Rustad { 1354e23f3336SMark Rustad switch (hw->phy.sfp_type) { 1355e23f3336SMark Rustad case ixgbe_sfp_type_not_present: 1356e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_PRESENT; 1357e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core0: 1358e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core1: 1359e23f3336SMark Rustad *linear = true; 1360e23f3336SMark Rustad break; 1361e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core0: 1362e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core1: 1363e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core0: 1364e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core1: 1365e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core0: 1366e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core1: 1367e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core0: 1368e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core1: 1369e23f3336SMark Rustad *linear = false; 1370e23f3336SMark Rustad break; 1371e23f3336SMark Rustad case ixgbe_sfp_type_unknown: 1372e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core0: 1373e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core1: 1374e23f3336SMark Rustad default: 1375e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_SUPPORTED; 1376e23f3336SMark Rustad } 1377e23f3336SMark Rustad 1378e23f3336SMark Rustad return 0; 1379e23f3336SMark Rustad } 1380e23f3336SMark Rustad 1381e23f3336SMark Rustad /** 13826d373a1bSMark Rustad * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. 13836d373a1bSMark Rustad * @hw: pointer to hardware structure 13846d373a1bSMark Rustad * 13856d373a1bSMark Rustad * Configures the extern PHY and the integrated KR PHY for SFP support. 13866d373a1bSMark Rustad */ 13876d373a1bSMark Rustad static s32 13886d373a1bSMark Rustad ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, 13896d373a1bSMark Rustad ixgbe_link_speed speed, 13906d373a1bSMark Rustad __always_unused bool autoneg_wait_to_complete) 13916d373a1bSMark Rustad { 1392e23f3336SMark Rustad s32 status; 1393812d7dffSEmil Tantilov u16 reg_slice, reg_val; 1394e23f3336SMark Rustad bool setup_linear = false; 1395e23f3336SMark Rustad 1396e23f3336SMark Rustad /* Check if SFP module is supported and linear */ 1397e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 1398e23f3336SMark Rustad 1399e23f3336SMark Rustad /* If no SFP module present, then return success. Return success since 1400e23f3336SMark Rustad * there is no reason to configure CS4227 and SFP not present error is 1401e23f3336SMark Rustad * not accepted in the setup MAC link flow. 1402e23f3336SMark Rustad */ 1403e23f3336SMark Rustad if (status == IXGBE_ERR_SFP_NOT_PRESENT) 1404e23f3336SMark Rustad return 0; 1405e23f3336SMark Rustad 1406e23f3336SMark Rustad if (status) 1407e23f3336SMark Rustad return status; 1408e23f3336SMark Rustad 1409d91e3a7dSMark Rustad /* Configure internal PHY for KR/KX. */ 1410812d7dffSEmil Tantilov ixgbe_setup_kr_speed_x550em(hw, speed); 1411e23f3336SMark Rustad 1412d91e3a7dSMark Rustad /* Configure CS4227 LINE side to proper mode. */ 1413812d7dffSEmil Tantilov reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 1414d91e3a7dSMark Rustad if (setup_linear) 1415812d7dffSEmil Tantilov reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; 1416d91e3a7dSMark Rustad else 1417812d7dffSEmil Tantilov reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; 1418b71f6c40SEmil Tantilov 1419b71f6c40SEmil Tantilov status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, 1420b71f6c40SEmil Tantilov reg_val); 1421b71f6c40SEmil Tantilov 1422e23f3336SMark Rustad return status; 14236d373a1bSMark Rustad } 14246d373a1bSMark Rustad 14256d373a1bSMark Rustad /** 14262d40cd17SMark Rustad * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP 14272d40cd17SMark Rustad * @hw: pointer to hardware structure 14282d40cd17SMark Rustad * 14292d40cd17SMark Rustad * Configure the the integrated PHY for native SFP support. 14302d40cd17SMark Rustad */ 14312d40cd17SMark Rustad static s32 14322d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, 14332d40cd17SMark Rustad __always_unused bool autoneg_wait_to_complete) 14342d40cd17SMark Rustad { 14352d40cd17SMark Rustad bool setup_linear = false; 14362d40cd17SMark Rustad u32 reg_phy_int; 14372d40cd17SMark Rustad s32 rc; 14382d40cd17SMark Rustad 14392d40cd17SMark Rustad /* Check if SFP module is supported and linear */ 14402d40cd17SMark Rustad rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 14412d40cd17SMark Rustad 14422d40cd17SMark Rustad /* If no SFP module present, then return success. Return success since 14432d40cd17SMark Rustad * SFP not present error is not excepted in the setup MAC link flow. 14442d40cd17SMark Rustad */ 14452d40cd17SMark Rustad if (rc == IXGBE_ERR_SFP_NOT_PRESENT) 14462d40cd17SMark Rustad return 0; 14472d40cd17SMark Rustad 14482d40cd17SMark Rustad if (!rc) 14492d40cd17SMark Rustad return rc; 14502d40cd17SMark Rustad 14512d40cd17SMark Rustad /* Configure internal PHY for native SFI */ 14522d40cd17SMark Rustad rc = hw->mac.ops.read_iosf_sb_reg(hw, 14532d40cd17SMark Rustad IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), 14542d40cd17SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 14552d40cd17SMark Rustad ®_phy_int); 14562d40cd17SMark Rustad if (rc) 14572d40cd17SMark Rustad return rc; 14582d40cd17SMark Rustad 14592d40cd17SMark Rustad if (setup_linear) { 14602d40cd17SMark Rustad reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING; 14612d40cd17SMark Rustad reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR; 14622d40cd17SMark Rustad } else { 14632d40cd17SMark Rustad reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING; 14642d40cd17SMark Rustad reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR; 14652d40cd17SMark Rustad } 14662d40cd17SMark Rustad 14672d40cd17SMark Rustad rc = hw->mac.ops.write_iosf_sb_reg(hw, 14682d40cd17SMark Rustad IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), 14692d40cd17SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 14702d40cd17SMark Rustad reg_phy_int); 14712d40cd17SMark Rustad if (rc) 14722d40cd17SMark Rustad return rc; 14732d40cd17SMark Rustad 14742d40cd17SMark Rustad /* Setup XFI/SFI internal link */ 14752d40cd17SMark Rustad return ixgbe_setup_ixfi_x550em(hw, &speed); 14762d40cd17SMark Rustad } 14772d40cd17SMark Rustad 14782d40cd17SMark Rustad /** 14792d40cd17SMark Rustad * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP 14802d40cd17SMark Rustad * @hw: pointer to hardware structure 14812d40cd17SMark Rustad * 14822d40cd17SMark Rustad * Configure the the integrated PHY for SFP support. 14832d40cd17SMark Rustad */ 14842d40cd17SMark Rustad static s32 14852d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, 14862d40cd17SMark Rustad __always_unused bool autoneg_wait_to_complete) 14872d40cd17SMark Rustad { 14882d40cd17SMark Rustad u32 reg_slice, slice_offset; 14892d40cd17SMark Rustad bool setup_linear = false; 14902d40cd17SMark Rustad u16 reg_phy_ext; 14912d40cd17SMark Rustad s32 rc; 14922d40cd17SMark Rustad 14932d40cd17SMark Rustad /* Check if SFP module is supported and linear */ 14942d40cd17SMark Rustad rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 14952d40cd17SMark Rustad 14962d40cd17SMark Rustad /* If no SFP module present, then return success. Return success since 14972d40cd17SMark Rustad * SFP not present error is not excepted in the setup MAC link flow. 14982d40cd17SMark Rustad */ 14992d40cd17SMark Rustad if (rc == IXGBE_ERR_SFP_NOT_PRESENT) 15002d40cd17SMark Rustad return 0; 15012d40cd17SMark Rustad 15022d40cd17SMark Rustad if (!rc) 15032d40cd17SMark Rustad return rc; 15042d40cd17SMark Rustad 15052d40cd17SMark Rustad /* Configure internal PHY for KR/KX. */ 15062d40cd17SMark Rustad ixgbe_setup_kr_speed_x550em(hw, speed); 15072d40cd17SMark Rustad 15087564a888SMark Rustad if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE) 15092d40cd17SMark Rustad return IXGBE_ERR_PHY_ADDR_INVALID; 15102d40cd17SMark Rustad 15112d40cd17SMark Rustad /* Get external PHY device id */ 15122d40cd17SMark Rustad rc = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, 15132d40cd17SMark Rustad IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 15142d40cd17SMark Rustad if (rc) 15152d40cd17SMark Rustad return rc; 15162d40cd17SMark Rustad 15172d40cd17SMark Rustad /* When configuring quad port CS4223, the MAC instance is part 15182d40cd17SMark Rustad * of the slice offset. 15192d40cd17SMark Rustad */ 15202d40cd17SMark Rustad if (reg_phy_ext == IXGBE_CS4223_PHY_ID) 15212d40cd17SMark Rustad slice_offset = (hw->bus.lan_id + 15222d40cd17SMark Rustad (hw->bus.instance_id << 1)) << 12; 15232d40cd17SMark Rustad else 15242d40cd17SMark Rustad slice_offset = hw->bus.lan_id << 12; 15252d40cd17SMark Rustad 15262d40cd17SMark Rustad /* Configure CS4227/CS4223 LINE side to proper mode. */ 15272d40cd17SMark Rustad reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; 15282d40cd17SMark Rustad if (setup_linear) 15292d40cd17SMark Rustad reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 15302d40cd17SMark Rustad else 15312d40cd17SMark Rustad reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 15322d40cd17SMark Rustad return hw->phy.ops.write_reg(hw, reg_slice, IXGBE_MDIO_ZERO_DEV_TYPE, 15332d40cd17SMark Rustad reg_phy_ext); 15342d40cd17SMark Rustad } 15352d40cd17SMark Rustad 15362d40cd17SMark Rustad /** 1537c3dc4c09SDon Skidmore * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 1538c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1539c3dc4c09SDon Skidmore * @speed: new link speed 1540c3dc4c09SDon Skidmore * @autoneg_wait_to_complete: true when waiting for completion is needed 1541c3dc4c09SDon Skidmore * 1542c3dc4c09SDon Skidmore * Setup internal/external PHY link speed based on link speed, then set 1543c3dc4c09SDon Skidmore * external PHY auto advertised link speed. 1544c3dc4c09SDon Skidmore * 1545c3dc4c09SDon Skidmore * Returns error status for any failure 1546c3dc4c09SDon Skidmore **/ 1547c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 1548c3dc4c09SDon Skidmore ixgbe_link_speed speed, 1549c3dc4c09SDon Skidmore bool autoneg_wait) 1550c3dc4c09SDon Skidmore { 1551c3dc4c09SDon Skidmore s32 status; 1552c3dc4c09SDon Skidmore ixgbe_link_speed force_speed; 1553c3dc4c09SDon Skidmore 1554c3dc4c09SDon Skidmore /* Setup internal/external PHY link speed to iXFI (10G), unless 1555c3dc4c09SDon Skidmore * only 1G is auto advertised then setup KX link. 1556c3dc4c09SDon Skidmore */ 1557c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1558c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 1559c3dc4c09SDon Skidmore else 1560c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 1561c3dc4c09SDon Skidmore 1562c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup XFI internal link. */ 1563c3dc4c09SDon Skidmore if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1564c3dc4c09SDon Skidmore status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 1565c3dc4c09SDon Skidmore 1566c3dc4c09SDon Skidmore if (status) 1567c3dc4c09SDon Skidmore return status; 1568c3dc4c09SDon Skidmore } 1569c3dc4c09SDon Skidmore 1570c3dc4c09SDon Skidmore return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 1571c3dc4c09SDon Skidmore } 1572c3dc4c09SDon Skidmore 1573a4e293a5SDon Skidmore /** ixgbe_check_link_t_X550em - Determine link and speed status 1574a4e293a5SDon Skidmore * @hw: pointer to hardware structure 1575a4e293a5SDon Skidmore * @speed: pointer to link speed 1576a4e293a5SDon Skidmore * @link_up: true when link is up 1577a4e293a5SDon Skidmore * @link_up_wait_to_complete: bool used to wait for link up or not 1578a4e293a5SDon Skidmore * 1579a4e293a5SDon Skidmore * Check that both the MAC and X557 external PHY have link. 1580a4e293a5SDon Skidmore **/ 1581a4e293a5SDon Skidmore static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, 1582a4e293a5SDon Skidmore ixgbe_link_speed *speed, 1583a4e293a5SDon Skidmore bool *link_up, 1584a4e293a5SDon Skidmore bool link_up_wait_to_complete) 1585a4e293a5SDon Skidmore { 1586a4e293a5SDon Skidmore u32 status; 158721d882ebSEmil Tantilov u16 i, autoneg_status; 1588a4e293a5SDon Skidmore 1589a4e293a5SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 1590a4e293a5SDon Skidmore return IXGBE_ERR_CONFIG; 1591a4e293a5SDon Skidmore 1592a4e293a5SDon Skidmore status = ixgbe_check_mac_link_generic(hw, speed, link_up, 1593a4e293a5SDon Skidmore link_up_wait_to_complete); 1594a4e293a5SDon Skidmore 1595a4e293a5SDon Skidmore /* If check link fails or MAC link is not up, then return */ 1596a4e293a5SDon Skidmore if (status || !(*link_up)) 1597a4e293a5SDon Skidmore return status; 1598a4e293a5SDon Skidmore 1599a4e293a5SDon Skidmore /* MAC link is up, so check external PHY link. 160021d882ebSEmil Tantilov * Link status is latching low, and can only be used to detect link 160121d882ebSEmil Tantilov * drop, and not the current status of the link without performing 160221d882ebSEmil Tantilov * back-to-back reads. 1603a4e293a5SDon Skidmore */ 160421d882ebSEmil Tantilov for (i = 0; i < 2; i++) { 16054dc4000bSEmil Tantilov status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 1606a4e293a5SDon Skidmore &autoneg_status); 160721d882ebSEmil Tantilov 1608a4e293a5SDon Skidmore if (status) 1609a4e293a5SDon Skidmore return status; 161021d882ebSEmil Tantilov } 1611a4e293a5SDon Skidmore 1612a4e293a5SDon Skidmore /* If external PHY link is not up, then indicate link not up */ 1613a4e293a5SDon Skidmore if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 1614a4e293a5SDon Skidmore *link_up = false; 1615a4e293a5SDon Skidmore 1616a4e293a5SDon Skidmore return 0; 1617a4e293a5SDon Skidmore } 1618a4e293a5SDon Skidmore 1619200157c2SMark Rustad /** 1620200157c2SMark Rustad * ixgbe_setup_sgmii - Set up link for sgmii 1621200157c2SMark Rustad * @hw: pointer to hardware structure 1622200157c2SMark Rustad */ 1623200157c2SMark Rustad static s32 1624200157c2SMark Rustad ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, 1625200157c2SMark Rustad __always_unused bool autoneg_wait_to_complete) 1626200157c2SMark Rustad { 1627200157c2SMark Rustad struct ixgbe_mac_info *mac = &hw->mac; 1628200157c2SMark Rustad u32 lval, sval; 1629200157c2SMark Rustad s32 rc; 1630200157c2SMark Rustad 1631200157c2SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 1632200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1633200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 1634200157c2SMark Rustad if (rc) 1635200157c2SMark Rustad return rc; 1636200157c2SMark Rustad 1637200157c2SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1638200157c2SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 1639200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 1640200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 1641200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 1642200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1643200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1644200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1645200157c2SMark Rustad if (rc) 1646200157c2SMark Rustad return rc; 1647200157c2SMark Rustad 1648200157c2SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 1649200157c2SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1650200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 1651200157c2SMark Rustad if (rc) 1652200157c2SMark Rustad return rc; 1653200157c2SMark Rustad 1654200157c2SMark Rustad sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 1655200157c2SMark Rustad sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 1656200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1657200157c2SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1658200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 1659200157c2SMark Rustad if (rc) 1660200157c2SMark Rustad return rc; 1661200157c2SMark Rustad 1662200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 1663200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1664200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1665200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1666200157c2SMark Rustad 1667200157c2SMark Rustad return rc; 1668200157c2SMark Rustad } 1669200157c2SMark Rustad 16702916500dSDon Skidmore /** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers 16712916500dSDon Skidmore * @hw: pointer to hardware structure 16722916500dSDon Skidmore **/ 16732916500dSDon Skidmore static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw) 16742916500dSDon Skidmore { 16752916500dSDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 16762916500dSDon Skidmore 16772916500dSDon Skidmore switch (mac->ops.get_media_type(hw)) { 16782916500dSDon Skidmore case ixgbe_media_type_fiber: 16792916500dSDon Skidmore mac->ops.setup_fc = NULL; 16802916500dSDon Skidmore mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; 16812916500dSDon Skidmore break; 16822916500dSDon Skidmore case ixgbe_media_type_backplane: 16832916500dSDon Skidmore mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; 16842916500dSDon Skidmore mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; 16852916500dSDon Skidmore break; 16862916500dSDon Skidmore default: 16872916500dSDon Skidmore break; 16882916500dSDon Skidmore } 16892916500dSDon Skidmore } 16902916500dSDon Skidmore 1691c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 1692c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1693c3dc4c09SDon Skidmore **/ 1694c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 1695c3dc4c09SDon Skidmore { 1696c3dc4c09SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 1697c3dc4c09SDon Skidmore 1698abf76d76SEmil Tantilov mac->ops.setup_fc = ixgbe_setup_fc_x550em; 1699abf76d76SEmil Tantilov 1700c3dc4c09SDon Skidmore switch (mac->ops.get_media_type(hw)) { 1701c3dc4c09SDon Skidmore case ixgbe_media_type_fiber: 1702c3dc4c09SDon Skidmore /* CS4227 does not support autoneg, so disable the laser control 1703c3dc4c09SDon Skidmore * functions for SFP+ fiber 1704c3dc4c09SDon Skidmore */ 1705c3dc4c09SDon Skidmore mac->ops.disable_tx_laser = NULL; 1706c3dc4c09SDon Skidmore mac->ops.enable_tx_laser = NULL; 1707c3dc4c09SDon Skidmore mac->ops.flap_tx_laser = NULL; 17086d373a1bSMark Rustad mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; 17092d40cd17SMark Rustad switch (hw->device_id) { 17102d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 17112d40cd17SMark Rustad mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; 17122d40cd17SMark Rustad break; 17132d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 17142d40cd17SMark Rustad mac->ops.setup_mac_link = 17152d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a; 17162d40cd17SMark Rustad break; 17172d40cd17SMark Rustad default: 17182d40cd17SMark Rustad mac->ops.setup_mac_link = 17192d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550em; 17202d40cd17SMark Rustad break; 17212d40cd17SMark Rustad } 17226d373a1bSMark Rustad mac->ops.set_rate_select_speed = 17236d373a1bSMark Rustad ixgbe_set_soft_rate_select_speed; 1724c3dc4c09SDon Skidmore break; 1725c3dc4c09SDon Skidmore case ixgbe_media_type_copper: 1726c3dc4c09SDon Skidmore mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 1727afdc71e4SMark Rustad mac->ops.setup_fc = ixgbe_setup_fc_generic; 1728a4e293a5SDon Skidmore mac->ops.check_link = ixgbe_check_link_t_X550em; 172949425dfcSMark Rustad return; 173049425dfcSMark Rustad case ixgbe_media_type_backplane: 1731200157c2SMark Rustad if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || 1732200157c2SMark Rustad hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) 1733200157c2SMark Rustad mac->ops.setup_link = ixgbe_setup_sgmii; 1734c3dc4c09SDon Skidmore break; 1735c3dc4c09SDon Skidmore default: 1736c3dc4c09SDon Skidmore break; 1737c3dc4c09SDon Skidmore } 17382916500dSDon Skidmore 17392916500dSDon Skidmore /* Additional modification for X550em_a devices */ 17402916500dSDon Skidmore if (hw->mac.type == ixgbe_mac_x550em_a) 17412916500dSDon Skidmore ixgbe_init_mac_link_ops_X550em_a(hw); 1742c3dc4c09SDon Skidmore } 1743c3dc4c09SDon Skidmore 1744c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module 1745c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1746c3dc4c09SDon Skidmore */ 1747c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 1748c3dc4c09SDon Skidmore { 1749e23f3336SMark Rustad s32 status; 1750e23f3336SMark Rustad bool linear; 1751c3dc4c09SDon Skidmore 1752e23f3336SMark Rustad /* Check if SFP module is supported */ 1753e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &linear); 1754e23f3336SMark Rustad if (status) 1755e23f3336SMark Rustad return status; 1756c3dc4c09SDon Skidmore 1757c3dc4c09SDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 1758c3dc4c09SDon Skidmore hw->phy.ops.reset = NULL; 1759c3dc4c09SDon Skidmore 1760e23f3336SMark Rustad return 0; 1761c3dc4c09SDon Skidmore } 1762c3dc4c09SDon Skidmore 1763c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities 1764c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1765c3dc4c09SDon Skidmore * @speed: pointer to link speed 1766c3dc4c09SDon Skidmore * @autoneg: true when autoneg or autotry is enabled 1767c3dc4c09SDon Skidmore **/ 1768c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 1769c3dc4c09SDon Skidmore ixgbe_link_speed *speed, 1770c3dc4c09SDon Skidmore bool *autoneg) 1771c3dc4c09SDon Skidmore { 1772c3dc4c09SDon Skidmore /* SFP */ 1773c3dc4c09SDon Skidmore if (hw->phy.media_type == ixgbe_media_type_fiber) { 1774c3dc4c09SDon Skidmore /* CS4227 SFP must not enable auto-negotiation */ 1775c3dc4c09SDon Skidmore *autoneg = false; 1776c3dc4c09SDon Skidmore 1777c3dc4c09SDon Skidmore if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 1778c3dc4c09SDon Skidmore hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { 1779c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 1780c3dc4c09SDon Skidmore return 0; 1781c3dc4c09SDon Skidmore } 1782c3dc4c09SDon Skidmore 1783c3dc4c09SDon Skidmore /* Link capabilities are based on SFP */ 1784c3dc4c09SDon Skidmore if (hw->phy.multispeed_fiber) 1785c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1786c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1787c3dc4c09SDon Skidmore else 1788c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL; 1789c3dc4c09SDon Skidmore } else { 1790c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1791c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1792c3dc4c09SDon Skidmore *autoneg = true; 1793c3dc4c09SDon Skidmore } 1794c3dc4c09SDon Skidmore return 0; 1795c3dc4c09SDon Skidmore } 1796c3dc4c09SDon Skidmore 1797c3dc4c09SDon Skidmore /** 1798c3dc4c09SDon Skidmore * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause 1799c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1800c3dc4c09SDon Skidmore * @lsc: pointer to boolean flag which indicates whether external Base T 1801c3dc4c09SDon Skidmore * PHY interrupt is lsc 1802c3dc4c09SDon Skidmore * 1803c3dc4c09SDon Skidmore * Determime if external Base T PHY interrupt cause is high temperature 1804c3dc4c09SDon Skidmore * failure alarm or link status change. 1805c3dc4c09SDon Skidmore * 1806c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1807c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1808c3dc4c09SDon Skidmore **/ 1809c3dc4c09SDon Skidmore static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) 1810c3dc4c09SDon Skidmore { 1811c3dc4c09SDon Skidmore u32 status; 1812c3dc4c09SDon Skidmore u16 reg; 1813c3dc4c09SDon Skidmore 1814c3dc4c09SDon Skidmore *lsc = false; 1815c3dc4c09SDon Skidmore 1816c3dc4c09SDon Skidmore /* Vendor alarm triggered */ 1817c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 18184dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1819c3dc4c09SDon Skidmore ®); 1820c3dc4c09SDon Skidmore 1821c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 1822c3dc4c09SDon Skidmore return status; 1823c3dc4c09SDon Skidmore 1824c3dc4c09SDon Skidmore /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 1825c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 18264dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1827c3dc4c09SDon Skidmore ®); 1828c3dc4c09SDon Skidmore 1829c3dc4c09SDon Skidmore if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1830c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 1831c3dc4c09SDon Skidmore return status; 1832c3dc4c09SDon Skidmore 183383a9fb20SMark Rustad /* Global alarm triggered */ 1834c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 18354dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1836c3dc4c09SDon Skidmore ®); 1837c3dc4c09SDon Skidmore 1838c3dc4c09SDon Skidmore if (status) 1839c3dc4c09SDon Skidmore return status; 1840c3dc4c09SDon Skidmore 1841c3dc4c09SDon Skidmore /* If high temperature failure, then return over temp error and exit */ 1842c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 1843c3dc4c09SDon Skidmore /* power down the PHY in case the PHY FW didn't already */ 1844c3dc4c09SDon Skidmore ixgbe_set_copper_phy_power(hw, false); 1845c3dc4c09SDon Skidmore return IXGBE_ERR_OVERTEMP; 1846c3dc4c09SDon Skidmore } 184783a9fb20SMark Rustad if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { 184883a9fb20SMark Rustad /* device fault alarm triggered */ 184983a9fb20SMark Rustad status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, 18504dc4000bSEmil Tantilov MDIO_MMD_VEND1, 185183a9fb20SMark Rustad ®); 185283a9fb20SMark Rustad if (status) 185383a9fb20SMark Rustad return status; 185483a9fb20SMark Rustad 185583a9fb20SMark Rustad /* if device fault was due to high temp alarm handle and exit */ 185683a9fb20SMark Rustad if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { 185783a9fb20SMark Rustad /* power down the PHY in case the PHY FW didn't */ 185883a9fb20SMark Rustad ixgbe_set_copper_phy_power(hw, false); 185983a9fb20SMark Rustad return IXGBE_ERR_OVERTEMP; 186083a9fb20SMark Rustad } 186183a9fb20SMark Rustad } 1862c3dc4c09SDon Skidmore 1863c3dc4c09SDon Skidmore /* Vendor alarm 2 triggered */ 1864c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 18654dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 1866c3dc4c09SDon Skidmore 1867c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 1868c3dc4c09SDon Skidmore return status; 1869c3dc4c09SDon Skidmore 1870c3dc4c09SDon Skidmore /* link connect/disconnect event occurred */ 1871c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 18724dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 1873c3dc4c09SDon Skidmore 1874c3dc4c09SDon Skidmore if (status) 1875c3dc4c09SDon Skidmore return status; 1876c3dc4c09SDon Skidmore 1877c3dc4c09SDon Skidmore /* Indicate LSC */ 1878c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 1879c3dc4c09SDon Skidmore *lsc = true; 1880c3dc4c09SDon Skidmore 1881c3dc4c09SDon Skidmore return 0; 1882c3dc4c09SDon Skidmore } 1883c3dc4c09SDon Skidmore 1884c3dc4c09SDon Skidmore /** 1885c3dc4c09SDon Skidmore * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 1886c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1887c3dc4c09SDon Skidmore * 1888c3dc4c09SDon Skidmore * Enable link status change and temperature failure alarm for the external 1889c3dc4c09SDon Skidmore * Base T PHY 1890c3dc4c09SDon Skidmore * 1891c3dc4c09SDon Skidmore * Returns PHY access status 1892c3dc4c09SDon Skidmore **/ 1893c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1894c3dc4c09SDon Skidmore { 1895c3dc4c09SDon Skidmore u32 status; 1896c3dc4c09SDon Skidmore u16 reg; 1897c3dc4c09SDon Skidmore bool lsc; 1898c3dc4c09SDon Skidmore 1899c3dc4c09SDon Skidmore /* Clear interrupt flags */ 1900c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1901c3dc4c09SDon Skidmore 1902c3dc4c09SDon Skidmore /* Enable link status change alarm */ 1903c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 19044dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 1905c3dc4c09SDon Skidmore if (status) 1906c3dc4c09SDon Skidmore return status; 1907c3dc4c09SDon Skidmore 1908c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 1909c3dc4c09SDon Skidmore 1910c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 19114dc4000bSEmil Tantilov MDIO_MMD_AN, reg); 1912c3dc4c09SDon Skidmore if (status) 1913c3dc4c09SDon Skidmore return status; 1914c3dc4c09SDon Skidmore 191583a9fb20SMark Rustad /* Enable high temperature failure and global fault alarms */ 1916c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 19174dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1918c3dc4c09SDon Skidmore ®); 1919c3dc4c09SDon Skidmore if (status) 1920c3dc4c09SDon Skidmore return status; 1921c3dc4c09SDon Skidmore 192283a9fb20SMark Rustad reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | 192383a9fb20SMark Rustad IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); 1924c3dc4c09SDon Skidmore 1925c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 19264dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1927c3dc4c09SDon Skidmore reg); 1928c3dc4c09SDon Skidmore if (status) 1929c3dc4c09SDon Skidmore return status; 1930c3dc4c09SDon Skidmore 1931c3dc4c09SDon Skidmore /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 1932c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 19334dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1934c3dc4c09SDon Skidmore ®); 1935c3dc4c09SDon Skidmore if (status) 1936c3dc4c09SDon Skidmore return status; 1937c3dc4c09SDon Skidmore 1938c3dc4c09SDon Skidmore reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1939c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT); 1940c3dc4c09SDon Skidmore 1941c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 19424dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1943c3dc4c09SDon Skidmore reg); 1944c3dc4c09SDon Skidmore if (status) 1945c3dc4c09SDon Skidmore return status; 1946c3dc4c09SDon Skidmore 1947c3dc4c09SDon Skidmore /* Enable chip-wide vendor alarm */ 1948c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 19494dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1950c3dc4c09SDon Skidmore ®); 1951c3dc4c09SDon Skidmore if (status) 1952c3dc4c09SDon Skidmore return status; 1953c3dc4c09SDon Skidmore 1954c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 1955c3dc4c09SDon Skidmore 1956c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 19574dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1958c3dc4c09SDon Skidmore reg); 1959c3dc4c09SDon Skidmore 1960c3dc4c09SDon Skidmore return status; 1961c3dc4c09SDon Skidmore } 1962c3dc4c09SDon Skidmore 1963c3dc4c09SDon Skidmore /** 1964c3dc4c09SDon Skidmore * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 1965c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1966c3dc4c09SDon Skidmore * 1967c3dc4c09SDon Skidmore * Handle external Base T PHY interrupt. If high temperature 1968c3dc4c09SDon Skidmore * failure alarm then return error, else if link status change 1969c3dc4c09SDon Skidmore * then setup internal/external PHY link 1970c3dc4c09SDon Skidmore * 1971c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1972c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1973c3dc4c09SDon Skidmore **/ 1974c3dc4c09SDon Skidmore static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1975c3dc4c09SDon Skidmore { 1976c3dc4c09SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 1977c3dc4c09SDon Skidmore bool lsc; 1978c3dc4c09SDon Skidmore u32 status; 1979c3dc4c09SDon Skidmore 1980c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1981c3dc4c09SDon Skidmore if (status) 1982c3dc4c09SDon Skidmore return status; 1983c3dc4c09SDon Skidmore 1984a85ce532SMark Rustad if (lsc && phy->ops.setup_internal_link) 1985c3dc4c09SDon Skidmore return phy->ops.setup_internal_link(hw); 1986c3dc4c09SDon Skidmore 1987c3dc4c09SDon Skidmore return 0; 1988c3dc4c09SDon Skidmore } 1989c3dc4c09SDon Skidmore 1990c3dc4c09SDon Skidmore /** 1991c3dc4c09SDon Skidmore * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 1992c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1993c3dc4c09SDon Skidmore * @speed: link speed 1994c3dc4c09SDon Skidmore * 1995c3dc4c09SDon Skidmore * Configures the integrated KR PHY. 1996c3dc4c09SDon Skidmore **/ 1997c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 1998c3dc4c09SDon Skidmore ixgbe_link_speed speed) 1999c3dc4c09SDon Skidmore { 2000c3dc4c09SDon Skidmore s32 status; 2001c3dc4c09SDon Skidmore u32 reg_val; 2002c3dc4c09SDon Skidmore 20039a5c27e6SMark Rustad status = hw->mac.ops.read_iosf_sb_reg(hw, 2004c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2005c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2006c3dc4c09SDon Skidmore if (status) 2007c3dc4c09SDon Skidmore return status; 2008c3dc4c09SDon Skidmore 2009c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 2010c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ | 2011c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC); 2012c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 2013c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 2014c3dc4c09SDon Skidmore 2015c3dc4c09SDon Skidmore /* Advertise 10G support. */ 2016c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 2017c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 2018c3dc4c09SDon Skidmore 2019c3dc4c09SDon Skidmore /* Advertise 1G support. */ 2020c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_1GB_FULL) 2021c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 2022c3dc4c09SDon Skidmore 2023c3dc4c09SDon Skidmore /* Restart auto-negotiation. */ 2024c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 20259a5c27e6SMark Rustad status = hw->mac.ops.write_iosf_sb_reg(hw, 2026c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2027c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2028c3dc4c09SDon Skidmore 2029c3dc4c09SDon Skidmore return status; 2030c3dc4c09SDon Skidmore } 2031c3dc4c09SDon Skidmore 20326a14ee0cSDon Skidmore /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. 20336a14ee0cSDon Skidmore * @hw: pointer to hardware structure 20346a14ee0cSDon Skidmore * 20356a14ee0cSDon Skidmore * Configures the integrated KX4 PHY. 20366a14ee0cSDon Skidmore **/ 20377ddbde3fSDon Skidmore static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) 20386a14ee0cSDon Skidmore { 20396a14ee0cSDon Skidmore s32 status; 20406a14ee0cSDon Skidmore u32 reg_val; 20416a14ee0cSDon Skidmore 20429a5c27e6SMark Rustad status = hw->mac.ops.read_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, 20436a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 20446a14ee0cSDon Skidmore hw->bus.lan_id, ®_val); 20456a14ee0cSDon Skidmore if (status) 20466a14ee0cSDon Skidmore return status; 20476a14ee0cSDon Skidmore 20486a14ee0cSDon Skidmore reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | 20496a14ee0cSDon Skidmore IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); 20506a14ee0cSDon Skidmore 20516a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; 20526a14ee0cSDon Skidmore 20536a14ee0cSDon Skidmore /* Advertise 10G support. */ 20546a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) 20556a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; 20566a14ee0cSDon Skidmore 20576a14ee0cSDon Skidmore /* Advertise 1G support. */ 20586a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) 20596a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; 20606a14ee0cSDon Skidmore 20616a14ee0cSDon Skidmore /* Restart auto-negotiation. */ 20626a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; 20639a5c27e6SMark Rustad status = hw->mac.ops.write_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, 20646a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 20656a14ee0cSDon Skidmore hw->bus.lan_id, reg_val); 20666a14ee0cSDon Skidmore 20676a14ee0cSDon Skidmore return status; 20686a14ee0cSDon Skidmore } 20696a14ee0cSDon Skidmore 2070f572b2c4SMark Rustad /** 2071f572b2c4SMark Rustad * ixgbe_setup_kr_x550em - Configure the KR PHY 20726a14ee0cSDon Skidmore * @hw: pointer to hardware structure 20736a14ee0cSDon Skidmore * 2074f572b2c4SMark Rustad * Configures the integrated KR PHY for X550EM_x. 20756a14ee0cSDon Skidmore **/ 20767ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 20776a14ee0cSDon Skidmore { 2078f572b2c4SMark Rustad if (hw->mac.type != ixgbe_mac_X550EM_x) 2079f572b2c4SMark Rustad return 0; 2080f572b2c4SMark Rustad 2081c3dc4c09SDon Skidmore return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 20826a14ee0cSDon Skidmore } 20836a14ee0cSDon Skidmore 2084c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 2085c3dc4c09SDon Skidmore * @hw: address of hardware structure 2086c3dc4c09SDon Skidmore * @link_up: address of boolean to indicate link status 2087c3dc4c09SDon Skidmore * 2088c3dc4c09SDon Skidmore * Returns error code if unable to get link status. 2089c3dc4c09SDon Skidmore **/ 2090c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 2091c3dc4c09SDon Skidmore { 2092c3dc4c09SDon Skidmore u32 ret; 2093c3dc4c09SDon Skidmore u16 autoneg_status; 2094c3dc4c09SDon Skidmore 2095c3dc4c09SDon Skidmore *link_up = false; 2096c3dc4c09SDon Skidmore 2097c3dc4c09SDon Skidmore /* read this twice back to back to indicate current status */ 20984dc4000bSEmil Tantilov ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 2099c3dc4c09SDon Skidmore &autoneg_status); 2100c3dc4c09SDon Skidmore if (ret) 2101c3dc4c09SDon Skidmore return ret; 2102c3dc4c09SDon Skidmore 21034dc4000bSEmil Tantilov ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 2104c3dc4c09SDon Skidmore &autoneg_status); 2105c3dc4c09SDon Skidmore if (ret) 2106c3dc4c09SDon Skidmore return ret; 2107c3dc4c09SDon Skidmore 2108c3dc4c09SDon Skidmore *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 2109c3dc4c09SDon Skidmore 2110c3dc4c09SDon Skidmore return 0; 2111c3dc4c09SDon Skidmore } 2112c3dc4c09SDon Skidmore 2113c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 21146a14ee0cSDon Skidmore * @hw: point to hardware structure 21156a14ee0cSDon Skidmore * 2116c3dc4c09SDon Skidmore * Configures the link between the integrated KR PHY and the external X557 PHY 2117c3dc4c09SDon Skidmore * The driver will call this function when it gets a link status change 2118c3dc4c09SDon Skidmore * interrupt from the X557 PHY. This function configures the link speed 2119c3dc4c09SDon Skidmore * between the PHYs to match the link speed of the BASE-T link. 21206a14ee0cSDon Skidmore * 21216a14ee0cSDon Skidmore * A return of a non-zero value indicates an error, and the base driver should 21226a14ee0cSDon Skidmore * not report link up. 21236a14ee0cSDon Skidmore **/ 2124c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 21256a14ee0cSDon Skidmore { 21266a14ee0cSDon Skidmore ixgbe_link_speed force_speed; 2127c3dc4c09SDon Skidmore bool link_up; 2128c3dc4c09SDon Skidmore u32 status; 2129c3dc4c09SDon Skidmore u16 speed; 21306a14ee0cSDon Skidmore 2131c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 2132c3dc4c09SDon Skidmore return IXGBE_ERR_CONFIG; 2133c3dc4c09SDon Skidmore 2134f164b845SMark Rustad if (hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { 2135f164b845SMark Rustad speed = IXGBE_LINK_SPEED_10GB_FULL | 2136f164b845SMark Rustad IXGBE_LINK_SPEED_1GB_FULL; 2137f164b845SMark Rustad return ixgbe_setup_kr_speed_x550em(hw, speed); 2138f164b845SMark Rustad } 2139f164b845SMark Rustad 2140c3dc4c09SDon Skidmore /* If link is not up, then there is no setup necessary so return */ 2141c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 21426a14ee0cSDon Skidmore if (status) 21436a14ee0cSDon Skidmore return status; 21446a14ee0cSDon Skidmore 2145c3dc4c09SDon Skidmore if (!link_up) 21466a14ee0cSDon Skidmore return 0; 21476a14ee0cSDon Skidmore 21486a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 21494dc4000bSEmil Tantilov MDIO_MMD_AN, 21506a14ee0cSDon Skidmore &speed); 2151c3dc4c09SDon Skidmore if (status) 2152c3dc4c09SDon Skidmore return status; 2153c3dc4c09SDon Skidmore 2154c3dc4c09SDon Skidmore /* If link is not still up, then no setup is necessary so return */ 2155c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 2156c3dc4c09SDon Skidmore if (status) 2157c3dc4c09SDon Skidmore return status; 2158c3dc4c09SDon Skidmore 2159c3dc4c09SDon Skidmore if (!link_up) 2160c3dc4c09SDon Skidmore return 0; 21616a14ee0cSDon Skidmore 21626a14ee0cSDon Skidmore /* clear everything but the speed and duplex bits */ 21636a14ee0cSDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 21646a14ee0cSDon Skidmore 21656a14ee0cSDon Skidmore switch (speed) { 21666a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 21676a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 21686a14ee0cSDon Skidmore break; 21696a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 21706a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 21716a14ee0cSDon Skidmore break; 21726a14ee0cSDon Skidmore default: 21736a14ee0cSDon Skidmore /* Internal PHY does not support anything else */ 21746a14ee0cSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 21756a14ee0cSDon Skidmore } 21766a14ee0cSDon Skidmore 21776a14ee0cSDon Skidmore return ixgbe_setup_ixfi_x550em(hw, &force_speed); 21786a14ee0cSDon Skidmore } 21796a14ee0cSDon Skidmore 2180f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 2181f4410d2cSDon Skidmore * @hw: pointer to hardware structure 2182f4410d2cSDon Skidmore **/ 2183f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 2184f4410d2cSDon Skidmore { 2185f4410d2cSDon Skidmore s32 status; 2186f4410d2cSDon Skidmore 2187f4410d2cSDon Skidmore status = ixgbe_reset_phy_generic(hw); 2188f4410d2cSDon Skidmore 2189f4410d2cSDon Skidmore if (status) 2190f4410d2cSDon Skidmore return status; 2191f4410d2cSDon Skidmore 2192f4410d2cSDon Skidmore /* Configure Link Status Alarm and Temperature Threshold interrupts */ 2193f4410d2cSDon Skidmore return ixgbe_enable_lasi_ext_t_x550em(hw); 2194f4410d2cSDon Skidmore } 2195f4410d2cSDon Skidmore 2196a0ad55a3SDon Skidmore /** 2197a0ad55a3SDon Skidmore * ixgbe_led_on_t_x550em - Turns on the software controllable LEDs. 2198a0ad55a3SDon Skidmore * @hw: pointer to hardware structure 2199a0ad55a3SDon Skidmore * @led_idx: led number to turn on 2200a0ad55a3SDon Skidmore **/ 2201d2d43e5bSEmil Tantilov static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 2202a0ad55a3SDon Skidmore { 2203a0ad55a3SDon Skidmore u16 phy_data; 2204a0ad55a3SDon Skidmore 2205a0ad55a3SDon Skidmore if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 2206a0ad55a3SDon Skidmore return IXGBE_ERR_PARAM; 2207a0ad55a3SDon Skidmore 2208a0ad55a3SDon Skidmore /* To turn on the LED, set mode to ON. */ 2209a0ad55a3SDon Skidmore hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 22104dc4000bSEmil Tantilov MDIO_MMD_VEND1, &phy_data); 2211a0ad55a3SDon Skidmore phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; 2212a0ad55a3SDon Skidmore hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 22134dc4000bSEmil Tantilov MDIO_MMD_VEND1, phy_data); 2214a0ad55a3SDon Skidmore 2215a0ad55a3SDon Skidmore return 0; 2216a0ad55a3SDon Skidmore } 2217a0ad55a3SDon Skidmore 2218a0ad55a3SDon Skidmore /** 2219a0ad55a3SDon Skidmore * ixgbe_led_off_t_x550em - Turns off the software controllable LEDs. 2220a0ad55a3SDon Skidmore * @hw: pointer to hardware structure 2221a0ad55a3SDon Skidmore * @led_idx: led number to turn off 2222a0ad55a3SDon Skidmore **/ 2223d2d43e5bSEmil Tantilov static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 2224a0ad55a3SDon Skidmore { 2225a0ad55a3SDon Skidmore u16 phy_data; 2226a0ad55a3SDon Skidmore 2227a0ad55a3SDon Skidmore if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 2228a0ad55a3SDon Skidmore return IXGBE_ERR_PARAM; 2229a0ad55a3SDon Skidmore 2230a0ad55a3SDon Skidmore /* To turn on the LED, set mode to ON. */ 2231a0ad55a3SDon Skidmore hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 22324dc4000bSEmil Tantilov MDIO_MMD_VEND1, &phy_data); 2233a0ad55a3SDon Skidmore phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; 2234a0ad55a3SDon Skidmore hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 22354dc4000bSEmil Tantilov MDIO_MMD_VEND1, phy_data); 2236a0ad55a3SDon Skidmore 2237a0ad55a3SDon Skidmore return 0; 2238a0ad55a3SDon Skidmore } 2239a0ad55a3SDon Skidmore 22406ac74394SDon Skidmore /** ixgbe_get_lcd_x550em - Determine lowest common denominator 22416ac74394SDon Skidmore * @hw: pointer to hardware structure 22426ac74394SDon Skidmore * @lcd_speed: pointer to lowest common link speed 22436ac74394SDon Skidmore * 22446ac74394SDon Skidmore * Determine lowest common link speed with link partner. 22456ac74394SDon Skidmore **/ 22466ac74394SDon Skidmore static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, 22476ac74394SDon Skidmore ixgbe_link_speed *lcd_speed) 22486ac74394SDon Skidmore { 22496ac74394SDon Skidmore u16 an_lp_status; 22506ac74394SDon Skidmore s32 status; 22516ac74394SDon Skidmore u16 word = hw->eeprom.ctrl_word_3; 22526ac74394SDon Skidmore 22536ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; 22546ac74394SDon Skidmore 22556ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, 22564dc4000bSEmil Tantilov MDIO_MMD_AN, 22576ac74394SDon Skidmore &an_lp_status); 22586ac74394SDon Skidmore if (status) 22596ac74394SDon Skidmore return status; 22606ac74394SDon Skidmore 22616ac74394SDon Skidmore /* If link partner advertised 1G, return 1G */ 22626ac74394SDon Skidmore if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { 22636ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; 22646ac74394SDon Skidmore return status; 22656ac74394SDon Skidmore } 22666ac74394SDon Skidmore 22676ac74394SDon Skidmore /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ 22686ac74394SDon Skidmore if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || 22696ac74394SDon Skidmore (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) 22706ac74394SDon Skidmore return status; 22716ac74394SDon Skidmore 22726ac74394SDon Skidmore /* Link partner not capable of lower speeds, return 10G */ 22736ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; 22746ac74394SDon Skidmore return status; 22756ac74394SDon Skidmore } 22766ac74394SDon Skidmore 2277afdc71e4SMark Rustad /** 2278afdc71e4SMark Rustad * ixgbe_setup_fc_x550em - Set up flow control 2279afdc71e4SMark Rustad * @hw: pointer to hardware structure 2280afdc71e4SMark Rustad */ 2281afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) 2282afdc71e4SMark Rustad { 2283afdc71e4SMark Rustad bool pause, asm_dir; 2284afdc71e4SMark Rustad u32 reg_val; 2285afdc71e4SMark Rustad s32 rc; 2286afdc71e4SMark Rustad 2287afdc71e4SMark Rustad /* Validate the requested mode */ 2288afdc71e4SMark Rustad if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 2289afdc71e4SMark Rustad hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 2290afdc71e4SMark Rustad return IXGBE_ERR_INVALID_LINK_SETTINGS; 2291afdc71e4SMark Rustad } 2292afdc71e4SMark Rustad 2293afdc71e4SMark Rustad /* 10gig parts do not have a word in the EEPROM to determine the 2294afdc71e4SMark Rustad * default flow control setting, so we explicitly set it to full. 2295afdc71e4SMark Rustad */ 2296afdc71e4SMark Rustad if (hw->fc.requested_mode == ixgbe_fc_default) 2297afdc71e4SMark Rustad hw->fc.requested_mode = ixgbe_fc_full; 2298afdc71e4SMark Rustad 2299afdc71e4SMark Rustad /* Determine PAUSE and ASM_DIR bits. */ 2300afdc71e4SMark Rustad switch (hw->fc.requested_mode) { 2301afdc71e4SMark Rustad case ixgbe_fc_none: 2302afdc71e4SMark Rustad pause = false; 2303afdc71e4SMark Rustad asm_dir = false; 2304afdc71e4SMark Rustad break; 2305afdc71e4SMark Rustad case ixgbe_fc_tx_pause: 2306afdc71e4SMark Rustad pause = false; 2307afdc71e4SMark Rustad asm_dir = true; 2308afdc71e4SMark Rustad break; 2309afdc71e4SMark Rustad case ixgbe_fc_rx_pause: 2310afdc71e4SMark Rustad /* Rx Flow control is enabled and Tx Flow control is 2311afdc71e4SMark Rustad * disabled by software override. Since there really 2312afdc71e4SMark Rustad * isn't a way to advertise that we are capable of RX 2313afdc71e4SMark Rustad * Pause ONLY, we will advertise that we support both 2314afdc71e4SMark Rustad * symmetric and asymmetric Rx PAUSE, as such we fall 2315afdc71e4SMark Rustad * through to the fc_full statement. Later, we will 2316afdc71e4SMark Rustad * disable the adapter's ability to send PAUSE frames. 2317afdc71e4SMark Rustad */ 2318afdc71e4SMark Rustad /* Fallthrough */ 2319afdc71e4SMark Rustad case ixgbe_fc_full: 2320afdc71e4SMark Rustad pause = true; 2321afdc71e4SMark Rustad asm_dir = true; 2322afdc71e4SMark Rustad break; 2323afdc71e4SMark Rustad default: 2324afdc71e4SMark Rustad hw_err(hw, "Flow control param set incorrectly\n"); 2325afdc71e4SMark Rustad return IXGBE_ERR_CONFIG; 2326afdc71e4SMark Rustad } 2327afdc71e4SMark Rustad 2328f572b2c4SMark Rustad if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR && 2329f572b2c4SMark Rustad hw->device_id != IXGBE_DEV_ID_X550EM_A_KR && 2330f572b2c4SMark Rustad hw->device_id != IXGBE_DEV_ID_X550EM_A_KR_L) 2331afdc71e4SMark Rustad return 0; 2332afdc71e4SMark Rustad 23339a5c27e6SMark Rustad rc = hw->mac.ops.read_iosf_sb_reg(hw, 2334afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 23359a5c27e6SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 23369a5c27e6SMark Rustad ®_val); 2337afdc71e4SMark Rustad if (rc) 2338afdc71e4SMark Rustad return rc; 2339afdc71e4SMark Rustad 2340afdc71e4SMark Rustad reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 2341afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 2342afdc71e4SMark Rustad if (pause) 2343afdc71e4SMark Rustad reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 2344afdc71e4SMark Rustad if (asm_dir) 2345afdc71e4SMark Rustad reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 23469a5c27e6SMark Rustad rc = hw->mac.ops.write_iosf_sb_reg(hw, 2347afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 23489a5c27e6SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 23499a5c27e6SMark Rustad reg_val); 2350afdc71e4SMark Rustad 2351afdc71e4SMark Rustad /* This device does not fully support AN. */ 2352afdc71e4SMark Rustad hw->fc.disable_fc_autoneg = true; 2353afdc71e4SMark Rustad 2354afdc71e4SMark Rustad return rc; 2355afdc71e4SMark Rustad } 2356afdc71e4SMark Rustad 23572916500dSDon Skidmore /** 23582916500dSDon Skidmore * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 23592916500dSDon Skidmore * @hw: pointer to hardware structure 23602916500dSDon Skidmore **/ 23612916500dSDon Skidmore static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) 23622916500dSDon Skidmore { 23632916500dSDon Skidmore u32 link_s1, lp_an_page_low, an_cntl_1; 23642916500dSDon Skidmore s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; 23652916500dSDon Skidmore ixgbe_link_speed speed; 23662916500dSDon Skidmore bool link_up; 23672916500dSDon Skidmore 23682916500dSDon Skidmore /* AN should have completed when the cable was plugged in. 23692916500dSDon Skidmore * Look for reasons to bail out. Bail out if: 23702916500dSDon Skidmore * - FC autoneg is disabled, or if 23712916500dSDon Skidmore * - link is not up. 23722916500dSDon Skidmore */ 23732916500dSDon Skidmore if (hw->fc.disable_fc_autoneg) { 23742916500dSDon Skidmore hw_err(hw, "Flow control autoneg is disabled"); 23752916500dSDon Skidmore goto out; 23762916500dSDon Skidmore } 23772916500dSDon Skidmore 23782916500dSDon Skidmore hw->mac.ops.check_link(hw, &speed, &link_up, false); 23792916500dSDon Skidmore if (!link_up) { 23802916500dSDon Skidmore hw_err(hw, "The link is down"); 23812916500dSDon Skidmore goto out; 23822916500dSDon Skidmore } 23832916500dSDon Skidmore 23842916500dSDon Skidmore /* Check at auto-negotiation has completed */ 23852916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 23862916500dSDon Skidmore IXGBE_KRM_LINK_S1(hw->bus.lan_id), 23872916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); 23882916500dSDon Skidmore 23892916500dSDon Skidmore if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { 23902916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 23912916500dSDon Skidmore status = IXGBE_ERR_FC_NOT_NEGOTIATED; 23922916500dSDon Skidmore goto out; 23932916500dSDon Skidmore } 23942916500dSDon Skidmore 23952916500dSDon Skidmore /* Read the 10g AN autoc and LP ability registers and resolve 23962916500dSDon Skidmore * local flow control settings accordingly 23972916500dSDon Skidmore */ 23982916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 23992916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 24002916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1); 24012916500dSDon Skidmore 24022916500dSDon Skidmore if (status) { 24032916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 24042916500dSDon Skidmore goto out; 24052916500dSDon Skidmore } 24062916500dSDon Skidmore 24072916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 24082916500dSDon Skidmore IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id), 24092916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low); 24102916500dSDon Skidmore 24112916500dSDon Skidmore if (status) { 24122916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 24132916500dSDon Skidmore goto out; 24142916500dSDon Skidmore } 24152916500dSDon Skidmore 24162916500dSDon Skidmore status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low, 24172916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_SYM_PAUSE, 24182916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_ASM_PAUSE, 24192916500dSDon Skidmore IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE, 24202916500dSDon Skidmore IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE); 24212916500dSDon Skidmore 24222916500dSDon Skidmore out: 24232916500dSDon Skidmore if (!status) { 24242916500dSDon Skidmore hw->fc.fc_was_autonegged = true; 24252916500dSDon Skidmore } else { 24262916500dSDon Skidmore hw->fc.fc_was_autonegged = false; 24272916500dSDon Skidmore hw->fc.current_mode = hw->fc.requested_mode; 24282916500dSDon Skidmore } 24292916500dSDon Skidmore } 24302916500dSDon Skidmore 24312916500dSDon Skidmore /** 24322916500dSDon Skidmore * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings 24332916500dSDon Skidmore * @hw: pointer to hardware structure 24342916500dSDon Skidmore **/ 24352916500dSDon Skidmore static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) 24362916500dSDon Skidmore { 24372916500dSDon Skidmore hw->fc.fc_was_autonegged = false; 24382916500dSDon Skidmore hw->fc.current_mode = hw->fc.requested_mode; 24392916500dSDon Skidmore } 24402916500dSDon Skidmore 24416ac74394SDon Skidmore /** ixgbe_enter_lplu_x550em - Transition to low power states 24426ac74394SDon Skidmore * @hw: pointer to hardware structure 24436ac74394SDon Skidmore * 24446ac74394SDon Skidmore * Configures Low Power Link Up on transition to low power states 24456ac74394SDon Skidmore * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting 24466ac74394SDon Skidmore * the X557 PHY immediately prior to entering LPLU. 24476ac74394SDon Skidmore **/ 24486ac74394SDon Skidmore static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) 24496ac74394SDon Skidmore { 24506ac74394SDon Skidmore u16 an_10g_cntl_reg, autoneg_reg, speed; 24516ac74394SDon Skidmore s32 status; 24526ac74394SDon Skidmore ixgbe_link_speed lcd_speed; 24536ac74394SDon Skidmore u32 save_autoneg; 24546ac74394SDon Skidmore bool link_up; 24556ac74394SDon Skidmore 24566ac74394SDon Skidmore /* If blocked by MNG FW, then don't restart AN */ 24576ac74394SDon Skidmore if (ixgbe_check_reset_blocked(hw)) 24586ac74394SDon Skidmore return 0; 24596ac74394SDon Skidmore 24606ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 24616ac74394SDon Skidmore if (status) 24626ac74394SDon Skidmore return status; 24636ac74394SDon Skidmore 24646ac74394SDon Skidmore status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, 24656ac74394SDon Skidmore &hw->eeprom.ctrl_word_3); 24666ac74394SDon Skidmore if (status) 24676ac74394SDon Skidmore return status; 24686ac74394SDon Skidmore 24696ac74394SDon Skidmore /* If link is down, LPLU disabled in NVM, WoL disabled, or 24706ac74394SDon Skidmore * manageability disabled, then force link down by entering 24716ac74394SDon Skidmore * low power mode. 24726ac74394SDon Skidmore */ 24736ac74394SDon Skidmore if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || 24746ac74394SDon Skidmore !(hw->wol_enabled || ixgbe_mng_present(hw))) 24756ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 24766ac74394SDon Skidmore 24776ac74394SDon Skidmore /* Determine LCD */ 24786ac74394SDon Skidmore status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); 24796ac74394SDon Skidmore if (status) 24806ac74394SDon Skidmore return status; 24816ac74394SDon Skidmore 24826ac74394SDon Skidmore /* If no valid LCD link speed, then force link down and exit. */ 24836ac74394SDon Skidmore if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) 24846ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 24856ac74394SDon Skidmore 24866ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 24874dc4000bSEmil Tantilov MDIO_MMD_AN, 24886ac74394SDon Skidmore &speed); 24896ac74394SDon Skidmore if (status) 24906ac74394SDon Skidmore return status; 24916ac74394SDon Skidmore 24926ac74394SDon Skidmore /* If no link now, speed is invalid so take link down */ 24936ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 24946ac74394SDon Skidmore if (status) 24956ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 24966ac74394SDon Skidmore 24976ac74394SDon Skidmore /* clear everything but the speed bits */ 24986ac74394SDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; 24996ac74394SDon Skidmore 25006ac74394SDon Skidmore /* If current speed is already LCD, then exit. */ 25016ac74394SDon Skidmore if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && 25026ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || 25036ac74394SDon Skidmore ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && 25046ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) 25056ac74394SDon Skidmore return status; 25066ac74394SDon Skidmore 25076ac74394SDon Skidmore /* Clear AN completed indication */ 25086ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, 25094dc4000bSEmil Tantilov MDIO_MMD_AN, 25106ac74394SDon Skidmore &autoneg_reg); 25116ac74394SDon Skidmore if (status) 25126ac74394SDon Skidmore return status; 25136ac74394SDon Skidmore 25144dc4000bSEmil Tantilov status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, 25154dc4000bSEmil Tantilov MDIO_MMD_AN, 25166ac74394SDon Skidmore &an_10g_cntl_reg); 25176ac74394SDon Skidmore if (status) 25186ac74394SDon Skidmore return status; 25196ac74394SDon Skidmore 25206ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, 25216ac74394SDon Skidmore IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, 25224dc4000bSEmil Tantilov MDIO_MMD_AN, 25236ac74394SDon Skidmore &autoneg_reg); 25246ac74394SDon Skidmore if (status) 25256ac74394SDon Skidmore return status; 25266ac74394SDon Skidmore 25276ac74394SDon Skidmore save_autoneg = hw->phy.autoneg_advertised; 25286ac74394SDon Skidmore 25296ac74394SDon Skidmore /* Setup link at least common link speed */ 25306ac74394SDon Skidmore status = hw->mac.ops.setup_link(hw, lcd_speed, false); 25316ac74394SDon Skidmore 25326ac74394SDon Skidmore /* restore autoneg from before setting lplu speed */ 25336ac74394SDon Skidmore hw->phy.autoneg_advertised = save_autoneg; 25346ac74394SDon Skidmore 25356ac74394SDon Skidmore return status; 25366ac74394SDon Skidmore } 25376ac74394SDon Skidmore 2538537cc5dfSMark Rustad /** 2539537cc5dfSMark Rustad * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register 2540537cc5dfSMark Rustad * @hw: pointer to hardware structure 2541537cc5dfSMark Rustad * 2542537cc5dfSMark Rustad * Read NW_MNG_IF_SEL register and save field values. 2543537cc5dfSMark Rustad */ 2544537cc5dfSMark Rustad static void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) 2545537cc5dfSMark Rustad { 2546537cc5dfSMark Rustad /* Save NW management interface connected on board. This is used 2547537cc5dfSMark Rustad * to determine internal PHY mode. 2548537cc5dfSMark Rustad */ 2549537cc5dfSMark Rustad hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 2550537cc5dfSMark Rustad 2551537cc5dfSMark Rustad /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set 2552537cc5dfSMark Rustad * PHY address. This register field was has only been used for X552. 2553537cc5dfSMark Rustad */ 2554ae3cb8cbSMark Rustad if (hw->mac.type == ixgbe_mac_x550em_a && 2555ae3cb8cbSMark Rustad hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) { 2556537cc5dfSMark Rustad hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel & 2557537cc5dfSMark Rustad IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> 2558537cc5dfSMark Rustad IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; 2559537cc5dfSMark Rustad } 2560ae3cb8cbSMark Rustad } 2561537cc5dfSMark Rustad 25626a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 25636a14ee0cSDon Skidmore * @hw: pointer to hardware structure 25646a14ee0cSDon Skidmore * 25656a14ee0cSDon Skidmore * Initialize any function pointers that were not able to be 25666a14ee0cSDon Skidmore * set during init_shared_code because the PHY/SFP type was 25676a14ee0cSDon Skidmore * not known. Perform the SFP init if necessary. 25686a14ee0cSDon Skidmore **/ 25697ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 25706a14ee0cSDon Skidmore { 25716a14ee0cSDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 25726a14ee0cSDon Skidmore s32 ret_val; 25736a14ee0cSDon Skidmore 25747e49d616SDon Skidmore hw->mac.ops.set_lan_id(hw); 25757e49d616SDon Skidmore 2576537cc5dfSMark Rustad ixgbe_read_mng_if_sel_x550em(hw); 2577537cc5dfSMark Rustad 2578c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 25796a14ee0cSDon Skidmore phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 2580ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 25816a14ee0cSDon Skidmore } 25826a14ee0cSDon Skidmore 25836a14ee0cSDon Skidmore /* Identify the PHY or SFP module */ 25846a14ee0cSDon Skidmore ret_val = phy->ops.identify(hw); 25856a14ee0cSDon Skidmore 2586c3dc4c09SDon Skidmore /* Setup function pointers based on detected hardware */ 25876a14ee0cSDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 25886a14ee0cSDon Skidmore if (phy->sfp_type != ixgbe_sfp_type_unknown) 25896a14ee0cSDon Skidmore phy->ops.reset = NULL; 25906a14ee0cSDon Skidmore 25916a14ee0cSDon Skidmore /* Set functions pointers based on phy type */ 25926a14ee0cSDon Skidmore switch (hw->phy.type) { 25936a14ee0cSDon Skidmore case ixgbe_phy_x550em_kx4: 25946a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kx4_x550em; 25956a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 25966a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 25976a14ee0cSDon Skidmore break; 25986a14ee0cSDon Skidmore case ixgbe_phy_x550em_kr: 25996a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kr_x550em; 26006a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 26016a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 26026a14ee0cSDon Skidmore break; 26036a14ee0cSDon Skidmore case ixgbe_phy_x550em_ext_t: 2604c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 2605c3dc4c09SDon Skidmore * to determine internal PHY mode 2606c3dc4c09SDon Skidmore */ 2607c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 2608c3dc4c09SDon Skidmore 2609c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup iXFI internal link, 2610c3dc4c09SDon Skidmore * else setup KR now. 2611c3dc4c09SDon Skidmore */ 2612c3dc4c09SDon Skidmore phy->ops.setup_internal_link = 2613c3dc4c09SDon Skidmore ixgbe_setup_internal_phy_t_x550em; 2614c3dc4c09SDon Skidmore 26156ac74394SDon Skidmore /* setup SW LPLU only for first revision */ 26163ca2b250SMark Rustad if (hw->mac.type == ixgbe_mac_X550EM_x && 26173ca2b250SMark Rustad !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) & 26183ca2b250SMark Rustad IXGBE_FUSES0_REV_MASK)) 26196ac74394SDon Skidmore phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; 26206ac74394SDon Skidmore 2621c3dc4c09SDon Skidmore phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 2622f4410d2cSDon Skidmore phy->ops.reset = ixgbe_reset_phy_t_X550em; 26236a14ee0cSDon Skidmore break; 26246a14ee0cSDon Skidmore default: 26256a14ee0cSDon Skidmore break; 26266a14ee0cSDon Skidmore } 2627c3dc4c09SDon Skidmore 26286a14ee0cSDon Skidmore return ret_val; 26296a14ee0cSDon Skidmore } 26306a14ee0cSDon Skidmore 26316a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type 26326a14ee0cSDon Skidmore * @hw: pointer to hardware structure 26336a14ee0cSDon Skidmore * 26346a14ee0cSDon Skidmore * Returns the media type (fiber, copper, backplane) 26356a14ee0cSDon Skidmore * 26366a14ee0cSDon Skidmore */ 26377ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 26386a14ee0cSDon Skidmore { 26396a14ee0cSDon Skidmore enum ixgbe_media_type media_type; 26406a14ee0cSDon Skidmore 26416a14ee0cSDon Skidmore /* Detect if there is a copper PHY attached. */ 26426a14ee0cSDon Skidmore switch (hw->device_id) { 2643200157c2SMark Rustad case IXGBE_DEV_ID_X550EM_A_SGMII: 2644200157c2SMark Rustad case IXGBE_DEV_ID_X550EM_A_SGMII_L: 2645200157c2SMark Rustad hw->phy.type = ixgbe_phy_sgmii; 2646200157c2SMark Rustad /* Fallthrough */ 26476a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 26486a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 2649f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR: 2650f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR_L: 26516a14ee0cSDon Skidmore media_type = ixgbe_media_type_backplane; 26526a14ee0cSDon Skidmore break; 26536a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 26542d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 265549425dfcSMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 26566a14ee0cSDon Skidmore media_type = ixgbe_media_type_fiber; 26576a14ee0cSDon Skidmore break; 26586a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 26596a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 266092ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 26616a14ee0cSDon Skidmore media_type = ixgbe_media_type_copper; 26626a14ee0cSDon Skidmore break; 26636a14ee0cSDon Skidmore default: 26646a14ee0cSDon Skidmore media_type = ixgbe_media_type_unknown; 26656a14ee0cSDon Skidmore break; 26666a14ee0cSDon Skidmore } 26676a14ee0cSDon Skidmore return media_type; 26686a14ee0cSDon Skidmore } 26696a14ee0cSDon Skidmore 26706a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 26716a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 26726a14ee0cSDon Skidmore **/ 26737ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 26746a14ee0cSDon Skidmore { 2675a1e869deSMark Rustad s32 status; 26766a14ee0cSDon Skidmore u16 reg; 26776a14ee0cSDon Skidmore 26786a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 26796a14ee0cSDon Skidmore IXGBE_MDIO_TX_VENDOR_ALARMS_3, 26804dc4000bSEmil Tantilov MDIO_MMD_PMAPMD, 26816a14ee0cSDon Skidmore ®); 26826a14ee0cSDon Skidmore if (status) 26836a14ee0cSDon Skidmore return status; 26846a14ee0cSDon Skidmore 2685e2261bccSDon Skidmore /* If PHY FW reset completed bit is set then this is the first 2686e2261bccSDon Skidmore * SW instance after a power on so the PHY FW must be un-stalled. 2687e2261bccSDon Skidmore */ 2688e2261bccSDon Skidmore if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 26896a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 26906a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 26914dc4000bSEmil Tantilov MDIO_MMD_VEND1, 26926a14ee0cSDon Skidmore ®); 26936a14ee0cSDon Skidmore if (status) 26946a14ee0cSDon Skidmore return status; 26956a14ee0cSDon Skidmore 26966a14ee0cSDon Skidmore reg &= ~IXGBE_MDIO_POWER_UP_STALL; 26976a14ee0cSDon Skidmore 26986a14ee0cSDon Skidmore status = hw->phy.ops.write_reg(hw, 26996a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 27004dc4000bSEmil Tantilov MDIO_MMD_VEND1, 27016a14ee0cSDon Skidmore reg); 2702e2261bccSDon Skidmore if (status) 2703e2261bccSDon Skidmore return status; 2704e2261bccSDon Skidmore } 2705e2261bccSDon Skidmore 27066a14ee0cSDon Skidmore return status; 27076a14ee0cSDon Skidmore } 27086a14ee0cSDon Skidmore 2709e84db727SMark Rustad /** 2710e84db727SMark Rustad * ixgbe_set_mdio_speed - Set MDIO clock speed 2711e84db727SMark Rustad * @hw: pointer to hardware structure 2712e84db727SMark Rustad */ 2713e84db727SMark Rustad static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) 2714e84db727SMark Rustad { 2715e84db727SMark Rustad u32 hlreg0; 2716e84db727SMark Rustad 2717e84db727SMark Rustad switch (hw->device_id) { 2718e84db727SMark Rustad case IXGBE_DEV_ID_X550EM_X_10G_T: 2719a83c27e7SDon Skidmore case IXGBE_DEV_ID_X550EM_A_SGMII: 2720a83c27e7SDon Skidmore case IXGBE_DEV_ID_X550EM_A_SGMII_L: 272192ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 27222d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 2723e84db727SMark Rustad /* Config MDIO clock speed before the first MDIO PHY access */ 2724e84db727SMark Rustad hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 2725e84db727SMark Rustad hlreg0 &= ~IXGBE_HLREG0_MDCSPD; 2726e84db727SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 2727e84db727SMark Rustad break; 2728e84db727SMark Rustad default: 2729e84db727SMark Rustad break; 2730e84db727SMark Rustad } 2731e84db727SMark Rustad } 2732e84db727SMark Rustad 27336a14ee0cSDon Skidmore /** ixgbe_reset_hw_X550em - Perform hardware reset 27346a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 27356a14ee0cSDon Skidmore ** 27366a14ee0cSDon Skidmore ** Resets the hardware by resetting the transmit and receive units, masks 27376a14ee0cSDon Skidmore ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 27386a14ee0cSDon Skidmore ** reset. 27396a14ee0cSDon Skidmore **/ 27407ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 27416a14ee0cSDon Skidmore { 27426a14ee0cSDon Skidmore ixgbe_link_speed link_speed; 27436a14ee0cSDon Skidmore s32 status; 27446a14ee0cSDon Skidmore u32 ctrl = 0; 27456a14ee0cSDon Skidmore u32 i; 27466a14ee0cSDon Skidmore bool link_up = false; 27476a14ee0cSDon Skidmore 27486a14ee0cSDon Skidmore /* Call adapter stop to disable Tx/Rx and clear interrupts */ 27496a14ee0cSDon Skidmore status = hw->mac.ops.stop_adapter(hw); 27506a14ee0cSDon Skidmore if (status) 27516a14ee0cSDon Skidmore return status; 27526a14ee0cSDon Skidmore 27536a14ee0cSDon Skidmore /* flush pending Tx transactions */ 27546a14ee0cSDon Skidmore ixgbe_clear_tx_pending(hw); 27556a14ee0cSDon Skidmore 27566a14ee0cSDon Skidmore /* PHY ops must be identified and initialized prior to reset */ 27576a14ee0cSDon Skidmore 27586a14ee0cSDon Skidmore /* Identify PHY and related function pointers */ 27596a14ee0cSDon Skidmore status = hw->phy.ops.init(hw); 27606a14ee0cSDon Skidmore 27616a14ee0cSDon Skidmore /* start the external PHY */ 27626a14ee0cSDon Skidmore if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 27636a14ee0cSDon Skidmore status = ixgbe_init_ext_t_x550em(hw); 27646a14ee0cSDon Skidmore if (status) 27656a14ee0cSDon Skidmore return status; 27666a14ee0cSDon Skidmore } 27676a14ee0cSDon Skidmore 27686a14ee0cSDon Skidmore /* Setup SFP module if there is one present. */ 27696a14ee0cSDon Skidmore if (hw->phy.sfp_setup_needed) { 27706a14ee0cSDon Skidmore status = hw->mac.ops.setup_sfp(hw); 27716a14ee0cSDon Skidmore hw->phy.sfp_setup_needed = false; 27726a14ee0cSDon Skidmore } 27736a14ee0cSDon Skidmore 27746a14ee0cSDon Skidmore /* Reset PHY */ 27756a14ee0cSDon Skidmore if (!hw->phy.reset_disable && hw->phy.ops.reset) 27766a14ee0cSDon Skidmore hw->phy.ops.reset(hw); 27776a14ee0cSDon Skidmore 27786a14ee0cSDon Skidmore mac_reset_top: 27796a14ee0cSDon Skidmore /* Issue global reset to the MAC. Needs to be SW reset if link is up. 27806a14ee0cSDon Skidmore * If link reset is used when link is up, it might reset the PHY when 27816a14ee0cSDon Skidmore * mng is using it. If link is down or the flag to force full link 27826a14ee0cSDon Skidmore * reset is set, then perform link reset. 27836a14ee0cSDon Skidmore */ 27846a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_LNK_RST; 27856a14ee0cSDon Skidmore 27866a14ee0cSDon Skidmore if (!hw->force_full_reset) { 27876a14ee0cSDon Skidmore hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 27886a14ee0cSDon Skidmore if (link_up) 27896a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_RST; 27906a14ee0cSDon Skidmore } 27916a14ee0cSDon Skidmore 27926a14ee0cSDon Skidmore ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 27936a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 27946a14ee0cSDon Skidmore IXGBE_WRITE_FLUSH(hw); 2795efff2e02SMark Rustad usleep_range(1000, 1200); 27966a14ee0cSDon Skidmore 27976a14ee0cSDon Skidmore /* Poll for reset bit to self-clear meaning reset is complete */ 27986a14ee0cSDon Skidmore for (i = 0; i < 10; i++) { 27996a14ee0cSDon Skidmore ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 28006a14ee0cSDon Skidmore if (!(ctrl & IXGBE_CTRL_RST_MASK)) 28016a14ee0cSDon Skidmore break; 2802efff2e02SMark Rustad udelay(1); 28036a14ee0cSDon Skidmore } 28046a14ee0cSDon Skidmore 28056a14ee0cSDon Skidmore if (ctrl & IXGBE_CTRL_RST_MASK) { 28066a14ee0cSDon Skidmore status = IXGBE_ERR_RESET_FAILED; 28076a14ee0cSDon Skidmore hw_dbg(hw, "Reset polling failed to complete.\n"); 28086a14ee0cSDon Skidmore } 28096a14ee0cSDon Skidmore 28106a14ee0cSDon Skidmore msleep(50); 28116a14ee0cSDon Skidmore 28126a14ee0cSDon Skidmore /* Double resets are required for recovery from certain error 28136a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 28146a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 28156a14ee0cSDon Skidmore */ 28166a14ee0cSDon Skidmore if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 28176a14ee0cSDon Skidmore hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 28186a14ee0cSDon Skidmore goto mac_reset_top; 28196a14ee0cSDon Skidmore } 28206a14ee0cSDon Skidmore 28216a14ee0cSDon Skidmore /* Store the permanent mac address */ 28226a14ee0cSDon Skidmore hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 28236a14ee0cSDon Skidmore 28246a14ee0cSDon Skidmore /* Store MAC address from RAR0, clear receive address registers, and 28256a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 28266a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 28276a14ee0cSDon Skidmore */ 28286a14ee0cSDon Skidmore hw->mac.num_rar_entries = 128; 28296a14ee0cSDon Skidmore hw->mac.ops.init_rx_addrs(hw); 28306a14ee0cSDon Skidmore 2831e84db727SMark Rustad ixgbe_set_mdio_speed(hw); 2832deda562aSDon Skidmore 2833ab5fe0c5SDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 2834ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 2835ab5fe0c5SDon Skidmore 28366a14ee0cSDon Skidmore return status; 28376a14ee0cSDon Skidmore } 28386a14ee0cSDon Skidmore 28395b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 28405b7f000fSDon Skidmore * anti-spoofing 28415b7f000fSDon Skidmore * @hw: pointer to hardware structure 28425b7f000fSDon Skidmore * @enable: enable or disable switch for Ethertype anti-spoofing 28435b7f000fSDon Skidmore * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 28445b7f000fSDon Skidmore **/ 2845bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 2846bc035fc5SDon Skidmore bool enable, int vf) 28475b7f000fSDon Skidmore { 28485b7f000fSDon Skidmore int vf_target_reg = vf >> 3; 28495b7f000fSDon Skidmore int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 28505b7f000fSDon Skidmore u32 pfvfspoof; 28515b7f000fSDon Skidmore 28525b7f000fSDon Skidmore pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 28535b7f000fSDon Skidmore if (enable) 2854b4f47a48SJacob Keller pfvfspoof |= BIT(vf_target_shift); 28555b7f000fSDon Skidmore else 2856b4f47a48SJacob Keller pfvfspoof &= ~BIT(vf_target_shift); 28575b7f000fSDon Skidmore 28585b7f000fSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 28595b7f000fSDon Skidmore } 28605b7f000fSDon Skidmore 28616d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 28626d4c96adSDon Skidmore * @hw: pointer to hardware structure 28636d4c96adSDon Skidmore * @enable: enable or disable source address pruning 28646d4c96adSDon Skidmore * @pool: Rx pool to set source address pruning for 28656d4c96adSDon Skidmore **/ 28666d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 28676d4c96adSDon Skidmore bool enable, 28686d4c96adSDon Skidmore unsigned int pool) 28696d4c96adSDon Skidmore { 28706d4c96adSDon Skidmore u64 pfflp; 28716d4c96adSDon Skidmore 28726d4c96adSDon Skidmore /* max rx pool is 63 */ 28736d4c96adSDon Skidmore if (pool > 63) 28746d4c96adSDon Skidmore return; 28756d4c96adSDon Skidmore 28766d4c96adSDon Skidmore pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 28776d4c96adSDon Skidmore pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 28786d4c96adSDon Skidmore 28796d4c96adSDon Skidmore if (enable) 28806d4c96adSDon Skidmore pfflp |= (1ULL << pool); 28816d4c96adSDon Skidmore else 28826d4c96adSDon Skidmore pfflp &= ~(1ULL << pool); 28836d4c96adSDon Skidmore 28846d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 28856d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 28866d4c96adSDon Skidmore } 28876d4c96adSDon Skidmore 2888449e21a9SMark Rustad /** 28892916500dSDon Skidmore * ixgbe_setup_fc_backplane_x550em_a - Set up flow control 28902916500dSDon Skidmore * @hw: pointer to hardware structure 28912916500dSDon Skidmore * 28922916500dSDon Skidmore * Called at init time to set up flow control. 28932916500dSDon Skidmore **/ 28942916500dSDon Skidmore static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) 28952916500dSDon Skidmore { 28962916500dSDon Skidmore s32 status = 0; 28972916500dSDon Skidmore u32 link_ctrl = 0; 28982916500dSDon Skidmore u32 an_cntl = 0; 28992916500dSDon Skidmore 29002916500dSDon Skidmore /* Validate the requested mode */ 29012916500dSDon Skidmore if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 29022916500dSDon Skidmore hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 29032916500dSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 29042916500dSDon Skidmore } 29052916500dSDon Skidmore 29062916500dSDon Skidmore if (hw->fc.requested_mode == ixgbe_fc_default) 29072916500dSDon Skidmore hw->fc.requested_mode = ixgbe_fc_full; 29082916500dSDon Skidmore 29092916500dSDon Skidmore /* Set up the 1G and 10G flow control advertisement registers so the 29102916500dSDon Skidmore * HW will be able to do FC autoneg once the cable is plugged in. If 29112916500dSDon Skidmore * we link at 10G, the 1G advertisement is harmless and vice versa. 29122916500dSDon Skidmore */ 29132916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 29142916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 29152916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl); 29162916500dSDon Skidmore 29172916500dSDon Skidmore if (status) { 29182916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 29192916500dSDon Skidmore return status; 29202916500dSDon Skidmore } 29212916500dSDon Skidmore 29222916500dSDon Skidmore /* The possible values of fc.requested_mode are: 29232916500dSDon Skidmore * 0: Flow control is completely disabled 29242916500dSDon Skidmore * 1: Rx flow control is enabled (we can receive pause frames, 29252916500dSDon Skidmore * but not send pause frames). 29262916500dSDon Skidmore * 2: Tx flow control is enabled (we can send pause frames but 29272916500dSDon Skidmore * we do not support receiving pause frames). 29282916500dSDon Skidmore * 3: Both Rx and Tx flow control (symmetric) are enabled. 29292916500dSDon Skidmore * other: Invalid. 29302916500dSDon Skidmore */ 29312916500dSDon Skidmore switch (hw->fc.requested_mode) { 29322916500dSDon Skidmore case ixgbe_fc_none: 29332916500dSDon Skidmore /* Flow control completely disabled by software override. */ 29342916500dSDon Skidmore an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 29352916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 29362916500dSDon Skidmore break; 29372916500dSDon Skidmore case ixgbe_fc_tx_pause: 29382916500dSDon Skidmore /* Tx Flow control is enabled, and Rx Flow control is 29392916500dSDon Skidmore * disabled by software override. 29402916500dSDon Skidmore */ 29412916500dSDon Skidmore an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 29422916500dSDon Skidmore an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 29432916500dSDon Skidmore break; 29442916500dSDon Skidmore case ixgbe_fc_rx_pause: 29452916500dSDon Skidmore /* Rx Flow control is enabled and Tx Flow control is 29462916500dSDon Skidmore * disabled by software override. Since there really 29472916500dSDon Skidmore * isn't a way to advertise that we are capable of RX 29482916500dSDon Skidmore * Pause ONLY, we will advertise that we support both 29492916500dSDon Skidmore * symmetric and asymmetric Rx PAUSE, as such we fall 29502916500dSDon Skidmore * through to the fc_full statement. Later, we will 29512916500dSDon Skidmore * disable the adapter's ability to send PAUSE frames. 29522916500dSDon Skidmore */ 29532916500dSDon Skidmore case ixgbe_fc_full: 29542916500dSDon Skidmore /* Flow control (both Rx and Tx) is enabled by SW override. */ 29552916500dSDon Skidmore an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 29562916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 29572916500dSDon Skidmore break; 29582916500dSDon Skidmore default: 29592916500dSDon Skidmore hw_err(hw, "Flow control param set incorrectly\n"); 29602916500dSDon Skidmore return IXGBE_ERR_CONFIG; 29612916500dSDon Skidmore } 29622916500dSDon Skidmore 29632916500dSDon Skidmore status = hw->mac.ops.write_iosf_sb_reg(hw, 29642916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 29652916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); 29662916500dSDon Skidmore 29672916500dSDon Skidmore /* Restart auto-negotiation. */ 29682916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 29692916500dSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 29702916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); 29712916500dSDon Skidmore if (status) { 29722916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 29732916500dSDon Skidmore return status; 29742916500dSDon Skidmore } 29752916500dSDon Skidmore 29762916500dSDon Skidmore link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 29772916500dSDon Skidmore status = hw->mac.ops.write_iosf_sb_reg(hw, 29782916500dSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 29792916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); 29802916500dSDon Skidmore 29812916500dSDon Skidmore return status; 29822916500dSDon Skidmore } 29832916500dSDon Skidmore 29842916500dSDon Skidmore /** 2985449e21a9SMark Rustad * ixgbe_set_mux - Set mux for port 1 access with CS4227 2986449e21a9SMark Rustad * @hw: pointer to hardware structure 2987449e21a9SMark Rustad * @state: set mux if 1, clear if 0 2988449e21a9SMark Rustad */ 2989449e21a9SMark Rustad static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) 2990449e21a9SMark Rustad { 2991449e21a9SMark Rustad u32 esdp; 2992449e21a9SMark Rustad 2993449e21a9SMark Rustad if (!hw->bus.lan_id) 2994449e21a9SMark Rustad return; 2995449e21a9SMark Rustad esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 2996449e21a9SMark Rustad if (state) 2997449e21a9SMark Rustad esdp |= IXGBE_ESDP_SDP1; 2998449e21a9SMark Rustad else 2999449e21a9SMark Rustad esdp &= ~IXGBE_ESDP_SDP1; 3000449e21a9SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 3001449e21a9SMark Rustad IXGBE_WRITE_FLUSH(hw); 3002449e21a9SMark Rustad } 3003449e21a9SMark Rustad 3004449e21a9SMark Rustad /** 3005449e21a9SMark Rustad * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore 3006449e21a9SMark Rustad * @hw: pointer to hardware structure 3007449e21a9SMark Rustad * @mask: Mask to specify which semaphore to acquire 3008449e21a9SMark Rustad * 3009449e21a9SMark Rustad * Acquires the SWFW semaphore and sets the I2C MUX 3010449e21a9SMark Rustad */ 3011449e21a9SMark Rustad static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 3012449e21a9SMark Rustad { 3013449e21a9SMark Rustad s32 status; 3014449e21a9SMark Rustad 3015449e21a9SMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, mask); 3016449e21a9SMark Rustad if (status) 3017449e21a9SMark Rustad return status; 3018449e21a9SMark Rustad 3019449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 3020449e21a9SMark Rustad ixgbe_set_mux(hw, 1); 3021449e21a9SMark Rustad 3022449e21a9SMark Rustad return 0; 3023449e21a9SMark Rustad } 3024449e21a9SMark Rustad 3025449e21a9SMark Rustad /** 3026449e21a9SMark Rustad * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore 3027449e21a9SMark Rustad * @hw: pointer to hardware structure 3028449e21a9SMark Rustad * @mask: Mask to specify which semaphore to release 3029449e21a9SMark Rustad * 3030449e21a9SMark Rustad * Releases the SWFW semaphore and sets the I2C MUX 3031449e21a9SMark Rustad */ 3032449e21a9SMark Rustad static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 3033449e21a9SMark Rustad { 3034449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 3035449e21a9SMark Rustad ixgbe_set_mux(hw, 0); 3036449e21a9SMark Rustad 3037449e21a9SMark Rustad ixgbe_release_swfw_sync_X540(hw, mask); 3038449e21a9SMark Rustad } 3039449e21a9SMark Rustad 304049425dfcSMark Rustad /** 304149425dfcSMark Rustad * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore 304249425dfcSMark Rustad * @hw: pointer to hardware structure 304349425dfcSMark Rustad * @mask: Mask to specify which semaphore to acquire 304449425dfcSMark Rustad * 304549425dfcSMark Rustad * Acquires the SWFW semaphore and get the shared PHY token as needed 304649425dfcSMark Rustad */ 304749425dfcSMark Rustad static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 304849425dfcSMark Rustad { 304949425dfcSMark Rustad u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 305049425dfcSMark Rustad int retries = FW_PHY_TOKEN_RETRIES; 305149425dfcSMark Rustad s32 status; 305249425dfcSMark Rustad 305349425dfcSMark Rustad while (--retries) { 305449425dfcSMark Rustad status = 0; 305549425dfcSMark Rustad if (hmask) 305649425dfcSMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, hmask); 305749425dfcSMark Rustad if (status) 305849425dfcSMark Rustad return status; 305949425dfcSMark Rustad if (!(mask & IXGBE_GSSR_TOKEN_SM)) 306049425dfcSMark Rustad return 0; 306149425dfcSMark Rustad 306249425dfcSMark Rustad status = ixgbe_get_phy_token(hw); 306349425dfcSMark Rustad if (!status) 306449425dfcSMark Rustad return 0; 306549425dfcSMark Rustad if (hmask) 306649425dfcSMark Rustad ixgbe_release_swfw_sync_X540(hw, hmask); 306749425dfcSMark Rustad if (status != IXGBE_ERR_TOKEN_RETRY) 306849425dfcSMark Rustad return status; 3069d4f90d9dSArnd Bergmann msleep(FW_PHY_TOKEN_DELAY); 307049425dfcSMark Rustad } 307149425dfcSMark Rustad 307249425dfcSMark Rustad return status; 307349425dfcSMark Rustad } 307449425dfcSMark Rustad 307549425dfcSMark Rustad /** 307649425dfcSMark Rustad * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore 307749425dfcSMark Rustad * @hw: pointer to hardware structure 307849425dfcSMark Rustad * @mask: Mask to specify which semaphore to release 307949425dfcSMark Rustad * 308049425dfcSMark Rustad * Release the SWFW semaphore and puts the shared PHY token as needed 308149425dfcSMark Rustad */ 308249425dfcSMark Rustad static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 308349425dfcSMark Rustad { 308449425dfcSMark Rustad u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 308549425dfcSMark Rustad 308649425dfcSMark Rustad if (mask & IXGBE_GSSR_TOKEN_SM) 308749425dfcSMark Rustad ixgbe_put_phy_token(hw); 308849425dfcSMark Rustad 308949425dfcSMark Rustad if (hmask) 309049425dfcSMark Rustad ixgbe_release_swfw_sync_X540(hw, hmask); 309149425dfcSMark Rustad } 309249425dfcSMark Rustad 3093d31afc8fSMark Rustad /** 3094d31afc8fSMark Rustad * ixgbe_read_phy_reg_x550a - Reads specified PHY register 3095d31afc8fSMark Rustad * @hw: pointer to hardware structure 3096d31afc8fSMark Rustad * @reg_addr: 32 bit address of PHY register to read 3097d31afc8fSMark Rustad * @phy_data: Pointer to read data from PHY register 3098d31afc8fSMark Rustad * 3099d31afc8fSMark Rustad * Reads a value from a specified PHY register using the SWFW lock and PHY 3100d31afc8fSMark Rustad * Token. The PHY Token is needed since the MDIO is shared between to MAC 3101d31afc8fSMark Rustad * instances. 3102d31afc8fSMark Rustad */ 3103d31afc8fSMark Rustad static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 3104d31afc8fSMark Rustad u32 device_type, u16 *phy_data) 3105d31afc8fSMark Rustad { 3106d31afc8fSMark Rustad u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 3107d31afc8fSMark Rustad s32 status; 3108d31afc8fSMark Rustad 3109d31afc8fSMark Rustad if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 3110d31afc8fSMark Rustad return IXGBE_ERR_SWFW_SYNC; 3111d31afc8fSMark Rustad 3112d31afc8fSMark Rustad status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); 3113d31afc8fSMark Rustad 3114d31afc8fSMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 3115d31afc8fSMark Rustad 3116d31afc8fSMark Rustad return status; 3117d31afc8fSMark Rustad } 3118d31afc8fSMark Rustad 3119d31afc8fSMark Rustad /** 3120d31afc8fSMark Rustad * ixgbe_write_phy_reg_x550a - Writes specified PHY register 3121d31afc8fSMark Rustad * @hw: pointer to hardware structure 3122d31afc8fSMark Rustad * @reg_addr: 32 bit PHY register to write 3123d31afc8fSMark Rustad * @device_type: 5 bit device type 3124d31afc8fSMark Rustad * @phy_data: Data to write to the PHY register 3125d31afc8fSMark Rustad * 3126d31afc8fSMark Rustad * Writes a value to specified PHY register using the SWFW lock and PHY Token. 3127d31afc8fSMark Rustad * The PHY Token is needed since the MDIO is shared between to MAC instances. 3128d31afc8fSMark Rustad */ 3129d31afc8fSMark Rustad static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 3130d31afc8fSMark Rustad u32 device_type, u16 phy_data) 3131d31afc8fSMark Rustad { 3132d31afc8fSMark Rustad u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 3133d31afc8fSMark Rustad s32 status; 3134d31afc8fSMark Rustad 3135d31afc8fSMark Rustad if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 3136d31afc8fSMark Rustad return IXGBE_ERR_SWFW_SYNC; 3137d31afc8fSMark Rustad 3138d31afc8fSMark Rustad status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data); 3139d31afc8fSMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 3140d31afc8fSMark Rustad 3141d31afc8fSMark Rustad return status; 3142d31afc8fSMark Rustad } 3143d31afc8fSMark Rustad 31446a14ee0cSDon Skidmore #define X550_COMMON_MAC \ 31456a14ee0cSDon Skidmore .init_hw = &ixgbe_init_hw_generic, \ 31466a14ee0cSDon Skidmore .start_hw = &ixgbe_start_hw_X540, \ 31476a14ee0cSDon Skidmore .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 31486a14ee0cSDon Skidmore .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 31496a14ee0cSDon Skidmore .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 31506a14ee0cSDon Skidmore .get_device_caps = &ixgbe_get_device_caps_generic, \ 31516a14ee0cSDon Skidmore .stop_adapter = &ixgbe_stop_adapter_generic, \ 31526a14ee0cSDon Skidmore .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 31536a14ee0cSDon Skidmore .read_analog_reg8 = NULL, \ 31546a14ee0cSDon Skidmore .write_analog_reg8 = NULL, \ 31556a14ee0cSDon Skidmore .set_rxpba = &ixgbe_set_rxpba_generic, \ 31566a14ee0cSDon Skidmore .check_link = &ixgbe_check_mac_link_generic, \ 31576a14ee0cSDon Skidmore .blink_led_start = &ixgbe_blink_led_start_X540, \ 31586a14ee0cSDon Skidmore .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 31596a14ee0cSDon Skidmore .set_rar = &ixgbe_set_rar_generic, \ 31606a14ee0cSDon Skidmore .clear_rar = &ixgbe_clear_rar_generic, \ 31616a14ee0cSDon Skidmore .set_vmdq = &ixgbe_set_vmdq_generic, \ 31626a14ee0cSDon Skidmore .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 31636a14ee0cSDon Skidmore .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 31646a14ee0cSDon Skidmore .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 31656a14ee0cSDon Skidmore .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 31666a14ee0cSDon Skidmore .enable_mc = &ixgbe_enable_mc_generic, \ 31676a14ee0cSDon Skidmore .disable_mc = &ixgbe_disable_mc_generic, \ 31686a14ee0cSDon Skidmore .clear_vfta = &ixgbe_clear_vfta_generic, \ 31696a14ee0cSDon Skidmore .set_vfta = &ixgbe_set_vfta_generic, \ 31706a14ee0cSDon Skidmore .fc_enable = &ixgbe_fc_enable_generic, \ 31716a14ee0cSDon Skidmore .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, \ 31726a14ee0cSDon Skidmore .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 31736a14ee0cSDon Skidmore .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 31746a14ee0cSDon Skidmore .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 31756d4c96adSDon Skidmore .set_source_address_pruning = \ 31766d4c96adSDon Skidmore &ixgbe_set_source_address_pruning_X550, \ 31775b7f000fSDon Skidmore .set_ethertype_anti_spoofing = \ 31785b7f000fSDon Skidmore &ixgbe_set_ethertype_anti_spoofing_X550, \ 31796a14ee0cSDon Skidmore .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 31806a14ee0cSDon Skidmore .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 31816a14ee0cSDon Skidmore .get_thermal_sensor_data = NULL, \ 31826a14ee0cSDon Skidmore .init_thermal_sensor_thresh = NULL, \ 31831f9ac57cSDon Skidmore .enable_rx = &ixgbe_enable_rx_generic, \ 31841f9ac57cSDon Skidmore .disable_rx = &ixgbe_disable_rx_x550, \ 31856a14ee0cSDon Skidmore 318637689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550 = { 31876a14ee0cSDon Skidmore X550_COMMON_MAC 3188a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_generic, 3189a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_generic, 3190805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 31916a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X540, 31926a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X540, 31936a14ee0cSDon Skidmore .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 31946a14ee0cSDon Skidmore .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 31956a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_mac_link_X540, 31966a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 3197454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_generic, 31986a14ee0cSDon Skidmore .setup_sfp = NULL, 3199449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, 3200449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X540, 3201dbd15b8fSDon Skidmore .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 3202afdc71e4SMark Rustad .prot_autoc_read = prot_autoc_read_generic, 3203afdc71e4SMark Rustad .prot_autoc_write = prot_autoc_write_generic, 3204afdc71e4SMark Rustad .setup_fc = ixgbe_setup_fc_generic, 32052916500dSDon Skidmore .fc_autoneg = ixgbe_fc_autoneg, 32066a14ee0cSDon Skidmore }; 32076a14ee0cSDon Skidmore 320837689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550EM_x = { 32096a14ee0cSDon Skidmore X550_COMMON_MAC 3210a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_t_x550em, 3211a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_t_x550em, 3212805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 32136a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X550em, 32146a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X550em, 32156a14ee0cSDon Skidmore .get_san_mac_addr = NULL, 32166a14ee0cSDon Skidmore .get_wwn_prefix = NULL, 32174695886cSEmil Tantilov .setup_link = &ixgbe_setup_mac_link_X540, 32186a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 3219454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_X550em, 32206a14ee0cSDon Skidmore .setup_sfp = ixgbe_setup_sfp_modules_X550em, 3221449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 3222449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 3223dbd15b8fSDon Skidmore .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 3224afdc71e4SMark Rustad .setup_fc = NULL, /* defined later */ 32252916500dSDon Skidmore .fc_autoneg = ixgbe_fc_autoneg, 32269a5c27e6SMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, 32279a5c27e6SMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, 32286a14ee0cSDon Skidmore }; 32296a14ee0cSDon Skidmore 323049425dfcSMark Rustad static struct ixgbe_mac_operations mac_ops_x550em_a = { 323149425dfcSMark Rustad X550_COMMON_MAC 3232a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_t_x550em, 3233a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_t_x550em, 3234805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 323549425dfcSMark Rustad .reset_hw = ixgbe_reset_hw_X550em, 323649425dfcSMark Rustad .get_media_type = ixgbe_get_media_type_X550em, 323749425dfcSMark Rustad .get_san_mac_addr = NULL, 323849425dfcSMark Rustad .get_wwn_prefix = NULL, 3239a0254a70SMark Rustad .setup_link = NULL, /* defined later */ 324049425dfcSMark Rustad .get_link_capabilities = ixgbe_get_link_capabilities_X550em, 324149425dfcSMark Rustad .get_bus_info = ixgbe_get_bus_info_X550em, 324249425dfcSMark Rustad .setup_sfp = ixgbe_setup_sfp_modules_X550em, 324349425dfcSMark Rustad .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, 324449425dfcSMark Rustad .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, 3245a0254a70SMark Rustad .setup_fc = ixgbe_setup_fc_x550em, 32462916500dSDon Skidmore .fc_autoneg = NULL, /* defined later */ 324749425dfcSMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, 324849425dfcSMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, 324949425dfcSMark Rustad }; 325049425dfcSMark Rustad 32516a14ee0cSDon Skidmore #define X550_COMMON_EEP \ 32526a14ee0cSDon Skidmore .read = &ixgbe_read_ee_hostif_X550, \ 32536a14ee0cSDon Skidmore .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 32546a14ee0cSDon Skidmore .write = &ixgbe_write_ee_hostif_X550, \ 32556a14ee0cSDon Skidmore .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 32566a14ee0cSDon Skidmore .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 32576a14ee0cSDon Skidmore .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 32586a14ee0cSDon Skidmore .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 32596a14ee0cSDon Skidmore 326037689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550 = { 32616a14ee0cSDon Skidmore X550_COMMON_EEP 32626a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X550, 32636a14ee0cSDon Skidmore }; 32646a14ee0cSDon Skidmore 326537689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 32666a14ee0cSDon Skidmore X550_COMMON_EEP 32676a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X540, 32686a14ee0cSDon Skidmore }; 32696a14ee0cSDon Skidmore 32706a14ee0cSDon Skidmore #define X550_COMMON_PHY \ 32716a14ee0cSDon Skidmore .identify_sfp = &ixgbe_identify_module_generic, \ 32726a14ee0cSDon Skidmore .reset = NULL, \ 32736a14ee0cSDon Skidmore .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 32746a14ee0cSDon Skidmore .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 32756a14ee0cSDon Skidmore .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 32766a14ee0cSDon Skidmore .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 32776a14ee0cSDon Skidmore .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 32786a14ee0cSDon Skidmore .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 3279bef23de1SDon Skidmore .setup_link = &ixgbe_setup_phy_link_generic, \ 3280b5529ef5SDon Skidmore .set_phy_power = NULL, \ 32816a14ee0cSDon Skidmore .check_overtemp = &ixgbe_tn_check_overtemp, \ 32826a14ee0cSDon Skidmore .get_firmware_version = &ixgbe_get_phy_firmware_version_generic, 32836a14ee0cSDon Skidmore 328437689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550 = { 32856a14ee0cSDon Skidmore X550_COMMON_PHY 32866a14ee0cSDon Skidmore .init = NULL, 32876a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_generic, 3288d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_generic, 3289d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_generic, 32906a14ee0cSDon Skidmore }; 32916a14ee0cSDon Skidmore 329237689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550EM_x = { 32936a14ee0cSDon Skidmore X550_COMMON_PHY 32946a14ee0cSDon Skidmore .init = &ixgbe_init_phy_ops_X550em, 32956a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_x550em, 3296d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_generic, 3297d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_generic, 32986a14ee0cSDon Skidmore }; 32996a14ee0cSDon Skidmore 3300d31afc8fSMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a = { 3301d31afc8fSMark Rustad X550_COMMON_PHY 3302d31afc8fSMark Rustad .init = &ixgbe_init_phy_ops_X550em, 3303d31afc8fSMark Rustad .identify = &ixgbe_identify_phy_x550em, 3304d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_x550a, 3305d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_x550a, 33068fe293aaSMark Rustad .read_reg_mdi = &ixgbe_read_phy_reg_mdi, 33078fe293aaSMark Rustad .write_reg_mdi = &ixgbe_write_phy_reg_mdi, 3308d31afc8fSMark Rustad }; 3309d31afc8fSMark Rustad 3310b71f6c40SEmil Tantilov static const struct ixgbe_link_operations link_ops_x550em_x = { 3311b71f6c40SEmil Tantilov .read_link = &ixgbe_read_i2c_combined_generic, 3312b71f6c40SEmil Tantilov .read_link_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, 3313b71f6c40SEmil Tantilov .write_link = &ixgbe_write_i2c_combined_generic, 3314b71f6c40SEmil Tantilov .write_link_unlocked = &ixgbe_write_i2c_combined_generic_unlocked, 3315b71f6c40SEmil Tantilov }; 3316b71f6c40SEmil Tantilov 33179a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 33189a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550) 33199a900ecaSDon Skidmore }; 33209a900ecaSDon Skidmore 33219a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 33229a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550EM_x) 33239a900ecaSDon Skidmore }; 33249a900ecaSDon Skidmore 332549425dfcSMark Rustad static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = { 332649425dfcSMark Rustad IXGBE_MVALS_INIT(X550EM_a) 332749425dfcSMark Rustad }; 332849425dfcSMark Rustad 332937689010SMark Rustad const struct ixgbe_info ixgbe_X550_info = { 33306a14ee0cSDon Skidmore .mac = ixgbe_mac_X550, 33316a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 33326a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550, 33336a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550, 33346a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550, 33356a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 33369a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550, 33376a14ee0cSDon Skidmore }; 33386a14ee0cSDon Skidmore 333937689010SMark Rustad const struct ixgbe_info ixgbe_X550EM_x_info = { 33406a14ee0cSDon Skidmore .mac = ixgbe_mac_X550EM_x, 3341b5529ef5SDon Skidmore .get_invariants = &ixgbe_get_invariants_X550_x, 33426a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550EM_x, 33436a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550EM_x, 33446a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550EM_x, 33456a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 33469a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550EM_x, 3347b71f6c40SEmil Tantilov .link_ops = &link_ops_x550em_x, 33486a14ee0cSDon Skidmore }; 334949425dfcSMark Rustad 335049425dfcSMark Rustad const struct ixgbe_info ixgbe_x550em_a_info = { 335149425dfcSMark Rustad .mac = ixgbe_mac_x550em_a, 3352b71f6c40SEmil Tantilov .get_invariants = &ixgbe_get_invariants_X550_a, 335349425dfcSMark Rustad .mac_ops = &mac_ops_x550em_a, 335449425dfcSMark Rustad .eeprom_ops = &eeprom_ops_X550EM_x, 3355d31afc8fSMark Rustad .phy_ops = &phy_ops_x550em_a, 335649425dfcSMark Rustad .mbx_ops = &mbx_ops_generic, 335749425dfcSMark Rustad .mvals = ixgbe_mvals_x550em_a, 335849425dfcSMark Rustad }; 3359