151dce24bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0 251dce24bSJeff Kirsher /* Copyright(c) 1999 - 2018 Intel Corporation. */ 351dce24bSJeff Kirsher 46a14ee0cSDon Skidmore #include "ixgbe_x540.h" 56a14ee0cSDon Skidmore #include "ixgbe_type.h" 66a14ee0cSDon Skidmore #include "ixgbe_common.h" 76a14ee0cSDon Skidmore #include "ixgbe_phy.h" 86a14ee0cSDon Skidmore 9d91e3a7dSMark Rustad static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed); 10afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *); 112916500dSDon Skidmore static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *); 122916500dSDon Skidmore static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *); 132916500dSDon Skidmore static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *); 14d91e3a7dSMark Rustad 15b5529ef5SDon Skidmore static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) 16b5529ef5SDon Skidmore { 17b5529ef5SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 18b5529ef5SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 19b71f6c40SEmil Tantilov struct ixgbe_link_info *link = &hw->link; 20b71f6c40SEmil Tantilov 21b71f6c40SEmil Tantilov /* Start with X540 invariants, since so simular */ 22b71f6c40SEmil Tantilov ixgbe_get_invariants_X540(hw); 23b71f6c40SEmil Tantilov 24b71f6c40SEmil Tantilov if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 25b71f6c40SEmil Tantilov phy->ops.set_phy_power = NULL; 26b71f6c40SEmil Tantilov 27b71f6c40SEmil Tantilov link->addr = IXGBE_CS4227; 28b71f6c40SEmil Tantilov 29b71f6c40SEmil Tantilov return 0; 30b71f6c40SEmil Tantilov } 31b71f6c40SEmil Tantilov 328dc963e1SPaul Greenwalt static s32 ixgbe_get_invariants_X550_x_fw(struct ixgbe_hw *hw) 338dc963e1SPaul Greenwalt { 348dc963e1SPaul Greenwalt struct ixgbe_phy_info *phy = &hw->phy; 358dc963e1SPaul Greenwalt 368dc963e1SPaul Greenwalt /* Start with X540 invariants, since so similar */ 378dc963e1SPaul Greenwalt ixgbe_get_invariants_X540(hw); 388dc963e1SPaul Greenwalt 398dc963e1SPaul Greenwalt phy->ops.set_phy_power = NULL; 408dc963e1SPaul Greenwalt 418dc963e1SPaul Greenwalt return 0; 428dc963e1SPaul Greenwalt } 438dc963e1SPaul Greenwalt 44b71f6c40SEmil Tantilov static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw) 45b71f6c40SEmil Tantilov { 46b71f6c40SEmil Tantilov struct ixgbe_mac_info *mac = &hw->mac; 47b71f6c40SEmil Tantilov struct ixgbe_phy_info *phy = &hw->phy; 48b5529ef5SDon Skidmore 49b5529ef5SDon Skidmore /* Start with X540 invariants, since so simular */ 50b5529ef5SDon Skidmore ixgbe_get_invariants_X540(hw); 51b5529ef5SDon Skidmore 52b5529ef5SDon Skidmore if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 53b5529ef5SDon Skidmore phy->ops.set_phy_power = NULL; 54b5529ef5SDon Skidmore 55b5529ef5SDon Skidmore return 0; 56b5529ef5SDon Skidmore } 57b5529ef5SDon Skidmore 58b3eb4e18SMark Rustad static s32 ixgbe_get_invariants_X550_a_fw(struct ixgbe_hw *hw) 59b3eb4e18SMark Rustad { 60b3eb4e18SMark Rustad struct ixgbe_phy_info *phy = &hw->phy; 61b3eb4e18SMark Rustad 62b3eb4e18SMark Rustad /* Start with X540 invariants, since so similar */ 63b3eb4e18SMark Rustad ixgbe_get_invariants_X540(hw); 64b3eb4e18SMark Rustad 65b3eb4e18SMark Rustad phy->ops.set_phy_power = NULL; 66b3eb4e18SMark Rustad 67b3eb4e18SMark Rustad return 0; 68b3eb4e18SMark Rustad } 69b3eb4e18SMark Rustad 70ab5fe0c5SDon Skidmore /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control 71ab5fe0c5SDon Skidmore * @hw: pointer to hardware structure 72ab5fe0c5SDon Skidmore **/ 73ab5fe0c5SDon Skidmore static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) 74ab5fe0c5SDon Skidmore { 75ab5fe0c5SDon Skidmore u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 76ab5fe0c5SDon Skidmore 77ab5fe0c5SDon Skidmore if (hw->bus.lan_id) { 78ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 79ab5fe0c5SDon Skidmore esdp |= IXGBE_ESDP_SDP1_DIR; 80ab5fe0c5SDon Skidmore } 81ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 82ab5fe0c5SDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 83ab5fe0c5SDon Skidmore IXGBE_WRITE_FLUSH(hw); 84ab5fe0c5SDon Skidmore } 85ab5fe0c5SDon Skidmore 86542b6eecSMark Rustad /** 87542b6eecSMark Rustad * ixgbe_read_cs4227 - Read CS4227 register 88542b6eecSMark Rustad * @hw: pointer to hardware structure 89542b6eecSMark Rustad * @reg: register number to write 90542b6eecSMark Rustad * @value: pointer to receive value read 91542b6eecSMark Rustad * 92542b6eecSMark Rustad * Returns status code 93542b6eecSMark Rustad */ 94542b6eecSMark Rustad static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) 95542b6eecSMark Rustad { 96b71f6c40SEmil Tantilov return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value); 97542b6eecSMark Rustad } 98542b6eecSMark Rustad 99542b6eecSMark Rustad /** 100542b6eecSMark Rustad * ixgbe_write_cs4227 - Write CS4227 register 101542b6eecSMark Rustad * @hw: pointer to hardware structure 102542b6eecSMark Rustad * @reg: register number to write 103542b6eecSMark Rustad * @value: value to write to register 104542b6eecSMark Rustad * 105542b6eecSMark Rustad * Returns status code 106542b6eecSMark Rustad */ 107542b6eecSMark Rustad static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) 108542b6eecSMark Rustad { 109b71f6c40SEmil Tantilov return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value); 110542b6eecSMark Rustad } 111542b6eecSMark Rustad 112542b6eecSMark Rustad /** 113542b6eecSMark Rustad * ixgbe_read_pe - Read register from port expander 114542b6eecSMark Rustad * @hw: pointer to hardware structure 115542b6eecSMark Rustad * @reg: register number to read 116542b6eecSMark Rustad * @value: pointer to receive read value 117542b6eecSMark Rustad * 118542b6eecSMark Rustad * Returns status code 119542b6eecSMark Rustad */ 120542b6eecSMark Rustad static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) 121542b6eecSMark Rustad { 122542b6eecSMark Rustad s32 status; 123542b6eecSMark Rustad 124542b6eecSMark Rustad status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, value); 125542b6eecSMark Rustad if (status) 126542b6eecSMark Rustad hw_err(hw, "port expander access failed with %d\n", status); 127542b6eecSMark Rustad return status; 128542b6eecSMark Rustad } 129542b6eecSMark Rustad 130542b6eecSMark Rustad /** 131542b6eecSMark Rustad * ixgbe_write_pe - Write register to port expander 132542b6eecSMark Rustad * @hw: pointer to hardware structure 133542b6eecSMark Rustad * @reg: register number to write 134542b6eecSMark Rustad * @value: value to write 135542b6eecSMark Rustad * 136542b6eecSMark Rustad * Returns status code 137542b6eecSMark Rustad */ 138542b6eecSMark Rustad static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) 139542b6eecSMark Rustad { 140542b6eecSMark Rustad s32 status; 141542b6eecSMark Rustad 142542b6eecSMark Rustad status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, 143542b6eecSMark Rustad value); 144542b6eecSMark Rustad if (status) 145542b6eecSMark Rustad hw_err(hw, "port expander access failed with %d\n", status); 146542b6eecSMark Rustad return status; 147542b6eecSMark Rustad } 148542b6eecSMark Rustad 149542b6eecSMark Rustad /** 150542b6eecSMark Rustad * ixgbe_reset_cs4227 - Reset CS4227 using port expander 151542b6eecSMark Rustad * @hw: pointer to hardware structure 152542b6eecSMark Rustad * 1538bf7a7b8SMark Rustad * This function assumes that the caller has acquired the proper semaphore. 154542b6eecSMark Rustad * Returns error code 155542b6eecSMark Rustad */ 156542b6eecSMark Rustad static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) 157542b6eecSMark Rustad { 158542b6eecSMark Rustad s32 status; 159542b6eecSMark Rustad u32 retry; 160542b6eecSMark Rustad u16 value; 161542b6eecSMark Rustad u8 reg; 162542b6eecSMark Rustad 163542b6eecSMark Rustad /* Trigger hard reset. */ 164542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 165542b6eecSMark Rustad if (status) 166542b6eecSMark Rustad return status; 167542b6eecSMark Rustad reg |= IXGBE_PE_BIT1; 168542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 169542b6eecSMark Rustad if (status) 170542b6eecSMark Rustad return status; 171542b6eecSMark Rustad 172542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); 173542b6eecSMark Rustad if (status) 174542b6eecSMark Rustad return status; 175542b6eecSMark Rustad reg &= ~IXGBE_PE_BIT1; 176542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); 177542b6eecSMark Rustad if (status) 178542b6eecSMark Rustad return status; 179542b6eecSMark Rustad 180542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 181542b6eecSMark Rustad if (status) 182542b6eecSMark Rustad return status; 183542b6eecSMark Rustad reg &= ~IXGBE_PE_BIT1; 184542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 185542b6eecSMark Rustad if (status) 186542b6eecSMark Rustad return status; 187542b6eecSMark Rustad 188542b6eecSMark Rustad usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100); 189542b6eecSMark Rustad 190542b6eecSMark Rustad status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 191542b6eecSMark Rustad if (status) 192542b6eecSMark Rustad return status; 193542b6eecSMark Rustad reg |= IXGBE_PE_BIT1; 194542b6eecSMark Rustad status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 195542b6eecSMark Rustad if (status) 196542b6eecSMark Rustad return status; 197542b6eecSMark Rustad 198542b6eecSMark Rustad /* Wait for the reset to complete. */ 199542b6eecSMark Rustad msleep(IXGBE_CS4227_RESET_DELAY); 200542b6eecSMark Rustad for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 201542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, 202542b6eecSMark Rustad &value); 203542b6eecSMark Rustad if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK) 204542b6eecSMark Rustad break; 205542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 206542b6eecSMark Rustad } 207542b6eecSMark Rustad if (retry == IXGBE_CS4227_RETRIES) { 208542b6eecSMark Rustad hw_err(hw, "CS4227 reset did not complete\n"); 209542b6eecSMark Rustad return IXGBE_ERR_PHY; 210542b6eecSMark Rustad } 211542b6eecSMark Rustad 212542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value); 213542b6eecSMark Rustad if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { 214542b6eecSMark Rustad hw_err(hw, "CS4227 EEPROM did not load successfully\n"); 215542b6eecSMark Rustad return IXGBE_ERR_PHY; 216542b6eecSMark Rustad } 217542b6eecSMark Rustad 218542b6eecSMark Rustad return 0; 219542b6eecSMark Rustad } 220542b6eecSMark Rustad 221542b6eecSMark Rustad /** 222542b6eecSMark Rustad * ixgbe_check_cs4227 - Check CS4227 and reset as needed 223542b6eecSMark Rustad * @hw: pointer to hardware structure 224542b6eecSMark Rustad */ 225542b6eecSMark Rustad static void ixgbe_check_cs4227(struct ixgbe_hw *hw) 226542b6eecSMark Rustad { 227542b6eecSMark Rustad u32 swfw_mask = hw->phy.phy_semaphore_mask; 228542b6eecSMark Rustad s32 status; 229542b6eecSMark Rustad u16 value; 230542b6eecSMark Rustad u8 retry; 231542b6eecSMark Rustad 232542b6eecSMark Rustad for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 233542b6eecSMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 234542b6eecSMark Rustad if (status) { 235542b6eecSMark Rustad hw_err(hw, "semaphore failed with %d\n", status); 236542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 237542b6eecSMark Rustad continue; 238542b6eecSMark Rustad } 239542b6eecSMark Rustad 240542b6eecSMark Rustad /* Get status of reset flow. */ 241542b6eecSMark Rustad status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); 242542b6eecSMark Rustad if (!status && value == IXGBE_CS4227_RESET_COMPLETE) 243542b6eecSMark Rustad goto out; 244542b6eecSMark Rustad 245542b6eecSMark Rustad if (status || value != IXGBE_CS4227_RESET_PENDING) 246542b6eecSMark Rustad break; 247542b6eecSMark Rustad 248542b6eecSMark Rustad /* Reset is pending. Wait and check again. */ 249542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 250542b6eecSMark Rustad msleep(IXGBE_CS4227_CHECK_DELAY); 251542b6eecSMark Rustad } 2528bf7a7b8SMark Rustad /* If still pending, assume other instance failed. */ 2538bf7a7b8SMark Rustad if (retry == IXGBE_CS4227_RETRIES) { 2548bf7a7b8SMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 2558bf7a7b8SMark Rustad if (status) { 2568bf7a7b8SMark Rustad hw_err(hw, "semaphore failed with %d\n", status); 2578bf7a7b8SMark Rustad return; 2588bf7a7b8SMark Rustad } 2598bf7a7b8SMark Rustad } 260542b6eecSMark Rustad 261542b6eecSMark Rustad /* Reset the CS4227. */ 262542b6eecSMark Rustad status = ixgbe_reset_cs4227(hw); 263542b6eecSMark Rustad if (status) { 264542b6eecSMark Rustad hw_err(hw, "CS4227 reset failed: %d", status); 265542b6eecSMark Rustad goto out; 266542b6eecSMark Rustad } 267542b6eecSMark Rustad 268542b6eecSMark Rustad /* Reset takes so long, temporarily release semaphore in case the 269542b6eecSMark Rustad * other driver instance is waiting for the reset indication. 270542b6eecSMark Rustad */ 271542b6eecSMark Rustad ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 272542b6eecSMark Rustad IXGBE_CS4227_RESET_PENDING); 273542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 274542b6eecSMark Rustad usleep_range(10000, 12000); 275542b6eecSMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 276542b6eecSMark Rustad if (status) { 277542b6eecSMark Rustad hw_err(hw, "semaphore failed with %d", status); 278542b6eecSMark Rustad return; 279542b6eecSMark Rustad } 280542b6eecSMark Rustad 281542b6eecSMark Rustad /* Record completion for next time. */ 282542b6eecSMark Rustad status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 283542b6eecSMark Rustad IXGBE_CS4227_RESET_COMPLETE); 284542b6eecSMark Rustad 285542b6eecSMark Rustad out: 286542b6eecSMark Rustad hw->mac.ops.release_swfw_sync(hw, swfw_mask); 287542b6eecSMark Rustad msleep(hw->eeprom.semaphore_delay); 288542b6eecSMark Rustad } 289542b6eecSMark Rustad 2906a14ee0cSDon Skidmore /** ixgbe_identify_phy_x550em - Get PHY type based on device id 2916a14ee0cSDon Skidmore * @hw: pointer to hardware structure 2926a14ee0cSDon Skidmore * 2936a14ee0cSDon Skidmore * Returns error code 2946a14ee0cSDon Skidmore */ 2956a14ee0cSDon Skidmore static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) 2966a14ee0cSDon Skidmore { 2976a14ee0cSDon Skidmore switch (hw->device_id) { 2982d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 2992d40cd17SMark Rustad if (hw->bus.lan_id) 3002d40cd17SMark Rustad hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 3012d40cd17SMark Rustad else 3022d40cd17SMark Rustad hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 3032d40cd17SMark Rustad return ixgbe_identify_module_generic(hw); 3046a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 3056a14ee0cSDon Skidmore /* set up for CS4227 usage */ 3066a14ee0cSDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 307ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 308542b6eecSMark Rustad ixgbe_check_cs4227(hw); 3095463fce6SJeff Kirsher fallthrough; 31049425dfcSMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 3116a14ee0cSDon Skidmore return ixgbe_identify_module_generic(hw); 3126a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 3136a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kx4; 3146a14ee0cSDon Skidmore break; 31518e01ee7SDon Skidmore case IXGBE_DEV_ID_X550EM_X_XFI: 31618e01ee7SDon Skidmore hw->phy.type = ixgbe_phy_x550em_xfi; 31718e01ee7SDon Skidmore break; 3186a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 319f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR: 320f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR_L: 3216a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kr; 3226a14ee0cSDon Skidmore break; 32392ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 32492ed8430SDon Skidmore if (hw->bus.lan_id) 32592ed8430SDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 32692ed8430SDon Skidmore else 32792ed8430SDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 3285463fce6SJeff Kirsher fallthrough; 3296a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 3306a14ee0cSDon Skidmore return ixgbe_identify_phy_generic(hw); 3318dc963e1SPaul Greenwalt case IXGBE_DEV_ID_X550EM_X_1G_T: 3328dc963e1SPaul Greenwalt hw->phy.type = ixgbe_phy_ext_1g_t; 3338dc963e1SPaul Greenwalt break; 33418bda0d9SDon Skidmore case IXGBE_DEV_ID_X550EM_A_1G_T: 33518bda0d9SDon Skidmore case IXGBE_DEV_ID_X550EM_A_1G_T_L: 33618bda0d9SDon Skidmore hw->phy.type = ixgbe_phy_fw; 33718bda0d9SDon Skidmore hw->phy.ops.read_reg = NULL; 33818bda0d9SDon Skidmore hw->phy.ops.write_reg = NULL; 33918bda0d9SDon Skidmore if (hw->bus.lan_id) 34018bda0d9SDon Skidmore hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; 34118bda0d9SDon Skidmore else 34218bda0d9SDon Skidmore hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM; 34318bda0d9SDon Skidmore break; 3446a14ee0cSDon Skidmore default: 3456a14ee0cSDon Skidmore break; 3466a14ee0cSDon Skidmore } 3476a14ee0cSDon Skidmore return 0; 3486a14ee0cSDon Skidmore } 3496a14ee0cSDon Skidmore 3506a14ee0cSDon Skidmore static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 3516a14ee0cSDon Skidmore u32 device_type, u16 *phy_data) 3526a14ee0cSDon Skidmore { 3536a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 3546a14ee0cSDon Skidmore } 3556a14ee0cSDon Skidmore 3566a14ee0cSDon Skidmore static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 3576a14ee0cSDon Skidmore u32 device_type, u16 phy_data) 3586a14ee0cSDon Skidmore { 3596a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 3606a14ee0cSDon Skidmore } 3616a14ee0cSDon Skidmore 362b71f6c40SEmil Tantilov /** 363b71f6c40SEmil Tantilov * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation 364b71f6c40SEmil Tantilov * @hw: pointer to the hardware structure 365b71f6c40SEmil Tantilov * @addr: I2C bus address to read from 366b71f6c40SEmil Tantilov * @reg: I2C device register to read from 367b71f6c40SEmil Tantilov * @val: pointer to location to receive read value 368b71f6c40SEmil Tantilov * 369b71f6c40SEmil Tantilov * Returns an error code on error. 370b71f6c40SEmil Tantilov **/ 371b71f6c40SEmil Tantilov static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, 372b71f6c40SEmil Tantilov u16 reg, u16 *val) 373b71f6c40SEmil Tantilov { 374b71f6c40SEmil Tantilov return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); 375b71f6c40SEmil Tantilov } 376b71f6c40SEmil Tantilov 377b71f6c40SEmil Tantilov /** 378b71f6c40SEmil Tantilov * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation 379b71f6c40SEmil Tantilov * @hw: pointer to the hardware structure 380b71f6c40SEmil Tantilov * @addr: I2C bus address to read from 381b71f6c40SEmil Tantilov * @reg: I2C device register to read from 382b71f6c40SEmil Tantilov * @val: pointer to location to receive read value 383b71f6c40SEmil Tantilov * 384b71f6c40SEmil Tantilov * Returns an error code on error. 385b71f6c40SEmil Tantilov **/ 386b71f6c40SEmil Tantilov static s32 387b71f6c40SEmil Tantilov ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, 388b71f6c40SEmil Tantilov u16 reg, u16 *val) 389b71f6c40SEmil Tantilov { 390b71f6c40SEmil Tantilov return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); 391b71f6c40SEmil Tantilov } 392b71f6c40SEmil Tantilov 393b71f6c40SEmil Tantilov /** 394b71f6c40SEmil Tantilov * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation 395b71f6c40SEmil Tantilov * @hw: pointer to the hardware structure 396b71f6c40SEmil Tantilov * @addr: I2C bus address to write to 397b71f6c40SEmil Tantilov * @reg: I2C device register to write to 398b71f6c40SEmil Tantilov * @val: value to write 399b71f6c40SEmil Tantilov * 400b71f6c40SEmil Tantilov * Returns an error code on error. 401b71f6c40SEmil Tantilov **/ 402b71f6c40SEmil Tantilov static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, 403b71f6c40SEmil Tantilov u8 addr, u16 reg, u16 val) 404b71f6c40SEmil Tantilov { 405b71f6c40SEmil Tantilov return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); 406b71f6c40SEmil Tantilov } 407b71f6c40SEmil Tantilov 408b71f6c40SEmil Tantilov /** 409b71f6c40SEmil Tantilov * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation 410b71f6c40SEmil Tantilov * @hw: pointer to the hardware structure 411b71f6c40SEmil Tantilov * @addr: I2C bus address to write to 412b71f6c40SEmil Tantilov * @reg: I2C device register to write to 413b71f6c40SEmil Tantilov * @val: value to write 414b71f6c40SEmil Tantilov * 415b71f6c40SEmil Tantilov * Returns an error code on error. 416b71f6c40SEmil Tantilov **/ 417b71f6c40SEmil Tantilov static s32 418b71f6c40SEmil Tantilov ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, 419b71f6c40SEmil Tantilov u8 addr, u16 reg, u16 val) 420b71f6c40SEmil Tantilov { 421b71f6c40SEmil Tantilov return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); 422b71f6c40SEmil Tantilov } 423b71f6c40SEmil Tantilov 42412c78ef0SMark Rustad /** 42512c78ef0SMark Rustad * ixgbe_fw_phy_activity - Perform an activity on a PHY 42612c78ef0SMark Rustad * @hw: pointer to hardware structure 42712c78ef0SMark Rustad * @activity: activity to perform 42812c78ef0SMark Rustad * @data: Pointer to 4 32-bit words of data 42912c78ef0SMark Rustad */ 43012c78ef0SMark Rustad s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity, 43112c78ef0SMark Rustad u32 (*data)[FW_PHY_ACT_DATA_COUNT]) 43212c78ef0SMark Rustad { 43312c78ef0SMark Rustad union { 43412c78ef0SMark Rustad struct ixgbe_hic_phy_activity_req cmd; 43512c78ef0SMark Rustad struct ixgbe_hic_phy_activity_resp rsp; 43612c78ef0SMark Rustad } hic; 43712c78ef0SMark Rustad u16 retries = FW_PHY_ACT_RETRIES; 43812c78ef0SMark Rustad s32 rc; 43912c78ef0SMark Rustad u32 i; 44012c78ef0SMark Rustad 44112c78ef0SMark Rustad do { 44212c78ef0SMark Rustad memset(&hic, 0, sizeof(hic)); 44312c78ef0SMark Rustad hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD; 44412c78ef0SMark Rustad hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN; 44512c78ef0SMark Rustad hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 44612c78ef0SMark Rustad hic.cmd.port_number = hw->bus.lan_id; 44712c78ef0SMark Rustad hic.cmd.activity_id = cpu_to_le16(activity); 44812c78ef0SMark Rustad for (i = 0; i < ARRAY_SIZE(hic.cmd.data); ++i) 44912c78ef0SMark Rustad hic.cmd.data[i] = cpu_to_be32((*data)[i]); 45012c78ef0SMark Rustad 45112c78ef0SMark Rustad rc = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 45212c78ef0SMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 45312c78ef0SMark Rustad true); 45412c78ef0SMark Rustad if (rc) 45512c78ef0SMark Rustad return rc; 45612c78ef0SMark Rustad if (hic.rsp.hdr.cmd_or_resp.ret_status == 45712c78ef0SMark Rustad FW_CEM_RESP_STATUS_SUCCESS) { 45812c78ef0SMark Rustad for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i) 45912c78ef0SMark Rustad (*data)[i] = be32_to_cpu(hic.rsp.data[i]); 46012c78ef0SMark Rustad return 0; 46112c78ef0SMark Rustad } 46212c78ef0SMark Rustad usleep_range(20, 30); 46312c78ef0SMark Rustad --retries; 46412c78ef0SMark Rustad } while (retries > 0); 46512c78ef0SMark Rustad 46612c78ef0SMark Rustad return IXGBE_ERR_HOST_INTERFACE_COMMAND; 46712c78ef0SMark Rustad } 46812c78ef0SMark Rustad 469b3eb4e18SMark Rustad static const struct { 470b3eb4e18SMark Rustad u16 fw_speed; 471b3eb4e18SMark Rustad ixgbe_link_speed phy_speed; 472b3eb4e18SMark Rustad } ixgbe_fw_map[] = { 473b3eb4e18SMark Rustad { FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL }, 474b3eb4e18SMark Rustad { FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL }, 475b3eb4e18SMark Rustad { FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL }, 476b3eb4e18SMark Rustad { FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL }, 477b3eb4e18SMark Rustad { FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL }, 478b3eb4e18SMark Rustad { FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL }, 479b3eb4e18SMark Rustad }; 480b3eb4e18SMark Rustad 481b3eb4e18SMark Rustad /** 482b3eb4e18SMark Rustad * ixgbe_get_phy_id_fw - Get the phy ID via firmware command 483b3eb4e18SMark Rustad * @hw: pointer to hardware structure 484b3eb4e18SMark Rustad * 485b3eb4e18SMark Rustad * Returns error code 486b3eb4e18SMark Rustad */ 487b3eb4e18SMark Rustad static s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw) 488b3eb4e18SMark Rustad { 489b3eb4e18SMark Rustad u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 }; 490b3eb4e18SMark Rustad u16 phy_speeds; 491b3eb4e18SMark Rustad u16 phy_id_lo; 492b3eb4e18SMark Rustad s32 rc; 493b3eb4e18SMark Rustad u16 i; 494b3eb4e18SMark Rustad 495b3eb4e18SMark Rustad if (hw->phy.id) 496b3eb4e18SMark Rustad return 0; 497b3eb4e18SMark Rustad 498b3eb4e18SMark Rustad rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info); 499b3eb4e18SMark Rustad if (rc) 500b3eb4e18SMark Rustad return rc; 501b3eb4e18SMark Rustad 502b3eb4e18SMark Rustad hw->phy.speeds_supported = 0; 503b3eb4e18SMark Rustad phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK; 504b3eb4e18SMark Rustad for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) { 505b3eb4e18SMark Rustad if (phy_speeds & ixgbe_fw_map[i].fw_speed) 506b3eb4e18SMark Rustad hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed; 507b3eb4e18SMark Rustad } 508b3eb4e18SMark Rustad 509b3eb4e18SMark Rustad hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK; 510b3eb4e18SMark Rustad phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK; 511b3eb4e18SMark Rustad hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK; 512b3eb4e18SMark Rustad hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK; 513b3eb4e18SMark Rustad if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK) 514b3eb4e18SMark Rustad return IXGBE_ERR_PHY_ADDR_INVALID; 515b3eb4e18SMark Rustad 516b3eb4e18SMark Rustad hw->phy.autoneg_advertised = hw->phy.speeds_supported; 517b3eb4e18SMark Rustad hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL | 518b3eb4e18SMark Rustad IXGBE_LINK_SPEED_1GB_FULL; 519b3eb4e18SMark Rustad hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported; 520b3eb4e18SMark Rustad return 0; 521b3eb4e18SMark Rustad } 522b3eb4e18SMark Rustad 523b3eb4e18SMark Rustad /** 524b3eb4e18SMark Rustad * ixgbe_identify_phy_fw - Get PHY type based on firmware command 525b3eb4e18SMark Rustad * @hw: pointer to hardware structure 526b3eb4e18SMark Rustad * 527b3eb4e18SMark Rustad * Returns error code 528b3eb4e18SMark Rustad */ 529b3eb4e18SMark Rustad static s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw) 530b3eb4e18SMark Rustad { 531b3eb4e18SMark Rustad if (hw->bus.lan_id) 532b3eb4e18SMark Rustad hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 533b3eb4e18SMark Rustad else 534b3eb4e18SMark Rustad hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 535b3eb4e18SMark Rustad 536b3eb4e18SMark Rustad hw->phy.type = ixgbe_phy_fw; 537b3eb4e18SMark Rustad hw->phy.ops.read_reg = NULL; 538b3eb4e18SMark Rustad hw->phy.ops.write_reg = NULL; 539b3eb4e18SMark Rustad return ixgbe_get_phy_id_fw(hw); 540b3eb4e18SMark Rustad } 541b3eb4e18SMark Rustad 542b3eb4e18SMark Rustad /** 543b3eb4e18SMark Rustad * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY 544b3eb4e18SMark Rustad * @hw: pointer to hardware structure 545b3eb4e18SMark Rustad * 546b3eb4e18SMark Rustad * Returns error code 547b3eb4e18SMark Rustad */ 548b3eb4e18SMark Rustad static s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw) 549b3eb4e18SMark Rustad { 550b3eb4e18SMark Rustad u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 }; 551b3eb4e18SMark Rustad 552b3eb4e18SMark Rustad setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF; 553b3eb4e18SMark Rustad return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup); 554b3eb4e18SMark Rustad } 555b3eb4e18SMark Rustad 556b3eb4e18SMark Rustad /** 557b3eb4e18SMark Rustad * ixgbe_setup_fw_link - Setup firmware-controlled PHYs 558b3eb4e18SMark Rustad * @hw: pointer to hardware structure 559b3eb4e18SMark Rustad */ 560b3eb4e18SMark Rustad static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw) 561b3eb4e18SMark Rustad { 562b3eb4e18SMark Rustad u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 }; 563b3eb4e18SMark Rustad s32 rc; 564b3eb4e18SMark Rustad u16 i; 565b3eb4e18SMark Rustad 566b3eb4e18SMark Rustad if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) 567b3eb4e18SMark Rustad return 0; 568b3eb4e18SMark Rustad 569b3eb4e18SMark Rustad if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 570b3eb4e18SMark Rustad hw_err(hw, "rx_pause not valid in strict IEEE mode\n"); 571b3eb4e18SMark Rustad return IXGBE_ERR_INVALID_LINK_SETTINGS; 572b3eb4e18SMark Rustad } 573b3eb4e18SMark Rustad 574b3eb4e18SMark Rustad switch (hw->fc.requested_mode) { 575b3eb4e18SMark Rustad case ixgbe_fc_full: 576b3eb4e18SMark Rustad setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX << 577b3eb4e18SMark Rustad FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 578b3eb4e18SMark Rustad break; 579b3eb4e18SMark Rustad case ixgbe_fc_rx_pause: 580b3eb4e18SMark Rustad setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX << 581b3eb4e18SMark Rustad FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 582b3eb4e18SMark Rustad break; 583b3eb4e18SMark Rustad case ixgbe_fc_tx_pause: 584b3eb4e18SMark Rustad setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX << 585b3eb4e18SMark Rustad FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 586b3eb4e18SMark Rustad break; 587b3eb4e18SMark Rustad default: 588b3eb4e18SMark Rustad break; 589b3eb4e18SMark Rustad } 590b3eb4e18SMark Rustad 591b3eb4e18SMark Rustad for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) { 592b3eb4e18SMark Rustad if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed) 593b3eb4e18SMark Rustad setup[0] |= ixgbe_fw_map[i].fw_speed; 594b3eb4e18SMark Rustad } 595b3eb4e18SMark Rustad setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN; 596b3eb4e18SMark Rustad 597b3eb4e18SMark Rustad if (hw->phy.eee_speeds_advertised) 598b3eb4e18SMark Rustad setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE; 599b3eb4e18SMark Rustad 600b3eb4e18SMark Rustad rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup); 601b3eb4e18SMark Rustad if (rc) 602b3eb4e18SMark Rustad return rc; 603b3eb4e18SMark Rustad if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN) 604b3eb4e18SMark Rustad return IXGBE_ERR_OVERTEMP; 605b3eb4e18SMark Rustad return 0; 606b3eb4e18SMark Rustad } 607b3eb4e18SMark Rustad 608b3eb4e18SMark Rustad /** 609b3eb4e18SMark Rustad * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs 610b3eb4e18SMark Rustad * @hw: pointer to hardware structure 611b3eb4e18SMark Rustad * 612b3eb4e18SMark Rustad * Called at init time to set up flow control. 613b3eb4e18SMark Rustad */ 614b3eb4e18SMark Rustad static s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw) 615b3eb4e18SMark Rustad { 616b3eb4e18SMark Rustad if (hw->fc.requested_mode == ixgbe_fc_default) 617b3eb4e18SMark Rustad hw->fc.requested_mode = ixgbe_fc_full; 618b3eb4e18SMark Rustad 619b3eb4e18SMark Rustad return ixgbe_setup_fw_link(hw); 620b3eb4e18SMark Rustad } 621b3eb4e18SMark Rustad 6226a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 6236a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6246a14ee0cSDon Skidmore * 6256a14ee0cSDon Skidmore * Initializes the EEPROM parameters ixgbe_eeprom_info within the 6266a14ee0cSDon Skidmore * ixgbe_hw struct in order to set up EEPROM access. 6276a14ee0cSDon Skidmore **/ 6287ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 6296a14ee0cSDon Skidmore { 6306a14ee0cSDon Skidmore struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 6316a14ee0cSDon Skidmore u32 eec; 6326a14ee0cSDon Skidmore u16 eeprom_size; 6336a14ee0cSDon Skidmore 6346a14ee0cSDon Skidmore if (eeprom->type == ixgbe_eeprom_uninitialized) { 6356a14ee0cSDon Skidmore eeprom->semaphore_delay = 10; 6366a14ee0cSDon Skidmore eeprom->type = ixgbe_flash; 6376a14ee0cSDon Skidmore 6389a900ecaSDon Skidmore eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 6396a14ee0cSDon Skidmore eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 6406a14ee0cSDon Skidmore IXGBE_EEC_SIZE_SHIFT); 641b4f47a48SJacob Keller eeprom->word_size = BIT(eeprom_size + 6426a14ee0cSDon Skidmore IXGBE_EEPROM_WORD_SIZE_SHIFT); 6436a14ee0cSDon Skidmore 6446a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 6456a14ee0cSDon Skidmore eeprom->type, eeprom->word_size); 6466a14ee0cSDon Skidmore } 6476a14ee0cSDon Skidmore 6486a14ee0cSDon Skidmore return 0; 6496a14ee0cSDon Skidmore } 6506a14ee0cSDon Skidmore 651ae14a1d8SMark Rustad /** 652ae14a1d8SMark Rustad * ixgbe_iosf_wait - Wait for IOSF command completion 653ae14a1d8SMark Rustad * @hw: pointer to hardware structure 654ae14a1d8SMark Rustad * @ctrl: pointer to location to receive final IOSF control value 655ae14a1d8SMark Rustad * 656ae14a1d8SMark Rustad * Return: failing status on timeout 657ae14a1d8SMark Rustad * 658ae14a1d8SMark Rustad * Note: ctrl can be NULL if the IOSF control register value is not needed 659ae14a1d8SMark Rustad */ 660ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 661ae14a1d8SMark Rustad { 662ae14a1d8SMark Rustad u32 i, command; 663ae14a1d8SMark Rustad 664ae14a1d8SMark Rustad /* Check every 10 usec to see if the address cycle completed. 665ae14a1d8SMark Rustad * The SB IOSF BUSY bit will clear when the operation is 666ae14a1d8SMark Rustad * complete. 667ae14a1d8SMark Rustad */ 668ae14a1d8SMark Rustad for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 669ae14a1d8SMark Rustad command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 670ae14a1d8SMark Rustad if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 671ae14a1d8SMark Rustad break; 672d90b5b0eSMark Rustad udelay(10); 673ae14a1d8SMark Rustad } 674ae14a1d8SMark Rustad if (ctrl) 675ae14a1d8SMark Rustad *ctrl = command; 676ae14a1d8SMark Rustad if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 677ae14a1d8SMark Rustad hw_dbg(hw, "IOSF wait timed out\n"); 678ae14a1d8SMark Rustad return IXGBE_ERR_PHY; 679ae14a1d8SMark Rustad } 680ae14a1d8SMark Rustad 681ae14a1d8SMark Rustad return 0; 682ae14a1d8SMark Rustad } 683ae14a1d8SMark Rustad 6846a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 6856a14ee0cSDon Skidmore * IOSF device 6866a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6876a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 6886a14ee0cSDon Skidmore * @device_type: 3 bit device type 6896a14ee0cSDon Skidmore * @phy_data: Pointer to read data from the register 6906a14ee0cSDon Skidmore **/ 6917ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 6926a14ee0cSDon Skidmore u32 device_type, u32 *data) 6936a14ee0cSDon Skidmore { 694ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 695ae14a1d8SMark Rustad u32 command, error; 696ae14a1d8SMark Rustad s32 ret; 697ae14a1d8SMark Rustad 698ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 699ae14a1d8SMark Rustad if (ret) 700ae14a1d8SMark Rustad return ret; 701ae14a1d8SMark Rustad 702ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 703ae14a1d8SMark Rustad if (ret) 704ae14a1d8SMark Rustad goto out; 7056a14ee0cSDon Skidmore 7066a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 7076a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 7086a14ee0cSDon Skidmore 7096a14ee0cSDon Skidmore /* Write IOSF control register */ 7106a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 7116a14ee0cSDon Skidmore 712ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 7136a14ee0cSDon Skidmore 7146a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 7156a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 7166a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 7176a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read, error %x\n", error); 7186a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 7196a14ee0cSDon Skidmore } 7206a14ee0cSDon Skidmore 721ae14a1d8SMark Rustad if (!ret) 7226a14ee0cSDon Skidmore *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 7236a14ee0cSDon Skidmore 724ae14a1d8SMark Rustad out: 725ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 726ae14a1d8SMark Rustad return ret; 7276a14ee0cSDon Skidmore } 7286a14ee0cSDon Skidmore 72949425dfcSMark Rustad /** 73049425dfcSMark Rustad * ixgbe_get_phy_token - Get the token for shared PHY access 73149425dfcSMark Rustad * @hw: Pointer to hardware structure 73249425dfcSMark Rustad */ 73349425dfcSMark Rustad static s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) 73449425dfcSMark Rustad { 73549425dfcSMark Rustad struct ixgbe_hic_phy_token_req token_cmd; 73649425dfcSMark Rustad s32 status; 73749425dfcSMark Rustad 73849425dfcSMark Rustad token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 73949425dfcSMark Rustad token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 74049425dfcSMark Rustad token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 74149425dfcSMark Rustad token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 74249425dfcSMark Rustad token_cmd.port_number = hw->bus.lan_id; 74349425dfcSMark Rustad token_cmd.command_type = FW_PHY_TOKEN_REQ; 74449425dfcSMark Rustad token_cmd.pad = 0; 74549425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 74649425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 74749425dfcSMark Rustad true); 74849425dfcSMark Rustad if (status) 74949425dfcSMark Rustad return status; 75049425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 75149425dfcSMark Rustad return 0; 75249425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) 75349425dfcSMark Rustad return IXGBE_ERR_FW_RESP_INVALID; 75449425dfcSMark Rustad 75549425dfcSMark Rustad return IXGBE_ERR_TOKEN_RETRY; 75649425dfcSMark Rustad } 75749425dfcSMark Rustad 75849425dfcSMark Rustad /** 75949425dfcSMark Rustad * ixgbe_put_phy_token - Put the token for shared PHY access 76049425dfcSMark Rustad * @hw: Pointer to hardware structure 76149425dfcSMark Rustad */ 76249425dfcSMark Rustad static s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) 76349425dfcSMark Rustad { 76449425dfcSMark Rustad struct ixgbe_hic_phy_token_req token_cmd; 76549425dfcSMark Rustad s32 status; 76649425dfcSMark Rustad 76749425dfcSMark Rustad token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 76849425dfcSMark Rustad token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 76949425dfcSMark Rustad token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 77049425dfcSMark Rustad token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 77149425dfcSMark Rustad token_cmd.port_number = hw->bus.lan_id; 77249425dfcSMark Rustad token_cmd.command_type = FW_PHY_TOKEN_REL; 77349425dfcSMark Rustad token_cmd.pad = 0; 77449425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), 77549425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, 77649425dfcSMark Rustad true); 77749425dfcSMark Rustad if (status) 77849425dfcSMark Rustad return status; 77949425dfcSMark Rustad if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 78049425dfcSMark Rustad return 0; 78149425dfcSMark Rustad return IXGBE_ERR_FW_RESP_INVALID; 78249425dfcSMark Rustad } 78349425dfcSMark Rustad 78449425dfcSMark Rustad /** 78549425dfcSMark Rustad * ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register 78649425dfcSMark Rustad * @hw: pointer to hardware structure 78749425dfcSMark Rustad * @reg_addr: 32 bit PHY register to write 78849425dfcSMark Rustad * @device_type: 3 bit device type 78949425dfcSMark Rustad * @data: Data to write to the register 79049425dfcSMark Rustad **/ 79149425dfcSMark Rustad static s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 79249425dfcSMark Rustad __always_unused u32 device_type, 79349425dfcSMark Rustad u32 data) 79449425dfcSMark Rustad { 79549425dfcSMark Rustad struct ixgbe_hic_internal_phy_req write_cmd; 79649425dfcSMark Rustad 79749425dfcSMark Rustad memset(&write_cmd, 0, sizeof(write_cmd)); 79849425dfcSMark Rustad write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 79949425dfcSMark Rustad write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 80049425dfcSMark Rustad write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 80149425dfcSMark Rustad write_cmd.port_number = hw->bus.lan_id; 80249425dfcSMark Rustad write_cmd.command_type = FW_INT_PHY_REQ_WRITE; 80349425dfcSMark Rustad write_cmd.address = cpu_to_be16(reg_addr); 80449425dfcSMark Rustad write_cmd.write_data = cpu_to_be32(data); 80549425dfcSMark Rustad 80649425dfcSMark Rustad return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd), 80749425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, false); 80849425dfcSMark Rustad } 80949425dfcSMark Rustad 81049425dfcSMark Rustad /** 81149425dfcSMark Rustad * ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register 81249425dfcSMark Rustad * @hw: pointer to hardware structure 81349425dfcSMark Rustad * @reg_addr: 32 bit PHY register to write 81449425dfcSMark Rustad * @device_type: 3 bit device type 81549425dfcSMark Rustad * @data: Pointer to read data from the register 81649425dfcSMark Rustad **/ 81749425dfcSMark Rustad static s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 81849425dfcSMark Rustad __always_unused u32 device_type, 81949425dfcSMark Rustad u32 *data) 82049425dfcSMark Rustad { 82149425dfcSMark Rustad union { 82249425dfcSMark Rustad struct ixgbe_hic_internal_phy_req cmd; 82349425dfcSMark Rustad struct ixgbe_hic_internal_phy_resp rsp; 82449425dfcSMark Rustad } hic; 82549425dfcSMark Rustad s32 status; 82649425dfcSMark Rustad 82749425dfcSMark Rustad memset(&hic, 0, sizeof(hic)); 82849425dfcSMark Rustad hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 82949425dfcSMark Rustad hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 83049425dfcSMark Rustad hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 83149425dfcSMark Rustad hic.cmd.port_number = hw->bus.lan_id; 83249425dfcSMark Rustad hic.cmd.command_type = FW_INT_PHY_REQ_READ; 83349425dfcSMark Rustad hic.cmd.address = cpu_to_be16(reg_addr); 83449425dfcSMark Rustad 83549425dfcSMark Rustad status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), 83649425dfcSMark Rustad IXGBE_HI_COMMAND_TIMEOUT, true); 83749425dfcSMark Rustad 83849425dfcSMark Rustad /* Extract the register value from the response. */ 83949425dfcSMark Rustad *data = be32_to_cpu(hic.rsp.read_data); 84049425dfcSMark Rustad 84149425dfcSMark Rustad return status; 84249425dfcSMark Rustad } 84349425dfcSMark Rustad 8446a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 8456a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8466a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 8476a14ee0cSDon Skidmore * @words: number of words 8486a14ee0cSDon Skidmore * @data: word(s) read from the EEPROM 8496a14ee0cSDon Skidmore * 8506a14ee0cSDon Skidmore * Reads a 16 bit word(s) from the EEPROM using the hostif. 8516a14ee0cSDon Skidmore **/ 8527ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 8536a14ee0cSDon Skidmore u16 offset, u16 words, u16 *data) 8546a14ee0cSDon Skidmore { 8553efa9ed2SMark Rustad const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; 8566a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 8576a14ee0cSDon Skidmore u32 current_word = 0; 8586a14ee0cSDon Skidmore u16 words_to_read; 8596a14ee0cSDon Skidmore s32 status; 8606a14ee0cSDon Skidmore u32 i; 8616a14ee0cSDon Skidmore 8626a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 8633efa9ed2SMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, mask); 8646a14ee0cSDon Skidmore if (status) { 8656a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 8666a14ee0cSDon Skidmore return status; 8676a14ee0cSDon Skidmore } 8686a14ee0cSDon Skidmore 8696a14ee0cSDon Skidmore while (words) { 8706a14ee0cSDon Skidmore if (words > FW_MAX_READ_BUFFER_SIZE / 2) 8716a14ee0cSDon Skidmore words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 8726a14ee0cSDon Skidmore else 8736a14ee0cSDon Skidmore words_to_read = words; 8746a14ee0cSDon Skidmore 8756a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 8766a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 8776a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 8786a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 8796a14ee0cSDon Skidmore 8806a14ee0cSDon Skidmore /* convert offset from words to bytes */ 8819cfbfa70SCathy Zhou buffer.address = (__force u32)cpu_to_be32((offset + 8829cfbfa70SCathy Zhou current_word) * 2); 8839cfbfa70SCathy Zhou buffer.length = (__force u16)cpu_to_be16(words_to_read * 2); 884dcfd6b83SEmil Tantilov buffer.pad2 = 0; 885dcfd6b83SEmil Tantilov buffer.pad3 = 0; 8866a14ee0cSDon Skidmore 8873efa9ed2SMark Rustad status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), 8883efa9ed2SMark Rustad IXGBE_HI_COMMAND_TIMEOUT); 8896a14ee0cSDon Skidmore if (status) { 8906a14ee0cSDon Skidmore hw_dbg(hw, "Host interface command failed\n"); 8916a14ee0cSDon Skidmore goto out; 8926a14ee0cSDon Skidmore } 8936a14ee0cSDon Skidmore 8946a14ee0cSDon Skidmore for (i = 0; i < words_to_read; i++) { 8956a14ee0cSDon Skidmore u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 8966a14ee0cSDon Skidmore 2 * i; 8976a14ee0cSDon Skidmore u32 value = IXGBE_READ_REG(hw, reg); 8986a14ee0cSDon Skidmore 8996a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 9006a14ee0cSDon Skidmore current_word++; 9016a14ee0cSDon Skidmore i++; 9026a14ee0cSDon Skidmore if (i < words_to_read) { 9036a14ee0cSDon Skidmore value >>= 16; 9046a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 9056a14ee0cSDon Skidmore current_word++; 9066a14ee0cSDon Skidmore } 9076a14ee0cSDon Skidmore } 9086a14ee0cSDon Skidmore words -= words_to_read; 9096a14ee0cSDon Skidmore } 9106a14ee0cSDon Skidmore 9116a14ee0cSDon Skidmore out: 9123efa9ed2SMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 9136a14ee0cSDon Skidmore return status; 9146a14ee0cSDon Skidmore } 9156a14ee0cSDon Skidmore 9166a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region 9176a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9186a14ee0cSDon Skidmore * @ptr: pointer offset in eeprom 9196a14ee0cSDon Skidmore * @size: size of section pointed by ptr, if 0 first word will be used as size 9206a14ee0cSDon Skidmore * @csum: address of checksum to update 9216a14ee0cSDon Skidmore * 9226a14ee0cSDon Skidmore * Returns error status for any failure 9236a14ee0cSDon Skidmore **/ 9246a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 9256a14ee0cSDon Skidmore u16 size, u16 *csum, u16 *buffer, 9266a14ee0cSDon Skidmore u32 buffer_size) 9276a14ee0cSDon Skidmore { 9286a14ee0cSDon Skidmore u16 buf[256]; 9296a14ee0cSDon Skidmore s32 status; 9306a14ee0cSDon Skidmore u16 length, bufsz, i, start; 9316a14ee0cSDon Skidmore u16 *local_buffer; 9326a14ee0cSDon Skidmore 933f0e49dc3SColin Ian King bufsz = ARRAY_SIZE(buf); 9346a14ee0cSDon Skidmore 9356a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 9366a14ee0cSDon Skidmore if (!buffer) { 9376a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 9386a14ee0cSDon Skidmore if (status) { 9396a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 9406a14ee0cSDon Skidmore return status; 9416a14ee0cSDon Skidmore } 9426a14ee0cSDon Skidmore local_buffer = buf; 9436a14ee0cSDon Skidmore } else { 9446a14ee0cSDon Skidmore if (buffer_size < ptr) 9456a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 9466a14ee0cSDon Skidmore local_buffer = &buffer[ptr]; 9476a14ee0cSDon Skidmore } 9486a14ee0cSDon Skidmore 9496a14ee0cSDon Skidmore if (size) { 9506a14ee0cSDon Skidmore start = 0; 9516a14ee0cSDon Skidmore length = size; 9526a14ee0cSDon Skidmore } else { 9536a14ee0cSDon Skidmore start = 1; 9546a14ee0cSDon Skidmore length = local_buffer[0]; 9556a14ee0cSDon Skidmore 9566a14ee0cSDon Skidmore /* Skip pointer section if length is invalid. */ 9576a14ee0cSDon Skidmore if (length == 0xFFFF || length == 0 || 9586a14ee0cSDon Skidmore (ptr + length) >= hw->eeprom.word_size) 9596a14ee0cSDon Skidmore return 0; 9606a14ee0cSDon Skidmore } 9616a14ee0cSDon Skidmore 9626a14ee0cSDon Skidmore if (buffer && ((u32)start + (u32)length > buffer_size)) 9636a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 9646a14ee0cSDon Skidmore 9656a14ee0cSDon Skidmore for (i = start; length; i++, length--) { 9666a14ee0cSDon Skidmore if (i == bufsz && !buffer) { 9676a14ee0cSDon Skidmore ptr += bufsz; 9686a14ee0cSDon Skidmore i = 0; 9696a14ee0cSDon Skidmore if (length < bufsz) 9706a14ee0cSDon Skidmore bufsz = length; 9716a14ee0cSDon Skidmore 9726a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 9736a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 9746a14ee0cSDon Skidmore bufsz, buf); 9756a14ee0cSDon Skidmore if (status) { 9766a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 9776a14ee0cSDon Skidmore return status; 9786a14ee0cSDon Skidmore } 9796a14ee0cSDon Skidmore } 9806a14ee0cSDon Skidmore *csum += local_buffer[i]; 9816a14ee0cSDon Skidmore } 9826a14ee0cSDon Skidmore return 0; 9836a14ee0cSDon Skidmore } 9846a14ee0cSDon Skidmore 9856a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 9866a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9876a14ee0cSDon Skidmore * @buffer: pointer to buffer containing calculated checksum 9886a14ee0cSDon Skidmore * @buffer_size: size of buffer 9896a14ee0cSDon Skidmore * 9906a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 9916a14ee0cSDon Skidmore **/ 9927ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 9937ddbde3fSDon Skidmore u32 buffer_size) 9946a14ee0cSDon Skidmore { 9956a14ee0cSDon Skidmore u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 9966a14ee0cSDon Skidmore u16 *local_buffer; 9976a14ee0cSDon Skidmore s32 status; 9986a14ee0cSDon Skidmore u16 checksum = 0; 9996a14ee0cSDon Skidmore u16 pointer, i, size; 10006a14ee0cSDon Skidmore 10016a14ee0cSDon Skidmore hw->eeprom.ops.init_params(hw); 10026a14ee0cSDon Skidmore 10036a14ee0cSDon Skidmore if (!buffer) { 10046a14ee0cSDon Skidmore /* Read pointer area */ 10056a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 10066a14ee0cSDon Skidmore IXGBE_EEPROM_LAST_WORD + 1, 10076a14ee0cSDon Skidmore eeprom_ptrs); 10086a14ee0cSDon Skidmore if (status) { 10096a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 10106a14ee0cSDon Skidmore return status; 10116a14ee0cSDon Skidmore } 10126a14ee0cSDon Skidmore local_buffer = eeprom_ptrs; 10136a14ee0cSDon Skidmore } else { 10146a14ee0cSDon Skidmore if (buffer_size < IXGBE_EEPROM_LAST_WORD) 10156a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 10166a14ee0cSDon Skidmore local_buffer = buffer; 10176a14ee0cSDon Skidmore } 10186a14ee0cSDon Skidmore 10196a14ee0cSDon Skidmore /* For X550 hardware include 0x0-0x41 in the checksum, skip the 10206a14ee0cSDon Skidmore * checksum word itself 10216a14ee0cSDon Skidmore */ 10226a14ee0cSDon Skidmore for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 10236a14ee0cSDon Skidmore if (i != IXGBE_EEPROM_CHECKSUM) 10246a14ee0cSDon Skidmore checksum += local_buffer[i]; 10256a14ee0cSDon Skidmore 10266a14ee0cSDon Skidmore /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 10276a14ee0cSDon Skidmore * FW, PHY module, and PCIe Expansion/Option ROM pointers. 10286a14ee0cSDon Skidmore */ 10296a14ee0cSDon Skidmore for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 10306a14ee0cSDon Skidmore if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 10316a14ee0cSDon Skidmore continue; 10326a14ee0cSDon Skidmore 10336a14ee0cSDon Skidmore pointer = local_buffer[i]; 10346a14ee0cSDon Skidmore 10356a14ee0cSDon Skidmore /* Skip pointer section if the pointer is invalid. */ 10366a14ee0cSDon Skidmore if (pointer == 0xFFFF || pointer == 0 || 10376a14ee0cSDon Skidmore pointer >= hw->eeprom.word_size) 10386a14ee0cSDon Skidmore continue; 10396a14ee0cSDon Skidmore 10406a14ee0cSDon Skidmore switch (i) { 10416a14ee0cSDon Skidmore case IXGBE_PCIE_GENERAL_PTR: 10426a14ee0cSDon Skidmore size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 10436a14ee0cSDon Skidmore break; 10446a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG0_PTR: 10456a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG1_PTR: 10466a14ee0cSDon Skidmore size = IXGBE_PCIE_CONFIG_SIZE; 10476a14ee0cSDon Skidmore break; 10486a14ee0cSDon Skidmore default: 10496a14ee0cSDon Skidmore size = 0; 10506a14ee0cSDon Skidmore break; 10516a14ee0cSDon Skidmore } 10526a14ee0cSDon Skidmore 10536a14ee0cSDon Skidmore status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 10546a14ee0cSDon Skidmore buffer, buffer_size); 10556a14ee0cSDon Skidmore if (status) 10566a14ee0cSDon Skidmore return status; 10576a14ee0cSDon Skidmore } 10586a14ee0cSDon Skidmore 10596a14ee0cSDon Skidmore checksum = (u16)IXGBE_EEPROM_SUM - checksum; 10606a14ee0cSDon Skidmore 10616a14ee0cSDon Skidmore return (s32)checksum; 10626a14ee0cSDon Skidmore } 10636a14ee0cSDon Skidmore 10646a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 10656a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10666a14ee0cSDon Skidmore * 10676a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 10686a14ee0cSDon Skidmore **/ 10697ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 10706a14ee0cSDon Skidmore { 10716a14ee0cSDon Skidmore return ixgbe_calc_checksum_X550(hw, NULL, 0); 10726a14ee0cSDon Skidmore } 10736a14ee0cSDon Skidmore 10746a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 10756a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10766a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 10776a14ee0cSDon Skidmore * @data: word read from the EEPROM 10786a14ee0cSDon Skidmore * 10796a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 10806a14ee0cSDon Skidmore **/ 10817ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 10826a14ee0cSDon Skidmore { 10833efa9ed2SMark Rustad const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; 10843efa9ed2SMark Rustad struct ixgbe_hic_read_shadow_ram buffer; 10853efa9ed2SMark Rustad s32 status; 10866a14ee0cSDon Skidmore 10873efa9ed2SMark Rustad buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 10883efa9ed2SMark Rustad buffer.hdr.req.buf_lenh = 0; 10893efa9ed2SMark Rustad buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 10903efa9ed2SMark Rustad buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 10913efa9ed2SMark Rustad 10923efa9ed2SMark Rustad /* convert offset from words to bytes */ 10939cfbfa70SCathy Zhou buffer.address = (__force u32)cpu_to_be32(offset * 2); 10943efa9ed2SMark Rustad /* one word */ 10959cfbfa70SCathy Zhou buffer.length = (__force u16)cpu_to_be16(sizeof(u16)); 10963efa9ed2SMark Rustad 10973efa9ed2SMark Rustad status = hw->mac.ops.acquire_swfw_sync(hw, mask); 10983efa9ed2SMark Rustad if (status) 10993efa9ed2SMark Rustad return status; 11003efa9ed2SMark Rustad 11013efa9ed2SMark Rustad status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), 11023efa9ed2SMark Rustad IXGBE_HI_COMMAND_TIMEOUT); 11033efa9ed2SMark Rustad if (!status) { 11043efa9ed2SMark Rustad *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 11053efa9ed2SMark Rustad FW_NVM_DATA_OFFSET); 11066a14ee0cSDon Skidmore } 11076a14ee0cSDon Skidmore 11083efa9ed2SMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 11096a14ee0cSDon Skidmore return status; 11106a14ee0cSDon Skidmore } 11116a14ee0cSDon Skidmore 11126a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 11136a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11146a14ee0cSDon Skidmore * @checksum_val: calculated checksum 11156a14ee0cSDon Skidmore * 11166a14ee0cSDon Skidmore * Performs checksum calculation and validates the EEPROM checksum. If the 11176a14ee0cSDon Skidmore * caller does not need checksum_val, the value can be NULL. 11186a14ee0cSDon Skidmore **/ 11197ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 11207ddbde3fSDon Skidmore u16 *checksum_val) 11216a14ee0cSDon Skidmore { 11226a14ee0cSDon Skidmore s32 status; 11236a14ee0cSDon Skidmore u16 checksum; 11246a14ee0cSDon Skidmore u16 read_checksum = 0; 11256a14ee0cSDon Skidmore 11266a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 11276a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 11286a14ee0cSDon Skidmore * EEPROM read fails 11296a14ee0cSDon Skidmore */ 11306a14ee0cSDon Skidmore status = hw->eeprom.ops.read(hw, 0, &checksum); 11316a14ee0cSDon Skidmore if (status) { 11326a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 11336a14ee0cSDon Skidmore return status; 11346a14ee0cSDon Skidmore } 11356a14ee0cSDon Skidmore 11366a14ee0cSDon Skidmore status = hw->eeprom.ops.calc_checksum(hw); 11376a14ee0cSDon Skidmore if (status < 0) 11386a14ee0cSDon Skidmore return status; 11396a14ee0cSDon Skidmore 11406a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 11416a14ee0cSDon Skidmore 11426a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 11436a14ee0cSDon Skidmore &read_checksum); 11446a14ee0cSDon Skidmore if (status) 11456a14ee0cSDon Skidmore return status; 11466a14ee0cSDon Skidmore 11476a14ee0cSDon Skidmore /* Verify read checksum from EEPROM is the same as 11486a14ee0cSDon Skidmore * calculated checksum 11496a14ee0cSDon Skidmore */ 11506a14ee0cSDon Skidmore if (read_checksum != checksum) { 11516a14ee0cSDon Skidmore status = IXGBE_ERR_EEPROM_CHECKSUM; 11526a14ee0cSDon Skidmore hw_dbg(hw, "Invalid EEPROM checksum"); 11536a14ee0cSDon Skidmore } 11546a14ee0cSDon Skidmore 11556a14ee0cSDon Skidmore /* If the user cares, return the calculated checksum */ 11566a14ee0cSDon Skidmore if (checksum_val) 11576a14ee0cSDon Skidmore *checksum_val = checksum; 11586a14ee0cSDon Skidmore 11596a14ee0cSDon Skidmore return status; 11606a14ee0cSDon Skidmore } 11616a14ee0cSDon Skidmore 11626a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 11636a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11646a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 11656a14ee0cSDon Skidmore * @data: word write to the EEPROM 11666a14ee0cSDon Skidmore * 11676a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 11686a14ee0cSDon Skidmore **/ 11697ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 11707ddbde3fSDon Skidmore u16 data) 11716a14ee0cSDon Skidmore { 11726a14ee0cSDon Skidmore s32 status; 11736a14ee0cSDon Skidmore struct ixgbe_hic_write_shadow_ram buffer; 11746a14ee0cSDon Skidmore 11756a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 11766a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 11776a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 11786a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 11796a14ee0cSDon Skidmore 11806a14ee0cSDon Skidmore /* one word */ 11816a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 11826a14ee0cSDon Skidmore buffer.data = data; 11836a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 11846a14ee0cSDon Skidmore 11855cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 11866a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 11876a14ee0cSDon Skidmore return status; 11886a14ee0cSDon Skidmore } 11896a14ee0cSDon Skidmore 11906a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 11916a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11926a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 11936a14ee0cSDon Skidmore * @data: word write to the EEPROM 11946a14ee0cSDon Skidmore * 11956a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 11966a14ee0cSDon Skidmore **/ 11977ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 11986a14ee0cSDon Skidmore { 11996a14ee0cSDon Skidmore s32 status = 0; 12006a14ee0cSDon Skidmore 12016a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 12026a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 12036a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 12046a14ee0cSDon Skidmore } else { 12056a14ee0cSDon Skidmore hw_dbg(hw, "write ee hostif failed to get semaphore"); 12066a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 12076a14ee0cSDon Skidmore } 12086a14ee0cSDon Skidmore 12096a14ee0cSDon Skidmore return status; 12106a14ee0cSDon Skidmore } 12116a14ee0cSDon Skidmore 12126a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 12136a14ee0cSDon Skidmore * @hw: pointer to hardware structure 12146a14ee0cSDon Skidmore * 12156a14ee0cSDon Skidmore * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 12166a14ee0cSDon Skidmore **/ 12177ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 12186a14ee0cSDon Skidmore { 12196a14ee0cSDon Skidmore s32 status = 0; 12206a14ee0cSDon Skidmore union ixgbe_hic_hdr2 buffer; 12216a14ee0cSDon Skidmore 12226a14ee0cSDon Skidmore buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 12236a14ee0cSDon Skidmore buffer.req.buf_lenh = 0; 12246a14ee0cSDon Skidmore buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 12256a14ee0cSDon Skidmore buffer.req.checksum = FW_DEFAULT_CHECKSUM; 12266a14ee0cSDon Skidmore 12275cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), 12286a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 12296a14ee0cSDon Skidmore return status; 12306a14ee0cSDon Skidmore } 12316a14ee0cSDon Skidmore 1232454c65ddSDon Skidmore /** 1233454c65ddSDon Skidmore * ixgbe_get_bus_info_X550em - Set PCI bus info 1234454c65ddSDon Skidmore * @hw: pointer to hardware structure 1235454c65ddSDon Skidmore * 1236454c65ddSDon Skidmore * Sets bus link width and speed to unknown because X550em is 1237454c65ddSDon Skidmore * not a PCI device. 1238454c65ddSDon Skidmore **/ 1239454c65ddSDon Skidmore static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) 1240454c65ddSDon Skidmore { 1241f9328bc6SDon Skidmore hw->bus.type = ixgbe_bus_type_internal; 1242454c65ddSDon Skidmore hw->bus.width = ixgbe_bus_width_unknown; 1243454c65ddSDon Skidmore hw->bus.speed = ixgbe_bus_speed_unknown; 1244454c65ddSDon Skidmore 1245454c65ddSDon Skidmore hw->mac.ops.set_lan_id(hw); 1246454c65ddSDon Skidmore 1247454c65ddSDon Skidmore return 0; 1248454c65ddSDon Skidmore } 1249454c65ddSDon Skidmore 125059dd45d5SSebastian Basierski /** 1251262de08fSJesse Brandeburg * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode 125259dd45d5SSebastian Basierski * @hw: pointer t hardware structure 125359dd45d5SSebastian Basierski * 125459dd45d5SSebastian Basierski * Returns true if in FW NVM recovery mode. 125559dd45d5SSebastian Basierski */ 125659dd45d5SSebastian Basierski static bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw) 125759dd45d5SSebastian Basierski { 125859dd45d5SSebastian Basierski u32 fwsm; 125959dd45d5SSebastian Basierski 126059dd45d5SSebastian Basierski fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw)); 126159dd45d5SSebastian Basierski return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE); 126259dd45d5SSebastian Basierski } 126359dd45d5SSebastian Basierski 12641f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit 12651f9ac57cSDon Skidmore * 12661f9ac57cSDon Skidmore * Enables the Rx DMA unit for x550 12671f9ac57cSDon Skidmore **/ 12681f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 12691f9ac57cSDon Skidmore { 12701f9ac57cSDon Skidmore u32 rxctrl, pfdtxgswc; 12711f9ac57cSDon Skidmore s32 status; 12721f9ac57cSDon Skidmore struct ixgbe_hic_disable_rxen fw_cmd; 12731f9ac57cSDon Skidmore 12741f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 12751f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 12761f9ac57cSDon Skidmore pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 12771f9ac57cSDon Skidmore if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 12781f9ac57cSDon Skidmore pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 12791f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 12801f9ac57cSDon Skidmore hw->mac.set_lben = true; 12811f9ac57cSDon Skidmore } else { 12821f9ac57cSDon Skidmore hw->mac.set_lben = false; 12831f9ac57cSDon Skidmore } 12841f9ac57cSDon Skidmore 12851f9ac57cSDon Skidmore fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 12861f9ac57cSDon Skidmore fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 12871f9ac57cSDon Skidmore fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 12883775b814SMark Rustad fw_cmd.port_number = hw->bus.lan_id; 12891f9ac57cSDon Skidmore 12905cffde30SMark Rustad status = ixgbe_host_interface_command(hw, &fw_cmd, 12911f9ac57cSDon Skidmore sizeof(struct ixgbe_hic_disable_rxen), 12921f9ac57cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, true); 12931f9ac57cSDon Skidmore 12941f9ac57cSDon Skidmore /* If we fail - disable RX using register write */ 12951f9ac57cSDon Skidmore if (status) { 12961f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 12971f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 12981f9ac57cSDon Skidmore rxctrl &= ~IXGBE_RXCTRL_RXEN; 12991f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 13001f9ac57cSDon Skidmore } 13011f9ac57cSDon Skidmore } 13021f9ac57cSDon Skidmore } 13031f9ac57cSDon Skidmore } 13041f9ac57cSDon Skidmore 13056a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 13066a14ee0cSDon Skidmore * @hw: pointer to hardware structure 13076a14ee0cSDon Skidmore * 13086a14ee0cSDon Skidmore * After writing EEPROM to shadow RAM using EEWR register, software calculates 13096a14ee0cSDon Skidmore * checksum and updates the EEPROM and instructs the hardware to update 13106a14ee0cSDon Skidmore * the flash. 13116a14ee0cSDon Skidmore **/ 13127ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 13136a14ee0cSDon Skidmore { 13146a14ee0cSDon Skidmore s32 status; 13156a14ee0cSDon Skidmore u16 checksum = 0; 13166a14ee0cSDon Skidmore 13176a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 13186a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 13196a14ee0cSDon Skidmore * EEPROM read fails 13206a14ee0cSDon Skidmore */ 13216a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 13226a14ee0cSDon Skidmore if (status) { 13236a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 13246a14ee0cSDon Skidmore return status; 13256a14ee0cSDon Skidmore } 13266a14ee0cSDon Skidmore 13276a14ee0cSDon Skidmore status = ixgbe_calc_eeprom_checksum_X550(hw); 13286a14ee0cSDon Skidmore if (status < 0) 13296a14ee0cSDon Skidmore return status; 13306a14ee0cSDon Skidmore 13316a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 13326a14ee0cSDon Skidmore 13336a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 13346a14ee0cSDon Skidmore checksum); 13356a14ee0cSDon Skidmore if (status) 13366a14ee0cSDon Skidmore return status; 13376a14ee0cSDon Skidmore 13386a14ee0cSDon Skidmore status = ixgbe_update_flash_X550(hw); 13396a14ee0cSDon Skidmore 13406a14ee0cSDon Skidmore return status; 13416a14ee0cSDon Skidmore } 13426a14ee0cSDon Skidmore 13436a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 13446a14ee0cSDon Skidmore * @hw: pointer to hardware structure 13456a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 13466a14ee0cSDon Skidmore * @words: number of words 13476a14ee0cSDon Skidmore * @data: word(s) write to the EEPROM 13486a14ee0cSDon Skidmore * 13496a14ee0cSDon Skidmore * 13506a14ee0cSDon Skidmore * Write a 16 bit word(s) to the EEPROM using the hostif. 13516a14ee0cSDon Skidmore **/ 13527ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 13537ddbde3fSDon Skidmore u16 offset, u16 words, 13547ddbde3fSDon Skidmore u16 *data) 13556a14ee0cSDon Skidmore { 13566a14ee0cSDon Skidmore s32 status = 0; 13576a14ee0cSDon Skidmore u32 i = 0; 13586a14ee0cSDon Skidmore 13596a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 13606a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 13616a14ee0cSDon Skidmore if (status) { 13626a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 13636a14ee0cSDon Skidmore return status; 13646a14ee0cSDon Skidmore } 13656a14ee0cSDon Skidmore 13666a14ee0cSDon Skidmore for (i = 0; i < words; i++) { 13676a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 13686a14ee0cSDon Skidmore data[i]); 13696a14ee0cSDon Skidmore if (status) { 13706a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom buffered write failed\n"); 13716a14ee0cSDon Skidmore break; 13726a14ee0cSDon Skidmore } 13736a14ee0cSDon Skidmore } 13746a14ee0cSDon Skidmore 13756a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 13766a14ee0cSDon Skidmore 13776a14ee0cSDon Skidmore return status; 13786a14ee0cSDon Skidmore } 13796a14ee0cSDon Skidmore 13806a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 13816a14ee0cSDon Skidmore * IOSF device 13826a14ee0cSDon Skidmore * 13836a14ee0cSDon Skidmore * @hw: pointer to hardware structure 13846a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 13856a14ee0cSDon Skidmore * @device_type: 3 bit device type 13866a14ee0cSDon Skidmore * @data: Data to write to the register 13876a14ee0cSDon Skidmore **/ 13887ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 13896a14ee0cSDon Skidmore u32 device_type, u32 data) 13906a14ee0cSDon Skidmore { 1391ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 1392ae14a1d8SMark Rustad u32 command, error; 1393ae14a1d8SMark Rustad s32 ret; 1394ae14a1d8SMark Rustad 1395ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 1396ae14a1d8SMark Rustad if (ret) 1397ae14a1d8SMark Rustad return ret; 1398ae14a1d8SMark Rustad 1399ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 1400ae14a1d8SMark Rustad if (ret) 1401ae14a1d8SMark Rustad goto out; 14026a14ee0cSDon Skidmore 14036a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 14046a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 14056a14ee0cSDon Skidmore 14066a14ee0cSDon Skidmore /* Write IOSF control register */ 14076a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 14086a14ee0cSDon Skidmore 14096a14ee0cSDon Skidmore /* Write IOSF data register */ 14106a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 14116a14ee0cSDon Skidmore 1412ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 14136a14ee0cSDon Skidmore 14146a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 14156a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 14166a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 14176a14ee0cSDon Skidmore hw_dbg(hw, "Failed to write, error %x\n", error); 14186a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 14196a14ee0cSDon Skidmore } 14206a14ee0cSDon Skidmore 1421ae14a1d8SMark Rustad out: 1422ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 1423ae14a1d8SMark Rustad return ret; 14246a14ee0cSDon Skidmore } 14256a14ee0cSDon Skidmore 14260c1b7de4SDon Skidmore /** 14270c1b7de4SDon Skidmore * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration 14286a14ee0cSDon Skidmore * @hw: pointer to hardware structure 14296a14ee0cSDon Skidmore * 14300c1b7de4SDon Skidmore * iXfI configuration needed for ixgbe_mac_X550EM_x devices. 14316a14ee0cSDon Skidmore **/ 14320c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) 14336a14ee0cSDon Skidmore { 14346a14ee0cSDon Skidmore s32 status; 14356a14ee0cSDon Skidmore u32 reg_val; 14366a14ee0cSDon Skidmore 14376a14ee0cSDon Skidmore /* Disable training protocol FSM. */ 14386a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 14396a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 14406a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 14416a14ee0cSDon Skidmore if (status) 14426a14ee0cSDon Skidmore return status; 14436a14ee0cSDon Skidmore 14446a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 14456a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 14466a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 14476a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 14486a14ee0cSDon Skidmore if (status) 14496a14ee0cSDon Skidmore return status; 14506a14ee0cSDon Skidmore 14516a14ee0cSDon Skidmore /* Disable Flex from training TXFFE. */ 14526a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 14536a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 14546a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 14556a14ee0cSDon Skidmore if (status) 14566a14ee0cSDon Skidmore return status; 14576a14ee0cSDon Skidmore 14586a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 14596a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 14606a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 14616a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 14626a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 14636a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 14646a14ee0cSDon Skidmore if (status) 14656a14ee0cSDon Skidmore return status; 14666a14ee0cSDon Skidmore 14676a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 14686a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 14696a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 14706a14ee0cSDon Skidmore if (status) 14716a14ee0cSDon Skidmore return status; 14726a14ee0cSDon Skidmore 14736a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 14746a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 14756a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 14766a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 14776a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 14786a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 14796a14ee0cSDon Skidmore if (status) 14806a14ee0cSDon Skidmore return status; 14816a14ee0cSDon Skidmore 14826a14ee0cSDon Skidmore /* Enable override for coefficients. */ 14836a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 14846a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 14856a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 14866a14ee0cSDon Skidmore if (status) 14876a14ee0cSDon Skidmore return status; 14886a14ee0cSDon Skidmore 14896a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 14906a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 14916a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 14926a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 14936a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 14946a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 14956a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 14960c1b7de4SDon Skidmore return status; 14970c1b7de4SDon Skidmore } 14980c1b7de4SDon Skidmore 1499470739b5SDon Skidmore /** 1500470739b5SDon Skidmore * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the 1501470739b5SDon Skidmore * internal PHY 1502470739b5SDon Skidmore * @hw: pointer to hardware structure 1503470739b5SDon Skidmore **/ 1504470739b5SDon Skidmore static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw) 1505470739b5SDon Skidmore { 1506470739b5SDon Skidmore s32 status; 1507470739b5SDon Skidmore u32 link_ctrl; 1508470739b5SDon Skidmore 1509470739b5SDon Skidmore /* Restart auto-negotiation. */ 1510470739b5SDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 1511470739b5SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1512470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); 1513470739b5SDon Skidmore 1514470739b5SDon Skidmore if (status) { 1515470739b5SDon Skidmore hw_dbg(hw, "Auto-negotiation did not complete\n"); 1516470739b5SDon Skidmore return status; 1517470739b5SDon Skidmore } 1518470739b5SDon Skidmore 1519470739b5SDon Skidmore link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 1520470739b5SDon Skidmore status = hw->mac.ops.write_iosf_sb_reg(hw, 1521470739b5SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1522470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); 1523470739b5SDon Skidmore 1524470739b5SDon Skidmore if (hw->mac.type == ixgbe_mac_x550em_a) { 1525470739b5SDon Skidmore u32 flx_mask_st20; 1526470739b5SDon Skidmore 1527470739b5SDon Skidmore /* Indicate to FW that AN restart has been asserted */ 1528470739b5SDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 1529470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1530470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20); 1531470739b5SDon Skidmore 1532470739b5SDon Skidmore if (status) { 1533470739b5SDon Skidmore hw_dbg(hw, "Auto-negotiation did not complete\n"); 1534470739b5SDon Skidmore return status; 1535470739b5SDon Skidmore } 1536470739b5SDon Skidmore 1537470739b5SDon Skidmore flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART; 1538470739b5SDon Skidmore status = hw->mac.ops.write_iosf_sb_reg(hw, 1539470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1540470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20); 1541470739b5SDon Skidmore } 1542470739b5SDon Skidmore 1543470739b5SDon Skidmore return status; 1544470739b5SDon Skidmore } 1545470739b5SDon Skidmore 15460c1b7de4SDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 15470c1b7de4SDon Skidmore * @hw: pointer to hardware structure 15480c1b7de4SDon Skidmore * @speed: the link speed to force 15490c1b7de4SDon Skidmore * 15500c1b7de4SDon Skidmore * Configures the integrated KR PHY to use iXFI mode. Used to connect an 15510c1b7de4SDon Skidmore * internal and external PHY at a specific speed, without autonegotiation. 15520c1b7de4SDon Skidmore **/ 15530c1b7de4SDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 15540c1b7de4SDon Skidmore { 155548301cf2STony Nguyen struct ixgbe_mac_info *mac = &hw->mac; 15560c1b7de4SDon Skidmore s32 status; 15570c1b7de4SDon Skidmore u32 reg_val; 15580c1b7de4SDon Skidmore 155948301cf2STony Nguyen /* iXFI is only supported with X552 */ 156048301cf2STony Nguyen if (mac->type != ixgbe_mac_X550EM_x) 156148301cf2STony Nguyen return IXGBE_ERR_LINK_SETUP; 156248301cf2STony Nguyen 15630c1b7de4SDon Skidmore /* Disable AN and force speed to 10G Serial. */ 15640c1b7de4SDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 15650c1b7de4SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 15660c1b7de4SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 15676a14ee0cSDon Skidmore if (status) 15686a14ee0cSDon Skidmore return status; 15696a14ee0cSDon Skidmore 15700c1b7de4SDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 15710c1b7de4SDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 15720c1b7de4SDon Skidmore 15730c1b7de4SDon Skidmore /* Select forced link speed for internal PHY. */ 15740c1b7de4SDon Skidmore switch (*speed) { 15750c1b7de4SDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 15760c1b7de4SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 15770c1b7de4SDon Skidmore break; 15780c1b7de4SDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 15790c1b7de4SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 15800c1b7de4SDon Skidmore break; 15810c1b7de4SDon Skidmore default: 15820c1b7de4SDon Skidmore /* Other link speeds are not supported by internal KR PHY. */ 15830c1b7de4SDon Skidmore return IXGBE_ERR_LINK_SETUP; 15840c1b7de4SDon Skidmore } 15850c1b7de4SDon Skidmore 15860c1b7de4SDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 15870c1b7de4SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 15880c1b7de4SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 15890c1b7de4SDon Skidmore if (status) 15900c1b7de4SDon Skidmore return status; 15910c1b7de4SDon Skidmore 15920c1b7de4SDon Skidmore /* Additional configuration needed for x550em_x */ 15930c1b7de4SDon Skidmore if (hw->mac.type == ixgbe_mac_X550EM_x) { 15940c1b7de4SDon Skidmore status = ixgbe_setup_ixfi_x550em_x(hw); 15950c1b7de4SDon Skidmore if (status) 15960c1b7de4SDon Skidmore return status; 15970c1b7de4SDon Skidmore } 15980c1b7de4SDon Skidmore 15996a14ee0cSDon Skidmore /* Toggle port SW reset by AN reset. */ 1600470739b5SDon Skidmore status = ixgbe_restart_an_internal_phy_x550em(hw); 16016a14ee0cSDon Skidmore 16026a14ee0cSDon Skidmore return status; 16036a14ee0cSDon Skidmore } 16046a14ee0cSDon Skidmore 1605c3dc4c09SDon Skidmore /** 1606e23f3336SMark Rustad * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported 1607e23f3336SMark Rustad * @hw: pointer to hardware structure 1608e23f3336SMark Rustad * @linear: true if SFP module is linear 1609e23f3336SMark Rustad */ 1610e23f3336SMark Rustad static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) 1611e23f3336SMark Rustad { 1612e23f3336SMark Rustad switch (hw->phy.sfp_type) { 1613e23f3336SMark Rustad case ixgbe_sfp_type_not_present: 1614e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_PRESENT; 1615e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core0: 1616e23f3336SMark Rustad case ixgbe_sfp_type_da_cu_core1: 1617e23f3336SMark Rustad *linear = true; 1618e23f3336SMark Rustad break; 1619e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core0: 1620e23f3336SMark Rustad case ixgbe_sfp_type_srlr_core1: 1621e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core0: 1622e23f3336SMark Rustad case ixgbe_sfp_type_da_act_lmt_core1: 1623e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core0: 1624e23f3336SMark Rustad case ixgbe_sfp_type_1g_sx_core1: 1625e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core0: 1626e23f3336SMark Rustad case ixgbe_sfp_type_1g_lx_core1: 1627e23f3336SMark Rustad *linear = false; 1628e23f3336SMark Rustad break; 1629e23f3336SMark Rustad case ixgbe_sfp_type_unknown: 1630e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core0: 1631e23f3336SMark Rustad case ixgbe_sfp_type_1g_cu_core1: 1632e23f3336SMark Rustad default: 1633e23f3336SMark Rustad return IXGBE_ERR_SFP_NOT_SUPPORTED; 1634e23f3336SMark Rustad } 1635e23f3336SMark Rustad 1636e23f3336SMark Rustad return 0; 1637e23f3336SMark Rustad } 1638e23f3336SMark Rustad 1639e23f3336SMark Rustad /** 16406d373a1bSMark Rustad * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. 16416d373a1bSMark Rustad * @hw: pointer to hardware structure 16425ba643c6STony Nguyen * @speed: the link speed to force 16435ba643c6STony Nguyen * @autoneg_wait_to_complete: unused 16446d373a1bSMark Rustad * 16456d373a1bSMark Rustad * Configures the extern PHY and the integrated KR PHY for SFP support. 16466d373a1bSMark Rustad */ 16476d373a1bSMark Rustad static s32 16486d373a1bSMark Rustad ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, 16496d373a1bSMark Rustad ixgbe_link_speed speed, 16506d373a1bSMark Rustad __always_unused bool autoneg_wait_to_complete) 16516d373a1bSMark Rustad { 1652e23f3336SMark Rustad s32 status; 1653812d7dffSEmil Tantilov u16 reg_slice, reg_val; 1654e23f3336SMark Rustad bool setup_linear = false; 1655e23f3336SMark Rustad 1656e23f3336SMark Rustad /* Check if SFP module is supported and linear */ 1657e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 1658e23f3336SMark Rustad 1659e23f3336SMark Rustad /* If no SFP module present, then return success. Return success since 1660e23f3336SMark Rustad * there is no reason to configure CS4227 and SFP not present error is 1661e23f3336SMark Rustad * not accepted in the setup MAC link flow. 1662e23f3336SMark Rustad */ 1663e23f3336SMark Rustad if (status == IXGBE_ERR_SFP_NOT_PRESENT) 1664e23f3336SMark Rustad return 0; 1665e23f3336SMark Rustad 1666e23f3336SMark Rustad if (status) 1667e23f3336SMark Rustad return status; 1668e23f3336SMark Rustad 1669d91e3a7dSMark Rustad /* Configure internal PHY for KR/KX. */ 1670812d7dffSEmil Tantilov ixgbe_setup_kr_speed_x550em(hw, speed); 1671e23f3336SMark Rustad 1672d91e3a7dSMark Rustad /* Configure CS4227 LINE side to proper mode. */ 1673812d7dffSEmil Tantilov reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); 1674d91e3a7dSMark Rustad if (setup_linear) 1675812d7dffSEmil Tantilov reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; 1676d91e3a7dSMark Rustad else 1677812d7dffSEmil Tantilov reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; 1678b71f6c40SEmil Tantilov 1679b71f6c40SEmil Tantilov status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, 1680b71f6c40SEmil Tantilov reg_val); 1681b71f6c40SEmil Tantilov 1682e23f3336SMark Rustad return status; 16836d373a1bSMark Rustad } 16846d373a1bSMark Rustad 16856d373a1bSMark Rustad /** 1686470739b5SDon Skidmore * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode 1687470739b5SDon Skidmore * @hw: pointer to hardware structure 1688470739b5SDon Skidmore * @speed: the link speed to force 1689470739b5SDon Skidmore * 1690470739b5SDon Skidmore * Configures the integrated PHY for native SFI mode. Used to connect the 1691470739b5SDon Skidmore * internal PHY directly to an SFP cage, without autonegotiation. 1692470739b5SDon Skidmore **/ 1693470739b5SDon Skidmore static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 1694470739b5SDon Skidmore { 1695470739b5SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 1696470739b5SDon Skidmore s32 status; 1697470739b5SDon Skidmore u32 reg_val; 1698470739b5SDon Skidmore 1699470739b5SDon Skidmore /* Disable all AN and force speed to 10G Serial. */ 1700470739b5SDon Skidmore status = mac->ops.read_iosf_sb_reg(hw, 1701470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1702470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 1703470739b5SDon Skidmore if (status) 1704470739b5SDon Skidmore return status; 1705470739b5SDon Skidmore 1706470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 1707470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 1708470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 1709470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 1710470739b5SDon Skidmore 1711470739b5SDon Skidmore /* Select forced link speed for internal PHY. */ 1712470739b5SDon Skidmore switch (*speed) { 1713470739b5SDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 1714470739b5SDon Skidmore reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G; 1715470739b5SDon Skidmore break; 1716470739b5SDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 1717470739b5SDon Skidmore reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; 1718470739b5SDon Skidmore break; 1719470739b5SDon Skidmore default: 1720470739b5SDon Skidmore /* Other link speeds are not supported by internal PHY. */ 1721470739b5SDon Skidmore return IXGBE_ERR_LINK_SETUP; 1722470739b5SDon Skidmore } 1723470739b5SDon Skidmore 1724470739b5SDon Skidmore status = mac->ops.write_iosf_sb_reg(hw, 1725470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1726470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 1727470739b5SDon Skidmore 1728470739b5SDon Skidmore /* Toggle port SW reset by AN reset. */ 1729470739b5SDon Skidmore status = ixgbe_restart_an_internal_phy_x550em(hw); 1730470739b5SDon Skidmore 1731470739b5SDon Skidmore return status; 1732470739b5SDon Skidmore } 1733470739b5SDon Skidmore 1734470739b5SDon Skidmore /** 17352d40cd17SMark Rustad * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP 17362d40cd17SMark Rustad * @hw: pointer to hardware structure 17375ba643c6STony Nguyen * @speed: link speed 17385ba643c6STony Nguyen * @autoneg_wait_to_complete: unused 17392d40cd17SMark Rustad * 17402d40cd17SMark Rustad * Configure the the integrated PHY for native SFP support. 17412d40cd17SMark Rustad */ 17422d40cd17SMark Rustad static s32 17432d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, 17442d40cd17SMark Rustad __always_unused bool autoneg_wait_to_complete) 17452d40cd17SMark Rustad { 17462d40cd17SMark Rustad bool setup_linear = false; 17472d40cd17SMark Rustad u32 reg_phy_int; 1748470739b5SDon Skidmore s32 ret_val; 17492d40cd17SMark Rustad 17502d40cd17SMark Rustad /* Check if SFP module is supported and linear */ 1751470739b5SDon Skidmore ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 17522d40cd17SMark Rustad 17532d40cd17SMark Rustad /* If no SFP module present, then return success. Return success since 17542d40cd17SMark Rustad * SFP not present error is not excepted in the setup MAC link flow. 17552d40cd17SMark Rustad */ 1756470739b5SDon Skidmore if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) 17572d40cd17SMark Rustad return 0; 17582d40cd17SMark Rustad 1759d9c23ff8SEmil Tantilov if (ret_val) 1760470739b5SDon Skidmore return ret_val; 17612d40cd17SMark Rustad 1762470739b5SDon Skidmore /* Configure internal PHY for native SFI based on module type */ 1763470739b5SDon Skidmore ret_val = hw->mac.ops.read_iosf_sb_reg(hw, 1764470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1765470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int); 1766d9c23ff8SEmil Tantilov if (ret_val) 1767470739b5SDon Skidmore return ret_val; 17682d40cd17SMark Rustad 1769470739b5SDon Skidmore reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA; 1770470739b5SDon Skidmore if (!setup_linear) 1771470739b5SDon Skidmore reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR; 17722d40cd17SMark Rustad 1773470739b5SDon Skidmore ret_val = hw->mac.ops.write_iosf_sb_reg(hw, 1774470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1775470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int); 1776d9c23ff8SEmil Tantilov if (ret_val) 1777470739b5SDon Skidmore return ret_val; 17782d40cd17SMark Rustad 1779470739b5SDon Skidmore /* Setup SFI internal link. */ 1780470739b5SDon Skidmore return ixgbe_setup_sfi_x550a(hw, &speed); 17812d40cd17SMark Rustad } 17822d40cd17SMark Rustad 17832d40cd17SMark Rustad /** 17842d40cd17SMark Rustad * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP 17852d40cd17SMark Rustad * @hw: pointer to hardware structure 17865ba643c6STony Nguyen * @speed: link speed 17875ba643c6STony Nguyen * @autoneg_wait_to_complete: unused 17882d40cd17SMark Rustad * 17892d40cd17SMark Rustad * Configure the the integrated PHY for SFP support. 17902d40cd17SMark Rustad */ 17912d40cd17SMark Rustad static s32 17922d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, 17932d40cd17SMark Rustad __always_unused bool autoneg_wait_to_complete) 17942d40cd17SMark Rustad { 17952d40cd17SMark Rustad u32 reg_slice, slice_offset; 17962d40cd17SMark Rustad bool setup_linear = false; 17972d40cd17SMark Rustad u16 reg_phy_ext; 1798470739b5SDon Skidmore s32 ret_val; 17992d40cd17SMark Rustad 18002d40cd17SMark Rustad /* Check if SFP module is supported and linear */ 1801470739b5SDon Skidmore ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 18022d40cd17SMark Rustad 18032d40cd17SMark Rustad /* If no SFP module present, then return success. Return success since 18042d40cd17SMark Rustad * SFP not present error is not excepted in the setup MAC link flow. 18052d40cd17SMark Rustad */ 1806470739b5SDon Skidmore if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) 18072d40cd17SMark Rustad return 0; 18082d40cd17SMark Rustad 1809d9c23ff8SEmil Tantilov if (ret_val) 1810470739b5SDon Skidmore return ret_val; 18112d40cd17SMark Rustad 18122d40cd17SMark Rustad /* Configure internal PHY for KR/KX. */ 18132d40cd17SMark Rustad ixgbe_setup_kr_speed_x550em(hw, speed); 18142d40cd17SMark Rustad 18157564a888SMark Rustad if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE) 18162d40cd17SMark Rustad return IXGBE_ERR_PHY_ADDR_INVALID; 18172d40cd17SMark Rustad 1818cc1de78cSEmil Tantilov /* Get external PHY SKU id */ 1819cc1de78cSEmil Tantilov ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU, 18202d40cd17SMark Rustad IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 1821470739b5SDon Skidmore if (ret_val) 1822470739b5SDon Skidmore return ret_val; 18232d40cd17SMark Rustad 18242d40cd17SMark Rustad /* When configuring quad port CS4223, the MAC instance is part 18252d40cd17SMark Rustad * of the slice offset. 18262d40cd17SMark Rustad */ 1827cc1de78cSEmil Tantilov if (reg_phy_ext == IXGBE_CS4223_SKU_ID) 18282d40cd17SMark Rustad slice_offset = (hw->bus.lan_id + 18292d40cd17SMark Rustad (hw->bus.instance_id << 1)) << 12; 18302d40cd17SMark Rustad else 18312d40cd17SMark Rustad slice_offset = hw->bus.lan_id << 12; 18322d40cd17SMark Rustad 18332d40cd17SMark Rustad /* Configure CS4227/CS4223 LINE side to proper mode. */ 18342d40cd17SMark Rustad reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; 1835410a4949SEmil Tantilov 1836410a4949SEmil Tantilov ret_val = hw->phy.ops.read_reg(hw, reg_slice, 1837410a4949SEmil Tantilov IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 1838410a4949SEmil Tantilov if (ret_val) 1839410a4949SEmil Tantilov return ret_val; 1840410a4949SEmil Tantilov 1841410a4949SEmil Tantilov reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1842410a4949SEmil Tantilov (IXGBE_CS4227_EDC_MODE_SR << 1)); 1843410a4949SEmil Tantilov 18442d40cd17SMark Rustad if (setup_linear) 18459bf1e20fSPaul Greenwalt reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; 18462d40cd17SMark Rustad else 18479bf1e20fSPaul Greenwalt reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; 1848410a4949SEmil Tantilov 1849410a4949SEmil Tantilov ret_val = hw->phy.ops.write_reg(hw, reg_slice, 1850410a4949SEmil Tantilov IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext); 1851410a4949SEmil Tantilov if (ret_val) 1852410a4949SEmil Tantilov return ret_val; 1853410a4949SEmil Tantilov 1854410a4949SEmil Tantilov /* Flush previous write with a read */ 1855410a4949SEmil Tantilov return hw->phy.ops.read_reg(hw, reg_slice, 1856410a4949SEmil Tantilov IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 18572d40cd17SMark Rustad } 18582d40cd17SMark Rustad 18592d40cd17SMark Rustad /** 1860c3dc4c09SDon Skidmore * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 1861c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1862c3dc4c09SDon Skidmore * @speed: new link speed 18635ba643c6STony Nguyen * @autoneg_wait: true when waiting for completion is needed 1864c3dc4c09SDon Skidmore * 1865c3dc4c09SDon Skidmore * Setup internal/external PHY link speed based on link speed, then set 1866c3dc4c09SDon Skidmore * external PHY auto advertised link speed. 1867c3dc4c09SDon Skidmore * 1868c3dc4c09SDon Skidmore * Returns error status for any failure 1869c3dc4c09SDon Skidmore **/ 1870c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 1871c3dc4c09SDon Skidmore ixgbe_link_speed speed, 1872c3dc4c09SDon Skidmore bool autoneg_wait) 1873c3dc4c09SDon Skidmore { 1874c3dc4c09SDon Skidmore s32 status; 1875c3dc4c09SDon Skidmore ixgbe_link_speed force_speed; 1876c3dc4c09SDon Skidmore 1877c3dc4c09SDon Skidmore /* Setup internal/external PHY link speed to iXFI (10G), unless 1878c3dc4c09SDon Skidmore * only 1G is auto advertised then setup KX link. 1879c3dc4c09SDon Skidmore */ 1880c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1881c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 1882c3dc4c09SDon Skidmore else 1883c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 1884c3dc4c09SDon Skidmore 188548301cf2STony Nguyen /* If X552 and internal link mode is XFI, then setup XFI internal link. 188648301cf2STony Nguyen */ 188748301cf2STony Nguyen if (hw->mac.type == ixgbe_mac_X550EM_x && 188848301cf2STony Nguyen !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1889c3dc4c09SDon Skidmore status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 1890c3dc4c09SDon Skidmore 1891c3dc4c09SDon Skidmore if (status) 1892c3dc4c09SDon Skidmore return status; 1893c3dc4c09SDon Skidmore } 1894c3dc4c09SDon Skidmore 1895c3dc4c09SDon Skidmore return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 1896c3dc4c09SDon Skidmore } 1897c3dc4c09SDon Skidmore 1898a4e293a5SDon Skidmore /** ixgbe_check_link_t_X550em - Determine link and speed status 1899a4e293a5SDon Skidmore * @hw: pointer to hardware structure 1900a4e293a5SDon Skidmore * @speed: pointer to link speed 1901a4e293a5SDon Skidmore * @link_up: true when link is up 1902a4e293a5SDon Skidmore * @link_up_wait_to_complete: bool used to wait for link up or not 1903a4e293a5SDon Skidmore * 1904a4e293a5SDon Skidmore * Check that both the MAC and X557 external PHY have link. 1905a4e293a5SDon Skidmore **/ 1906a4e293a5SDon Skidmore static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, 1907a4e293a5SDon Skidmore ixgbe_link_speed *speed, 1908a4e293a5SDon Skidmore bool *link_up, 1909a4e293a5SDon Skidmore bool link_up_wait_to_complete) 1910a4e293a5SDon Skidmore { 1911a4e293a5SDon Skidmore u32 status; 191221d882ebSEmil Tantilov u16 i, autoneg_status; 1913a4e293a5SDon Skidmore 1914a4e293a5SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 1915a4e293a5SDon Skidmore return IXGBE_ERR_CONFIG; 1916a4e293a5SDon Skidmore 1917a4e293a5SDon Skidmore status = ixgbe_check_mac_link_generic(hw, speed, link_up, 1918a4e293a5SDon Skidmore link_up_wait_to_complete); 1919a4e293a5SDon Skidmore 1920a4e293a5SDon Skidmore /* If check link fails or MAC link is not up, then return */ 1921a4e293a5SDon Skidmore if (status || !(*link_up)) 1922a4e293a5SDon Skidmore return status; 1923a4e293a5SDon Skidmore 1924a4e293a5SDon Skidmore /* MAC link is up, so check external PHY link. 192521d882ebSEmil Tantilov * Link status is latching low, and can only be used to detect link 192621d882ebSEmil Tantilov * drop, and not the current status of the link without performing 192721d882ebSEmil Tantilov * back-to-back reads. 1928a4e293a5SDon Skidmore */ 192921d882ebSEmil Tantilov for (i = 0; i < 2; i++) { 19304dc4000bSEmil Tantilov status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 1931a4e293a5SDon Skidmore &autoneg_status); 193221d882ebSEmil Tantilov 1933a4e293a5SDon Skidmore if (status) 1934a4e293a5SDon Skidmore return status; 193521d882ebSEmil Tantilov } 1936a4e293a5SDon Skidmore 1937a4e293a5SDon Skidmore /* If external PHY link is not up, then indicate link not up */ 1938a4e293a5SDon Skidmore if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 1939a4e293a5SDon Skidmore *link_up = false; 1940a4e293a5SDon Skidmore 1941a4e293a5SDon Skidmore return 0; 1942a4e293a5SDon Skidmore } 1943a4e293a5SDon Skidmore 1944200157c2SMark Rustad /** 1945200157c2SMark Rustad * ixgbe_setup_sgmii - Set up link for sgmii 1946200157c2SMark Rustad * @hw: pointer to hardware structure 19475ba643c6STony Nguyen * @speed: unused 19485ba643c6STony Nguyen * @autoneg_wait_to_complete: unused 1949200157c2SMark Rustad */ 1950200157c2SMark Rustad static s32 1951200157c2SMark Rustad ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, 1952200157c2SMark Rustad __always_unused bool autoneg_wait_to_complete) 1953200157c2SMark Rustad { 1954200157c2SMark Rustad struct ixgbe_mac_info *mac = &hw->mac; 1955470739b5SDon Skidmore u32 lval, sval, flx_val; 1956200157c2SMark Rustad s32 rc; 1957200157c2SMark Rustad 1958200157c2SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 1959200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1960200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 1961200157c2SMark Rustad if (rc) 1962200157c2SMark Rustad return rc; 1963200157c2SMark Rustad 1964200157c2SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1965200157c2SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 1966200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 1967200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 1968200157c2SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 1969200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1970200157c2SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1971200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1972200157c2SMark Rustad if (rc) 1973200157c2SMark Rustad return rc; 1974200157c2SMark Rustad 1975200157c2SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 1976200157c2SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1977200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 1978200157c2SMark Rustad if (rc) 1979200157c2SMark Rustad return rc; 1980200157c2SMark Rustad 1981200157c2SMark Rustad sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 1982200157c2SMark Rustad sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 1983200157c2SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 1984200157c2SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1985200157c2SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 1986200157c2SMark Rustad if (rc) 1987200157c2SMark Rustad return rc; 1988200157c2SMark Rustad 1989470739b5SDon Skidmore rc = mac->ops.read_iosf_sb_reg(hw, 1990470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1991470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 1992470739b5SDon Skidmore if (rc) 1993470739b5SDon Skidmore return rc; 1994200157c2SMark Rustad 1995470739b5SDon Skidmore rc = mac->ops.read_iosf_sb_reg(hw, 1996470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1997470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 1998470739b5SDon Skidmore if (rc) 1999470739b5SDon Skidmore return rc; 2000470739b5SDon Skidmore 2001470739b5SDon Skidmore flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 2002470739b5SDon Skidmore flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; 2003470739b5SDon Skidmore flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 2004470739b5SDon Skidmore flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 2005470739b5SDon Skidmore flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 2006470739b5SDon Skidmore 2007470739b5SDon Skidmore rc = mac->ops.write_iosf_sb_reg(hw, 2008470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2009470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); 2010470739b5SDon Skidmore if (rc) 2011470739b5SDon Skidmore return rc; 2012470739b5SDon Skidmore 2013470739b5SDon Skidmore rc = ixgbe_restart_an_internal_phy_x550em(hw); 2014200157c2SMark Rustad return rc; 2015200157c2SMark Rustad } 2016200157c2SMark Rustad 2017b3eb4e18SMark Rustad /** 2018b3eb4e18SMark Rustad * ixgbe_setup_sgmii_fw - Set up link for sgmii with firmware-controlled PHYs 2019b3eb4e18SMark Rustad * @hw: pointer to hardware structure 20205ba643c6STony Nguyen * @speed: the link speed to force 20215ba643c6STony Nguyen * @autoneg_wait: true when waiting for completion is needed 2022b3eb4e18SMark Rustad */ 2023b3eb4e18SMark Rustad static s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed, 2024b3eb4e18SMark Rustad bool autoneg_wait) 2025b3eb4e18SMark Rustad { 2026b3eb4e18SMark Rustad struct ixgbe_mac_info *mac = &hw->mac; 2027b3eb4e18SMark Rustad u32 lval, sval, flx_val; 2028b3eb4e18SMark Rustad s32 rc; 2029b3eb4e18SMark Rustad 2030b3eb4e18SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 2031b3eb4e18SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2032b3eb4e18SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 2033b3eb4e18SMark Rustad if (rc) 2034b3eb4e18SMark Rustad return rc; 2035b3eb4e18SMark Rustad 2036b3eb4e18SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 2037b3eb4e18SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 2038b3eb4e18SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 2039b3eb4e18SMark Rustad lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 2040b3eb4e18SMark Rustad lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 2041b3eb4e18SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 2042b3eb4e18SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2043b3eb4e18SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 2044b3eb4e18SMark Rustad if (rc) 2045b3eb4e18SMark Rustad return rc; 2046b3eb4e18SMark Rustad 2047b3eb4e18SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 2048b3eb4e18SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 2049b3eb4e18SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 2050b3eb4e18SMark Rustad if (rc) 2051b3eb4e18SMark Rustad return rc; 2052b3eb4e18SMark Rustad 2053b3eb4e18SMark Rustad sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 2054b3eb4e18SMark Rustad sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 2055b3eb4e18SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 2056b3eb4e18SMark Rustad IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 2057b3eb4e18SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 2058b3eb4e18SMark Rustad if (rc) 2059b3eb4e18SMark Rustad return rc; 2060b3eb4e18SMark Rustad 2061b3eb4e18SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 2062b3eb4e18SMark Rustad IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2063b3eb4e18SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 2064b3eb4e18SMark Rustad if (rc) 2065b3eb4e18SMark Rustad return rc; 2066b3eb4e18SMark Rustad 2067b3eb4e18SMark Rustad rc = mac->ops.read_iosf_sb_reg(hw, 2068b3eb4e18SMark Rustad IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2069b3eb4e18SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 2070b3eb4e18SMark Rustad if (rc) 2071b3eb4e18SMark Rustad return rc; 2072b3eb4e18SMark Rustad 2073b3eb4e18SMark Rustad flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 2074b3eb4e18SMark Rustad flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; 2075b3eb4e18SMark Rustad flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 2076b3eb4e18SMark Rustad flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 2077b3eb4e18SMark Rustad flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 2078b3eb4e18SMark Rustad 2079b3eb4e18SMark Rustad rc = mac->ops.write_iosf_sb_reg(hw, 2080b3eb4e18SMark Rustad IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2081b3eb4e18SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); 2082b3eb4e18SMark Rustad if (rc) 2083b3eb4e18SMark Rustad return rc; 2084b3eb4e18SMark Rustad 2085b3eb4e18SMark Rustad ixgbe_restart_an_internal_phy_x550em(hw); 2086b3eb4e18SMark Rustad 2087b3eb4e18SMark Rustad return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 2088b3eb4e18SMark Rustad } 2089b3eb4e18SMark Rustad 2090b3eb4e18SMark Rustad /** 2091b3eb4e18SMark Rustad * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37 2092b3eb4e18SMark Rustad * @hw: pointer to hardware structure 2093b3eb4e18SMark Rustad * 2094b3eb4e18SMark Rustad * Enable flow control according to IEEE clause 37. 2095b3eb4e18SMark Rustad */ 2096b3eb4e18SMark Rustad static void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw) 2097b3eb4e18SMark Rustad { 2098b3eb4e18SMark Rustad s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; 2099b3eb4e18SMark Rustad u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 }; 2100b3eb4e18SMark Rustad ixgbe_link_speed speed; 2101b3eb4e18SMark Rustad bool link_up; 2102b3eb4e18SMark Rustad 2103b3eb4e18SMark Rustad /* AN should have completed when the cable was plugged in. 2104b3eb4e18SMark Rustad * Look for reasons to bail out. Bail out if: 2105b3eb4e18SMark Rustad * - FC autoneg is disabled, or if 2106b3eb4e18SMark Rustad * - link is not up. 2107b3eb4e18SMark Rustad */ 2108b3eb4e18SMark Rustad if (hw->fc.disable_fc_autoneg) 2109b3eb4e18SMark Rustad goto out; 2110b3eb4e18SMark Rustad 2111b3eb4e18SMark Rustad hw->mac.ops.check_link(hw, &speed, &link_up, false); 2112b3eb4e18SMark Rustad if (!link_up) 2113b3eb4e18SMark Rustad goto out; 2114b3eb4e18SMark Rustad 2115b3eb4e18SMark Rustad /* Check if auto-negotiation has completed */ 2116b3eb4e18SMark Rustad status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info); 2117b3eb4e18SMark Rustad if (status || !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) { 2118b3eb4e18SMark Rustad status = IXGBE_ERR_FC_NOT_NEGOTIATED; 2119b3eb4e18SMark Rustad goto out; 2120b3eb4e18SMark Rustad } 2121b3eb4e18SMark Rustad 2122b3eb4e18SMark Rustad /* Negotiate the flow control */ 2123b3eb4e18SMark Rustad status = ixgbe_negotiate_fc(hw, info[0], info[0], 2124b3eb4e18SMark Rustad FW_PHY_ACT_GET_LINK_INFO_FC_RX, 2125b3eb4e18SMark Rustad FW_PHY_ACT_GET_LINK_INFO_FC_TX, 2126b3eb4e18SMark Rustad FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX, 2127b3eb4e18SMark Rustad FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX); 2128b3eb4e18SMark Rustad 2129b3eb4e18SMark Rustad out: 2130b3eb4e18SMark Rustad if (!status) { 2131b3eb4e18SMark Rustad hw->fc.fc_was_autonegged = true; 2132b3eb4e18SMark Rustad } else { 2133b3eb4e18SMark Rustad hw->fc.fc_was_autonegged = false; 2134b3eb4e18SMark Rustad hw->fc.current_mode = hw->fc.requested_mode; 2135b3eb4e18SMark Rustad } 2136b3eb4e18SMark Rustad } 2137b3eb4e18SMark Rustad 21382916500dSDon Skidmore /** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers 21392916500dSDon Skidmore * @hw: pointer to hardware structure 21402916500dSDon Skidmore **/ 21412916500dSDon Skidmore static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw) 21422916500dSDon Skidmore { 21432916500dSDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 21442916500dSDon Skidmore 21452916500dSDon Skidmore switch (mac->ops.get_media_type(hw)) { 21462916500dSDon Skidmore case ixgbe_media_type_fiber: 21472916500dSDon Skidmore mac->ops.setup_fc = NULL; 21482916500dSDon Skidmore mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; 21492916500dSDon Skidmore break; 2150b3eb4e18SMark Rustad case ixgbe_media_type_copper: 2151b3eb4e18SMark Rustad if (hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T && 2152b3eb4e18SMark Rustad hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T_L) { 2153b3eb4e18SMark Rustad mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 2154b3eb4e18SMark Rustad break; 2155b3eb4e18SMark Rustad } 2156b3eb4e18SMark Rustad mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a; 2157b3eb4e18SMark Rustad mac->ops.setup_fc = ixgbe_fc_autoneg_fw; 2158b3eb4e18SMark Rustad mac->ops.setup_link = ixgbe_setup_sgmii_fw; 2159b3eb4e18SMark Rustad mac->ops.check_link = ixgbe_check_mac_link_generic; 2160b3eb4e18SMark Rustad break; 21612916500dSDon Skidmore case ixgbe_media_type_backplane: 21622916500dSDon Skidmore mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; 21632916500dSDon Skidmore mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; 21642916500dSDon Skidmore break; 21652916500dSDon Skidmore default: 21662916500dSDon Skidmore break; 21672916500dSDon Skidmore } 21682916500dSDon Skidmore } 21692916500dSDon Skidmore 2170c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 2171c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 2172c3dc4c09SDon Skidmore **/ 2173c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 2174c3dc4c09SDon Skidmore { 2175c3dc4c09SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 2176c3dc4c09SDon Skidmore 2177abf76d76SEmil Tantilov mac->ops.setup_fc = ixgbe_setup_fc_x550em; 2178abf76d76SEmil Tantilov 2179c3dc4c09SDon Skidmore switch (mac->ops.get_media_type(hw)) { 2180c3dc4c09SDon Skidmore case ixgbe_media_type_fiber: 2181c3dc4c09SDon Skidmore /* CS4227 does not support autoneg, so disable the laser control 2182c3dc4c09SDon Skidmore * functions for SFP+ fiber 2183c3dc4c09SDon Skidmore */ 2184c3dc4c09SDon Skidmore mac->ops.disable_tx_laser = NULL; 2185c3dc4c09SDon Skidmore mac->ops.enable_tx_laser = NULL; 2186c3dc4c09SDon Skidmore mac->ops.flap_tx_laser = NULL; 21876d373a1bSMark Rustad mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; 21882d40cd17SMark Rustad switch (hw->device_id) { 21892d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 21902d40cd17SMark Rustad mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; 21912d40cd17SMark Rustad break; 21922d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 21932d40cd17SMark Rustad mac->ops.setup_mac_link = 21942d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550a; 21952d40cd17SMark Rustad break; 21962d40cd17SMark Rustad default: 21972d40cd17SMark Rustad mac->ops.setup_mac_link = 21982d40cd17SMark Rustad ixgbe_setup_mac_link_sfp_x550em; 21992d40cd17SMark Rustad break; 22002d40cd17SMark Rustad } 22016d373a1bSMark Rustad mac->ops.set_rate_select_speed = 22026d373a1bSMark Rustad ixgbe_set_soft_rate_select_speed; 2203c3dc4c09SDon Skidmore break; 2204c3dc4c09SDon Skidmore case ixgbe_media_type_copper: 22058dc963e1SPaul Greenwalt if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T) 22068dc963e1SPaul Greenwalt break; 2207c3dc4c09SDon Skidmore mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 2208afdc71e4SMark Rustad mac->ops.setup_fc = ixgbe_setup_fc_generic; 2209a4e293a5SDon Skidmore mac->ops.check_link = ixgbe_check_link_t_X550em; 2210b3eb4e18SMark Rustad break; 221149425dfcSMark Rustad case ixgbe_media_type_backplane: 2212200157c2SMark Rustad if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || 2213200157c2SMark Rustad hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) 2214200157c2SMark Rustad mac->ops.setup_link = ixgbe_setup_sgmii; 2215c3dc4c09SDon Skidmore break; 2216c3dc4c09SDon Skidmore default: 2217c3dc4c09SDon Skidmore break; 2218c3dc4c09SDon Skidmore } 22192916500dSDon Skidmore 22202916500dSDon Skidmore /* Additional modification for X550em_a devices */ 22212916500dSDon Skidmore if (hw->mac.type == ixgbe_mac_x550em_a) 22222916500dSDon Skidmore ixgbe_init_mac_link_ops_X550em_a(hw); 2223c3dc4c09SDon Skidmore } 2224c3dc4c09SDon Skidmore 2225c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module 2226c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 2227c3dc4c09SDon Skidmore */ 2228c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 2229c3dc4c09SDon Skidmore { 2230e23f3336SMark Rustad s32 status; 2231e23f3336SMark Rustad bool linear; 2232c3dc4c09SDon Skidmore 2233e23f3336SMark Rustad /* Check if SFP module is supported */ 2234e23f3336SMark Rustad status = ixgbe_supported_sfp_modules_X550em(hw, &linear); 2235e23f3336SMark Rustad if (status) 2236e23f3336SMark Rustad return status; 2237c3dc4c09SDon Skidmore 2238c3dc4c09SDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 2239c3dc4c09SDon Skidmore hw->phy.ops.reset = NULL; 2240c3dc4c09SDon Skidmore 2241e23f3336SMark Rustad return 0; 2242c3dc4c09SDon Skidmore } 2243c3dc4c09SDon Skidmore 2244c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities 2245c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 2246c3dc4c09SDon Skidmore * @speed: pointer to link speed 2247c3dc4c09SDon Skidmore * @autoneg: true when autoneg or autotry is enabled 2248c3dc4c09SDon Skidmore **/ 2249c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 2250c3dc4c09SDon Skidmore ixgbe_link_speed *speed, 2251c3dc4c09SDon Skidmore bool *autoneg) 2252c3dc4c09SDon Skidmore { 2253b3eb4e18SMark Rustad if (hw->phy.type == ixgbe_phy_fw) { 2254b3eb4e18SMark Rustad *autoneg = true; 2255b3eb4e18SMark Rustad *speed = hw->phy.speeds_supported; 2256b3eb4e18SMark Rustad return 0; 2257b3eb4e18SMark Rustad } 2258b3eb4e18SMark Rustad 2259c3dc4c09SDon Skidmore /* SFP */ 2260c3dc4c09SDon Skidmore if (hw->phy.media_type == ixgbe_media_type_fiber) { 2261c3dc4c09SDon Skidmore /* CS4227 SFP must not enable auto-negotiation */ 2262c3dc4c09SDon Skidmore *autoneg = false; 2263c3dc4c09SDon Skidmore 2264c3dc4c09SDon Skidmore if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 2265a8bf879aSJosh Elsasser hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 || 2266a8bf879aSJosh Elsasser hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || 2267a8bf879aSJosh Elsasser hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) { 2268c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 2269c3dc4c09SDon Skidmore return 0; 2270c3dc4c09SDon Skidmore } 2271c3dc4c09SDon Skidmore 2272c3dc4c09SDon Skidmore /* Link capabilities are based on SFP */ 2273c3dc4c09SDon Skidmore if (hw->phy.multispeed_fiber) 2274c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 2275c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 2276c3dc4c09SDon Skidmore else 2277c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL; 2278c3dc4c09SDon Skidmore } else { 227918bda0d9SDon Skidmore switch (hw->phy.type) { 228018bda0d9SDon Skidmore case ixgbe_phy_x550em_kx4: 228118bda0d9SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL | 228218bda0d9SDon Skidmore IXGBE_LINK_SPEED_2_5GB_FULL | 228318bda0d9SDon Skidmore IXGBE_LINK_SPEED_10GB_FULL; 228418bda0d9SDon Skidmore break; 228518e01ee7SDon Skidmore case ixgbe_phy_x550em_xfi: 228618e01ee7SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL | 228718e01ee7SDon Skidmore IXGBE_LINK_SPEED_10GB_FULL; 228818e01ee7SDon Skidmore break; 22898dc963e1SPaul Greenwalt case ixgbe_phy_ext_1g_t: 229018bda0d9SDon Skidmore case ixgbe_phy_sgmii: 229118bda0d9SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 229218bda0d9SDon Skidmore break; 22938e5c9c53SDon Skidmore case ixgbe_phy_x550em_kr: 22948e5c9c53SDon Skidmore if (hw->mac.type == ixgbe_mac_x550em_a) { 22958e5c9c53SDon Skidmore /* check different backplane modes */ 22968e5c9c53SDon Skidmore if (hw->phy.nw_mng_if_sel & 22978e5c9c53SDon Skidmore IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) { 22988e5c9c53SDon Skidmore *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 22998e5c9c53SDon Skidmore break; 23008e5c9c53SDon Skidmore } else if (hw->device_id == 23018e5c9c53SDon Skidmore IXGBE_DEV_ID_X550EM_A_KR_L) { 23028e5c9c53SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 23038e5c9c53SDon Skidmore break; 23048e5c9c53SDon Skidmore } 23058e5c9c53SDon Skidmore } 23065463fce6SJeff Kirsher fallthrough; 230718bda0d9SDon Skidmore default: 2308c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 2309c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 231018bda0d9SDon Skidmore break; 231118bda0d9SDon Skidmore } 2312c3dc4c09SDon Skidmore *autoneg = true; 2313c3dc4c09SDon Skidmore } 2314c3dc4c09SDon Skidmore return 0; 2315c3dc4c09SDon Skidmore } 2316c3dc4c09SDon Skidmore 2317c3dc4c09SDon Skidmore /** 2318c3dc4c09SDon Skidmore * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause 2319c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 2320c3dc4c09SDon Skidmore * @lsc: pointer to boolean flag which indicates whether external Base T 2321c3dc4c09SDon Skidmore * PHY interrupt is lsc 2322c3dc4c09SDon Skidmore * 2323c3dc4c09SDon Skidmore * Determime if external Base T PHY interrupt cause is high temperature 2324c3dc4c09SDon Skidmore * failure alarm or link status change. 2325c3dc4c09SDon Skidmore * 2326c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 2327c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 2328c3dc4c09SDon Skidmore **/ 2329c3dc4c09SDon Skidmore static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) 2330c3dc4c09SDon Skidmore { 2331c3dc4c09SDon Skidmore u32 status; 2332c3dc4c09SDon Skidmore u16 reg; 2333c3dc4c09SDon Skidmore 2334c3dc4c09SDon Skidmore *lsc = false; 2335c3dc4c09SDon Skidmore 2336c3dc4c09SDon Skidmore /* Vendor alarm triggered */ 2337c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 23384dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2339c3dc4c09SDon Skidmore ®); 2340c3dc4c09SDon Skidmore 2341c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 2342c3dc4c09SDon Skidmore return status; 2343c3dc4c09SDon Skidmore 2344c3dc4c09SDon Skidmore /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 2345c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 23464dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2347c3dc4c09SDon Skidmore ®); 2348c3dc4c09SDon Skidmore 2349c3dc4c09SDon Skidmore if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 2350c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 2351c3dc4c09SDon Skidmore return status; 2352c3dc4c09SDon Skidmore 235383a9fb20SMark Rustad /* Global alarm triggered */ 2354c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 23554dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2356c3dc4c09SDon Skidmore ®); 2357c3dc4c09SDon Skidmore 2358c3dc4c09SDon Skidmore if (status) 2359c3dc4c09SDon Skidmore return status; 2360c3dc4c09SDon Skidmore 2361c3dc4c09SDon Skidmore /* If high temperature failure, then return over temp error and exit */ 2362c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 2363c3dc4c09SDon Skidmore /* power down the PHY in case the PHY FW didn't already */ 2364c3dc4c09SDon Skidmore ixgbe_set_copper_phy_power(hw, false); 2365c3dc4c09SDon Skidmore return IXGBE_ERR_OVERTEMP; 2366c3dc4c09SDon Skidmore } 236783a9fb20SMark Rustad if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { 236883a9fb20SMark Rustad /* device fault alarm triggered */ 236983a9fb20SMark Rustad status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, 23704dc4000bSEmil Tantilov MDIO_MMD_VEND1, 237183a9fb20SMark Rustad ®); 237283a9fb20SMark Rustad if (status) 237383a9fb20SMark Rustad return status; 237483a9fb20SMark Rustad 237583a9fb20SMark Rustad /* if device fault was due to high temp alarm handle and exit */ 237683a9fb20SMark Rustad if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { 237783a9fb20SMark Rustad /* power down the PHY in case the PHY FW didn't */ 237883a9fb20SMark Rustad ixgbe_set_copper_phy_power(hw, false); 237983a9fb20SMark Rustad return IXGBE_ERR_OVERTEMP; 238083a9fb20SMark Rustad } 238183a9fb20SMark Rustad } 2382c3dc4c09SDon Skidmore 2383c3dc4c09SDon Skidmore /* Vendor alarm 2 triggered */ 2384c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 23854dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 2386c3dc4c09SDon Skidmore 2387c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 2388c3dc4c09SDon Skidmore return status; 2389c3dc4c09SDon Skidmore 2390c3dc4c09SDon Skidmore /* link connect/disconnect event occurred */ 2391c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 23924dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 2393c3dc4c09SDon Skidmore 2394c3dc4c09SDon Skidmore if (status) 2395c3dc4c09SDon Skidmore return status; 2396c3dc4c09SDon Skidmore 2397c3dc4c09SDon Skidmore /* Indicate LSC */ 2398c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 2399c3dc4c09SDon Skidmore *lsc = true; 2400c3dc4c09SDon Skidmore 2401c3dc4c09SDon Skidmore return 0; 2402c3dc4c09SDon Skidmore } 2403c3dc4c09SDon Skidmore 2404c3dc4c09SDon Skidmore /** 2405c3dc4c09SDon Skidmore * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 2406c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 2407c3dc4c09SDon Skidmore * 2408c3dc4c09SDon Skidmore * Enable link status change and temperature failure alarm for the external 2409c3dc4c09SDon Skidmore * Base T PHY 2410c3dc4c09SDon Skidmore * 2411c3dc4c09SDon Skidmore * Returns PHY access status 2412c3dc4c09SDon Skidmore **/ 2413c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 2414c3dc4c09SDon Skidmore { 2415c3dc4c09SDon Skidmore u32 status; 2416c3dc4c09SDon Skidmore u16 reg; 2417c3dc4c09SDon Skidmore bool lsc; 2418c3dc4c09SDon Skidmore 2419c3dc4c09SDon Skidmore /* Clear interrupt flags */ 2420c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 2421c3dc4c09SDon Skidmore 2422c3dc4c09SDon Skidmore /* Enable link status change alarm */ 242372f740b1STony Nguyen 242472f740b1STony Nguyen /* Enable the LASI interrupts on X552 devices to receive notifications 242572f740b1STony Nguyen * of the link configurations of the external PHY and correspondingly 242672f740b1STony Nguyen * support the configuration of the internal iXFI link, since iXFI does 242772f740b1STony Nguyen * not support auto-negotiation. This is not required for X553 devices 242872f740b1STony Nguyen * having KR support, which performs auto-negotiations and which is used 242972f740b1STony Nguyen * as the internal link to the external PHY. Hence adding a check here 243072f740b1STony Nguyen * to avoid enabling LASI interrupts for X553 devices. 243172f740b1STony Nguyen */ 243272f740b1STony Nguyen if (hw->mac.type != ixgbe_mac_x550em_a) { 243372f740b1STony Nguyen status = hw->phy.ops.read_reg(hw, 243472f740b1STony Nguyen IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 24354dc4000bSEmil Tantilov MDIO_MMD_AN, ®); 2436c3dc4c09SDon Skidmore if (status) 2437c3dc4c09SDon Skidmore return status; 2438c3dc4c09SDon Skidmore 2439c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 2440c3dc4c09SDon Skidmore 244172f740b1STony Nguyen status = hw->phy.ops.write_reg(hw, 244272f740b1STony Nguyen IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 24434dc4000bSEmil Tantilov MDIO_MMD_AN, reg); 2444c3dc4c09SDon Skidmore if (status) 2445c3dc4c09SDon Skidmore return status; 244672f740b1STony Nguyen } 2447c3dc4c09SDon Skidmore 244883a9fb20SMark Rustad /* Enable high temperature failure and global fault alarms */ 2449c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 24504dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2451c3dc4c09SDon Skidmore ®); 2452c3dc4c09SDon Skidmore if (status) 2453c3dc4c09SDon Skidmore return status; 2454c3dc4c09SDon Skidmore 245583a9fb20SMark Rustad reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | 245683a9fb20SMark Rustad IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); 2457c3dc4c09SDon Skidmore 2458c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 24594dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2460c3dc4c09SDon Skidmore reg); 2461c3dc4c09SDon Skidmore if (status) 2462c3dc4c09SDon Skidmore return status; 2463c3dc4c09SDon Skidmore 2464c3dc4c09SDon Skidmore /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 2465c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 24664dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2467c3dc4c09SDon Skidmore ®); 2468c3dc4c09SDon Skidmore if (status) 2469c3dc4c09SDon Skidmore return status; 2470c3dc4c09SDon Skidmore 2471c3dc4c09SDon Skidmore reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 2472c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT); 2473c3dc4c09SDon Skidmore 2474c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 24754dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2476c3dc4c09SDon Skidmore reg); 2477c3dc4c09SDon Skidmore if (status) 2478c3dc4c09SDon Skidmore return status; 2479c3dc4c09SDon Skidmore 2480c3dc4c09SDon Skidmore /* Enable chip-wide vendor alarm */ 2481c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 24824dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2483c3dc4c09SDon Skidmore ®); 2484c3dc4c09SDon Skidmore if (status) 2485c3dc4c09SDon Skidmore return status; 2486c3dc4c09SDon Skidmore 2487c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 2488c3dc4c09SDon Skidmore 2489c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 24904dc4000bSEmil Tantilov MDIO_MMD_VEND1, 2491c3dc4c09SDon Skidmore reg); 2492c3dc4c09SDon Skidmore 2493c3dc4c09SDon Skidmore return status; 2494c3dc4c09SDon Skidmore } 2495c3dc4c09SDon Skidmore 2496c3dc4c09SDon Skidmore /** 2497c3dc4c09SDon Skidmore * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 2498c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 2499c3dc4c09SDon Skidmore * 2500c3dc4c09SDon Skidmore * Handle external Base T PHY interrupt. If high temperature 2501c3dc4c09SDon Skidmore * failure alarm then return error, else if link status change 2502c3dc4c09SDon Skidmore * then setup internal/external PHY link 2503c3dc4c09SDon Skidmore * 2504c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 2505c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 2506c3dc4c09SDon Skidmore **/ 2507c3dc4c09SDon Skidmore static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) 2508c3dc4c09SDon Skidmore { 2509c3dc4c09SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 2510c3dc4c09SDon Skidmore bool lsc; 2511c3dc4c09SDon Skidmore u32 status; 2512c3dc4c09SDon Skidmore 2513c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 2514c3dc4c09SDon Skidmore if (status) 2515c3dc4c09SDon Skidmore return status; 2516c3dc4c09SDon Skidmore 2517a85ce532SMark Rustad if (lsc && phy->ops.setup_internal_link) 2518c3dc4c09SDon Skidmore return phy->ops.setup_internal_link(hw); 2519c3dc4c09SDon Skidmore 2520c3dc4c09SDon Skidmore return 0; 2521c3dc4c09SDon Skidmore } 2522c3dc4c09SDon Skidmore 2523c3dc4c09SDon Skidmore /** 2524c3dc4c09SDon Skidmore * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 2525c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 2526c3dc4c09SDon Skidmore * @speed: link speed 2527c3dc4c09SDon Skidmore * 2528c3dc4c09SDon Skidmore * Configures the integrated KR PHY. 2529c3dc4c09SDon Skidmore **/ 2530c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 2531c3dc4c09SDon Skidmore ixgbe_link_speed speed) 2532c3dc4c09SDon Skidmore { 2533c3dc4c09SDon Skidmore s32 status; 2534c3dc4c09SDon Skidmore u32 reg_val; 2535c3dc4c09SDon Skidmore 25369a5c27e6SMark Rustad status = hw->mac.ops.read_iosf_sb_reg(hw, 2537c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2538c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2539c3dc4c09SDon Skidmore if (status) 2540c3dc4c09SDon Skidmore return status; 2541c3dc4c09SDon Skidmore 2542c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 2543c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 2544c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 2545c3dc4c09SDon Skidmore 2546c3dc4c09SDon Skidmore /* Advertise 10G support. */ 2547c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 2548c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 2549c3dc4c09SDon Skidmore 2550c3dc4c09SDon Skidmore /* Advertise 1G support. */ 2551c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_1GB_FULL) 2552c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 2553c3dc4c09SDon Skidmore 25549a5c27e6SMark Rustad status = hw->mac.ops.write_iosf_sb_reg(hw, 2555c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2556c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2557c3dc4c09SDon Skidmore 2558470739b5SDon Skidmore if (hw->mac.type == ixgbe_mac_x550em_a) { 2559470739b5SDon Skidmore /* Set lane mode to KR auto negotiation */ 2560470739b5SDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 2561470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2562470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2563470739b5SDon Skidmore 2564470739b5SDon Skidmore if (status) 2565c3dc4c09SDon Skidmore return status; 2566470739b5SDon Skidmore 2567470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 2568470739b5SDon Skidmore reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; 2569470739b5SDon Skidmore reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 2570470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 2571470739b5SDon Skidmore reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 2572470739b5SDon Skidmore 2573470739b5SDon Skidmore status = hw->mac.ops.write_iosf_sb_reg(hw, 2574470739b5SDon Skidmore IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2575470739b5SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2576470739b5SDon Skidmore } 2577470739b5SDon Skidmore 2578470739b5SDon Skidmore return ixgbe_restart_an_internal_phy_x550em(hw); 2579c3dc4c09SDon Skidmore } 2580c3dc4c09SDon Skidmore 2581f572b2c4SMark Rustad /** 2582f572b2c4SMark Rustad * ixgbe_setup_kr_x550em - Configure the KR PHY 25836a14ee0cSDon Skidmore * @hw: pointer to hardware structure 25846a14ee0cSDon Skidmore **/ 25857ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 25866a14ee0cSDon Skidmore { 258754f6d4c4SDon Skidmore /* leave link alone for 2.5G */ 258854f6d4c4SDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) 2589f572b2c4SMark Rustad return 0; 2590f572b2c4SMark Rustad 2591f4a6374bSTony Nguyen if (ixgbe_check_reset_blocked(hw)) 2592f4a6374bSTony Nguyen return 0; 2593f4a6374bSTony Nguyen 2594c3dc4c09SDon Skidmore return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 25956a14ee0cSDon Skidmore } 25966a14ee0cSDon Skidmore 2597c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 2598c3dc4c09SDon Skidmore * @hw: address of hardware structure 2599c3dc4c09SDon Skidmore * @link_up: address of boolean to indicate link status 2600c3dc4c09SDon Skidmore * 2601c3dc4c09SDon Skidmore * Returns error code if unable to get link status. 2602c3dc4c09SDon Skidmore **/ 2603c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 2604c3dc4c09SDon Skidmore { 2605c3dc4c09SDon Skidmore u32 ret; 2606c3dc4c09SDon Skidmore u16 autoneg_status; 2607c3dc4c09SDon Skidmore 2608c3dc4c09SDon Skidmore *link_up = false; 2609c3dc4c09SDon Skidmore 2610c3dc4c09SDon Skidmore /* read this twice back to back to indicate current status */ 26114dc4000bSEmil Tantilov ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 2612c3dc4c09SDon Skidmore &autoneg_status); 2613c3dc4c09SDon Skidmore if (ret) 2614c3dc4c09SDon Skidmore return ret; 2615c3dc4c09SDon Skidmore 26164dc4000bSEmil Tantilov ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, 2617c3dc4c09SDon Skidmore &autoneg_status); 2618c3dc4c09SDon Skidmore if (ret) 2619c3dc4c09SDon Skidmore return ret; 2620c3dc4c09SDon Skidmore 2621c3dc4c09SDon Skidmore *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 2622c3dc4c09SDon Skidmore 2623c3dc4c09SDon Skidmore return 0; 2624c3dc4c09SDon Skidmore } 2625c3dc4c09SDon Skidmore 2626c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 26276a14ee0cSDon Skidmore * @hw: point to hardware structure 26286a14ee0cSDon Skidmore * 2629c3dc4c09SDon Skidmore * Configures the link between the integrated KR PHY and the external X557 PHY 2630c3dc4c09SDon Skidmore * The driver will call this function when it gets a link status change 2631c3dc4c09SDon Skidmore * interrupt from the X557 PHY. This function configures the link speed 2632c3dc4c09SDon Skidmore * between the PHYs to match the link speed of the BASE-T link. 26336a14ee0cSDon Skidmore * 26346a14ee0cSDon Skidmore * A return of a non-zero value indicates an error, and the base driver should 26356a14ee0cSDon Skidmore * not report link up. 26366a14ee0cSDon Skidmore **/ 2637c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 26386a14ee0cSDon Skidmore { 26396a14ee0cSDon Skidmore ixgbe_link_speed force_speed; 2640c3dc4c09SDon Skidmore bool link_up; 2641c3dc4c09SDon Skidmore u32 status; 2642c3dc4c09SDon Skidmore u16 speed; 26436a14ee0cSDon Skidmore 2644c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 2645c3dc4c09SDon Skidmore return IXGBE_ERR_CONFIG; 2646c3dc4c09SDon Skidmore 264748301cf2STony Nguyen if (!(hw->mac.type == ixgbe_mac_X550EM_x && 264848301cf2STony Nguyen !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))) { 2649f164b845SMark Rustad speed = IXGBE_LINK_SPEED_10GB_FULL | 2650f164b845SMark Rustad IXGBE_LINK_SPEED_1GB_FULL; 2651f164b845SMark Rustad return ixgbe_setup_kr_speed_x550em(hw, speed); 2652f164b845SMark Rustad } 2653f164b845SMark Rustad 2654c3dc4c09SDon Skidmore /* If link is not up, then there is no setup necessary so return */ 2655c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 26566a14ee0cSDon Skidmore if (status) 26576a14ee0cSDon Skidmore return status; 26586a14ee0cSDon Skidmore 2659c3dc4c09SDon Skidmore if (!link_up) 26606a14ee0cSDon Skidmore return 0; 26616a14ee0cSDon Skidmore 26626a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 26634dc4000bSEmil Tantilov MDIO_MMD_AN, 26646a14ee0cSDon Skidmore &speed); 2665c3dc4c09SDon Skidmore if (status) 2666c3dc4c09SDon Skidmore return status; 2667c3dc4c09SDon Skidmore 2668c3dc4c09SDon Skidmore /* If link is not still up, then no setup is necessary so return */ 2669c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 2670c3dc4c09SDon Skidmore if (status) 2671c3dc4c09SDon Skidmore return status; 2672c3dc4c09SDon Skidmore 2673c3dc4c09SDon Skidmore if (!link_up) 2674c3dc4c09SDon Skidmore return 0; 26756a14ee0cSDon Skidmore 26766a14ee0cSDon Skidmore /* clear everything but the speed and duplex bits */ 26776a14ee0cSDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 26786a14ee0cSDon Skidmore 26796a14ee0cSDon Skidmore switch (speed) { 26806a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 26816a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 26826a14ee0cSDon Skidmore break; 26836a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 26846a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 26856a14ee0cSDon Skidmore break; 26866a14ee0cSDon Skidmore default: 26876a14ee0cSDon Skidmore /* Internal PHY does not support anything else */ 26886a14ee0cSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 26896a14ee0cSDon Skidmore } 26906a14ee0cSDon Skidmore 26916a14ee0cSDon Skidmore return ixgbe_setup_ixfi_x550em(hw, &force_speed); 26926a14ee0cSDon Skidmore } 26936a14ee0cSDon Skidmore 2694f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 2695f4410d2cSDon Skidmore * @hw: pointer to hardware structure 2696f4410d2cSDon Skidmore **/ 2697f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 2698f4410d2cSDon Skidmore { 2699f4410d2cSDon Skidmore s32 status; 2700f4410d2cSDon Skidmore 2701f4410d2cSDon Skidmore status = ixgbe_reset_phy_generic(hw); 2702f4410d2cSDon Skidmore 2703f4410d2cSDon Skidmore if (status) 2704f4410d2cSDon Skidmore return status; 2705f4410d2cSDon Skidmore 2706f4410d2cSDon Skidmore /* Configure Link Status Alarm and Temperature Threshold interrupts */ 2707f4410d2cSDon Skidmore return ixgbe_enable_lasi_ext_t_x550em(hw); 2708f4410d2cSDon Skidmore } 2709f4410d2cSDon Skidmore 2710a0ad55a3SDon Skidmore /** 2711a0ad55a3SDon Skidmore * ixgbe_led_on_t_x550em - Turns on the software controllable LEDs. 2712a0ad55a3SDon Skidmore * @hw: pointer to hardware structure 2713a0ad55a3SDon Skidmore * @led_idx: led number to turn on 2714a0ad55a3SDon Skidmore **/ 2715d2d43e5bSEmil Tantilov static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 2716a0ad55a3SDon Skidmore { 2717a0ad55a3SDon Skidmore u16 phy_data; 2718a0ad55a3SDon Skidmore 2719a0ad55a3SDon Skidmore if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 2720a0ad55a3SDon Skidmore return IXGBE_ERR_PARAM; 2721a0ad55a3SDon Skidmore 2722a0ad55a3SDon Skidmore /* To turn on the LED, set mode to ON. */ 2723a0ad55a3SDon Skidmore hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 27244dc4000bSEmil Tantilov MDIO_MMD_VEND1, &phy_data); 2725a0ad55a3SDon Skidmore phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; 2726a0ad55a3SDon Skidmore hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 27274dc4000bSEmil Tantilov MDIO_MMD_VEND1, phy_data); 2728a0ad55a3SDon Skidmore 2729a0ad55a3SDon Skidmore return 0; 2730a0ad55a3SDon Skidmore } 2731a0ad55a3SDon Skidmore 2732a0ad55a3SDon Skidmore /** 2733a0ad55a3SDon Skidmore * ixgbe_led_off_t_x550em - Turns off the software controllable LEDs. 2734a0ad55a3SDon Skidmore * @hw: pointer to hardware structure 2735a0ad55a3SDon Skidmore * @led_idx: led number to turn off 2736a0ad55a3SDon Skidmore **/ 2737d2d43e5bSEmil Tantilov static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx) 2738a0ad55a3SDon Skidmore { 2739a0ad55a3SDon Skidmore u16 phy_data; 2740a0ad55a3SDon Skidmore 2741a0ad55a3SDon Skidmore if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 2742a0ad55a3SDon Skidmore return IXGBE_ERR_PARAM; 2743a0ad55a3SDon Skidmore 2744a0ad55a3SDon Skidmore /* To turn on the LED, set mode to ON. */ 2745a0ad55a3SDon Skidmore hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 27464dc4000bSEmil Tantilov MDIO_MMD_VEND1, &phy_data); 2747a0ad55a3SDon Skidmore phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; 2748a0ad55a3SDon Skidmore hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 27494dc4000bSEmil Tantilov MDIO_MMD_VEND1, phy_data); 2750a0ad55a3SDon Skidmore 2751a0ad55a3SDon Skidmore return 0; 2752a0ad55a3SDon Skidmore } 2753a0ad55a3SDon Skidmore 2754cb8e0514STony Nguyen /** 2755cb8e0514STony Nguyen * ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware 2756cb8e0514STony Nguyen * @hw: pointer to the HW structure 2757cb8e0514STony Nguyen * @maj: driver version major number 2758cb8e0514STony Nguyen * @min: driver version minor number 2759cb8e0514STony Nguyen * @build: driver version build number 2760cb8e0514STony Nguyen * @sub: driver version sub build number 2761cb8e0514STony Nguyen * @len: length of driver_ver string 2762cb8e0514STony Nguyen * @driver_ver: driver string 2763cb8e0514STony Nguyen * 2764cb8e0514STony Nguyen * Sends driver version number to firmware through the manageability 2765cb8e0514STony Nguyen * block. On success return 0 2766cb8e0514STony Nguyen * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring 2767cb8e0514STony Nguyen * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 2768cb8e0514STony Nguyen **/ 2769cb8e0514STony Nguyen static s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min, 2770cb8e0514STony Nguyen u8 build, u8 sub, u16 len, 2771cb8e0514STony Nguyen const char *driver_ver) 2772cb8e0514STony Nguyen { 2773cb8e0514STony Nguyen struct ixgbe_hic_drv_info2 fw_cmd; 2774cb8e0514STony Nguyen s32 ret_val; 2775cb8e0514STony Nguyen int i; 2776cb8e0514STony Nguyen 2777cb8e0514STony Nguyen if (!len || !driver_ver || (len > sizeof(fw_cmd.driver_string))) 2778cb8e0514STony Nguyen return IXGBE_ERR_INVALID_ARGUMENT; 2779cb8e0514STony Nguyen 2780cb8e0514STony Nguyen fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 2781cb8e0514STony Nguyen fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len; 2782cb8e0514STony Nguyen fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 2783cb8e0514STony Nguyen fw_cmd.port_num = (u8)hw->bus.func; 2784cb8e0514STony Nguyen fw_cmd.ver_maj = maj; 2785cb8e0514STony Nguyen fw_cmd.ver_min = min; 2786cb8e0514STony Nguyen fw_cmd.ver_build = build; 2787cb8e0514STony Nguyen fw_cmd.ver_sub = sub; 2788cb8e0514STony Nguyen fw_cmd.hdr.checksum = 0; 2789cb8e0514STony Nguyen memcpy(fw_cmd.driver_string, driver_ver, len); 2790cb8e0514STony Nguyen fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 2791cb8e0514STony Nguyen (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 2792cb8e0514STony Nguyen 2793cb8e0514STony Nguyen for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 2794cb8e0514STony Nguyen ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 2795cb8e0514STony Nguyen sizeof(fw_cmd), 2796cb8e0514STony Nguyen IXGBE_HI_COMMAND_TIMEOUT, 2797cb8e0514STony Nguyen true); 2798cb8e0514STony Nguyen if (ret_val) 2799cb8e0514STony Nguyen continue; 2800cb8e0514STony Nguyen 2801cb8e0514STony Nguyen if (fw_cmd.hdr.cmd_or_resp.ret_status != 2802cb8e0514STony Nguyen FW_CEM_RESP_STATUS_SUCCESS) 2803cb8e0514STony Nguyen return IXGBE_ERR_HOST_INTERFACE_COMMAND; 2804cb8e0514STony Nguyen return 0; 2805cb8e0514STony Nguyen } 2806cb8e0514STony Nguyen 2807cb8e0514STony Nguyen return ret_val; 2808cb8e0514STony Nguyen } 2809cb8e0514STony Nguyen 28106ac74394SDon Skidmore /** ixgbe_get_lcd_x550em - Determine lowest common denominator 28116ac74394SDon Skidmore * @hw: pointer to hardware structure 28126ac74394SDon Skidmore * @lcd_speed: pointer to lowest common link speed 28136ac74394SDon Skidmore * 28146ac74394SDon Skidmore * Determine lowest common link speed with link partner. 28156ac74394SDon Skidmore **/ 28166ac74394SDon Skidmore static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, 28176ac74394SDon Skidmore ixgbe_link_speed *lcd_speed) 28186ac74394SDon Skidmore { 28196ac74394SDon Skidmore u16 an_lp_status; 28206ac74394SDon Skidmore s32 status; 28216ac74394SDon Skidmore u16 word = hw->eeprom.ctrl_word_3; 28226ac74394SDon Skidmore 28236ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; 28246ac74394SDon Skidmore 28256ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, 28264dc4000bSEmil Tantilov MDIO_MMD_AN, 28276ac74394SDon Skidmore &an_lp_status); 28286ac74394SDon Skidmore if (status) 28296ac74394SDon Skidmore return status; 28306ac74394SDon Skidmore 28316ac74394SDon Skidmore /* If link partner advertised 1G, return 1G */ 28326ac74394SDon Skidmore if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { 28336ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; 28346ac74394SDon Skidmore return status; 28356ac74394SDon Skidmore } 28366ac74394SDon Skidmore 28376ac74394SDon Skidmore /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ 28386ac74394SDon Skidmore if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || 28396ac74394SDon Skidmore (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) 28406ac74394SDon Skidmore return status; 28416ac74394SDon Skidmore 28426ac74394SDon Skidmore /* Link partner not capable of lower speeds, return 10G */ 28436ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; 28446ac74394SDon Skidmore return status; 28456ac74394SDon Skidmore } 28466ac74394SDon Skidmore 2847afdc71e4SMark Rustad /** 2848afdc71e4SMark Rustad * ixgbe_setup_fc_x550em - Set up flow control 2849afdc71e4SMark Rustad * @hw: pointer to hardware structure 2850afdc71e4SMark Rustad */ 2851afdc71e4SMark Rustad static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) 2852afdc71e4SMark Rustad { 2853afdc71e4SMark Rustad bool pause, asm_dir; 2854afdc71e4SMark Rustad u32 reg_val; 28557adbccbbSTony Nguyen s32 rc = 0; 2856afdc71e4SMark Rustad 2857afdc71e4SMark Rustad /* Validate the requested mode */ 2858afdc71e4SMark Rustad if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 2859afdc71e4SMark Rustad hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 2860afdc71e4SMark Rustad return IXGBE_ERR_INVALID_LINK_SETTINGS; 2861afdc71e4SMark Rustad } 2862afdc71e4SMark Rustad 2863afdc71e4SMark Rustad /* 10gig parts do not have a word in the EEPROM to determine the 2864afdc71e4SMark Rustad * default flow control setting, so we explicitly set it to full. 2865afdc71e4SMark Rustad */ 2866afdc71e4SMark Rustad if (hw->fc.requested_mode == ixgbe_fc_default) 2867afdc71e4SMark Rustad hw->fc.requested_mode = ixgbe_fc_full; 2868afdc71e4SMark Rustad 2869afdc71e4SMark Rustad /* Determine PAUSE and ASM_DIR bits. */ 2870afdc71e4SMark Rustad switch (hw->fc.requested_mode) { 2871afdc71e4SMark Rustad case ixgbe_fc_none: 2872afdc71e4SMark Rustad pause = false; 2873afdc71e4SMark Rustad asm_dir = false; 2874afdc71e4SMark Rustad break; 2875afdc71e4SMark Rustad case ixgbe_fc_tx_pause: 2876afdc71e4SMark Rustad pause = false; 2877afdc71e4SMark Rustad asm_dir = true; 2878afdc71e4SMark Rustad break; 2879afdc71e4SMark Rustad case ixgbe_fc_rx_pause: 2880afdc71e4SMark Rustad /* Rx Flow control is enabled and Tx Flow control is 2881afdc71e4SMark Rustad * disabled by software override. Since there really 2882afdc71e4SMark Rustad * isn't a way to advertise that we are capable of RX 2883afdc71e4SMark Rustad * Pause ONLY, we will advertise that we support both 2884afdc71e4SMark Rustad * symmetric and asymmetric Rx PAUSE, as such we fall 2885afdc71e4SMark Rustad * through to the fc_full statement. Later, we will 2886afdc71e4SMark Rustad * disable the adapter's ability to send PAUSE frames. 2887afdc71e4SMark Rustad */ 28885463fce6SJeff Kirsher fallthrough; 2889afdc71e4SMark Rustad case ixgbe_fc_full: 2890afdc71e4SMark Rustad pause = true; 2891afdc71e4SMark Rustad asm_dir = true; 2892afdc71e4SMark Rustad break; 2893afdc71e4SMark Rustad default: 2894afdc71e4SMark Rustad hw_err(hw, "Flow control param set incorrectly\n"); 2895afdc71e4SMark Rustad return IXGBE_ERR_CONFIG; 2896afdc71e4SMark Rustad } 2897afdc71e4SMark Rustad 28987adbccbbSTony Nguyen switch (hw->device_id) { 28997adbccbbSTony Nguyen case IXGBE_DEV_ID_X550EM_X_KR: 29007adbccbbSTony Nguyen case IXGBE_DEV_ID_X550EM_A_KR: 29017adbccbbSTony Nguyen case IXGBE_DEV_ID_X550EM_A_KR_L: 29029a5c27e6SMark Rustad rc = hw->mac.ops.read_iosf_sb_reg(hw, 2903afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 29049a5c27e6SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 29059a5c27e6SMark Rustad ®_val); 2906afdc71e4SMark Rustad if (rc) 2907afdc71e4SMark Rustad return rc; 2908afdc71e4SMark Rustad 2909afdc71e4SMark Rustad reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 2910afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 2911afdc71e4SMark Rustad if (pause) 2912afdc71e4SMark Rustad reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 2913afdc71e4SMark Rustad if (asm_dir) 2914afdc71e4SMark Rustad reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 29159a5c27e6SMark Rustad rc = hw->mac.ops.write_iosf_sb_reg(hw, 2916afdc71e4SMark Rustad IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 29179a5c27e6SMark Rustad IXGBE_SB_IOSF_TARGET_KR_PHY, 29189a5c27e6SMark Rustad reg_val); 2919afdc71e4SMark Rustad 2920afdc71e4SMark Rustad /* This device does not fully support AN. */ 2921afdc71e4SMark Rustad hw->fc.disable_fc_autoneg = true; 29227adbccbbSTony Nguyen break; 29237adbccbbSTony Nguyen case IXGBE_DEV_ID_X550EM_X_XFI: 29247adbccbbSTony Nguyen hw->fc.disable_fc_autoneg = true; 29257adbccbbSTony Nguyen break; 29267adbccbbSTony Nguyen default: 29277adbccbbSTony Nguyen break; 29287adbccbbSTony Nguyen } 2929afdc71e4SMark Rustad return rc; 2930afdc71e4SMark Rustad } 2931afdc71e4SMark Rustad 29322916500dSDon Skidmore /** 29332916500dSDon Skidmore * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 29342916500dSDon Skidmore * @hw: pointer to hardware structure 29352916500dSDon Skidmore **/ 29362916500dSDon Skidmore static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) 29372916500dSDon Skidmore { 29382916500dSDon Skidmore u32 link_s1, lp_an_page_low, an_cntl_1; 29392916500dSDon Skidmore s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; 29402916500dSDon Skidmore ixgbe_link_speed speed; 29412916500dSDon Skidmore bool link_up; 29422916500dSDon Skidmore 29432916500dSDon Skidmore /* AN should have completed when the cable was plugged in. 29442916500dSDon Skidmore * Look for reasons to bail out. Bail out if: 29452916500dSDon Skidmore * - FC autoneg is disabled, or if 29462916500dSDon Skidmore * - link is not up. 29472916500dSDon Skidmore */ 29482916500dSDon Skidmore if (hw->fc.disable_fc_autoneg) { 29492916500dSDon Skidmore hw_err(hw, "Flow control autoneg is disabled"); 29502916500dSDon Skidmore goto out; 29512916500dSDon Skidmore } 29522916500dSDon Skidmore 29532916500dSDon Skidmore hw->mac.ops.check_link(hw, &speed, &link_up, false); 29542916500dSDon Skidmore if (!link_up) { 29552916500dSDon Skidmore hw_err(hw, "The link is down"); 29562916500dSDon Skidmore goto out; 29572916500dSDon Skidmore } 29582916500dSDon Skidmore 29592916500dSDon Skidmore /* Check at auto-negotiation has completed */ 29602916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 29612916500dSDon Skidmore IXGBE_KRM_LINK_S1(hw->bus.lan_id), 29622916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); 29632916500dSDon Skidmore 29642916500dSDon Skidmore if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { 29652916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 29662916500dSDon Skidmore status = IXGBE_ERR_FC_NOT_NEGOTIATED; 29672916500dSDon Skidmore goto out; 29682916500dSDon Skidmore } 29692916500dSDon Skidmore 29702916500dSDon Skidmore /* Read the 10g AN autoc and LP ability registers and resolve 29712916500dSDon Skidmore * local flow control settings accordingly 29722916500dSDon Skidmore */ 29732916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 29742916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 29752916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1); 29762916500dSDon Skidmore 29772916500dSDon Skidmore if (status) { 29782916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 29792916500dSDon Skidmore goto out; 29802916500dSDon Skidmore } 29812916500dSDon Skidmore 29822916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 29832916500dSDon Skidmore IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id), 29842916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low); 29852916500dSDon Skidmore 29862916500dSDon Skidmore if (status) { 29872916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 29882916500dSDon Skidmore goto out; 29892916500dSDon Skidmore } 29902916500dSDon Skidmore 29912916500dSDon Skidmore status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low, 29922916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_SYM_PAUSE, 29932916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_ASM_PAUSE, 29942916500dSDon Skidmore IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE, 29952916500dSDon Skidmore IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE); 29962916500dSDon Skidmore 29972916500dSDon Skidmore out: 29982916500dSDon Skidmore if (!status) { 29992916500dSDon Skidmore hw->fc.fc_was_autonegged = true; 30002916500dSDon Skidmore } else { 30012916500dSDon Skidmore hw->fc.fc_was_autonegged = false; 30022916500dSDon Skidmore hw->fc.current_mode = hw->fc.requested_mode; 30032916500dSDon Skidmore } 30042916500dSDon Skidmore } 30052916500dSDon Skidmore 30062916500dSDon Skidmore /** 30072916500dSDon Skidmore * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings 30082916500dSDon Skidmore * @hw: pointer to hardware structure 30092916500dSDon Skidmore **/ 30102916500dSDon Skidmore static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) 30112916500dSDon Skidmore { 30122916500dSDon Skidmore hw->fc.fc_was_autonegged = false; 30132916500dSDon Skidmore hw->fc.current_mode = hw->fc.requested_mode; 30142916500dSDon Skidmore } 30152916500dSDon Skidmore 30166ac74394SDon Skidmore /** ixgbe_enter_lplu_x550em - Transition to low power states 30176ac74394SDon Skidmore * @hw: pointer to hardware structure 30186ac74394SDon Skidmore * 30196ac74394SDon Skidmore * Configures Low Power Link Up on transition to low power states 30206ac74394SDon Skidmore * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting 30216ac74394SDon Skidmore * the X557 PHY immediately prior to entering LPLU. 30226ac74394SDon Skidmore **/ 30236ac74394SDon Skidmore static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) 30246ac74394SDon Skidmore { 30256ac74394SDon Skidmore u16 an_10g_cntl_reg, autoneg_reg, speed; 30266ac74394SDon Skidmore s32 status; 30276ac74394SDon Skidmore ixgbe_link_speed lcd_speed; 30286ac74394SDon Skidmore u32 save_autoneg; 30296ac74394SDon Skidmore bool link_up; 30306ac74394SDon Skidmore 30316ac74394SDon Skidmore /* If blocked by MNG FW, then don't restart AN */ 30326ac74394SDon Skidmore if (ixgbe_check_reset_blocked(hw)) 30336ac74394SDon Skidmore return 0; 30346ac74394SDon Skidmore 30356ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 30366ac74394SDon Skidmore if (status) 30376ac74394SDon Skidmore return status; 30386ac74394SDon Skidmore 30396ac74394SDon Skidmore status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, 30406ac74394SDon Skidmore &hw->eeprom.ctrl_word_3); 30416ac74394SDon Skidmore if (status) 30426ac74394SDon Skidmore return status; 30436ac74394SDon Skidmore 30446ac74394SDon Skidmore /* If link is down, LPLU disabled in NVM, WoL disabled, or 30456ac74394SDon Skidmore * manageability disabled, then force link down by entering 30466ac74394SDon Skidmore * low power mode. 30476ac74394SDon Skidmore */ 30486ac74394SDon Skidmore if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || 30496ac74394SDon Skidmore !(hw->wol_enabled || ixgbe_mng_present(hw))) 30506ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 30516ac74394SDon Skidmore 30526ac74394SDon Skidmore /* Determine LCD */ 30536ac74394SDon Skidmore status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); 30546ac74394SDon Skidmore if (status) 30556ac74394SDon Skidmore return status; 30566ac74394SDon Skidmore 30576ac74394SDon Skidmore /* If no valid LCD link speed, then force link down and exit. */ 30586ac74394SDon Skidmore if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) 30596ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 30606ac74394SDon Skidmore 30616ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 30624dc4000bSEmil Tantilov MDIO_MMD_AN, 30636ac74394SDon Skidmore &speed); 30646ac74394SDon Skidmore if (status) 30656ac74394SDon Skidmore return status; 30666ac74394SDon Skidmore 30676ac74394SDon Skidmore /* If no link now, speed is invalid so take link down */ 30686ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 30696ac74394SDon Skidmore if (status) 30706ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 30716ac74394SDon Skidmore 30726ac74394SDon Skidmore /* clear everything but the speed bits */ 30736ac74394SDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; 30746ac74394SDon Skidmore 30756ac74394SDon Skidmore /* If current speed is already LCD, then exit. */ 30766ac74394SDon Skidmore if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && 30776ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || 30786ac74394SDon Skidmore ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && 30796ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) 30806ac74394SDon Skidmore return status; 30816ac74394SDon Skidmore 30826ac74394SDon Skidmore /* Clear AN completed indication */ 30836ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, 30844dc4000bSEmil Tantilov MDIO_MMD_AN, 30856ac74394SDon Skidmore &autoneg_reg); 30866ac74394SDon Skidmore if (status) 30876ac74394SDon Skidmore return status; 30886ac74394SDon Skidmore 30894dc4000bSEmil Tantilov status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, 30904dc4000bSEmil Tantilov MDIO_MMD_AN, 30916ac74394SDon Skidmore &an_10g_cntl_reg); 30926ac74394SDon Skidmore if (status) 30936ac74394SDon Skidmore return status; 30946ac74394SDon Skidmore 30956ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, 30966ac74394SDon Skidmore IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, 30974dc4000bSEmil Tantilov MDIO_MMD_AN, 30986ac74394SDon Skidmore &autoneg_reg); 30996ac74394SDon Skidmore if (status) 31006ac74394SDon Skidmore return status; 31016ac74394SDon Skidmore 31026ac74394SDon Skidmore save_autoneg = hw->phy.autoneg_advertised; 31036ac74394SDon Skidmore 31046ac74394SDon Skidmore /* Setup link at least common link speed */ 31056ac74394SDon Skidmore status = hw->mac.ops.setup_link(hw, lcd_speed, false); 31066ac74394SDon Skidmore 31076ac74394SDon Skidmore /* restore autoneg from before setting lplu speed */ 31086ac74394SDon Skidmore hw->phy.autoneg_advertised = save_autoneg; 31096ac74394SDon Skidmore 31106ac74394SDon Skidmore return status; 31116ac74394SDon Skidmore } 31126ac74394SDon Skidmore 3113537cc5dfSMark Rustad /** 3114b3eb4e18SMark Rustad * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs 3115b3eb4e18SMark Rustad * @hw: pointer to hardware structure 3116b3eb4e18SMark Rustad */ 3117b3eb4e18SMark Rustad static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw) 3118b3eb4e18SMark Rustad { 3119b3eb4e18SMark Rustad u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 }; 3120b3eb4e18SMark Rustad s32 rc; 3121b3eb4e18SMark Rustad 3122b3eb4e18SMark Rustad if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) 3123b3eb4e18SMark Rustad return 0; 3124b3eb4e18SMark Rustad 3125b3eb4e18SMark Rustad rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store); 3126b3eb4e18SMark Rustad if (rc) 3127b3eb4e18SMark Rustad return rc; 3128b3eb4e18SMark Rustad memset(store, 0, sizeof(store)); 3129b3eb4e18SMark Rustad 3130b3eb4e18SMark Rustad rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store); 3131b3eb4e18SMark Rustad if (rc) 3132b3eb4e18SMark Rustad return rc; 3133b3eb4e18SMark Rustad 3134b3eb4e18SMark Rustad return ixgbe_setup_fw_link(hw); 3135b3eb4e18SMark Rustad } 3136b3eb4e18SMark Rustad 3137b3eb4e18SMark Rustad /** 3138b3eb4e18SMark Rustad * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp 3139b3eb4e18SMark Rustad * @hw: pointer to hardware structure 3140b3eb4e18SMark Rustad */ 3141b3eb4e18SMark Rustad static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw) 3142b3eb4e18SMark Rustad { 3143b3eb4e18SMark Rustad u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 }; 3144b3eb4e18SMark Rustad s32 rc; 3145b3eb4e18SMark Rustad 3146b3eb4e18SMark Rustad rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store); 3147b3eb4e18SMark Rustad if (rc) 3148b3eb4e18SMark Rustad return rc; 3149b3eb4e18SMark Rustad 3150b3eb4e18SMark Rustad if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) { 3151b3eb4e18SMark Rustad ixgbe_shutdown_fw_phy(hw); 3152b3eb4e18SMark Rustad return IXGBE_ERR_OVERTEMP; 3153b3eb4e18SMark Rustad } 3154b3eb4e18SMark Rustad return 0; 3155b3eb4e18SMark Rustad } 3156b3eb4e18SMark Rustad 3157b3eb4e18SMark Rustad /** 3158537cc5dfSMark Rustad * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register 3159537cc5dfSMark Rustad * @hw: pointer to hardware structure 3160537cc5dfSMark Rustad * 3161537cc5dfSMark Rustad * Read NW_MNG_IF_SEL register and save field values. 3162537cc5dfSMark Rustad */ 3163537cc5dfSMark Rustad static void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) 3164537cc5dfSMark Rustad { 3165537cc5dfSMark Rustad /* Save NW management interface connected on board. This is used 3166537cc5dfSMark Rustad * to determine internal PHY mode. 3167537cc5dfSMark Rustad */ 3168537cc5dfSMark Rustad hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 3169537cc5dfSMark Rustad 3170537cc5dfSMark Rustad /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set 3171537cc5dfSMark Rustad * PHY address. This register field was has only been used for X552. 3172537cc5dfSMark Rustad */ 3173ae3cb8cbSMark Rustad if (hw->mac.type == ixgbe_mac_x550em_a && 3174ae3cb8cbSMark Rustad hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) { 3175537cc5dfSMark Rustad hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel & 3176537cc5dfSMark Rustad IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> 3177537cc5dfSMark Rustad IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; 3178537cc5dfSMark Rustad } 3179ae3cb8cbSMark Rustad } 3180537cc5dfSMark Rustad 31816a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 31826a14ee0cSDon Skidmore * @hw: pointer to hardware structure 31836a14ee0cSDon Skidmore * 31846a14ee0cSDon Skidmore * Initialize any function pointers that were not able to be 31856a14ee0cSDon Skidmore * set during init_shared_code because the PHY/SFP type was 31866a14ee0cSDon Skidmore * not known. Perform the SFP init if necessary. 31876a14ee0cSDon Skidmore **/ 31887ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 31896a14ee0cSDon Skidmore { 31906a14ee0cSDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 31916a14ee0cSDon Skidmore s32 ret_val; 31926a14ee0cSDon Skidmore 31937e49d616SDon Skidmore hw->mac.ops.set_lan_id(hw); 31947e49d616SDon Skidmore 3195537cc5dfSMark Rustad ixgbe_read_mng_if_sel_x550em(hw); 3196537cc5dfSMark Rustad 3197c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 31986a14ee0cSDon Skidmore phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 3199ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 32006a14ee0cSDon Skidmore } 32016a14ee0cSDon Skidmore 32026a14ee0cSDon Skidmore /* Identify the PHY or SFP module */ 32036a14ee0cSDon Skidmore ret_val = phy->ops.identify(hw); 3204c69be946SEmil Tantilov if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED || 3205c69be946SEmil Tantilov ret_val == IXGBE_ERR_PHY_ADDR_INVALID) 3206c69be946SEmil Tantilov return ret_val; 32076a14ee0cSDon Skidmore 3208c3dc4c09SDon Skidmore /* Setup function pointers based on detected hardware */ 32096a14ee0cSDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 32106a14ee0cSDon Skidmore if (phy->sfp_type != ixgbe_sfp_type_unknown) 32116a14ee0cSDon Skidmore phy->ops.reset = NULL; 32126a14ee0cSDon Skidmore 32136a14ee0cSDon Skidmore /* Set functions pointers based on phy type */ 32146a14ee0cSDon Skidmore switch (hw->phy.type) { 32156a14ee0cSDon Skidmore case ixgbe_phy_x550em_kx4: 32165fbf5addSTony Nguyen phy->ops.setup_link = NULL; 32176a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 32186a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 32196a14ee0cSDon Skidmore break; 32206a14ee0cSDon Skidmore case ixgbe_phy_x550em_kr: 32216a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kr_x550em; 32226a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 32236a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 32246a14ee0cSDon Skidmore break; 322518e01ee7SDon Skidmore case ixgbe_phy_x550em_xfi: 322618e01ee7SDon Skidmore /* link is managed by HW */ 322718e01ee7SDon Skidmore phy->ops.setup_link = NULL; 322818e01ee7SDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 322918e01ee7SDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 323018e01ee7SDon Skidmore break; 32316a14ee0cSDon Skidmore case ixgbe_phy_x550em_ext_t: 3232c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 3233c3dc4c09SDon Skidmore * to determine internal PHY mode 3234c3dc4c09SDon Skidmore */ 3235c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 3236c3dc4c09SDon Skidmore 3237c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup iXFI internal link, 3238c3dc4c09SDon Skidmore * else setup KR now. 3239c3dc4c09SDon Skidmore */ 3240c3dc4c09SDon Skidmore phy->ops.setup_internal_link = 3241c3dc4c09SDon Skidmore ixgbe_setup_internal_phy_t_x550em; 3242c3dc4c09SDon Skidmore 32436ac74394SDon Skidmore /* setup SW LPLU only for first revision */ 32443ca2b250SMark Rustad if (hw->mac.type == ixgbe_mac_X550EM_x && 32453ca2b250SMark Rustad !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) & 32463ca2b250SMark Rustad IXGBE_FUSES0_REV_MASK)) 32476ac74394SDon Skidmore phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; 32486ac74394SDon Skidmore 3249c3dc4c09SDon Skidmore phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 3250f4410d2cSDon Skidmore phy->ops.reset = ixgbe_reset_phy_t_X550em; 32516a14ee0cSDon Skidmore break; 325218bda0d9SDon Skidmore case ixgbe_phy_sgmii: 325318bda0d9SDon Skidmore phy->ops.setup_link = NULL; 325418bda0d9SDon Skidmore break; 3255b3eb4e18SMark Rustad case ixgbe_phy_fw: 3256b3eb4e18SMark Rustad phy->ops.setup_link = ixgbe_setup_fw_link; 3257b3eb4e18SMark Rustad phy->ops.reset = ixgbe_reset_phy_fw; 3258b3eb4e18SMark Rustad break; 32598dc963e1SPaul Greenwalt case ixgbe_phy_ext_1g_t: 32608dc963e1SPaul Greenwalt phy->ops.setup_link = NULL; 32618dc963e1SPaul Greenwalt phy->ops.read_reg = NULL; 32628dc963e1SPaul Greenwalt phy->ops.write_reg = NULL; 32635e999fb4SPaul Greenwalt phy->ops.reset = NULL; 32648dc963e1SPaul Greenwalt break; 32656a14ee0cSDon Skidmore default: 32666a14ee0cSDon Skidmore break; 32676a14ee0cSDon Skidmore } 3268c3dc4c09SDon Skidmore 32696a14ee0cSDon Skidmore return ret_val; 32706a14ee0cSDon Skidmore } 32716a14ee0cSDon Skidmore 32726a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type 32736a14ee0cSDon Skidmore * @hw: pointer to hardware structure 32746a14ee0cSDon Skidmore * 32756a14ee0cSDon Skidmore * Returns the media type (fiber, copper, backplane) 32766a14ee0cSDon Skidmore * 32776a14ee0cSDon Skidmore */ 32787ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 32796a14ee0cSDon Skidmore { 32806a14ee0cSDon Skidmore enum ixgbe_media_type media_type; 32816a14ee0cSDon Skidmore 32826a14ee0cSDon Skidmore /* Detect if there is a copper PHY attached. */ 32836a14ee0cSDon Skidmore switch (hw->device_id) { 3284200157c2SMark Rustad case IXGBE_DEV_ID_X550EM_A_SGMII: 3285200157c2SMark Rustad case IXGBE_DEV_ID_X550EM_A_SGMII_L: 3286200157c2SMark Rustad hw->phy.type = ixgbe_phy_sgmii; 32875463fce6SJeff Kirsher fallthrough; 32886a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 32896a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 329018e01ee7SDon Skidmore case IXGBE_DEV_ID_X550EM_X_XFI: 3291f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR: 3292f572b2c4SMark Rustad case IXGBE_DEV_ID_X550EM_A_KR_L: 32936a14ee0cSDon Skidmore media_type = ixgbe_media_type_backplane; 32946a14ee0cSDon Skidmore break; 32956a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 32962d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 329749425dfcSMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP_N: 32986a14ee0cSDon Skidmore media_type = ixgbe_media_type_fiber; 32996a14ee0cSDon Skidmore break; 33006a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 33016a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 330292ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 3303b3eb4e18SMark Rustad case IXGBE_DEV_ID_X550EM_A_1G_T: 3304b3eb4e18SMark Rustad case IXGBE_DEV_ID_X550EM_A_1G_T_L: 33056a14ee0cSDon Skidmore media_type = ixgbe_media_type_copper; 33066a14ee0cSDon Skidmore break; 33076a14ee0cSDon Skidmore default: 33086a14ee0cSDon Skidmore media_type = ixgbe_media_type_unknown; 33096a14ee0cSDon Skidmore break; 33106a14ee0cSDon Skidmore } 33116a14ee0cSDon Skidmore return media_type; 33126a14ee0cSDon Skidmore } 33136a14ee0cSDon Skidmore 33146a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 33156a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 33166a14ee0cSDon Skidmore **/ 33177ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 33186a14ee0cSDon Skidmore { 3319a1e869deSMark Rustad s32 status; 33206a14ee0cSDon Skidmore u16 reg; 33216a14ee0cSDon Skidmore 33226a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 33236a14ee0cSDon Skidmore IXGBE_MDIO_TX_VENDOR_ALARMS_3, 33244dc4000bSEmil Tantilov MDIO_MMD_PMAPMD, 33256a14ee0cSDon Skidmore ®); 33266a14ee0cSDon Skidmore if (status) 33276a14ee0cSDon Skidmore return status; 33286a14ee0cSDon Skidmore 3329e2261bccSDon Skidmore /* If PHY FW reset completed bit is set then this is the first 3330e2261bccSDon Skidmore * SW instance after a power on so the PHY FW must be un-stalled. 3331e2261bccSDon Skidmore */ 3332e2261bccSDon Skidmore if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 33336a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 33346a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 33354dc4000bSEmil Tantilov MDIO_MMD_VEND1, 33366a14ee0cSDon Skidmore ®); 33376a14ee0cSDon Skidmore if (status) 33386a14ee0cSDon Skidmore return status; 33396a14ee0cSDon Skidmore 33406a14ee0cSDon Skidmore reg &= ~IXGBE_MDIO_POWER_UP_STALL; 33416a14ee0cSDon Skidmore 33426a14ee0cSDon Skidmore status = hw->phy.ops.write_reg(hw, 33436a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 33444dc4000bSEmil Tantilov MDIO_MMD_VEND1, 33456a14ee0cSDon Skidmore reg); 3346e2261bccSDon Skidmore if (status) 3347e2261bccSDon Skidmore return status; 3348e2261bccSDon Skidmore } 3349e2261bccSDon Skidmore 33506a14ee0cSDon Skidmore return status; 33516a14ee0cSDon Skidmore } 33526a14ee0cSDon Skidmore 3353e84db727SMark Rustad /** 3354e84db727SMark Rustad * ixgbe_set_mdio_speed - Set MDIO clock speed 3355e84db727SMark Rustad * @hw: pointer to hardware structure 3356e84db727SMark Rustad */ 3357e84db727SMark Rustad static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) 3358e84db727SMark Rustad { 3359e84db727SMark Rustad u32 hlreg0; 3360e84db727SMark Rustad 3361e84db727SMark Rustad switch (hw->device_id) { 3362e84db727SMark Rustad case IXGBE_DEV_ID_X550EM_X_10G_T: 3363a83c27e7SDon Skidmore case IXGBE_DEV_ID_X550EM_A_SGMII: 3364a83c27e7SDon Skidmore case IXGBE_DEV_ID_X550EM_A_SGMII_L: 336592ed8430SDon Skidmore case IXGBE_DEV_ID_X550EM_A_10G_T: 33662d40cd17SMark Rustad case IXGBE_DEV_ID_X550EM_A_SFP: 3367e84db727SMark Rustad /* Config MDIO clock speed before the first MDIO PHY access */ 3368e84db727SMark Rustad hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 3369e84db727SMark Rustad hlreg0 &= ~IXGBE_HLREG0_MDCSPD; 3370e84db727SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 3371e84db727SMark Rustad break; 3372b3eb4e18SMark Rustad case IXGBE_DEV_ID_X550EM_A_1G_T: 3373b3eb4e18SMark Rustad case IXGBE_DEV_ID_X550EM_A_1G_T_L: 3374b3eb4e18SMark Rustad /* Select fast MDIO clock speed for these devices */ 3375b3eb4e18SMark Rustad hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 3376b3eb4e18SMark Rustad hlreg0 |= IXGBE_HLREG0_MDCSPD; 3377b3eb4e18SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 3378b3eb4e18SMark Rustad break; 3379e84db727SMark Rustad default: 3380e84db727SMark Rustad break; 3381e84db727SMark Rustad } 3382e84db727SMark Rustad } 3383e84db727SMark Rustad 33846a14ee0cSDon Skidmore /** ixgbe_reset_hw_X550em - Perform hardware reset 33856a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 33866a14ee0cSDon Skidmore ** 33876a14ee0cSDon Skidmore ** Resets the hardware by resetting the transmit and receive units, masks 33886a14ee0cSDon Skidmore ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 33896a14ee0cSDon Skidmore ** reset. 33906a14ee0cSDon Skidmore **/ 33917ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 33926a14ee0cSDon Skidmore { 33936a14ee0cSDon Skidmore ixgbe_link_speed link_speed; 33946a14ee0cSDon Skidmore s32 status; 33956a14ee0cSDon Skidmore u32 ctrl = 0; 33966a14ee0cSDon Skidmore u32 i; 33976a14ee0cSDon Skidmore bool link_up = false; 33986133406bSPaul Greenwalt u32 swfw_mask = hw->phy.phy_semaphore_mask; 33996a14ee0cSDon Skidmore 34006a14ee0cSDon Skidmore /* Call adapter stop to disable Tx/Rx and clear interrupts */ 34016a14ee0cSDon Skidmore status = hw->mac.ops.stop_adapter(hw); 34026a14ee0cSDon Skidmore if (status) 34036a14ee0cSDon Skidmore return status; 34046a14ee0cSDon Skidmore 34056a14ee0cSDon Skidmore /* flush pending Tx transactions */ 34066a14ee0cSDon Skidmore ixgbe_clear_tx_pending(hw); 34076a14ee0cSDon Skidmore 3408*bf0a3750SCyril Novikov /* set MDIO speed before talking to the PHY in case it's the 1st time */ 3409*bf0a3750SCyril Novikov ixgbe_set_mdio_speed(hw); 3410*bf0a3750SCyril Novikov 34116a14ee0cSDon Skidmore /* PHY ops must be identified and initialized prior to reset */ 34126a14ee0cSDon Skidmore status = hw->phy.ops.init(hw); 3413c69be946SEmil Tantilov if (status == IXGBE_ERR_SFP_NOT_SUPPORTED || 3414c69be946SEmil Tantilov status == IXGBE_ERR_PHY_ADDR_INVALID) 3415c69be946SEmil Tantilov return status; 34166a14ee0cSDon Skidmore 34176a14ee0cSDon Skidmore /* start the external PHY */ 34186a14ee0cSDon Skidmore if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 34196a14ee0cSDon Skidmore status = ixgbe_init_ext_t_x550em(hw); 34206a14ee0cSDon Skidmore if (status) 34216a14ee0cSDon Skidmore return status; 34226a14ee0cSDon Skidmore } 34236a14ee0cSDon Skidmore 34246a14ee0cSDon Skidmore /* Setup SFP module if there is one present. */ 34256a14ee0cSDon Skidmore if (hw->phy.sfp_setup_needed) { 34266a14ee0cSDon Skidmore status = hw->mac.ops.setup_sfp(hw); 34276a14ee0cSDon Skidmore hw->phy.sfp_setup_needed = false; 34286a14ee0cSDon Skidmore } 34296a14ee0cSDon Skidmore 3430bbb27076SEmil Tantilov if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) 3431bbb27076SEmil Tantilov return status; 3432bbb27076SEmil Tantilov 34336a14ee0cSDon Skidmore /* Reset PHY */ 34346a14ee0cSDon Skidmore if (!hw->phy.reset_disable && hw->phy.ops.reset) 34356a14ee0cSDon Skidmore hw->phy.ops.reset(hw); 34366a14ee0cSDon Skidmore 34376a14ee0cSDon Skidmore mac_reset_top: 34386a14ee0cSDon Skidmore /* Issue global reset to the MAC. Needs to be SW reset if link is up. 34396a14ee0cSDon Skidmore * If link reset is used when link is up, it might reset the PHY when 34406a14ee0cSDon Skidmore * mng is using it. If link is down or the flag to force full link 34416a14ee0cSDon Skidmore * reset is set, then perform link reset. 34426a14ee0cSDon Skidmore */ 34436a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_LNK_RST; 34446a14ee0cSDon Skidmore 34456a14ee0cSDon Skidmore if (!hw->force_full_reset) { 34466a14ee0cSDon Skidmore hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 34476a14ee0cSDon Skidmore if (link_up) 34486a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_RST; 34496a14ee0cSDon Skidmore } 34506a14ee0cSDon Skidmore 34516133406bSPaul Greenwalt status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 34526133406bSPaul Greenwalt if (status) { 34536133406bSPaul Greenwalt hw_dbg(hw, "semaphore failed with %d", status); 34546133406bSPaul Greenwalt return IXGBE_ERR_SWFW_SYNC; 34556133406bSPaul Greenwalt } 34566133406bSPaul Greenwalt 34576a14ee0cSDon Skidmore ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 34586a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 34596a14ee0cSDon Skidmore IXGBE_WRITE_FLUSH(hw); 34606133406bSPaul Greenwalt hw->mac.ops.release_swfw_sync(hw, swfw_mask); 3461efff2e02SMark Rustad usleep_range(1000, 1200); 34626a14ee0cSDon Skidmore 34636a14ee0cSDon Skidmore /* Poll for reset bit to self-clear meaning reset is complete */ 34646a14ee0cSDon Skidmore for (i = 0; i < 10; i++) { 34656a14ee0cSDon Skidmore ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 34666a14ee0cSDon Skidmore if (!(ctrl & IXGBE_CTRL_RST_MASK)) 34676a14ee0cSDon Skidmore break; 3468efff2e02SMark Rustad udelay(1); 34696a14ee0cSDon Skidmore } 34706a14ee0cSDon Skidmore 34716a14ee0cSDon Skidmore if (ctrl & IXGBE_CTRL_RST_MASK) { 34726a14ee0cSDon Skidmore status = IXGBE_ERR_RESET_FAILED; 34736a14ee0cSDon Skidmore hw_dbg(hw, "Reset polling failed to complete.\n"); 34746a14ee0cSDon Skidmore } 34756a14ee0cSDon Skidmore 34766a14ee0cSDon Skidmore msleep(50); 34776a14ee0cSDon Skidmore 34786a14ee0cSDon Skidmore /* Double resets are required for recovery from certain error 34796a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 34806a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 34816a14ee0cSDon Skidmore */ 34826a14ee0cSDon Skidmore if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 34836a14ee0cSDon Skidmore hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 34846a14ee0cSDon Skidmore goto mac_reset_top; 34856a14ee0cSDon Skidmore } 34866a14ee0cSDon Skidmore 34876a14ee0cSDon Skidmore /* Store the permanent mac address */ 34886a14ee0cSDon Skidmore hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 34896a14ee0cSDon Skidmore 34906a14ee0cSDon Skidmore /* Store MAC address from RAR0, clear receive address registers, and 34916a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 34926a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 34936a14ee0cSDon Skidmore */ 34946a14ee0cSDon Skidmore hw->mac.num_rar_entries = 128; 34956a14ee0cSDon Skidmore hw->mac.ops.init_rx_addrs(hw); 34966a14ee0cSDon Skidmore 3497e84db727SMark Rustad ixgbe_set_mdio_speed(hw); 3498deda562aSDon Skidmore 3499ab5fe0c5SDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 3500ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 3501ab5fe0c5SDon Skidmore 35026a14ee0cSDon Skidmore return status; 35036a14ee0cSDon Skidmore } 35046a14ee0cSDon Skidmore 35055b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 35065b7f000fSDon Skidmore * anti-spoofing 35075b7f000fSDon Skidmore * @hw: pointer to hardware structure 35085b7f000fSDon Skidmore * @enable: enable or disable switch for Ethertype anti-spoofing 35095b7f000fSDon Skidmore * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 35105b7f000fSDon Skidmore **/ 3511bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 3512bc035fc5SDon Skidmore bool enable, int vf) 35135b7f000fSDon Skidmore { 35145b7f000fSDon Skidmore int vf_target_reg = vf >> 3; 35155b7f000fSDon Skidmore int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 35165b7f000fSDon Skidmore u32 pfvfspoof; 35175b7f000fSDon Skidmore 35185b7f000fSDon Skidmore pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 35195b7f000fSDon Skidmore if (enable) 3520b4f47a48SJacob Keller pfvfspoof |= BIT(vf_target_shift); 35215b7f000fSDon Skidmore else 3522b4f47a48SJacob Keller pfvfspoof &= ~BIT(vf_target_shift); 35235b7f000fSDon Skidmore 35245b7f000fSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 35255b7f000fSDon Skidmore } 35265b7f000fSDon Skidmore 35276d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 35286d4c96adSDon Skidmore * @hw: pointer to hardware structure 35296d4c96adSDon Skidmore * @enable: enable or disable source address pruning 35306d4c96adSDon Skidmore * @pool: Rx pool to set source address pruning for 35316d4c96adSDon Skidmore **/ 35326d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 35336d4c96adSDon Skidmore bool enable, 35346d4c96adSDon Skidmore unsigned int pool) 35356d4c96adSDon Skidmore { 35366d4c96adSDon Skidmore u64 pfflp; 35376d4c96adSDon Skidmore 35386d4c96adSDon Skidmore /* max rx pool is 63 */ 35396d4c96adSDon Skidmore if (pool > 63) 35406d4c96adSDon Skidmore return; 35416d4c96adSDon Skidmore 35426d4c96adSDon Skidmore pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 35436d4c96adSDon Skidmore pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 35446d4c96adSDon Skidmore 35456d4c96adSDon Skidmore if (enable) 35466d4c96adSDon Skidmore pfflp |= (1ULL << pool); 35476d4c96adSDon Skidmore else 35486d4c96adSDon Skidmore pfflp &= ~(1ULL << pool); 35496d4c96adSDon Skidmore 35506d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 35516d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 35526d4c96adSDon Skidmore } 35536d4c96adSDon Skidmore 3554449e21a9SMark Rustad /** 35552916500dSDon Skidmore * ixgbe_setup_fc_backplane_x550em_a - Set up flow control 35562916500dSDon Skidmore * @hw: pointer to hardware structure 35572916500dSDon Skidmore * 35582916500dSDon Skidmore * Called at init time to set up flow control. 35592916500dSDon Skidmore **/ 35602916500dSDon Skidmore static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) 35612916500dSDon Skidmore { 35622916500dSDon Skidmore s32 status = 0; 35632916500dSDon Skidmore u32 an_cntl = 0; 35642916500dSDon Skidmore 35652916500dSDon Skidmore /* Validate the requested mode */ 35662916500dSDon Skidmore if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 35672916500dSDon Skidmore hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 35682916500dSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 35692916500dSDon Skidmore } 35702916500dSDon Skidmore 35712916500dSDon Skidmore if (hw->fc.requested_mode == ixgbe_fc_default) 35722916500dSDon Skidmore hw->fc.requested_mode = ixgbe_fc_full; 35732916500dSDon Skidmore 35742916500dSDon Skidmore /* Set up the 1G and 10G flow control advertisement registers so the 35752916500dSDon Skidmore * HW will be able to do FC autoneg once the cable is plugged in. If 35762916500dSDon Skidmore * we link at 10G, the 1G advertisement is harmless and vice versa. 35772916500dSDon Skidmore */ 35782916500dSDon Skidmore status = hw->mac.ops.read_iosf_sb_reg(hw, 35792916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 35802916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl); 35812916500dSDon Skidmore 35822916500dSDon Skidmore if (status) { 35832916500dSDon Skidmore hw_dbg(hw, "Auto-Negotiation did not complete\n"); 35842916500dSDon Skidmore return status; 35852916500dSDon Skidmore } 35862916500dSDon Skidmore 35872916500dSDon Skidmore /* The possible values of fc.requested_mode are: 35882916500dSDon Skidmore * 0: Flow control is completely disabled 35892916500dSDon Skidmore * 1: Rx flow control is enabled (we can receive pause frames, 35902916500dSDon Skidmore * but not send pause frames). 35912916500dSDon Skidmore * 2: Tx flow control is enabled (we can send pause frames but 35922916500dSDon Skidmore * we do not support receiving pause frames). 35932916500dSDon Skidmore * 3: Both Rx and Tx flow control (symmetric) are enabled. 35942916500dSDon Skidmore * other: Invalid. 35952916500dSDon Skidmore */ 35962916500dSDon Skidmore switch (hw->fc.requested_mode) { 35972916500dSDon Skidmore case ixgbe_fc_none: 35982916500dSDon Skidmore /* Flow control completely disabled by software override. */ 35992916500dSDon Skidmore an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 36002916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 36012916500dSDon Skidmore break; 36022916500dSDon Skidmore case ixgbe_fc_tx_pause: 36032916500dSDon Skidmore /* Tx Flow control is enabled, and Rx Flow control is 36042916500dSDon Skidmore * disabled by software override. 36052916500dSDon Skidmore */ 36062916500dSDon Skidmore an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 36072916500dSDon Skidmore an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 36082916500dSDon Skidmore break; 36092916500dSDon Skidmore case ixgbe_fc_rx_pause: 36102916500dSDon Skidmore /* Rx Flow control is enabled and Tx Flow control is 36112916500dSDon Skidmore * disabled by software override. Since there really 36122916500dSDon Skidmore * isn't a way to advertise that we are capable of RX 36132916500dSDon Skidmore * Pause ONLY, we will advertise that we support both 36142916500dSDon Skidmore * symmetric and asymmetric Rx PAUSE, as such we fall 36152916500dSDon Skidmore * through to the fc_full statement. Later, we will 36162916500dSDon Skidmore * disable the adapter's ability to send PAUSE frames. 36172916500dSDon Skidmore */ 36182916500dSDon Skidmore case ixgbe_fc_full: 36192916500dSDon Skidmore /* Flow control (both Rx and Tx) is enabled by SW override. */ 36202916500dSDon Skidmore an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 36212916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 36222916500dSDon Skidmore break; 36232916500dSDon Skidmore default: 36242916500dSDon Skidmore hw_err(hw, "Flow control param set incorrectly\n"); 36252916500dSDon Skidmore return IXGBE_ERR_CONFIG; 36262916500dSDon Skidmore } 36272916500dSDon Skidmore 36282916500dSDon Skidmore status = hw->mac.ops.write_iosf_sb_reg(hw, 36292916500dSDon Skidmore IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 36302916500dSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); 36312916500dSDon Skidmore 36322916500dSDon Skidmore /* Restart auto-negotiation. */ 3633470739b5SDon Skidmore status = ixgbe_restart_an_internal_phy_x550em(hw); 36342916500dSDon Skidmore 36352916500dSDon Skidmore return status; 36362916500dSDon Skidmore } 36372916500dSDon Skidmore 36382916500dSDon Skidmore /** 3639449e21a9SMark Rustad * ixgbe_set_mux - Set mux for port 1 access with CS4227 3640449e21a9SMark Rustad * @hw: pointer to hardware structure 3641449e21a9SMark Rustad * @state: set mux if 1, clear if 0 3642449e21a9SMark Rustad */ 3643449e21a9SMark Rustad static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) 3644449e21a9SMark Rustad { 3645449e21a9SMark Rustad u32 esdp; 3646449e21a9SMark Rustad 3647449e21a9SMark Rustad if (!hw->bus.lan_id) 3648449e21a9SMark Rustad return; 3649449e21a9SMark Rustad esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 3650449e21a9SMark Rustad if (state) 3651449e21a9SMark Rustad esdp |= IXGBE_ESDP_SDP1; 3652449e21a9SMark Rustad else 3653449e21a9SMark Rustad esdp &= ~IXGBE_ESDP_SDP1; 3654449e21a9SMark Rustad IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 3655449e21a9SMark Rustad IXGBE_WRITE_FLUSH(hw); 3656449e21a9SMark Rustad } 3657449e21a9SMark Rustad 3658449e21a9SMark Rustad /** 3659449e21a9SMark Rustad * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore 3660449e21a9SMark Rustad * @hw: pointer to hardware structure 3661449e21a9SMark Rustad * @mask: Mask to specify which semaphore to acquire 3662449e21a9SMark Rustad * 3663449e21a9SMark Rustad * Acquires the SWFW semaphore and sets the I2C MUX 3664449e21a9SMark Rustad */ 3665449e21a9SMark Rustad static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 3666449e21a9SMark Rustad { 3667449e21a9SMark Rustad s32 status; 3668449e21a9SMark Rustad 3669449e21a9SMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, mask); 3670449e21a9SMark Rustad if (status) 3671449e21a9SMark Rustad return status; 3672449e21a9SMark Rustad 3673449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 3674449e21a9SMark Rustad ixgbe_set_mux(hw, 1); 3675449e21a9SMark Rustad 3676449e21a9SMark Rustad return 0; 3677449e21a9SMark Rustad } 3678449e21a9SMark Rustad 3679449e21a9SMark Rustad /** 3680449e21a9SMark Rustad * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore 3681449e21a9SMark Rustad * @hw: pointer to hardware structure 3682449e21a9SMark Rustad * @mask: Mask to specify which semaphore to release 3683449e21a9SMark Rustad * 3684449e21a9SMark Rustad * Releases the SWFW semaphore and sets the I2C MUX 3685449e21a9SMark Rustad */ 3686449e21a9SMark Rustad static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) 3687449e21a9SMark Rustad { 3688449e21a9SMark Rustad if (mask & IXGBE_GSSR_I2C_MASK) 3689449e21a9SMark Rustad ixgbe_set_mux(hw, 0); 3690449e21a9SMark Rustad 3691449e21a9SMark Rustad ixgbe_release_swfw_sync_X540(hw, mask); 3692449e21a9SMark Rustad } 3693449e21a9SMark Rustad 369449425dfcSMark Rustad /** 369549425dfcSMark Rustad * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore 369649425dfcSMark Rustad * @hw: pointer to hardware structure 369749425dfcSMark Rustad * @mask: Mask to specify which semaphore to acquire 369849425dfcSMark Rustad * 369949425dfcSMark Rustad * Acquires the SWFW semaphore and get the shared PHY token as needed 370049425dfcSMark Rustad */ 370149425dfcSMark Rustad static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 370249425dfcSMark Rustad { 370349425dfcSMark Rustad u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 370449425dfcSMark Rustad int retries = FW_PHY_TOKEN_RETRIES; 370549425dfcSMark Rustad s32 status; 370649425dfcSMark Rustad 370749425dfcSMark Rustad while (--retries) { 370849425dfcSMark Rustad status = 0; 370949425dfcSMark Rustad if (hmask) 371049425dfcSMark Rustad status = ixgbe_acquire_swfw_sync_X540(hw, hmask); 371149425dfcSMark Rustad if (status) 371249425dfcSMark Rustad return status; 371349425dfcSMark Rustad if (!(mask & IXGBE_GSSR_TOKEN_SM)) 371449425dfcSMark Rustad return 0; 371549425dfcSMark Rustad 371649425dfcSMark Rustad status = ixgbe_get_phy_token(hw); 371749425dfcSMark Rustad if (!status) 371849425dfcSMark Rustad return 0; 371949425dfcSMark Rustad if (hmask) 372049425dfcSMark Rustad ixgbe_release_swfw_sync_X540(hw, hmask); 372149425dfcSMark Rustad if (status != IXGBE_ERR_TOKEN_RETRY) 372249425dfcSMark Rustad return status; 3723d4f90d9dSArnd Bergmann msleep(FW_PHY_TOKEN_DELAY); 372449425dfcSMark Rustad } 372549425dfcSMark Rustad 372649425dfcSMark Rustad return status; 372749425dfcSMark Rustad } 372849425dfcSMark Rustad 372949425dfcSMark Rustad /** 373049425dfcSMark Rustad * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore 373149425dfcSMark Rustad * @hw: pointer to hardware structure 373249425dfcSMark Rustad * @mask: Mask to specify which semaphore to release 373349425dfcSMark Rustad * 373449425dfcSMark Rustad * Release the SWFW semaphore and puts the shared PHY token as needed 373549425dfcSMark Rustad */ 373649425dfcSMark Rustad static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) 373749425dfcSMark Rustad { 373849425dfcSMark Rustad u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 373949425dfcSMark Rustad 374049425dfcSMark Rustad if (mask & IXGBE_GSSR_TOKEN_SM) 374149425dfcSMark Rustad ixgbe_put_phy_token(hw); 374249425dfcSMark Rustad 374349425dfcSMark Rustad if (hmask) 374449425dfcSMark Rustad ixgbe_release_swfw_sync_X540(hw, hmask); 374549425dfcSMark Rustad } 374649425dfcSMark Rustad 3747d31afc8fSMark Rustad /** 3748d31afc8fSMark Rustad * ixgbe_read_phy_reg_x550a - Reads specified PHY register 3749d31afc8fSMark Rustad * @hw: pointer to hardware structure 3750d31afc8fSMark Rustad * @reg_addr: 32 bit address of PHY register to read 37515ba643c6STony Nguyen * @device_type: 5 bit device type 3752d31afc8fSMark Rustad * @phy_data: Pointer to read data from PHY register 3753d31afc8fSMark Rustad * 3754d31afc8fSMark Rustad * Reads a value from a specified PHY register using the SWFW lock and PHY 3755d31afc8fSMark Rustad * Token. The PHY Token is needed since the MDIO is shared between to MAC 3756d31afc8fSMark Rustad * instances. 3757d31afc8fSMark Rustad */ 3758d31afc8fSMark Rustad static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 3759d31afc8fSMark Rustad u32 device_type, u16 *phy_data) 3760d31afc8fSMark Rustad { 3761d31afc8fSMark Rustad u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 3762d31afc8fSMark Rustad s32 status; 3763d31afc8fSMark Rustad 3764d31afc8fSMark Rustad if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 3765d31afc8fSMark Rustad return IXGBE_ERR_SWFW_SYNC; 3766d31afc8fSMark Rustad 3767d31afc8fSMark Rustad status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); 3768d31afc8fSMark Rustad 3769d31afc8fSMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 3770d31afc8fSMark Rustad 3771d31afc8fSMark Rustad return status; 3772d31afc8fSMark Rustad } 3773d31afc8fSMark Rustad 3774d31afc8fSMark Rustad /** 3775d31afc8fSMark Rustad * ixgbe_write_phy_reg_x550a - Writes specified PHY register 3776d31afc8fSMark Rustad * @hw: pointer to hardware structure 3777d31afc8fSMark Rustad * @reg_addr: 32 bit PHY register to write 3778d31afc8fSMark Rustad * @device_type: 5 bit device type 3779d31afc8fSMark Rustad * @phy_data: Data to write to the PHY register 3780d31afc8fSMark Rustad * 3781d31afc8fSMark Rustad * Writes a value to specified PHY register using the SWFW lock and PHY Token. 3782d31afc8fSMark Rustad * The PHY Token is needed since the MDIO is shared between to MAC instances. 3783d31afc8fSMark Rustad */ 3784d31afc8fSMark Rustad static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, 3785d31afc8fSMark Rustad u32 device_type, u16 phy_data) 3786d31afc8fSMark Rustad { 3787d31afc8fSMark Rustad u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 3788d31afc8fSMark Rustad s32 status; 3789d31afc8fSMark Rustad 3790d31afc8fSMark Rustad if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 3791d31afc8fSMark Rustad return IXGBE_ERR_SWFW_SYNC; 3792d31afc8fSMark Rustad 3793d31afc8fSMark Rustad status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data); 3794d31afc8fSMark Rustad hw->mac.ops.release_swfw_sync(hw, mask); 3795d31afc8fSMark Rustad 3796d31afc8fSMark Rustad return status; 3797d31afc8fSMark Rustad } 3798d31afc8fSMark Rustad 37996a14ee0cSDon Skidmore #define X550_COMMON_MAC \ 38006a14ee0cSDon Skidmore .init_hw = &ixgbe_init_hw_generic, \ 38016a14ee0cSDon Skidmore .start_hw = &ixgbe_start_hw_X540, \ 38026a14ee0cSDon Skidmore .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 38036a14ee0cSDon Skidmore .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 38046a14ee0cSDon Skidmore .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 38056a14ee0cSDon Skidmore .get_device_caps = &ixgbe_get_device_caps_generic, \ 38066a14ee0cSDon Skidmore .stop_adapter = &ixgbe_stop_adapter_generic, \ 38076a14ee0cSDon Skidmore .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 38086a14ee0cSDon Skidmore .read_analog_reg8 = NULL, \ 38096a14ee0cSDon Skidmore .write_analog_reg8 = NULL, \ 38106a14ee0cSDon Skidmore .set_rxpba = &ixgbe_set_rxpba_generic, \ 38116a14ee0cSDon Skidmore .check_link = &ixgbe_check_mac_link_generic, \ 38126a14ee0cSDon Skidmore .blink_led_start = &ixgbe_blink_led_start_X540, \ 38136a14ee0cSDon Skidmore .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 38146a14ee0cSDon Skidmore .set_rar = &ixgbe_set_rar_generic, \ 38156a14ee0cSDon Skidmore .clear_rar = &ixgbe_clear_rar_generic, \ 38166a14ee0cSDon Skidmore .set_vmdq = &ixgbe_set_vmdq_generic, \ 38176a14ee0cSDon Skidmore .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 38186a14ee0cSDon Skidmore .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 38196a14ee0cSDon Skidmore .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 38206a14ee0cSDon Skidmore .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 38216a14ee0cSDon Skidmore .enable_mc = &ixgbe_enable_mc_generic, \ 38226a14ee0cSDon Skidmore .disable_mc = &ixgbe_disable_mc_generic, \ 38236a14ee0cSDon Skidmore .clear_vfta = &ixgbe_clear_vfta_generic, \ 38246a14ee0cSDon Skidmore .set_vfta = &ixgbe_set_vfta_generic, \ 38256a14ee0cSDon Skidmore .fc_enable = &ixgbe_fc_enable_generic, \ 3826cb8e0514STony Nguyen .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_x550, \ 38276a14ee0cSDon Skidmore .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 38286a14ee0cSDon Skidmore .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 38296a14ee0cSDon Skidmore .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 38306d4c96adSDon Skidmore .set_source_address_pruning = \ 38316d4c96adSDon Skidmore &ixgbe_set_source_address_pruning_X550, \ 38325b7f000fSDon Skidmore .set_ethertype_anti_spoofing = \ 38335b7f000fSDon Skidmore &ixgbe_set_ethertype_anti_spoofing_X550, \ 38346a14ee0cSDon Skidmore .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 38356a14ee0cSDon Skidmore .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 38366a14ee0cSDon Skidmore .get_thermal_sensor_data = NULL, \ 38376a14ee0cSDon Skidmore .init_thermal_sensor_thresh = NULL, \ 383859dd45d5SSebastian Basierski .fw_recovery_mode = &ixgbe_fw_recovery_mode_X550, \ 38391f9ac57cSDon Skidmore .enable_rx = &ixgbe_enable_rx_generic, \ 38401f9ac57cSDon Skidmore .disable_rx = &ixgbe_disable_rx_x550, \ 38416a14ee0cSDon Skidmore 384237689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550 = { 38436a14ee0cSDon Skidmore X550_COMMON_MAC 3844a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_generic, 3845a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_generic, 3846805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 38476a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X540, 38486a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X540, 38496a14ee0cSDon Skidmore .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 38506a14ee0cSDon Skidmore .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 38516a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_mac_link_X540, 38526a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 3853454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_generic, 38546a14ee0cSDon Skidmore .setup_sfp = NULL, 3855449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, 3856449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X540, 3857dbd15b8fSDon Skidmore .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 3858afdc71e4SMark Rustad .prot_autoc_read = prot_autoc_read_generic, 3859afdc71e4SMark Rustad .prot_autoc_write = prot_autoc_write_generic, 3860afdc71e4SMark Rustad .setup_fc = ixgbe_setup_fc_generic, 38612916500dSDon Skidmore .fc_autoneg = ixgbe_fc_autoneg, 38626a14ee0cSDon Skidmore }; 38636a14ee0cSDon Skidmore 386437689010SMark Rustad static const struct ixgbe_mac_operations mac_ops_X550EM_x = { 38656a14ee0cSDon Skidmore X550_COMMON_MAC 3866a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_t_x550em, 3867a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_t_x550em, 3868805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 38696a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X550em, 38706a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X550em, 38716a14ee0cSDon Skidmore .get_san_mac_addr = NULL, 38726a14ee0cSDon Skidmore .get_wwn_prefix = NULL, 38734695886cSEmil Tantilov .setup_link = &ixgbe_setup_mac_link_X540, 38746a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 3875454c65ddSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_X550em, 38766a14ee0cSDon Skidmore .setup_sfp = ixgbe_setup_sfp_modules_X550em, 3877449e21a9SMark Rustad .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 3878449e21a9SMark Rustad .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 3879dbd15b8fSDon Skidmore .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 3880afdc71e4SMark Rustad .setup_fc = NULL, /* defined later */ 38812916500dSDon Skidmore .fc_autoneg = ixgbe_fc_autoneg, 38829a5c27e6SMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, 38839a5c27e6SMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, 38846a14ee0cSDon Skidmore }; 38856a14ee0cSDon Skidmore 38865e999fb4SPaul Greenwalt static const struct ixgbe_mac_operations mac_ops_X550EM_x_fw = { 38875e999fb4SPaul Greenwalt X550_COMMON_MAC 38885e999fb4SPaul Greenwalt .led_on = NULL, 38895e999fb4SPaul Greenwalt .led_off = NULL, 38905e999fb4SPaul Greenwalt .init_led_link_act = NULL, 38915e999fb4SPaul Greenwalt .reset_hw = &ixgbe_reset_hw_X550em, 38925e999fb4SPaul Greenwalt .get_media_type = &ixgbe_get_media_type_X550em, 38935e999fb4SPaul Greenwalt .get_san_mac_addr = NULL, 38945e999fb4SPaul Greenwalt .get_wwn_prefix = NULL, 38955e999fb4SPaul Greenwalt .setup_link = &ixgbe_setup_mac_link_X540, 38965e999fb4SPaul Greenwalt .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 38975e999fb4SPaul Greenwalt .get_bus_info = &ixgbe_get_bus_info_X550em, 38985e999fb4SPaul Greenwalt .setup_sfp = ixgbe_setup_sfp_modules_X550em, 38995e999fb4SPaul Greenwalt .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, 39005e999fb4SPaul Greenwalt .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, 39015e999fb4SPaul Greenwalt .init_swfw_sync = &ixgbe_init_swfw_sync_X540, 39025e999fb4SPaul Greenwalt .setup_fc = NULL, 39035e999fb4SPaul Greenwalt .fc_autoneg = ixgbe_fc_autoneg, 39045e999fb4SPaul Greenwalt .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, 39055e999fb4SPaul Greenwalt .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, 39065e999fb4SPaul Greenwalt }; 39075e999fb4SPaul Greenwalt 39082e033eacSBhumika Goyal static const struct ixgbe_mac_operations mac_ops_x550em_a = { 390949425dfcSMark Rustad X550_COMMON_MAC 3910a0ad55a3SDon Skidmore .led_on = ixgbe_led_on_t_x550em, 3911a0ad55a3SDon Skidmore .led_off = ixgbe_led_off_t_x550em, 3912805cedd6SDon Skidmore .init_led_link_act = ixgbe_init_led_link_act_generic, 391349425dfcSMark Rustad .reset_hw = ixgbe_reset_hw_X550em, 391449425dfcSMark Rustad .get_media_type = ixgbe_get_media_type_X550em, 391549425dfcSMark Rustad .get_san_mac_addr = NULL, 391649425dfcSMark Rustad .get_wwn_prefix = NULL, 39175b9d3cfbSEmil Tantilov .setup_link = &ixgbe_setup_mac_link_X540, 391849425dfcSMark Rustad .get_link_capabilities = ixgbe_get_link_capabilities_X550em, 391949425dfcSMark Rustad .get_bus_info = ixgbe_get_bus_info_X550em, 392049425dfcSMark Rustad .setup_sfp = ixgbe_setup_sfp_modules_X550em, 392149425dfcSMark Rustad .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, 392249425dfcSMark Rustad .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, 3923a0254a70SMark Rustad .setup_fc = ixgbe_setup_fc_x550em, 3924470739b5SDon Skidmore .fc_autoneg = ixgbe_fc_autoneg, 392549425dfcSMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, 392649425dfcSMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, 392749425dfcSMark Rustad }; 392849425dfcSMark Rustad 39292e033eacSBhumika Goyal static const struct ixgbe_mac_operations mac_ops_x550em_a_fw = { 3930b3eb4e18SMark Rustad X550_COMMON_MAC 3931b3eb4e18SMark Rustad .led_on = ixgbe_led_on_generic, 3932b3eb4e18SMark Rustad .led_off = ixgbe_led_off_generic, 3933b3eb4e18SMark Rustad .init_led_link_act = ixgbe_init_led_link_act_generic, 3934b3eb4e18SMark Rustad .reset_hw = ixgbe_reset_hw_X550em, 3935b3eb4e18SMark Rustad .get_media_type = ixgbe_get_media_type_X550em, 3936b3eb4e18SMark Rustad .get_san_mac_addr = NULL, 3937b3eb4e18SMark Rustad .get_wwn_prefix = NULL, 3938b3eb4e18SMark Rustad .setup_link = NULL, /* defined later */ 3939b3eb4e18SMark Rustad .get_link_capabilities = ixgbe_get_link_capabilities_X550em, 3940b3eb4e18SMark Rustad .get_bus_info = ixgbe_get_bus_info_X550em, 3941b3eb4e18SMark Rustad .setup_sfp = ixgbe_setup_sfp_modules_X550em, 3942b3eb4e18SMark Rustad .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, 3943b3eb4e18SMark Rustad .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, 3944b3eb4e18SMark Rustad .setup_fc = ixgbe_setup_fc_x550em, 3945b3eb4e18SMark Rustad .fc_autoneg = ixgbe_fc_autoneg, 3946b3eb4e18SMark Rustad .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, 3947b3eb4e18SMark Rustad .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, 3948b3eb4e18SMark Rustad }; 3949b3eb4e18SMark Rustad 39506a14ee0cSDon Skidmore #define X550_COMMON_EEP \ 39516a14ee0cSDon Skidmore .read = &ixgbe_read_ee_hostif_X550, \ 39526a14ee0cSDon Skidmore .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 39536a14ee0cSDon Skidmore .write = &ixgbe_write_ee_hostif_X550, \ 39546a14ee0cSDon Skidmore .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 39556a14ee0cSDon Skidmore .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 39566a14ee0cSDon Skidmore .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 39576a14ee0cSDon Skidmore .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 39586a14ee0cSDon Skidmore 395937689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550 = { 39606a14ee0cSDon Skidmore X550_COMMON_EEP 39616a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X550, 39626a14ee0cSDon Skidmore }; 39636a14ee0cSDon Skidmore 396437689010SMark Rustad static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 39656a14ee0cSDon Skidmore X550_COMMON_EEP 39666a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X540, 39676a14ee0cSDon Skidmore }; 39686a14ee0cSDon Skidmore 39696a14ee0cSDon Skidmore #define X550_COMMON_PHY \ 39706a14ee0cSDon Skidmore .identify_sfp = &ixgbe_identify_module_generic, \ 39716a14ee0cSDon Skidmore .reset = NULL, \ 39726a14ee0cSDon Skidmore .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 39736a14ee0cSDon Skidmore .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 39746a14ee0cSDon Skidmore .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 39756a14ee0cSDon Skidmore .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 39766a14ee0cSDon Skidmore .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 39776a14ee0cSDon Skidmore .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 3978bef23de1SDon Skidmore .setup_link = &ixgbe_setup_phy_link_generic, \ 3979b3eb4e18SMark Rustad .set_phy_power = NULL, 39806a14ee0cSDon Skidmore 398137689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550 = { 39826a14ee0cSDon Skidmore X550_COMMON_PHY 3983b3eb4e18SMark Rustad .check_overtemp = &ixgbe_tn_check_overtemp, 39846a14ee0cSDon Skidmore .init = NULL, 39856a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_generic, 3986d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_generic, 3987d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_generic, 39886a14ee0cSDon Skidmore }; 39896a14ee0cSDon Skidmore 399037689010SMark Rustad static const struct ixgbe_phy_operations phy_ops_X550EM_x = { 39916a14ee0cSDon Skidmore X550_COMMON_PHY 3992b3eb4e18SMark Rustad .check_overtemp = &ixgbe_tn_check_overtemp, 39936a14ee0cSDon Skidmore .init = &ixgbe_init_phy_ops_X550em, 39946a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_x550em, 3995d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_generic, 3996d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_generic, 39976a14ee0cSDon Skidmore }; 39986a14ee0cSDon Skidmore 39998dc963e1SPaul Greenwalt static const struct ixgbe_phy_operations phy_ops_x550em_x_fw = { 40008dc963e1SPaul Greenwalt X550_COMMON_PHY 40018dc963e1SPaul Greenwalt .check_overtemp = NULL, 40028dc963e1SPaul Greenwalt .init = ixgbe_init_phy_ops_X550em, 40038dc963e1SPaul Greenwalt .identify = ixgbe_identify_phy_x550em, 40048dc963e1SPaul Greenwalt .read_reg = NULL, 40058dc963e1SPaul Greenwalt .write_reg = NULL, 40068dc963e1SPaul Greenwalt .read_reg_mdi = NULL, 40078dc963e1SPaul Greenwalt .write_reg_mdi = NULL, 40088dc963e1SPaul Greenwalt }; 40098dc963e1SPaul Greenwalt 4010d31afc8fSMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a = { 4011d31afc8fSMark Rustad X550_COMMON_PHY 4012b3eb4e18SMark Rustad .check_overtemp = &ixgbe_tn_check_overtemp, 4013d31afc8fSMark Rustad .init = &ixgbe_init_phy_ops_X550em, 4014d31afc8fSMark Rustad .identify = &ixgbe_identify_phy_x550em, 4015d31afc8fSMark Rustad .read_reg = &ixgbe_read_phy_reg_x550a, 4016d31afc8fSMark Rustad .write_reg = &ixgbe_write_phy_reg_x550a, 40178fe293aaSMark Rustad .read_reg_mdi = &ixgbe_read_phy_reg_mdi, 40188fe293aaSMark Rustad .write_reg_mdi = &ixgbe_write_phy_reg_mdi, 4019d31afc8fSMark Rustad }; 4020d31afc8fSMark Rustad 4021b3eb4e18SMark Rustad static const struct ixgbe_phy_operations phy_ops_x550em_a_fw = { 4022b3eb4e18SMark Rustad X550_COMMON_PHY 4023b3eb4e18SMark Rustad .check_overtemp = ixgbe_check_overtemp_fw, 4024b3eb4e18SMark Rustad .init = ixgbe_init_phy_ops_X550em, 4025b3eb4e18SMark Rustad .identify = ixgbe_identify_phy_fw, 4026b3eb4e18SMark Rustad .read_reg = NULL, 4027b3eb4e18SMark Rustad .write_reg = NULL, 4028b3eb4e18SMark Rustad .read_reg_mdi = NULL, 4029b3eb4e18SMark Rustad .write_reg_mdi = NULL, 4030b3eb4e18SMark Rustad }; 4031b3eb4e18SMark Rustad 4032b71f6c40SEmil Tantilov static const struct ixgbe_link_operations link_ops_x550em_x = { 4033b71f6c40SEmil Tantilov .read_link = &ixgbe_read_i2c_combined_generic, 4034b71f6c40SEmil Tantilov .read_link_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, 4035b71f6c40SEmil Tantilov .write_link = &ixgbe_write_i2c_combined_generic, 4036b71f6c40SEmil Tantilov .write_link_unlocked = &ixgbe_write_i2c_combined_generic_unlocked, 4037b71f6c40SEmil Tantilov }; 4038b71f6c40SEmil Tantilov 40399a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 40409a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550) 40419a900ecaSDon Skidmore }; 40429a900ecaSDon Skidmore 40439a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 40449a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550EM_x) 40459a900ecaSDon Skidmore }; 40469a900ecaSDon Skidmore 404749425dfcSMark Rustad static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = { 404849425dfcSMark Rustad IXGBE_MVALS_INIT(X550EM_a) 404949425dfcSMark Rustad }; 405049425dfcSMark Rustad 405137689010SMark Rustad const struct ixgbe_info ixgbe_X550_info = { 40526a14ee0cSDon Skidmore .mac = ixgbe_mac_X550, 40536a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 40546a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550, 40556a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550, 40566a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550, 40576a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 40589a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550, 40596a14ee0cSDon Skidmore }; 40606a14ee0cSDon Skidmore 406137689010SMark Rustad const struct ixgbe_info ixgbe_X550EM_x_info = { 40626a14ee0cSDon Skidmore .mac = ixgbe_mac_X550EM_x, 4063b5529ef5SDon Skidmore .get_invariants = &ixgbe_get_invariants_X550_x, 40646a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550EM_x, 40656a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550EM_x, 40666a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550EM_x, 40676a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 40689a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550EM_x, 4069b71f6c40SEmil Tantilov .link_ops = &link_ops_x550em_x, 40706a14ee0cSDon Skidmore }; 407149425dfcSMark Rustad 40728dc963e1SPaul Greenwalt const struct ixgbe_info ixgbe_x550em_x_fw_info = { 40738dc963e1SPaul Greenwalt .mac = ixgbe_mac_X550EM_x, 40748dc963e1SPaul Greenwalt .get_invariants = ixgbe_get_invariants_X550_x_fw, 40755e999fb4SPaul Greenwalt .mac_ops = &mac_ops_X550EM_x_fw, 40768dc963e1SPaul Greenwalt .eeprom_ops = &eeprom_ops_X550EM_x, 40778dc963e1SPaul Greenwalt .phy_ops = &phy_ops_x550em_x_fw, 40788dc963e1SPaul Greenwalt .mbx_ops = &mbx_ops_generic, 40798dc963e1SPaul Greenwalt .mvals = ixgbe_mvals_X550EM_x, 40808dc963e1SPaul Greenwalt }; 40818dc963e1SPaul Greenwalt 408249425dfcSMark Rustad const struct ixgbe_info ixgbe_x550em_a_info = { 408349425dfcSMark Rustad .mac = ixgbe_mac_x550em_a, 4084b71f6c40SEmil Tantilov .get_invariants = &ixgbe_get_invariants_X550_a, 408549425dfcSMark Rustad .mac_ops = &mac_ops_x550em_a, 408649425dfcSMark Rustad .eeprom_ops = &eeprom_ops_X550EM_x, 4087d31afc8fSMark Rustad .phy_ops = &phy_ops_x550em_a, 408849425dfcSMark Rustad .mbx_ops = &mbx_ops_generic, 408949425dfcSMark Rustad .mvals = ixgbe_mvals_x550em_a, 409049425dfcSMark Rustad }; 4091b3eb4e18SMark Rustad 4092b3eb4e18SMark Rustad const struct ixgbe_info ixgbe_x550em_a_fw_info = { 4093b3eb4e18SMark Rustad .mac = ixgbe_mac_x550em_a, 4094b3eb4e18SMark Rustad .get_invariants = ixgbe_get_invariants_X550_a_fw, 4095b3eb4e18SMark Rustad .mac_ops = &mac_ops_x550em_a_fw, 4096b3eb4e18SMark Rustad .eeprom_ops = &eeprom_ops_X550EM_x, 4097b3eb4e18SMark Rustad .phy_ops = &phy_ops_x550em_a_fw, 4098b3eb4e18SMark Rustad .mbx_ops = &mbx_ops_generic, 4099b3eb4e18SMark Rustad .mvals = ixgbe_mvals_x550em_a, 4100b3eb4e18SMark Rustad }; 4101