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 40512c78ef0SMark Rustad /** 40612c78ef0SMark Rustad * ixgbe_fw_phy_activity - Perform an activity on a PHY 40712c78ef0SMark Rustad * @hw: pointer to hardware structure 40812c78ef0SMark Rustad * @activity: activity to perform 40912c78ef0SMark Rustad * @data: Pointer to 4 32-bit words of data 41012c78ef0SMark Rustad */ 41112c78ef0SMark Rustad s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity, 41212c78ef0SMark Rustad u32 (*data)[FW_PHY_ACT_DATA_COUNT]) 41312c78ef0SMark Rustad { 41412c78ef0SMark Rustad union { 41512c78ef0SMark Rustad struct ixgbe_hic_phy_activity_req cmd; 41612c78ef0SMark Rustad struct ixgbe_hic_phy_activity_resp rsp; 41712c78ef0SMark Rustad } hic; 41812c78ef0SMark Rustad u16 retries = FW_PHY_ACT_RETRIES; 41912c78ef0SMark Rustad s32 rc; 42012c78ef0SMark Rustad u32 i; 42112c78ef0SMark Rustad 42212c78ef0SMark Rustad do { 42312c78ef0SMark Rustad memset(&hic, 0, sizeof(hic)); 42412c78ef0SMark Rustad hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD; 42512c78ef0SMark Rustad hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN; 42612c78ef0SMark Rustad hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 42712c78ef0SMark Rustad hic.cmd.port_number = hw->bus.lan_id; 42812c78ef0SMark Rustad hic.cmd.activity_id = cpu_to_le16(activity); 42912c78ef0SMark Rustad for (i = 0; i < ARRAY_SIZE(hic.cmd.data); ++i) 43012c78ef0SMark Rustad hic.cmd.data[i] = cpu_to_be32((*data)[i]); 43112c78ef0SMark Rustad 43212c78ef0SMark Rustad rc = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 43312c78ef0SMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 43412c78ef0SMark Rustad true); 43512c78ef0SMark Rustad if (rc) 43612c78ef0SMark Rustad return rc; 43712c78ef0SMark Rustad if (hic.rsp.hdr.cmd_or_resp.ret_status == 43812c78ef0SMark Rustad FW_CEM_RESP_STATUS_SUCCESS) { 43912c78ef0SMark Rustad for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i) 44012c78ef0SMark Rustad (*data)[i] = be32_to_cpu(hic.rsp.data[i]); 44112c78ef0SMark Rustad return 0; 44212c78ef0SMark Rustad } 44312c78ef0SMark Rustad usleep_range(20, 30); 44412c78ef0SMark Rustad --retries; 44512c78ef0SMark Rustad } while (retries > 0); 44612c78ef0SMark Rustad 44712c78ef0SMark Rustad return IXGBE_ERR_HOST_INTERFACE_COMMAND; 44812c78ef0SMark Rustad } 44912c78ef0SMark Rustad 4506a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 4516a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4526a14ee0cSDon Skidmore * 4536a14ee0cSDon Skidmore * Initializes the EEPROM parameters ixgbe_eeprom_info within the 4546a14ee0cSDon Skidmore * ixgbe_hw struct in order to set up EEPROM access. 4556a14ee0cSDon Skidmore **/ 4567ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 4576a14ee0cSDon Skidmore { 4586a14ee0cSDon Skidmore struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 4596a14ee0cSDon Skidmore u32 eec; 4606a14ee0cSDon Skidmore u16 eeprom_size; 4616a14ee0cSDon Skidmore 4626a14ee0cSDon Skidmore if (eeprom->type == ixgbe_eeprom_uninitialized) { 4636a14ee0cSDon Skidmore eeprom->semaphore_delay = 10; 4646a14ee0cSDon Skidmore eeprom->type = ixgbe_flash; 4656a14ee0cSDon Skidmore 4669a900ecaSDon Skidmore eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 4676a14ee0cSDon Skidmore eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 4686a14ee0cSDon Skidmore IXGBE_EEC_SIZE_SHIFT); 469b4f47a48SJacob Keller eeprom->word_size = BIT(eeprom_size + 4706a14ee0cSDon Skidmore IXGBE_EEPROM_WORD_SIZE_SHIFT); 4716a14ee0cSDon Skidmore 4726a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 4736a14ee0cSDon Skidmore eeprom->type, eeprom->word_size); 4746a14ee0cSDon Skidmore } 4756a14ee0cSDon Skidmore 4766a14ee0cSDon Skidmore return 0; 4776a14ee0cSDon Skidmore } 4786a14ee0cSDon Skidmore 479ae14a1d8SMark Rustad /** 480ae14a1d8SMark Rustad * ixgbe_iosf_wait - Wait for IOSF command completion 481ae14a1d8SMark Rustad * @hw: pointer to hardware structure 482ae14a1d8SMark Rustad * @ctrl: pointer to location to receive final IOSF control value 483ae14a1d8SMark Rustad * 484ae14a1d8SMark Rustad * Return: failing status on timeout 485ae14a1d8SMark Rustad * 486ae14a1d8SMark Rustad * Note: ctrl can be NULL if the IOSF control register value is not needed 487ae14a1d8SMark Rustad */ 488ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 489ae14a1d8SMark Rustad { 490ae14a1d8SMark Rustad u32 i, command; 491ae14a1d8SMark Rustad 492ae14a1d8SMark Rustad /* Check every 10 usec to see if the address cycle completed. 493ae14a1d8SMark Rustad * The SB IOSF BUSY bit will clear when the operation is 494ae14a1d8SMark Rustad * complete. 495ae14a1d8SMark Rustad */ 496ae14a1d8SMark Rustad for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 497ae14a1d8SMark Rustad command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 498ae14a1d8SMark Rustad if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 499ae14a1d8SMark Rustad break; 500d90b5b0eSMark Rustad udelay(10); 501ae14a1d8SMark Rustad } 502ae14a1d8SMark Rustad if (ctrl) 503ae14a1d8SMark Rustad *ctrl = command; 504ae14a1d8SMark Rustad if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 505ae14a1d8SMark Rustad hw_dbg(hw, "IOSF wait timed out\n"); 506ae14a1d8SMark Rustad return IXGBE_ERR_PHY; 507ae14a1d8SMark Rustad } 508ae14a1d8SMark Rustad 509ae14a1d8SMark Rustad return 0; 510ae14a1d8SMark Rustad } 511ae14a1d8SMark Rustad 5126a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 5136a14ee0cSDon Skidmore * IOSF device 5146a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5156a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 5166a14ee0cSDon Skidmore * @device_type: 3 bit device type 5176a14ee0cSDon Skidmore * @phy_data: Pointer to read data from the register 5186a14ee0cSDon Skidmore **/ 5197ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 5206a14ee0cSDon Skidmore u32 device_type, u32 *data) 5216a14ee0cSDon Skidmore { 522ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 523ae14a1d8SMark Rustad u32 command, error; 524ae14a1d8SMark Rustad s32 ret; 525ae14a1d8SMark Rustad 526ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 527ae14a1d8SMark Rustad if (ret) 528ae14a1d8SMark Rustad return ret; 529ae14a1d8SMark Rustad 530ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 531ae14a1d8SMark Rustad if (ret) 532ae14a1d8SMark Rustad goto out; 5336a14ee0cSDon Skidmore 5346a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 5356a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 5366a14ee0cSDon Skidmore 5376a14ee0cSDon Skidmore /* Write IOSF control register */ 5386a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 5396a14ee0cSDon Skidmore 540ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 5416a14ee0cSDon Skidmore 5426a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 5436a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 5446a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 5456a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read, error %x\n", error); 5466a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 5476a14ee0cSDon Skidmore } 5486a14ee0cSDon Skidmore 549ae14a1d8SMark Rustad if (!ret) 5506a14ee0cSDon Skidmore *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 5516a14ee0cSDon Skidmore 552ae14a1d8SMark Rustad out: 553ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 554ae14a1d8SMark Rustad return ret; 5556a14ee0cSDon Skidmore } 5566a14ee0cSDon Skidmore 55749425dfcSMark Rustad /** 55849425dfcSMark Rustad * ixgbe_get_phy_token - Get the token for shared PHY access 55949425dfcSMark Rustad * @hw: Pointer to hardware structure 56049425dfcSMark Rustad */ 56149425dfcSMark Rustad static s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) 56249425dfcSMark Rustad { 56349425dfcSMark Rustad struct ixgbe_hic_phy_token_req token_cmd; 56449425dfcSMark Rustad s32 status; 56549425dfcSMark Rustad 56649425dfcSMark Rustad token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 56749425dfcSMark Rustad token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 56849425dfcSMark Rustad token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 56949425dfcSMark Rustad token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 57049425dfcSMark Rustad token_cmd.port_number = hw->bus.lan_id; 57149425dfcSMark Rustad token_cmd.command_type = FW_PHY_TOKEN_REQ; 57249425dfcSMark Rustad token_cmd.pad = 0; 57349425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 57449425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 57549425dfcSMark Rustad true); 57649425dfcSMark Rustad if (status) 57749425dfcSMark Rustad return status; 57849425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 57949425dfcSMark Rustad return 0; 58049425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) 58149425dfcSMark Rustad return IXGBE_ERR_FW_RESP_INVALID; 58249425dfcSMark Rustad 58349425dfcSMark Rustad return IXGBE_ERR_TOKEN_RETRY; 58449425dfcSMark Rustad } 58549425dfcSMark Rustad 58649425dfcSMark Rustad /** 58749425dfcSMark Rustad * ixgbe_put_phy_token - Put the token for shared PHY access 58849425dfcSMark Rustad * @hw: Pointer to hardware structure 58949425dfcSMark Rustad */ 59049425dfcSMark Rustad static s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) 59149425dfcSMark Rustad { 59249425dfcSMark Rustad struct ixgbe_hic_phy_token_req token_cmd; 59349425dfcSMark Rustad s32 status; 59449425dfcSMark Rustad 59549425dfcSMark Rustad token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 59649425dfcSMark Rustad token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 59749425dfcSMark Rustad token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 59849425dfcSMark Rustad token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 59949425dfcSMark Rustad token_cmd.port_number = hw->bus.lan_id; 60049425dfcSMark Rustad token_cmd.command_type = FW_PHY_TOKEN_REL; 60149425dfcSMark Rustad token_cmd.pad = 0; 60249425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 60349425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 60449425dfcSMark Rustad true); 60549425dfcSMark Rustad if (status) 60649425dfcSMark Rustad return status; 60749425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 60849425dfcSMark Rustad return 0; 60949425dfcSMark Rustad return IXGBE_ERR_FW_RESP_INVALID; 61049425dfcSMark Rustad } 61149425dfcSMark Rustad 61249425dfcSMark Rustad /** 61349425dfcSMark Rustad * ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register 61449425dfcSMark Rustad * @hw: pointer to hardware structure 61549425dfcSMark Rustad * @reg_addr: 32 bit PHY register to write 61649425dfcSMark Rustad * @device_type: 3 bit device type 61749425dfcSMark Rustad * @data: Data to write to the register 61849425dfcSMark Rustad **/ 61949425dfcSMark Rustad static s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 62049425dfcSMark Rustad __always_unused u32 device_type, 62149425dfcSMark Rustad u32 data) 62249425dfcSMark Rustad { 62349425dfcSMark Rustad struct ixgbe_hic_internal_phy_req write_cmd; 62449425dfcSMark Rustad 62549425dfcSMark Rustad memset(&write_cmd, 0, sizeof(write_cmd)); 62649425dfcSMark Rustad write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 62749425dfcSMark Rustad write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 62849425dfcSMark Rustad write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 62949425dfcSMark Rustad write_cmd.port_number = hw->bus.lan_id; 63049425dfcSMark Rustad write_cmd.command_type = FW_INT_PHY_REQ_WRITE; 63149425dfcSMark Rustad write_cmd.address = cpu_to_be16(reg_addr); 63249425dfcSMark Rustad write_cmd.write_data = cpu_to_be32(data); 63349425dfcSMark Rustad 63449425dfcSMark Rustad return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd), 63549425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, false); 63649425dfcSMark Rustad } 63749425dfcSMark Rustad 63849425dfcSMark Rustad /** 63949425dfcSMark Rustad * ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register 64049425dfcSMark Rustad * @hw: pointer to hardware structure 64149425dfcSMark Rustad * @reg_addr: 32 bit PHY register to write 64249425dfcSMark Rustad * @device_type: 3 bit device type 64349425dfcSMark Rustad * @data: Pointer to read data from the register 64449425dfcSMark Rustad **/ 64549425dfcSMark Rustad static s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 64649425dfcSMark Rustad __always_unused u32 device_type, 64749425dfcSMark Rustad u32 *data) 64849425dfcSMark Rustad { 64949425dfcSMark Rustad union { 65049425dfcSMark Rustad struct ixgbe_hic_internal_phy_req cmd; 65149425dfcSMark Rustad struct ixgbe_hic_internal_phy_resp rsp; 65249425dfcSMark Rustad } hic; 65349425dfcSMark Rustad s32 status; 65449425dfcSMark Rustad 65549425dfcSMark Rustad memset(&hic, 0, sizeof(hic)); 65649425dfcSMark Rustad hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 65749425dfcSMark Rustad hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 65849425dfcSMark Rustad hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 65949425dfcSMark Rustad hic.cmd.port_number = hw->bus.lan_id; 66049425dfcSMark Rustad hic.cmd.command_type = FW_INT_PHY_REQ_READ; 66149425dfcSMark Rustad hic.cmd.address = cpu_to_be16(reg_addr); 66249425dfcSMark Rustad 66349425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 66449425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, true); 66549425dfcSMark Rustad 66649425dfcSMark Rustad /* Extract the register value from the response. */ 66749425dfcSMark Rustad *data = be32_to_cpu(hic.rsp.read_data); 66849425dfcSMark Rustad 66949425dfcSMark Rustad return status; 67049425dfcSMark Rustad } 67149425dfcSMark Rustad 6726a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 6736a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6746a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 6756a14ee0cSDon Skidmore * @words: number of words 6766a14ee0cSDon Skidmore * @data: word(s) read from the EEPROM 6776a14ee0cSDon Skidmore * 6786a14ee0cSDon Skidmore * Reads a 16 bit word(s) from the EEPROM using the hostif. 6796a14ee0cSDon Skidmore **/ 6807ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 6816a14ee0cSDon Skidmore u16 offset, u16 words, u16 *data) 6826a14ee0cSDon Skidmore { 6833efa9ed2SMark Rustad const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; 6846a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 6856a14ee0cSDon Skidmore u32 current_word = 0; 6866a14ee0cSDon Skidmore u16 words_to_read; 6876a14ee0cSDon Skidmore s32 status; 6886a14ee0cSDon Skidmore u32 i; 6896a14ee0cSDon Skidmore 6906a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 6913efa9ed2SMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, mask); 6926a14ee0cSDon Skidmore if (status) { 6936a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 6946a14ee0cSDon Skidmore return status; 6956a14ee0cSDon Skidmore } 6966a14ee0cSDon Skidmore 6976a14ee0cSDon Skidmore while (words) { 6986a14ee0cSDon Skidmore if (words > FW_MAX_READ_BUFFER_SIZE / 2) 6996a14ee0cSDon Skidmore words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 7006a14ee0cSDon Skidmore else 7016a14ee0cSDon Skidmore words_to_read = words; 7026a14ee0cSDon Skidmore 7036a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 7046a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 7056a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 7066a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 7076a14ee0cSDon Skidmore 7086a14ee0cSDon Skidmore /* convert offset from words to bytes */ 7096a14ee0cSDon Skidmore buffer.address = cpu_to_be32((offset + current_word) * 2); 7106a14ee0cSDon Skidmore buffer.length = cpu_to_be16(words_to_read * 2); 7116a14ee0cSDon Skidmore 7123efa9ed2SMark Rustad status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), 7133efa9ed2SMark Rustad IXGBE_HI_COMMAND_TIMEOUT); 7146a14ee0cSDon Skidmore if (status) { 7156a14ee0cSDon Skidmore hw_dbg(hw, "Host interface command failed\n"); 7166a14ee0cSDon Skidmore goto out; 7176a14ee0cSDon Skidmore } 7186a14ee0cSDon Skidmore 7196a14ee0cSDon Skidmore for (i = 0; i < words_to_read; i++) { 7206a14ee0cSDon Skidmore u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 7216a14ee0cSDon Skidmore 2 * i; 7226a14ee0cSDon Skidmore u32 value = IXGBE_READ_REG(hw, reg); 7236a14ee0cSDon Skidmore 7246a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 7256a14ee0cSDon Skidmore current_word++; 7266a14ee0cSDon Skidmore i++; 7276a14ee0cSDon Skidmore if (i < words_to_read) { 7286a14ee0cSDon Skidmore value >>= 16; 7296a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 7306a14ee0cSDon Skidmore current_word++; 7316a14ee0cSDon Skidmore } 7326a14ee0cSDon Skidmore } 7336a14ee0cSDon Skidmore words -= words_to_read; 7346a14ee0cSDon Skidmore } 7356a14ee0cSDon Skidmore 7366a14ee0cSDon Skidmore out: 7373efa9ed2SMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 7386a14ee0cSDon Skidmore return status; 7396a14ee0cSDon Skidmore } 7406a14ee0cSDon Skidmore 7416a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region 7426a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7436a14ee0cSDon Skidmore * @ptr: pointer offset in eeprom 7446a14ee0cSDon Skidmore * @size: size of section pointed by ptr, if 0 first word will be used as size 7456a14ee0cSDon Skidmore * @csum: address of checksum to update 7466a14ee0cSDon Skidmore * 7476a14ee0cSDon Skidmore * Returns error status for any failure 7486a14ee0cSDon Skidmore **/ 7496a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 7506a14ee0cSDon Skidmore u16 size, u16 *csum, u16 *buffer, 7516a14ee0cSDon Skidmore u32 buffer_size) 7526a14ee0cSDon Skidmore { 7536a14ee0cSDon Skidmore u16 buf[256]; 7546a14ee0cSDon Skidmore s32 status; 7556a14ee0cSDon Skidmore u16 length, bufsz, i, start; 7566a14ee0cSDon Skidmore u16 *local_buffer; 7576a14ee0cSDon Skidmore 7586a14ee0cSDon Skidmore bufsz = sizeof(buf) / sizeof(buf[0]); 7596a14ee0cSDon Skidmore 7606a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 7616a14ee0cSDon Skidmore if (!buffer) { 7626a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 7636a14ee0cSDon Skidmore if (status) { 7646a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 7656a14ee0cSDon Skidmore return status; 7666a14ee0cSDon Skidmore } 7676a14ee0cSDon Skidmore local_buffer = buf; 7686a14ee0cSDon Skidmore } else { 7696a14ee0cSDon Skidmore if (buffer_size < ptr) 7706a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 7716a14ee0cSDon Skidmore local_buffer = &buffer[ptr]; 7726a14ee0cSDon Skidmore } 7736a14ee0cSDon Skidmore 7746a14ee0cSDon Skidmore if (size) { 7756a14ee0cSDon Skidmore start = 0; 7766a14ee0cSDon Skidmore length = size; 7776a14ee0cSDon Skidmore } else { 7786a14ee0cSDon Skidmore start = 1; 7796a14ee0cSDon Skidmore length = local_buffer[0]; 7806a14ee0cSDon Skidmore 7816a14ee0cSDon Skidmore /* Skip pointer section if length is invalid. */ 7826a14ee0cSDon Skidmore if (length == 0xFFFF || length == 0 || 7836a14ee0cSDon Skidmore (ptr + length) >= hw->eeprom.word_size) 7846a14ee0cSDon Skidmore return 0; 7856a14ee0cSDon Skidmore } 7866a14ee0cSDon Skidmore 7876a14ee0cSDon Skidmore if (buffer && ((u32)start + (u32)length > buffer_size)) 7886a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 7896a14ee0cSDon Skidmore 7906a14ee0cSDon Skidmore for (i = start; length; i++, length--) { 7916a14ee0cSDon Skidmore if (i == bufsz && !buffer) { 7926a14ee0cSDon Skidmore ptr += bufsz; 7936a14ee0cSDon Skidmore i = 0; 7946a14ee0cSDon Skidmore if (length < bufsz) 7956a14ee0cSDon Skidmore bufsz = length; 7966a14ee0cSDon Skidmore 7976a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 7986a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 7996a14ee0cSDon Skidmore bufsz, buf); 8006a14ee0cSDon Skidmore if (status) { 8016a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 8026a14ee0cSDon Skidmore return status; 8036a14ee0cSDon Skidmore } 8046a14ee0cSDon Skidmore } 8056a14ee0cSDon Skidmore *csum += local_buffer[i]; 8066a14ee0cSDon Skidmore } 8076a14ee0cSDon Skidmore return 0; 8086a14ee0cSDon Skidmore } 8096a14ee0cSDon Skidmore 8106a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 8116a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8126a14ee0cSDon Skidmore * @buffer: pointer to buffer containing calculated checksum 8136a14ee0cSDon Skidmore * @buffer_size: size of buffer 8146a14ee0cSDon Skidmore * 8156a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 8166a14ee0cSDon Skidmore **/ 8177ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 8187ddbde3fSDon Skidmore u32 buffer_size) 8196a14ee0cSDon Skidmore { 8206a14ee0cSDon Skidmore u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 8216a14ee0cSDon Skidmore u16 *local_buffer; 8226a14ee0cSDon Skidmore s32 status; 8236a14ee0cSDon Skidmore u16 checksum = 0; 8246a14ee0cSDon Skidmore u16 pointer, i, size; 8256a14ee0cSDon Skidmore 8266a14ee0cSDon Skidmore hw->eeprom.ops.init_params(hw); 8276a14ee0cSDon Skidmore 8286a14ee0cSDon Skidmore if (!buffer) { 8296a14ee0cSDon Skidmore /* Read pointer area */ 8306a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 8316a14ee0cSDon Skidmore IXGBE_EEPROM_LAST_WORD + 1, 8326a14ee0cSDon Skidmore eeprom_ptrs); 8336a14ee0cSDon Skidmore if (status) { 8346a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 8356a14ee0cSDon Skidmore return status; 8366a14ee0cSDon Skidmore } 8376a14ee0cSDon Skidmore local_buffer = eeprom_ptrs; 8386a14ee0cSDon Skidmore } else { 8396a14ee0cSDon Skidmore if (buffer_size < IXGBE_EEPROM_LAST_WORD) 8406a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 8416a14ee0cSDon Skidmore local_buffer = buffer; 8426a14ee0cSDon Skidmore } 8436a14ee0cSDon Skidmore 8446a14ee0cSDon Skidmore /* For X550 hardware include 0x0-0x41 in the checksum, skip the 8456a14ee0cSDon Skidmore * checksum word itself 8466a14ee0cSDon Skidmore */ 8476a14ee0cSDon Skidmore for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 8486a14ee0cSDon Skidmore if (i != IXGBE_EEPROM_CHECKSUM) 8496a14ee0cSDon Skidmore checksum += local_buffer[i]; 8506a14ee0cSDon Skidmore 8516a14ee0cSDon Skidmore /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 8526a14ee0cSDon Skidmore * FW, PHY module, and PCIe Expansion/Option ROM pointers. 8536a14ee0cSDon Skidmore */ 8546a14ee0cSDon Skidmore for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 8556a14ee0cSDon Skidmore if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 8566a14ee0cSDon Skidmore continue; 8576a14ee0cSDon Skidmore 8586a14ee0cSDon Skidmore pointer = local_buffer[i]; 8596a14ee0cSDon Skidmore 8606a14ee0cSDon Skidmore /* Skip pointer section if the pointer is invalid. */ 8616a14ee0cSDon Skidmore if (pointer == 0xFFFF || pointer == 0 || 8626a14ee0cSDon Skidmore pointer >= hw->eeprom.word_size) 8636a14ee0cSDon Skidmore continue; 8646a14ee0cSDon Skidmore 8656a14ee0cSDon Skidmore switch (i) { 8666a14ee0cSDon Skidmore case IXGBE_PCIE_GENERAL_PTR: 8676a14ee0cSDon Skidmore size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 8686a14ee0cSDon Skidmore break; 8696a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG0_PTR: 8706a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG1_PTR: 8716a14ee0cSDon Skidmore size = IXGBE_PCIE_CONFIG_SIZE; 8726a14ee0cSDon Skidmore break; 8736a14ee0cSDon Skidmore default: 8746a14ee0cSDon Skidmore size = 0; 8756a14ee0cSDon Skidmore break; 8766a14ee0cSDon Skidmore } 8776a14ee0cSDon Skidmore 8786a14ee0cSDon Skidmore status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 8796a14ee0cSDon Skidmore buffer, buffer_size); 8806a14ee0cSDon Skidmore if (status) 8816a14ee0cSDon Skidmore return status; 8826a14ee0cSDon Skidmore } 8836a14ee0cSDon Skidmore 8846a14ee0cSDon Skidmore checksum = (u16)IXGBE_EEPROM_SUM - checksum; 8856a14ee0cSDon Skidmore 8866a14ee0cSDon Skidmore return (s32)checksum; 8876a14ee0cSDon Skidmore } 8886a14ee0cSDon Skidmore 8896a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 8906a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8916a14ee0cSDon Skidmore * 8926a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 8936a14ee0cSDon Skidmore **/ 8947ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 8956a14ee0cSDon Skidmore { 8966a14ee0cSDon Skidmore return ixgbe_calc_checksum_X550(hw, NULL, 0); 8976a14ee0cSDon Skidmore } 8986a14ee0cSDon Skidmore 8996a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 9006a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9016a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 9026a14ee0cSDon Skidmore * @data: word read from the EEPROM 9036a14ee0cSDon Skidmore * 9046a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 9056a14ee0cSDon Skidmore **/ 9067ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 9076a14ee0cSDon Skidmore { 9083efa9ed2SMark Rustad const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; 9093efa9ed2SMark Rustad struct ixgbe_hic_read_shadow_ram buffer; 9103efa9ed2SMark Rustad s32 status; 9116a14ee0cSDon Skidmore 9123efa9ed2SMark Rustad buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 9133efa9ed2SMark Rustad buffer.hdr.req.buf_lenh = 0; 9143efa9ed2SMark Rustad buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 9153efa9ed2SMark Rustad buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 9163efa9ed2SMark Rustad 9173efa9ed2SMark Rustad /* convert offset from words to bytes */ 9183efa9ed2SMark Rustad buffer.address = cpu_to_be32(offset * 2); 9193efa9ed2SMark Rustad /* one word */ 9203efa9ed2SMark Rustad buffer.length = cpu_to_be16(sizeof(u16)); 9213efa9ed2SMark Rustad 9223efa9ed2SMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, mask); 9233efa9ed2SMark Rustad if (status) 9243efa9ed2SMark Rustad return status; 9253efa9ed2SMark Rustad 9263efa9ed2SMark Rustad status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), 9273efa9ed2SMark Rustad IXGBE_HI_COMMAND_TIMEOUT); 9283efa9ed2SMark Rustad if (!status) { 9293efa9ed2SMark Rustad *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 9303efa9ed2SMark Rustad FW_NVM_DATA_OFFSET); 9316a14ee0cSDon Skidmore } 9326a14ee0cSDon Skidmore 9333efa9ed2SMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 9346a14ee0cSDon Skidmore return status; 9356a14ee0cSDon Skidmore } 9366a14ee0cSDon Skidmore 9376a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 9386a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9396a14ee0cSDon Skidmore * @checksum_val: calculated checksum 9406a14ee0cSDon Skidmore * 9416a14ee0cSDon Skidmore * Performs checksum calculation and validates the EEPROM checksum. If the 9426a14ee0cSDon Skidmore * caller does not need checksum_val, the value can be NULL. 9436a14ee0cSDon Skidmore **/ 9447ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 9457ddbde3fSDon Skidmore u16 *checksum_val) 9466a14ee0cSDon Skidmore { 9476a14ee0cSDon Skidmore s32 status; 9486a14ee0cSDon Skidmore u16 checksum; 9496a14ee0cSDon Skidmore u16 read_checksum = 0; 9506a14ee0cSDon Skidmore 9516a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 9526a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 9536a14ee0cSDon Skidmore * EEPROM read fails 9546a14ee0cSDon Skidmore */ 9556a14ee0cSDon Skidmore status = hw->eeprom.ops.read(hw, 0, &checksum); 9566a14ee0cSDon Skidmore if (status) { 9576a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 9586a14ee0cSDon Skidmore return status; 9596a14ee0cSDon Skidmore } 9606a14ee0cSDon Skidmore 9616a14ee0cSDon Skidmore status = hw->eeprom.ops.calc_checksum(hw); 9626a14ee0cSDon Skidmore if (status < 0) 9636a14ee0cSDon Skidmore return status; 9646a14ee0cSDon Skidmore 9656a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 9666a14ee0cSDon Skidmore 9676a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 9686a14ee0cSDon Skidmore &read_checksum); 9696a14ee0cSDon Skidmore if (status) 9706a14ee0cSDon Skidmore return status; 9716a14ee0cSDon Skidmore 9726a14ee0cSDon Skidmore /* Verify read checksum from EEPROM is the same as 9736a14ee0cSDon Skidmore * calculated checksum 9746a14ee0cSDon Skidmore */ 9756a14ee0cSDon Skidmore if (read_checksum != checksum) { 9766a14ee0cSDon Skidmore status = IXGBE_ERR_EEPROM_CHECKSUM; 9776a14ee0cSDon Skidmore hw_dbg(hw, "Invalid EEPROM checksum"); 9786a14ee0cSDon Skidmore } 9796a14ee0cSDon Skidmore 9806a14ee0cSDon Skidmore /* If the user cares, return the calculated checksum */ 9816a14ee0cSDon Skidmore if (checksum_val) 9826a14ee0cSDon Skidmore *checksum_val = checksum; 9836a14ee0cSDon Skidmore 9846a14ee0cSDon Skidmore return status; 9856a14ee0cSDon Skidmore } 9866a14ee0cSDon Skidmore 9876a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 9886a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9896a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 9906a14ee0cSDon Skidmore * @data: word write to the EEPROM 9916a14ee0cSDon Skidmore * 9926a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 9936a14ee0cSDon Skidmore **/ 9947ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 9957ddbde3fSDon Skidmore u16 data) 9966a14ee0cSDon Skidmore { 9976a14ee0cSDon Skidmore s32 status; 9986a14ee0cSDon Skidmore struct ixgbe_hic_write_shadow_ram buffer; 9996a14ee0cSDon Skidmore 10006a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 10016a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 10026a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 10036a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 10046a14ee0cSDon Skidmore 10056a14ee0cSDon Skidmore /* one word */ 10066a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 10076a14ee0cSDon Skidmore buffer.data = data; 10086a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 10096a14ee0cSDon Skidmore 10105cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 10116a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 10126a14ee0cSDon Skidmore return status; 10136a14ee0cSDon Skidmore } 10146a14ee0cSDon Skidmore 10156a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 10166a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10176a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 10186a14ee0cSDon Skidmore * @data: word write to the EEPROM 10196a14ee0cSDon Skidmore * 10206a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 10216a14ee0cSDon Skidmore **/ 10227ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 10236a14ee0cSDon Skidmore { 10246a14ee0cSDon Skidmore s32 status = 0; 10256a14ee0cSDon Skidmore 10266a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 10276a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 10286a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 10296a14ee0cSDon Skidmore } else { 10306a14ee0cSDon Skidmore hw_dbg(hw, "write ee hostif failed to get semaphore"); 10316a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 10326a14ee0cSDon Skidmore } 10336a14ee0cSDon Skidmore 10346a14ee0cSDon Skidmore return status; 10356a14ee0cSDon Skidmore } 10366a14ee0cSDon Skidmore 10376a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 10386a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10396a14ee0cSDon Skidmore * 10406a14ee0cSDon Skidmore * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 10416a14ee0cSDon Skidmore **/ 10427ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 10436a14ee0cSDon Skidmore { 10446a14ee0cSDon Skidmore s32 status = 0; 10456a14ee0cSDon Skidmore union ixgbe_hic_hdr2 buffer; 10466a14ee0cSDon Skidmore 10476a14ee0cSDon Skidmore buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 10486a14ee0cSDon Skidmore buffer.req.buf_lenh = 0; 10496a14ee0cSDon Skidmore buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 10506a14ee0cSDon Skidmore buffer.req.checksum = FW_DEFAULT_CHECKSUM; 10516a14ee0cSDon Skidmore 10525cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 10536a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 10546a14ee0cSDon Skidmore return status; 10556a14ee0cSDon Skidmore } 10566a14ee0cSDon Skidmore 1057454c65ddSDon Skidmore /** 1058454c65ddSDon Skidmore * ixgbe_get_bus_info_X550em - Set PCI bus info 1059454c65ddSDon Skidmore * @hw: pointer to hardware structure 1060454c65ddSDon Skidmore * 1061454c65ddSDon Skidmore * Sets bus link width and speed to unknown because X550em is 1062454c65ddSDon Skidmore * not a PCI device. 1063454c65ddSDon Skidmore **/ 1064454c65ddSDon Skidmore static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) 1065454c65ddSDon Skidmore { 1066f9328bc6SDon Skidmore hw->bus.type = ixgbe_bus_type_internal; 1067454c65ddSDon Skidmore hw->bus.width = ixgbe_bus_width_unknown; 1068454c65ddSDon Skidmore hw->bus.speed = ixgbe_bus_speed_unknown; 1069454c65ddSDon Skidmore 1070454c65ddSDon Skidmore hw->mac.ops.set_lan_id(hw); 1071454c65ddSDon Skidmore 1072454c65ddSDon Skidmore return 0; 1073454c65ddSDon Skidmore } 1074454c65ddSDon Skidmore 10751f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit 10761f9ac57cSDon Skidmore * 10771f9ac57cSDon Skidmore * Enables the Rx DMA unit for x550 10781f9ac57cSDon Skidmore **/ 10791f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 10801f9ac57cSDon Skidmore { 10811f9ac57cSDon Skidmore u32 rxctrl, pfdtxgswc; 10821f9ac57cSDon Skidmore s32 status; 10831f9ac57cSDon Skidmore struct ixgbe_hic_disable_rxen fw_cmd; 10841f9ac57cSDon Skidmore 10851f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 10861f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 10871f9ac57cSDon Skidmore pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 10881f9ac57cSDon Skidmore if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 10891f9ac57cSDon Skidmore pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 10901f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 10911f9ac57cSDon Skidmore hw->mac.set_lben = true; 10921f9ac57cSDon Skidmore } else { 10931f9ac57cSDon Skidmore hw->mac.set_lben = false; 10941f9ac57cSDon Skidmore } 10951f9ac57cSDon Skidmore 10961f9ac57cSDon Skidmore fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 10971f9ac57cSDon Skidmore fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 10981f9ac57cSDon Skidmore fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 10993775b814SMark Rustad fw_cmd.port_number = hw->bus.lan_id; 11001f9ac57cSDon Skidmore 11015cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &fw_cmd, 11021f9ac57cSDon Skidmore sizeof(struct ixgbe_hic_disable_rxen), 11031f9ac57cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, true); 11041f9ac57cSDon Skidmore 11051f9ac57cSDon Skidmore /* If we fail - disable RX using register write */ 11061f9ac57cSDon Skidmore if (status) { 11071f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 11081f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 11091f9ac57cSDon Skidmore rxctrl &= ~IXGBE_RXCTRL_RXEN; 11101f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 11111f9ac57cSDon Skidmore } 11121f9ac57cSDon Skidmore } 11131f9ac57cSDon Skidmore } 11141f9ac57cSDon Skidmore } 11151f9ac57cSDon Skidmore 11166a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 11176a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11186a14ee0cSDon Skidmore * 11196a14ee0cSDon Skidmore * After writing EEPROM to shadow RAM using EEWR register, software calculates 11206a14ee0cSDon Skidmore * checksum and updates the EEPROM and instructs the hardware to update 11216a14ee0cSDon Skidmore * the flash. 11226a14ee0cSDon Skidmore **/ 11237ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 11246a14ee0cSDon Skidmore { 11256a14ee0cSDon Skidmore s32 status; 11266a14ee0cSDon Skidmore u16 checksum = 0; 11276a14ee0cSDon Skidmore 11286a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 11296a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 11306a14ee0cSDon Skidmore * EEPROM read fails 11316a14ee0cSDon Skidmore */ 11326a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 11336a14ee0cSDon Skidmore if (status) { 11346a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 11356a14ee0cSDon Skidmore return status; 11366a14ee0cSDon Skidmore } 11376a14ee0cSDon Skidmore 11386a14ee0cSDon Skidmore status = ixgbe_calc_eeprom_checksum_X550(hw); 11396a14ee0cSDon Skidmore if (status < 0) 11406a14ee0cSDon Skidmore return status; 11416a14ee0cSDon Skidmore 11426a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 11436a14ee0cSDon Skidmore 11446a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 11456a14ee0cSDon Skidmore checksum); 11466a14ee0cSDon Skidmore if (status) 11476a14ee0cSDon Skidmore return status; 11486a14ee0cSDon Skidmore 11496a14ee0cSDon Skidmore status = ixgbe_update_flash_X550(hw); 11506a14ee0cSDon Skidmore 11516a14ee0cSDon Skidmore return status; 11526a14ee0cSDon Skidmore } 11536a14ee0cSDon Skidmore 11546a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 11556a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11566a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 11576a14ee0cSDon Skidmore * @words: number of words 11586a14ee0cSDon Skidmore * @data: word(s) write to the EEPROM 11596a14ee0cSDon Skidmore * 11606a14ee0cSDon Skidmore * 11616a14ee0cSDon Skidmore * Write a 16 bit word(s) to the EEPROM using the hostif. 11626a14ee0cSDon Skidmore **/ 11637ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 11647ddbde3fSDon Skidmore u16 offset, u16 words, 11657ddbde3fSDon Skidmore u16 *data) 11666a14ee0cSDon Skidmore { 11676a14ee0cSDon Skidmore s32 status = 0; 11686a14ee0cSDon Skidmore u32 i = 0; 11696a14ee0cSDon Skidmore 11706a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 11716a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 11726a14ee0cSDon Skidmore if (status) { 11736a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 11746a14ee0cSDon Skidmore return status; 11756a14ee0cSDon Skidmore } 11766a14ee0cSDon Skidmore 11776a14ee0cSDon Skidmore for (i = 0; i < words; i++) { 11786a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 11796a14ee0cSDon Skidmore data[i]); 11806a14ee0cSDon Skidmore if (status) { 11816a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom buffered write failed\n"); 11826a14ee0cSDon Skidmore break; 11836a14ee0cSDon Skidmore } 11846a14ee0cSDon Skidmore } 11856a14ee0cSDon Skidmore 11866a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 11876a14ee0cSDon Skidmore 11886a14ee0cSDon Skidmore return status; 11896a14ee0cSDon Skidmore } 11906a14ee0cSDon Skidmore 11916a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 11926a14ee0cSDon Skidmore * IOSF device 11936a14ee0cSDon Skidmore * 11946a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11956a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 11966a14ee0cSDon Skidmore * @device_type: 3 bit device type 11976a14ee0cSDon Skidmore * @data: Data to write to the register 11986a14ee0cSDon Skidmore **/ 11997ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 12006a14ee0cSDon Skidmore u32 device_type, u32 data) 12016a14ee0cSDon Skidmore { 1202ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 1203ae14a1d8SMark Rustad u32 command, error; 1204ae14a1d8SMark Rustad s32 ret; 1205ae14a1d8SMark Rustad 1206ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 1207ae14a1d8SMark Rustad if (ret) 1208ae14a1d8SMark Rustad return ret; 1209ae14a1d8SMark Rustad 1210ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 1211ae14a1d8SMark Rustad if (ret) 1212ae14a1d8SMark Rustad goto out; 12136a14ee0cSDon Skidmore 12146a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 12156a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 12166a14ee0cSDon Skidmore 12176a14ee0cSDon Skidmore /* Write IOSF control register */ 12186a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 12196a14ee0cSDon Skidmore 12206a14ee0cSDon Skidmore /* Write IOSF data register */ 12216a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 12226a14ee0cSDon Skidmore 1223ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 12246a14ee0cSDon Skidmore 12256a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 12266a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 12276a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 12286a14ee0cSDon Skidmore hw_dbg(hw, "Failed to write, error %x\n", error); 12296a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 12306a14ee0cSDon Skidmore } 12316a14ee0cSDon Skidmore 1232ae14a1d8SMark Rustad out: 1233ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 1234ae14a1d8SMark Rustad return ret; 12356a14ee0cSDon Skidmore } 12366a14ee0cSDon Skidmore 12370c1b7de4SDon Skidmore /** 12380c1b7de4SDon Skidmore * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration 12396a14ee0cSDon Skidmore * @hw: pointer to hardware structure 12406a14ee0cSDon Skidmore * 12410c1b7de4SDon Skidmore * iXfI configuration needed for ixgbe_mac_X550EM_x devices. 12426a14ee0cSDon Skidmore **/ 12430c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) 12446a14ee0cSDon Skidmore { 12456a14ee0cSDon Skidmore s32 status; 12466a14ee0cSDon Skidmore u32 reg_val; 12476a14ee0cSDon Skidmore 12486a14ee0cSDon Skidmore /* Disable training protocol FSM. */ 12496a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12506a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 12516a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12526a14ee0cSDon Skidmore if (status) 12536a14ee0cSDon Skidmore return status; 12546a14ee0cSDon Skidmore 12556a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 12566a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12576a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 12586a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12596a14ee0cSDon Skidmore if (status) 12606a14ee0cSDon Skidmore return status; 12616a14ee0cSDon Skidmore 12626a14ee0cSDon Skidmore /* Disable Flex from training TXFFE. */ 12636a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12646a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 12656a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12666a14ee0cSDon Skidmore if (status) 12676a14ee0cSDon Skidmore return status; 12686a14ee0cSDon Skidmore 12696a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 12706a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 12716a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 12726a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12736a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 12746a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12756a14ee0cSDon Skidmore if (status) 12766a14ee0cSDon Skidmore return status; 12776a14ee0cSDon Skidmore 12786a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12796a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 12806a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12816a14ee0cSDon Skidmore if (status) 12826a14ee0cSDon Skidmore return status; 12836a14ee0cSDon Skidmore 12846a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 12856a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 12866a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 12876a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 12886a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 12896a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 12906a14ee0cSDon Skidmore if (status) 12916a14ee0cSDon Skidmore return status; 12926a14ee0cSDon Skidmore 12936a14ee0cSDon Skidmore /* Enable override for coefficients. */ 12946a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 12956a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 12966a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 12976a14ee0cSDon Skidmore if (status) 12986a14ee0cSDon Skidmore return status; 12996a14ee0cSDon Skidmore 13006a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 13016a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 13026a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 13036a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 13046a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 13056a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 13066a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 13070c1b7de4SDon Skidmore return status; 13080c1b7de4SDon Skidmore } 13090c1b7de4SDon Skidmore 1310470739b5SDon Skidmore /** 1311470739b5SDon Skidmore * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the 1312470739b5SDon Skidmore * internal PHY 1313470739b5SDon Skidmore * @hw: pointer to hardware structure 1314470739b5SDon Skidmore **/ 1315470739b5SDon Skidmore static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw) 1316470739b5SDon Skidmore { 1317470739b5SDon Skidmore s32 status; 1318470739b5SDon Skidmore u32 link_ctrl; 1319470739b5SDon Skidmore 1320470739b5SDon Skidmore /* Restart auto-negotiation. */ 1321470739b5SDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 1322470739b5SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1323470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); 1324470739b5SDon Skidmore 1325470739b5SDon Skidmore if (status) { 1326470739b5SDon Skidmore hw_dbg(hw, "Auto-negotiation did not complete\n"); 1327470739b5SDon Skidmore return status; 1328470739b5SDon Skidmore } 1329470739b5SDon Skidmore 1330470739b5SDon Skidmore link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 1331470739b5SDon Skidmore status = hw->mac.ops.write_iosf_sb_reg(hw, 1332470739b5SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1333470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); 1334470739b5SDon Skidmore 1335470739b5SDon Skidmore if (hw->mac.type == ixgbe_mac_x550em_a) { 1336470739b5SDon Skidmore u32 flx_mask_st20; 1337470739b5SDon Skidmore 1338470739b5SDon Skidmore /* Indicate to FW that AN restart has been asserted */ 1339470739b5SDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 1340470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1341470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20); 1342470739b5SDon Skidmore 1343470739b5SDon Skidmore if (status) { 1344470739b5SDon Skidmore hw_dbg(hw, "Auto-negotiation did not complete\n"); 1345470739b5SDon Skidmore return status; 1346470739b5SDon Skidmore } 1347470739b5SDon Skidmore 1348470739b5SDon Skidmore flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART; 1349470739b5SDon Skidmore status = hw->mac.ops.write_iosf_sb_reg(hw, 1350470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1351470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20); 1352470739b5SDon Skidmore } 1353470739b5SDon Skidmore 1354470739b5SDon Skidmore return status; 1355470739b5SDon Skidmore } 1356470739b5SDon Skidmore 13570c1b7de4SDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 13580c1b7de4SDon Skidmore * @hw: pointer to hardware structure 13590c1b7de4SDon Skidmore * @speed: the link speed to force 13600c1b7de4SDon Skidmore * 13610c1b7de4SDon Skidmore * Configures the integrated KR PHY to use iXFI mode. Used to connect an 13620c1b7de4SDon Skidmore * internal and external PHY at a specific speed, without autonegotiation. 13630c1b7de4SDon Skidmore **/ 13640c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 13650c1b7de4SDon Skidmore { 13660c1b7de4SDon Skidmore s32 status; 13670c1b7de4SDon Skidmore u32 reg_val; 13680c1b7de4SDon Skidmore 13690c1b7de4SDon Skidmore /* Disable AN and force speed to 10G Serial. */ 13700c1b7de4SDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 13710c1b7de4SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 13720c1b7de4SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 13736a14ee0cSDon Skidmore if (status) 13746a14ee0cSDon Skidmore return status; 13756a14ee0cSDon Skidmore 13760c1b7de4SDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 13770c1b7de4SDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 13780c1b7de4SDon Skidmore 13790c1b7de4SDon Skidmore /* Select forced link speed for internal PHY. */ 13800c1b7de4SDon Skidmore switch (*speed) { 13810c1b7de4SDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 13820c1b7de4SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 13830c1b7de4SDon Skidmore break; 13840c1b7de4SDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 13850c1b7de4SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 13860c1b7de4SDon Skidmore break; 13870c1b7de4SDon Skidmore default: 13880c1b7de4SDon Skidmore /* Other link speeds are not supported by internal KR PHY. */ 13890c1b7de4SDon Skidmore return IXGBE_ERR_LINK_SETUP; 13900c1b7de4SDon Skidmore } 13910c1b7de4SDon Skidmore 13920c1b7de4SDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 13930c1b7de4SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 13940c1b7de4SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 13950c1b7de4SDon Skidmore if (status) 13960c1b7de4SDon Skidmore return status; 13970c1b7de4SDon Skidmore 13980c1b7de4SDon Skidmore /* Additional configuration needed for x550em_x */ 13990c1b7de4SDon Skidmore if (hw->mac.type == ixgbe_mac_X550EM_x) { 14000c1b7de4SDon Skidmore status = ixgbe_setup_ixfi_x550em_x(hw); 14010c1b7de4SDon Skidmore if (status) 14020c1b7de4SDon Skidmore return status; 14030c1b7de4SDon Skidmore } 14040c1b7de4SDon Skidmore 14056a14ee0cSDon Skidmore /* Toggle port SW reset by AN reset. */ 1406470739b5SDon Skidmore status = ixgbe_restart_an_internal_phy_x550em(hw); 14076a14ee0cSDon Skidmore 14086a14ee0cSDon Skidmore return status; 14096a14ee0cSDon Skidmore } 14106a14ee0cSDon Skidmore 1411c3dc4c09SDon Skidmore /** 1412e23f3336SMark Rustad * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported 1413e23f3336SMark Rustad * @hw: pointer to hardware structure 1414e23f3336SMark Rustad * @linear: true if SFP module is linear 1415e23f3336SMark Rustad */ 1416e23f3336SMark Rustad static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) 1417e23f3336SMark Rustad { 1418e23f3336SMark Rustad switch (hw->phy.sfp_type) { 1419e23f3336SMark Rustad case ixgbe_sfp_type_not_present: 1420e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_PRESENT; 1421e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core0: 1422e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core1: 1423e23f3336SMark Rustad *linear = true; 1424e23f3336SMark Rustad break; 1425e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core0: 1426e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core1: 1427e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core0: 1428e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core1: 1429e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core0: 1430e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core1: 1431e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core0: 1432e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core1: 1433e23f3336SMark Rustad *linear = false; 1434e23f3336SMark Rustad break; 1435e23f3336SMark Rustad case ixgbe_sfp_type_unknown: 1436e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core0: 1437e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core1: 1438e23f3336SMark Rustad default: 1439e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_SUPPORTED; 1440e23f3336SMark Rustad } 1441e23f3336SMark Rustad 1442e23f3336SMark Rustad return 0; 1443e23f3336SMark Rustad } 1444e23f3336SMark Rustad 1445e23f3336SMark Rustad /** 14466d373a1bSMark Rustad * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. 14476d373a1bSMark Rustad * @hw: pointer to hardware structure 14486d373a1bSMark Rustad * 14496d373a1bSMark Rustad * Configures the extern PHY and the integrated KR PHY for SFP support. 14506d373a1bSMark Rustad */ 14516d373a1bSMark Rustad static s32 14526d373a1bSMark Rustad ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, 14536d373a1bSMark Rustad ixgbe_link_speed speed, 14546d373a1bSMark Rustad __always_unused bool autoneg_wait_to_complete) 14556d373a1bSMark Rustad { 1456e23f3336SMark Rustad s32 status; 1457812d7dffSEmil Tantilov u16 reg_slice, reg_val; 1458e23f3336SMark Rustad bool setup_linear = false; 1459e23f3336SMark Rustad 1460e23f3336SMark Rustad /* Check if SFP module is supported and linear */ 1461e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 1462e23f3336SMark Rustad 1463e23f3336SMark Rustad /* If no SFP module present, then return success. Return success since 1464e23f3336SMark Rustad * there is no reason to configure CS4227 and SFP not present error is 1465e23f3336SMark Rustad * not accepted in the setup MAC link flow. 1466e23f3336SMark Rustad */ 1467e23f3336SMark Rustad if (status == IXGBE_ERR_SFP_NOT_PRESENT) 1468e23f3336SMark Rustad return 0; 1469e23f3336SMark Rustad 1470e23f3336SMark Rustad if (status) 1471e23f3336SMark Rustad return status; 1472e23f3336SMark Rustad 1473d91e3a7dSMark Rustad /* Configure internal PHY for KR/KX. */ 1474812d7dffSEmil Tantilov ixgbe_setup_kr_speed_x550em(hw, speed); 1475e23f3336SMark Rustad 1476d91e3a7dSMark Rustad /* Configure CS4227 LINE side to proper mode. */ 1477812d7dffSEmil Tantilov reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 1478d91e3a7dSMark Rustad if (setup_linear) 1479812d7dffSEmil Tantilov reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; 1480d91e3a7dSMark Rustad else 1481812d7dffSEmil Tantilov reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; 1482b71f6c40SEmil Tantilov 1483b71f6c40SEmil Tantilov status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, 1484b71f6c40SEmil Tantilov reg_val); 1485b71f6c40SEmil Tantilov 1486e23f3336SMark Rustad return status; 14876d373a1bSMark Rustad } 14886d373a1bSMark Rustad 14896d373a1bSMark Rustad /** 1490470739b5SDon Skidmore * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode 1491470739b5SDon Skidmore * @hw: pointer to hardware structure 1492470739b5SDon Skidmore * @speed: the link speed to force 1493470739b5SDon Skidmore * 1494470739b5SDon Skidmore * Configures the integrated PHY for native SFI mode. Used to connect the 1495470739b5SDon Skidmore * internal PHY directly to an SFP cage, without autonegotiation. 1496470739b5SDon Skidmore **/ 1497470739b5SDon Skidmore static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 1498470739b5SDon Skidmore { 1499470739b5SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 1500470739b5SDon Skidmore s32 status; 1501470739b5SDon Skidmore u32 reg_val; 1502470739b5SDon Skidmore 1503470739b5SDon Skidmore /* Disable all AN and force speed to 10G Serial. */ 1504470739b5SDon Skidmore status = mac->ops.read_iosf_sb_reg(hw, 1505470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1506470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 1507470739b5SDon Skidmore if (status) 1508470739b5SDon Skidmore return status; 1509470739b5SDon Skidmore 1510470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 1511470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 1512470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 1513470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 1514470739b5SDon Skidmore 1515470739b5SDon Skidmore /* Select forced link speed for internal PHY. */ 1516470739b5SDon Skidmore switch (*speed) { 1517470739b5SDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 1518470739b5SDon Skidmore reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G; 1519470739b5SDon Skidmore break; 1520470739b5SDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 1521470739b5SDon Skidmore reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; 1522470739b5SDon Skidmore break; 1523470739b5SDon Skidmore default: 1524470739b5SDon Skidmore /* Other link speeds are not supported by internal PHY. */ 1525470739b5SDon Skidmore return IXGBE_ERR_LINK_SETUP; 1526470739b5SDon Skidmore } 1527470739b5SDon Skidmore 1528470739b5SDon Skidmore status = mac->ops.write_iosf_sb_reg(hw, 1529470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1530470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 1531470739b5SDon Skidmore 1532470739b5SDon Skidmore /* Toggle port SW reset by AN reset. */ 1533470739b5SDon Skidmore status = ixgbe_restart_an_internal_phy_x550em(hw); 1534470739b5SDon Skidmore 1535470739b5SDon Skidmore return status; 1536470739b5SDon Skidmore } 1537470739b5SDon Skidmore 1538470739b5SDon Skidmore /** 15392d40cd17SMark Rustad * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP 15402d40cd17SMark Rustad * @hw: pointer to hardware structure 15412d40cd17SMark Rustad * 15422d40cd17SMark Rustad * Configure the the integrated PHY for native SFP support. 15432d40cd17SMark Rustad */ 15442d40cd17SMark Rustad static s32 15452d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, 15462d40cd17SMark Rustad __always_unused bool autoneg_wait_to_complete) 15472d40cd17SMark Rustad { 15482d40cd17SMark Rustad bool setup_linear = false; 15492d40cd17SMark Rustad u32 reg_phy_int; 1550470739b5SDon Skidmore s32 ret_val; 15512d40cd17SMark Rustad 15522d40cd17SMark Rustad /* Check if SFP module is supported and linear */ 1553470739b5SDon Skidmore ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 15542d40cd17SMark Rustad 15552d40cd17SMark Rustad /* If no SFP module present, then return success. Return success since 15562d40cd17SMark Rustad * SFP not present error is not excepted in the setup MAC link flow. 15572d40cd17SMark Rustad */ 1558470739b5SDon Skidmore if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) 15592d40cd17SMark Rustad return 0; 15602d40cd17SMark Rustad 1561470739b5SDon Skidmore if (!ret_val) 1562470739b5SDon Skidmore return ret_val; 15632d40cd17SMark Rustad 1564470739b5SDon Skidmore /* Configure internal PHY for native SFI based on module type */ 1565470739b5SDon Skidmore ret_val = hw->mac.ops.read_iosf_sb_reg(hw, 1566470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1567470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int); 1568470739b5SDon Skidmore if (!ret_val) 1569470739b5SDon Skidmore return ret_val; 15702d40cd17SMark Rustad 1571470739b5SDon Skidmore reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA; 1572470739b5SDon Skidmore if (!setup_linear) 1573470739b5SDon Skidmore reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR; 15742d40cd17SMark Rustad 1575470739b5SDon Skidmore ret_val = hw->mac.ops.write_iosf_sb_reg(hw, 1576470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1577470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int); 1578470739b5SDon Skidmore if (!ret_val) 1579470739b5SDon Skidmore return ret_val; 15802d40cd17SMark Rustad 1581470739b5SDon Skidmore /* Setup SFI internal link. */ 1582470739b5SDon Skidmore return ixgbe_setup_sfi_x550a(hw, &speed); 15832d40cd17SMark Rustad } 15842d40cd17SMark Rustad 15852d40cd17SMark Rustad /** 15862d40cd17SMark Rustad * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP 15872d40cd17SMark Rustad * @hw: pointer to hardware structure 15882d40cd17SMark Rustad * 15892d40cd17SMark Rustad * Configure the the integrated PHY for SFP support. 15902d40cd17SMark Rustad */ 15912d40cd17SMark Rustad static s32 15922d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, 15932d40cd17SMark Rustad __always_unused bool autoneg_wait_to_complete) 15942d40cd17SMark Rustad { 15952d40cd17SMark Rustad u32 reg_slice, slice_offset; 15962d40cd17SMark Rustad bool setup_linear = false; 15972d40cd17SMark Rustad u16 reg_phy_ext; 1598470739b5SDon Skidmore s32 ret_val; 15992d40cd17SMark Rustad 16002d40cd17SMark Rustad /* Check if SFP module is supported and linear */ 1601470739b5SDon Skidmore ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 16022d40cd17SMark Rustad 16032d40cd17SMark Rustad /* If no SFP module present, then return success. Return success since 16042d40cd17SMark Rustad * SFP not present error is not excepted in the setup MAC link flow. 16052d40cd17SMark Rustad */ 1606470739b5SDon Skidmore if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) 16072d40cd17SMark Rustad return 0; 16082d40cd17SMark Rustad 1609470739b5SDon Skidmore if (!ret_val) 1610470739b5SDon Skidmore return ret_val; 16112d40cd17SMark Rustad 16122d40cd17SMark Rustad /* Configure internal PHY for KR/KX. */ 16132d40cd17SMark Rustad ixgbe_setup_kr_speed_x550em(hw, speed); 16142d40cd17SMark Rustad 16157564a888SMark Rustad if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE) 16162d40cd17SMark Rustad return IXGBE_ERR_PHY_ADDR_INVALID; 16172d40cd17SMark Rustad 16182d40cd17SMark Rustad /* Get external PHY device id */ 1619470739b5SDon Skidmore ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, 16202d40cd17SMark Rustad IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 1621470739b5SDon Skidmore if (ret_val) 1622470739b5SDon Skidmore return ret_val; 16232d40cd17SMark Rustad 16242d40cd17SMark Rustad /* When configuring quad port CS4223, the MAC instance is part 16252d40cd17SMark Rustad * of the slice offset. 16262d40cd17SMark Rustad */ 16272d40cd17SMark Rustad if (reg_phy_ext == IXGBE_CS4223_PHY_ID) 16282d40cd17SMark Rustad slice_offset = (hw->bus.lan_id + 16292d40cd17SMark Rustad (hw->bus.instance_id << 1)) << 12; 16302d40cd17SMark Rustad else 16312d40cd17SMark Rustad slice_offset = hw->bus.lan_id << 12; 16322d40cd17SMark Rustad 16332d40cd17SMark Rustad /* Configure CS4227/CS4223 LINE side to proper mode. */ 16342d40cd17SMark Rustad reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; 16352d40cd17SMark Rustad if (setup_linear) 16362d40cd17SMark Rustad reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 16372d40cd17SMark Rustad else 16382d40cd17SMark Rustad reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 16392d40cd17SMark Rustad return hw->phy.ops.write_reg(hw, reg_slice, IXGBE_MDIO_ZERO_DEV_TYPE, 16402d40cd17SMark Rustad reg_phy_ext); 16412d40cd17SMark Rustad } 16422d40cd17SMark Rustad 16432d40cd17SMark Rustad /** 1644c3dc4c09SDon Skidmore * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 1645c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1646c3dc4c09SDon Skidmore * @speed: new link speed 1647c3dc4c09SDon Skidmore * @autoneg_wait_to_complete: true when waiting for completion is needed 1648c3dc4c09SDon Skidmore * 1649c3dc4c09SDon Skidmore * Setup internal/external PHY link speed based on link speed, then set 1650c3dc4c09SDon Skidmore * external PHY auto advertised link speed. 1651c3dc4c09SDon Skidmore * 1652c3dc4c09SDon Skidmore * Returns error status for any failure 1653c3dc4c09SDon Skidmore **/ 1654c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 1655c3dc4c09SDon Skidmore ixgbe_link_speed speed, 1656c3dc4c09SDon Skidmore bool autoneg_wait) 1657c3dc4c09SDon Skidmore { 1658c3dc4c09SDon Skidmore s32 status; 1659c3dc4c09SDon Skidmore ixgbe_link_speed force_speed; 1660c3dc4c09SDon Skidmore 1661c3dc4c09SDon Skidmore /* Setup internal/external PHY link speed to iXFI (10G), unless 1662c3dc4c09SDon Skidmore * only 1G is auto advertised then setup KX link. 1663c3dc4c09SDon Skidmore */ 1664c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1665c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 1666c3dc4c09SDon Skidmore else 1667c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 1668c3dc4c09SDon Skidmore 1669c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup XFI internal link. */ 1670c3dc4c09SDon Skidmore if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1671c3dc4c09SDon Skidmore status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 1672c3dc4c09SDon Skidmore 1673c3dc4c09SDon Skidmore if (status) 1674c3dc4c09SDon Skidmore return status; 1675c3dc4c09SDon Skidmore } 1676c3dc4c09SDon Skidmore 1677c3dc4c09SDon Skidmore return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 1678c3dc4c09SDon Skidmore } 1679c3dc4c09SDon Skidmore 1680a4e293a5SDon Skidmore /** ixgbe_check_link_t_X550em - Determine link and speed status 1681a4e293a5SDon Skidmore * @hw: pointer to hardware structure 1682a4e293a5SDon Skidmore * @speed: pointer to link speed 1683a4e293a5SDon Skidmore * @link_up: true when link is up 1684a4e293a5SDon Skidmore * @link_up_wait_to_complete: bool used to wait for link up or not 1685a4e293a5SDon Skidmore * 1686a4e293a5SDon Skidmore * Check that both the MAC and X557 external PHY have link. 1687a4e293a5SDon Skidmore **/ 1688a4e293a5SDon Skidmore static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, 1689a4e293a5SDon Skidmore ixgbe_link_speed *speed, 1690a4e293a5SDon Skidmore bool *link_up, 1691a4e293a5SDon Skidmore bool link_up_wait_to_complete) 1692a4e293a5SDon Skidmore { 1693a4e293a5SDon Skidmore u32 status; 169421d882ebSEmil Tantilov u16 i, autoneg_status; 1695a4e293a5SDon Skidmore 1696a4e293a5SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 1697a4e293a5SDon Skidmore return IXGBE_ERR_CONFIG; 1698a4e293a5SDon Skidmore 1699a4e293a5SDon Skidmore status = ixgbe_check_mac_link_generic(hw, speed, link_up, 1700a4e293a5SDon Skidmore link_up_wait_to_complete); 1701a4e293a5SDon Skidmore 1702a4e293a5SDon Skidmore /* If check link fails or MAC link is not up, then return */ 1703a4e293a5SDon Skidmore if (status || !(*link_up)) 1704a4e293a5SDon Skidmore return status; 1705a4e293a5SDon Skidmore 1706a4e293a5SDon Skidmore /* MAC link is up, so check external PHY link. 170721d882ebSEmil Tantilov * Link status is latching low, and can only be used to detect link 170821d882ebSEmil Tantilov * drop, and not the current status of the link without performing 170921d882ebSEmil Tantilov * back-to-back reads. 1710a4e293a5SDon Skidmore */ 171121d882ebSEmil Tantilov for (i = 0; i < 2; i++) { 17124dc4000bSEmil Tantilov status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 1713a4e293a5SDon Skidmore &autoneg_status); 171421d882ebSEmil Tantilov 1715a4e293a5SDon Skidmore if (status) 1716a4e293a5SDon Skidmore return status; 171721d882ebSEmil Tantilov } 1718a4e293a5SDon Skidmore 1719a4e293a5SDon Skidmore /* If external PHY link is not up, then indicate link not up */ 1720a4e293a5SDon Skidmore if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 1721a4e293a5SDon Skidmore *link_up = false; 1722a4e293a5SDon Skidmore 1723a4e293a5SDon Skidmore return 0; 1724a4e293a5SDon Skidmore } 1725a4e293a5SDon Skidmore 1726200157c2SMark Rustad /** 1727200157c2SMark Rustad * ixgbe_setup_sgmii - Set up link for sgmii 1728200157c2SMark Rustad * @hw: pointer to hardware structure 1729200157c2SMark Rustad */ 1730200157c2SMark Rustad static s32 1731200157c2SMark Rustad ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, 1732200157c2SMark Rustad __always_unused bool autoneg_wait_to_complete) 1733200157c2SMark Rustad { 1734200157c2SMark Rustad struct ixgbe_mac_info *mac = &hw->mac; 1735470739b5SDon Skidmore u32 lval, sval, flx_val; 1736200157c2SMark Rustad s32 rc; 1737200157c2SMark Rustad 1738200157c2SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 1739200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1740200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 1741200157c2SMark Rustad if (rc) 1742200157c2SMark Rustad return rc; 1743200157c2SMark Rustad 1744200157c2SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1745200157c2SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 1746200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 1747200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 1748200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 1749200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1750200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1751200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1752200157c2SMark Rustad if (rc) 1753200157c2SMark Rustad return rc; 1754200157c2SMark Rustad 1755200157c2SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 1756200157c2SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1757200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 1758200157c2SMark Rustad if (rc) 1759200157c2SMark Rustad return rc; 1760200157c2SMark Rustad 1761200157c2SMark Rustad sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 1762200157c2SMark Rustad sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 1763200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1764200157c2SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1765200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 1766200157c2SMark Rustad if (rc) 1767200157c2SMark Rustad return rc; 1768200157c2SMark Rustad 1769470739b5SDon Skidmore rc = mac->ops.read_iosf_sb_reg(hw, 1770470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1771470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 1772470739b5SDon Skidmore if (rc) 1773470739b5SDon Skidmore return rc; 1774200157c2SMark Rustad 1775470739b5SDon Skidmore rc = mac->ops.read_iosf_sb_reg(hw, 1776470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1777470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 1778470739b5SDon Skidmore if (rc) 1779470739b5SDon Skidmore return rc; 1780470739b5SDon Skidmore 1781470739b5SDon Skidmore flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 1782470739b5SDon Skidmore flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; 1783470739b5SDon Skidmore flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 1784470739b5SDon Skidmore flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 1785470739b5SDon Skidmore flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 1786470739b5SDon Skidmore 1787470739b5SDon Skidmore rc = mac->ops.write_iosf_sb_reg(hw, 1788470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1789470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); 1790470739b5SDon Skidmore if (rc) 1791470739b5SDon Skidmore return rc; 1792470739b5SDon Skidmore 1793470739b5SDon Skidmore rc = ixgbe_restart_an_internal_phy_x550em(hw); 1794200157c2SMark Rustad return rc; 1795200157c2SMark Rustad } 1796200157c2SMark Rustad 17972916500dSDon Skidmore /** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers 17982916500dSDon Skidmore * @hw: pointer to hardware structure 17992916500dSDon Skidmore **/ 18002916500dSDon Skidmore static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw) 18012916500dSDon Skidmore { 18022916500dSDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 18032916500dSDon Skidmore 18042916500dSDon Skidmore switch (mac->ops.get_media_type(hw)) { 18052916500dSDon Skidmore case ixgbe_media_type_fiber: 18062916500dSDon Skidmore mac->ops.setup_fc = NULL; 18072916500dSDon Skidmore mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; 18082916500dSDon Skidmore break; 18092916500dSDon Skidmore case ixgbe_media_type_backplane: 18102916500dSDon Skidmore mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; 18112916500dSDon Skidmore mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; 18122916500dSDon Skidmore break; 18132916500dSDon Skidmore default: 18142916500dSDon Skidmore break; 18152916500dSDon Skidmore } 18162916500dSDon Skidmore } 18172916500dSDon Skidmore 1818c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 1819c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1820c3dc4c09SDon Skidmore **/ 1821c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 1822c3dc4c09SDon Skidmore { 1823c3dc4c09SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 1824c3dc4c09SDon Skidmore 1825abf76d76SEmil Tantilov mac->ops.setup_fc = ixgbe_setup_fc_x550em; 1826abf76d76SEmil Tantilov 1827c3dc4c09SDon Skidmore switch (mac->ops.get_media_type(hw)) { 1828c3dc4c09SDon Skidmore case ixgbe_media_type_fiber: 1829c3dc4c09SDon Skidmore /* CS4227 does not support autoneg, so disable the laser control 1830c3dc4c09SDon Skidmore * functions for SFP+ fiber 1831c3dc4c09SDon Skidmore */ 1832c3dc4c09SDon Skidmore mac->ops.disable_tx_laser = NULL; 1833c3dc4c09SDon Skidmore mac->ops.enable_tx_laser = NULL; 1834c3dc4c09SDon Skidmore mac->ops.flap_tx_laser = NULL; 18356d373a1bSMark Rustad mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; 18362d40cd17SMark Rustad switch (hw->device_id) { 18372d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 18382d40cd17SMark Rustad mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; 18392d40cd17SMark Rustad break; 18402d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 18412d40cd17SMark Rustad mac->ops.setup_mac_link = 18422d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a; 18432d40cd17SMark Rustad break; 18442d40cd17SMark Rustad default: 18452d40cd17SMark Rustad mac->ops.setup_mac_link = 18462d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550em; 18472d40cd17SMark Rustad break; 18482d40cd17SMark Rustad } 18496d373a1bSMark Rustad mac->ops.set_rate_select_speed = 18506d373a1bSMark Rustad ixgbe_set_soft_rate_select_speed; 1851c3dc4c09SDon Skidmore break; 1852c3dc4c09SDon Skidmore case ixgbe_media_type_copper: 1853c3dc4c09SDon Skidmore mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 1854afdc71e4SMark Rustad mac->ops.setup_fc = ixgbe_setup_fc_generic; 1855a4e293a5SDon Skidmore mac->ops.check_link = ixgbe_check_link_t_X550em; 185649425dfcSMark Rustad return; 185749425dfcSMark Rustad case ixgbe_media_type_backplane: 1858200157c2SMark Rustad if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || 1859200157c2SMark Rustad hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) 1860200157c2SMark Rustad mac->ops.setup_link = ixgbe_setup_sgmii; 1861c3dc4c09SDon Skidmore break; 1862c3dc4c09SDon Skidmore default: 1863c3dc4c09SDon Skidmore break; 1864c3dc4c09SDon Skidmore } 18652916500dSDon Skidmore 18662916500dSDon Skidmore /* Additional modification for X550em_a devices */ 18672916500dSDon Skidmore if (hw->mac.type == ixgbe_mac_x550em_a) 18682916500dSDon Skidmore ixgbe_init_mac_link_ops_X550em_a(hw); 1869c3dc4c09SDon Skidmore } 1870c3dc4c09SDon Skidmore 1871c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module 1872c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1873c3dc4c09SDon Skidmore */ 1874c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 1875c3dc4c09SDon Skidmore { 1876e23f3336SMark Rustad s32 status; 1877e23f3336SMark Rustad bool linear; 1878c3dc4c09SDon Skidmore 1879e23f3336SMark Rustad /* Check if SFP module is supported */ 1880e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &linear); 1881e23f3336SMark Rustad if (status) 1882e23f3336SMark Rustad return status; 1883c3dc4c09SDon Skidmore 1884c3dc4c09SDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 1885c3dc4c09SDon Skidmore hw->phy.ops.reset = NULL; 1886c3dc4c09SDon Skidmore 1887e23f3336SMark Rustad return 0; 1888c3dc4c09SDon Skidmore } 1889c3dc4c09SDon Skidmore 1890c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities 1891c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1892c3dc4c09SDon Skidmore * @speed: pointer to link speed 1893c3dc4c09SDon Skidmore * @autoneg: true when autoneg or autotry is enabled 1894c3dc4c09SDon Skidmore **/ 1895c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 1896c3dc4c09SDon Skidmore ixgbe_link_speed *speed, 1897c3dc4c09SDon Skidmore bool *autoneg) 1898c3dc4c09SDon Skidmore { 1899c3dc4c09SDon Skidmore /* SFP */ 1900c3dc4c09SDon Skidmore if (hw->phy.media_type == ixgbe_media_type_fiber) { 1901c3dc4c09SDon Skidmore /* CS4227 SFP must not enable auto-negotiation */ 1902c3dc4c09SDon Skidmore *autoneg = false; 1903c3dc4c09SDon Skidmore 1904c3dc4c09SDon Skidmore if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 1905c3dc4c09SDon Skidmore hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { 1906c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 1907c3dc4c09SDon Skidmore return 0; 1908c3dc4c09SDon Skidmore } 1909c3dc4c09SDon Skidmore 1910c3dc4c09SDon Skidmore /* Link capabilities are based on SFP */ 1911c3dc4c09SDon Skidmore if (hw->phy.multispeed_fiber) 1912c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1913c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1914c3dc4c09SDon Skidmore else 1915c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL; 1916c3dc4c09SDon Skidmore } else { 1917c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1918c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1919c3dc4c09SDon Skidmore *autoneg = true; 1920c3dc4c09SDon Skidmore } 1921c3dc4c09SDon Skidmore return 0; 1922c3dc4c09SDon Skidmore } 1923c3dc4c09SDon Skidmore 1924c3dc4c09SDon Skidmore /** 1925c3dc4c09SDon Skidmore * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause 1926c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1927c3dc4c09SDon Skidmore * @lsc: pointer to boolean flag which indicates whether external Base T 1928c3dc4c09SDon Skidmore * PHY interrupt is lsc 1929c3dc4c09SDon Skidmore * 1930c3dc4c09SDon Skidmore * Determime if external Base T PHY interrupt cause is high temperature 1931c3dc4c09SDon Skidmore * failure alarm or link status change. 1932c3dc4c09SDon Skidmore * 1933c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1934c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1935c3dc4c09SDon Skidmore **/ 1936c3dc4c09SDon Skidmore static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) 1937c3dc4c09SDon Skidmore { 1938c3dc4c09SDon Skidmore u32 status; 1939c3dc4c09SDon Skidmore u16 reg; 1940c3dc4c09SDon Skidmore 1941c3dc4c09SDon Skidmore *lsc = false; 1942c3dc4c09SDon Skidmore 1943c3dc4c09SDon Skidmore /* Vendor alarm triggered */ 1944c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 19454dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1946c3dc4c09SDon Skidmore ®); 1947c3dc4c09SDon Skidmore 1948c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 1949c3dc4c09SDon Skidmore return status; 1950c3dc4c09SDon Skidmore 1951c3dc4c09SDon Skidmore /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 1952c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 19534dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1954c3dc4c09SDon Skidmore ®); 1955c3dc4c09SDon Skidmore 1956c3dc4c09SDon Skidmore if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1957c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 1958c3dc4c09SDon Skidmore return status; 1959c3dc4c09SDon Skidmore 196083a9fb20SMark Rustad /* Global alarm triggered */ 1961c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 19624dc4000bSEmil Tantilov MDIO_MMD_VEND1, 1963c3dc4c09SDon Skidmore ®); 1964c3dc4c09SDon Skidmore 1965c3dc4c09SDon Skidmore if (status) 1966c3dc4c09SDon Skidmore return status; 1967c3dc4c09SDon Skidmore 1968c3dc4c09SDon Skidmore /* If high temperature failure, then return over temp error and exit */ 1969c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 1970c3dc4c09SDon Skidmore /* power down the PHY in case the PHY FW didn't already */ 1971c3dc4c09SDon Skidmore ixgbe_set_copper_phy_power(hw, false); 1972c3dc4c09SDon Skidmore return IXGBE_ERR_OVERTEMP; 1973c3dc4c09SDon Skidmore } 197483a9fb20SMark Rustad if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { 197583a9fb20SMark Rustad /* device fault alarm triggered */ 197683a9fb20SMark Rustad status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, 19774dc4000bSEmil Tantilov MDIO_MMD_VEND1, 197883a9fb20SMark Rustad ®); 197983a9fb20SMark Rustad if (status) 198083a9fb20SMark Rustad return status; 198183a9fb20SMark Rustad 198283a9fb20SMark Rustad /* if device fault was due to high temp alarm handle and exit */ 198383a9fb20SMark Rustad if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { 198483a9fb20SMark Rustad /* power down the PHY in case the PHY FW didn't */ 198583a9fb20SMark Rustad ixgbe_set_copper_phy_power(hw, false); 198683a9fb20SMark Rustad return IXGBE_ERR_OVERTEMP; 198783a9fb20SMark Rustad } 198883a9fb20SMark Rustad } 1989c3dc4c09SDon Skidmore 1990c3dc4c09SDon Skidmore /* Vendor alarm 2 triggered */ 1991c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 19924dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 1993c3dc4c09SDon Skidmore 1994c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 1995c3dc4c09SDon Skidmore return status; 1996c3dc4c09SDon Skidmore 1997c3dc4c09SDon Skidmore /* link connect/disconnect event occurred */ 1998c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 19994dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 2000c3dc4c09SDon Skidmore 2001c3dc4c09SDon Skidmore if (status) 2002c3dc4c09SDon Skidmore return status; 2003c3dc4c09SDon Skidmore 2004c3dc4c09SDon Skidmore /* Indicate LSC */ 2005c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 2006c3dc4c09SDon Skidmore *lsc = true; 2007c3dc4c09SDon Skidmore 2008c3dc4c09SDon Skidmore return 0; 2009c3dc4c09SDon Skidmore } 2010c3dc4c09SDon Skidmore 2011c3dc4c09SDon Skidmore /** 2012c3dc4c09SDon Skidmore * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 2013c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 2014c3dc4c09SDon Skidmore * 2015c3dc4c09SDon Skidmore * Enable link status change and temperature failure alarm for the external 2016c3dc4c09SDon Skidmore * Base T PHY 2017c3dc4c09SDon Skidmore * 2018c3dc4c09SDon Skidmore * Returns PHY access status 2019c3dc4c09SDon Skidmore **/ 2020c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 2021c3dc4c09SDon Skidmore { 2022c3dc4c09SDon Skidmore u32 status; 2023c3dc4c09SDon Skidmore u16 reg; 2024c3dc4c09SDon Skidmore bool lsc; 2025c3dc4c09SDon Skidmore 2026c3dc4c09SDon Skidmore /* Clear interrupt flags */ 2027c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 2028c3dc4c09SDon Skidmore 2029c3dc4c09SDon Skidmore /* Enable link status change alarm */ 2030c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 20314dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 2032c3dc4c09SDon Skidmore if (status) 2033c3dc4c09SDon Skidmore return status; 2034c3dc4c09SDon Skidmore 2035c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 2036c3dc4c09SDon Skidmore 2037c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 20384dc4000bSEmil Tantilov MDIO_MMD_AN, reg); 2039c3dc4c09SDon Skidmore if (status) 2040c3dc4c09SDon Skidmore return status; 2041c3dc4c09SDon Skidmore 204283a9fb20SMark Rustad /* Enable high temperature failure and global fault alarms */ 2043c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 20444dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2045c3dc4c09SDon Skidmore ®); 2046c3dc4c09SDon Skidmore if (status) 2047c3dc4c09SDon Skidmore return status; 2048c3dc4c09SDon Skidmore 204983a9fb20SMark Rustad reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | 205083a9fb20SMark Rustad IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); 2051c3dc4c09SDon Skidmore 2052c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 20534dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2054c3dc4c09SDon Skidmore reg); 2055c3dc4c09SDon Skidmore if (status) 2056c3dc4c09SDon Skidmore return status; 2057c3dc4c09SDon Skidmore 2058c3dc4c09SDon Skidmore /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 2059c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 20604dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2061c3dc4c09SDon Skidmore ®); 2062c3dc4c09SDon Skidmore if (status) 2063c3dc4c09SDon Skidmore return status; 2064c3dc4c09SDon Skidmore 2065c3dc4c09SDon Skidmore reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 2066c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT); 2067c3dc4c09SDon Skidmore 2068c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 20694dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2070c3dc4c09SDon Skidmore reg); 2071c3dc4c09SDon Skidmore if (status) 2072c3dc4c09SDon Skidmore return status; 2073c3dc4c09SDon Skidmore 2074c3dc4c09SDon Skidmore /* Enable chip-wide vendor alarm */ 2075c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 20764dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2077c3dc4c09SDon Skidmore ®); 2078c3dc4c09SDon Skidmore if (status) 2079c3dc4c09SDon Skidmore return status; 2080c3dc4c09SDon Skidmore 2081c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 2082c3dc4c09SDon Skidmore 2083c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 20844dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2085c3dc4c09SDon Skidmore reg); 2086c3dc4c09SDon Skidmore 2087c3dc4c09SDon Skidmore return status; 2088c3dc4c09SDon Skidmore } 2089c3dc4c09SDon Skidmore 2090c3dc4c09SDon Skidmore /** 2091c3dc4c09SDon Skidmore * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 2092c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 2093c3dc4c09SDon Skidmore * 2094c3dc4c09SDon Skidmore * Handle external Base T PHY interrupt. If high temperature 2095c3dc4c09SDon Skidmore * failure alarm then return error, else if link status change 2096c3dc4c09SDon Skidmore * then setup internal/external PHY link 2097c3dc4c09SDon Skidmore * 2098c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 2099c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 2100c3dc4c09SDon Skidmore **/ 2101c3dc4c09SDon Skidmore static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) 2102c3dc4c09SDon Skidmore { 2103c3dc4c09SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 2104c3dc4c09SDon Skidmore bool lsc; 2105c3dc4c09SDon Skidmore u32 status; 2106c3dc4c09SDon Skidmore 2107c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 2108c3dc4c09SDon Skidmore if (status) 2109c3dc4c09SDon Skidmore return status; 2110c3dc4c09SDon Skidmore 2111a85ce532SMark Rustad if (lsc && phy->ops.setup_internal_link) 2112c3dc4c09SDon Skidmore return phy->ops.setup_internal_link(hw); 2113c3dc4c09SDon Skidmore 2114c3dc4c09SDon Skidmore return 0; 2115c3dc4c09SDon Skidmore } 2116c3dc4c09SDon Skidmore 2117c3dc4c09SDon Skidmore /** 2118c3dc4c09SDon Skidmore * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 2119c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 2120c3dc4c09SDon Skidmore * @speed: link speed 2121c3dc4c09SDon Skidmore * 2122c3dc4c09SDon Skidmore * Configures the integrated KR PHY. 2123c3dc4c09SDon Skidmore **/ 2124c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 2125c3dc4c09SDon Skidmore ixgbe_link_speed speed) 2126c3dc4c09SDon Skidmore { 2127c3dc4c09SDon Skidmore s32 status; 2128c3dc4c09SDon Skidmore u32 reg_val; 2129c3dc4c09SDon Skidmore 21309a5c27e6SMark Rustad status = hw->mac.ops.read_iosf_sb_reg(hw, 2131c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2132c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2133c3dc4c09SDon Skidmore if (status) 2134c3dc4c09SDon Skidmore return status; 2135c3dc4c09SDon Skidmore 2136c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 2137c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 2138c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 2139c3dc4c09SDon Skidmore 2140c3dc4c09SDon Skidmore /* Advertise 10G support. */ 2141c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 2142c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 2143c3dc4c09SDon Skidmore 2144c3dc4c09SDon Skidmore /* Advertise 1G support. */ 2145c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_1GB_FULL) 2146c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 2147c3dc4c09SDon Skidmore 21489a5c27e6SMark Rustad status = hw->mac.ops.write_iosf_sb_reg(hw, 2149c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2150c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2151c3dc4c09SDon Skidmore 2152470739b5SDon Skidmore if (hw->mac.type == ixgbe_mac_x550em_a) { 2153470739b5SDon Skidmore /* Set lane mode to KR auto negotiation */ 2154470739b5SDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 2155470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2156470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2157470739b5SDon Skidmore 2158470739b5SDon Skidmore if (status) 2159c3dc4c09SDon Skidmore return status; 2160470739b5SDon Skidmore 2161470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 2162470739b5SDon Skidmore reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; 2163470739b5SDon Skidmore reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 2164470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 2165470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 2166470739b5SDon Skidmore 2167470739b5SDon Skidmore status = hw->mac.ops.write_iosf_sb_reg(hw, 2168470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2169470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2170470739b5SDon Skidmore } 2171470739b5SDon Skidmore 2172470739b5SDon Skidmore return ixgbe_restart_an_internal_phy_x550em(hw); 2173c3dc4c09SDon Skidmore } 2174c3dc4c09SDon Skidmore 21756a14ee0cSDon Skidmore /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. 21766a14ee0cSDon Skidmore * @hw: pointer to hardware structure 21776a14ee0cSDon Skidmore * 21786a14ee0cSDon Skidmore * Configures the integrated KX4 PHY. 21796a14ee0cSDon Skidmore **/ 21807ddbde3fSDon Skidmore static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) 21816a14ee0cSDon Skidmore { 21826a14ee0cSDon Skidmore s32 status; 21836a14ee0cSDon Skidmore u32 reg_val; 21846a14ee0cSDon Skidmore 21859a5c27e6SMark Rustad status = hw->mac.ops.read_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, 21866a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 21876a14ee0cSDon Skidmore hw->bus.lan_id, ®_val); 21886a14ee0cSDon Skidmore if (status) 21896a14ee0cSDon Skidmore return status; 21906a14ee0cSDon Skidmore 21916a14ee0cSDon Skidmore reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | 21926a14ee0cSDon Skidmore IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); 21936a14ee0cSDon Skidmore 21946a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; 21956a14ee0cSDon Skidmore 21966a14ee0cSDon Skidmore /* Advertise 10G support. */ 21976a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) 21986a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; 21996a14ee0cSDon Skidmore 22006a14ee0cSDon Skidmore /* Advertise 1G support. */ 22016a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) 22026a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; 22036a14ee0cSDon Skidmore 22046a14ee0cSDon Skidmore /* Restart auto-negotiation. */ 22056a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; 22069a5c27e6SMark Rustad status = hw->mac.ops.write_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, 22076a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 22086a14ee0cSDon Skidmore hw->bus.lan_id, reg_val); 22096a14ee0cSDon Skidmore 22106a14ee0cSDon Skidmore return status; 22116a14ee0cSDon Skidmore } 22126a14ee0cSDon Skidmore 2213f572b2c4SMark Rustad /** 2214f572b2c4SMark Rustad * ixgbe_setup_kr_x550em - Configure the KR PHY 22156a14ee0cSDon Skidmore * @hw: pointer to hardware structure 22166a14ee0cSDon Skidmore **/ 22177ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 22186a14ee0cSDon Skidmore { 221954f6d4c4SDon Skidmore /* leave link alone for 2.5G */ 222054f6d4c4SDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) 2221f572b2c4SMark Rustad return 0; 2222f572b2c4SMark Rustad 2223c3dc4c09SDon Skidmore return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 22246a14ee0cSDon Skidmore } 22256a14ee0cSDon Skidmore 2226c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 2227c3dc4c09SDon Skidmore * @hw: address of hardware structure 2228c3dc4c09SDon Skidmore * @link_up: address of boolean to indicate link status 2229c3dc4c09SDon Skidmore * 2230c3dc4c09SDon Skidmore * Returns error code if unable to get link status. 2231c3dc4c09SDon Skidmore **/ 2232c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 2233c3dc4c09SDon Skidmore { 2234c3dc4c09SDon Skidmore u32 ret; 2235c3dc4c09SDon Skidmore u16 autoneg_status; 2236c3dc4c09SDon Skidmore 2237c3dc4c09SDon Skidmore *link_up = false; 2238c3dc4c09SDon Skidmore 2239c3dc4c09SDon Skidmore /* read this twice back to back to indicate current status */ 22404dc4000bSEmil Tantilov ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 2241c3dc4c09SDon Skidmore &autoneg_status); 2242c3dc4c09SDon Skidmore if (ret) 2243c3dc4c09SDon Skidmore return ret; 2244c3dc4c09SDon Skidmore 22454dc4000bSEmil Tantilov ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 2246c3dc4c09SDon Skidmore &autoneg_status); 2247c3dc4c09SDon Skidmore if (ret) 2248c3dc4c09SDon Skidmore return ret; 2249c3dc4c09SDon Skidmore 2250c3dc4c09SDon Skidmore *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 2251c3dc4c09SDon Skidmore 2252c3dc4c09SDon Skidmore return 0; 2253c3dc4c09SDon Skidmore } 2254c3dc4c09SDon Skidmore 2255c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 22566a14ee0cSDon Skidmore * @hw: point to hardware structure 22576a14ee0cSDon Skidmore * 2258c3dc4c09SDon Skidmore * Configures the link between the integrated KR PHY and the external X557 PHY 2259c3dc4c09SDon Skidmore * The driver will call this function when it gets a link status change 2260c3dc4c09SDon Skidmore * interrupt from the X557 PHY. This function configures the link speed 2261c3dc4c09SDon Skidmore * between the PHYs to match the link speed of the BASE-T link. 22626a14ee0cSDon Skidmore * 22636a14ee0cSDon Skidmore * A return of a non-zero value indicates an error, and the base driver should 22646a14ee0cSDon Skidmore * not report link up. 22656a14ee0cSDon Skidmore **/ 2266c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 22676a14ee0cSDon Skidmore { 22686a14ee0cSDon Skidmore ixgbe_link_speed force_speed; 2269c3dc4c09SDon Skidmore bool link_up; 2270c3dc4c09SDon Skidmore u32 status; 2271c3dc4c09SDon Skidmore u16 speed; 22726a14ee0cSDon Skidmore 2273c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 2274c3dc4c09SDon Skidmore return IXGBE_ERR_CONFIG; 2275c3dc4c09SDon Skidmore 2276f164b845SMark Rustad if (hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { 2277f164b845SMark Rustad speed = IXGBE_LINK_SPEED_10GB_FULL | 2278f164b845SMark Rustad IXGBE_LINK_SPEED_1GB_FULL; 2279f164b845SMark Rustad return ixgbe_setup_kr_speed_x550em(hw, speed); 2280f164b845SMark Rustad } 2281f164b845SMark Rustad 2282c3dc4c09SDon Skidmore /* If link is not up, then there is no setup necessary so return */ 2283c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 22846a14ee0cSDon Skidmore if (status) 22856a14ee0cSDon Skidmore return status; 22866a14ee0cSDon Skidmore 2287c3dc4c09SDon Skidmore if (!link_up) 22886a14ee0cSDon Skidmore return 0; 22896a14ee0cSDon Skidmore 22906a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 22914dc4000bSEmil Tantilov MDIO_MMD_AN, 22926a14ee0cSDon Skidmore &speed); 2293c3dc4c09SDon Skidmore if (status) 2294c3dc4c09SDon Skidmore return status; 2295c3dc4c09SDon Skidmore 2296c3dc4c09SDon Skidmore /* If link is not still up, then no setup is necessary so return */ 2297c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 2298c3dc4c09SDon Skidmore if (status) 2299c3dc4c09SDon Skidmore return status; 2300c3dc4c09SDon Skidmore 2301c3dc4c09SDon Skidmore if (!link_up) 2302c3dc4c09SDon Skidmore return 0; 23036a14ee0cSDon Skidmore 23046a14ee0cSDon Skidmore /* clear everything but the speed and duplex bits */ 23056a14ee0cSDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 23066a14ee0cSDon Skidmore 23076a14ee0cSDon Skidmore switch (speed) { 23086a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 23096a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 23106a14ee0cSDon Skidmore break; 23116a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 23126a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 23136a14ee0cSDon Skidmore break; 23146a14ee0cSDon Skidmore default: 23156a14ee0cSDon Skidmore /* Internal PHY does not support anything else */ 23166a14ee0cSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 23176a14ee0cSDon Skidmore } 23186a14ee0cSDon Skidmore 23196a14ee0cSDon Skidmore return ixgbe_setup_ixfi_x550em(hw, &force_speed); 23206a14ee0cSDon Skidmore } 23216a14ee0cSDon Skidmore 2322f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 2323f4410d2cSDon Skidmore * @hw: pointer to hardware structure 2324f4410d2cSDon Skidmore **/ 2325f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 2326f4410d2cSDon Skidmore { 2327f4410d2cSDon Skidmore s32 status; 2328f4410d2cSDon Skidmore 2329f4410d2cSDon Skidmore status = ixgbe_reset_phy_generic(hw); 2330f4410d2cSDon Skidmore 2331f4410d2cSDon Skidmore if (status) 2332f4410d2cSDon Skidmore return status; 2333f4410d2cSDon Skidmore 2334f4410d2cSDon Skidmore /* Configure Link Status Alarm and Temperature Threshold interrupts */ 2335f4410d2cSDon Skidmore return ixgbe_enable_lasi_ext_t_x550em(hw); 2336f4410d2cSDon Skidmore } 2337f4410d2cSDon Skidmore 2338a0ad55a3SDon Skidmore /** 2339a0ad55a3SDon Skidmore * ixgbe_led_on_t_x550em - Turns on the software controllable LEDs. 2340a0ad55a3SDon Skidmore * @hw: pointer to hardware structure 2341a0ad55a3SDon Skidmore * @led_idx: led number to turn on 2342a0ad55a3SDon Skidmore **/ 2343d2d43e5bSEmil Tantilov static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 2344a0ad55a3SDon Skidmore { 2345a0ad55a3SDon Skidmore u16 phy_data; 2346a0ad55a3SDon Skidmore 2347a0ad55a3SDon Skidmore if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 2348a0ad55a3SDon Skidmore return IXGBE_ERR_PARAM; 2349a0ad55a3SDon Skidmore 2350a0ad55a3SDon Skidmore /* To turn on the LED, set mode to ON. */ 2351a0ad55a3SDon Skidmore hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 23524dc4000bSEmil Tantilov MDIO_MMD_VEND1, &phy_data); 2353a0ad55a3SDon Skidmore phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; 2354a0ad55a3SDon Skidmore hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 23554dc4000bSEmil Tantilov MDIO_MMD_VEND1, phy_data); 2356a0ad55a3SDon Skidmore 2357a0ad55a3SDon Skidmore return 0; 2358a0ad55a3SDon Skidmore } 2359a0ad55a3SDon Skidmore 2360a0ad55a3SDon Skidmore /** 2361a0ad55a3SDon Skidmore * ixgbe_led_off_t_x550em - Turns off the software controllable LEDs. 2362a0ad55a3SDon Skidmore * @hw: pointer to hardware structure 2363a0ad55a3SDon Skidmore * @led_idx: led number to turn off 2364a0ad55a3SDon Skidmore **/ 2365d2d43e5bSEmil Tantilov static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 2366a0ad55a3SDon Skidmore { 2367a0ad55a3SDon Skidmore u16 phy_data; 2368a0ad55a3SDon Skidmore 2369a0ad55a3SDon Skidmore if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 2370a0ad55a3SDon Skidmore return IXGBE_ERR_PARAM; 2371a0ad55a3SDon Skidmore 2372a0ad55a3SDon Skidmore /* To turn on the LED, set mode to ON. */ 2373a0ad55a3SDon Skidmore hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 23744dc4000bSEmil Tantilov MDIO_MMD_VEND1, &phy_data); 2375a0ad55a3SDon Skidmore phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; 2376a0ad55a3SDon Skidmore hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 23774dc4000bSEmil Tantilov MDIO_MMD_VEND1, phy_data); 2378a0ad55a3SDon Skidmore 2379a0ad55a3SDon Skidmore return 0; 2380a0ad55a3SDon Skidmore } 2381a0ad55a3SDon Skidmore 2382cb8e0514STony Nguyen /** 2383cb8e0514STony Nguyen * ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware 2384cb8e0514STony Nguyen * @hw: pointer to the HW structure 2385cb8e0514STony Nguyen * @maj: driver version major number 2386cb8e0514STony Nguyen * @min: driver version minor number 2387cb8e0514STony Nguyen * @build: driver version build number 2388cb8e0514STony Nguyen * @sub: driver version sub build number 2389cb8e0514STony Nguyen * @len: length of driver_ver string 2390cb8e0514STony Nguyen * @driver_ver: driver string 2391cb8e0514STony Nguyen * 2392cb8e0514STony Nguyen * Sends driver version number to firmware through the manageability 2393cb8e0514STony Nguyen * block. On success return 0 2394cb8e0514STony Nguyen * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring 2395cb8e0514STony Nguyen * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 2396cb8e0514STony Nguyen **/ 2397cb8e0514STony Nguyen static s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min, 2398cb8e0514STony Nguyen u8 build, u8 sub, u16 len, 2399cb8e0514STony Nguyen const char *driver_ver) 2400cb8e0514STony Nguyen { 2401cb8e0514STony Nguyen struct ixgbe_hic_drv_info2 fw_cmd; 2402cb8e0514STony Nguyen s32 ret_val; 2403cb8e0514STony Nguyen int i; 2404cb8e0514STony Nguyen 2405cb8e0514STony Nguyen if (!len || !driver_ver || (len > sizeof(fw_cmd.driver_string))) 2406cb8e0514STony Nguyen return IXGBE_ERR_INVALID_ARGUMENT; 2407cb8e0514STony Nguyen 2408cb8e0514STony Nguyen fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 2409cb8e0514STony Nguyen fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len; 2410cb8e0514STony Nguyen fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 2411cb8e0514STony Nguyen fw_cmd.port_num = (u8)hw->bus.func; 2412cb8e0514STony Nguyen fw_cmd.ver_maj = maj; 2413cb8e0514STony Nguyen fw_cmd.ver_min = min; 2414cb8e0514STony Nguyen fw_cmd.ver_build = build; 2415cb8e0514STony Nguyen fw_cmd.ver_sub = sub; 2416cb8e0514STony Nguyen fw_cmd.hdr.checksum = 0; 2417cb8e0514STony Nguyen memcpy(fw_cmd.driver_string, driver_ver, len); 2418cb8e0514STony Nguyen fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 2419cb8e0514STony Nguyen (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 2420cb8e0514STony Nguyen 2421cb8e0514STony Nguyen for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 2422cb8e0514STony Nguyen ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 2423cb8e0514STony Nguyen sizeof(fw_cmd), 2424cb8e0514STony Nguyen IXGBE_HI_COMMAND_TIMEOUT, 2425cb8e0514STony Nguyen true); 2426cb8e0514STony Nguyen if (ret_val) 2427cb8e0514STony Nguyen continue; 2428cb8e0514STony Nguyen 2429cb8e0514STony Nguyen if (fw_cmd.hdr.cmd_or_resp.ret_status != 2430cb8e0514STony Nguyen FW_CEM_RESP_STATUS_SUCCESS) 2431cb8e0514STony Nguyen return IXGBE_ERR_HOST_INTERFACE_COMMAND; 2432cb8e0514STony Nguyen return 0; 2433cb8e0514STony Nguyen } 2434cb8e0514STony Nguyen 2435cb8e0514STony Nguyen return ret_val; 2436cb8e0514STony Nguyen } 2437cb8e0514STony Nguyen 24386ac74394SDon Skidmore /** ixgbe_get_lcd_x550em - Determine lowest common denominator 24396ac74394SDon Skidmore * @hw: pointer to hardware structure 24406ac74394SDon Skidmore * @lcd_speed: pointer to lowest common link speed 24416ac74394SDon Skidmore * 24426ac74394SDon Skidmore * Determine lowest common link speed with link partner. 24436ac74394SDon Skidmore **/ 24446ac74394SDon Skidmore static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, 24456ac74394SDon Skidmore ixgbe_link_speed *lcd_speed) 24466ac74394SDon Skidmore { 24476ac74394SDon Skidmore u16 an_lp_status; 24486ac74394SDon Skidmore s32 status; 24496ac74394SDon Skidmore u16 word = hw->eeprom.ctrl_word_3; 24506ac74394SDon Skidmore 24516ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; 24526ac74394SDon Skidmore 24536ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, 24544dc4000bSEmil Tantilov MDIO_MMD_AN, 24556ac74394SDon Skidmore &an_lp_status); 24566ac74394SDon Skidmore if (status) 24576ac74394SDon Skidmore return status; 24586ac74394SDon Skidmore 24596ac74394SDon Skidmore /* If link partner advertised 1G, return 1G */ 24606ac74394SDon Skidmore if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { 24616ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; 24626ac74394SDon Skidmore return status; 24636ac74394SDon Skidmore } 24646ac74394SDon Skidmore 24656ac74394SDon Skidmore /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ 24666ac74394SDon Skidmore if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || 24676ac74394SDon Skidmore (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) 24686ac74394SDon Skidmore return status; 24696ac74394SDon Skidmore 24706ac74394SDon Skidmore /* Link partner not capable of lower speeds, return 10G */ 24716ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; 24726ac74394SDon Skidmore return status; 24736ac74394SDon Skidmore } 24746ac74394SDon Skidmore 2475afdc71e4SMark Rustad /** 2476afdc71e4SMark Rustad * ixgbe_setup_fc_x550em - Set up flow control 2477afdc71e4SMark Rustad * @hw: pointer to hardware structure 2478afdc71e4SMark Rustad */ 2479afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) 2480afdc71e4SMark Rustad { 2481afdc71e4SMark Rustad bool pause, asm_dir; 2482afdc71e4SMark Rustad u32 reg_val; 2483afdc71e4SMark Rustad s32 rc; 2484afdc71e4SMark Rustad 2485afdc71e4SMark Rustad /* Validate the requested mode */ 2486afdc71e4SMark Rustad if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 2487afdc71e4SMark Rustad hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 2488afdc71e4SMark Rustad return IXGBE_ERR_INVALID_LINK_SETTINGS; 2489afdc71e4SMark Rustad } 2490afdc71e4SMark Rustad 2491afdc71e4SMark Rustad /* 10gig parts do not have a word in the EEPROM to determine the 2492afdc71e4SMark Rustad * default flow control setting, so we explicitly set it to full. 2493afdc71e4SMark Rustad */ 2494afdc71e4SMark Rustad if (hw->fc.requested_mode == ixgbe_fc_default) 2495afdc71e4SMark Rustad hw->fc.requested_mode = ixgbe_fc_full; 2496afdc71e4SMark Rustad 2497afdc71e4SMark Rustad /* Determine PAUSE and ASM_DIR bits. */ 2498afdc71e4SMark Rustad switch (hw->fc.requested_mode) { 2499afdc71e4SMark Rustad case ixgbe_fc_none: 2500afdc71e4SMark Rustad pause = false; 2501afdc71e4SMark Rustad asm_dir = false; 2502afdc71e4SMark Rustad break; 2503afdc71e4SMark Rustad case ixgbe_fc_tx_pause: 2504afdc71e4SMark Rustad pause = false; 2505afdc71e4SMark Rustad asm_dir = true; 2506afdc71e4SMark Rustad break; 2507afdc71e4SMark Rustad case ixgbe_fc_rx_pause: 2508afdc71e4SMark Rustad /* Rx Flow control is enabled and Tx Flow control is 2509afdc71e4SMark Rustad * disabled by software override. Since there really 2510afdc71e4SMark Rustad * isn't a way to advertise that we are capable of RX 2511afdc71e4SMark Rustad * Pause ONLY, we will advertise that we support both 2512afdc71e4SMark Rustad * symmetric and asymmetric Rx PAUSE, as such we fall 2513afdc71e4SMark Rustad * through to the fc_full statement. Later, we will 2514afdc71e4SMark Rustad * disable the adapter's ability to send PAUSE frames. 2515afdc71e4SMark Rustad */ 2516afdc71e4SMark Rustad /* Fallthrough */ 2517afdc71e4SMark Rustad case ixgbe_fc_full: 2518afdc71e4SMark Rustad pause = true; 2519afdc71e4SMark Rustad asm_dir = true; 2520afdc71e4SMark Rustad break; 2521afdc71e4SMark Rustad default: 2522afdc71e4SMark Rustad hw_err(hw, "Flow control param set incorrectly\n"); 2523afdc71e4SMark Rustad return IXGBE_ERR_CONFIG; 2524afdc71e4SMark Rustad } 2525afdc71e4SMark Rustad 2526f572b2c4SMark Rustad if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR && 2527f572b2c4SMark Rustad hw->device_id != IXGBE_DEV_ID_X550EM_A_KR && 2528f572b2c4SMark Rustad hw->device_id != IXGBE_DEV_ID_X550EM_A_KR_L) 2529afdc71e4SMark Rustad return 0; 2530afdc71e4SMark Rustad 25319a5c27e6SMark Rustad rc = hw->mac.ops.read_iosf_sb_reg(hw, 2532afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 25339a5c27e6SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 25349a5c27e6SMark Rustad ®_val); 2535afdc71e4SMark Rustad if (rc) 2536afdc71e4SMark Rustad return rc; 2537afdc71e4SMark Rustad 2538afdc71e4SMark Rustad reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 2539afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 2540afdc71e4SMark Rustad if (pause) 2541afdc71e4SMark Rustad reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 2542afdc71e4SMark Rustad if (asm_dir) 2543afdc71e4SMark Rustad reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 25449a5c27e6SMark Rustad rc = hw->mac.ops.write_iosf_sb_reg(hw, 2545afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 25469a5c27e6SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 25479a5c27e6SMark Rustad reg_val); 2548afdc71e4SMark Rustad 2549afdc71e4SMark Rustad /* This device does not fully support AN. */ 2550afdc71e4SMark Rustad hw->fc.disable_fc_autoneg = true; 2551afdc71e4SMark Rustad 2552afdc71e4SMark Rustad return rc; 2553afdc71e4SMark Rustad } 2554afdc71e4SMark Rustad 25552916500dSDon Skidmore /** 25562916500dSDon Skidmore * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 25572916500dSDon Skidmore * @hw: pointer to hardware structure 25582916500dSDon Skidmore **/ 25592916500dSDon Skidmore static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) 25602916500dSDon Skidmore { 25612916500dSDon Skidmore u32 link_s1, lp_an_page_low, an_cntl_1; 25622916500dSDon Skidmore s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; 25632916500dSDon Skidmore ixgbe_link_speed speed; 25642916500dSDon Skidmore bool link_up; 25652916500dSDon Skidmore 25662916500dSDon Skidmore /* AN should have completed when the cable was plugged in. 25672916500dSDon Skidmore * Look for reasons to bail out. Bail out if: 25682916500dSDon Skidmore * - FC autoneg is disabled, or if 25692916500dSDon Skidmore * - link is not up. 25702916500dSDon Skidmore */ 25712916500dSDon Skidmore if (hw->fc.disable_fc_autoneg) { 25722916500dSDon Skidmore hw_err(hw, "Flow control autoneg is disabled"); 25732916500dSDon Skidmore goto out; 25742916500dSDon Skidmore } 25752916500dSDon Skidmore 25762916500dSDon Skidmore hw->mac.ops.check_link(hw, &speed, &link_up, false); 25772916500dSDon Skidmore if (!link_up) { 25782916500dSDon Skidmore hw_err(hw, "The link is down"); 25792916500dSDon Skidmore goto out; 25802916500dSDon Skidmore } 25812916500dSDon Skidmore 25822916500dSDon Skidmore /* Check at auto-negotiation has completed */ 25832916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 25842916500dSDon Skidmore IXGBE_KRM_LINK_S1(hw->bus.lan_id), 25852916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); 25862916500dSDon Skidmore 25872916500dSDon Skidmore if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { 25882916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 25892916500dSDon Skidmore status = IXGBE_ERR_FC_NOT_NEGOTIATED; 25902916500dSDon Skidmore goto out; 25912916500dSDon Skidmore } 25922916500dSDon Skidmore 25932916500dSDon Skidmore /* Read the 10g AN autoc and LP ability registers and resolve 25942916500dSDon Skidmore * local flow control settings accordingly 25952916500dSDon Skidmore */ 25962916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 25972916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 25982916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1); 25992916500dSDon Skidmore 26002916500dSDon Skidmore if (status) { 26012916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 26022916500dSDon Skidmore goto out; 26032916500dSDon Skidmore } 26042916500dSDon Skidmore 26052916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 26062916500dSDon Skidmore IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id), 26072916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low); 26082916500dSDon Skidmore 26092916500dSDon Skidmore if (status) { 26102916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 26112916500dSDon Skidmore goto out; 26122916500dSDon Skidmore } 26132916500dSDon Skidmore 26142916500dSDon Skidmore status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low, 26152916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_SYM_PAUSE, 26162916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_ASM_PAUSE, 26172916500dSDon Skidmore IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE, 26182916500dSDon Skidmore IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE); 26192916500dSDon Skidmore 26202916500dSDon Skidmore out: 26212916500dSDon Skidmore if (!status) { 26222916500dSDon Skidmore hw->fc.fc_was_autonegged = true; 26232916500dSDon Skidmore } else { 26242916500dSDon Skidmore hw->fc.fc_was_autonegged = false; 26252916500dSDon Skidmore hw->fc.current_mode = hw->fc.requested_mode; 26262916500dSDon Skidmore } 26272916500dSDon Skidmore } 26282916500dSDon Skidmore 26292916500dSDon Skidmore /** 26302916500dSDon Skidmore * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings 26312916500dSDon Skidmore * @hw: pointer to hardware structure 26322916500dSDon Skidmore **/ 26332916500dSDon Skidmore static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) 26342916500dSDon Skidmore { 26352916500dSDon Skidmore hw->fc.fc_was_autonegged = false; 26362916500dSDon Skidmore hw->fc.current_mode = hw->fc.requested_mode; 26372916500dSDon Skidmore } 26382916500dSDon Skidmore 26396ac74394SDon Skidmore /** ixgbe_enter_lplu_x550em - Transition to low power states 26406ac74394SDon Skidmore * @hw: pointer to hardware structure 26416ac74394SDon Skidmore * 26426ac74394SDon Skidmore * Configures Low Power Link Up on transition to low power states 26436ac74394SDon Skidmore * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting 26446ac74394SDon Skidmore * the X557 PHY immediately prior to entering LPLU. 26456ac74394SDon Skidmore **/ 26466ac74394SDon Skidmore static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) 26476ac74394SDon Skidmore { 26486ac74394SDon Skidmore u16 an_10g_cntl_reg, autoneg_reg, speed; 26496ac74394SDon Skidmore s32 status; 26506ac74394SDon Skidmore ixgbe_link_speed lcd_speed; 26516ac74394SDon Skidmore u32 save_autoneg; 26526ac74394SDon Skidmore bool link_up; 26536ac74394SDon Skidmore 26546ac74394SDon Skidmore /* If blocked by MNG FW, then don't restart AN */ 26556ac74394SDon Skidmore if (ixgbe_check_reset_blocked(hw)) 26566ac74394SDon Skidmore return 0; 26576ac74394SDon Skidmore 26586ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 26596ac74394SDon Skidmore if (status) 26606ac74394SDon Skidmore return status; 26616ac74394SDon Skidmore 26626ac74394SDon Skidmore status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, 26636ac74394SDon Skidmore &hw->eeprom.ctrl_word_3); 26646ac74394SDon Skidmore if (status) 26656ac74394SDon Skidmore return status; 26666ac74394SDon Skidmore 26676ac74394SDon Skidmore /* If link is down, LPLU disabled in NVM, WoL disabled, or 26686ac74394SDon Skidmore * manageability disabled, then force link down by entering 26696ac74394SDon Skidmore * low power mode. 26706ac74394SDon Skidmore */ 26716ac74394SDon Skidmore if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || 26726ac74394SDon Skidmore !(hw->wol_enabled || ixgbe_mng_present(hw))) 26736ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 26746ac74394SDon Skidmore 26756ac74394SDon Skidmore /* Determine LCD */ 26766ac74394SDon Skidmore status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); 26776ac74394SDon Skidmore if (status) 26786ac74394SDon Skidmore return status; 26796ac74394SDon Skidmore 26806ac74394SDon Skidmore /* If no valid LCD link speed, then force link down and exit. */ 26816ac74394SDon Skidmore if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) 26826ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 26836ac74394SDon Skidmore 26846ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 26854dc4000bSEmil Tantilov MDIO_MMD_AN, 26866ac74394SDon Skidmore &speed); 26876ac74394SDon Skidmore if (status) 26886ac74394SDon Skidmore return status; 26896ac74394SDon Skidmore 26906ac74394SDon Skidmore /* If no link now, speed is invalid so take link down */ 26916ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 26926ac74394SDon Skidmore if (status) 26936ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 26946ac74394SDon Skidmore 26956ac74394SDon Skidmore /* clear everything but the speed bits */ 26966ac74394SDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; 26976ac74394SDon Skidmore 26986ac74394SDon Skidmore /* If current speed is already LCD, then exit. */ 26996ac74394SDon Skidmore if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && 27006ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || 27016ac74394SDon Skidmore ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && 27026ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) 27036ac74394SDon Skidmore return status; 27046ac74394SDon Skidmore 27056ac74394SDon Skidmore /* Clear AN completed indication */ 27066ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, 27074dc4000bSEmil Tantilov MDIO_MMD_AN, 27086ac74394SDon Skidmore &autoneg_reg); 27096ac74394SDon Skidmore if (status) 27106ac74394SDon Skidmore return status; 27116ac74394SDon Skidmore 27124dc4000bSEmil Tantilov status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, 27134dc4000bSEmil Tantilov MDIO_MMD_AN, 27146ac74394SDon Skidmore &an_10g_cntl_reg); 27156ac74394SDon Skidmore if (status) 27166ac74394SDon Skidmore return status; 27176ac74394SDon Skidmore 27186ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, 27196ac74394SDon Skidmore IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, 27204dc4000bSEmil Tantilov MDIO_MMD_AN, 27216ac74394SDon Skidmore &autoneg_reg); 27226ac74394SDon Skidmore if (status) 27236ac74394SDon Skidmore return status; 27246ac74394SDon Skidmore 27256ac74394SDon Skidmore save_autoneg = hw->phy.autoneg_advertised; 27266ac74394SDon Skidmore 27276ac74394SDon Skidmore /* Setup link at least common link speed */ 27286ac74394SDon Skidmore status = hw->mac.ops.setup_link(hw, lcd_speed, false); 27296ac74394SDon Skidmore 27306ac74394SDon Skidmore /* restore autoneg from before setting lplu speed */ 27316ac74394SDon Skidmore hw->phy.autoneg_advertised = save_autoneg; 27326ac74394SDon Skidmore 27336ac74394SDon Skidmore return status; 27346ac74394SDon Skidmore } 27356ac74394SDon Skidmore 2736537cc5dfSMark Rustad /** 2737537cc5dfSMark Rustad * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register 2738537cc5dfSMark Rustad * @hw: pointer to hardware structure 2739537cc5dfSMark Rustad * 2740537cc5dfSMark Rustad * Read NW_MNG_IF_SEL register and save field values. 2741537cc5dfSMark Rustad */ 2742537cc5dfSMark Rustad static void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) 2743537cc5dfSMark Rustad { 2744537cc5dfSMark Rustad /* Save NW management interface connected on board. This is used 2745537cc5dfSMark Rustad * to determine internal PHY mode. 2746537cc5dfSMark Rustad */ 2747537cc5dfSMark Rustad hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 2748537cc5dfSMark Rustad 2749537cc5dfSMark Rustad /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set 2750537cc5dfSMark Rustad * PHY address. This register field was has only been used for X552. 2751537cc5dfSMark Rustad */ 2752ae3cb8cbSMark Rustad if (hw->mac.type == ixgbe_mac_x550em_a && 2753ae3cb8cbSMark Rustad hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) { 2754537cc5dfSMark Rustad hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel & 2755537cc5dfSMark Rustad IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> 2756537cc5dfSMark Rustad IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; 2757537cc5dfSMark Rustad } 2758ae3cb8cbSMark Rustad } 2759537cc5dfSMark Rustad 27606a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 27616a14ee0cSDon Skidmore * @hw: pointer to hardware structure 27626a14ee0cSDon Skidmore * 27636a14ee0cSDon Skidmore * Initialize any function pointers that were not able to be 27646a14ee0cSDon Skidmore * set during init_shared_code because the PHY/SFP type was 27656a14ee0cSDon Skidmore * not known. Perform the SFP init if necessary. 27666a14ee0cSDon Skidmore **/ 27677ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 27686a14ee0cSDon Skidmore { 27696a14ee0cSDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 27706a14ee0cSDon Skidmore s32 ret_val; 27716a14ee0cSDon Skidmore 27727e49d616SDon Skidmore hw->mac.ops.set_lan_id(hw); 27737e49d616SDon Skidmore 2774537cc5dfSMark Rustad ixgbe_read_mng_if_sel_x550em(hw); 2775537cc5dfSMark Rustad 2776c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 27776a14ee0cSDon Skidmore phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 2778ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 27796a14ee0cSDon Skidmore } 27806a14ee0cSDon Skidmore 27816a14ee0cSDon Skidmore /* Identify the PHY or SFP module */ 27826a14ee0cSDon Skidmore ret_val = phy->ops.identify(hw); 27836a14ee0cSDon Skidmore 2784c3dc4c09SDon Skidmore /* Setup function pointers based on detected hardware */ 27856a14ee0cSDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 27866a14ee0cSDon Skidmore if (phy->sfp_type != ixgbe_sfp_type_unknown) 27876a14ee0cSDon Skidmore phy->ops.reset = NULL; 27886a14ee0cSDon Skidmore 27896a14ee0cSDon Skidmore /* Set functions pointers based on phy type */ 27906a14ee0cSDon Skidmore switch (hw->phy.type) { 27916a14ee0cSDon Skidmore case ixgbe_phy_x550em_kx4: 27926a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kx4_x550em; 27936a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 27946a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 27956a14ee0cSDon Skidmore break; 27966a14ee0cSDon Skidmore case ixgbe_phy_x550em_kr: 27976a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kr_x550em; 27986a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 27996a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 28006a14ee0cSDon Skidmore break; 28016a14ee0cSDon Skidmore case ixgbe_phy_x550em_ext_t: 2802c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 2803c3dc4c09SDon Skidmore * to determine internal PHY mode 2804c3dc4c09SDon Skidmore */ 2805c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 2806c3dc4c09SDon Skidmore 2807c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup iXFI internal link, 2808c3dc4c09SDon Skidmore * else setup KR now. 2809c3dc4c09SDon Skidmore */ 2810c3dc4c09SDon Skidmore phy->ops.setup_internal_link = 2811c3dc4c09SDon Skidmore ixgbe_setup_internal_phy_t_x550em; 2812c3dc4c09SDon Skidmore 28136ac74394SDon Skidmore /* setup SW LPLU only for first revision */ 28143ca2b250SMark Rustad if (hw->mac.type == ixgbe_mac_X550EM_x && 28153ca2b250SMark Rustad !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) & 28163ca2b250SMark Rustad IXGBE_FUSES0_REV_MASK)) 28176ac74394SDon Skidmore phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; 28186ac74394SDon Skidmore 2819c3dc4c09SDon Skidmore phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 2820f4410d2cSDon Skidmore phy->ops.reset = ixgbe_reset_phy_t_X550em; 28216a14ee0cSDon Skidmore break; 28226a14ee0cSDon Skidmore default: 28236a14ee0cSDon Skidmore break; 28246a14ee0cSDon Skidmore } 2825c3dc4c09SDon Skidmore 28266a14ee0cSDon Skidmore return ret_val; 28276a14ee0cSDon Skidmore } 28286a14ee0cSDon Skidmore 28296a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type 28306a14ee0cSDon Skidmore * @hw: pointer to hardware structure 28316a14ee0cSDon Skidmore * 28326a14ee0cSDon Skidmore * Returns the media type (fiber, copper, backplane) 28336a14ee0cSDon Skidmore * 28346a14ee0cSDon Skidmore */ 28357ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 28366a14ee0cSDon Skidmore { 28376a14ee0cSDon Skidmore enum ixgbe_media_type media_type; 28386a14ee0cSDon Skidmore 28396a14ee0cSDon Skidmore /* Detect if there is a copper PHY attached. */ 28406a14ee0cSDon Skidmore switch (hw->device_id) { 2841200157c2SMark Rustad case IXGBE_DEV_ID_X550EM_A_SGMII: 2842200157c2SMark Rustad case IXGBE_DEV_ID_X550EM_A_SGMII_L: 2843200157c2SMark Rustad hw->phy.type = ixgbe_phy_sgmii; 2844200157c2SMark Rustad /* Fallthrough */ 28456a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 28466a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 2847f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR: 2848f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR_L: 28496a14ee0cSDon Skidmore media_type = ixgbe_media_type_backplane; 28506a14ee0cSDon Skidmore break; 28516a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 28522d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 285349425dfcSMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 28546a14ee0cSDon Skidmore media_type = ixgbe_media_type_fiber; 28556a14ee0cSDon Skidmore break; 28566a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 28576a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 285892ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 28596a14ee0cSDon Skidmore media_type = ixgbe_media_type_copper; 28606a14ee0cSDon Skidmore break; 28616a14ee0cSDon Skidmore default: 28626a14ee0cSDon Skidmore media_type = ixgbe_media_type_unknown; 28636a14ee0cSDon Skidmore break; 28646a14ee0cSDon Skidmore } 28656a14ee0cSDon Skidmore return media_type; 28666a14ee0cSDon Skidmore } 28676a14ee0cSDon Skidmore 28686a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 28696a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 28706a14ee0cSDon Skidmore **/ 28717ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 28726a14ee0cSDon Skidmore { 2873a1e869deSMark Rustad s32 status; 28746a14ee0cSDon Skidmore u16 reg; 28756a14ee0cSDon Skidmore 28766a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 28776a14ee0cSDon Skidmore IXGBE_MDIO_TX_VENDOR_ALARMS_3, 28784dc4000bSEmil Tantilov MDIO_MMD_PMAPMD, 28796a14ee0cSDon Skidmore ®); 28806a14ee0cSDon Skidmore if (status) 28816a14ee0cSDon Skidmore return status; 28826a14ee0cSDon Skidmore 2883e2261bccSDon Skidmore /* If PHY FW reset completed bit is set then this is the first 2884e2261bccSDon Skidmore * SW instance after a power on so the PHY FW must be un-stalled. 2885e2261bccSDon Skidmore */ 2886e2261bccSDon Skidmore if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 28876a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 28886a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 28894dc4000bSEmil Tantilov MDIO_MMD_VEND1, 28906a14ee0cSDon Skidmore ®); 28916a14ee0cSDon Skidmore if (status) 28926a14ee0cSDon Skidmore return status; 28936a14ee0cSDon Skidmore 28946a14ee0cSDon Skidmore reg &= ~IXGBE_MDIO_POWER_UP_STALL; 28956a14ee0cSDon Skidmore 28966a14ee0cSDon Skidmore status = hw->phy.ops.write_reg(hw, 28976a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 28984dc4000bSEmil Tantilov MDIO_MMD_VEND1, 28996a14ee0cSDon Skidmore reg); 2900e2261bccSDon Skidmore if (status) 2901e2261bccSDon Skidmore return status; 2902e2261bccSDon Skidmore } 2903e2261bccSDon Skidmore 29046a14ee0cSDon Skidmore return status; 29056a14ee0cSDon Skidmore } 29066a14ee0cSDon Skidmore 2907e84db727SMark Rustad /** 2908e84db727SMark Rustad * ixgbe_set_mdio_speed - Set MDIO clock speed 2909e84db727SMark Rustad * @hw: pointer to hardware structure 2910e84db727SMark Rustad */ 2911e84db727SMark Rustad static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) 2912e84db727SMark Rustad { 2913e84db727SMark Rustad u32 hlreg0; 2914e84db727SMark Rustad 2915e84db727SMark Rustad switch (hw->device_id) { 2916e84db727SMark Rustad case IXGBE_DEV_ID_X550EM_X_10G_T: 2917a83c27e7SDon Skidmore case IXGBE_DEV_ID_X550EM_A_SGMII: 2918a83c27e7SDon Skidmore case IXGBE_DEV_ID_X550EM_A_SGMII_L: 291992ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 29202d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 2921e84db727SMark Rustad /* Config MDIO clock speed before the first MDIO PHY access */ 2922e84db727SMark Rustad hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 2923e84db727SMark Rustad hlreg0 &= ~IXGBE_HLREG0_MDCSPD; 2924e84db727SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 2925e84db727SMark Rustad break; 2926e84db727SMark Rustad default: 2927e84db727SMark Rustad break; 2928e84db727SMark Rustad } 2929e84db727SMark Rustad } 2930e84db727SMark Rustad 29316a14ee0cSDon Skidmore /** ixgbe_reset_hw_X550em - Perform hardware reset 29326a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 29336a14ee0cSDon Skidmore ** 29346a14ee0cSDon Skidmore ** Resets the hardware by resetting the transmit and receive units, masks 29356a14ee0cSDon Skidmore ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 29366a14ee0cSDon Skidmore ** reset. 29376a14ee0cSDon Skidmore **/ 29387ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 29396a14ee0cSDon Skidmore { 29406a14ee0cSDon Skidmore ixgbe_link_speed link_speed; 29416a14ee0cSDon Skidmore s32 status; 29426a14ee0cSDon Skidmore u32 ctrl = 0; 29436a14ee0cSDon Skidmore u32 i; 29446a14ee0cSDon Skidmore bool link_up = false; 29456a14ee0cSDon Skidmore 29466a14ee0cSDon Skidmore /* Call adapter stop to disable Tx/Rx and clear interrupts */ 29476a14ee0cSDon Skidmore status = hw->mac.ops.stop_adapter(hw); 29486a14ee0cSDon Skidmore if (status) 29496a14ee0cSDon Skidmore return status; 29506a14ee0cSDon Skidmore 29516a14ee0cSDon Skidmore /* flush pending Tx transactions */ 29526a14ee0cSDon Skidmore ixgbe_clear_tx_pending(hw); 29536a14ee0cSDon Skidmore 29546a14ee0cSDon Skidmore /* PHY ops must be identified and initialized prior to reset */ 29556a14ee0cSDon Skidmore 29566a14ee0cSDon Skidmore /* Identify PHY and related function pointers */ 29576a14ee0cSDon Skidmore status = hw->phy.ops.init(hw); 29586a14ee0cSDon Skidmore 29596a14ee0cSDon Skidmore /* start the external PHY */ 29606a14ee0cSDon Skidmore if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 29616a14ee0cSDon Skidmore status = ixgbe_init_ext_t_x550em(hw); 29626a14ee0cSDon Skidmore if (status) 29636a14ee0cSDon Skidmore return status; 29646a14ee0cSDon Skidmore } 29656a14ee0cSDon Skidmore 29666a14ee0cSDon Skidmore /* Setup SFP module if there is one present. */ 29676a14ee0cSDon Skidmore if (hw->phy.sfp_setup_needed) { 29686a14ee0cSDon Skidmore status = hw->mac.ops.setup_sfp(hw); 29696a14ee0cSDon Skidmore hw->phy.sfp_setup_needed = false; 29706a14ee0cSDon Skidmore } 29716a14ee0cSDon Skidmore 29726a14ee0cSDon Skidmore /* Reset PHY */ 29736a14ee0cSDon Skidmore if (!hw->phy.reset_disable && hw->phy.ops.reset) 29746a14ee0cSDon Skidmore hw->phy.ops.reset(hw); 29756a14ee0cSDon Skidmore 29766a14ee0cSDon Skidmore mac_reset_top: 29776a14ee0cSDon Skidmore /* Issue global reset to the MAC. Needs to be SW reset if link is up. 29786a14ee0cSDon Skidmore * If link reset is used when link is up, it might reset the PHY when 29796a14ee0cSDon Skidmore * mng is using it. If link is down or the flag to force full link 29806a14ee0cSDon Skidmore * reset is set, then perform link reset. 29816a14ee0cSDon Skidmore */ 29826a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_LNK_RST; 29836a14ee0cSDon Skidmore 29846a14ee0cSDon Skidmore if (!hw->force_full_reset) { 29856a14ee0cSDon Skidmore hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 29866a14ee0cSDon Skidmore if (link_up) 29876a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_RST; 29886a14ee0cSDon Skidmore } 29896a14ee0cSDon Skidmore 29906a14ee0cSDon Skidmore ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 29916a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 29926a14ee0cSDon Skidmore IXGBE_WRITE_FLUSH(hw); 2993efff2e02SMark Rustad usleep_range(1000, 1200); 29946a14ee0cSDon Skidmore 29956a14ee0cSDon Skidmore /* Poll for reset bit to self-clear meaning reset is complete */ 29966a14ee0cSDon Skidmore for (i = 0; i < 10; i++) { 29976a14ee0cSDon Skidmore ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 29986a14ee0cSDon Skidmore if (!(ctrl & IXGBE_CTRL_RST_MASK)) 29996a14ee0cSDon Skidmore break; 3000efff2e02SMark Rustad udelay(1); 30016a14ee0cSDon Skidmore } 30026a14ee0cSDon Skidmore 30036a14ee0cSDon Skidmore if (ctrl & IXGBE_CTRL_RST_MASK) { 30046a14ee0cSDon Skidmore status = IXGBE_ERR_RESET_FAILED; 30056a14ee0cSDon Skidmore hw_dbg(hw, "Reset polling failed to complete.\n"); 30066a14ee0cSDon Skidmore } 30076a14ee0cSDon Skidmore 30086a14ee0cSDon Skidmore msleep(50); 30096a14ee0cSDon Skidmore 30106a14ee0cSDon Skidmore /* Double resets are required for recovery from certain error 30116a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 30126a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 30136a14ee0cSDon Skidmore */ 30146a14ee0cSDon Skidmore if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 30156a14ee0cSDon Skidmore hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 30166a14ee0cSDon Skidmore goto mac_reset_top; 30176a14ee0cSDon Skidmore } 30186a14ee0cSDon Skidmore 30196a14ee0cSDon Skidmore /* Store the permanent mac address */ 30206a14ee0cSDon Skidmore hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 30216a14ee0cSDon Skidmore 30226a14ee0cSDon Skidmore /* Store MAC address from RAR0, clear receive address registers, and 30236a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 30246a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 30256a14ee0cSDon Skidmore */ 30266a14ee0cSDon Skidmore hw->mac.num_rar_entries = 128; 30276a14ee0cSDon Skidmore hw->mac.ops.init_rx_addrs(hw); 30286a14ee0cSDon Skidmore 3029e84db727SMark Rustad ixgbe_set_mdio_speed(hw); 3030deda562aSDon Skidmore 3031ab5fe0c5SDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 3032ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 3033ab5fe0c5SDon Skidmore 30346a14ee0cSDon Skidmore return status; 30356a14ee0cSDon Skidmore } 30366a14ee0cSDon Skidmore 30375b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 30385b7f000fSDon Skidmore * anti-spoofing 30395b7f000fSDon Skidmore * @hw: pointer to hardware structure 30405b7f000fSDon Skidmore * @enable: enable or disable switch for Ethertype anti-spoofing 30415b7f000fSDon Skidmore * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 30425b7f000fSDon Skidmore **/ 3043bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 3044bc035fc5SDon Skidmore bool enable, int vf) 30455b7f000fSDon Skidmore { 30465b7f000fSDon Skidmore int vf_target_reg = vf >> 3; 30475b7f000fSDon Skidmore int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 30485b7f000fSDon Skidmore u32 pfvfspoof; 30495b7f000fSDon Skidmore 30505b7f000fSDon Skidmore pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 30515b7f000fSDon Skidmore if (enable) 3052b4f47a48SJacob Keller pfvfspoof |= BIT(vf_target_shift); 30535b7f000fSDon Skidmore else 3054b4f47a48SJacob Keller pfvfspoof &= ~BIT(vf_target_shift); 30555b7f000fSDon Skidmore 30565b7f000fSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 30575b7f000fSDon Skidmore } 30585b7f000fSDon Skidmore 30596d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 30606d4c96adSDon Skidmore * @hw: pointer to hardware structure 30616d4c96adSDon Skidmore * @enable: enable or disable source address pruning 30626d4c96adSDon Skidmore * @pool: Rx pool to set source address pruning for 30636d4c96adSDon Skidmore **/ 30646d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 30656d4c96adSDon Skidmore bool enable, 30666d4c96adSDon Skidmore unsigned int pool) 30676d4c96adSDon Skidmore { 30686d4c96adSDon Skidmore u64 pfflp; 30696d4c96adSDon Skidmore 30706d4c96adSDon Skidmore /* max rx pool is 63 */ 30716d4c96adSDon Skidmore if (pool > 63) 30726d4c96adSDon Skidmore return; 30736d4c96adSDon Skidmore 30746d4c96adSDon Skidmore pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 30756d4c96adSDon Skidmore pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 30766d4c96adSDon Skidmore 30776d4c96adSDon Skidmore if (enable) 30786d4c96adSDon Skidmore pfflp |= (1ULL << pool); 30796d4c96adSDon Skidmore else 30806d4c96adSDon Skidmore pfflp &= ~(1ULL << pool); 30816d4c96adSDon Skidmore 30826d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 30836d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 30846d4c96adSDon Skidmore } 30856d4c96adSDon Skidmore 3086449e21a9SMark Rustad /** 30872916500dSDon Skidmore * ixgbe_setup_fc_backplane_x550em_a - Set up flow control 30882916500dSDon Skidmore * @hw: pointer to hardware structure 30892916500dSDon Skidmore * 30902916500dSDon Skidmore * Called at init time to set up flow control. 30912916500dSDon Skidmore **/ 30922916500dSDon Skidmore static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) 30932916500dSDon Skidmore { 30942916500dSDon Skidmore s32 status = 0; 30952916500dSDon Skidmore u32 an_cntl = 0; 30962916500dSDon Skidmore 30972916500dSDon Skidmore /* Validate the requested mode */ 30982916500dSDon Skidmore if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 30992916500dSDon Skidmore hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 31002916500dSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 31012916500dSDon Skidmore } 31022916500dSDon Skidmore 31032916500dSDon Skidmore if (hw->fc.requested_mode == ixgbe_fc_default) 31042916500dSDon Skidmore hw->fc.requested_mode = ixgbe_fc_full; 31052916500dSDon Skidmore 31062916500dSDon Skidmore /* Set up the 1G and 10G flow control advertisement registers so the 31072916500dSDon Skidmore * HW will be able to do FC autoneg once the cable is plugged in. If 31082916500dSDon Skidmore * we link at 10G, the 1G advertisement is harmless and vice versa. 31092916500dSDon Skidmore */ 31102916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 31112916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 31122916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl); 31132916500dSDon Skidmore 31142916500dSDon Skidmore if (status) { 31152916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 31162916500dSDon Skidmore return status; 31172916500dSDon Skidmore } 31182916500dSDon Skidmore 31192916500dSDon Skidmore /* The possible values of fc.requested_mode are: 31202916500dSDon Skidmore * 0: Flow control is completely disabled 31212916500dSDon Skidmore * 1: Rx flow control is enabled (we can receive pause frames, 31222916500dSDon Skidmore * but not send pause frames). 31232916500dSDon Skidmore * 2: Tx flow control is enabled (we can send pause frames but 31242916500dSDon Skidmore * we do not support receiving pause frames). 31252916500dSDon Skidmore * 3: Both Rx and Tx flow control (symmetric) are enabled. 31262916500dSDon Skidmore * other: Invalid. 31272916500dSDon Skidmore */ 31282916500dSDon Skidmore switch (hw->fc.requested_mode) { 31292916500dSDon Skidmore case ixgbe_fc_none: 31302916500dSDon Skidmore /* Flow control completely disabled by software override. */ 31312916500dSDon Skidmore an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 31322916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 31332916500dSDon Skidmore break; 31342916500dSDon Skidmore case ixgbe_fc_tx_pause: 31352916500dSDon Skidmore /* Tx Flow control is enabled, and Rx Flow control is 31362916500dSDon Skidmore * disabled by software override. 31372916500dSDon Skidmore */ 31382916500dSDon Skidmore an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 31392916500dSDon Skidmore an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 31402916500dSDon Skidmore break; 31412916500dSDon Skidmore case ixgbe_fc_rx_pause: 31422916500dSDon Skidmore /* Rx Flow control is enabled and Tx Flow control is 31432916500dSDon Skidmore * disabled by software override. Since there really 31442916500dSDon Skidmore * isn't a way to advertise that we are capable of RX 31452916500dSDon Skidmore * Pause ONLY, we will advertise that we support both 31462916500dSDon Skidmore * symmetric and asymmetric Rx PAUSE, as such we fall 31472916500dSDon Skidmore * through to the fc_full statement. Later, we will 31482916500dSDon Skidmore * disable the adapter's ability to send PAUSE frames. 31492916500dSDon Skidmore */ 31502916500dSDon Skidmore case ixgbe_fc_full: 31512916500dSDon Skidmore /* Flow control (both Rx and Tx) is enabled by SW override. */ 31522916500dSDon Skidmore an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 31532916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 31542916500dSDon Skidmore break; 31552916500dSDon Skidmore default: 31562916500dSDon Skidmore hw_err(hw, "Flow control param set incorrectly\n"); 31572916500dSDon Skidmore return IXGBE_ERR_CONFIG; 31582916500dSDon Skidmore } 31592916500dSDon Skidmore 31602916500dSDon Skidmore status = hw->mac.ops.write_iosf_sb_reg(hw, 31612916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 31622916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); 31632916500dSDon Skidmore 31642916500dSDon Skidmore /* Restart auto-negotiation. */ 3165470739b5SDon Skidmore status = ixgbe_restart_an_internal_phy_x550em(hw); 31662916500dSDon Skidmore 31672916500dSDon Skidmore return status; 31682916500dSDon Skidmore } 31692916500dSDon Skidmore 31702916500dSDon Skidmore /** 3171449e21a9SMark Rustad * ixgbe_set_mux - Set mux for port 1 access with CS4227 3172449e21a9SMark Rustad * @hw: pointer to hardware structure 3173449e21a9SMark Rustad * @state: set mux if 1, clear if 0 3174449e21a9SMark Rustad */ 3175449e21a9SMark Rustad static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) 3176449e21a9SMark Rustad { 3177449e21a9SMark Rustad u32 esdp; 3178449e21a9SMark Rustad 3179449e21a9SMark Rustad if (!hw->bus.lan_id) 3180449e21a9SMark Rustad return; 3181449e21a9SMark Rustad esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 3182449e21a9SMark Rustad if (state) 3183449e21a9SMark Rustad esdp |= IXGBE_ESDP_SDP1; 3184449e21a9SMark Rustad else 3185449e21a9SMark Rustad esdp &= ~IXGBE_ESDP_SDP1; 3186449e21a9SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 3187449e21a9SMark Rustad IXGBE_WRITE_FLUSH(hw); 3188449e21a9SMark Rustad } 3189449e21a9SMark Rustad 3190449e21a9SMark Rustad /** 3191449e21a9SMark Rustad * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore 3192449e21a9SMark Rustad * @hw: pointer to hardware structure 3193449e21a9SMark Rustad * @mask: Mask to specify which semaphore to acquire 3194449e21a9SMark Rustad * 3195449e21a9SMark Rustad * Acquires the SWFW semaphore and sets the I2C MUX 3196449e21a9SMark Rustad */ 3197449e21a9SMark Rustad static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 3198449e21a9SMark Rustad { 3199449e21a9SMark Rustad s32 status; 3200449e21a9SMark Rustad 3201449e21a9SMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, mask); 3202449e21a9SMark Rustad if (status) 3203449e21a9SMark Rustad return status; 3204449e21a9SMark Rustad 3205449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 3206449e21a9SMark Rustad ixgbe_set_mux(hw, 1); 3207449e21a9SMark Rustad 3208449e21a9SMark Rustad return 0; 3209449e21a9SMark Rustad } 3210449e21a9SMark Rustad 3211449e21a9SMark Rustad /** 3212449e21a9SMark Rustad * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore 3213449e21a9SMark Rustad * @hw: pointer to hardware structure 3214449e21a9SMark Rustad * @mask: Mask to specify which semaphore to release 3215449e21a9SMark Rustad * 3216449e21a9SMark Rustad * Releases the SWFW semaphore and sets the I2C MUX 3217449e21a9SMark Rustad */ 3218449e21a9SMark Rustad static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 3219449e21a9SMark Rustad { 3220449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 3221449e21a9SMark Rustad ixgbe_set_mux(hw, 0); 3222449e21a9SMark Rustad 3223449e21a9SMark Rustad ixgbe_release_swfw_sync_X540(hw, mask); 3224449e21a9SMark Rustad } 3225449e21a9SMark Rustad 322649425dfcSMark Rustad /** 322749425dfcSMark Rustad * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore 322849425dfcSMark Rustad * @hw: pointer to hardware structure 322949425dfcSMark Rustad * @mask: Mask to specify which semaphore to acquire 323049425dfcSMark Rustad * 323149425dfcSMark Rustad * Acquires the SWFW semaphore and get the shared PHY token as needed 323249425dfcSMark Rustad */ 323349425dfcSMark Rustad static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 323449425dfcSMark Rustad { 323549425dfcSMark Rustad u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 323649425dfcSMark Rustad int retries = FW_PHY_TOKEN_RETRIES; 323749425dfcSMark Rustad s32 status; 323849425dfcSMark Rustad 323949425dfcSMark Rustad while (--retries) { 324049425dfcSMark Rustad status = 0; 324149425dfcSMark Rustad if (hmask) 324249425dfcSMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, hmask); 324349425dfcSMark Rustad if (status) 324449425dfcSMark Rustad return status; 324549425dfcSMark Rustad if (!(mask & IXGBE_GSSR_TOKEN_SM)) 324649425dfcSMark Rustad return 0; 324749425dfcSMark Rustad 324849425dfcSMark Rustad status = ixgbe_get_phy_token(hw); 324949425dfcSMark Rustad if (!status) 325049425dfcSMark Rustad return 0; 325149425dfcSMark Rustad if (hmask) 325249425dfcSMark Rustad ixgbe_release_swfw_sync_X540(hw, hmask); 325349425dfcSMark Rustad if (status != IXGBE_ERR_TOKEN_RETRY) 325449425dfcSMark Rustad return status; 3255d4f90d9dSArnd Bergmann msleep(FW_PHY_TOKEN_DELAY); 325649425dfcSMark Rustad } 325749425dfcSMark Rustad 325849425dfcSMark Rustad return status; 325949425dfcSMark Rustad } 326049425dfcSMark Rustad 326149425dfcSMark Rustad /** 326249425dfcSMark Rustad * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore 326349425dfcSMark Rustad * @hw: pointer to hardware structure 326449425dfcSMark Rustad * @mask: Mask to specify which semaphore to release 326549425dfcSMark Rustad * 326649425dfcSMark Rustad * Release the SWFW semaphore and puts the shared PHY token as needed 326749425dfcSMark Rustad */ 326849425dfcSMark Rustad static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 326949425dfcSMark Rustad { 327049425dfcSMark Rustad u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 327149425dfcSMark Rustad 327249425dfcSMark Rustad if (mask & IXGBE_GSSR_TOKEN_SM) 327349425dfcSMark Rustad ixgbe_put_phy_token(hw); 327449425dfcSMark Rustad 327549425dfcSMark Rustad if (hmask) 327649425dfcSMark Rustad ixgbe_release_swfw_sync_X540(hw, hmask); 327749425dfcSMark Rustad } 327849425dfcSMark Rustad 3279d31afc8fSMark Rustad /** 3280d31afc8fSMark Rustad * ixgbe_read_phy_reg_x550a - Reads specified PHY register 3281d31afc8fSMark Rustad * @hw: pointer to hardware structure 3282d31afc8fSMark Rustad * @reg_addr: 32 bit address of PHY register to read 3283d31afc8fSMark Rustad * @phy_data: Pointer to read data from PHY register 3284d31afc8fSMark Rustad * 3285d31afc8fSMark Rustad * Reads a value from a specified PHY register using the SWFW lock and PHY 3286d31afc8fSMark Rustad * Token. The PHY Token is needed since the MDIO is shared between to MAC 3287d31afc8fSMark Rustad * instances. 3288d31afc8fSMark Rustad */ 3289d31afc8fSMark Rustad static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 3290d31afc8fSMark Rustad u32 device_type, u16 *phy_data) 3291d31afc8fSMark Rustad { 3292d31afc8fSMark Rustad u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 3293d31afc8fSMark Rustad s32 status; 3294d31afc8fSMark Rustad 3295d31afc8fSMark Rustad if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 3296d31afc8fSMark Rustad return IXGBE_ERR_SWFW_SYNC; 3297d31afc8fSMark Rustad 3298d31afc8fSMark Rustad status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); 3299d31afc8fSMark Rustad 3300d31afc8fSMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 3301d31afc8fSMark Rustad 3302d31afc8fSMark Rustad return status; 3303d31afc8fSMark Rustad } 3304d31afc8fSMark Rustad 3305d31afc8fSMark Rustad /** 3306d31afc8fSMark Rustad * ixgbe_write_phy_reg_x550a - Writes specified PHY register 3307d31afc8fSMark Rustad * @hw: pointer to hardware structure 3308d31afc8fSMark Rustad * @reg_addr: 32 bit PHY register to write 3309d31afc8fSMark Rustad * @device_type: 5 bit device type 3310d31afc8fSMark Rustad * @phy_data: Data to write to the PHY register 3311d31afc8fSMark Rustad * 3312d31afc8fSMark Rustad * Writes a value to specified PHY register using the SWFW lock and PHY Token. 3313d31afc8fSMark Rustad * The PHY Token is needed since the MDIO is shared between to MAC instances. 3314d31afc8fSMark Rustad */ 3315d31afc8fSMark Rustad static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 3316d31afc8fSMark Rustad u32 device_type, u16 phy_data) 3317d31afc8fSMark Rustad { 3318d31afc8fSMark Rustad u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 3319d31afc8fSMark Rustad s32 status; 3320d31afc8fSMark Rustad 3321d31afc8fSMark Rustad if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 3322d31afc8fSMark Rustad return IXGBE_ERR_SWFW_SYNC; 3323d31afc8fSMark Rustad 3324d31afc8fSMark Rustad status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data); 3325d31afc8fSMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 3326d31afc8fSMark Rustad 3327d31afc8fSMark Rustad return status; 3328d31afc8fSMark Rustad } 3329d31afc8fSMark Rustad 33306a14ee0cSDon Skidmore #define X550_COMMON_MAC \ 33316a14ee0cSDon Skidmore .init_hw = &ixgbe_init_hw_generic, \ 33326a14ee0cSDon Skidmore .start_hw = &ixgbe_start_hw_X540, \ 33336a14ee0cSDon Skidmore .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 33346a14ee0cSDon Skidmore .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 33356a14ee0cSDon Skidmore .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 33366a14ee0cSDon Skidmore .get_device_caps = &ixgbe_get_device_caps_generic, \ 33376a14ee0cSDon Skidmore .stop_adapter = &ixgbe_stop_adapter_generic, \ 33386a14ee0cSDon Skidmore .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 33396a14ee0cSDon Skidmore .read_analog_reg8 = NULL, \ 33406a14ee0cSDon Skidmore .write_analog_reg8 = NULL, \ 33416a14ee0cSDon Skidmore .set_rxpba = &ixgbe_set_rxpba_generic, \ 33426a14ee0cSDon Skidmore .check_link = &ixgbe_check_mac_link_generic, \ 33436a14ee0cSDon Skidmore .blink_led_start = &ixgbe_blink_led_start_X540, \ 33446a14ee0cSDon Skidmore .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 33456a14ee0cSDon Skidmore .set_rar = &ixgbe_set_rar_generic, \ 33466a14ee0cSDon Skidmore .clear_rar = &ixgbe_clear_rar_generic, \ 33476a14ee0cSDon Skidmore .set_vmdq = &ixgbe_set_vmdq_generic, \ 33486a14ee0cSDon Skidmore .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 33496a14ee0cSDon Skidmore .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 33506a14ee0cSDon Skidmore .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 33516a14ee0cSDon Skidmore .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 33526a14ee0cSDon Skidmore .enable_mc = &ixgbe_enable_mc_generic, \ 33536a14ee0cSDon Skidmore .disable_mc = &ixgbe_disable_mc_generic, \ 33546a14ee0cSDon Skidmore .clear_vfta = &ixgbe_clear_vfta_generic, \ 33556a14ee0cSDon Skidmore .set_vfta = &ixgbe_set_vfta_generic, \ 33566a14ee0cSDon Skidmore .fc_enable = &ixgbe_fc_enable_generic, \ 3357cb8e0514STony Nguyen .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_x550, \ 33586a14ee0cSDon Skidmore .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 33596a14ee0cSDon Skidmore .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 33606a14ee0cSDon Skidmore .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 33616d4c96adSDon Skidmore .set_source_address_pruning = \ 33626d4c96adSDon Skidmore &ixgbe_set_source_address_pruning_X550, \ 33635b7f000fSDon Skidmore .set_ethertype_anti_spoofing = \ 33645b7f000fSDon Skidmore &ixgbe_set_ethertype_anti_spoofing_X550, \ 33656a14ee0cSDon Skidmore .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 33666a14ee0cSDon Skidmore .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 33676a14ee0cSDon Skidmore .get_thermal_sensor_data = NULL, \ 33686a14ee0cSDon Skidmore .init_thermal_sensor_thresh = NULL, \ 33691f9ac57cSDon Skidmore .enable_rx = &ixgbe_enable_rx_generic, \ 33701f9ac57cSDon Skidmore .disable_rx = &ixgbe_disable_rx_x550, \ 33716a14ee0cSDon Skidmore 337237689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550 = { 33736a14ee0cSDon Skidmore X550_COMMON_MAC 3374a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_generic, 3375a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_generic, 3376805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 33776a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X540, 33786a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X540, 33796a14ee0cSDon Skidmore .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 33806a14ee0cSDon Skidmore .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 33816a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_mac_link_X540, 33826a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 3383454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_generic, 33846a14ee0cSDon Skidmore .setup_sfp = NULL, 3385449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, 3386449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X540, 3387dbd15b8fSDon Skidmore .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 3388afdc71e4SMark Rustad .prot_autoc_read = prot_autoc_read_generic, 3389afdc71e4SMark Rustad .prot_autoc_write = prot_autoc_write_generic, 3390afdc71e4SMark Rustad .setup_fc = ixgbe_setup_fc_generic, 33912916500dSDon Skidmore .fc_autoneg = ixgbe_fc_autoneg, 33926a14ee0cSDon Skidmore }; 33936a14ee0cSDon Skidmore 339437689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550EM_x = { 33956a14ee0cSDon Skidmore X550_COMMON_MAC 3396a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_t_x550em, 3397a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_t_x550em, 3398805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 33996a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X550em, 34006a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X550em, 34016a14ee0cSDon Skidmore .get_san_mac_addr = NULL, 34026a14ee0cSDon Skidmore .get_wwn_prefix = NULL, 34034695886cSEmil Tantilov .setup_link = &ixgbe_setup_mac_link_X540, 34046a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 3405454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_X550em, 34066a14ee0cSDon Skidmore .setup_sfp = ixgbe_setup_sfp_modules_X550em, 3407449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 3408449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 3409dbd15b8fSDon Skidmore .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 3410afdc71e4SMark Rustad .setup_fc = NULL, /* defined later */ 34112916500dSDon Skidmore .fc_autoneg = ixgbe_fc_autoneg, 34129a5c27e6SMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, 34139a5c27e6SMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, 34146a14ee0cSDon Skidmore }; 34156a14ee0cSDon Skidmore 341649425dfcSMark Rustad static struct ixgbe_mac_operations mac_ops_x550em_a = { 341749425dfcSMark Rustad X550_COMMON_MAC 3418a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_t_x550em, 3419a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_t_x550em, 3420805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 342149425dfcSMark Rustad .reset_hw = ixgbe_reset_hw_X550em, 342249425dfcSMark Rustad .get_media_type = ixgbe_get_media_type_X550em, 342349425dfcSMark Rustad .get_san_mac_addr = NULL, 342449425dfcSMark Rustad .get_wwn_prefix = NULL, 3425a0254a70SMark Rustad .setup_link = NULL, /* defined later */ 342649425dfcSMark Rustad .get_link_capabilities = ixgbe_get_link_capabilities_X550em, 342749425dfcSMark Rustad .get_bus_info = ixgbe_get_bus_info_X550em, 342849425dfcSMark Rustad .setup_sfp = ixgbe_setup_sfp_modules_X550em, 342949425dfcSMark Rustad .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, 343049425dfcSMark Rustad .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, 3431a0254a70SMark Rustad .setup_fc = ixgbe_setup_fc_x550em, 3432470739b5SDon Skidmore .fc_autoneg = ixgbe_fc_autoneg, 343349425dfcSMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, 343449425dfcSMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, 343549425dfcSMark Rustad }; 343649425dfcSMark Rustad 34376a14ee0cSDon Skidmore #define X550_COMMON_EEP \ 34386a14ee0cSDon Skidmore .read = &ixgbe_read_ee_hostif_X550, \ 34396a14ee0cSDon Skidmore .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 34406a14ee0cSDon Skidmore .write = &ixgbe_write_ee_hostif_X550, \ 34416a14ee0cSDon Skidmore .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 34426a14ee0cSDon Skidmore .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 34436a14ee0cSDon Skidmore .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 34446a14ee0cSDon Skidmore .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 34456a14ee0cSDon Skidmore 344637689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550 = { 34476a14ee0cSDon Skidmore X550_COMMON_EEP 34486a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X550, 34496a14ee0cSDon Skidmore }; 34506a14ee0cSDon Skidmore 345137689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 34526a14ee0cSDon Skidmore X550_COMMON_EEP 34536a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X540, 34546a14ee0cSDon Skidmore }; 34556a14ee0cSDon Skidmore 34566a14ee0cSDon Skidmore #define X550_COMMON_PHY \ 34576a14ee0cSDon Skidmore .identify_sfp = &ixgbe_identify_module_generic, \ 34586a14ee0cSDon Skidmore .reset = NULL, \ 34596a14ee0cSDon Skidmore .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 34606a14ee0cSDon Skidmore .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 34616a14ee0cSDon Skidmore .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 34626a14ee0cSDon Skidmore .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 34636a14ee0cSDon Skidmore .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 34646a14ee0cSDon Skidmore .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 3465bef23de1SDon Skidmore .setup_link = &ixgbe_setup_phy_link_generic, \ 3466b5529ef5SDon Skidmore .set_phy_power = NULL, \ 3467d2a10ae7SMark Rustad .check_overtemp = &ixgbe_tn_check_overtemp, 34686a14ee0cSDon Skidmore 346937689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550 = { 34706a14ee0cSDon Skidmore X550_COMMON_PHY 34716a14ee0cSDon Skidmore .init = NULL, 34726a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_generic, 3473d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_generic, 3474d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_generic, 34756a14ee0cSDon Skidmore }; 34766a14ee0cSDon Skidmore 347737689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550EM_x = { 34786a14ee0cSDon Skidmore X550_COMMON_PHY 34796a14ee0cSDon Skidmore .init = &ixgbe_init_phy_ops_X550em, 34806a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_x550em, 3481d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_generic, 3482d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_generic, 34836a14ee0cSDon Skidmore }; 34846a14ee0cSDon Skidmore 3485d31afc8fSMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a = { 3486d31afc8fSMark Rustad X550_COMMON_PHY 3487d31afc8fSMark Rustad .init = &ixgbe_init_phy_ops_X550em, 3488d31afc8fSMark Rustad .identify = &ixgbe_identify_phy_x550em, 3489d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_x550a, 3490d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_x550a, 34918fe293aaSMark Rustad .read_reg_mdi = &ixgbe_read_phy_reg_mdi, 34928fe293aaSMark Rustad .write_reg_mdi = &ixgbe_write_phy_reg_mdi, 3493d31afc8fSMark Rustad }; 3494d31afc8fSMark Rustad 3495b71f6c40SEmil Tantilov static const struct ixgbe_link_operations link_ops_x550em_x = { 3496b71f6c40SEmil Tantilov .read_link = &ixgbe_read_i2c_combined_generic, 3497b71f6c40SEmil Tantilov .read_link_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, 3498b71f6c40SEmil Tantilov .write_link = &ixgbe_write_i2c_combined_generic, 3499b71f6c40SEmil Tantilov .write_link_unlocked = &ixgbe_write_i2c_combined_generic_unlocked, 3500b71f6c40SEmil Tantilov }; 3501b71f6c40SEmil Tantilov 35029a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 35039a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550) 35049a900ecaSDon Skidmore }; 35059a900ecaSDon Skidmore 35069a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 35079a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550EM_x) 35089a900ecaSDon Skidmore }; 35099a900ecaSDon Skidmore 351049425dfcSMark Rustad static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = { 351149425dfcSMark Rustad IXGBE_MVALS_INIT(X550EM_a) 351249425dfcSMark Rustad }; 351349425dfcSMark Rustad 351437689010SMark Rustad const struct ixgbe_info ixgbe_X550_info = { 35156a14ee0cSDon Skidmore .mac = ixgbe_mac_X550, 35166a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 35176a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550, 35186a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550, 35196a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550, 35206a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 35219a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550, 35226a14ee0cSDon Skidmore }; 35236a14ee0cSDon Skidmore 352437689010SMark Rustad const struct ixgbe_info ixgbe_X550EM_x_info = { 35256a14ee0cSDon Skidmore .mac = ixgbe_mac_X550EM_x, 3526b5529ef5SDon Skidmore .get_invariants = &ixgbe_get_invariants_X550_x, 35276a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550EM_x, 35286a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550EM_x, 35296a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550EM_x, 35306a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 35319a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550EM_x, 3532b71f6c40SEmil Tantilov .link_ops = &link_ops_x550em_x, 35336a14ee0cSDon Skidmore }; 353449425dfcSMark Rustad 353549425dfcSMark Rustad const struct ixgbe_info ixgbe_x550em_a_info = { 353649425dfcSMark Rustad .mac = ixgbe_mac_x550em_a, 3537b71f6c40SEmil Tantilov .get_invariants = &ixgbe_get_invariants_X550_a, 353849425dfcSMark Rustad .mac_ops = &mac_ops_x550em_a, 353949425dfcSMark Rustad .eeprom_ops = &eeprom_ops_X550EM_x, 3540d31afc8fSMark Rustad .phy_ops = &phy_ops_x550em_a, 354149425dfcSMark Rustad .mbx_ops = &mbx_ops_generic, 354249425dfcSMark Rustad .mvals = ixgbe_mvals_x550em_a, 354349425dfcSMark Rustad }; 3544