1*54fbbda3Sjsg /* $OpenBSD: ixgbe_x550.c,v 1.10 2024/09/01 03:09:00 jsg Exp $ */ 2ac13930bSmikeb 3ac13930bSmikeb /****************************************************************************** 4ac13930bSmikeb 5d7a8f955Sjmatthew Copyright (c) 2001-2017, Intel Corporation 6ac13930bSmikeb All rights reserved. 7ac13930bSmikeb 8ac13930bSmikeb Redistribution and use in source and binary forms, with or without 9ac13930bSmikeb modification, are permitted provided that the following conditions are met: 10ac13930bSmikeb 11ac13930bSmikeb 1. Redistributions of source code must retain the above copyright notice, 12ac13930bSmikeb this list of conditions and the following disclaimer. 13ac13930bSmikeb 14ac13930bSmikeb 2. Redistributions in binary form must reproduce the above copyright 15ac13930bSmikeb notice, this list of conditions and the following disclaimer in the 16ac13930bSmikeb documentation and/or other materials provided with the distribution. 17ac13930bSmikeb 18ac13930bSmikeb 3. Neither the name of the Intel Corporation nor the names of its 19ac13930bSmikeb contributors may be used to endorse or promote products derived from 20ac13930bSmikeb this software without specific prior written permission. 21ac13930bSmikeb 22ac13930bSmikeb THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23ac13930bSmikeb AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24ac13930bSmikeb IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25ac13930bSmikeb ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26ac13930bSmikeb LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27ac13930bSmikeb CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28ac13930bSmikeb SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29ac13930bSmikeb INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30ac13930bSmikeb CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31ac13930bSmikeb ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32ac13930bSmikeb POSSIBILITY OF SUCH DAMAGE. 33ac13930bSmikeb 34ac13930bSmikeb ******************************************************************************/ 35d7a8f955Sjmatthew /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x550.c 333870 2018-05-19 05:57:26Z mmacy $*/ 36ac13930bSmikeb 37ac13930bSmikeb #include <dev/pci/ixgbe.h> 38ac13930bSmikeb #include <dev/pci/ixgbe_type.h> 39ac13930bSmikeb 40ac13930bSmikeb extern int32_t ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw); 41ac13930bSmikeb extern int32_t ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, uint32_t mask); 42ac13930bSmikeb extern void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, uint32_t mask); 43ac13930bSmikeb 44d7a8f955Sjmatthew int32_t ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *, uint32_t mask); 45d7a8f955Sjmatthew void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *, uint32_t mask); 46d7a8f955Sjmatthew int32_t ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw); 47d7a8f955Sjmatthew 48d7a8f955Sjmatthew int32_t ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, 49d7a8f955Sjmatthew ixgbe_link_speed speed, 50d7a8f955Sjmatthew bool autoneg_wait_to_complete); 51d7a8f955Sjmatthew 52d7a8f955Sjmatthew int32_t ixgbe_dmac_config_X550(struct ixgbe_hw *hw); 53d7a8f955Sjmatthew int32_t ixgbe_dmac_config_tcs_X550(struct ixgbe_hw *hw); 54d7a8f955Sjmatthew int32_t ixgbe_dmac_update_tcs_X550(struct ixgbe_hw *hw); 55d7a8f955Sjmatthew 56ac13930bSmikeb int32_t ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw); 57ac13930bSmikeb int32_t ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw); 58ac13930bSmikeb int32_t ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw); 59ac13930bSmikeb int32_t ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw); 60ac13930bSmikeb int32_t ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, uint16_t *buffer, 61ac13930bSmikeb uint32_t buffer_size); 62ac13930bSmikeb int32_t ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 63ac13930bSmikeb uint16_t *checksum_val); 64ac13930bSmikeb int32_t ixgbe_update_flash_X550(struct ixgbe_hw *hw); 65ac13930bSmikeb int32_t ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, uint16_t offset, 66ac13930bSmikeb uint16_t data); 67ac13930bSmikeb int32_t ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 68ac13930bSmikeb uint16_t offset, uint16_t words, 69ac13930bSmikeb uint16_t *data); 70ac13930bSmikeb int32_t ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, uint16_t offset, 71ac13930bSmikeb uint16_t *data); 72ac13930bSmikeb int32_t ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, uint16_t offset, 73ac13930bSmikeb uint16_t data); 74d7a8f955Sjmatthew void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable, 75d7a8f955Sjmatthew unsigned int pool); 76ac13930bSmikeb int32_t ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, uint32_t reg_addr, 77ac13930bSmikeb uint32_t device_type, uint32_t data); 78ac13930bSmikeb int32_t ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, uint32_t reg_addr, 79ac13930bSmikeb uint32_t device_type, uint32_t *data); 80d7a8f955Sjmatthew int32_t ixgbe_get_phy_token(struct ixgbe_hw *); 81d7a8f955Sjmatthew int32_t ixgbe_put_phy_token(struct ixgbe_hw *); 82d7a8f955Sjmatthew int32_t ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, uint32_t reg_addr, 83d7a8f955Sjmatthew uint32_t device_type, uint32_t data); 84d7a8f955Sjmatthew int32_t ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, uint32_t reg_addr, 85d7a8f955Sjmatthew uint32_t device_type, uint32_t *data); 86ac13930bSmikeb enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw); 87ac13930bSmikeb int32_t ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw); 88ac13930bSmikeb int32_t ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 89ac13930bSmikeb ixgbe_link_speed *speed, 90ac13930bSmikeb bool *autoneg); 91ac13930bSmikeb void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw); 92ac13930bSmikeb int32_t ixgbe_reset_hw_X550em(struct ixgbe_hw *hw); 93ac13930bSmikeb int32_t ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw); 94ac13930bSmikeb int32_t ixgbe_setup_kr_x550em(struct ixgbe_hw *hw); 95ac13930bSmikeb int32_t ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw); 96ac13930bSmikeb int32_t ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw); 97ac13930bSmikeb int32_t ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw); 98d7a8f955Sjmatthew uint64_t ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw); 99ac13930bSmikeb void ixgbe_disable_rx_x550(struct ixgbe_hw *hw); 100ac13930bSmikeb int32_t ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed); 101d7a8f955Sjmatthew int32_t ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw); 102ac13930bSmikeb int32_t ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, uint32_t mask); 103ac13930bSmikeb void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, uint32_t mask); 104ac13930bSmikeb int32_t ixgbe_setup_fc_X550em(struct ixgbe_hw *hw); 105ac13930bSmikeb int32_t ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, 106ac13930bSmikeb ixgbe_link_speed speed, 107ac13930bSmikeb bool autoneg_wait_to_complete); 108d7a8f955Sjmatthew int32_t ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, uint32_t reg_addr, 109d7a8f955Sjmatthew uint32_t device_type, uint16_t *phy_data); 110d7a8f955Sjmatthew int32_t ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, uint32_t reg_addr, 111d7a8f955Sjmatthew uint32_t device_type, uint16_t phy_data); 112d7a8f955Sjmatthew int32_t ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw); 113d7a8f955Sjmatthew void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw); 114d7a8f955Sjmatthew void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw); 115d7a8f955Sjmatthew void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw); 116ac13930bSmikeb int32_t ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw); 117ac13930bSmikeb int32_t ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 118ac13930bSmikeb ixgbe_link_speed speed, 119ac13930bSmikeb bool autoneg_wait_to_complete); 120ac13930bSmikeb int32_t ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed, 121ac13930bSmikeb bool *link_up, bool link_up_wait_to_complete); 122ac13930bSmikeb int32_t ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw); 123ac13930bSmikeb int32_t ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw); 124ac13930bSmikeb int32_t ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, uint32_t led_idx); 125ac13930bSmikeb int32_t ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, uint32_t led_idx); 126ac13930bSmikeb 127ac13930bSmikeb int32_t ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed); 128ac13930bSmikeb 129d7a8f955Sjmatthew 130ac13930bSmikeb /** 131ac13930bSmikeb * ixgbe_init_ops_X550 - Inits func ptrs and MAC type 132ac13930bSmikeb * @hw: pointer to hardware structure 133ac13930bSmikeb * 134ac13930bSmikeb * Initialize the function pointers and assign the MAC type for X550. 135ac13930bSmikeb * Does not touch the hardware. 136ac13930bSmikeb **/ 137ac13930bSmikeb int32_t ixgbe_init_ops_X550(struct ixgbe_hw *hw) 138ac13930bSmikeb { 139ac13930bSmikeb struct ixgbe_mac_info *mac = &hw->mac; 140ac13930bSmikeb struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 141ac13930bSmikeb int32_t ret_val; 142ac13930bSmikeb 143ac13930bSmikeb DEBUGFUNC("ixgbe_init_ops_X550"); 144ac13930bSmikeb 145ac13930bSmikeb ret_val = ixgbe_init_ops_X540(hw); 146d7a8f955Sjmatthew mac->ops.dmac_config = ixgbe_dmac_config_X550; 147d7a8f955Sjmatthew mac->ops.dmac_config_tcs = ixgbe_dmac_config_tcs_X550; 148d7a8f955Sjmatthew mac->ops.dmac_update_tcs = ixgbe_dmac_update_tcs_X550; 149d7a8f955Sjmatthew mac->ops.setup_eee = NULL; 150d7a8f955Sjmatthew mac->ops.set_source_address_pruning = 151d7a8f955Sjmatthew ixgbe_set_source_address_pruning_X550; 152ac13930bSmikeb 153ac13930bSmikeb eeprom->ops.init_params = ixgbe_init_eeprom_params_X550; 154ac13930bSmikeb eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550; 155ac13930bSmikeb eeprom->ops.read = ixgbe_read_ee_hostif_X550; 156ac13930bSmikeb eeprom->ops.write = ixgbe_write_ee_hostif_X550; 157ac13930bSmikeb eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550; 158ac13930bSmikeb eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550; 159ac13930bSmikeb 160ac13930bSmikeb mac->ops.disable_rx = ixgbe_disable_rx_x550; 161d7a8f955Sjmatthew switch (hw->device_id) { 162d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_1G_T: 163d7a8f955Sjmatthew hw->mac.ops.led_on = NULL; 164d7a8f955Sjmatthew hw->mac.ops.led_off = NULL; 165d7a8f955Sjmatthew break; 166d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_10G_T: 167d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_10G_T: 168ac13930bSmikeb hw->mac.ops.led_on = ixgbe_led_on_t_X550em; 169ac13930bSmikeb hw->mac.ops.led_off = ixgbe_led_off_t_X550em; 170d7a8f955Sjmatthew break; 171d7a8f955Sjmatthew default: 172d7a8f955Sjmatthew break; 173ac13930bSmikeb } 174ac13930bSmikeb return ret_val; 175ac13930bSmikeb } 176ac13930bSmikeb 177ac13930bSmikeb /** 178ac13930bSmikeb * ixgbe_read_cs4227 - Read CS4227 register 179ac13930bSmikeb * @hw: pointer to hardware structure 180ac13930bSmikeb * @reg: register number to write 181ac13930bSmikeb * @value: pointer to receive value read 182ac13930bSmikeb * 183ac13930bSmikeb * Returns status code 184ac13930bSmikeb **/ 185ac13930bSmikeb int32_t ixgbe_read_cs4227(struct ixgbe_hw *hw, uint16_t reg, uint16_t *value) 186ac13930bSmikeb { 187d7a8f955Sjmatthew return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value); 188ac13930bSmikeb } 189ac13930bSmikeb 190ac13930bSmikeb /** 191ac13930bSmikeb * ixgbe_write_cs4227 - Write CS4227 register 192ac13930bSmikeb * @hw: pointer to hardware structure 193ac13930bSmikeb * @reg: register number to write 194ac13930bSmikeb * @value: value to write to register 195ac13930bSmikeb * 196ac13930bSmikeb * Returns status code 197ac13930bSmikeb **/ 198ac13930bSmikeb int32_t ixgbe_write_cs4227(struct ixgbe_hw *hw, uint16_t reg, uint16_t value) 199ac13930bSmikeb { 200d7a8f955Sjmatthew return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value); 201ac13930bSmikeb } 202ac13930bSmikeb 203ac13930bSmikeb /** 204ac13930bSmikeb * ixgbe_read_pe - Read register from port expander 205ac13930bSmikeb * @hw: pointer to hardware structure 206ac13930bSmikeb * @reg: register number to read 207ac13930bSmikeb * @value: pointer to receive read value 208ac13930bSmikeb * 209ac13930bSmikeb * Returns status code 210ac13930bSmikeb **/ 211ac13930bSmikeb int32_t ixgbe_read_pe(struct ixgbe_hw *hw, uint8_t reg, uint8_t *value) 212ac13930bSmikeb { 213d7a8f955Sjmatthew int32_t status = IXGBE_NOT_IMPLEMENTED; 214ac13930bSmikeb 215d7a8f955Sjmatthew if (hw->phy.ops.read_i2c_byte_unlocked) 216d7a8f955Sjmatthew status = hw->phy.ops.read_i2c_byte_unlocked(hw, reg, IXGBE_PE, 217d7a8f955Sjmatthew value); 218ac13930bSmikeb if (status != IXGBE_SUCCESS) 219d7a8f955Sjmatthew ERROR_REPORT2(IXGBE_ERROR_CAUTION, 220d7a8f955Sjmatthew "port expander access failed with %d\n", status); 221ac13930bSmikeb return status; 222ac13930bSmikeb } 223ac13930bSmikeb 224ac13930bSmikeb /** 225ac13930bSmikeb * ixgbe_write_pe - Write register to port expander 226ac13930bSmikeb * @hw: pointer to hardware structure 227ac13930bSmikeb * @reg: register number to write 228ac13930bSmikeb * @value: value to write 229ac13930bSmikeb * 230ac13930bSmikeb * Returns status code 231ac13930bSmikeb **/ 232ac13930bSmikeb int32_t ixgbe_write_pe(struct ixgbe_hw *hw, uint8_t reg, uint8_t value) 233ac13930bSmikeb { 234d7a8f955Sjmatthew int32_t status = IXGBE_NOT_IMPLEMENTED; 235ac13930bSmikeb 236d7a8f955Sjmatthew if (hw->phy.ops.write_i2c_byte_unlocked) 237d7a8f955Sjmatthew status = hw->phy.ops.write_i2c_byte_unlocked(hw, reg, IXGBE_PE, 238d7a8f955Sjmatthew value); 239ac13930bSmikeb if (status != IXGBE_SUCCESS) 240d7a8f955Sjmatthew ERROR_REPORT2(IXGBE_ERROR_CAUTION, 241d7a8f955Sjmatthew "port expander access failed with %d\n", status); 242ac13930bSmikeb return status; 243ac13930bSmikeb } 244ac13930bSmikeb 245ac13930bSmikeb /** 246ac13930bSmikeb * ixgbe_reset_cs4227 - Reset CS4227 using port expander 247ac13930bSmikeb * @hw: pointer to hardware structure 248ac13930bSmikeb * 249ac13930bSmikeb * This function assumes that the caller has acquired the proper semaphore. 250ac13930bSmikeb * Returns error code 251ac13930bSmikeb **/ 252ac13930bSmikeb int32_t ixgbe_reset_cs4227(struct ixgbe_hw *hw) 253ac13930bSmikeb { 254ac13930bSmikeb int32_t status; 255ac13930bSmikeb uint32_t retry; 256ac13930bSmikeb uint16_t value; 257ac13930bSmikeb uint8_t reg; 258ac13930bSmikeb 259ac13930bSmikeb /* Trigger hard reset. */ 260ac13930bSmikeb status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 261ac13930bSmikeb if (status != IXGBE_SUCCESS) 262ac13930bSmikeb return status; 263ac13930bSmikeb reg |= IXGBE_PE_BIT1; 264ac13930bSmikeb status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 265ac13930bSmikeb if (status != IXGBE_SUCCESS) 266ac13930bSmikeb return status; 267ac13930bSmikeb 268ac13930bSmikeb status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); 269ac13930bSmikeb if (status != IXGBE_SUCCESS) 270ac13930bSmikeb return status; 271ac13930bSmikeb reg &= ~IXGBE_PE_BIT1; 272ac13930bSmikeb status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); 273ac13930bSmikeb if (status != IXGBE_SUCCESS) 274ac13930bSmikeb return status; 275ac13930bSmikeb 276ac13930bSmikeb status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 277ac13930bSmikeb if (status != IXGBE_SUCCESS) 278ac13930bSmikeb return status; 279ac13930bSmikeb reg &= ~IXGBE_PE_BIT1; 280ac13930bSmikeb status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 281ac13930bSmikeb if (status != IXGBE_SUCCESS) 282ac13930bSmikeb return status; 283ac13930bSmikeb 284ac13930bSmikeb usec_delay(IXGBE_CS4227_RESET_HOLD); 285ac13930bSmikeb 286ac13930bSmikeb status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); 287ac13930bSmikeb if (status != IXGBE_SUCCESS) 288ac13930bSmikeb return status; 289ac13930bSmikeb reg |= IXGBE_PE_BIT1; 290ac13930bSmikeb status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); 291ac13930bSmikeb if (status != IXGBE_SUCCESS) 292ac13930bSmikeb return status; 293ac13930bSmikeb 294ac13930bSmikeb /* Wait for the reset to complete. */ 295ac13930bSmikeb msec_delay(IXGBE_CS4227_RESET_DELAY); 296ac13930bSmikeb for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 297ac13930bSmikeb status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, 298ac13930bSmikeb &value); 299ac13930bSmikeb if (status == IXGBE_SUCCESS && 300ac13930bSmikeb value == IXGBE_CS4227_EEPROM_LOAD_OK) 301ac13930bSmikeb break; 302ac13930bSmikeb msec_delay(IXGBE_CS4227_CHECK_DELAY); 303ac13930bSmikeb } 304ac13930bSmikeb if (retry == IXGBE_CS4227_RETRIES) { 305d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, 306d7a8f955Sjmatthew "CS4227 reset did not complete."); 307ac13930bSmikeb return IXGBE_ERR_PHY; 308ac13930bSmikeb } 309ac13930bSmikeb 310ac13930bSmikeb status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value); 311ac13930bSmikeb if (status != IXGBE_SUCCESS || 312ac13930bSmikeb !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { 313d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, 314d7a8f955Sjmatthew "CS4227 EEPROM did not load successfully."); 315ac13930bSmikeb return IXGBE_ERR_PHY; 316ac13930bSmikeb } 317ac13930bSmikeb 318ac13930bSmikeb return IXGBE_SUCCESS; 319ac13930bSmikeb } 320ac13930bSmikeb 321ac13930bSmikeb /** 322ac13930bSmikeb * ixgbe_check_cs4227 - Check CS4227 and reset as needed 323ac13930bSmikeb * @hw: pointer to hardware structure 324ac13930bSmikeb **/ 325ac13930bSmikeb void ixgbe_check_cs4227(struct ixgbe_hw *hw) 326ac13930bSmikeb { 327ac13930bSmikeb int32_t status = IXGBE_SUCCESS; 328ac13930bSmikeb uint32_t swfw_mask = hw->phy.phy_semaphore_mask; 329ac13930bSmikeb uint16_t value = 0; 330ac13930bSmikeb uint8_t retry; 331ac13930bSmikeb 332ac13930bSmikeb for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { 333ac13930bSmikeb status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 334ac13930bSmikeb if (status != IXGBE_SUCCESS) { 335d7a8f955Sjmatthew ERROR_REPORT2(IXGBE_ERROR_CAUTION, 336d7a8f955Sjmatthew "semaphore failed with %d", status); 337ac13930bSmikeb msec_delay(IXGBE_CS4227_CHECK_DELAY); 338ac13930bSmikeb continue; 339ac13930bSmikeb } 340ac13930bSmikeb 341ac13930bSmikeb /* Get status of reset flow. */ 342ac13930bSmikeb status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); 343ac13930bSmikeb 344ac13930bSmikeb if (status == IXGBE_SUCCESS && 345ac13930bSmikeb value == IXGBE_CS4227_RESET_COMPLETE) 346ac13930bSmikeb goto out; 347ac13930bSmikeb 348ac13930bSmikeb if (status != IXGBE_SUCCESS || 349ac13930bSmikeb value != IXGBE_CS4227_RESET_PENDING) 350ac13930bSmikeb break; 351ac13930bSmikeb 352ac13930bSmikeb /* Reset is pending. Wait and check again. */ 353ac13930bSmikeb hw->mac.ops.release_swfw_sync(hw, swfw_mask); 354ac13930bSmikeb msec_delay(IXGBE_CS4227_CHECK_DELAY); 355ac13930bSmikeb } 356ac13930bSmikeb 357ac13930bSmikeb /* If still pending, assume other instance failed. */ 358ac13930bSmikeb if (retry == IXGBE_CS4227_RETRIES) { 359ac13930bSmikeb status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 360ac13930bSmikeb if (status != IXGBE_SUCCESS) { 361d7a8f955Sjmatthew ERROR_REPORT2(IXGBE_ERROR_CAUTION, 362d7a8f955Sjmatthew "semaphore failed with %d", status); 363ac13930bSmikeb return; 364ac13930bSmikeb } 365ac13930bSmikeb } 366ac13930bSmikeb 367ac13930bSmikeb /* Reset the CS4227. */ 368ac13930bSmikeb status = ixgbe_reset_cs4227(hw); 369ac13930bSmikeb if (status != IXGBE_SUCCESS) { 370d7a8f955Sjmatthew ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 371d7a8f955Sjmatthew "CS4227 reset failed: %d", status); 372ac13930bSmikeb goto out; 373ac13930bSmikeb } 374ac13930bSmikeb 375ac13930bSmikeb /* Reset takes so long, temporarily release semaphore in case the 376ac13930bSmikeb * other driver instance is waiting for the reset indication. 377ac13930bSmikeb */ 378ac13930bSmikeb ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 379ac13930bSmikeb IXGBE_CS4227_RESET_PENDING); 380ac13930bSmikeb hw->mac.ops.release_swfw_sync(hw, swfw_mask); 381ac13930bSmikeb msec_delay(10); 382ac13930bSmikeb status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 383ac13930bSmikeb if (status != IXGBE_SUCCESS) { 384d7a8f955Sjmatthew ERROR_REPORT2(IXGBE_ERROR_CAUTION, 385d7a8f955Sjmatthew "semaphore failed with %d", status); 386ac13930bSmikeb return; 387ac13930bSmikeb } 388ac13930bSmikeb 389ac13930bSmikeb /* Record completion for next time. */ 390ac13930bSmikeb status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, 391ac13930bSmikeb IXGBE_CS4227_RESET_COMPLETE); 392ac13930bSmikeb 393ac13930bSmikeb out: 394ac13930bSmikeb hw->mac.ops.release_swfw_sync(hw, swfw_mask); 395ac13930bSmikeb msec_delay(hw->eeprom.semaphore_delay); 396ac13930bSmikeb } 397ac13930bSmikeb 398ac13930bSmikeb /** 399ac13930bSmikeb * ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control 400ac13930bSmikeb * @hw: pointer to hardware structure 401ac13930bSmikeb **/ 402ac13930bSmikeb void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) 403ac13930bSmikeb { 404ac13930bSmikeb uint32_t esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 405ac13930bSmikeb 406ac13930bSmikeb if (hw->bus.lan_id) { 407ac13930bSmikeb esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 408ac13930bSmikeb esdp |= IXGBE_ESDP_SDP1_DIR; 409ac13930bSmikeb } 410ac13930bSmikeb esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 411ac13930bSmikeb IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 412ac13930bSmikeb IXGBE_WRITE_FLUSH(hw); 413ac13930bSmikeb } 414ac13930bSmikeb 415ac13930bSmikeb /** 416ac13930bSmikeb * ixgbe_identify_phy_x550em - Get PHY type based on device id 417ac13930bSmikeb * @hw: pointer to hardware structure 418ac13930bSmikeb * 419ac13930bSmikeb * Returns error code 420ac13930bSmikeb */ 421ac13930bSmikeb int32_t ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) 422ac13930bSmikeb { 423d7a8f955Sjmatthew hw->mac.ops.set_lan_id(hw); 424d7a8f955Sjmatthew 425d7a8f955Sjmatthew ixgbe_read_mng_if_sel_x550em(hw); 4261544f1b6Smikeb 427ac13930bSmikeb switch (hw->device_id) { 428d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_SFP: 429d7a8f955Sjmatthew return ixgbe_identify_module_generic(hw); 430ac13930bSmikeb case IXGBE_DEV_ID_X550EM_X_SFP: 431ac13930bSmikeb /* set up for CS4227 usage */ 432ac13930bSmikeb ixgbe_setup_mux_ctl(hw); 433ac13930bSmikeb ixgbe_check_cs4227(hw); 434d7a8f955Sjmatthew /* Fallthrough */ 435ac13930bSmikeb 436d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_SFP_N: 437d7a8f955Sjmatthew return ixgbe_identify_module_generic(hw); 438ac13930bSmikeb break; 439ac13930bSmikeb case IXGBE_DEV_ID_X550EM_X_KX4: 440ac13930bSmikeb hw->phy.type = ixgbe_phy_x550em_kx4; 441ac13930bSmikeb break; 442d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_XFI: 443d7a8f955Sjmatthew hw->phy.type = ixgbe_phy_x550em_xfi; 444d7a8f955Sjmatthew break; 445ac13930bSmikeb case IXGBE_DEV_ID_X550EM_X_KR: 446d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_KR: 447d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_KR_L: 448ac13930bSmikeb hw->phy.type = ixgbe_phy_x550em_kr; 449ac13930bSmikeb break; 450d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_10G_T: 451ac13930bSmikeb case IXGBE_DEV_ID_X550EM_X_10G_T: 452ac13930bSmikeb return ixgbe_identify_phy_generic(hw); 453d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_1G_T: 454d7a8f955Sjmatthew hw->phy.type = ixgbe_phy_ext_1g_t; 455d7a8f955Sjmatthew break; 456d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T: 457d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T_L: 458d7a8f955Sjmatthew hw->phy.type = ixgbe_phy_fw; 459d7a8f955Sjmatthew if (hw->bus.lan_id) 460d7a8f955Sjmatthew hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; 461d7a8f955Sjmatthew else 462d7a8f955Sjmatthew hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM; 463d7a8f955Sjmatthew break; 464ac13930bSmikeb default: 465ac13930bSmikeb break; 466ac13930bSmikeb } 467ac13930bSmikeb return IXGBE_SUCCESS; 468ac13930bSmikeb } 469ac13930bSmikeb 470d7a8f955Sjmatthew /** 471d7a8f955Sjmatthew * ixgbe_fw_phy_activity - Perform an activity on a PHY 472d7a8f955Sjmatthew * @hw: pointer to hardware structure 473d7a8f955Sjmatthew * @activity: activity to perform 474d7a8f955Sjmatthew * @data: Pointer to 4 32-bit words of data 475d7a8f955Sjmatthew */ 476d7a8f955Sjmatthew int32_t ixgbe_fw_phy_activity(struct ixgbe_hw *hw, uint16_t activity, 477d7a8f955Sjmatthew uint32_t (*data)[FW_PHY_ACT_DATA_COUNT]) 478d7a8f955Sjmatthew { 479d7a8f955Sjmatthew union { 480d7a8f955Sjmatthew struct ixgbe_hic_phy_activity_req cmd; 481d7a8f955Sjmatthew struct ixgbe_hic_phy_activity_resp rsp; 482d7a8f955Sjmatthew } hic; 483d7a8f955Sjmatthew uint16_t retries = FW_PHY_ACT_RETRIES; 484d7a8f955Sjmatthew int32_t rc; 485d7a8f955Sjmatthew uint16_t i; 486d7a8f955Sjmatthew 487d7a8f955Sjmatthew do { 488d7a8f955Sjmatthew memset(&hic, 0, sizeof(hic)); 489d7a8f955Sjmatthew hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD; 490d7a8f955Sjmatthew hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN; 491d7a8f955Sjmatthew hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 492d7a8f955Sjmatthew hic.cmd.port_number = hw->bus.lan_id; 493d7a8f955Sjmatthew hic.cmd.activity_id = htole16(activity); 494d7a8f955Sjmatthew for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i) 495d7a8f955Sjmatthew hic.cmd.data[i] = htobe32((*data)[i]); 496d7a8f955Sjmatthew 497d7a8f955Sjmatthew rc = ixgbe_host_interface_command(hw, (uint32_t *)&hic.cmd, 498d7a8f955Sjmatthew sizeof(hic.cmd), 499d7a8f955Sjmatthew IXGBE_HI_COMMAND_TIMEOUT, 500d7a8f955Sjmatthew TRUE); 501d7a8f955Sjmatthew if (rc != IXGBE_SUCCESS) 502d7a8f955Sjmatthew return rc; 503d7a8f955Sjmatthew if (hic.rsp.hdr.cmd_or_resp.ret_status == 504d7a8f955Sjmatthew FW_CEM_RESP_STATUS_SUCCESS) { 505d7a8f955Sjmatthew for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i) 506d7a8f955Sjmatthew (*data)[i] = betoh32(hic.rsp.data[i]); 507d7a8f955Sjmatthew return IXGBE_SUCCESS; 508d7a8f955Sjmatthew } 509d7a8f955Sjmatthew usec_delay(20); 510d7a8f955Sjmatthew --retries; 511d7a8f955Sjmatthew } while (retries > 0); 512d7a8f955Sjmatthew 513d7a8f955Sjmatthew return IXGBE_ERR_HOST_INTERFACE_COMMAND; 514d7a8f955Sjmatthew } 515d7a8f955Sjmatthew 516d7a8f955Sjmatthew static const struct { 517d7a8f955Sjmatthew uint16_t fw_speed; 518d7a8f955Sjmatthew ixgbe_link_speed phy_speed; 519d7a8f955Sjmatthew } ixgbe_fw_map[] = { 520d7a8f955Sjmatthew { FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL }, 521d7a8f955Sjmatthew { FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL }, 522d7a8f955Sjmatthew { FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL }, 523d7a8f955Sjmatthew { FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL }, 524d7a8f955Sjmatthew { FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL }, 525d7a8f955Sjmatthew { FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL }, 526d7a8f955Sjmatthew }; 527d7a8f955Sjmatthew 528d7a8f955Sjmatthew /** 529d7a8f955Sjmatthew * ixgbe_get_phy_id_fw - Get the phy ID via firmware command 530d7a8f955Sjmatthew * @hw: pointer to hardware structure 531d7a8f955Sjmatthew * 532d7a8f955Sjmatthew * Returns error code 533d7a8f955Sjmatthew */ 534d7a8f955Sjmatthew int32_t ixgbe_get_phy_id_fw(struct ixgbe_hw *hw) 535d7a8f955Sjmatthew { 536d7a8f955Sjmatthew uint32_t info[FW_PHY_ACT_DATA_COUNT] = { 0 }; 537d7a8f955Sjmatthew uint16_t phy_speeds; 538d7a8f955Sjmatthew uint16_t phy_id_lo; 539d7a8f955Sjmatthew int32_t rc; 540d7a8f955Sjmatthew uint16_t i; 541d7a8f955Sjmatthew 542d7a8f955Sjmatthew rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info); 543d7a8f955Sjmatthew if (rc) 544d7a8f955Sjmatthew return rc; 545d7a8f955Sjmatthew 546d7a8f955Sjmatthew hw->phy.speeds_supported = 0; 547d7a8f955Sjmatthew phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK; 548d7a8f955Sjmatthew for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) { 549d7a8f955Sjmatthew if (phy_speeds & ixgbe_fw_map[i].fw_speed) 550d7a8f955Sjmatthew hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed; 551d7a8f955Sjmatthew } 552d7a8f955Sjmatthew if (!hw->phy.autoneg_advertised) 553d7a8f955Sjmatthew hw->phy.autoneg_advertised = hw->phy.speeds_supported; 554d7a8f955Sjmatthew 555d7a8f955Sjmatthew hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK; 556d7a8f955Sjmatthew phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK; 557d7a8f955Sjmatthew hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK; 558d7a8f955Sjmatthew hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK; 559d7a8f955Sjmatthew if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK) 560d7a8f955Sjmatthew return IXGBE_ERR_PHY_ADDR_INVALID; 561d7a8f955Sjmatthew return IXGBE_SUCCESS; 562d7a8f955Sjmatthew } 563d7a8f955Sjmatthew 564d7a8f955Sjmatthew /** 565d7a8f955Sjmatthew * ixgbe_identify_phy_fw - Get PHY type based on firmware command 566d7a8f955Sjmatthew * @hw: pointer to hardware structure 567d7a8f955Sjmatthew * 568d7a8f955Sjmatthew * Returns error code 569d7a8f955Sjmatthew */ 570d7a8f955Sjmatthew int32_t ixgbe_identify_phy_fw(struct ixgbe_hw *hw) 571d7a8f955Sjmatthew { 572d7a8f955Sjmatthew if (hw->bus.lan_id) 573d7a8f955Sjmatthew hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; 574d7a8f955Sjmatthew else 575d7a8f955Sjmatthew hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; 576d7a8f955Sjmatthew 577d7a8f955Sjmatthew hw->phy.type = ixgbe_phy_fw; 578d7a8f955Sjmatthew hw->phy.ops.read_reg = NULL; 579d7a8f955Sjmatthew hw->phy.ops.write_reg = NULL; 580d7a8f955Sjmatthew return ixgbe_get_phy_id_fw(hw); 581d7a8f955Sjmatthew } 582d7a8f955Sjmatthew 583d7a8f955Sjmatthew /** 584d7a8f955Sjmatthew * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY 585d7a8f955Sjmatthew * @hw: pointer to hardware structure 586d7a8f955Sjmatthew * 587d7a8f955Sjmatthew * Returns error code 588d7a8f955Sjmatthew */ 589d7a8f955Sjmatthew int32_t ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw) 590d7a8f955Sjmatthew { 591d7a8f955Sjmatthew uint32_t setup[FW_PHY_ACT_DATA_COUNT] = { 0 }; 592d7a8f955Sjmatthew 593d7a8f955Sjmatthew setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF; 594d7a8f955Sjmatthew return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup); 595d7a8f955Sjmatthew } 596d7a8f955Sjmatthew 597ac13930bSmikeb int32_t ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, uint32_t reg_addr, 598ac13930bSmikeb uint32_t device_type, uint16_t *phy_data) 599ac13930bSmikeb { 600ac13930bSmikeb return IXGBE_NOT_IMPLEMENTED; 601ac13930bSmikeb } 602ac13930bSmikeb 603ac13930bSmikeb int32_t ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, uint32_t reg_addr, 604ac13930bSmikeb uint32_t device_type, uint16_t phy_data) 605ac13930bSmikeb { 606ac13930bSmikeb return IXGBE_NOT_IMPLEMENTED; 607ac13930bSmikeb } 608ac13930bSmikeb 609ac13930bSmikeb /** 610ac13930bSmikeb * ixgbe_init_ops_X550EM - Inits func ptrs and MAC type 611ac13930bSmikeb * @hw: pointer to hardware structure 612ac13930bSmikeb * 613ac13930bSmikeb * Initialize the function pointers and for MAC type X550EM. 614ac13930bSmikeb * Does not touch the hardware. 615ac13930bSmikeb **/ 616ac13930bSmikeb int32_t ixgbe_init_ops_X550EM(struct ixgbe_hw *hw) 617ac13930bSmikeb { 618ac13930bSmikeb struct ixgbe_mac_info *mac = &hw->mac; 619ac13930bSmikeb struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 620ac13930bSmikeb struct ixgbe_phy_info *phy = &hw->phy; 621ac13930bSmikeb int32_t ret_val; 622ac13930bSmikeb 623ac13930bSmikeb DEBUGFUNC("ixgbe_init_ops_X550EM"); 624ac13930bSmikeb 625ac13930bSmikeb /* Similar to X550 so start there. */ 626ac13930bSmikeb ret_val = ixgbe_init_ops_X550(hw); 627ac13930bSmikeb 628ac13930bSmikeb /* Since this function eventually calls 629ac13930bSmikeb * ixgbe_init_ops_540 by design, we are setting 630ac13930bSmikeb * the pointers to NULL explicitly here to overwrite 631ac13930bSmikeb * the values being set in the x540 function. 632ac13930bSmikeb */ 633ac13930bSmikeb 634ac13930bSmikeb /* IPsec not supported in x550EM */ 635ac13930bSmikeb mac->ops.disable_sec_rx_path = NULL; 636ac13930bSmikeb mac->ops.enable_sec_rx_path = NULL; 637ac13930bSmikeb 638ac13930bSmikeb /* AUTOC register is not present in x550EM. */ 639ac13930bSmikeb mac->ops.prot_autoc_read = NULL; 640ac13930bSmikeb mac->ops.prot_autoc_write = NULL; 641ac13930bSmikeb 642ac13930bSmikeb /* X550EM bus type is internal*/ 643ac13930bSmikeb hw->bus.type = ixgbe_bus_type_internal; 644ac13930bSmikeb mac->ops.get_bus_info = ixgbe_get_bus_info_X550em; 645ac13930bSmikeb 646d7a8f955Sjmatthew 647ac13930bSmikeb mac->ops.get_media_type = ixgbe_get_media_type_X550em; 648ac13930bSmikeb mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em; 649ac13930bSmikeb mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em; 650ac13930bSmikeb mac->ops.reset_hw = ixgbe_reset_hw_X550em; 651ac13930bSmikeb mac->ops.get_supported_physical_layer = 652ac13930bSmikeb ixgbe_get_supported_physical_layer_X550em; 653ac13930bSmikeb 654ac13930bSmikeb if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) 655ac13930bSmikeb mac->ops.setup_fc = ixgbe_setup_fc_generic; 656ac13930bSmikeb else 657ac13930bSmikeb mac->ops.setup_fc = ixgbe_setup_fc_X550em; 658ac13930bSmikeb 659ac13930bSmikeb /* PHY */ 660ac13930bSmikeb phy->ops.init = ixgbe_init_phy_ops_X550em; 661d7a8f955Sjmatthew switch (hw->device_id) { 662d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T: 663d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T_L: 664d7a8f955Sjmatthew mac->ops.setup_fc = NULL; 665d7a8f955Sjmatthew phy->ops.identify = ixgbe_identify_phy_fw; 666d7a8f955Sjmatthew phy->ops.set_phy_power = NULL; 667d7a8f955Sjmatthew phy->ops.get_firmware_version = NULL; 668d7a8f955Sjmatthew break; 669d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_1G_T: 670d7a8f955Sjmatthew mac->ops.setup_fc = NULL; 671ac13930bSmikeb phy->ops.identify = ixgbe_identify_phy_x550em; 672d7a8f955Sjmatthew phy->ops.set_phy_power = NULL; 673d7a8f955Sjmatthew break; 674d7a8f955Sjmatthew default: 675d7a8f955Sjmatthew phy->ops.identify = ixgbe_identify_phy_x550em; 676d7a8f955Sjmatthew } 677d7a8f955Sjmatthew 678ac13930bSmikeb if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 679ac13930bSmikeb phy->ops.set_phy_power = NULL; 680ac13930bSmikeb 681ac13930bSmikeb 682ac13930bSmikeb /* EEPROM */ 683ac13930bSmikeb eeprom->ops.init_params = ixgbe_init_eeprom_params_X540; 684ac13930bSmikeb eeprom->ops.read = ixgbe_read_ee_hostif_X550; 685ac13930bSmikeb eeprom->ops.write = ixgbe_write_ee_hostif_X550; 686ac13930bSmikeb eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550; 687ac13930bSmikeb eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550; 688ac13930bSmikeb eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550; 689ac13930bSmikeb 690ac13930bSmikeb return ret_val; 691ac13930bSmikeb } 692ac13930bSmikeb 693ac13930bSmikeb /** 694d7a8f955Sjmatthew * ixgbe_setup_fw_link - Setup firmware-controlled PHYs 695d7a8f955Sjmatthew * @hw: pointer to hardware structure 696d7a8f955Sjmatthew */ 697d7a8f955Sjmatthew int32_t ixgbe_setup_fw_link(struct ixgbe_hw *hw) 698d7a8f955Sjmatthew { 699d7a8f955Sjmatthew uint32_t setup[FW_PHY_ACT_DATA_COUNT] = { 0 }; 700d7a8f955Sjmatthew int32_t rc; 701d7a8f955Sjmatthew uint16_t i; 702d7a8f955Sjmatthew 703d7a8f955Sjmatthew if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) 704d7a8f955Sjmatthew return 0; 705d7a8f955Sjmatthew 706d7a8f955Sjmatthew if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 707d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 708d7a8f955Sjmatthew "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 709d7a8f955Sjmatthew return IXGBE_ERR_INVALID_LINK_SETTINGS; 710d7a8f955Sjmatthew } 711d7a8f955Sjmatthew 712d7a8f955Sjmatthew switch (hw->fc.requested_mode) { 713d7a8f955Sjmatthew case ixgbe_fc_full: 714d7a8f955Sjmatthew setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX << 715d7a8f955Sjmatthew FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 716d7a8f955Sjmatthew break; 717d7a8f955Sjmatthew case ixgbe_fc_rx_pause: 718d7a8f955Sjmatthew setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX << 719d7a8f955Sjmatthew FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 720d7a8f955Sjmatthew break; 721d7a8f955Sjmatthew case ixgbe_fc_tx_pause: 722d7a8f955Sjmatthew setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX << 723d7a8f955Sjmatthew FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; 724d7a8f955Sjmatthew break; 725d7a8f955Sjmatthew default: 726d7a8f955Sjmatthew break; 727d7a8f955Sjmatthew } 728d7a8f955Sjmatthew 729d7a8f955Sjmatthew for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) { 730d7a8f955Sjmatthew if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed) 731d7a8f955Sjmatthew setup[0] |= ixgbe_fw_map[i].fw_speed; 732d7a8f955Sjmatthew } 733d7a8f955Sjmatthew setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN; 734d7a8f955Sjmatthew 735d7a8f955Sjmatthew if (hw->phy.eee_speeds_advertised) 736d7a8f955Sjmatthew setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE; 737d7a8f955Sjmatthew 738d7a8f955Sjmatthew rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup); 739d7a8f955Sjmatthew if (rc) 740d7a8f955Sjmatthew return rc; 741d7a8f955Sjmatthew if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN) 742d7a8f955Sjmatthew return IXGBE_ERR_OVERTEMP; 743d7a8f955Sjmatthew return IXGBE_SUCCESS; 744d7a8f955Sjmatthew } 745d7a8f955Sjmatthew 746d7a8f955Sjmatthew /** 747d7a8f955Sjmatthew * ixgbe_fc_autoneg_fw _ Set up flow control for FW-controlled PHYs 748d7a8f955Sjmatthew * @hw: pointer to hardware structure 749d7a8f955Sjmatthew * 750d7a8f955Sjmatthew * Called at init time to set up flow control. 751d7a8f955Sjmatthew */ 752d7a8f955Sjmatthew int32_t ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw) 753d7a8f955Sjmatthew { 754d7a8f955Sjmatthew if (hw->fc.requested_mode == ixgbe_fc_default) 755d7a8f955Sjmatthew hw->fc.requested_mode = ixgbe_fc_full; 756d7a8f955Sjmatthew 757d7a8f955Sjmatthew return ixgbe_setup_fw_link(hw); 758d7a8f955Sjmatthew } 759d7a8f955Sjmatthew 760d7a8f955Sjmatthew /** 761d7a8f955Sjmatthew * ixgbe_setup_eee_fw - Enable/disable EEE support 762d7a8f955Sjmatthew * @hw: pointer to the HW structure 763d7a8f955Sjmatthew * @enable_eee: boolean flag to enable EEE 764d7a8f955Sjmatthew * 765d7a8f955Sjmatthew * Enable/disable EEE based on enable_eee flag. 766d7a8f955Sjmatthew * This function controls EEE for firmware-based PHY implementations. 767d7a8f955Sjmatthew */ 768d7a8f955Sjmatthew int32_t ixgbe_setup_eee_fw(struct ixgbe_hw *hw, bool enable_eee) 769d7a8f955Sjmatthew { 770d7a8f955Sjmatthew if (!!hw->phy.eee_speeds_advertised == enable_eee) 771d7a8f955Sjmatthew return IXGBE_SUCCESS; 772d7a8f955Sjmatthew if (enable_eee) 773d7a8f955Sjmatthew hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported; 774d7a8f955Sjmatthew else 775d7a8f955Sjmatthew hw->phy.eee_speeds_advertised = 0; 776d7a8f955Sjmatthew return hw->phy.ops.setup_link(hw); 777d7a8f955Sjmatthew } 778d7a8f955Sjmatthew 779d7a8f955Sjmatthew /** 780d7a8f955Sjmatthew * ixgbe_init_ops_X550EM_a - Inits func ptrs and MAC type 781d7a8f955Sjmatthew * @hw: pointer to hardware structure 782d7a8f955Sjmatthew * 783d7a8f955Sjmatthew * Initialize the function pointers and for MAC type X550EM_a. 784d7a8f955Sjmatthew * Does not touch the hardware. 785d7a8f955Sjmatthew **/ 786d7a8f955Sjmatthew int32_t ixgbe_init_ops_X550EM_a(struct ixgbe_hw *hw) 787d7a8f955Sjmatthew { 788d7a8f955Sjmatthew struct ixgbe_mac_info *mac = &hw->mac; 789d7a8f955Sjmatthew int32_t ret_val; 790d7a8f955Sjmatthew 791d7a8f955Sjmatthew DEBUGFUNC("ixgbe_init_ops_X550EM_a"); 792d7a8f955Sjmatthew 793d7a8f955Sjmatthew /* Start with generic X550EM init */ 794d7a8f955Sjmatthew ret_val = ixgbe_init_ops_X550EM(hw); 795d7a8f955Sjmatthew 796d7a8f955Sjmatthew if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || 797d7a8f955Sjmatthew hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) { 798d7a8f955Sjmatthew mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550; 799d7a8f955Sjmatthew mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550; 800d7a8f955Sjmatthew } else { 801d7a8f955Sjmatthew mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a; 802d7a8f955Sjmatthew mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a; 803d7a8f955Sjmatthew } 804d7a8f955Sjmatthew mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550a; 805d7a8f955Sjmatthew mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550a; 806d7a8f955Sjmatthew 807d7a8f955Sjmatthew switch (mac->ops.get_media_type(hw)) { 808d7a8f955Sjmatthew case ixgbe_media_type_fiber: 809d7a8f955Sjmatthew mac->ops.setup_fc = NULL; 810d7a8f955Sjmatthew mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; 811d7a8f955Sjmatthew break; 812d7a8f955Sjmatthew case ixgbe_media_type_backplane: 813d7a8f955Sjmatthew mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; 814d7a8f955Sjmatthew mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; 815d7a8f955Sjmatthew break; 816d7a8f955Sjmatthew default: 817d7a8f955Sjmatthew break; 818d7a8f955Sjmatthew } 819d7a8f955Sjmatthew 820d7a8f955Sjmatthew switch (hw->device_id) { 821d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T: 822d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T_L: 823d7a8f955Sjmatthew mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a; 824d7a8f955Sjmatthew mac->ops.setup_fc = ixgbe_fc_autoneg_fw; 825d7a8f955Sjmatthew mac->ops.setup_eee = ixgbe_setup_eee_fw; 826d7a8f955Sjmatthew hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL | 827d7a8f955Sjmatthew IXGBE_LINK_SPEED_1GB_FULL; 828d7a8f955Sjmatthew hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported; 829d7a8f955Sjmatthew break; 830d7a8f955Sjmatthew default: 831d7a8f955Sjmatthew break; 832d7a8f955Sjmatthew } 833d7a8f955Sjmatthew 834d7a8f955Sjmatthew return ret_val; 835d7a8f955Sjmatthew } 836d7a8f955Sjmatthew 837d7a8f955Sjmatthew /** 838d7a8f955Sjmatthew * ixgbe_init_ops_X550EM_x - Inits func ptrs and MAC type 839d7a8f955Sjmatthew * @hw: pointer to hardware structure 840d7a8f955Sjmatthew * 841d7a8f955Sjmatthew * Initialize the function pointers and for MAC type X550EM_x. 842d7a8f955Sjmatthew * Does not touch the hardware. 843d7a8f955Sjmatthew **/ 844d7a8f955Sjmatthew int32_t ixgbe_init_ops_X550EM_x(struct ixgbe_hw *hw) 845d7a8f955Sjmatthew { 846d7a8f955Sjmatthew struct ixgbe_mac_info *mac = &hw->mac; 847d7a8f955Sjmatthew struct ixgbe_link_info *link = &hw->link; 848d7a8f955Sjmatthew int32_t ret_val; 849d7a8f955Sjmatthew 850d7a8f955Sjmatthew DEBUGFUNC("ixgbe_init_ops_X550EM_x"); 851d7a8f955Sjmatthew 852d7a8f955Sjmatthew /* Start with generic X550EM init */ 853d7a8f955Sjmatthew ret_val = ixgbe_init_ops_X550EM(hw); 854d7a8f955Sjmatthew 855d7a8f955Sjmatthew mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550; 856d7a8f955Sjmatthew mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550; 857d7a8f955Sjmatthew mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550em; 858d7a8f955Sjmatthew mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550em; 859d7a8f955Sjmatthew link->ops.read_link = ixgbe_read_i2c_combined_generic; 860d7a8f955Sjmatthew link->ops.read_link_unlocked = ixgbe_read_i2c_combined_generic_unlocked; 861d7a8f955Sjmatthew link->ops.write_link = ixgbe_write_i2c_combined_generic; 862d7a8f955Sjmatthew link->ops.write_link_unlocked = 863d7a8f955Sjmatthew ixgbe_write_i2c_combined_generic_unlocked; 864d7a8f955Sjmatthew link->addr = IXGBE_CS4227; 865d7a8f955Sjmatthew 866d7a8f955Sjmatthew if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T) { 867d7a8f955Sjmatthew mac->ops.setup_fc = NULL; 868d7a8f955Sjmatthew mac->ops.setup_eee = NULL; 869d7a8f955Sjmatthew } 870d7a8f955Sjmatthew 871d7a8f955Sjmatthew return ret_val; 872d7a8f955Sjmatthew } 873d7a8f955Sjmatthew 874d7a8f955Sjmatthew /** 875d7a8f955Sjmatthew * ixgbe_dmac_config_X550 876d7a8f955Sjmatthew * @hw: pointer to hardware structure 877d7a8f955Sjmatthew * 878d7a8f955Sjmatthew * Configure DMA coalescing. If enabling dmac, dmac is activated. 879d7a8f955Sjmatthew * When disabling dmac, dmac enable dmac bit is cleared. 880d7a8f955Sjmatthew **/ 881d7a8f955Sjmatthew int32_t ixgbe_dmac_config_X550(struct ixgbe_hw *hw) 882d7a8f955Sjmatthew { 883d7a8f955Sjmatthew uint32_t reg; 884d7a8f955Sjmatthew 885d7a8f955Sjmatthew DEBUGFUNC("ixgbe_dmac_config_X550"); 886d7a8f955Sjmatthew 887d7a8f955Sjmatthew /* Disable DMA coalescing before configuring */ 888d7a8f955Sjmatthew reg = IXGBE_READ_REG(hw, IXGBE_DMACR); 889d7a8f955Sjmatthew reg &= ~IXGBE_DMACR_DMAC_EN; 890d7a8f955Sjmatthew IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); 891d7a8f955Sjmatthew 892d7a8f955Sjmatthew /* Disable DMA Coalescing if the watchdog timer is 0 */ 893d7a8f955Sjmatthew if (!hw->mac.dmac_config.watchdog_timer) 894d7a8f955Sjmatthew goto out; 895d7a8f955Sjmatthew 896d7a8f955Sjmatthew ixgbe_dmac_config_tcs_X550(hw); 897d7a8f955Sjmatthew 898d7a8f955Sjmatthew /* Configure DMA Coalescing Control Register */ 899d7a8f955Sjmatthew reg = IXGBE_READ_REG(hw, IXGBE_DMACR); 900d7a8f955Sjmatthew 901d7a8f955Sjmatthew /* Set the watchdog timer in units of 40.96 usec */ 902d7a8f955Sjmatthew reg &= ~IXGBE_DMACR_DMACWT_MASK; 903d7a8f955Sjmatthew reg |= (hw->mac.dmac_config.watchdog_timer * 100) / 4096; 904d7a8f955Sjmatthew 905d7a8f955Sjmatthew reg &= ~IXGBE_DMACR_HIGH_PRI_TC_MASK; 906d7a8f955Sjmatthew reg |= IXGBE_DMACR_EN_MNG_IND; 907d7a8f955Sjmatthew 908d7a8f955Sjmatthew /* Enable DMA coalescing after configuration */ 909d7a8f955Sjmatthew reg |= IXGBE_DMACR_DMAC_EN; 910d7a8f955Sjmatthew IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); 911d7a8f955Sjmatthew 912d7a8f955Sjmatthew out: 913d7a8f955Sjmatthew return IXGBE_SUCCESS; 914d7a8f955Sjmatthew } 915d7a8f955Sjmatthew 916d7a8f955Sjmatthew /** 917d7a8f955Sjmatthew * ixgbe_dmac_config_tcs_X550 918d7a8f955Sjmatthew * @hw: pointer to hardware structure 919d7a8f955Sjmatthew * 920d7a8f955Sjmatthew * Configure DMA coalescing threshold per TC. The dmac enable bit must 921d7a8f955Sjmatthew * be cleared before configuring. 922d7a8f955Sjmatthew **/ 923d7a8f955Sjmatthew int32_t ixgbe_dmac_config_tcs_X550(struct ixgbe_hw *hw) 924d7a8f955Sjmatthew { 925d7a8f955Sjmatthew uint32_t tc, reg, pb_headroom, rx_pb_size, maxframe_size_kb; 926d7a8f955Sjmatthew 927d7a8f955Sjmatthew DEBUGFUNC("ixgbe_dmac_config_tcs_X550"); 928d7a8f955Sjmatthew 929d7a8f955Sjmatthew /* Configure DMA coalescing enabled */ 930d7a8f955Sjmatthew switch (hw->mac.dmac_config.link_speed) { 931d7a8f955Sjmatthew case IXGBE_LINK_SPEED_10_FULL: 932d7a8f955Sjmatthew case IXGBE_LINK_SPEED_100_FULL: 933d7a8f955Sjmatthew pb_headroom = IXGBE_DMACRXT_100M; 934d7a8f955Sjmatthew break; 935d7a8f955Sjmatthew case IXGBE_LINK_SPEED_1GB_FULL: 936d7a8f955Sjmatthew pb_headroom = IXGBE_DMACRXT_1G; 937d7a8f955Sjmatthew break; 938d7a8f955Sjmatthew default: 939d7a8f955Sjmatthew pb_headroom = IXGBE_DMACRXT_10G; 940d7a8f955Sjmatthew break; 941d7a8f955Sjmatthew } 942d7a8f955Sjmatthew 943d7a8f955Sjmatthew maxframe_size_kb = ((IXGBE_READ_REG(hw, IXGBE_MAXFRS) >> 944d7a8f955Sjmatthew IXGBE_MHADD_MFS_SHIFT) / 1024); 945d7a8f955Sjmatthew 946d7a8f955Sjmatthew /* Set the per Rx packet buffer receive threshold */ 947d7a8f955Sjmatthew for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) { 948d7a8f955Sjmatthew reg = IXGBE_READ_REG(hw, IXGBE_DMCTH(tc)); 949d7a8f955Sjmatthew reg &= ~IXGBE_DMCTH_DMACRXT_MASK; 950d7a8f955Sjmatthew 951d7a8f955Sjmatthew if (tc < hw->mac.dmac_config.num_tcs) { 952d7a8f955Sjmatthew /* Get Rx PB size */ 953d7a8f955Sjmatthew rx_pb_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(tc)); 954d7a8f955Sjmatthew rx_pb_size = (rx_pb_size & IXGBE_RXPBSIZE_MASK) >> 955d7a8f955Sjmatthew IXGBE_RXPBSIZE_SHIFT; 956d7a8f955Sjmatthew 957d7a8f955Sjmatthew /* Calculate receive buffer threshold in kilobytes */ 958d7a8f955Sjmatthew if (rx_pb_size > pb_headroom) 959d7a8f955Sjmatthew rx_pb_size = rx_pb_size - pb_headroom; 960d7a8f955Sjmatthew else 961d7a8f955Sjmatthew rx_pb_size = 0; 962d7a8f955Sjmatthew 963d7a8f955Sjmatthew /* Minimum of MFS shall be set for DMCTH */ 964d7a8f955Sjmatthew reg |= (rx_pb_size > maxframe_size_kb) ? 965d7a8f955Sjmatthew rx_pb_size : maxframe_size_kb; 966d7a8f955Sjmatthew } 967d7a8f955Sjmatthew IXGBE_WRITE_REG(hw, IXGBE_DMCTH(tc), reg); 968d7a8f955Sjmatthew } 969d7a8f955Sjmatthew return IXGBE_SUCCESS; 970d7a8f955Sjmatthew } 971d7a8f955Sjmatthew 972d7a8f955Sjmatthew /** 973d7a8f955Sjmatthew * ixgbe_dmac_update_tcs_X550 974d7a8f955Sjmatthew * @hw: pointer to hardware structure 975d7a8f955Sjmatthew * 976d7a8f955Sjmatthew * Disables dmac, updates per TC settings, and then enables dmac. 977d7a8f955Sjmatthew **/ 978d7a8f955Sjmatthew int32_t ixgbe_dmac_update_tcs_X550(struct ixgbe_hw *hw) 979d7a8f955Sjmatthew { 980d7a8f955Sjmatthew uint32_t reg; 981d7a8f955Sjmatthew 982d7a8f955Sjmatthew DEBUGFUNC("ixgbe_dmac_update_tcs_X550"); 983d7a8f955Sjmatthew 984d7a8f955Sjmatthew /* Disable DMA coalescing before configuring */ 985d7a8f955Sjmatthew reg = IXGBE_READ_REG(hw, IXGBE_DMACR); 986d7a8f955Sjmatthew reg &= ~IXGBE_DMACR_DMAC_EN; 987d7a8f955Sjmatthew IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); 988d7a8f955Sjmatthew 989d7a8f955Sjmatthew ixgbe_dmac_config_tcs_X550(hw); 990d7a8f955Sjmatthew 991d7a8f955Sjmatthew /* Enable DMA coalescing after configuration */ 992d7a8f955Sjmatthew reg = IXGBE_READ_REG(hw, IXGBE_DMACR); 993d7a8f955Sjmatthew reg |= IXGBE_DMACR_DMAC_EN; 994d7a8f955Sjmatthew IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); 995d7a8f955Sjmatthew 996d7a8f955Sjmatthew return IXGBE_SUCCESS; 997d7a8f955Sjmatthew } 998d7a8f955Sjmatthew 999d7a8f955Sjmatthew /** 1000ac13930bSmikeb * ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 1001ac13930bSmikeb * @hw: pointer to hardware structure 1002ac13930bSmikeb * 1003ac13930bSmikeb * Initializes the EEPROM parameters ixgbe_eeprom_info within the 1004ac13930bSmikeb * ixgbe_hw struct in order to set up EEPROM access. 1005ac13930bSmikeb **/ 1006ac13930bSmikeb int32_t ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 1007ac13930bSmikeb { 1008ac13930bSmikeb struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 1009ac13930bSmikeb uint32_t eec; 1010ac13930bSmikeb uint16_t eeprom_size; 1011ac13930bSmikeb 1012ac13930bSmikeb DEBUGFUNC("ixgbe_init_eeprom_params_X550"); 1013ac13930bSmikeb 1014ac13930bSmikeb if (eeprom->type == ixgbe_eeprom_uninitialized) { 1015ac13930bSmikeb eeprom->semaphore_delay = 10; 1016ac13930bSmikeb eeprom->type = ixgbe_flash; 1017ac13930bSmikeb 1018ac13930bSmikeb eec = IXGBE_READ_REG(hw, IXGBE_EEC); 1019ac13930bSmikeb eeprom_size = (uint16_t)((eec & IXGBE_EEC_SIZE) >> 1020ac13930bSmikeb IXGBE_EEC_SIZE_SHIFT); 1021ac13930bSmikeb eeprom->word_size = 1 << (eeprom_size + 1022ac13930bSmikeb IXGBE_EEPROM_WORD_SIZE_SHIFT); 1023ac13930bSmikeb 1024ac13930bSmikeb DEBUGOUT2("Eeprom params: type = %d, size = %d\n", 1025ac13930bSmikeb eeprom->type, eeprom->word_size); 1026ac13930bSmikeb } 1027ac13930bSmikeb 1028ac13930bSmikeb return IXGBE_SUCCESS; 1029ac13930bSmikeb } 1030ac13930bSmikeb 1031ac13930bSmikeb /** 10324b1a56afSjsg * ixgbe_set_source_address_pruning_X550 - Enable/Disable source address pruning 1033d7a8f955Sjmatthew * @hw: pointer to hardware structure 1034d7a8f955Sjmatthew * @enable: enable or disable source address pruning 1035d7a8f955Sjmatthew * @pool: Rx pool to set source address pruning for 1036d7a8f955Sjmatthew **/ 1037d7a8f955Sjmatthew void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable, 1038d7a8f955Sjmatthew unsigned int pool) 1039d7a8f955Sjmatthew { 1040d7a8f955Sjmatthew uint64_t pfflp; 1041d7a8f955Sjmatthew 1042d7a8f955Sjmatthew /* max rx pool is 63 */ 1043d7a8f955Sjmatthew if (pool > 63) 1044d7a8f955Sjmatthew return; 1045d7a8f955Sjmatthew 1046d7a8f955Sjmatthew pfflp = (uint64_t)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 1047d7a8f955Sjmatthew pfflp |= (uint64_t)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 1048d7a8f955Sjmatthew 1049d7a8f955Sjmatthew if (enable) 1050d7a8f955Sjmatthew pfflp |= (1ULL << pool); 1051d7a8f955Sjmatthew else 1052d7a8f955Sjmatthew pfflp &= ~(1ULL << pool); 1053d7a8f955Sjmatthew 1054d7a8f955Sjmatthew IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (uint32_t)pfflp); 1055d7a8f955Sjmatthew IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (uint32_t)(pfflp >> 32)); 1056d7a8f955Sjmatthew } 1057d7a8f955Sjmatthew 1058d7a8f955Sjmatthew /** 1059ac13930bSmikeb * ixgbe_iosf_wait - Wait for IOSF command completion 1060ac13930bSmikeb * @hw: pointer to hardware structure 1061ac13930bSmikeb * @ctrl: pointer to location to receive final IOSF control value 1062ac13930bSmikeb * 1063ac13930bSmikeb * Returns failing status on timeout 1064ac13930bSmikeb * 1065ac13930bSmikeb * Note: ctrl can be NULL if the IOSF control register value is not needed 1066ac13930bSmikeb **/ 1067ac13930bSmikeb int32_t ixgbe_iosf_wait(struct ixgbe_hw *hw, uint32_t *ctrl) 1068ac13930bSmikeb { 1069ac13930bSmikeb uint32_t i, command = 0; 1070ac13930bSmikeb 1071ac13930bSmikeb /* Check every 10 usec to see if the address cycle completed. 1072ac13930bSmikeb * The SB IOSF BUSY bit will clear when the operation is 1073ac13930bSmikeb * complete 1074ac13930bSmikeb */ 1075ac13930bSmikeb for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 1076ac13930bSmikeb command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 1077ac13930bSmikeb if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0) 1078ac13930bSmikeb break; 1079ac13930bSmikeb usec_delay(10); 1080ac13930bSmikeb } 1081ac13930bSmikeb if (ctrl) 1082ac13930bSmikeb *ctrl = command; 1083ac13930bSmikeb if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 1084d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_POLLING, "Wait timed out\n"); 1085ac13930bSmikeb return IXGBE_ERR_PHY; 1086ac13930bSmikeb } 1087ac13930bSmikeb 1088ac13930bSmikeb return IXGBE_SUCCESS; 1089ac13930bSmikeb } 1090ac13930bSmikeb 1091ac13930bSmikeb /** 1092d7a8f955Sjmatthew * ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register 1093d7a8f955Sjmatthew * of the IOSF device 1094ac13930bSmikeb * @hw: pointer to hardware structure 1095ac13930bSmikeb * @reg_addr: 32 bit PHY register to write 1096ac13930bSmikeb * @device_type: 3 bit device type 1097ac13930bSmikeb * @data: Data to write to the register 1098ac13930bSmikeb **/ 1099ac13930bSmikeb int32_t ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, uint32_t reg_addr, 1100ac13930bSmikeb uint32_t device_type, uint32_t data) 1101ac13930bSmikeb { 1102ac13930bSmikeb uint32_t gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 1103d7a8f955Sjmatthew uint32_t command, error __unused; 1104ac13930bSmikeb int32_t ret; 1105ac13930bSmikeb 1106ac13930bSmikeb ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 1107ac13930bSmikeb if (ret != IXGBE_SUCCESS) 1108ac13930bSmikeb return ret; 1109ac13930bSmikeb 1110ac13930bSmikeb ret = ixgbe_iosf_wait(hw, NULL); 1111ac13930bSmikeb if (ret != IXGBE_SUCCESS) 1112ac13930bSmikeb goto out; 1113ac13930bSmikeb 1114ac13930bSmikeb command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 1115ac13930bSmikeb (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 1116ac13930bSmikeb 1117ac13930bSmikeb /* Write IOSF control register */ 1118ac13930bSmikeb IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 1119ac13930bSmikeb 1120ac13930bSmikeb /* Write IOSF data register */ 1121ac13930bSmikeb IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 1122ac13930bSmikeb 1123ac13930bSmikeb ret = ixgbe_iosf_wait(hw, &command); 1124ac13930bSmikeb 1125ac13930bSmikeb if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 1126ac13930bSmikeb error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 1127ac13930bSmikeb IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 1128d7a8f955Sjmatthew ERROR_REPORT2(IXGBE_ERROR_POLLING, 1129d7a8f955Sjmatthew "Failed to write, error %x\n", error); 1130ac13930bSmikeb ret = IXGBE_ERR_PHY; 1131ac13930bSmikeb } 1132ac13930bSmikeb 1133ac13930bSmikeb out: 1134ac13930bSmikeb hw->mac.ops.release_swfw_sync(hw, gssr); 1135ac13930bSmikeb return ret; 1136ac13930bSmikeb } 1137ac13930bSmikeb 1138ac13930bSmikeb /** 1139d7a8f955Sjmatthew * ixgbe_read_iosf_sb_reg_x550 - Reads specified register of the IOSF device 1140ac13930bSmikeb * @hw: pointer to hardware structure 1141ac13930bSmikeb * @reg_addr: 32 bit PHY register to write 1142ac13930bSmikeb * @device_type: 3 bit device type 1143d7a8f955Sjmatthew * @data: Pointer to read data from the register 1144ac13930bSmikeb **/ 1145ac13930bSmikeb int32_t ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, uint32_t reg_addr, 1146ac13930bSmikeb uint32_t device_type, uint32_t *data) 1147ac13930bSmikeb { 1148ac13930bSmikeb uint32_t gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 1149d7a8f955Sjmatthew uint32_t command, error __unused; 1150ac13930bSmikeb int32_t ret; 1151ac13930bSmikeb 1152ac13930bSmikeb ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 1153ac13930bSmikeb if (ret != IXGBE_SUCCESS) 1154ac13930bSmikeb return ret; 1155ac13930bSmikeb 1156ac13930bSmikeb ret = ixgbe_iosf_wait(hw, NULL); 1157ac13930bSmikeb if (ret != IXGBE_SUCCESS) 1158ac13930bSmikeb goto out; 1159ac13930bSmikeb 1160ac13930bSmikeb command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 1161ac13930bSmikeb (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 1162ac13930bSmikeb 1163ac13930bSmikeb /* Write IOSF control register */ 1164ac13930bSmikeb IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 1165ac13930bSmikeb 1166ac13930bSmikeb ret = ixgbe_iosf_wait(hw, &command); 1167ac13930bSmikeb 1168ac13930bSmikeb if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 1169ac13930bSmikeb error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 1170ac13930bSmikeb IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 1171d7a8f955Sjmatthew ERROR_REPORT2(IXGBE_ERROR_POLLING, 1172d7a8f955Sjmatthew "Failed to read, error %x\n", error); 1173ac13930bSmikeb ret = IXGBE_ERR_PHY; 1174ac13930bSmikeb } 1175ac13930bSmikeb 1176ac13930bSmikeb if (ret == IXGBE_SUCCESS) 1177ac13930bSmikeb *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 1178ac13930bSmikeb 1179ac13930bSmikeb out: 1180ac13930bSmikeb hw->mac.ops.release_swfw_sync(hw, gssr); 1181ac13930bSmikeb return ret; 1182ac13930bSmikeb } 1183ac13930bSmikeb 1184ac13930bSmikeb /** 1185d7a8f955Sjmatthew * ixgbe_get_phy_token - Get the token for shared phy access 1186d7a8f955Sjmatthew * @hw: Pointer to hardware structure 1187d7a8f955Sjmatthew */ 1188d7a8f955Sjmatthew 1189d7a8f955Sjmatthew int32_t ixgbe_get_phy_token(struct ixgbe_hw *hw) 1190d7a8f955Sjmatthew { 1191d7a8f955Sjmatthew struct ixgbe_hic_phy_token_req token_cmd; 1192d7a8f955Sjmatthew int32_t status; 1193d7a8f955Sjmatthew 1194d7a8f955Sjmatthew token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 1195d7a8f955Sjmatthew token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 1196d7a8f955Sjmatthew token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 1197d7a8f955Sjmatthew token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 1198d7a8f955Sjmatthew token_cmd.port_number = hw->bus.lan_id; 1199d7a8f955Sjmatthew token_cmd.command_type = FW_PHY_TOKEN_REQ; 1200d7a8f955Sjmatthew token_cmd.pad = 0; 1201d7a8f955Sjmatthew status = ixgbe_host_interface_command(hw, (uint32_t *)&token_cmd, 1202d7a8f955Sjmatthew sizeof(token_cmd), 1203d7a8f955Sjmatthew IXGBE_HI_COMMAND_TIMEOUT, 1204d7a8f955Sjmatthew TRUE); 1205d7a8f955Sjmatthew if (status) { 1206d7a8f955Sjmatthew DEBUGOUT1("Issuing host interface command failed with Status = %d\n", 1207d7a8f955Sjmatthew status); 1208d7a8f955Sjmatthew return status; 1209d7a8f955Sjmatthew } 1210d7a8f955Sjmatthew if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 1211d7a8f955Sjmatthew return IXGBE_SUCCESS; 1212d7a8f955Sjmatthew if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) { 1213d7a8f955Sjmatthew DEBUGOUT1("Host interface command returned 0x%08x , returning IXGBE_ERR_FW_RESP_INVALID\n", 1214d7a8f955Sjmatthew token_cmd.hdr.cmd_or_resp.ret_status); 1215d7a8f955Sjmatthew return IXGBE_ERR_FW_RESP_INVALID; 1216d7a8f955Sjmatthew } 1217d7a8f955Sjmatthew 1218d7a8f955Sjmatthew DEBUGOUT("Returning IXGBE_ERR_TOKEN_RETRY\n"); 1219d7a8f955Sjmatthew return IXGBE_ERR_TOKEN_RETRY; 1220d7a8f955Sjmatthew } 1221d7a8f955Sjmatthew 1222d7a8f955Sjmatthew /** 1223d7a8f955Sjmatthew * ixgbe_put_phy_token - Put the token for shared phy access 1224d7a8f955Sjmatthew * @hw: Pointer to hardware structure 1225d7a8f955Sjmatthew */ 1226d7a8f955Sjmatthew 1227d7a8f955Sjmatthew int32_t ixgbe_put_phy_token(struct ixgbe_hw *hw) 1228d7a8f955Sjmatthew { 1229d7a8f955Sjmatthew struct ixgbe_hic_phy_token_req token_cmd; 1230d7a8f955Sjmatthew int32_t status; 1231d7a8f955Sjmatthew 1232d7a8f955Sjmatthew token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; 1233d7a8f955Sjmatthew token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; 1234d7a8f955Sjmatthew token_cmd.hdr.cmd_or_resp.cmd_resv = 0; 1235d7a8f955Sjmatthew token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 1236d7a8f955Sjmatthew token_cmd.port_number = hw->bus.lan_id; 1237d7a8f955Sjmatthew token_cmd.command_type = FW_PHY_TOKEN_REL; 1238d7a8f955Sjmatthew token_cmd.pad = 0; 1239d7a8f955Sjmatthew status = ixgbe_host_interface_command(hw, (uint32_t *)&token_cmd, 1240d7a8f955Sjmatthew sizeof(token_cmd), 1241d7a8f955Sjmatthew IXGBE_HI_COMMAND_TIMEOUT, 1242d7a8f955Sjmatthew TRUE); 1243d7a8f955Sjmatthew if (status) 1244d7a8f955Sjmatthew return status; 1245d7a8f955Sjmatthew if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) 1246d7a8f955Sjmatthew return IXGBE_SUCCESS; 1247d7a8f955Sjmatthew 1248d7a8f955Sjmatthew DEBUGOUT("Put PHY Token host interface command failed"); 1249d7a8f955Sjmatthew return IXGBE_ERR_FW_RESP_INVALID; 1250d7a8f955Sjmatthew } 1251d7a8f955Sjmatthew 1252d7a8f955Sjmatthew /** 1253d7a8f955Sjmatthew * ixgbe_write_iosf_sb_reg_x550a - Writes a value to specified register 1254d7a8f955Sjmatthew * of the IOSF device 1255d7a8f955Sjmatthew * @hw: pointer to hardware structure 1256d7a8f955Sjmatthew * @reg_addr: 32 bit PHY register to write 1257d7a8f955Sjmatthew * @device_type: 3 bit device type 1258d7a8f955Sjmatthew * @data: Data to write to the register 1259d7a8f955Sjmatthew **/ 1260d7a8f955Sjmatthew int32_t ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, uint32_t reg_addr, 1261d7a8f955Sjmatthew uint32_t device_type, uint32_t data) 1262d7a8f955Sjmatthew { 1263d7a8f955Sjmatthew struct ixgbe_hic_internal_phy_req write_cmd; 1264d7a8f955Sjmatthew int32_t status; 1265d7a8f955Sjmatthew 1266d7a8f955Sjmatthew memset(&write_cmd, 0, sizeof(write_cmd)); 1267d7a8f955Sjmatthew write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 1268d7a8f955Sjmatthew write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 1269d7a8f955Sjmatthew write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 1270d7a8f955Sjmatthew write_cmd.port_number = hw->bus.lan_id; 1271d7a8f955Sjmatthew write_cmd.command_type = FW_INT_PHY_REQ_WRITE; 1272d7a8f955Sjmatthew write_cmd.address = htobe16(reg_addr); 1273d7a8f955Sjmatthew write_cmd.write_data = htobe32(data); 1274d7a8f955Sjmatthew 1275d7a8f955Sjmatthew status = ixgbe_host_interface_command(hw, (uint32_t *)&write_cmd, 1276d7a8f955Sjmatthew sizeof(write_cmd), 1277d7a8f955Sjmatthew IXGBE_HI_COMMAND_TIMEOUT, FALSE); 1278d7a8f955Sjmatthew 1279d7a8f955Sjmatthew return status; 1280d7a8f955Sjmatthew } 1281d7a8f955Sjmatthew 1282d7a8f955Sjmatthew /** 1283d7a8f955Sjmatthew * ixgbe_read_iosf_sb_reg_x550a - Reads specified register of the IOSF device 1284d7a8f955Sjmatthew * @hw: pointer to hardware structure 1285d7a8f955Sjmatthew * @reg_addr: 32 bit PHY register to write 1286d7a8f955Sjmatthew * @device_type: 3 bit device type 1287d7a8f955Sjmatthew * @data: Pointer to read data from the register 1288d7a8f955Sjmatthew **/ 1289d7a8f955Sjmatthew int32_t ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, uint32_t reg_addr, 1290d7a8f955Sjmatthew uint32_t device_type, uint32_t *data) 1291d7a8f955Sjmatthew { 1292d7a8f955Sjmatthew union { 1293d7a8f955Sjmatthew struct ixgbe_hic_internal_phy_req cmd; 1294d7a8f955Sjmatthew struct ixgbe_hic_internal_phy_resp rsp; 1295d7a8f955Sjmatthew } hic; 1296d7a8f955Sjmatthew int32_t status; 1297d7a8f955Sjmatthew 1298d7a8f955Sjmatthew memset(&hic, 0, sizeof(hic)); 1299d7a8f955Sjmatthew hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; 1300d7a8f955Sjmatthew hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; 1301d7a8f955Sjmatthew hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 1302d7a8f955Sjmatthew hic.cmd.port_number = hw->bus.lan_id; 1303d7a8f955Sjmatthew hic.cmd.command_type = FW_INT_PHY_REQ_READ; 1304d7a8f955Sjmatthew hic.cmd.address = htobe16(reg_addr); 1305d7a8f955Sjmatthew 1306d7a8f955Sjmatthew status = ixgbe_host_interface_command(hw, (uint32_t *)&hic.cmd, 1307d7a8f955Sjmatthew sizeof(hic.cmd), 1308d7a8f955Sjmatthew IXGBE_HI_COMMAND_TIMEOUT, TRUE); 1309d7a8f955Sjmatthew 1310d7a8f955Sjmatthew /* Extract the register value from the response. */ 1311d7a8f955Sjmatthew *data = betoh32(hic.rsp.read_data); 1312d7a8f955Sjmatthew 1313d7a8f955Sjmatthew return status; 1314d7a8f955Sjmatthew } 1315d7a8f955Sjmatthew 1316d7a8f955Sjmatthew /** 1317ac13930bSmikeb * ixgbe_get_media_type_X550em - Get media type 1318ac13930bSmikeb * @hw: pointer to hardware structure 1319ac13930bSmikeb * 1320ac13930bSmikeb * Returns the media type (fiber, copper, backplane) 1321ac13930bSmikeb */ 1322ac13930bSmikeb enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 1323ac13930bSmikeb { 1324ac13930bSmikeb enum ixgbe_media_type media_type; 1325ac13930bSmikeb 1326ac13930bSmikeb DEBUGFUNC("ixgbe_get_media_type_X550em"); 1327ac13930bSmikeb 1328ac13930bSmikeb /* Detect if there is a copper PHY attached. */ 1329ac13930bSmikeb switch (hw->device_id) { 1330ac13930bSmikeb case IXGBE_DEV_ID_X550EM_X_KR: 1331ac13930bSmikeb case IXGBE_DEV_ID_X550EM_X_KX4: 1332d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_XFI: 1333d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_KR: 1334d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_KR_L: 1335ac13930bSmikeb media_type = ixgbe_media_type_backplane; 1336ac13930bSmikeb break; 1337ac13930bSmikeb case IXGBE_DEV_ID_X550EM_X_SFP: 1338d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_SFP: 1339d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_SFP_N: 1340d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_QSFP: 1341d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_QSFP_N: 1342ac13930bSmikeb media_type = ixgbe_media_type_fiber; 1343ac13930bSmikeb break; 1344ac13930bSmikeb case IXGBE_DEV_ID_X550EM_X_1G_T: 1345ac13930bSmikeb case IXGBE_DEV_ID_X550EM_X_10G_T: 1346d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_10G_T: 1347d7a8f955Sjmatthew media_type = ixgbe_media_type_copper; 1348d7a8f955Sjmatthew break; 1349d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_SGMII: 1350d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_SGMII_L: 1351d7a8f955Sjmatthew media_type = ixgbe_media_type_backplane; 1352d7a8f955Sjmatthew hw->phy.type = ixgbe_phy_sgmii; 1353d7a8f955Sjmatthew break; 1354d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T: 1355d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T_L: 1356ac13930bSmikeb media_type = ixgbe_media_type_copper; 1357ac13930bSmikeb break; 1358ac13930bSmikeb default: 1359ac13930bSmikeb media_type = ixgbe_media_type_unknown; 1360ac13930bSmikeb break; 1361ac13930bSmikeb } 1362ac13930bSmikeb return media_type; 1363ac13930bSmikeb } 1364ac13930bSmikeb 1365ac13930bSmikeb /** 1366ac13930bSmikeb * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported 1367ac13930bSmikeb * @hw: pointer to hardware structure 1368ac13930bSmikeb * @linear: TRUE if SFP module is linear 1369ac13930bSmikeb */ 1370ac13930bSmikeb int32_t ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) 1371ac13930bSmikeb { 1372ac13930bSmikeb DEBUGFUNC("ixgbe_supported_sfp_modules_X550em"); 1373ac13930bSmikeb 1374ac13930bSmikeb switch (hw->phy.sfp_type) { 1375ac13930bSmikeb case ixgbe_sfp_type_not_present: 1376ac13930bSmikeb return IXGBE_ERR_SFP_NOT_PRESENT; 1377ac13930bSmikeb case ixgbe_sfp_type_da_cu_core0: 1378ac13930bSmikeb case ixgbe_sfp_type_da_cu_core1: 1379ac13930bSmikeb *linear = TRUE; 1380ac13930bSmikeb break; 1381ac13930bSmikeb case ixgbe_sfp_type_srlr_core0: 1382ac13930bSmikeb case ixgbe_sfp_type_srlr_core1: 1383ac13930bSmikeb case ixgbe_sfp_type_da_act_lmt_core0: 1384ac13930bSmikeb case ixgbe_sfp_type_da_act_lmt_core1: 1385ac13930bSmikeb case ixgbe_sfp_type_1g_sx_core0: 1386ac13930bSmikeb case ixgbe_sfp_type_1g_sx_core1: 1387ac13930bSmikeb case ixgbe_sfp_type_1g_lx_core0: 1388ac13930bSmikeb case ixgbe_sfp_type_1g_lx_core1: 1389ac13930bSmikeb *linear = FALSE; 1390ac13930bSmikeb break; 1391ac13930bSmikeb case ixgbe_sfp_type_unknown: 1392ac13930bSmikeb case ixgbe_sfp_type_1g_cu_core0: 1393ac13930bSmikeb case ixgbe_sfp_type_1g_cu_core1: 1394ac13930bSmikeb default: 1395ac13930bSmikeb return IXGBE_ERR_SFP_NOT_SUPPORTED; 1396ac13930bSmikeb } 1397ac13930bSmikeb 1398ac13930bSmikeb return IXGBE_SUCCESS; 1399ac13930bSmikeb } 1400ac13930bSmikeb 1401ac13930bSmikeb /** 1402ac13930bSmikeb * ixgbe_identify_sfp_module_X550em - Identifies SFP modules 1403ac13930bSmikeb * @hw: pointer to hardware structure 1404ac13930bSmikeb * 1405ac13930bSmikeb * Searches for and identifies the SFP module and assigns appropriate PHY type. 1406ac13930bSmikeb **/ 1407ac13930bSmikeb int32_t ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw) 1408ac13930bSmikeb { 1409ac13930bSmikeb int32_t status; 1410ac13930bSmikeb bool linear; 1411ac13930bSmikeb 1412ac13930bSmikeb DEBUGFUNC("ixgbe_identify_sfp_module_X550em"); 1413ac13930bSmikeb 1414ac13930bSmikeb status = ixgbe_identify_module_generic(hw); 1415ac13930bSmikeb 1416ac13930bSmikeb if (status != IXGBE_SUCCESS) 1417ac13930bSmikeb return status; 1418ac13930bSmikeb 1419ac13930bSmikeb /* Check if SFP module is supported */ 1420ac13930bSmikeb status = ixgbe_supported_sfp_modules_X550em(hw, &linear); 1421ac13930bSmikeb 1422ac13930bSmikeb return status; 1423ac13930bSmikeb } 1424ac13930bSmikeb 1425ac13930bSmikeb /** 1426ac13930bSmikeb * ixgbe_setup_sfp_modules_X550em - Setup MAC link ops 1427ac13930bSmikeb * @hw: pointer to hardware structure 1428ac13930bSmikeb */ 1429ac13930bSmikeb int32_t ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 1430ac13930bSmikeb { 1431ac13930bSmikeb int32_t status; 1432ac13930bSmikeb bool linear; 1433ac13930bSmikeb 1434ac13930bSmikeb DEBUGFUNC("ixgbe_setup_sfp_modules_X550em"); 1435ac13930bSmikeb 1436ac13930bSmikeb /* Check if SFP module is supported */ 1437ac13930bSmikeb status = ixgbe_supported_sfp_modules_X550em(hw, &linear); 1438ac13930bSmikeb 1439ac13930bSmikeb if (status != IXGBE_SUCCESS) 1440ac13930bSmikeb return status; 1441ac13930bSmikeb 1442ac13930bSmikeb ixgbe_init_mac_link_ops_X550em(hw); 1443ac13930bSmikeb hw->phy.ops.reset = NULL; 1444ac13930bSmikeb 1445ac13930bSmikeb return IXGBE_SUCCESS; 1446ac13930bSmikeb } 1447ac13930bSmikeb 1448ac13930bSmikeb /** 1449d7a8f955Sjmatthew * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the 1450d7a8f955Sjmatthew * internal PHY 1451d7a8f955Sjmatthew * @hw: pointer to hardware structure 1452d7a8f955Sjmatthew **/ 1453d7a8f955Sjmatthew int32_t ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw) 1454d7a8f955Sjmatthew { 1455d7a8f955Sjmatthew int32_t status; 1456d7a8f955Sjmatthew uint32_t link_ctrl; 1457d7a8f955Sjmatthew 1458d7a8f955Sjmatthew /* Restart auto-negotiation. */ 1459d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 1460d7a8f955Sjmatthew IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1461d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); 1462d7a8f955Sjmatthew 1463d7a8f955Sjmatthew if (status) { 1464d7a8f955Sjmatthew DEBUGOUT("Auto-negotiation did not complete\n"); 1465d7a8f955Sjmatthew return status; 1466d7a8f955Sjmatthew } 1467d7a8f955Sjmatthew 1468d7a8f955Sjmatthew link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 1469d7a8f955Sjmatthew status = hw->mac.ops.write_iosf_sb_reg(hw, 1470d7a8f955Sjmatthew IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1471d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); 1472d7a8f955Sjmatthew 1473d7a8f955Sjmatthew if (hw->mac.type == ixgbe_mac_X550EM_a) { 1474d7a8f955Sjmatthew uint32_t flx_mask_st20; 1475d7a8f955Sjmatthew 1476d7a8f955Sjmatthew /* Indicate to FW that AN restart has been asserted */ 1477d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 1478d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1479d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20); 1480d7a8f955Sjmatthew 1481d7a8f955Sjmatthew if (status) { 1482d7a8f955Sjmatthew DEBUGOUT("Auto-negotiation did not complete\n"); 1483d7a8f955Sjmatthew return status; 1484d7a8f955Sjmatthew } 1485d7a8f955Sjmatthew 1486d7a8f955Sjmatthew flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART; 1487d7a8f955Sjmatthew status = hw->mac.ops.write_iosf_sb_reg(hw, 1488d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1489d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20); 1490d7a8f955Sjmatthew } 1491d7a8f955Sjmatthew 1492d7a8f955Sjmatthew return status; 1493d7a8f955Sjmatthew } 1494d7a8f955Sjmatthew 1495d7a8f955Sjmatthew /** 1496d7a8f955Sjmatthew * ixgbe_setup_sgmii - Set up link for sgmii 1497d7a8f955Sjmatthew * @hw: pointer to hardware structure 1498d7a8f955Sjmatthew * @speed: new link speed 1499d7a8f955Sjmatthew * @autoneg_wait: TRUE when waiting for completion is needed 1500d7a8f955Sjmatthew */ 1501d7a8f955Sjmatthew int32_t ixgbe_setup_sgmii(struct ixgbe_hw *hw, ixgbe_link_speed speed, 1502d7a8f955Sjmatthew bool autoneg_wait) 1503d7a8f955Sjmatthew { 1504d7a8f955Sjmatthew struct ixgbe_mac_info *mac = &hw->mac; 1505d7a8f955Sjmatthew uint32_t lval, sval, flx_val; 1506d7a8f955Sjmatthew int32_t rc; 1507d7a8f955Sjmatthew 1508d7a8f955Sjmatthew rc = mac->ops.read_iosf_sb_reg(hw, 1509d7a8f955Sjmatthew IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1510d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 1511d7a8f955Sjmatthew if (rc) 1512d7a8f955Sjmatthew return rc; 1513d7a8f955Sjmatthew 1514d7a8f955Sjmatthew lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1515d7a8f955Sjmatthew lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 1516d7a8f955Sjmatthew lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 1517d7a8f955Sjmatthew lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 1518d7a8f955Sjmatthew lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 1519d7a8f955Sjmatthew rc = mac->ops.write_iosf_sb_reg(hw, 1520d7a8f955Sjmatthew IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1521d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1522d7a8f955Sjmatthew if (rc) 1523d7a8f955Sjmatthew return rc; 1524d7a8f955Sjmatthew 1525d7a8f955Sjmatthew rc = mac->ops.read_iosf_sb_reg(hw, 1526d7a8f955Sjmatthew IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1527d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 1528d7a8f955Sjmatthew if (rc) 1529d7a8f955Sjmatthew return rc; 1530d7a8f955Sjmatthew 1531d7a8f955Sjmatthew sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 1532d7a8f955Sjmatthew sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 1533d7a8f955Sjmatthew rc = mac->ops.write_iosf_sb_reg(hw, 1534d7a8f955Sjmatthew IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1535d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 1536d7a8f955Sjmatthew if (rc) 1537d7a8f955Sjmatthew return rc; 1538d7a8f955Sjmatthew 1539d7a8f955Sjmatthew rc = mac->ops.read_iosf_sb_reg(hw, 1540d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1541d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 1542d7a8f955Sjmatthew if (rc) 1543d7a8f955Sjmatthew return rc; 1544d7a8f955Sjmatthew 1545d7a8f955Sjmatthew flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 1546d7a8f955Sjmatthew flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; 1547d7a8f955Sjmatthew flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 1548d7a8f955Sjmatthew flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 1549d7a8f955Sjmatthew flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 1550d7a8f955Sjmatthew 1551d7a8f955Sjmatthew rc = mac->ops.write_iosf_sb_reg(hw, 1552d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1553d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); 1554d7a8f955Sjmatthew if (rc) 1555d7a8f955Sjmatthew return rc; 1556d7a8f955Sjmatthew 1557d7a8f955Sjmatthew rc = ixgbe_restart_an_internal_phy_x550em(hw); 1558d7a8f955Sjmatthew if (rc) 1559d7a8f955Sjmatthew return rc; 1560d7a8f955Sjmatthew 1561d7a8f955Sjmatthew return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 1562d7a8f955Sjmatthew } 1563d7a8f955Sjmatthew 1564d7a8f955Sjmatthew /** 1565d7a8f955Sjmatthew * ixgbe_setup_sgmii_fw - Set up link for internal PHY SGMII auto-negotiation 1566d7a8f955Sjmatthew * @hw: pointer to hardware structure 1567d7a8f955Sjmatthew * @speed: new link speed 1568d7a8f955Sjmatthew * @autoneg_wait: TRUE when waiting for completion is needed 1569d7a8f955Sjmatthew */ 1570d7a8f955Sjmatthew int32_t ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed, 1571d7a8f955Sjmatthew bool autoneg_wait) 1572d7a8f955Sjmatthew { 1573d7a8f955Sjmatthew struct ixgbe_mac_info *mac = &hw->mac; 1574d7a8f955Sjmatthew uint32_t lval, sval, flx_val; 1575d7a8f955Sjmatthew int32_t rc; 1576d7a8f955Sjmatthew 1577d7a8f955Sjmatthew rc = mac->ops.read_iosf_sb_reg(hw, 1578d7a8f955Sjmatthew IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1579d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); 1580d7a8f955Sjmatthew if (rc) 1581d7a8f955Sjmatthew return rc; 1582d7a8f955Sjmatthew 1583d7a8f955Sjmatthew lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1584d7a8f955Sjmatthew lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 1585d7a8f955Sjmatthew lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; 1586d7a8f955Sjmatthew lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; 1587d7a8f955Sjmatthew lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 1588d7a8f955Sjmatthew rc = mac->ops.write_iosf_sb_reg(hw, 1589d7a8f955Sjmatthew IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1590d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1591d7a8f955Sjmatthew if (rc) 1592d7a8f955Sjmatthew return rc; 1593d7a8f955Sjmatthew 1594d7a8f955Sjmatthew rc = mac->ops.read_iosf_sb_reg(hw, 1595d7a8f955Sjmatthew IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1596d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); 1597d7a8f955Sjmatthew if (rc) 1598d7a8f955Sjmatthew return rc; 1599d7a8f955Sjmatthew 1600d7a8f955Sjmatthew sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; 1601d7a8f955Sjmatthew sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; 1602d7a8f955Sjmatthew rc = mac->ops.write_iosf_sb_reg(hw, 1603d7a8f955Sjmatthew IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), 1604d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, sval); 1605d7a8f955Sjmatthew if (rc) 1606d7a8f955Sjmatthew return rc; 1607d7a8f955Sjmatthew 1608d7a8f955Sjmatthew rc = mac->ops.write_iosf_sb_reg(hw, 1609d7a8f955Sjmatthew IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1610d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, lval); 1611d7a8f955Sjmatthew if (rc) 1612d7a8f955Sjmatthew return rc; 1613d7a8f955Sjmatthew 1614d7a8f955Sjmatthew rc = mac->ops.read_iosf_sb_reg(hw, 1615d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1616d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); 1617d7a8f955Sjmatthew if (rc) 1618d7a8f955Sjmatthew return rc; 1619d7a8f955Sjmatthew 1620d7a8f955Sjmatthew flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 1621d7a8f955Sjmatthew flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; 1622d7a8f955Sjmatthew flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 1623d7a8f955Sjmatthew flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 1624d7a8f955Sjmatthew flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 1625d7a8f955Sjmatthew 1626d7a8f955Sjmatthew rc = mac->ops.write_iosf_sb_reg(hw, 1627d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1628d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); 1629d7a8f955Sjmatthew if (rc) 1630d7a8f955Sjmatthew return rc; 1631d7a8f955Sjmatthew 1632d7a8f955Sjmatthew rc = ixgbe_restart_an_internal_phy_x550em(hw); 1633d7a8f955Sjmatthew 1634d7a8f955Sjmatthew return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 1635d7a8f955Sjmatthew } 1636d7a8f955Sjmatthew 1637d7a8f955Sjmatthew /** 1638ac13930bSmikeb * ixgbe_init_mac_link_ops_X550em - init mac link function pointers 1639ac13930bSmikeb * @hw: pointer to hardware structure 1640ac13930bSmikeb */ 1641ac13930bSmikeb void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 1642ac13930bSmikeb { 1643ac13930bSmikeb struct ixgbe_mac_info *mac = &hw->mac; 1644ac13930bSmikeb 1645ac13930bSmikeb DEBUGFUNC("ixgbe_init_mac_link_ops_X550em"); 1646ac13930bSmikeb 1647ac13930bSmikeb switch (hw->mac.ops.get_media_type(hw)) { 1648ac13930bSmikeb case ixgbe_media_type_fiber: 1649ac13930bSmikeb /* CS4227 does not support autoneg, so disable the laser control 1650ac13930bSmikeb * functions for SFP+ fiber 1651ac13930bSmikeb */ 1652ac13930bSmikeb mac->ops.disable_tx_laser = NULL; 1653ac13930bSmikeb mac->ops.enable_tx_laser = NULL; 1654ac13930bSmikeb mac->ops.flap_tx_laser = NULL; 1655ac13930bSmikeb mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; 1656ac13930bSmikeb mac->ops.set_rate_select_speed = 1657ac13930bSmikeb ixgbe_set_soft_rate_select_speed; 1658d7a8f955Sjmatthew 1659d7a8f955Sjmatthew if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) || 1660d7a8f955Sjmatthew (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP)) 1661d7a8f955Sjmatthew mac->ops.setup_mac_link = 1662d7a8f955Sjmatthew ixgbe_setup_mac_link_sfp_x550a; 1663d7a8f955Sjmatthew else 1664d7a8f955Sjmatthew mac->ops.setup_mac_link = 1665d7a8f955Sjmatthew ixgbe_setup_mac_link_sfp_x550em; 1666ac13930bSmikeb break; 1667ac13930bSmikeb case ixgbe_media_type_copper: 1668d7a8f955Sjmatthew if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T) 1669d7a8f955Sjmatthew break; 1670d7a8f955Sjmatthew if (hw->mac.type == ixgbe_mac_X550EM_a) { 1671d7a8f955Sjmatthew if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T || 1672d7a8f955Sjmatthew hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) { 1673d7a8f955Sjmatthew mac->ops.setup_link = ixgbe_setup_sgmii_fw; 1674d7a8f955Sjmatthew mac->ops.check_link = 1675d7a8f955Sjmatthew ixgbe_check_mac_link_generic; 1676d7a8f955Sjmatthew } else { 1677d7a8f955Sjmatthew mac->ops.setup_link = 1678d7a8f955Sjmatthew ixgbe_setup_mac_link_t_X550em; 1679d7a8f955Sjmatthew } 1680d7a8f955Sjmatthew } else { 1681ac13930bSmikeb mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 1682ac13930bSmikeb mac->ops.check_link = ixgbe_check_link_t_X550em; 1683d7a8f955Sjmatthew } 1684d7a8f955Sjmatthew break; 1685d7a8f955Sjmatthew case ixgbe_media_type_backplane: 1686d7a8f955Sjmatthew if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || 1687d7a8f955Sjmatthew hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) 1688d7a8f955Sjmatthew mac->ops.setup_link = ixgbe_setup_sgmii; 1689ac13930bSmikeb break; 1690ac13930bSmikeb default: 1691ac13930bSmikeb break; 1692ac13930bSmikeb } 1693ac13930bSmikeb } 1694ac13930bSmikeb 1695ac13930bSmikeb /** 1696ac13930bSmikeb * ixgbe_get_link_capabilities_x550em - Determines link capabilities 1697ac13930bSmikeb * @hw: pointer to hardware structure 1698ac13930bSmikeb * @speed: pointer to link speed 1699ac13930bSmikeb * @autoneg: TRUE when autoneg or autotry is enabled 1700ac13930bSmikeb */ 1701ac13930bSmikeb int32_t ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 1702ac13930bSmikeb ixgbe_link_speed *speed, 1703ac13930bSmikeb bool *autoneg) 1704ac13930bSmikeb { 1705ac13930bSmikeb DEBUGFUNC("ixgbe_get_link_capabilities_X550em"); 1706ac13930bSmikeb 1707d7a8f955Sjmatthew 1708d7a8f955Sjmatthew if (hw->phy.type == ixgbe_phy_fw) { 1709d7a8f955Sjmatthew *autoneg = TRUE; 1710d7a8f955Sjmatthew *speed = hw->phy.speeds_supported; 1711d7a8f955Sjmatthew return 0; 1712d7a8f955Sjmatthew } 1713d7a8f955Sjmatthew 1714ac13930bSmikeb /* SFP */ 1715ac13930bSmikeb if (hw->phy.media_type == ixgbe_media_type_fiber) { 1716ac13930bSmikeb 1717ac13930bSmikeb /* CS4227 SFP must not enable auto-negotiation */ 1718ac13930bSmikeb *autoneg = FALSE; 1719ac13930bSmikeb 1720ac13930bSmikeb /* Check if 1G SFP module. */ 1721ac13930bSmikeb if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 1722ac13930bSmikeb hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 1723ac13930bSmikeb || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || 1724ac13930bSmikeb hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) { 1725ac13930bSmikeb *speed = IXGBE_LINK_SPEED_1GB_FULL; 1726ac13930bSmikeb return IXGBE_SUCCESS; 1727ac13930bSmikeb } 1728ac13930bSmikeb 1729ac13930bSmikeb /* Link capabilities are based on SFP */ 1730ac13930bSmikeb if (hw->phy.multispeed_fiber) 1731ac13930bSmikeb *speed = IXGBE_LINK_SPEED_10GB_FULL | 1732ac13930bSmikeb IXGBE_LINK_SPEED_1GB_FULL; 1733ac13930bSmikeb else 1734ac13930bSmikeb *speed = IXGBE_LINK_SPEED_10GB_FULL; 1735ac13930bSmikeb } else { 1736d7a8f955Sjmatthew switch (hw->phy.type) { 1737d7a8f955Sjmatthew case ixgbe_phy_ext_1g_t: 1738d7a8f955Sjmatthew case ixgbe_phy_sgmii: 1739d7a8f955Sjmatthew *speed = IXGBE_LINK_SPEED_1GB_FULL; 1740d7a8f955Sjmatthew break; 1741d7a8f955Sjmatthew case ixgbe_phy_x550em_kr: 1742d7a8f955Sjmatthew if (hw->mac.type == ixgbe_mac_X550EM_a) { 1743d7a8f955Sjmatthew /* check different backplane modes */ 1744d7a8f955Sjmatthew if (hw->phy.nw_mng_if_sel & 1745d7a8f955Sjmatthew IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) { 1746d7a8f955Sjmatthew *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 1747d7a8f955Sjmatthew break; 1748d7a8f955Sjmatthew } else if (hw->device_id == 1749d7a8f955Sjmatthew IXGBE_DEV_ID_X550EM_A_KR_L) { 1750d7a8f955Sjmatthew *speed = IXGBE_LINK_SPEED_1GB_FULL; 1751d7a8f955Sjmatthew break; 1752d7a8f955Sjmatthew } 1753d7a8f955Sjmatthew } 1754d7a8f955Sjmatthew /* fall through */ 1755d7a8f955Sjmatthew default: 1756ac13930bSmikeb *speed = IXGBE_LINK_SPEED_10GB_FULL | 1757ac13930bSmikeb IXGBE_LINK_SPEED_1GB_FULL; 1758d7a8f955Sjmatthew break; 1759d7a8f955Sjmatthew } 1760ac13930bSmikeb *autoneg = TRUE; 1761ac13930bSmikeb } 1762ac13930bSmikeb 1763ac13930bSmikeb return IXGBE_SUCCESS; 1764ac13930bSmikeb } 1765ac13930bSmikeb 1766ac13930bSmikeb /** 1767*54fbbda3Sjsg * ixgbe_get_lasi_ext_t_x550em - Determine external Base T PHY interrupt cause 1768ac13930bSmikeb * @hw: pointer to hardware structure 1769ac13930bSmikeb * @lsc: pointer to boolean flag which indicates whether external Base T 1770ac13930bSmikeb * PHY interrupt is lsc 1771ac13930bSmikeb * 1772*54fbbda3Sjsg * Determine if external Base T PHY interrupt cause is high temperature 1773ac13930bSmikeb * failure alarm or link status change. 1774ac13930bSmikeb * 1775ac13930bSmikeb * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1776ac13930bSmikeb * failure alarm, else return PHY access status. 1777ac13930bSmikeb */ 1778ac13930bSmikeb int32_t ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) 1779ac13930bSmikeb { 1780ac13930bSmikeb uint32_t status; 1781ac13930bSmikeb uint16_t reg; 1782ac13930bSmikeb 1783ac13930bSmikeb *lsc = FALSE; 1784ac13930bSmikeb 1785ac13930bSmikeb /* Vendor alarm triggered */ 1786ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 1787ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1788ac13930bSmikeb ®); 1789ac13930bSmikeb 1790ac13930bSmikeb if (status != IXGBE_SUCCESS || 1791ac13930bSmikeb !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 1792ac13930bSmikeb return status; 1793ac13930bSmikeb 1794ac13930bSmikeb /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 1795ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 1796ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1797ac13930bSmikeb ®); 1798ac13930bSmikeb 1799ac13930bSmikeb if (status != IXGBE_SUCCESS || 1800ac13930bSmikeb !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1801ac13930bSmikeb IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 1802ac13930bSmikeb return status; 1803ac13930bSmikeb 1804ac13930bSmikeb /* Global alarm triggered */ 1805ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 1806ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1807ac13930bSmikeb ®); 1808ac13930bSmikeb 1809ac13930bSmikeb if (status != IXGBE_SUCCESS) 1810ac13930bSmikeb return status; 1811ac13930bSmikeb 1812ac13930bSmikeb /* If high temperature failure, then return over temp error and exit */ 1813ac13930bSmikeb if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 1814ac13930bSmikeb /* power down the PHY in case the PHY FW didn't already */ 1815ac13930bSmikeb ixgbe_set_copper_phy_power(hw, FALSE); 1816ac13930bSmikeb return IXGBE_ERR_OVERTEMP; 1817ac13930bSmikeb } else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { 1818ac13930bSmikeb /* device fault alarm triggered */ 1819ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, 1820ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1821ac13930bSmikeb ®); 1822ac13930bSmikeb 1823ac13930bSmikeb if (status != IXGBE_SUCCESS) 1824ac13930bSmikeb return status; 1825ac13930bSmikeb 1826ac13930bSmikeb /* if device fault was due to high temp alarm handle and exit */ 1827ac13930bSmikeb if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { 1828ac13930bSmikeb /* power down the PHY in case the PHY FW didn't */ 1829ac13930bSmikeb ixgbe_set_copper_phy_power(hw, FALSE); 1830ac13930bSmikeb return IXGBE_ERR_OVERTEMP; 1831ac13930bSmikeb } 1832ac13930bSmikeb } 1833ac13930bSmikeb 1834ac13930bSmikeb /* Vendor alarm 2 triggered */ 1835ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 1836ac13930bSmikeb IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1837ac13930bSmikeb 1838ac13930bSmikeb if (status != IXGBE_SUCCESS || 1839ac13930bSmikeb !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 1840ac13930bSmikeb return status; 1841ac13930bSmikeb 1842ac13930bSmikeb /* link connect/disconnect event occurred */ 1843ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 1844ac13930bSmikeb IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1845ac13930bSmikeb 1846ac13930bSmikeb if (status != IXGBE_SUCCESS) 1847ac13930bSmikeb return status; 1848ac13930bSmikeb 1849ac13930bSmikeb /* Indicate LSC */ 1850ac13930bSmikeb if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 1851ac13930bSmikeb *lsc = TRUE; 1852ac13930bSmikeb 1853ac13930bSmikeb return IXGBE_SUCCESS; 1854ac13930bSmikeb } 1855ac13930bSmikeb 1856ac13930bSmikeb /** 1857ac13930bSmikeb * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 1858ac13930bSmikeb * @hw: pointer to hardware structure 1859ac13930bSmikeb * 1860ac13930bSmikeb * Enable link status change and temperature failure alarm for the external 1861ac13930bSmikeb * Base T PHY 1862ac13930bSmikeb * 1863ac13930bSmikeb * Returns PHY access status 1864ac13930bSmikeb */ 1865ac13930bSmikeb int32_t ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1866ac13930bSmikeb { 1867ac13930bSmikeb uint32_t status; 1868ac13930bSmikeb uint16_t reg; 1869ac13930bSmikeb bool lsc; 1870ac13930bSmikeb 1871ac13930bSmikeb /* Clear interrupt flags */ 1872ac13930bSmikeb status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1873ac13930bSmikeb 1874ac13930bSmikeb /* Enable link status change alarm */ 1875d7a8f955Sjmatthew 1876d7a8f955Sjmatthew /* Enable the LASI interrupts on X552 devices to receive notifications 1877d7a8f955Sjmatthew * of the link configurations of the external PHY and correspondingly 1878d7a8f955Sjmatthew * support the configuration of the internal iXFI link, since iXFI does 1879d7a8f955Sjmatthew * not support auto-negotiation. This is not required for X553 devices 1880d7a8f955Sjmatthew * having KR support, which performs auto-negotiations and which is used 1881d7a8f955Sjmatthew * as the internal link to the external PHY. Hence adding a check here 1882d7a8f955Sjmatthew * to avoid enabling LASI interrupts for X553 devices. 1883d7a8f955Sjmatthew */ 1884d7a8f955Sjmatthew if (hw->mac.type != ixgbe_mac_X550EM_a) { 1885d7a8f955Sjmatthew status = hw->phy.ops.read_reg(hw, 1886d7a8f955Sjmatthew IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 1887ac13930bSmikeb IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1888ac13930bSmikeb 1889ac13930bSmikeb if (status != IXGBE_SUCCESS) 1890ac13930bSmikeb return status; 1891ac13930bSmikeb 1892ac13930bSmikeb reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 1893ac13930bSmikeb 1894d7a8f955Sjmatthew status = hw->phy.ops.write_reg(hw, 1895d7a8f955Sjmatthew IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 1896ac13930bSmikeb IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); 1897ac13930bSmikeb 1898ac13930bSmikeb if (status != IXGBE_SUCCESS) 1899ac13930bSmikeb return status; 1900d7a8f955Sjmatthew } 1901ac13930bSmikeb 1902d7a8f955Sjmatthew /* Enable high temperature failure and global fault alarms */ 1903ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 1904ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1905ac13930bSmikeb ®); 1906ac13930bSmikeb 1907ac13930bSmikeb if (status != IXGBE_SUCCESS) 1908ac13930bSmikeb return status; 1909ac13930bSmikeb 1910d7a8f955Sjmatthew reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | 1911d7a8f955Sjmatthew IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); 1912ac13930bSmikeb 1913ac13930bSmikeb status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 1914ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1915ac13930bSmikeb reg); 1916ac13930bSmikeb 1917ac13930bSmikeb if (status != IXGBE_SUCCESS) 1918ac13930bSmikeb return status; 1919ac13930bSmikeb 1920ac13930bSmikeb /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 1921ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 1922ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1923ac13930bSmikeb ®); 1924ac13930bSmikeb 1925ac13930bSmikeb if (status != IXGBE_SUCCESS) 1926ac13930bSmikeb return status; 1927ac13930bSmikeb 1928ac13930bSmikeb reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1929ac13930bSmikeb IXGBE_MDIO_GLOBAL_ALARM_1_INT); 1930ac13930bSmikeb 1931ac13930bSmikeb status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 1932ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1933ac13930bSmikeb reg); 1934ac13930bSmikeb 1935ac13930bSmikeb if (status != IXGBE_SUCCESS) 1936ac13930bSmikeb return status; 1937ac13930bSmikeb 1938ac13930bSmikeb /* Enable chip-wide vendor alarm */ 1939ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 1940ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1941ac13930bSmikeb ®); 1942ac13930bSmikeb 1943ac13930bSmikeb if (status != IXGBE_SUCCESS) 1944ac13930bSmikeb return status; 1945ac13930bSmikeb 1946ac13930bSmikeb reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 1947ac13930bSmikeb 1948ac13930bSmikeb status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 1949ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1950ac13930bSmikeb reg); 1951ac13930bSmikeb 1952ac13930bSmikeb return status; 1953ac13930bSmikeb } 1954ac13930bSmikeb 1955ac13930bSmikeb /** 1956ac13930bSmikeb * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 1957ac13930bSmikeb * @hw: pointer to hardware structure 1958ac13930bSmikeb * @speed: link speed 1959ac13930bSmikeb * 1960ac13930bSmikeb * Configures the integrated KR PHY. 1961ac13930bSmikeb **/ 1962ac13930bSmikeb int32_t ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 1963ac13930bSmikeb ixgbe_link_speed speed) 1964ac13930bSmikeb { 1965ac13930bSmikeb int32_t status; 1966ac13930bSmikeb uint32_t reg_val; 1967ac13930bSmikeb 1968d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 1969ac13930bSmikeb IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1970ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 1971ac13930bSmikeb if (status) 1972ac13930bSmikeb return status; 1973ac13930bSmikeb 1974ac13930bSmikeb reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1975ac13930bSmikeb reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 1976ac13930bSmikeb IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 1977ac13930bSmikeb 1978ac13930bSmikeb /* Advertise 10G support. */ 1979ac13930bSmikeb if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1980ac13930bSmikeb reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 1981ac13930bSmikeb 1982ac13930bSmikeb /* Advertise 1G support. */ 1983ac13930bSmikeb if (speed & IXGBE_LINK_SPEED_1GB_FULL) 1984ac13930bSmikeb reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 1985ac13930bSmikeb 1986d7a8f955Sjmatthew status = hw->mac.ops.write_iosf_sb_reg(hw, 1987ac13930bSmikeb IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1988ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 1989ac13930bSmikeb 1990d7a8f955Sjmatthew if (hw->mac.type == ixgbe_mac_X550EM_a) { 1991d7a8f955Sjmatthew /* Set lane mode to KR auto negotiation */ 1992d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 1993d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 1994d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 1995d7a8f955Sjmatthew 1996d7a8f955Sjmatthew if (status) 1997ac13930bSmikeb return status; 1998d7a8f955Sjmatthew 1999d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 2000d7a8f955Sjmatthew reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; 2001d7a8f955Sjmatthew reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 2002d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 2003d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 2004d7a8f955Sjmatthew 2005d7a8f955Sjmatthew status = hw->mac.ops.write_iosf_sb_reg(hw, 2006d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2007d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2008d7a8f955Sjmatthew } 2009d7a8f955Sjmatthew 2010d7a8f955Sjmatthew return ixgbe_restart_an_internal_phy_x550em(hw); 2011d7a8f955Sjmatthew } 2012d7a8f955Sjmatthew 2013d7a8f955Sjmatthew /** 2014d7a8f955Sjmatthew * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs 2015d7a8f955Sjmatthew * @hw: pointer to hardware structure 2016d7a8f955Sjmatthew */ 2017d7a8f955Sjmatthew int32_t ixgbe_reset_phy_fw(struct ixgbe_hw *hw) 2018d7a8f955Sjmatthew { 2019d7a8f955Sjmatthew uint32_t store[FW_PHY_ACT_DATA_COUNT] = { 0 }; 2020d7a8f955Sjmatthew int32_t rc; 2021d7a8f955Sjmatthew 2022d7a8f955Sjmatthew if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) 2023d7a8f955Sjmatthew return IXGBE_SUCCESS; 2024d7a8f955Sjmatthew 2025d7a8f955Sjmatthew rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store); 2026d7a8f955Sjmatthew if (rc) 2027d7a8f955Sjmatthew return rc; 2028d7a8f955Sjmatthew memset(store, 0, sizeof(store)); 2029d7a8f955Sjmatthew 2030d7a8f955Sjmatthew rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store); 2031d7a8f955Sjmatthew if (rc) 2032d7a8f955Sjmatthew return rc; 2033d7a8f955Sjmatthew 2034d7a8f955Sjmatthew return ixgbe_setup_fw_link(hw); 2035d7a8f955Sjmatthew } 2036d7a8f955Sjmatthew 2037d7a8f955Sjmatthew /** 2038d7a8f955Sjmatthew * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp 2039d7a8f955Sjmatthew * @hw: pointer to hardware structure 2040d7a8f955Sjmatthew */ 2041d7a8f955Sjmatthew int32_t ixgbe_check_overtemp_fw(struct ixgbe_hw *hw) 2042d7a8f955Sjmatthew { 2043d7a8f955Sjmatthew uint32_t store[FW_PHY_ACT_DATA_COUNT] = { 0 }; 2044d7a8f955Sjmatthew int32_t rc; 2045d7a8f955Sjmatthew 2046d7a8f955Sjmatthew rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store); 2047d7a8f955Sjmatthew if (rc) 2048d7a8f955Sjmatthew return rc; 2049d7a8f955Sjmatthew 2050d7a8f955Sjmatthew if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) { 2051d7a8f955Sjmatthew ixgbe_shutdown_fw_phy(hw); 2052d7a8f955Sjmatthew return IXGBE_ERR_OVERTEMP; 2053d7a8f955Sjmatthew } 2054d7a8f955Sjmatthew return IXGBE_SUCCESS; 2055d7a8f955Sjmatthew } 2056d7a8f955Sjmatthew 2057d7a8f955Sjmatthew /** 2058d7a8f955Sjmatthew * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register 2059d7a8f955Sjmatthew * @hw: pointer to hardware structure 2060d7a8f955Sjmatthew * 2061d7a8f955Sjmatthew * Read NW_MNG_IF_SEL register and save field values, and check for valid field 2062d7a8f955Sjmatthew * values. 2063d7a8f955Sjmatthew **/ 2064d7a8f955Sjmatthew int32_t ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) 2065d7a8f955Sjmatthew { 2066d7a8f955Sjmatthew /* Save NW management interface connected on board. This is used 2067d7a8f955Sjmatthew * to determine internal PHY mode. 2068d7a8f955Sjmatthew */ 2069d7a8f955Sjmatthew hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 2070d7a8f955Sjmatthew 2071d7a8f955Sjmatthew /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set 2072d7a8f955Sjmatthew * PHY address. This register field was has only been used for X552. 2073d7a8f955Sjmatthew */ 2074d7a8f955Sjmatthew if (hw->mac.type == ixgbe_mac_X550EM_a && 2075d7a8f955Sjmatthew hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) { 2076d7a8f955Sjmatthew hw->phy.addr = (hw->phy.nw_mng_if_sel & 2077d7a8f955Sjmatthew IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> 2078d7a8f955Sjmatthew IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; 2079d7a8f955Sjmatthew } 2080d7a8f955Sjmatthew 2081d7a8f955Sjmatthew return IXGBE_SUCCESS; 2082ac13930bSmikeb } 2083ac13930bSmikeb 2084ac13930bSmikeb /** 2085ac13930bSmikeb * ixgbe_init_phy_ops_X550em - PHY/SFP specific init 2086ac13930bSmikeb * @hw: pointer to hardware structure 2087ac13930bSmikeb * 2088ac13930bSmikeb * Initialize any function pointers that were not able to be 2089ac13930bSmikeb * set during init_shared_code because the PHY/SFP type was 2090ac13930bSmikeb * not known. Perform the SFP init if necessary. 2091ac13930bSmikeb */ 2092ac13930bSmikeb int32_t ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 2093ac13930bSmikeb { 2094ac13930bSmikeb struct ixgbe_phy_info *phy = &hw->phy; 2095ac13930bSmikeb int32_t ret_val; 2096ac13930bSmikeb 2097ac13930bSmikeb DEBUGFUNC("ixgbe_init_phy_ops_X550em"); 2098ac13930bSmikeb 2099ac13930bSmikeb hw->mac.ops.set_lan_id(hw); 2100d7a8f955Sjmatthew ixgbe_read_mng_if_sel_x550em(hw); 2101ac13930bSmikeb 2102ac13930bSmikeb if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 2103ac13930bSmikeb phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 2104ac13930bSmikeb ixgbe_setup_mux_ctl(hw); 2105457e2542Sderaadt phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em; 21067042a378Sderaadt } 21077042a378Sderaadt 2108d7a8f955Sjmatthew switch (hw->device_id) { 2109d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T: 2110d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T_L: 2111d7a8f955Sjmatthew phy->ops.read_reg_mdi = NULL; 2112d7a8f955Sjmatthew phy->ops.write_reg_mdi = NULL; 2113d7a8f955Sjmatthew hw->phy.ops.read_reg = NULL; 2114d7a8f955Sjmatthew hw->phy.ops.write_reg = NULL; 2115d7a8f955Sjmatthew phy->ops.check_overtemp = ixgbe_check_overtemp_fw; 2116d7a8f955Sjmatthew if (hw->bus.lan_id) 2117d7a8f955Sjmatthew hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; 2118d7a8f955Sjmatthew else 2119d7a8f955Sjmatthew hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM; 2120d7a8f955Sjmatthew 2121d7a8f955Sjmatthew break; 2122d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_10G_T: 2123d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_SFP: 2124d7a8f955Sjmatthew hw->phy.ops.read_reg = ixgbe_read_phy_reg_x550a; 2125d7a8f955Sjmatthew hw->phy.ops.write_reg = ixgbe_write_phy_reg_x550a; 2126d7a8f955Sjmatthew if (hw->bus.lan_id) 2127d7a8f955Sjmatthew hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; 2128d7a8f955Sjmatthew else 2129d7a8f955Sjmatthew hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM; 2130d7a8f955Sjmatthew break; 2131d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_SFP: 2132d7a8f955Sjmatthew /* set up for CS4227 usage */ 2133d7a8f955Sjmatthew hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 2134d7a8f955Sjmatthew break; 2135d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_1G_T: 2136d7a8f955Sjmatthew phy->ops.read_reg_mdi = NULL; 2137d7a8f955Sjmatthew phy->ops.write_reg_mdi = NULL; 2138d7a8f955Sjmatthew default: 2139d7a8f955Sjmatthew break; 2140d7a8f955Sjmatthew } 2141d7a8f955Sjmatthew 2142ac13930bSmikeb /* Identify the PHY or SFP module */ 2143ac13930bSmikeb ret_val = phy->ops.identify(hw); 2144d7a8f955Sjmatthew if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED || 2145d7a8f955Sjmatthew ret_val == IXGBE_ERR_PHY_ADDR_INVALID) 2146ac13930bSmikeb return ret_val; 2147ac13930bSmikeb 2148ac13930bSmikeb /* Setup function pointers based on detected hardware */ 2149ac13930bSmikeb ixgbe_init_mac_link_ops_X550em(hw); 2150ac13930bSmikeb if (phy->sfp_type != ixgbe_sfp_type_unknown) 2151ac13930bSmikeb phy->ops.reset = NULL; 2152ac13930bSmikeb 2153ac13930bSmikeb /* Set functions pointers based on phy type */ 2154ac13930bSmikeb switch (hw->phy.type) { 2155ac13930bSmikeb case ixgbe_phy_x550em_kx4: 2156ac13930bSmikeb phy->ops.setup_link = NULL; 2157ac13930bSmikeb phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 2158ac13930bSmikeb phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 2159ac13930bSmikeb break; 2160ac13930bSmikeb case ixgbe_phy_x550em_kr: 2161ac13930bSmikeb phy->ops.setup_link = ixgbe_setup_kr_x550em; 2162ac13930bSmikeb phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 2163ac13930bSmikeb phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 2164ac13930bSmikeb break; 2165d7a8f955Sjmatthew case ixgbe_phy_ext_1g_t: 2166d7a8f955Sjmatthew /* link is managed by FW */ 2167d7a8f955Sjmatthew phy->ops.setup_link = NULL; 2168d7a8f955Sjmatthew phy->ops.reset = NULL; 2169d7a8f955Sjmatthew break; 2170d7a8f955Sjmatthew case ixgbe_phy_x550em_xfi: 2171d7a8f955Sjmatthew /* link is managed by HW */ 2172d7a8f955Sjmatthew phy->ops.setup_link = NULL; 2173d7a8f955Sjmatthew phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 2174d7a8f955Sjmatthew phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 2175d7a8f955Sjmatthew break; 2176ac13930bSmikeb case ixgbe_phy_x550em_ext_t: 2177ac13930bSmikeb /* If internal link mode is XFI, then setup iXFI internal link, 2178ac13930bSmikeb * else setup KR now. 2179ac13930bSmikeb */ 2180ac13930bSmikeb phy->ops.setup_internal_link = 2181ac13930bSmikeb ixgbe_setup_internal_phy_t_x550em; 2182d7a8f955Sjmatthew 2183d7a8f955Sjmatthew /* setup SW LPLU only for first revision of X550EM_x */ 2184d7a8f955Sjmatthew if ((hw->mac.type == ixgbe_mac_X550EM_x) && 2185d7a8f955Sjmatthew !(IXGBE_FUSES0_REV_MASK & 2186d7a8f955Sjmatthew IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))) 2187d7a8f955Sjmatthew phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; 2188ac13930bSmikeb 2189ac13930bSmikeb phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 2190ac13930bSmikeb phy->ops.reset = ixgbe_reset_phy_t_X550em; 2191ac13930bSmikeb break; 2192d7a8f955Sjmatthew case ixgbe_phy_sgmii: 2193d7a8f955Sjmatthew phy->ops.setup_link = NULL; 2194d7a8f955Sjmatthew break; 2195d7a8f955Sjmatthew case ixgbe_phy_fw: 2196d7a8f955Sjmatthew phy->ops.setup_link = ixgbe_setup_fw_link; 2197d7a8f955Sjmatthew phy->ops.reset = ixgbe_reset_phy_fw; 2198d7a8f955Sjmatthew break; 2199ac13930bSmikeb default: 2200ac13930bSmikeb break; 2201ac13930bSmikeb } 2202ac13930bSmikeb return ret_val; 2203ac13930bSmikeb } 2204ac13930bSmikeb 2205ac13930bSmikeb /** 2206d7a8f955Sjmatthew * ixgbe_set_mdio_speed - Set MDIO clock speed 2207d7a8f955Sjmatthew * @hw: pointer to hardware structure 2208d7a8f955Sjmatthew */ 2209d7a8f955Sjmatthew void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) 2210d7a8f955Sjmatthew { 2211d7a8f955Sjmatthew uint32_t hlreg0; 2212d7a8f955Sjmatthew 2213d7a8f955Sjmatthew switch (hw->device_id) { 2214d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_10G_T: 2215d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_SGMII: 2216d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_SGMII_L: 2217d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_10G_T: 2218d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_SFP: 2219d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_QSFP: 2220d7a8f955Sjmatthew /* Config MDIO clock speed before the first MDIO PHY access */ 2221d7a8f955Sjmatthew hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 2222d7a8f955Sjmatthew hlreg0 &= ~IXGBE_HLREG0_MDCSPD; 2223d7a8f955Sjmatthew IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 2224d7a8f955Sjmatthew break; 2225d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T: 2226d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_1G_T_L: 2227d7a8f955Sjmatthew /* Select fast MDIO clock speed for these devices */ 2228d7a8f955Sjmatthew hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 2229d7a8f955Sjmatthew hlreg0 |= IXGBE_HLREG0_MDCSPD; 2230d7a8f955Sjmatthew IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 2231d7a8f955Sjmatthew break; 2232d7a8f955Sjmatthew default: 2233d7a8f955Sjmatthew break; 2234d7a8f955Sjmatthew } 2235d7a8f955Sjmatthew } 2236d7a8f955Sjmatthew 2237d7a8f955Sjmatthew /** 2238ac13930bSmikeb * ixgbe_reset_hw_X550em - Perform hardware reset 2239ac13930bSmikeb * @hw: pointer to hardware structure 2240ac13930bSmikeb * 2241ac13930bSmikeb * Resets the hardware by resetting the transmit and receive units, masks 2242ac13930bSmikeb * and clears all interrupts, perform a PHY reset, and perform a link (MAC) 2243ac13930bSmikeb * reset. 2244ac13930bSmikeb */ 2245ac13930bSmikeb int32_t ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 2246ac13930bSmikeb { 2247ac13930bSmikeb ixgbe_link_speed link_speed; 2248ac13930bSmikeb int32_t status; 2249ac13930bSmikeb uint32_t ctrl = 0; 2250ac13930bSmikeb uint32_t i; 2251ac13930bSmikeb bool link_up = FALSE; 2252d7a8f955Sjmatthew uint32_t swfw_mask = hw->phy.phy_semaphore_mask; 2253ac13930bSmikeb 2254ac13930bSmikeb DEBUGFUNC("ixgbe_reset_hw_X550em"); 2255ac13930bSmikeb 2256ac13930bSmikeb /* Call adapter stop to disable Tx/Rx and clear interrupts */ 2257ac13930bSmikeb status = hw->mac.ops.stop_adapter(hw); 2258d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) { 2259d7a8f955Sjmatthew DEBUGOUT1("Failed to stop adapter, STATUS = %d\n", status); 2260ac13930bSmikeb return status; 2261d7a8f955Sjmatthew } 2262ac13930bSmikeb /* flush pending Tx transactions */ 2263ac13930bSmikeb ixgbe_clear_tx_pending(hw); 2264ac13930bSmikeb 2265d7a8f955Sjmatthew ixgbe_set_mdio_speed(hw); 2266ac13930bSmikeb 2267ac13930bSmikeb /* PHY ops must be identified and initialized prior to reset */ 2268ac13930bSmikeb status = hw->phy.ops.init(hw); 2269ac13930bSmikeb 2270d7a8f955Sjmatthew if (status) 2271d7a8f955Sjmatthew DEBUGOUT1("Failed to initialize PHY ops, STATUS = %d\n", 2272d7a8f955Sjmatthew status); 2273d7a8f955Sjmatthew 2274d7a8f955Sjmatthew if (status == IXGBE_ERR_SFP_NOT_SUPPORTED || 2275d7a8f955Sjmatthew status == IXGBE_ERR_PHY_ADDR_INVALID) { 2276d7a8f955Sjmatthew DEBUGOUT("Returning from reset HW due to PHY init failure\n"); 2277ac13930bSmikeb return status; 2278d7a8f955Sjmatthew } 2279ac13930bSmikeb 2280ac13930bSmikeb /* start the external PHY */ 2281ac13930bSmikeb if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 2282ac13930bSmikeb status = ixgbe_init_ext_t_x550em(hw); 2283d7a8f955Sjmatthew if (status) { 2284d7a8f955Sjmatthew DEBUGOUT1("Failed to start the external PHY, STATUS = %d\n", 2285d7a8f955Sjmatthew status); 2286ac13930bSmikeb return status; 2287ac13930bSmikeb } 2288d7a8f955Sjmatthew } 2289ac13930bSmikeb 2290ac13930bSmikeb /* Setup SFP module if there is one present. */ 2291ac13930bSmikeb if (hw->phy.sfp_setup_needed) { 2292ac13930bSmikeb status = hw->mac.ops.setup_sfp(hw); 2293ac13930bSmikeb hw->phy.sfp_setup_needed = FALSE; 2294ac13930bSmikeb } 2295ac13930bSmikeb 2296ac13930bSmikeb if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) 2297ac13930bSmikeb return status; 2298ac13930bSmikeb 2299ac13930bSmikeb /* Reset PHY */ 2300d7a8f955Sjmatthew if (!hw->phy.reset_disable && hw->phy.ops.reset) { 2301d7a8f955Sjmatthew if (hw->phy.ops.reset(hw) == IXGBE_ERR_OVERTEMP) 2302d7a8f955Sjmatthew return IXGBE_ERR_OVERTEMP; 2303d7a8f955Sjmatthew } 2304ac13930bSmikeb 2305ac13930bSmikeb mac_reset_top: 2306ac13930bSmikeb /* Issue global reset to the MAC. Needs to be SW reset if link is up. 2307ac13930bSmikeb * If link reset is used when link is up, it might reset the PHY when 2308ac13930bSmikeb * mng is using it. If link is down or the flag to force full link 2309ac13930bSmikeb * reset is set, then perform link reset. 2310ac13930bSmikeb */ 2311ac13930bSmikeb ctrl = IXGBE_CTRL_LNK_RST; 2312ac13930bSmikeb if (!hw->force_full_reset) { 2313ac13930bSmikeb hw->mac.ops.check_link(hw, &link_speed, &link_up, FALSE); 2314ac13930bSmikeb if (link_up) 2315ac13930bSmikeb ctrl = IXGBE_CTRL_RST; 2316ac13930bSmikeb } 2317ac13930bSmikeb 2318d7a8f955Sjmatthew status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); 2319d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) { 2320d7a8f955Sjmatthew ERROR_REPORT2(IXGBE_ERROR_CAUTION, 2321d7a8f955Sjmatthew "semaphore failed with %d", status); 2322d7a8f955Sjmatthew return IXGBE_ERR_SWFW_SYNC; 2323d7a8f955Sjmatthew } 2324ac13930bSmikeb ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 2325ac13930bSmikeb IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 2326ac13930bSmikeb IXGBE_WRITE_FLUSH(hw); 2327d7a8f955Sjmatthew hw->mac.ops.release_swfw_sync(hw, swfw_mask); 2328ac13930bSmikeb 2329ac13930bSmikeb /* Poll for reset bit to self-clear meaning reset is complete */ 2330ac13930bSmikeb for (i = 0; i < 10; i++) { 2331ac13930bSmikeb usec_delay(1); 2332ac13930bSmikeb ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 2333ac13930bSmikeb if (!(ctrl & IXGBE_CTRL_RST_MASK)) 2334ac13930bSmikeb break; 2335ac13930bSmikeb } 2336ac13930bSmikeb 2337ac13930bSmikeb if (ctrl & IXGBE_CTRL_RST_MASK) { 2338ac13930bSmikeb status = IXGBE_ERR_RESET_FAILED; 2339ac13930bSmikeb DEBUGOUT("Reset polling failed to complete.\n"); 2340ac13930bSmikeb } 2341ac13930bSmikeb 2342ac13930bSmikeb msec_delay(50); 2343ac13930bSmikeb 2344ac13930bSmikeb /* Double resets are required for recovery from certain error 2345ac13930bSmikeb * conditions. Between resets, it is necessary to stall to 2346ac13930bSmikeb * allow time for any pending HW events to complete. 2347ac13930bSmikeb */ 2348ac13930bSmikeb if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 2349ac13930bSmikeb hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 2350ac13930bSmikeb goto mac_reset_top; 2351ac13930bSmikeb } 2352ac13930bSmikeb 2353ac13930bSmikeb /* Store the permanent mac address */ 2354ac13930bSmikeb hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 2355ac13930bSmikeb 2356ac13930bSmikeb /* Store MAC address from RAR0, clear receive address registers, and 2357ac13930bSmikeb * clear the multicast table. Also reset num_rar_entries to 128, 2358ac13930bSmikeb * since we modify this value when programming the SAN MAC address. 2359ac13930bSmikeb */ 2360ac13930bSmikeb hw->mac.num_rar_entries = 128; 2361ac13930bSmikeb hw->mac.ops.init_rx_addrs(hw); 2362ac13930bSmikeb 2363d7a8f955Sjmatthew ixgbe_set_mdio_speed(hw); 2364d7a8f955Sjmatthew 2365ac13930bSmikeb if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 2366ac13930bSmikeb ixgbe_setup_mux_ctl(hw); 2367ac13930bSmikeb 2368d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 2369d7a8f955Sjmatthew DEBUGOUT1("Reset HW failed, STATUS = %d\n", status); 2370d7a8f955Sjmatthew 2371ac13930bSmikeb return status; 2372ac13930bSmikeb } 2373ac13930bSmikeb 2374ac13930bSmikeb /** 2375ac13930bSmikeb * ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 2376ac13930bSmikeb * @hw: pointer to hardware structure 2377ac13930bSmikeb */ 2378ac13930bSmikeb int32_t ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 2379ac13930bSmikeb { 2380ac13930bSmikeb uint32_t status; 2381ac13930bSmikeb uint16_t reg; 2382ac13930bSmikeb 2383ac13930bSmikeb status = hw->phy.ops.read_reg(hw, 2384ac13930bSmikeb IXGBE_MDIO_TX_VENDOR_ALARMS_3, 2385ac13930bSmikeb IXGBE_MDIO_PMA_PMD_DEV_TYPE, 2386ac13930bSmikeb ®); 2387ac13930bSmikeb 2388ac13930bSmikeb if (status != IXGBE_SUCCESS) 2389ac13930bSmikeb return status; 2390ac13930bSmikeb 2391ac13930bSmikeb /* If PHY FW reset completed bit is set then this is the first 2392ac13930bSmikeb * SW instance after a power on so the PHY FW must be un-stalled. 2393ac13930bSmikeb */ 2394ac13930bSmikeb if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 2395ac13930bSmikeb status = hw->phy.ops.read_reg(hw, 2396ac13930bSmikeb IXGBE_MDIO_GLOBAL_RES_PR_10, 2397ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 2398ac13930bSmikeb ®); 2399ac13930bSmikeb 2400ac13930bSmikeb if (status != IXGBE_SUCCESS) 2401ac13930bSmikeb return status; 2402ac13930bSmikeb 2403ac13930bSmikeb reg &= ~IXGBE_MDIO_POWER_UP_STALL; 2404ac13930bSmikeb 2405ac13930bSmikeb status = hw->phy.ops.write_reg(hw, 2406ac13930bSmikeb IXGBE_MDIO_GLOBAL_RES_PR_10, 2407ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 2408ac13930bSmikeb reg); 2409ac13930bSmikeb 2410ac13930bSmikeb if (status != IXGBE_SUCCESS) 2411ac13930bSmikeb return status; 2412ac13930bSmikeb } 2413ac13930bSmikeb 2414ac13930bSmikeb return status; 2415ac13930bSmikeb } 2416ac13930bSmikeb 2417ac13930bSmikeb /** 2418ac13930bSmikeb * ixgbe_setup_kr_x550em - Configure the KR PHY. 2419ac13930bSmikeb * @hw: pointer to hardware structure 2420ac13930bSmikeb **/ 2421ac13930bSmikeb int32_t ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 2422ac13930bSmikeb { 2423d7a8f955Sjmatthew /* leave link alone for 2.5G */ 2424d7a8f955Sjmatthew if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) 2425d7a8f955Sjmatthew return IXGBE_SUCCESS; 2426d7a8f955Sjmatthew 2427d7a8f955Sjmatthew if (ixgbe_check_reset_blocked(hw)) 2428d7a8f955Sjmatthew return 0; 2429d7a8f955Sjmatthew 2430ac13930bSmikeb return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 2431ac13930bSmikeb } 2432ac13930bSmikeb 2433ac13930bSmikeb /** 2434ac13930bSmikeb * ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP 2435ac13930bSmikeb * @hw: pointer to hardware structure 2436d7a8f955Sjmatthew * @speed: new link speed 2437d7a8f955Sjmatthew * @autoneg_wait_to_complete: unused 2438ac13930bSmikeb * 2439ac13930bSmikeb * Configure the external PHY and the integrated KR PHY for SFP support. 2440ac13930bSmikeb **/ 2441ac13930bSmikeb int32_t ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, 2442ac13930bSmikeb ixgbe_link_speed speed, 2443ac13930bSmikeb bool autoneg_wait_to_complete) 2444ac13930bSmikeb { 2445ac13930bSmikeb int32_t ret_val; 2446ac13930bSmikeb uint16_t reg_slice, reg_val; 2447ac13930bSmikeb bool setup_linear = FALSE; 2448ac13930bSmikeb 2449ac13930bSmikeb /* Check if SFP module is supported and linear */ 2450ac13930bSmikeb ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 2451ac13930bSmikeb 2452ac13930bSmikeb /* If no SFP module present, then return success. Return success since 2453ac13930bSmikeb * there is no reason to configure CS4227 and SFP not present error is 2454ac13930bSmikeb * not excepted in the setup MAC link flow. 2455ac13930bSmikeb */ 2456ac13930bSmikeb if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) 2457ac13930bSmikeb return IXGBE_SUCCESS; 2458ac13930bSmikeb 2459ac13930bSmikeb if (ret_val != IXGBE_SUCCESS) 2460ac13930bSmikeb return ret_val; 2461ac13930bSmikeb 2462ac13930bSmikeb /* Configure internal PHY for KR/KX. */ 2463ac13930bSmikeb ixgbe_setup_kr_speed_x550em(hw, speed); 2464ac13930bSmikeb 2465ac13930bSmikeb /* Configure CS4227 LINE side to proper mode. */ 2466ac13930bSmikeb reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + 2467ac13930bSmikeb (hw->bus.lan_id << 12); 2468ac13930bSmikeb if (setup_linear) 2469ac13930bSmikeb reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; 2470ac13930bSmikeb else 2471ac13930bSmikeb reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; 2472d7a8f955Sjmatthew ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, 2473d7a8f955Sjmatthew reg_val); 2474d7a8f955Sjmatthew return ret_val; 2475d7a8f955Sjmatthew } 2476d7a8f955Sjmatthew 2477d7a8f955Sjmatthew /** 2478d7a8f955Sjmatthew * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode 2479d7a8f955Sjmatthew * @hw: pointer to hardware structure 2480d7a8f955Sjmatthew * @speed: the link speed to force 2481d7a8f955Sjmatthew * 2482d7a8f955Sjmatthew * Configures the integrated PHY for native SFI mode. Used to connect the 2483d7a8f955Sjmatthew * internal PHY directly to an SFP cage, without autonegotiation. 2484d7a8f955Sjmatthew **/ 2485d7a8f955Sjmatthew int32_t ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 2486d7a8f955Sjmatthew { 2487d7a8f955Sjmatthew struct ixgbe_mac_info *mac = &hw->mac; 2488d7a8f955Sjmatthew int32_t status; 2489d7a8f955Sjmatthew uint32_t reg_val; 2490d7a8f955Sjmatthew 2491d7a8f955Sjmatthew /* Disable all AN and force speed to 10G Serial. */ 2492d7a8f955Sjmatthew status = mac->ops.read_iosf_sb_reg(hw, 2493d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2494d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2495d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 2496d7a8f955Sjmatthew return status; 2497d7a8f955Sjmatthew 2498d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; 2499d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; 2500d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; 2501d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; 2502d7a8f955Sjmatthew 2503d7a8f955Sjmatthew /* Select forced link speed for internal PHY. */ 2504d7a8f955Sjmatthew switch (*speed) { 2505d7a8f955Sjmatthew case IXGBE_LINK_SPEED_10GB_FULL: 2506d7a8f955Sjmatthew reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G; 2507d7a8f955Sjmatthew break; 2508d7a8f955Sjmatthew case IXGBE_LINK_SPEED_1GB_FULL: 2509d7a8f955Sjmatthew reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; 2510d7a8f955Sjmatthew break; 2511d7a8f955Sjmatthew default: 2512d7a8f955Sjmatthew /* Other link speeds are not supported by internal PHY. */ 2513d7a8f955Sjmatthew return IXGBE_ERR_LINK_SETUP; 2514d7a8f955Sjmatthew } 2515d7a8f955Sjmatthew 2516d7a8f955Sjmatthew status = mac->ops.write_iosf_sb_reg(hw, 2517d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2518d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2519d7a8f955Sjmatthew 2520d7a8f955Sjmatthew /* Toggle port SW reset by AN reset. */ 2521d7a8f955Sjmatthew status = ixgbe_restart_an_internal_phy_x550em(hw); 2522d7a8f955Sjmatthew 2523d7a8f955Sjmatthew return status; 2524d7a8f955Sjmatthew } 2525d7a8f955Sjmatthew 2526d7a8f955Sjmatthew /** 2527d7a8f955Sjmatthew * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP 2528d7a8f955Sjmatthew * @hw: pointer to hardware structure 2529d7a8f955Sjmatthew * @speed: new link speed 2530d7a8f955Sjmatthew * @autoneg_wait_to_complete: unused 2531d7a8f955Sjmatthew * 25324b1a56afSjsg * Configure the integrated PHY for SFP support. 2533d7a8f955Sjmatthew **/ 2534d7a8f955Sjmatthew int32_t ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, 2535d7a8f955Sjmatthew ixgbe_link_speed speed, 2536d7a8f955Sjmatthew bool autoneg_wait_to_complete) 2537d7a8f955Sjmatthew { 2538d7a8f955Sjmatthew int32_t ret_val; 2539d7a8f955Sjmatthew uint16_t reg_phy_ext; 2540d7a8f955Sjmatthew bool setup_linear = FALSE; 2541d7a8f955Sjmatthew uint32_t reg_slice, reg_phy_int, slice_offset; 2542d7a8f955Sjmatthew 2543d7a8f955Sjmatthew /* Check if SFP module is supported and linear */ 2544d7a8f955Sjmatthew ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); 2545d7a8f955Sjmatthew 2546d7a8f955Sjmatthew /* If no SFP module present, then return success. Return success since 2547d7a8f955Sjmatthew * SFP not present error is not excepted in the setup MAC link flow. 2548d7a8f955Sjmatthew */ 2549d7a8f955Sjmatthew if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) 2550d7a8f955Sjmatthew return IXGBE_SUCCESS; 2551d7a8f955Sjmatthew 2552d7a8f955Sjmatthew if (ret_val != IXGBE_SUCCESS) 2553d7a8f955Sjmatthew return ret_val; 2554d7a8f955Sjmatthew 2555d7a8f955Sjmatthew if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) { 2556d7a8f955Sjmatthew /* Configure internal PHY for native SFI based on module type */ 2557d7a8f955Sjmatthew ret_val = hw->mac.ops.read_iosf_sb_reg(hw, 2558d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2559d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int); 2560d7a8f955Sjmatthew 2561d7a8f955Sjmatthew if (ret_val != IXGBE_SUCCESS) 2562d7a8f955Sjmatthew return ret_val; 2563d7a8f955Sjmatthew 2564d7a8f955Sjmatthew reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA; 2565d7a8f955Sjmatthew if (!setup_linear) 2566d7a8f955Sjmatthew reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR; 2567d7a8f955Sjmatthew 2568d7a8f955Sjmatthew ret_val = hw->mac.ops.write_iosf_sb_reg(hw, 2569d7a8f955Sjmatthew IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), 2570d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int); 2571d7a8f955Sjmatthew 2572d7a8f955Sjmatthew if (ret_val != IXGBE_SUCCESS) 2573d7a8f955Sjmatthew return ret_val; 2574d7a8f955Sjmatthew 2575d7a8f955Sjmatthew /* Setup SFI internal link. */ 2576d7a8f955Sjmatthew ret_val = ixgbe_setup_sfi_x550a(hw, &speed); 2577d7a8f955Sjmatthew } else { 2578d7a8f955Sjmatthew /* Configure internal PHY for KR/KX. */ 2579d7a8f955Sjmatthew ixgbe_setup_kr_speed_x550em(hw, speed); 2580d7a8f955Sjmatthew 2581d7a8f955Sjmatthew if (hw->phy.addr == 0x0 || hw->phy.addr == 0xFFFF) { 2582d7a8f955Sjmatthew /* Find Address */ 2583d7a8f955Sjmatthew DEBUGOUT("Invalid NW_MNG_IF_SEL.MDIO_PHY_ADD value\n"); 2584d7a8f955Sjmatthew return IXGBE_ERR_PHY_ADDR_INVALID; 2585d7a8f955Sjmatthew } 2586d7a8f955Sjmatthew 2587d7a8f955Sjmatthew /* Get external PHY SKU id */ 2588d7a8f955Sjmatthew ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU, 2589d7a8f955Sjmatthew IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 2590d7a8f955Sjmatthew 2591d7a8f955Sjmatthew if (ret_val != IXGBE_SUCCESS) 2592d7a8f955Sjmatthew return ret_val; 2593d7a8f955Sjmatthew 2594d7a8f955Sjmatthew /* When configuring quad port CS4223, the MAC instance is part 2595d7a8f955Sjmatthew * of the slice offset. 2596d7a8f955Sjmatthew */ 2597d7a8f955Sjmatthew if (reg_phy_ext == IXGBE_CS4223_SKU_ID) 2598d7a8f955Sjmatthew slice_offset = (hw->bus.lan_id + 2599d7a8f955Sjmatthew (hw->bus.instance_id << 1)) << 12; 2600d7a8f955Sjmatthew else 2601d7a8f955Sjmatthew slice_offset = hw->bus.lan_id << 12; 2602d7a8f955Sjmatthew 2603d7a8f955Sjmatthew /* Configure CS4227/CS4223 LINE side to proper mode. */ 2604d7a8f955Sjmatthew reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; 2605d7a8f955Sjmatthew 2606d7a8f955Sjmatthew ret_val = hw->phy.ops.read_reg(hw, reg_slice, 2607d7a8f955Sjmatthew IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 2608d7a8f955Sjmatthew 2609d7a8f955Sjmatthew if (ret_val != IXGBE_SUCCESS) 2610d7a8f955Sjmatthew return ret_val; 2611d7a8f955Sjmatthew 2612d7a8f955Sjmatthew reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) | 2613d7a8f955Sjmatthew (IXGBE_CS4227_EDC_MODE_SR << 1)); 2614d7a8f955Sjmatthew 2615d7a8f955Sjmatthew if (setup_linear) 2616d7a8f955Sjmatthew reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; 2617d7a8f955Sjmatthew else 2618d7a8f955Sjmatthew reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; 2619d7a8f955Sjmatthew ret_val = hw->phy.ops.write_reg(hw, reg_slice, 2620d7a8f955Sjmatthew IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext); 2621d7a8f955Sjmatthew 2622d7a8f955Sjmatthew /* Flush previous write with a read */ 2623d7a8f955Sjmatthew ret_val = hw->phy.ops.read_reg(hw, reg_slice, 2624d7a8f955Sjmatthew IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); 2625ac13930bSmikeb } 2626ac13930bSmikeb return ret_val; 2627ac13930bSmikeb } 2628ac13930bSmikeb 2629ac13930bSmikeb /** 2630d7a8f955Sjmatthew * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration 2631d7a8f955Sjmatthew * @hw: pointer to hardware structure 2632d7a8f955Sjmatthew * 2633d7a8f955Sjmatthew * iXfI configuration needed for ixgbe_mac_X550EM_x devices. 2634d7a8f955Sjmatthew **/ 2635d7a8f955Sjmatthew int32_t ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) 2636d7a8f955Sjmatthew { 2637d7a8f955Sjmatthew struct ixgbe_mac_info *mac = &hw->mac; 2638d7a8f955Sjmatthew int32_t status; 2639d7a8f955Sjmatthew uint32_t reg_val; 2640d7a8f955Sjmatthew 2641d7a8f955Sjmatthew /* Disable training protocol FSM. */ 2642d7a8f955Sjmatthew status = mac->ops.read_iosf_sb_reg(hw, 2643d7a8f955Sjmatthew IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 2644d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2645d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 2646d7a8f955Sjmatthew return status; 2647d7a8f955Sjmatthew reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 2648d7a8f955Sjmatthew status = mac->ops.write_iosf_sb_reg(hw, 2649d7a8f955Sjmatthew IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 2650d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2651d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 2652d7a8f955Sjmatthew return status; 2653d7a8f955Sjmatthew 2654d7a8f955Sjmatthew /* Disable Flex from training TXFFE. */ 2655d7a8f955Sjmatthew status = mac->ops.read_iosf_sb_reg(hw, 2656d7a8f955Sjmatthew IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 2657d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2658d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 2659d7a8f955Sjmatthew return status; 2660d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 2661d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 2662d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 2663d7a8f955Sjmatthew status = mac->ops.write_iosf_sb_reg(hw, 2664d7a8f955Sjmatthew IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 2665d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2666d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 2667d7a8f955Sjmatthew return status; 2668d7a8f955Sjmatthew status = mac->ops.read_iosf_sb_reg(hw, 2669d7a8f955Sjmatthew IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 2670d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2671d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 2672d7a8f955Sjmatthew return status; 2673d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 2674d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 2675d7a8f955Sjmatthew reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 2676d7a8f955Sjmatthew status = mac->ops.write_iosf_sb_reg(hw, 2677d7a8f955Sjmatthew IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 2678d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2679d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 2680d7a8f955Sjmatthew return status; 2681d7a8f955Sjmatthew 2682d7a8f955Sjmatthew /* Enable override for coefficients. */ 2683d7a8f955Sjmatthew status = mac->ops.read_iosf_sb_reg(hw, 2684d7a8f955Sjmatthew IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 2685d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2686d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 2687d7a8f955Sjmatthew return status; 2688d7a8f955Sjmatthew reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 2689d7a8f955Sjmatthew reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 2690d7a8f955Sjmatthew reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 2691d7a8f955Sjmatthew reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 2692d7a8f955Sjmatthew status = mac->ops.write_iosf_sb_reg(hw, 2693d7a8f955Sjmatthew IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 2694d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2695d7a8f955Sjmatthew return status; 2696d7a8f955Sjmatthew } 2697d7a8f955Sjmatthew 2698d7a8f955Sjmatthew /** 2699ac13930bSmikeb * ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 2700ac13930bSmikeb * @hw: pointer to hardware structure 2701ac13930bSmikeb * @speed: the link speed to force 2702ac13930bSmikeb * 2703ac13930bSmikeb * Configures the integrated KR PHY to use iXFI mode. Used to connect an 2704ac13930bSmikeb * internal and external PHY at a specific speed, without autonegotiation. 2705ac13930bSmikeb **/ 2706ac13930bSmikeb int32_t ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 2707ac13930bSmikeb { 2708d7a8f955Sjmatthew struct ixgbe_mac_info *mac = &hw->mac; 2709ac13930bSmikeb int32_t status; 2710ac13930bSmikeb uint32_t reg_val; 2711ac13930bSmikeb 2712d7a8f955Sjmatthew /* iXFI is only supported with X552 */ 2713d7a8f955Sjmatthew if (mac->type != ixgbe_mac_X550EM_x) 2714d7a8f955Sjmatthew return IXGBE_ERR_LINK_SETUP; 2715d7a8f955Sjmatthew 2716ac13930bSmikeb /* Disable AN and force speed to 10G Serial. */ 2717d7a8f955Sjmatthew status = mac->ops.read_iosf_sb_reg(hw, 2718ac13930bSmikeb IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2719ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2720ac13930bSmikeb if (status != IXGBE_SUCCESS) 2721ac13930bSmikeb return status; 2722ac13930bSmikeb 2723ac13930bSmikeb reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 2724ac13930bSmikeb reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 2725ac13930bSmikeb 2726ac13930bSmikeb /* Select forced link speed for internal PHY. */ 2727ac13930bSmikeb switch (*speed) { 2728ac13930bSmikeb case IXGBE_LINK_SPEED_10GB_FULL: 2729ac13930bSmikeb reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 2730ac13930bSmikeb break; 2731ac13930bSmikeb case IXGBE_LINK_SPEED_1GB_FULL: 2732ac13930bSmikeb reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 2733ac13930bSmikeb break; 2734ac13930bSmikeb default: 2735ac13930bSmikeb /* Other link speeds are not supported by internal KR PHY. */ 2736ac13930bSmikeb return IXGBE_ERR_LINK_SETUP; 2737ac13930bSmikeb } 2738ac13930bSmikeb 2739d7a8f955Sjmatthew status = mac->ops.write_iosf_sb_reg(hw, 2740ac13930bSmikeb IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2741ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2742ac13930bSmikeb if (status != IXGBE_SUCCESS) 2743ac13930bSmikeb return status; 2744ac13930bSmikeb 2745d7a8f955Sjmatthew /* Additional configuration needed for x550em_x */ 2746d7a8f955Sjmatthew if (hw->mac.type == ixgbe_mac_X550EM_x) { 2747d7a8f955Sjmatthew status = ixgbe_setup_ixfi_x550em_x(hw); 2748ac13930bSmikeb if (status != IXGBE_SUCCESS) 2749ac13930bSmikeb return status; 2750d7a8f955Sjmatthew } 2751ac13930bSmikeb 2752ac13930bSmikeb /* Toggle port SW reset by AN reset. */ 2753d7a8f955Sjmatthew status = ixgbe_restart_an_internal_phy_x550em(hw); 2754ac13930bSmikeb 2755ac13930bSmikeb return status; 2756ac13930bSmikeb } 2757ac13930bSmikeb 2758ac13930bSmikeb /** 2759ac13930bSmikeb * ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 2760ac13930bSmikeb * @hw: address of hardware structure 2761ac13930bSmikeb * @link_up: address of boolean to indicate link status 2762ac13930bSmikeb * 2763ac13930bSmikeb * Returns error code if unable to get link status. 2764ac13930bSmikeb */ 2765ac13930bSmikeb int32_t ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 2766ac13930bSmikeb { 2767ac13930bSmikeb uint32_t ret; 2768ac13930bSmikeb uint16_t autoneg_status; 2769ac13930bSmikeb 2770ac13930bSmikeb *link_up = FALSE; 2771ac13930bSmikeb 2772ac13930bSmikeb /* read this twice back to back to indicate current status */ 2773ac13930bSmikeb ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 2774ac13930bSmikeb IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 2775ac13930bSmikeb &autoneg_status); 2776ac13930bSmikeb if (ret != IXGBE_SUCCESS) 2777ac13930bSmikeb return ret; 2778ac13930bSmikeb 2779ac13930bSmikeb ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 2780ac13930bSmikeb IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 2781ac13930bSmikeb &autoneg_status); 2782ac13930bSmikeb if (ret != IXGBE_SUCCESS) 2783ac13930bSmikeb return ret; 2784ac13930bSmikeb 2785ac13930bSmikeb *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 2786ac13930bSmikeb 2787ac13930bSmikeb return IXGBE_SUCCESS; 2788ac13930bSmikeb } 2789ac13930bSmikeb 2790ac13930bSmikeb /** 2791ac13930bSmikeb * ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 2792ac13930bSmikeb * @hw: point to hardware structure 2793ac13930bSmikeb * 2794ac13930bSmikeb * Configures the link between the integrated KR PHY and the external X557 PHY 2795ac13930bSmikeb * The driver will call this function when it gets a link status change 2796ac13930bSmikeb * interrupt from the X557 PHY. This function configures the link speed 2797ac13930bSmikeb * between the PHYs to match the link speed of the BASE-T link. 2798ac13930bSmikeb * 2799ac13930bSmikeb * A return of a non-zero value indicates an error, and the base driver should 2800ac13930bSmikeb * not report link up. 2801ac13930bSmikeb */ 2802ac13930bSmikeb int32_t ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 2803ac13930bSmikeb { 2804ac13930bSmikeb ixgbe_link_speed force_speed; 2805ac13930bSmikeb bool link_up; 2806ac13930bSmikeb uint32_t status; 2807ac13930bSmikeb uint16_t speed; 2808ac13930bSmikeb 2809ac13930bSmikeb if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 2810ac13930bSmikeb return IXGBE_ERR_CONFIG; 2811ac13930bSmikeb 2812d7a8f955Sjmatthew if (hw->mac.type == ixgbe_mac_X550EM_x && 2813d7a8f955Sjmatthew !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 2814d7a8f955Sjmatthew /* If link is down, there is no setup necessary so return */ 2815ac13930bSmikeb status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 2816ac13930bSmikeb if (status != IXGBE_SUCCESS) 2817ac13930bSmikeb return status; 2818ac13930bSmikeb 2819ac13930bSmikeb if (!link_up) 2820ac13930bSmikeb return IXGBE_SUCCESS; 2821ac13930bSmikeb 2822d7a8f955Sjmatthew status = hw->phy.ops.read_reg(hw, 2823d7a8f955Sjmatthew IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 2824ac13930bSmikeb IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 2825ac13930bSmikeb &speed); 2826ac13930bSmikeb if (status != IXGBE_SUCCESS) 2827ac13930bSmikeb return status; 2828ac13930bSmikeb 2829d7a8f955Sjmatthew /* If link is still down - no setup is required so return */ 2830ac13930bSmikeb status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 2831ac13930bSmikeb if (status != IXGBE_SUCCESS) 2832ac13930bSmikeb return status; 2833ac13930bSmikeb if (!link_up) 2834ac13930bSmikeb return IXGBE_SUCCESS; 2835ac13930bSmikeb 2836ac13930bSmikeb /* clear everything but the speed and duplex bits */ 2837ac13930bSmikeb speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 2838ac13930bSmikeb 2839ac13930bSmikeb switch (speed) { 2840ac13930bSmikeb case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 2841ac13930bSmikeb force_speed = IXGBE_LINK_SPEED_10GB_FULL; 2842ac13930bSmikeb break; 2843ac13930bSmikeb case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 2844ac13930bSmikeb force_speed = IXGBE_LINK_SPEED_1GB_FULL; 2845ac13930bSmikeb break; 2846ac13930bSmikeb default: 2847ac13930bSmikeb /* Internal PHY does not support anything else */ 2848ac13930bSmikeb return IXGBE_ERR_INVALID_LINK_SETTINGS; 2849ac13930bSmikeb } 2850ac13930bSmikeb 2851ac13930bSmikeb return ixgbe_setup_ixfi_x550em(hw, &force_speed); 2852d7a8f955Sjmatthew } else { 2853d7a8f955Sjmatthew speed = IXGBE_LINK_SPEED_10GB_FULL | 2854d7a8f955Sjmatthew IXGBE_LINK_SPEED_1GB_FULL; 2855d7a8f955Sjmatthew return ixgbe_setup_kr_speed_x550em(hw, speed); 2856d7a8f955Sjmatthew } 2857ac13930bSmikeb } 2858ac13930bSmikeb 2859ac13930bSmikeb /** 2860ac13930bSmikeb * ixgbe_setup_phy_loopback_x550em - Configure the KR PHY for loopback. 2861ac13930bSmikeb * @hw: pointer to hardware structure 2862ac13930bSmikeb * 2863ac13930bSmikeb * Configures the integrated KR PHY to use internal loopback mode. 2864ac13930bSmikeb **/ 2865ac13930bSmikeb int32_t ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw) 2866ac13930bSmikeb { 2867ac13930bSmikeb int32_t status; 2868ac13930bSmikeb uint32_t reg_val; 2869ac13930bSmikeb 2870ac13930bSmikeb /* Disable AN and force speed to 10G Serial. */ 2871d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 2872ac13930bSmikeb IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2873ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2874ac13930bSmikeb if (status != IXGBE_SUCCESS) 2875ac13930bSmikeb return status; 2876ac13930bSmikeb reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 2877ac13930bSmikeb reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 2878ac13930bSmikeb reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 2879d7a8f955Sjmatthew status = hw->mac.ops.write_iosf_sb_reg(hw, 2880ac13930bSmikeb IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 2881ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2882ac13930bSmikeb if (status != IXGBE_SUCCESS) 2883ac13930bSmikeb return status; 2884ac13930bSmikeb 2885ac13930bSmikeb /* Set near-end loopback clocks. */ 2886d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 2887ac13930bSmikeb IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id), 2888ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2889ac13930bSmikeb if (status != IXGBE_SUCCESS) 2890ac13930bSmikeb return status; 2891ac13930bSmikeb reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B; 2892ac13930bSmikeb reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS; 2893d7a8f955Sjmatthew status = hw->mac.ops.write_iosf_sb_reg(hw, 2894ac13930bSmikeb IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id), 2895ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2896ac13930bSmikeb if (status != IXGBE_SUCCESS) 2897ac13930bSmikeb return status; 2898ac13930bSmikeb 2899ac13930bSmikeb /* Set loopback enable. */ 2900d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 2901ac13930bSmikeb IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id), 2902ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2903ac13930bSmikeb if (status != IXGBE_SUCCESS) 2904ac13930bSmikeb return status; 2905ac13930bSmikeb reg_val |= IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK; 2906d7a8f955Sjmatthew status = hw->mac.ops.write_iosf_sb_reg(hw, 2907ac13930bSmikeb IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id), 2908ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2909ac13930bSmikeb if (status != IXGBE_SUCCESS) 2910ac13930bSmikeb return status; 2911ac13930bSmikeb 2912ac13930bSmikeb /* Training bypass. */ 2913d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 2914ac13930bSmikeb IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 2915ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 2916ac13930bSmikeb if (status != IXGBE_SUCCESS) 2917ac13930bSmikeb return status; 2918ac13930bSmikeb reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS; 2919d7a8f955Sjmatthew status = hw->mac.ops.write_iosf_sb_reg(hw, 2920ac13930bSmikeb IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 2921ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 2922ac13930bSmikeb 2923ac13930bSmikeb return status; 2924ac13930bSmikeb } 2925ac13930bSmikeb 2926ac13930bSmikeb /** 2927ac13930bSmikeb * ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 2928ac13930bSmikeb * assuming that the semaphore is already obtained. 2929ac13930bSmikeb * @hw: pointer to hardware structure 2930ac13930bSmikeb * @offset: offset of word in the EEPROM to read 2931ac13930bSmikeb * @data: word read from the EEPROM 2932ac13930bSmikeb * 2933ac13930bSmikeb * Reads a 16 bit word from the EEPROM using the hostif. 2934ac13930bSmikeb **/ 2935d7a8f955Sjmatthew int32_t ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, uint16_t offset,uint16_t *data) 2936ac13930bSmikeb { 2937d7a8f955Sjmatthew const uint32_t mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; 2938457e2542Sderaadt struct ixgbe_hic_read_shadow_ram buffer; 2939d7a8f955Sjmatthew int32_t status; 2940ac13930bSmikeb 2941d7a8f955Sjmatthew DEBUGFUNC("ixgbe_read_ee_hostif_X550"); 2942ac13930bSmikeb buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 2943ac13930bSmikeb buffer.hdr.req.buf_lenh = 0; 2944ac13930bSmikeb buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 2945ac13930bSmikeb buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 2946ac13930bSmikeb 2947ac13930bSmikeb /* convert offset from words to bytes */ 2948ac13930bSmikeb buffer.address = htobe32(offset * 2); 2949ac13930bSmikeb /* one word */ 2950ac13930bSmikeb buffer.length = htobe16(sizeof(uint16_t)); 2951d7a8f955Sjmatthew buffer.pad2 = 0; 2952d7a8f955Sjmatthew buffer.pad3 = 0; 2953ac13930bSmikeb 2954d7a8f955Sjmatthew status = hw->mac.ops.acquire_swfw_sync(hw, mask); 2955ac13930bSmikeb if (status) 2956ac13930bSmikeb return status; 2957ac13930bSmikeb 2958d7a8f955Sjmatthew status = ixgbe_hic_unlocked(hw, (uint32_t *)&buffer, sizeof(buffer), 2959d7a8f955Sjmatthew IXGBE_HI_COMMAND_TIMEOUT); 2960d7a8f955Sjmatthew if (!status) { 2961ac13930bSmikeb *data = (uint16_t)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 2962ac13930bSmikeb FW_NVM_DATA_OFFSET); 2963ac13930bSmikeb } 2964ac13930bSmikeb 2965d7a8f955Sjmatthew hw->mac.ops.release_swfw_sync(hw, mask); 2966ac13930bSmikeb return status; 2967ac13930bSmikeb } 2968ac13930bSmikeb 2969ac13930bSmikeb /** 2970ac13930bSmikeb * ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 2971ac13930bSmikeb * @hw: pointer to hardware structure 2972ac13930bSmikeb * @offset: offset of word in the EEPROM to read 2973ac13930bSmikeb * @words: number of words 2974ac13930bSmikeb * @data: word(s) read from the EEPROM 2975ac13930bSmikeb * 2976ac13930bSmikeb * Reads a 16 bit word(s) from the EEPROM using the hostif. 2977ac13930bSmikeb **/ 2978ac13930bSmikeb int32_t ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 2979ac13930bSmikeb uint16_t offset, uint16_t words, 2980ac13930bSmikeb uint16_t *data) 2981ac13930bSmikeb { 2982d7a8f955Sjmatthew const uint32_t mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; 2983ac13930bSmikeb struct ixgbe_hic_read_shadow_ram buffer; 2984ac13930bSmikeb uint32_t current_word = 0; 2985ac13930bSmikeb uint16_t words_to_read; 2986ac13930bSmikeb int32_t status; 2987ac13930bSmikeb uint32_t i; 2988ac13930bSmikeb 2989ac13930bSmikeb DEBUGFUNC("ixgbe_read_ee_hostif_buffer_X550"); 2990ac13930bSmikeb 2991ac13930bSmikeb /* Take semaphore for the entire operation. */ 2992d7a8f955Sjmatthew status = hw->mac.ops.acquire_swfw_sync(hw, mask); 2993ac13930bSmikeb if (status) { 2994ac13930bSmikeb DEBUGOUT("EEPROM read buffer - semaphore failed\n"); 2995ac13930bSmikeb return status; 2996ac13930bSmikeb } 2997d7a8f955Sjmatthew 2998ac13930bSmikeb while (words) { 2999ac13930bSmikeb if (words > FW_MAX_READ_BUFFER_SIZE / 2) 3000ac13930bSmikeb words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 3001ac13930bSmikeb else 3002ac13930bSmikeb words_to_read = words; 3003ac13930bSmikeb 3004ac13930bSmikeb buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 3005ac13930bSmikeb buffer.hdr.req.buf_lenh = 0; 3006ac13930bSmikeb buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 3007ac13930bSmikeb buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 3008ac13930bSmikeb 3009ac13930bSmikeb /* convert offset from words to bytes */ 3010ac13930bSmikeb buffer.address = htobe32((offset + current_word) * 2); 3011ac13930bSmikeb buffer.length = htobe16(words_to_read * 2); 3012d7a8f955Sjmatthew buffer.pad2 = 0; 3013d7a8f955Sjmatthew buffer.pad3 = 0; 3014ac13930bSmikeb 3015d7a8f955Sjmatthew status = ixgbe_hic_unlocked(hw, (uint32_t *)&buffer, sizeof(buffer), 3016d7a8f955Sjmatthew IXGBE_HI_COMMAND_TIMEOUT); 3017ac13930bSmikeb 3018ac13930bSmikeb if (status) { 3019ac13930bSmikeb DEBUGOUT("Host interface command failed\n"); 3020ac13930bSmikeb goto out; 3021ac13930bSmikeb } 3022ac13930bSmikeb 3023ac13930bSmikeb for (i = 0; i < words_to_read; i++) { 3024ac13930bSmikeb uint32_t reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 3025ac13930bSmikeb 2 * i; 3026ac13930bSmikeb uint32_t value = IXGBE_READ_REG(hw, reg); 3027ac13930bSmikeb 3028ac13930bSmikeb data[current_word] = (uint16_t)(value & 0xffff); 3029ac13930bSmikeb current_word++; 3030ac13930bSmikeb i++; 3031ac13930bSmikeb if (i < words_to_read) { 3032ac13930bSmikeb value >>= 16; 3033ac13930bSmikeb data[current_word] = (uint16_t)(value & 0xffff); 3034ac13930bSmikeb current_word++; 3035ac13930bSmikeb } 3036ac13930bSmikeb } 3037ac13930bSmikeb words -= words_to_read; 3038ac13930bSmikeb } 3039ac13930bSmikeb 3040ac13930bSmikeb out: 3041d7a8f955Sjmatthew hw->mac.ops.release_swfw_sync(hw, mask); 3042ac13930bSmikeb return status; 3043ac13930bSmikeb } 3044ac13930bSmikeb 3045ac13930bSmikeb /** 3046ac13930bSmikeb * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 3047ac13930bSmikeb * @hw: pointer to hardware structure 3048ac13930bSmikeb * @offset: offset of word in the EEPROM to write 3049ac13930bSmikeb * @data: word write to the EEPROM 3050ac13930bSmikeb * 3051ac13930bSmikeb * Write a 16 bit word to the EEPROM using the hostif. 3052ac13930bSmikeb **/ 3053ac13930bSmikeb int32_t ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, uint16_t offset, 3054ac13930bSmikeb uint16_t data) 3055ac13930bSmikeb { 3056ac13930bSmikeb int32_t status; 3057ac13930bSmikeb struct ixgbe_hic_write_shadow_ram buffer; 3058ac13930bSmikeb 3059ac13930bSmikeb DEBUGFUNC("ixgbe_write_ee_hostif_data_X550"); 3060ac13930bSmikeb 3061ac13930bSmikeb buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 3062ac13930bSmikeb buffer.hdr.req.buf_lenh = 0; 3063ac13930bSmikeb buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 3064ac13930bSmikeb buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 3065ac13930bSmikeb 3066ac13930bSmikeb /* one word */ 3067ac13930bSmikeb buffer.length = htobe16(sizeof(uint16_t)); 3068ac13930bSmikeb buffer.data = data; 3069ac13930bSmikeb buffer.address = htobe32(offset * 2); 3070ac13930bSmikeb 3071ac13930bSmikeb status = ixgbe_host_interface_command(hw, (uint32_t *)&buffer, 3072ac13930bSmikeb sizeof(buffer), 3073ac13930bSmikeb IXGBE_HI_COMMAND_TIMEOUT, FALSE); 3074ac13930bSmikeb 3075ac13930bSmikeb return status; 3076ac13930bSmikeb } 3077ac13930bSmikeb 3078ac13930bSmikeb /** 3079ac13930bSmikeb * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 3080ac13930bSmikeb * @hw: pointer to hardware structure 3081ac13930bSmikeb * @offset: offset of word in the EEPROM to write 3082ac13930bSmikeb * @data: word write to the EEPROM 3083ac13930bSmikeb * 3084ac13930bSmikeb * Write a 16 bit word to the EEPROM using the hostif. 3085ac13930bSmikeb **/ 3086ac13930bSmikeb int32_t ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, uint16_t offset, 3087ac13930bSmikeb uint16_t data) 3088ac13930bSmikeb { 3089ac13930bSmikeb int32_t status = IXGBE_SUCCESS; 3090ac13930bSmikeb 3091ac13930bSmikeb DEBUGFUNC("ixgbe_write_ee_hostif_X550"); 3092ac13930bSmikeb 3093ac13930bSmikeb if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 3094ac13930bSmikeb IXGBE_SUCCESS) { 3095ac13930bSmikeb status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 3096ac13930bSmikeb hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 3097ac13930bSmikeb } else { 3098d7a8f955Sjmatthew DEBUGOUT("write ee hostif failed to get semaphore"); 3099ac13930bSmikeb status = IXGBE_ERR_SWFW_SYNC; 3100ac13930bSmikeb } 3101ac13930bSmikeb 3102ac13930bSmikeb return status; 3103ac13930bSmikeb } 3104ac13930bSmikeb 3105ac13930bSmikeb /** 3106ac13930bSmikeb * ixgbe_checksum_ptr_x550 - Checksum one pointer region 3107ac13930bSmikeb * @hw: pointer to hardware structure 3108ac13930bSmikeb * @ptr: pointer offset in eeprom 3109ac13930bSmikeb * @size: size of section pointed by ptr, if 0 first word will be used as size 3110ac13930bSmikeb * @csum: address of checksum to update 3111d7a8f955Sjmatthew * @buffer: pointer to buffer containing calculated checksum 3112d7a8f955Sjmatthew * @buffer_size: size of buffer 3113ac13930bSmikeb * 3114ac13930bSmikeb * Returns error status for any failure 3115ac13930bSmikeb */ 3116ac13930bSmikeb int32_t ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, uint16_t ptr, 3117ac13930bSmikeb uint16_t size, uint16_t *csum, uint16_t *buffer, 3118ac13930bSmikeb uint32_t buffer_size) 3119ac13930bSmikeb { 3120ac13930bSmikeb uint16_t buf[256]; 3121ac13930bSmikeb int32_t status; 3122ac13930bSmikeb uint16_t length, bufsz, i, start; 3123ac13930bSmikeb uint16_t *local_buffer; 3124ac13930bSmikeb 3125ac13930bSmikeb bufsz = sizeof(buf) / sizeof(buf[0]); 3126ac13930bSmikeb 3127ac13930bSmikeb /* Read a chunk at the pointer location */ 3128ac13930bSmikeb if (!buffer) { 3129ac13930bSmikeb status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 3130ac13930bSmikeb if (status) { 3131ac13930bSmikeb DEBUGOUT("Failed to read EEPROM image\n"); 3132ac13930bSmikeb return status; 3133ac13930bSmikeb } 3134ac13930bSmikeb local_buffer = buf; 3135ac13930bSmikeb } else { 3136ac13930bSmikeb if (buffer_size < ptr) 3137ac13930bSmikeb return IXGBE_ERR_PARAM; 3138ac13930bSmikeb local_buffer = &buffer[ptr]; 3139ac13930bSmikeb } 3140ac13930bSmikeb 3141ac13930bSmikeb if (size) { 3142ac13930bSmikeb start = 0; 3143ac13930bSmikeb length = size; 3144ac13930bSmikeb } else { 3145ac13930bSmikeb start = 1; 3146ac13930bSmikeb length = local_buffer[0]; 3147ac13930bSmikeb 3148ac13930bSmikeb /* Skip pointer section if length is invalid. */ 3149ac13930bSmikeb if (length == 0xFFFF || length == 0 || 3150ac13930bSmikeb (ptr + length) >= hw->eeprom.word_size) 3151ac13930bSmikeb return IXGBE_SUCCESS; 3152ac13930bSmikeb } 3153ac13930bSmikeb 3154ac13930bSmikeb if (buffer && ((uint32_t)start + (uint32_t)length > buffer_size)) 3155ac13930bSmikeb return IXGBE_ERR_PARAM; 3156ac13930bSmikeb 3157ac13930bSmikeb for (i = start; length; i++, length--) { 3158ac13930bSmikeb if (i == bufsz && !buffer) { 3159ac13930bSmikeb ptr += bufsz; 3160ac13930bSmikeb i = 0; 3161ac13930bSmikeb if (length < bufsz) 3162ac13930bSmikeb bufsz = length; 3163ac13930bSmikeb 3164ac13930bSmikeb /* Read a chunk at the pointer location */ 3165ac13930bSmikeb status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 3166ac13930bSmikeb bufsz, buf); 3167ac13930bSmikeb if (status) { 3168ac13930bSmikeb DEBUGOUT("Failed to read EEPROM image\n"); 3169ac13930bSmikeb return status; 3170ac13930bSmikeb } 3171ac13930bSmikeb } 3172ac13930bSmikeb *csum += local_buffer[i]; 3173ac13930bSmikeb } 3174ac13930bSmikeb return IXGBE_SUCCESS; 3175ac13930bSmikeb } 3176ac13930bSmikeb 3177ac13930bSmikeb /** 3178ac13930bSmikeb * ixgbe_calc_checksum_X550 - Calculates and returns the checksum 3179ac13930bSmikeb * @hw: pointer to hardware structure 3180ac13930bSmikeb * @buffer: pointer to buffer containing calculated checksum 3181ac13930bSmikeb * @buffer_size: size of buffer 3182ac13930bSmikeb * 3183ac13930bSmikeb * Returns a negative error code on error, or the 16-bit checksum 3184ac13930bSmikeb **/ 3185ac13930bSmikeb int32_t ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, uint16_t *buffer, 3186ac13930bSmikeb uint32_t buffer_size) 3187ac13930bSmikeb { 3188ac13930bSmikeb uint16_t eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 3189ac13930bSmikeb uint16_t *local_buffer; 3190ac13930bSmikeb int32_t status; 3191ac13930bSmikeb uint16_t checksum = 0; 3192ac13930bSmikeb uint16_t pointer, i, size; 3193ac13930bSmikeb 3194ac13930bSmikeb DEBUGFUNC("ixgbe_calc_eeprom_checksum_X550"); 3195ac13930bSmikeb 3196ac13930bSmikeb hw->eeprom.ops.init_params(hw); 3197ac13930bSmikeb 3198ac13930bSmikeb if (!buffer) { 3199ac13930bSmikeb /* Read pointer area */ 3200ac13930bSmikeb status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 3201ac13930bSmikeb IXGBE_EEPROM_LAST_WORD + 1, 3202ac13930bSmikeb eeprom_ptrs); 3203ac13930bSmikeb if (status) { 3204ac13930bSmikeb DEBUGOUT("Failed to read EEPROM image\n"); 3205ac13930bSmikeb return status; 3206ac13930bSmikeb } 3207ac13930bSmikeb local_buffer = eeprom_ptrs; 3208ac13930bSmikeb } else { 3209ac13930bSmikeb if (buffer_size < IXGBE_EEPROM_LAST_WORD) 3210ac13930bSmikeb return IXGBE_ERR_PARAM; 3211ac13930bSmikeb local_buffer = buffer; 3212ac13930bSmikeb } 3213ac13930bSmikeb 3214ac13930bSmikeb /* 3215ac13930bSmikeb * For X550 hardware include 0x0-0x41 in the checksum, skip the 3216ac13930bSmikeb * checksum word itself 3217ac13930bSmikeb */ 3218ac13930bSmikeb for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 3219ac13930bSmikeb if (i != IXGBE_EEPROM_CHECKSUM) 3220ac13930bSmikeb checksum += local_buffer[i]; 3221ac13930bSmikeb 3222ac13930bSmikeb /* 3223ac13930bSmikeb * Include all data from pointers 0x3, 0x6-0xE. This excludes the 3224ac13930bSmikeb * FW, PHY module, and PCIe Expansion/Option ROM pointers. 3225ac13930bSmikeb */ 3226ac13930bSmikeb for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 3227ac13930bSmikeb if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 3228ac13930bSmikeb continue; 3229ac13930bSmikeb 3230ac13930bSmikeb pointer = local_buffer[i]; 3231ac13930bSmikeb 3232ac13930bSmikeb /* Skip pointer section if the pointer is invalid. */ 3233ac13930bSmikeb if (pointer == 0xFFFF || pointer == 0 || 3234ac13930bSmikeb pointer >= hw->eeprom.word_size) 3235ac13930bSmikeb continue; 3236ac13930bSmikeb 3237ac13930bSmikeb switch (i) { 3238ac13930bSmikeb case IXGBE_PCIE_GENERAL_PTR: 3239ac13930bSmikeb size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 3240ac13930bSmikeb break; 3241ac13930bSmikeb case IXGBE_PCIE_CONFIG0_PTR: 3242ac13930bSmikeb case IXGBE_PCIE_CONFIG1_PTR: 3243ac13930bSmikeb size = IXGBE_PCIE_CONFIG_SIZE; 3244ac13930bSmikeb break; 3245ac13930bSmikeb default: 3246ac13930bSmikeb size = 0; 3247ac13930bSmikeb break; 3248ac13930bSmikeb } 3249ac13930bSmikeb 3250ac13930bSmikeb status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 3251ac13930bSmikeb buffer, buffer_size); 3252ac13930bSmikeb if (status) 3253ac13930bSmikeb return status; 3254ac13930bSmikeb } 3255ac13930bSmikeb 3256ac13930bSmikeb checksum = (uint16_t)IXGBE_EEPROM_SUM - checksum; 3257ac13930bSmikeb 3258ac13930bSmikeb return (int32_t)checksum; 3259ac13930bSmikeb } 3260ac13930bSmikeb 3261ac13930bSmikeb /** 3262ac13930bSmikeb * ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 3263ac13930bSmikeb * @hw: pointer to hardware structure 3264ac13930bSmikeb * 3265ac13930bSmikeb * Returns a negative error code on error, or the 16-bit checksum 3266ac13930bSmikeb **/ 3267ac13930bSmikeb int32_t ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 3268ac13930bSmikeb { 3269ac13930bSmikeb return ixgbe_calc_checksum_X550(hw, NULL, 0); 3270ac13930bSmikeb } 3271ac13930bSmikeb 3272ac13930bSmikeb /** 3273ac13930bSmikeb * ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 3274ac13930bSmikeb * @hw: pointer to hardware structure 3275ac13930bSmikeb * @checksum_val: calculated checksum 3276ac13930bSmikeb * 3277ac13930bSmikeb * Performs checksum calculation and validates the EEPROM checksum. If the 3278ac13930bSmikeb * caller does not need checksum_val, the value can be NULL. 3279ac13930bSmikeb **/ 3280ac13930bSmikeb int32_t ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, uint16_t *checksum_val) 3281ac13930bSmikeb { 3282ac13930bSmikeb int32_t status; 3283ac13930bSmikeb uint16_t checksum; 3284ac13930bSmikeb uint16_t read_checksum = 0; 3285ac13930bSmikeb 3286ac13930bSmikeb DEBUGFUNC("ixgbe_validate_eeprom_checksum_X550"); 3287ac13930bSmikeb 3288ac13930bSmikeb /* Read the first word from the EEPROM. If this times out or fails, do 3289ac13930bSmikeb * not continue or we could be in for a very long wait while every 3290ac13930bSmikeb * EEPROM read fails 3291ac13930bSmikeb */ 3292ac13930bSmikeb status = hw->eeprom.ops.read(hw, 0, &checksum); 3293ac13930bSmikeb if (status) { 3294ac13930bSmikeb DEBUGOUT("EEPROM read failed\n"); 3295ac13930bSmikeb return status; 3296ac13930bSmikeb } 3297ac13930bSmikeb 3298ac13930bSmikeb status = hw->eeprom.ops.calc_checksum(hw); 3299ac13930bSmikeb if (status < 0) 3300ac13930bSmikeb return status; 3301ac13930bSmikeb 3302ac13930bSmikeb checksum = (uint16_t)(status & 0xffff); 3303ac13930bSmikeb 3304ac13930bSmikeb status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 3305ac13930bSmikeb &read_checksum); 3306ac13930bSmikeb if (status) 3307ac13930bSmikeb return status; 3308ac13930bSmikeb 3309ac13930bSmikeb /* Verify read checksum from EEPROM is the same as 3310ac13930bSmikeb * calculated checksum 3311ac13930bSmikeb */ 3312ac13930bSmikeb if (read_checksum != checksum) { 3313ac13930bSmikeb status = IXGBE_ERR_EEPROM_CHECKSUM; 3314d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, 3315d7a8f955Sjmatthew "Invalid EEPROM checksum"); 3316ac13930bSmikeb } 3317ac13930bSmikeb 3318ac13930bSmikeb /* If the user cares, return the calculated checksum */ 3319ac13930bSmikeb if (checksum_val) 3320ac13930bSmikeb *checksum_val = checksum; 3321ac13930bSmikeb 3322ac13930bSmikeb return status; 3323ac13930bSmikeb } 3324ac13930bSmikeb 3325ac13930bSmikeb /** 3326ac13930bSmikeb * ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 3327ac13930bSmikeb * @hw: pointer to hardware structure 3328ac13930bSmikeb * 3329ac13930bSmikeb * After writing EEPROM to shadow RAM using EEWR register, software calculates 3330ac13930bSmikeb * checksum and updates the EEPROM and instructs the hardware to update 3331ac13930bSmikeb * the flash. 3332ac13930bSmikeb **/ 3333ac13930bSmikeb int32_t ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 3334ac13930bSmikeb { 3335ac13930bSmikeb int32_t status; 3336ac13930bSmikeb uint16_t checksum = 0; 3337ac13930bSmikeb 3338ac13930bSmikeb DEBUGFUNC("ixgbe_update_eeprom_checksum_X550"); 3339ac13930bSmikeb 3340ac13930bSmikeb /* Read the first word from the EEPROM. If this times out or fails, do 3341ac13930bSmikeb * not continue or we could be in for a very long wait while every 3342ac13930bSmikeb * EEPROM read fails 3343ac13930bSmikeb */ 3344ac13930bSmikeb status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 3345ac13930bSmikeb if (status) { 3346ac13930bSmikeb DEBUGOUT("EEPROM read failed\n"); 3347ac13930bSmikeb return status; 3348ac13930bSmikeb } 3349ac13930bSmikeb 3350ac13930bSmikeb status = ixgbe_calc_eeprom_checksum_X550(hw); 3351ac13930bSmikeb if (status < 0) 3352ac13930bSmikeb return status; 3353ac13930bSmikeb 3354ac13930bSmikeb checksum = (uint16_t)(status & 0xffff); 3355ac13930bSmikeb 3356ac13930bSmikeb status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 3357ac13930bSmikeb checksum); 3358ac13930bSmikeb if (status) 3359ac13930bSmikeb return status; 3360ac13930bSmikeb 3361ac13930bSmikeb status = ixgbe_update_flash_X550(hw); 3362ac13930bSmikeb 3363ac13930bSmikeb return status; 3364ac13930bSmikeb } 3365ac13930bSmikeb 3366ac13930bSmikeb /** 3367ac13930bSmikeb * ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 3368ac13930bSmikeb * @hw: pointer to hardware structure 3369ac13930bSmikeb * 3370ac13930bSmikeb * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 3371ac13930bSmikeb **/ 3372ac13930bSmikeb int32_t ixgbe_update_flash_X550(struct ixgbe_hw *hw) 3373ac13930bSmikeb { 3374ac13930bSmikeb int32_t status = IXGBE_SUCCESS; 3375ac13930bSmikeb union ixgbe_hic_hdr2 buffer; 3376ac13930bSmikeb 3377ac13930bSmikeb DEBUGFUNC("ixgbe_update_flash_X550"); 3378ac13930bSmikeb 3379ac13930bSmikeb buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 3380ac13930bSmikeb buffer.req.buf_lenh = 0; 3381ac13930bSmikeb buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 3382ac13930bSmikeb buffer.req.checksum = FW_DEFAULT_CHECKSUM; 3383ac13930bSmikeb 3384ac13930bSmikeb status = ixgbe_host_interface_command(hw, (uint32_t *)&buffer, 3385ac13930bSmikeb sizeof(buffer), 3386ac13930bSmikeb IXGBE_HI_COMMAND_TIMEOUT, FALSE); 3387ac13930bSmikeb 3388ac13930bSmikeb return status; 3389ac13930bSmikeb } 3390ac13930bSmikeb 3391ac13930bSmikeb /** 3392ac13930bSmikeb * ixgbe_get_supported_physical_layer_X550em - Returns physical layer type 3393ac13930bSmikeb * @hw: pointer to hardware structure 3394ac13930bSmikeb * 3395ac13930bSmikeb * Determines physical layer capabilities of the current configuration. 3396ac13930bSmikeb **/ 3397d7a8f955Sjmatthew uint64_t ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw) 3398ac13930bSmikeb { 3399d7a8f955Sjmatthew uint64_t physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; 3400ac13930bSmikeb uint16_t ext_ability = 0; 3401ac13930bSmikeb 3402ac13930bSmikeb DEBUGFUNC("ixgbe_get_supported_physical_layer_X550em"); 3403ac13930bSmikeb 3404ac13930bSmikeb hw->phy.ops.identify(hw); 3405ac13930bSmikeb 3406ac13930bSmikeb switch (hw->phy.type) { 3407ac13930bSmikeb case ixgbe_phy_x550em_kr: 3408d7a8f955Sjmatthew if (hw->mac.type == ixgbe_mac_X550EM_a) { 3409d7a8f955Sjmatthew if (hw->phy.nw_mng_if_sel & 3410d7a8f955Sjmatthew IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) { 3411d7a8f955Sjmatthew physical_layer = 3412d7a8f955Sjmatthew IXGBE_PHYSICAL_LAYER_2500BASE_KX; 3413d7a8f955Sjmatthew break; 3414d7a8f955Sjmatthew } else if (hw->device_id == 3415d7a8f955Sjmatthew IXGBE_DEV_ID_X550EM_A_KR_L) { 3416d7a8f955Sjmatthew physical_layer = 3417d7a8f955Sjmatthew IXGBE_PHYSICAL_LAYER_1000BASE_KX; 3418d7a8f955Sjmatthew break; 3419d7a8f955Sjmatthew } 3420d7a8f955Sjmatthew } 3421d7a8f955Sjmatthew /* fall through */ 3422d7a8f955Sjmatthew case ixgbe_phy_x550em_xfi: 3423ac13930bSmikeb physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR | 3424ac13930bSmikeb IXGBE_PHYSICAL_LAYER_1000BASE_KX; 3425ac13930bSmikeb break; 3426ac13930bSmikeb case ixgbe_phy_x550em_kx4: 3427ac13930bSmikeb physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | 3428ac13930bSmikeb IXGBE_PHYSICAL_LAYER_1000BASE_KX; 3429ac13930bSmikeb break; 3430ac13930bSmikeb case ixgbe_phy_x550em_ext_t: 3431ac13930bSmikeb hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, 3432ac13930bSmikeb IXGBE_MDIO_PMA_PMD_DEV_TYPE, 3433ac13930bSmikeb &ext_ability); 3434ac13930bSmikeb if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) 3435ac13930bSmikeb physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; 3436ac13930bSmikeb if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) 3437ac13930bSmikeb physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; 3438ac13930bSmikeb break; 3439d7a8f955Sjmatthew case ixgbe_phy_fw: 3440d7a8f955Sjmatthew if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_1GB_FULL) 3441d7a8f955Sjmatthew physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; 3442d7a8f955Sjmatthew if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_100_FULL) 3443d7a8f955Sjmatthew physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; 3444d7a8f955Sjmatthew if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_10_FULL) 3445d7a8f955Sjmatthew physical_layer |= IXGBE_PHYSICAL_LAYER_10BASE_T; 3446d7a8f955Sjmatthew break; 3447d7a8f955Sjmatthew case ixgbe_phy_sgmii: 3448d7a8f955Sjmatthew physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX; 3449d7a8f955Sjmatthew break; 3450d7a8f955Sjmatthew case ixgbe_phy_ext_1g_t: 3451d7a8f955Sjmatthew physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T; 3452d7a8f955Sjmatthew break; 3453ac13930bSmikeb default: 3454ac13930bSmikeb break; 3455ac13930bSmikeb } 3456ac13930bSmikeb 3457ac13930bSmikeb if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) 3458ac13930bSmikeb physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw); 3459ac13930bSmikeb 3460ac13930bSmikeb return physical_layer; 3461ac13930bSmikeb } 3462ac13930bSmikeb 3463ac13930bSmikeb /** 3464ac13930bSmikeb * ixgbe_get_bus_info_x550em - Set PCI bus info 3465ac13930bSmikeb * @hw: pointer to hardware structure 3466ac13930bSmikeb * 3467ac13930bSmikeb * Sets bus link width and speed to unknown because X550em is 3468ac13930bSmikeb * not a PCI device. 3469ac13930bSmikeb **/ 3470ac13930bSmikeb int32_t ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) 3471ac13930bSmikeb { 3472ac13930bSmikeb 3473ac13930bSmikeb DEBUGFUNC("ixgbe_get_bus_info_x550em"); 3474ac13930bSmikeb 3475ac13930bSmikeb hw->bus.width = ixgbe_bus_width_unknown; 3476ac13930bSmikeb hw->bus.speed = ixgbe_bus_speed_unknown; 3477ac13930bSmikeb 3478ac13930bSmikeb hw->mac.ops.set_lan_id(hw); 3479ac13930bSmikeb 3480ac13930bSmikeb return IXGBE_SUCCESS; 3481ac13930bSmikeb } 3482ac13930bSmikeb 3483ac13930bSmikeb /** 3484ac13930bSmikeb * ixgbe_disable_rx_x550 - Disable RX unit 3485d7a8f955Sjmatthew * @hw: pointer to hardware structure 3486ac13930bSmikeb * 3487ac13930bSmikeb * Enables the Rx DMA unit for x550 3488ac13930bSmikeb **/ 3489ac13930bSmikeb void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 3490ac13930bSmikeb { 3491d7a8f955Sjmatthew uint32_t rxctrl, pfdtxgswc; 3492ac13930bSmikeb int32_t status; 3493ac13930bSmikeb struct ixgbe_hic_disable_rxen fw_cmd; 3494ac13930bSmikeb 3495d7a8f955Sjmatthew DEBUGFUNC("ixgbe_enable_rx_dma_x550"); 3496ac13930bSmikeb 3497ac13930bSmikeb rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 3498ac13930bSmikeb if (rxctrl & IXGBE_RXCTRL_RXEN) { 3499d7a8f955Sjmatthew pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 3500d7a8f955Sjmatthew if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 3501d7a8f955Sjmatthew pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 3502d7a8f955Sjmatthew IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 3503d7a8f955Sjmatthew hw->mac.set_lben = TRUE; 3504d7a8f955Sjmatthew } else { 3505d7a8f955Sjmatthew hw->mac.set_lben = FALSE; 3506d7a8f955Sjmatthew } 3507d7a8f955Sjmatthew 3508ac13930bSmikeb fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 3509ac13930bSmikeb fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 3510ac13930bSmikeb fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 3511ac13930bSmikeb fw_cmd.port_number = (uint8_t)hw->bus.lan_id; 3512ac13930bSmikeb 3513ac13930bSmikeb status = ixgbe_host_interface_command(hw, (uint32_t *)&fw_cmd, 3514ac13930bSmikeb sizeof(struct ixgbe_hic_disable_rxen), 3515ac13930bSmikeb IXGBE_HI_COMMAND_TIMEOUT, TRUE); 3516ac13930bSmikeb 3517ac13930bSmikeb /* If we fail - disable RX using register write */ 3518ac13930bSmikeb if (status) { 3519ac13930bSmikeb rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 3520ac13930bSmikeb if (rxctrl & IXGBE_RXCTRL_RXEN) { 3521ac13930bSmikeb rxctrl &= ~IXGBE_RXCTRL_RXEN; 3522ac13930bSmikeb IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 3523ac13930bSmikeb } 3524ac13930bSmikeb } 3525ac13930bSmikeb } 3526ac13930bSmikeb } 3527ac13930bSmikeb 3528ac13930bSmikeb /** 3529d7a8f955Sjmatthew * ixgbe_enter_lplu_x550em - Transition to low power states 3530d7a8f955Sjmatthew * @hw: pointer to hardware structure 3531d7a8f955Sjmatthew * 3532d7a8f955Sjmatthew * Configures Low Power Link Up on transition to low power states 3533d7a8f955Sjmatthew * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting the 3534d7a8f955Sjmatthew * X557 PHY immediately prior to entering LPLU. 3535d7a8f955Sjmatthew **/ 3536d7a8f955Sjmatthew int32_t ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) 3537d7a8f955Sjmatthew { 3538d7a8f955Sjmatthew uint16_t an_10g_cntl_reg, autoneg_reg, speed; 3539d7a8f955Sjmatthew int32_t status; 3540d7a8f955Sjmatthew ixgbe_link_speed lcd_speed; 3541d7a8f955Sjmatthew uint32_t save_autoneg; 3542d7a8f955Sjmatthew bool link_up; 3543d7a8f955Sjmatthew 3544d7a8f955Sjmatthew /* SW LPLU not required on later HW revisions. */ 3545d7a8f955Sjmatthew if ((hw->mac.type == ixgbe_mac_X550EM_x) && 3546d7a8f955Sjmatthew (IXGBE_FUSES0_REV_MASK & 3547d7a8f955Sjmatthew IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))) 3548d7a8f955Sjmatthew return IXGBE_SUCCESS; 3549d7a8f955Sjmatthew 3550d7a8f955Sjmatthew /* If blocked by MNG FW, then don't restart AN */ 3551d7a8f955Sjmatthew if (ixgbe_check_reset_blocked(hw)) 3552d7a8f955Sjmatthew return IXGBE_SUCCESS; 3553d7a8f955Sjmatthew 3554d7a8f955Sjmatthew status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 3555d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 3556d7a8f955Sjmatthew return status; 3557d7a8f955Sjmatthew 3558d7a8f955Sjmatthew status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, &hw->eeprom.ctrl_word_3); 3559d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 3560d7a8f955Sjmatthew return status; 3561d7a8f955Sjmatthew 3562d7a8f955Sjmatthew /* If link is down, LPLU disabled in NVM, WoL disabled, or manageability 3563d7a8f955Sjmatthew * disabled, then force link down by entering low power mode. 3564d7a8f955Sjmatthew */ 3565d7a8f955Sjmatthew if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || 3566d7a8f955Sjmatthew !(hw->wol_enabled || ixgbe_mng_present(hw))) 3567d7a8f955Sjmatthew return ixgbe_set_copper_phy_power(hw, FALSE); 3568d7a8f955Sjmatthew 3569d7a8f955Sjmatthew /* Determine LCD */ 3570d7a8f955Sjmatthew status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); 3571d7a8f955Sjmatthew 3572d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 3573d7a8f955Sjmatthew return status; 3574d7a8f955Sjmatthew 3575d7a8f955Sjmatthew /* If no valid LCD link speed, then force link down and exit. */ 3576d7a8f955Sjmatthew if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) 3577d7a8f955Sjmatthew return ixgbe_set_copper_phy_power(hw, FALSE); 3578d7a8f955Sjmatthew 3579d7a8f955Sjmatthew status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 3580d7a8f955Sjmatthew IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3581d7a8f955Sjmatthew &speed); 3582d7a8f955Sjmatthew 3583d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 3584d7a8f955Sjmatthew return status; 3585d7a8f955Sjmatthew 3586d7a8f955Sjmatthew /* If no link now, speed is invalid so take link down */ 3587d7a8f955Sjmatthew status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 3588d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 3589d7a8f955Sjmatthew return ixgbe_set_copper_phy_power(hw, FALSE); 3590d7a8f955Sjmatthew 3591d7a8f955Sjmatthew /* clear everything but the speed bits */ 3592d7a8f955Sjmatthew speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; 3593d7a8f955Sjmatthew 3594d7a8f955Sjmatthew /* If current speed is already LCD, then exit. */ 3595d7a8f955Sjmatthew if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && 3596d7a8f955Sjmatthew (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || 3597d7a8f955Sjmatthew ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && 3598d7a8f955Sjmatthew (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) 3599d7a8f955Sjmatthew return status; 3600d7a8f955Sjmatthew 3601d7a8f955Sjmatthew /* Clear AN completed indication */ 3602d7a8f955Sjmatthew status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, 3603d7a8f955Sjmatthew IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3604d7a8f955Sjmatthew &autoneg_reg); 3605d7a8f955Sjmatthew 3606d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 3607d7a8f955Sjmatthew return status; 3608d7a8f955Sjmatthew 3609d7a8f955Sjmatthew status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, 3610d7a8f955Sjmatthew IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3611d7a8f955Sjmatthew &an_10g_cntl_reg); 3612d7a8f955Sjmatthew 3613d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 3614d7a8f955Sjmatthew return status; 3615d7a8f955Sjmatthew 3616d7a8f955Sjmatthew status = hw->phy.ops.read_reg(hw, 3617d7a8f955Sjmatthew IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, 3618d7a8f955Sjmatthew IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3619d7a8f955Sjmatthew &autoneg_reg); 3620d7a8f955Sjmatthew 3621d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) 3622d7a8f955Sjmatthew return status; 3623d7a8f955Sjmatthew 3624d7a8f955Sjmatthew save_autoneg = hw->phy.autoneg_advertised; 3625d7a8f955Sjmatthew 3626d7a8f955Sjmatthew /* Setup link at least common link speed */ 3627d7a8f955Sjmatthew status = hw->mac.ops.setup_link(hw, lcd_speed, FALSE); 3628d7a8f955Sjmatthew 3629d7a8f955Sjmatthew /* restore autoneg from before setting lplu speed */ 3630d7a8f955Sjmatthew hw->phy.autoneg_advertised = save_autoneg; 3631d7a8f955Sjmatthew 3632d7a8f955Sjmatthew return status; 3633d7a8f955Sjmatthew } 3634d7a8f955Sjmatthew 3635d7a8f955Sjmatthew /** 3636ac13930bSmikeb * ixgbe_get_lcd_x550em - Determine lowest common denominator 3637ac13930bSmikeb * @hw: pointer to hardware structure 3638ac13930bSmikeb * @lcd_speed: pointer to lowest common link speed 3639ac13930bSmikeb * 3640ac13930bSmikeb * Determine lowest common link speed with link partner. 3641ac13930bSmikeb **/ 3642ac13930bSmikeb int32_t ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed) 3643ac13930bSmikeb { 3644ac13930bSmikeb uint16_t an_lp_status; 3645ac13930bSmikeb int32_t status; 3646ac13930bSmikeb uint16_t word = hw->eeprom.ctrl_word_3; 3647ac13930bSmikeb 3648ac13930bSmikeb *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; 3649ac13930bSmikeb 3650ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, 3651ac13930bSmikeb IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3652ac13930bSmikeb &an_lp_status); 3653ac13930bSmikeb 3654ac13930bSmikeb if (status != IXGBE_SUCCESS) 3655ac13930bSmikeb return status; 3656ac13930bSmikeb 3657ac13930bSmikeb /* If link partner advertised 1G, return 1G */ 3658ac13930bSmikeb if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { 3659ac13930bSmikeb *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; 3660ac13930bSmikeb return status; 3661ac13930bSmikeb } 3662ac13930bSmikeb 3663ac13930bSmikeb /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ 3664ac13930bSmikeb if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || 3665ac13930bSmikeb (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) 3666ac13930bSmikeb return status; 3667ac13930bSmikeb 3668ac13930bSmikeb /* Link partner not capable of lower speeds, return 10G */ 3669ac13930bSmikeb *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; 3670ac13930bSmikeb return status; 3671ac13930bSmikeb } 3672ac13930bSmikeb 3673ac13930bSmikeb /** 3674ac13930bSmikeb * ixgbe_setup_fc_X550em - Set up flow control 3675ac13930bSmikeb * @hw: pointer to hardware structure 3676ac13930bSmikeb * 3677ac13930bSmikeb * Called at init time to set up flow control. 3678ac13930bSmikeb **/ 3679ac13930bSmikeb int32_t ixgbe_setup_fc_X550em(struct ixgbe_hw *hw) 3680ac13930bSmikeb { 3681ac13930bSmikeb int32_t ret_val = IXGBE_SUCCESS; 3682ac13930bSmikeb uint32_t pause, asm_dir, reg_val; 3683ac13930bSmikeb 3684ac13930bSmikeb DEBUGFUNC("ixgbe_setup_fc_X550em"); 3685ac13930bSmikeb 3686ac13930bSmikeb /* Validate the requested mode */ 3687ac13930bSmikeb if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 3688d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 3689d7a8f955Sjmatthew "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 3690ac13930bSmikeb ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 3691ac13930bSmikeb goto out; 3692ac13930bSmikeb } 3693ac13930bSmikeb 3694ac13930bSmikeb /* 10gig parts do not have a word in the EEPROM to determine the 3695ac13930bSmikeb * default flow control setting, so we explicitly set it to full. 3696ac13930bSmikeb */ 3697ac13930bSmikeb if (hw->fc.requested_mode == ixgbe_fc_default) 3698ac13930bSmikeb hw->fc.requested_mode = ixgbe_fc_full; 3699ac13930bSmikeb 3700ac13930bSmikeb /* Determine PAUSE and ASM_DIR bits. */ 3701ac13930bSmikeb switch (hw->fc.requested_mode) { 3702ac13930bSmikeb case ixgbe_fc_none: 3703ac13930bSmikeb pause = 0; 3704ac13930bSmikeb asm_dir = 0; 3705ac13930bSmikeb break; 3706ac13930bSmikeb case ixgbe_fc_tx_pause: 3707ac13930bSmikeb pause = 0; 3708ac13930bSmikeb asm_dir = 1; 3709ac13930bSmikeb break; 3710ac13930bSmikeb case ixgbe_fc_rx_pause: 3711ac13930bSmikeb /* Rx Flow control is enabled and Tx Flow control is 3712ac13930bSmikeb * disabled by software override. Since there really 3713ac13930bSmikeb * isn't a way to advertise that we are capable of RX 3714ac13930bSmikeb * Pause ONLY, we will advertise that we support both 3715ac13930bSmikeb * symmetric and asymmetric Rx PAUSE, as such we fall 3716ac13930bSmikeb * through to the fc_full statement. Later, we will 3717ac13930bSmikeb * disable the adapter's ability to send PAUSE frames. 3718ac13930bSmikeb */ 3719ac13930bSmikeb case ixgbe_fc_full: 3720ac13930bSmikeb pause = 1; 3721ac13930bSmikeb asm_dir = 1; 3722ac13930bSmikeb break; 3723ac13930bSmikeb default: 3724d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 3725d7a8f955Sjmatthew "Flow control param set incorrectly\n"); 3726ac13930bSmikeb ret_val = IXGBE_ERR_CONFIG; 3727ac13930bSmikeb goto out; 3728ac13930bSmikeb } 3729ac13930bSmikeb 3730d7a8f955Sjmatthew switch (hw->device_id) { 3731d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_KR: 3732d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_KR: 3733d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_A_KR_L: 3734d7a8f955Sjmatthew ret_val = hw->mac.ops.read_iosf_sb_reg(hw, 3735ac13930bSmikeb IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 3736ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 3737ac13930bSmikeb if (ret_val != IXGBE_SUCCESS) 3738ac13930bSmikeb goto out; 3739ac13930bSmikeb reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 3740ac13930bSmikeb IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 3741ac13930bSmikeb if (pause) 3742ac13930bSmikeb reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 3743ac13930bSmikeb if (asm_dir) 3744ac13930bSmikeb reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 3745d7a8f955Sjmatthew ret_val = hw->mac.ops.write_iosf_sb_reg(hw, 3746ac13930bSmikeb IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 3747ac13930bSmikeb IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 3748ac13930bSmikeb 3749ac13930bSmikeb /* This device does not fully support AN. */ 3750ac13930bSmikeb hw->fc.disable_fc_autoneg = TRUE; 3751d7a8f955Sjmatthew break; 3752d7a8f955Sjmatthew case IXGBE_DEV_ID_X550EM_X_XFI: 3753d7a8f955Sjmatthew hw->fc.disable_fc_autoneg = TRUE; 3754d7a8f955Sjmatthew break; 3755d7a8f955Sjmatthew default: 3756d7a8f955Sjmatthew break; 3757ac13930bSmikeb } 3758ac13930bSmikeb 3759ac13930bSmikeb out: 3760ac13930bSmikeb return ret_val; 3761ac13930bSmikeb } 3762ac13930bSmikeb 3763ac13930bSmikeb /** 3764d7a8f955Sjmatthew * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 3765d7a8f955Sjmatthew * @hw: pointer to hardware structure 3766d7a8f955Sjmatthew * 3767d7a8f955Sjmatthew * Enable flow control according to IEEE clause 37. 3768d7a8f955Sjmatthew **/ 3769d7a8f955Sjmatthew void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) 3770d7a8f955Sjmatthew { 3771d7a8f955Sjmatthew uint32_t link_s1, lp_an_page_low, an_cntl_1; 3772d7a8f955Sjmatthew int32_t status = IXGBE_ERR_FC_NOT_NEGOTIATED; 3773d7a8f955Sjmatthew ixgbe_link_speed speed; 3774d7a8f955Sjmatthew bool link_up; 3775d7a8f955Sjmatthew 3776d7a8f955Sjmatthew /* AN should have completed when the cable was plugged in. 3777d7a8f955Sjmatthew * Look for reasons to bail out. Bail out if: 3778d7a8f955Sjmatthew * - FC autoneg is disabled, or if 3779d7a8f955Sjmatthew * - link is not up. 3780d7a8f955Sjmatthew */ 3781d7a8f955Sjmatthew if (hw->fc.disable_fc_autoneg) { 3782d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 3783d7a8f955Sjmatthew "Flow control autoneg is disabled"); 3784d7a8f955Sjmatthew goto out; 3785d7a8f955Sjmatthew } 3786d7a8f955Sjmatthew 3787d7a8f955Sjmatthew hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 3788d7a8f955Sjmatthew if (!link_up) { 3789d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); 3790d7a8f955Sjmatthew goto out; 3791d7a8f955Sjmatthew } 3792d7a8f955Sjmatthew 3793d7a8f955Sjmatthew /* Check at auto-negotiation has completed */ 3794d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 3795d7a8f955Sjmatthew IXGBE_KRM_LINK_S1(hw->bus.lan_id), 3796d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); 3797d7a8f955Sjmatthew 3798d7a8f955Sjmatthew if (status != IXGBE_SUCCESS || 3799d7a8f955Sjmatthew (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { 3800d7a8f955Sjmatthew DEBUGOUT("Auto-Negotiation did not complete\n"); 3801d7a8f955Sjmatthew status = IXGBE_ERR_FC_NOT_NEGOTIATED; 3802d7a8f955Sjmatthew goto out; 3803d7a8f955Sjmatthew } 3804d7a8f955Sjmatthew 3805d7a8f955Sjmatthew /* Read the 10g AN autoc and LP ability registers and resolve 3806d7a8f955Sjmatthew * local flow control settings accordingly 3807d7a8f955Sjmatthew */ 3808d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 3809d7a8f955Sjmatthew IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 3810d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1); 3811d7a8f955Sjmatthew 3812d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) { 3813d7a8f955Sjmatthew DEBUGOUT("Auto-Negotiation did not complete\n"); 3814d7a8f955Sjmatthew goto out; 3815d7a8f955Sjmatthew } 3816d7a8f955Sjmatthew 3817d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 3818d7a8f955Sjmatthew IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id), 3819d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low); 3820d7a8f955Sjmatthew 3821d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) { 3822d7a8f955Sjmatthew DEBUGOUT("Auto-Negotiation did not complete\n"); 3823d7a8f955Sjmatthew goto out; 3824d7a8f955Sjmatthew } 3825d7a8f955Sjmatthew 3826d7a8f955Sjmatthew status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low, 3827d7a8f955Sjmatthew IXGBE_KRM_AN_CNTL_1_SYM_PAUSE, 3828d7a8f955Sjmatthew IXGBE_KRM_AN_CNTL_1_ASM_PAUSE, 3829d7a8f955Sjmatthew IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE, 3830d7a8f955Sjmatthew IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE); 3831d7a8f955Sjmatthew 3832d7a8f955Sjmatthew out: 3833d7a8f955Sjmatthew if (status == IXGBE_SUCCESS) { 3834d7a8f955Sjmatthew hw->fc.fc_was_autonegged = TRUE; 3835d7a8f955Sjmatthew } else { 3836d7a8f955Sjmatthew hw->fc.fc_was_autonegged = FALSE; 3837d7a8f955Sjmatthew hw->fc.current_mode = hw->fc.requested_mode; 3838d7a8f955Sjmatthew } 3839d7a8f955Sjmatthew } 3840d7a8f955Sjmatthew 3841d7a8f955Sjmatthew /** 3842d7a8f955Sjmatthew * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings 3843d7a8f955Sjmatthew * @hw: pointer to hardware structure 3844d7a8f955Sjmatthew * 3845d7a8f955Sjmatthew **/ 3846d7a8f955Sjmatthew void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) 3847d7a8f955Sjmatthew { 3848d7a8f955Sjmatthew hw->fc.fc_was_autonegged = FALSE; 3849d7a8f955Sjmatthew hw->fc.current_mode = hw->fc.requested_mode; 3850d7a8f955Sjmatthew } 3851d7a8f955Sjmatthew 3852d7a8f955Sjmatthew /** 3853d7a8f955Sjmatthew * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37 3854d7a8f955Sjmatthew * @hw: pointer to hardware structure 3855d7a8f955Sjmatthew * 3856d7a8f955Sjmatthew * Enable flow control according to IEEE clause 37. 3857d7a8f955Sjmatthew **/ 3858d7a8f955Sjmatthew void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw) 3859d7a8f955Sjmatthew { 3860d7a8f955Sjmatthew int32_t status = IXGBE_ERR_FC_NOT_NEGOTIATED; 3861d7a8f955Sjmatthew uint32_t info[FW_PHY_ACT_DATA_COUNT] = { 0 }; 3862d7a8f955Sjmatthew ixgbe_link_speed speed; 3863d7a8f955Sjmatthew bool link_up; 3864d7a8f955Sjmatthew 3865d7a8f955Sjmatthew /* AN should have completed when the cable was plugged in. 3866d7a8f955Sjmatthew * Look for reasons to bail out. Bail out if: 3867d7a8f955Sjmatthew * - FC autoneg is disabled, or if 3868d7a8f955Sjmatthew * - link is not up. 3869d7a8f955Sjmatthew */ 3870d7a8f955Sjmatthew if (hw->fc.disable_fc_autoneg) { 3871d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 3872d7a8f955Sjmatthew "Flow control autoneg is disabled"); 3873d7a8f955Sjmatthew goto out; 3874d7a8f955Sjmatthew } 3875d7a8f955Sjmatthew 3876d7a8f955Sjmatthew hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 3877d7a8f955Sjmatthew if (!link_up) { 3878d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); 3879d7a8f955Sjmatthew goto out; 3880d7a8f955Sjmatthew } 3881d7a8f955Sjmatthew 3882d7a8f955Sjmatthew /* Check if auto-negotiation has completed */ 3883d7a8f955Sjmatthew status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info); 3884d7a8f955Sjmatthew if (status != IXGBE_SUCCESS || 3885d7a8f955Sjmatthew !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) { 3886d7a8f955Sjmatthew DEBUGOUT("Auto-Negotiation did not complete\n"); 3887d7a8f955Sjmatthew status = IXGBE_ERR_FC_NOT_NEGOTIATED; 3888d7a8f955Sjmatthew goto out; 3889d7a8f955Sjmatthew } 3890d7a8f955Sjmatthew 3891d7a8f955Sjmatthew /* Negotiate the flow control */ 3892d7a8f955Sjmatthew status = ixgbe_negotiate_fc(hw, info[0], info[0], 3893d7a8f955Sjmatthew FW_PHY_ACT_GET_LINK_INFO_FC_RX, 3894d7a8f955Sjmatthew FW_PHY_ACT_GET_LINK_INFO_FC_TX, 3895d7a8f955Sjmatthew FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX, 3896d7a8f955Sjmatthew FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX); 3897d7a8f955Sjmatthew 3898d7a8f955Sjmatthew out: 3899d7a8f955Sjmatthew if (status == IXGBE_SUCCESS) { 3900d7a8f955Sjmatthew hw->fc.fc_was_autonegged = TRUE; 3901d7a8f955Sjmatthew } else { 3902d7a8f955Sjmatthew hw->fc.fc_was_autonegged = FALSE; 3903d7a8f955Sjmatthew hw->fc.current_mode = hw->fc.requested_mode; 3904d7a8f955Sjmatthew } 3905d7a8f955Sjmatthew } 3906d7a8f955Sjmatthew 3907d7a8f955Sjmatthew /** 3908d7a8f955Sjmatthew * ixgbe_setup_fc_backplane_x550em_a - Set up flow control 3909d7a8f955Sjmatthew * @hw: pointer to hardware structure 3910d7a8f955Sjmatthew * 3911d7a8f955Sjmatthew * Called at init time to set up flow control. 3912d7a8f955Sjmatthew **/ 3913d7a8f955Sjmatthew int32_t ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) 3914d7a8f955Sjmatthew { 3915d7a8f955Sjmatthew int32_t status = IXGBE_SUCCESS; 3916d7a8f955Sjmatthew uint32_t an_cntl = 0; 3917d7a8f955Sjmatthew 3918d7a8f955Sjmatthew DEBUGFUNC("ixgbe_setup_fc_backplane_x550em_a"); 3919d7a8f955Sjmatthew 3920d7a8f955Sjmatthew /* Validate the requested mode */ 3921d7a8f955Sjmatthew if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 3922d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 3923d7a8f955Sjmatthew "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 3924d7a8f955Sjmatthew return IXGBE_ERR_INVALID_LINK_SETTINGS; 3925d7a8f955Sjmatthew } 3926d7a8f955Sjmatthew 3927d7a8f955Sjmatthew if (hw->fc.requested_mode == ixgbe_fc_default) 3928d7a8f955Sjmatthew hw->fc.requested_mode = ixgbe_fc_full; 3929d7a8f955Sjmatthew 3930d7a8f955Sjmatthew /* Set up the 1G and 10G flow control advertisement registers so the 3931d7a8f955Sjmatthew * HW will be able to do FC autoneg once the cable is plugged in. If 3932d7a8f955Sjmatthew * we link at 10G, the 1G advertisement is harmless and vice versa. 3933d7a8f955Sjmatthew */ 3934d7a8f955Sjmatthew status = hw->mac.ops.read_iosf_sb_reg(hw, 3935d7a8f955Sjmatthew IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 3936d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl); 3937d7a8f955Sjmatthew 3938d7a8f955Sjmatthew if (status != IXGBE_SUCCESS) { 3939d7a8f955Sjmatthew DEBUGOUT("Auto-Negotiation did not complete\n"); 3940d7a8f955Sjmatthew return status; 3941d7a8f955Sjmatthew } 3942d7a8f955Sjmatthew 3943d7a8f955Sjmatthew /* The possible values of fc.requested_mode are: 3944d7a8f955Sjmatthew * 0: Flow control is completely disabled 3945d7a8f955Sjmatthew * 1: Rx flow control is enabled (we can receive pause frames, 3946d7a8f955Sjmatthew * but not send pause frames). 3947d7a8f955Sjmatthew * 2: Tx flow control is enabled (we can send pause frames but 3948d7a8f955Sjmatthew * we do not support receiving pause frames). 3949d7a8f955Sjmatthew * 3: Both Rx and Tx flow control (symmetric) are enabled. 3950d7a8f955Sjmatthew * other: Invalid. 3951d7a8f955Sjmatthew */ 3952d7a8f955Sjmatthew switch (hw->fc.requested_mode) { 3953d7a8f955Sjmatthew case ixgbe_fc_none: 3954d7a8f955Sjmatthew /* Flow control completely disabled by software override. */ 3955d7a8f955Sjmatthew an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 3956d7a8f955Sjmatthew IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); 3957d7a8f955Sjmatthew break; 3958d7a8f955Sjmatthew case ixgbe_fc_tx_pause: 3959d7a8f955Sjmatthew /* Tx Flow control is enabled, and Rx Flow control is 3960d7a8f955Sjmatthew * disabled by software override. 3961d7a8f955Sjmatthew */ 3962d7a8f955Sjmatthew an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 3963d7a8f955Sjmatthew an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; 3964d7a8f955Sjmatthew break; 3965d7a8f955Sjmatthew case ixgbe_fc_rx_pause: 3966d7a8f955Sjmatthew /* Rx Flow control is enabled and Tx Flow control is 3967d7a8f955Sjmatthew * disabled by software override. Since there really 3968d7a8f955Sjmatthew * isn't a way to advertise that we are capable of RX 3969d7a8f955Sjmatthew * Pause ONLY, we will advertise that we support both 3970d7a8f955Sjmatthew * symmetric and asymmetric Rx PAUSE, as such we fall 3971d7a8f955Sjmatthew * through to the fc_full statement. Later, we will 3972d7a8f955Sjmatthew * disable the adapter's ability to send PAUSE frames. 3973d7a8f955Sjmatthew */ 3974d7a8f955Sjmatthew case ixgbe_fc_full: 3975d7a8f955Sjmatthew /* Flow control (both Rx and Tx) is enabled by SW override. */ 3976d7a8f955Sjmatthew an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | 3977d7a8f955Sjmatthew IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; 3978d7a8f955Sjmatthew break; 3979d7a8f955Sjmatthew default: 3980d7a8f955Sjmatthew ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 3981d7a8f955Sjmatthew "Flow control param set incorrectly\n"); 3982d7a8f955Sjmatthew return IXGBE_ERR_CONFIG; 3983d7a8f955Sjmatthew } 3984d7a8f955Sjmatthew 3985d7a8f955Sjmatthew status = hw->mac.ops.write_iosf_sb_reg(hw, 3986d7a8f955Sjmatthew IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), 3987d7a8f955Sjmatthew IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); 3988d7a8f955Sjmatthew 3989d7a8f955Sjmatthew /* Restart auto-negotiation. */ 3990d7a8f955Sjmatthew status = ixgbe_restart_an_internal_phy_x550em(hw); 3991d7a8f955Sjmatthew 3992d7a8f955Sjmatthew return status; 3993d7a8f955Sjmatthew } 3994d7a8f955Sjmatthew 3995d7a8f955Sjmatthew /** 3996ac13930bSmikeb * ixgbe_set_mux - Set mux for port 1 access with CS4227 3997ac13930bSmikeb * @hw: pointer to hardware structure 3998ac13930bSmikeb * @state: set mux if 1, clear if 0 3999ac13930bSmikeb */ 4000ac13930bSmikeb void ixgbe_set_mux(struct ixgbe_hw *hw, uint8_t state) 4001ac13930bSmikeb { 4002ac13930bSmikeb uint32_t esdp; 4003ac13930bSmikeb 4004ac13930bSmikeb if (!hw->bus.lan_id) 4005ac13930bSmikeb return; 4006ac13930bSmikeb esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 4007ac13930bSmikeb if (state) 4008ac13930bSmikeb esdp |= IXGBE_ESDP_SDP1; 4009ac13930bSmikeb else 4010ac13930bSmikeb esdp &= ~IXGBE_ESDP_SDP1; 4011ac13930bSmikeb IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 4012ac13930bSmikeb IXGBE_WRITE_FLUSH(hw); 4013ac13930bSmikeb } 4014ac13930bSmikeb 4015ac13930bSmikeb /** 4016ac13930bSmikeb * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore 4017ac13930bSmikeb * @hw: pointer to hardware structure 4018ac13930bSmikeb * @mask: Mask to specify which semaphore to acquire 4019ac13930bSmikeb * 4020ac13930bSmikeb * Acquires the SWFW semaphore and sets the I2C MUX 4021ac13930bSmikeb **/ 4022ac13930bSmikeb int32_t ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, uint32_t mask) 4023ac13930bSmikeb { 4024ac13930bSmikeb int32_t status; 4025ac13930bSmikeb 4026ac13930bSmikeb DEBUGFUNC("ixgbe_acquire_swfw_sync_X550em"); 4027ac13930bSmikeb 4028ac13930bSmikeb status = ixgbe_acquire_swfw_sync_X540(hw, mask); 4029ac13930bSmikeb if (status) 4030ac13930bSmikeb return status; 4031ac13930bSmikeb 4032ac13930bSmikeb if (mask & IXGBE_GSSR_I2C_MASK) 4033ac13930bSmikeb ixgbe_set_mux(hw, 1); 4034ac13930bSmikeb 4035ac13930bSmikeb return IXGBE_SUCCESS; 4036ac13930bSmikeb } 4037ac13930bSmikeb 4038ac13930bSmikeb /** 4039ac13930bSmikeb * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore 4040ac13930bSmikeb * @hw: pointer to hardware structure 4041ac13930bSmikeb * @mask: Mask to specify which semaphore to release 4042ac13930bSmikeb * 4043ac13930bSmikeb * Releases the SWFW semaphore and sets the I2C MUX 4044ac13930bSmikeb **/ 4045ac13930bSmikeb void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, uint32_t mask) 4046ac13930bSmikeb { 4047ac13930bSmikeb DEBUGFUNC("ixgbe_release_swfw_sync_X550em"); 4048ac13930bSmikeb 4049ac13930bSmikeb if (mask & IXGBE_GSSR_I2C_MASK) 4050ac13930bSmikeb ixgbe_set_mux(hw, 0); 4051ac13930bSmikeb 4052ac13930bSmikeb ixgbe_release_swfw_sync_X540(hw, mask); 4053ac13930bSmikeb } 4054ac13930bSmikeb 4055ac13930bSmikeb /** 4056d7a8f955Sjmatthew * ixgbe_acquire_swfw_sync_X550a - Acquire SWFW semaphore 4057d7a8f955Sjmatthew * @hw: pointer to hardware structure 4058d7a8f955Sjmatthew * @mask: Mask to specify which semaphore to acquire 4059d7a8f955Sjmatthew * 4060d7a8f955Sjmatthew * Acquires the SWFW semaphore and get the shared phy token as needed 4061d7a8f955Sjmatthew */ 4062d7a8f955Sjmatthew int32_t ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *hw, uint32_t mask) 4063d7a8f955Sjmatthew { 4064d7a8f955Sjmatthew uint32_t hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 4065d7a8f955Sjmatthew int retries = FW_PHY_TOKEN_RETRIES; 4066d7a8f955Sjmatthew int32_t status = IXGBE_SUCCESS; 4067d7a8f955Sjmatthew 4068d7a8f955Sjmatthew DEBUGFUNC("ixgbe_acquire_swfw_sync_X550a"); 4069d7a8f955Sjmatthew 4070d7a8f955Sjmatthew while (--retries) { 4071d7a8f955Sjmatthew status = IXGBE_SUCCESS; 4072d7a8f955Sjmatthew if (hmask) 4073d7a8f955Sjmatthew status = ixgbe_acquire_swfw_sync_X540(hw, hmask); 4074d7a8f955Sjmatthew if (status) { 4075d7a8f955Sjmatthew DEBUGOUT1("Could not acquire SWFW semaphore, Status = %d\n", 4076d7a8f955Sjmatthew status); 4077d7a8f955Sjmatthew return status; 4078d7a8f955Sjmatthew } 4079d7a8f955Sjmatthew if (!(mask & IXGBE_GSSR_TOKEN_SM)) 4080d7a8f955Sjmatthew return IXGBE_SUCCESS; 4081d7a8f955Sjmatthew 4082d7a8f955Sjmatthew status = ixgbe_get_phy_token(hw); 4083d7a8f955Sjmatthew if (status == IXGBE_ERR_TOKEN_RETRY) 4084d7a8f955Sjmatthew DEBUGOUT1("Could not acquire PHY token, Status = %d\n", 4085d7a8f955Sjmatthew status); 4086d7a8f955Sjmatthew 4087d7a8f955Sjmatthew if (status == IXGBE_SUCCESS) 4088d7a8f955Sjmatthew return IXGBE_SUCCESS; 4089d7a8f955Sjmatthew 4090d7a8f955Sjmatthew if (hmask) 4091d7a8f955Sjmatthew ixgbe_release_swfw_sync_X540(hw, hmask); 4092d7a8f955Sjmatthew 4093d7a8f955Sjmatthew if (status != IXGBE_ERR_TOKEN_RETRY) { 4094d7a8f955Sjmatthew DEBUGOUT1("Unable to retry acquiring the PHY token, Status = %d\n", 4095d7a8f955Sjmatthew status); 4096d7a8f955Sjmatthew return status; 4097d7a8f955Sjmatthew } 4098d7a8f955Sjmatthew } 4099d7a8f955Sjmatthew 4100d7a8f955Sjmatthew DEBUGOUT1("Semaphore acquisition retries failed!: PHY ID = 0x%08X\n", 4101d7a8f955Sjmatthew hw->phy.id); 4102d7a8f955Sjmatthew return status; 4103d7a8f955Sjmatthew } 4104d7a8f955Sjmatthew 4105d7a8f955Sjmatthew /** 4106d7a8f955Sjmatthew * ixgbe_release_swfw_sync_X550a - Release SWFW semaphore 4107d7a8f955Sjmatthew * @hw: pointer to hardware structure 4108d7a8f955Sjmatthew * @mask: Mask to specify which semaphore to release 4109d7a8f955Sjmatthew * 4110d7a8f955Sjmatthew * Releases the SWFW semaphore and puts the shared phy token as needed 4111d7a8f955Sjmatthew */ 4112d7a8f955Sjmatthew void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *hw, uint32_t mask) 4113d7a8f955Sjmatthew { 4114d7a8f955Sjmatthew uint32_t hmask = mask & ~IXGBE_GSSR_TOKEN_SM; 4115d7a8f955Sjmatthew 4116d7a8f955Sjmatthew DEBUGFUNC("ixgbe_release_swfw_sync_X550a"); 4117d7a8f955Sjmatthew 4118d7a8f955Sjmatthew if (mask & IXGBE_GSSR_TOKEN_SM) 4119d7a8f955Sjmatthew ixgbe_put_phy_token(hw); 4120d7a8f955Sjmatthew 4121d7a8f955Sjmatthew if (hmask) 4122d7a8f955Sjmatthew ixgbe_release_swfw_sync_X540(hw, hmask); 4123d7a8f955Sjmatthew } 4124d7a8f955Sjmatthew 4125d7a8f955Sjmatthew /** 4126d7a8f955Sjmatthew * ixgbe_read_phy_reg_x550a - Reads specified PHY register 4127d7a8f955Sjmatthew * @hw: pointer to hardware structure 4128d7a8f955Sjmatthew * @reg_addr: 32 bit address of PHY register to read 4129d7a8f955Sjmatthew * @device_type: 5 bit device type 4130d7a8f955Sjmatthew * @phy_data: Pointer to read data from PHY register 4131d7a8f955Sjmatthew * 4132d7a8f955Sjmatthew * Reads a value from a specified PHY register using the SWFW lock and PHY 4133d7a8f955Sjmatthew * Token. The PHY Token is needed since the MDIO is shared between to MAC 4134d7a8f955Sjmatthew * instances. 4135d7a8f955Sjmatthew **/ 4136d7a8f955Sjmatthew int32_t ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, uint32_t reg_addr, 4137d7a8f955Sjmatthew uint32_t device_type, uint16_t *phy_data) 4138d7a8f955Sjmatthew { 4139d7a8f955Sjmatthew int32_t status; 4140d7a8f955Sjmatthew uint32_t mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 4141d7a8f955Sjmatthew 4142d7a8f955Sjmatthew DEBUGFUNC("ixgbe_read_phy_reg_x550a"); 4143d7a8f955Sjmatthew 4144d7a8f955Sjmatthew if (hw->mac.ops.acquire_swfw_sync(hw, mask)) 4145d7a8f955Sjmatthew return IXGBE_ERR_SWFW_SYNC; 4146d7a8f955Sjmatthew 4147d7a8f955Sjmatthew status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); 4148d7a8f955Sjmatthew 4149d7a8f955Sjmatthew hw->mac.ops.release_swfw_sync(hw, mask); 4150d7a8f955Sjmatthew 4151d7a8f955Sjmatthew return status; 4152d7a8f955Sjmatthew } 4153d7a8f955Sjmatthew 4154d7a8f955Sjmatthew /** 4155d7a8f955Sjmatthew * ixgbe_write_phy_reg_x550a - Writes specified PHY register 4156d7a8f955Sjmatthew * @hw: pointer to hardware structure 4157d7a8f955Sjmatthew * @reg_addr: 32 bit PHY register to write 4158d7a8f955Sjmatthew * @device_type: 5 bit device type 4159d7a8f955Sjmatthew * @phy_data: Data to write to the PHY register 4160d7a8f955Sjmatthew * 4161d7a8f955Sjmatthew * Writes a value to specified PHY register using the SWFW lock and PHY Token. 4162d7a8f955Sjmatthew * The PHY Token is needed since the MDIO is shared between to MAC instances. 4163d7a8f955Sjmatthew **/ 4164d7a8f955Sjmatthew int32_t ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, uint32_t reg_addr, 4165d7a8f955Sjmatthew uint32_t device_type, uint16_t phy_data) 4166d7a8f955Sjmatthew { 4167d7a8f955Sjmatthew int32_t status; 4168d7a8f955Sjmatthew uint32_t mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; 4169d7a8f955Sjmatthew 4170d7a8f955Sjmatthew DEBUGFUNC("ixgbe_write_phy_reg_x550a"); 4171d7a8f955Sjmatthew 4172d7a8f955Sjmatthew if (hw->mac.ops.acquire_swfw_sync(hw, mask) == IXGBE_SUCCESS) { 4173d7a8f955Sjmatthew status = hw->phy.ops.write_reg_mdi(hw, reg_addr, device_type, 4174d7a8f955Sjmatthew phy_data); 4175d7a8f955Sjmatthew hw->mac.ops.release_swfw_sync(hw, mask); 4176d7a8f955Sjmatthew } else { 4177d7a8f955Sjmatthew status = IXGBE_ERR_SWFW_SYNC; 4178d7a8f955Sjmatthew } 4179d7a8f955Sjmatthew 4180d7a8f955Sjmatthew return status; 4181d7a8f955Sjmatthew } 4182d7a8f955Sjmatthew 4183d7a8f955Sjmatthew /** 4184ac13930bSmikeb * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 4185ac13930bSmikeb * @hw: pointer to hardware structure 4186ac13930bSmikeb * 4187ac13930bSmikeb * Handle external Base T PHY interrupt. If high temperature 4188ac13930bSmikeb * failure alarm then return error, else if link status change 4189ac13930bSmikeb * then setup internal/external PHY link 4190ac13930bSmikeb * 4191ac13930bSmikeb * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 4192ac13930bSmikeb * failure alarm, else return PHY access status. 4193ac13930bSmikeb */ 4194ac13930bSmikeb int32_t ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) 4195ac13930bSmikeb { 4196ac13930bSmikeb bool lsc; 4197ac13930bSmikeb uint32_t status; 4198ac13930bSmikeb 4199ac13930bSmikeb status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 4200ac13930bSmikeb 4201ac13930bSmikeb if (status != IXGBE_SUCCESS) 4202ac13930bSmikeb return status; 4203ac13930bSmikeb 4204d7a8f955Sjmatthew if (lsc) 4205ac13930bSmikeb return hw->phy.ops.setup_internal_link(hw); 4206ac13930bSmikeb 4207ac13930bSmikeb return IXGBE_SUCCESS; 4208ac13930bSmikeb } 4209ac13930bSmikeb 4210ac13930bSmikeb /** 4211ac13930bSmikeb * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 4212ac13930bSmikeb * @hw: pointer to hardware structure 4213ac13930bSmikeb * @speed: new link speed 4214ac13930bSmikeb * @autoneg_wait_to_complete: TRUE when waiting for completion is needed 4215ac13930bSmikeb * 4216ac13930bSmikeb * Setup internal/external PHY link speed based on link speed, then set 4217ac13930bSmikeb * external PHY auto advertised link speed. 4218ac13930bSmikeb * 4219ac13930bSmikeb * Returns error status for any failure 4220ac13930bSmikeb **/ 4221ac13930bSmikeb int32_t ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 4222ac13930bSmikeb ixgbe_link_speed speed, 4223ac13930bSmikeb bool autoneg_wait_to_complete) 4224ac13930bSmikeb { 4225ac13930bSmikeb int32_t status; 4226ac13930bSmikeb ixgbe_link_speed force_speed; 4227ac13930bSmikeb 4228ac13930bSmikeb DEBUGFUNC("ixgbe_setup_mac_link_t_X550em"); 4229ac13930bSmikeb 4230ac13930bSmikeb /* Setup internal/external PHY link speed to iXFI (10G), unless 4231ac13930bSmikeb * only 1G is auto advertised then setup KX link. 4232ac13930bSmikeb */ 4233ac13930bSmikeb if (speed & IXGBE_LINK_SPEED_10GB_FULL) 4234ac13930bSmikeb force_speed = IXGBE_LINK_SPEED_10GB_FULL; 4235ac13930bSmikeb else 4236ac13930bSmikeb force_speed = IXGBE_LINK_SPEED_1GB_FULL; 4237ac13930bSmikeb 4238d7a8f955Sjmatthew /* If X552 and internal link mode is XFI, then setup XFI internal link. 4239d7a8f955Sjmatthew */ 4240d7a8f955Sjmatthew if (hw->mac.type == ixgbe_mac_X550EM_x && 4241d7a8f955Sjmatthew !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 4242ac13930bSmikeb status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 4243ac13930bSmikeb 4244ac13930bSmikeb if (status != IXGBE_SUCCESS) 4245ac13930bSmikeb return status; 4246ac13930bSmikeb } 4247ac13930bSmikeb 4248ac13930bSmikeb return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete); 4249ac13930bSmikeb } 4250ac13930bSmikeb 4251ac13930bSmikeb /** 4252ac13930bSmikeb * ixgbe_check_link_t_X550em - Determine link and speed status 4253ac13930bSmikeb * @hw: pointer to hardware structure 4254ac13930bSmikeb * @speed: pointer to link speed 4255ac13930bSmikeb * @link_up: TRUE when link is up 4256ac13930bSmikeb * @link_up_wait_to_complete: bool used to wait for link up or not 4257ac13930bSmikeb * 4258ac13930bSmikeb * Check that both the MAC and X557 external PHY have link. 4259ac13930bSmikeb **/ 4260ac13930bSmikeb int32_t ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed, 4261ac13930bSmikeb bool *link_up, bool link_up_wait_to_complete) 4262ac13930bSmikeb { 4263ac13930bSmikeb uint32_t status; 4264d7a8f955Sjmatthew uint16_t i, autoneg_status = 0; 4265ac13930bSmikeb 4266ac13930bSmikeb if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 4267ac13930bSmikeb return IXGBE_ERR_CONFIG; 4268ac13930bSmikeb 4269ac13930bSmikeb status = ixgbe_check_mac_link_generic(hw, speed, link_up, 4270ac13930bSmikeb link_up_wait_to_complete); 4271ac13930bSmikeb 4272ac13930bSmikeb /* If check link fails or MAC link is not up, then return */ 4273ac13930bSmikeb if (status != IXGBE_SUCCESS || !(*link_up)) 4274ac13930bSmikeb return status; 4275ac13930bSmikeb 4276ac13930bSmikeb /* MAC link is up, so check external PHY link. 4277d7a8f955Sjmatthew * X557 PHY. Link status is latching low, and can only be used to detect 4278d7a8f955Sjmatthew * link drop, and not the current status of the link without performing 4279d7a8f955Sjmatthew * back-to-back reads. 4280ac13930bSmikeb */ 4281d7a8f955Sjmatthew for (i = 0; i < 2; i++) { 4282ac13930bSmikeb status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 4283ac13930bSmikeb IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 4284ac13930bSmikeb &autoneg_status); 4285ac13930bSmikeb 4286ac13930bSmikeb if (status != IXGBE_SUCCESS) 4287ac13930bSmikeb return status; 4288d7a8f955Sjmatthew } 4289ac13930bSmikeb 4290ac13930bSmikeb /* If external PHY link is not up, then indicate link not up */ 4291ac13930bSmikeb if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 4292ac13930bSmikeb *link_up = FALSE; 4293ac13930bSmikeb 4294ac13930bSmikeb return IXGBE_SUCCESS; 4295ac13930bSmikeb } 4296ac13930bSmikeb 4297ac13930bSmikeb /** 4298ac13930bSmikeb * ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 4299ac13930bSmikeb * @hw: pointer to hardware structure 4300ac13930bSmikeb **/ 4301ac13930bSmikeb int32_t ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 4302ac13930bSmikeb { 4303ac13930bSmikeb int32_t status; 4304ac13930bSmikeb 4305ac13930bSmikeb status = ixgbe_reset_phy_generic(hw); 4306ac13930bSmikeb 4307ac13930bSmikeb if (status != IXGBE_SUCCESS) 4308ac13930bSmikeb return status; 4309ac13930bSmikeb 4310ac13930bSmikeb /* Configure Link Status Alarm and Temperature Threshold interrupts */ 4311ac13930bSmikeb return ixgbe_enable_lasi_ext_t_x550em(hw); 4312ac13930bSmikeb } 4313ac13930bSmikeb 4314ac13930bSmikeb /** 4315ac13930bSmikeb * ixgbe_led_on_t_X550em - Turns on the software controllable LEDs. 4316ac13930bSmikeb * @hw: pointer to hardware structure 4317ac13930bSmikeb * @led_idx: led number to turn on 4318ac13930bSmikeb **/ 4319ac13930bSmikeb int32_t ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, uint32_t led_idx) 4320ac13930bSmikeb { 4321ac13930bSmikeb uint16_t phy_data; 4322ac13930bSmikeb 4323ac13930bSmikeb DEBUGFUNC("ixgbe_led_on_t_X550em"); 4324ac13930bSmikeb 4325ac13930bSmikeb if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 4326ac13930bSmikeb return IXGBE_ERR_PARAM; 4327ac13930bSmikeb 4328d7a8f955Sjmatthew if (hw->phy.id == 0) 4329d7a8f955Sjmatthew ixgbe_identify_phy(hw); 4330d7a8f955Sjmatthew 4331ac13930bSmikeb /* To turn on the LED, set mode to ON. */ 4332ac13930bSmikeb hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 4333ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); 4334ac13930bSmikeb phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; 4335ac13930bSmikeb hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 4336ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); 4337ac13930bSmikeb 4338d7a8f955Sjmatthew /* Some designs have the LEDs wired to the MAC */ 4339d7a8f955Sjmatthew return ixgbe_led_on_generic(hw, led_idx); 4340ac13930bSmikeb } 4341ac13930bSmikeb 4342ac13930bSmikeb /** 4343ac13930bSmikeb * ixgbe_led_off_t_X550em - Turns off the software controllable LEDs. 4344ac13930bSmikeb * @hw: pointer to hardware structure 4345ac13930bSmikeb * @led_idx: led number to turn off 4346ac13930bSmikeb **/ 4347ac13930bSmikeb int32_t ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, uint32_t led_idx) 4348ac13930bSmikeb { 4349ac13930bSmikeb uint16_t phy_data; 4350ac13930bSmikeb 4351ac13930bSmikeb DEBUGFUNC("ixgbe_led_off_t_X550em"); 4352ac13930bSmikeb 4353ac13930bSmikeb if (led_idx >= IXGBE_X557_MAX_LED_INDEX) 4354ac13930bSmikeb return IXGBE_ERR_PARAM; 4355ac13930bSmikeb 4356d7a8f955Sjmatthew if (hw->phy.id == 0) 4357d7a8f955Sjmatthew ixgbe_identify_phy(hw); 4358d7a8f955Sjmatthew 4359ac13930bSmikeb /* To turn on the LED, set mode to ON. */ 4360ac13930bSmikeb hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 4361ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); 4362ac13930bSmikeb phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; 4363ac13930bSmikeb hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, 4364ac13930bSmikeb IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); 4365ac13930bSmikeb 4366d7a8f955Sjmatthew /* Some designs have the LEDs wired to the MAC */ 4367d7a8f955Sjmatthew return ixgbe_led_off_generic(hw, led_idx); 4368ac13930bSmikeb } 4369